From 1305e9418227ea3badac2710b39a17d3c96a3bca Mon Sep 17 00:00:00 2001 From: Randy Armstrong Date: Fri, 5 Feb 2021 18:35:53 +0900 Subject: [PATCH 1/3] Merge model compiler fixes with latest code. --- .../Stack/State/ModelCompilerExtension.cs | 69 +++++++++++++ Stack/Opc.Ua.Core/Stack/State/NodeState.cs | 2 +- .../Stack/State/NodeStateCollection.cs | 2 +- .../Opc.Ua.Core/Types/Encoders/JsonEncoder.cs | 99 ++++++++++--------- .../Opc.Ua.Core/Types/Encoders/XmlEncoder.cs | 29 +++++- 5 files changed, 148 insertions(+), 53 deletions(-) create mode 100644 Stack/Opc.Ua.Core/Stack/State/ModelCompilerExtension.cs diff --git a/Stack/Opc.Ua.Core/Stack/State/ModelCompilerExtension.cs b/Stack/Opc.Ua.Core/Stack/State/ModelCompilerExtension.cs new file mode 100644 index 0000000000..b5eaa62203 --- /dev/null +++ b/Stack/Opc.Ua.Core/Stack/State/ModelCompilerExtension.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; +using System.Threading.Tasks; + +namespace Opc.Ua +{ + public partial class NodeState + { + /// + /// The specification that defines the node. + /// + public string Specification { get; set; } + + /// + /// The documentation for the node that is saved in the NodeSet. + /// + public string NodeSetDocumentation { get; set; } + } + + public partial class StructureDefinition + { + /// + /// The first non-inherited field in the structure definition. + /// + public int FirstExplicitFieldIndex { get; set; } + } + + public partial class NodeStateCollection + { + /// + /// Writes the collection to a stream using the Opc.Ua.Schema.UANodeSet schema. + /// + public void SaveAsNodeSet2( + ISystemContext context, + Stream ostrm, + Export.ModelTableEntry model, + DateTime lastModified, + bool outputRedundantNames) + { + Opc.Ua.Export.UANodeSet nodeSet = new Opc.Ua.Export.UANodeSet(); + + if (lastModified != DateTime.MinValue) + { + nodeSet.LastModified = lastModified; + nodeSet.LastModifiedSpecified = true; + } + + if (model != null) + { + nodeSet.Models = new Export.ModelTableEntry[] { model }; + } + + for (int ii = 0; ii < s_AliasesToUse.Length; ii++) + { + nodeSet.AddAlias(context, s_AliasesToUse[ii].Alias, s_AliasesToUse[ii].NodeId); + } + + for (int ii = 0; ii < this.Count; ii++) + { + nodeSet.Export(context, this[ii], outputRedundantNames); + } + + nodeSet.Write(ostrm); + } + } +} diff --git a/Stack/Opc.Ua.Core/Stack/State/NodeState.cs b/Stack/Opc.Ua.Core/Stack/State/NodeState.cs index 8d0e67b57f..29fb50f64a 100644 --- a/Stack/Opc.Ua.Core/Stack/State/NodeState.cs +++ b/Stack/Opc.Ua.Core/Stack/State/NodeState.cs @@ -23,7 +23,7 @@ namespace Opc.Ua /// /// The base class for custom nodes. /// - public abstract class NodeState : IDisposable, IFormattable + public abstract partial class NodeState : IDisposable, IFormattable { #region Constructors /// diff --git a/Stack/Opc.Ua.Core/Stack/State/NodeStateCollection.cs b/Stack/Opc.Ua.Core/Stack/State/NodeStateCollection.cs index be6a3d6ead..266f7c2eb7 100644 --- a/Stack/Opc.Ua.Core/Stack/State/NodeStateCollection.cs +++ b/Stack/Opc.Ua.Core/Stack/State/NodeStateCollection.cs @@ -23,7 +23,7 @@ namespace Opc.Ua /// /// Stores a collection of nodes. /// - public class NodeStateCollection : List + public partial class NodeStateCollection : List { #region Constructors /// diff --git a/Stack/Opc.Ua.Core/Types/Encoders/JsonEncoder.cs b/Stack/Opc.Ua.Core/Types/Encoders/JsonEncoder.cs index 9ef1853411..4e5886851e 100644 --- a/Stack/Opc.Ua.Core/Types/Encoders/JsonEncoder.cs +++ b/Stack/Opc.Ua.Core/Types/Encoders/JsonEncoder.cs @@ -228,14 +228,14 @@ namespace Opc.Ua { if (!m_dontWriteClosing) { - if (m_topLevelIsArray) - { - m_writer.Write("]"); - } - else - { - m_writer.Write("}"); - } + if (m_topLevelIsArray) + { + m_writer.Write("]"); + } + else + { + m_writer.Write("}"); + } } m_writer.Flush(); @@ -1296,6 +1296,7 @@ namespace Opc.Ua m_context.MaxEncodingNestingLevels); } + if (value == null) { WriteSimpleField(fieldName, null, false); @@ -1376,7 +1377,7 @@ namespace Opc.Ua /// public void WriteBooleanArray(string fieldName, IList values) { - if (values == null) + if (values == null || values.Count == 0) { WriteSimpleField(fieldName, null, false); return; @@ -1403,7 +1404,7 @@ namespace Opc.Ua /// public void WriteSByteArray(string fieldName, IList values) { - if (values == null) + if (values == null || values.Count == 0) { WriteSimpleField(fieldName, null, false); return; @@ -1430,7 +1431,7 @@ namespace Opc.Ua /// public void WriteByteArray(string fieldName, IList values) { - if (values == null) + if (values == null || values.Count == 0) { WriteSimpleField(fieldName, null, false); return; @@ -1457,7 +1458,7 @@ namespace Opc.Ua /// public void WriteInt16Array(string fieldName, IList values) { - if (values == null) + if (values == null || values.Count == 0) { WriteSimpleField(fieldName, null, false); return; @@ -1484,7 +1485,7 @@ namespace Opc.Ua /// public void WriteUInt16Array(string fieldName, IList values) { - if (values == null) + if (values == null || values.Count == 0) { WriteSimpleField(fieldName, null, false); return; @@ -1511,7 +1512,7 @@ namespace Opc.Ua /// public void WriteInt32Array(string fieldName, IList values) { - if (values == null) + if (values == null || values.Count == 0) { WriteSimpleField(fieldName, null, false); return; @@ -1538,7 +1539,7 @@ namespace Opc.Ua /// public void WriteUInt32Array(string fieldName, IList values) { - if (values == null) + if (values == null || values.Count == 0) { WriteSimpleField(fieldName, null, false); return; @@ -1565,7 +1566,7 @@ namespace Opc.Ua /// public void WriteInt64Array(string fieldName, IList values) { - if (values == null) + if (values == null || values.Count == 0) { WriteSimpleField(fieldName, null, false); return; @@ -1592,7 +1593,7 @@ namespace Opc.Ua /// public void WriteUInt64Array(string fieldName, IList values) { - if (values == null) + if (values == null || values.Count == 0) { WriteSimpleField(fieldName, null, false); return; @@ -1619,7 +1620,7 @@ namespace Opc.Ua /// public void WriteFloatArray(string fieldName, IList values) { - if (values == null) + if (values == null || values.Count == 0) { WriteSimpleField(fieldName, null, false); return; @@ -1646,7 +1647,7 @@ namespace Opc.Ua /// public void WriteDoubleArray(string fieldName, IList values) { - if (values == null) + if (values == null || values.Count == 0) { WriteSimpleField(fieldName, null, false); return; @@ -1673,7 +1674,7 @@ namespace Opc.Ua /// public void WriteStringArray(string fieldName, IList values) { - if (values == null) + if (values == null || values.Count == 0) { WriteSimpleField(fieldName, null, false); return; @@ -1700,7 +1701,7 @@ namespace Opc.Ua /// public void WriteDateTimeArray(string fieldName, IList values) { - if (values == null) + if (values == null || values.Count == 0) { WriteSimpleField(fieldName, null, false); return; @@ -1734,7 +1735,7 @@ namespace Opc.Ua /// public void WriteGuidArray(string fieldName, IList values) { - if (values == null) + if (values == null || values.Count == 0) { WriteSimpleField(fieldName, null, false); return; @@ -1761,7 +1762,7 @@ namespace Opc.Ua /// public void WriteGuidArray(string fieldName, IList values) { - if (values == null) + if (values == null || values.Count == 0) { WriteSimpleField(fieldName, null, false); return; @@ -1788,7 +1789,7 @@ namespace Opc.Ua /// public void WriteByteStringArray(string fieldName, IList values) { - if (values == null) + if (values == null || values.Count == 0) { WriteSimpleField(fieldName, null, false); return; @@ -1815,7 +1816,7 @@ namespace Opc.Ua /// public void WriteXmlElementArray(string fieldName, IList values) { - if (values == null) + if (values == null || values.Count == 0) { WriteSimpleField(fieldName, null, false); return; @@ -1842,7 +1843,7 @@ namespace Opc.Ua /// public void WriteNodeIdArray(string fieldName, IList values) { - if (values == null) + if (values == null || values.Count == 0) { WriteSimpleField(fieldName, null, false); return; @@ -1869,7 +1870,7 @@ namespace Opc.Ua /// public void WriteExpandedNodeIdArray(string fieldName, IList values) { - if (values == null) + if (values == null || values.Count == 0) { WriteSimpleField(fieldName, null, false); return; @@ -1896,7 +1897,7 @@ namespace Opc.Ua /// public void WriteStatusCodeArray(string fieldName, IList values) { - if (values == null) + if (values == null || values.Count == 0) { WriteSimpleField(fieldName, null, false); return; @@ -1931,7 +1932,7 @@ namespace Opc.Ua /// public void WriteDiagnosticInfoArray(string fieldName, IList values) { - if (values == null) + if (values == null || values.Count == 0) { WriteSimpleField(fieldName, null, false); return; @@ -1958,7 +1959,7 @@ namespace Opc.Ua /// public void WriteQualifiedNameArray(string fieldName, IList values) { - if (values == null) + if (values == null || values.Count == 0) { WriteSimpleField(fieldName, null, false); return; @@ -1985,7 +1986,7 @@ namespace Opc.Ua /// public void WriteLocalizedTextArray(string fieldName, IList values) { - if (values == null) + if (values == null || values.Count == 0) { WriteSimpleField(fieldName, null, false); return; @@ -2012,7 +2013,7 @@ namespace Opc.Ua /// public void WriteVariantArray(string fieldName, IList values) { - if (values == null) + if (values == null || values.Count == 0) { WriteSimpleField(fieldName, null, false); return; @@ -2045,7 +2046,7 @@ namespace Opc.Ua /// public void WriteDataValueArray(string fieldName, IList values) { - if (values == null) + if (values == null || values.Count == 0) { WriteSimpleField(fieldName, null, false); return; @@ -2072,7 +2073,7 @@ namespace Opc.Ua /// public void WriteExtensionObjectArray(string fieldName, IList values) { - if (values == null) + if (values == null || values.Count == 0) { WriteSimpleField(fieldName, null, false); return; @@ -2099,7 +2100,7 @@ namespace Opc.Ua /// public void WriteEncodeableArray(string fieldName, IList values, System.Type systemType) { - if (values == null) + if (values == null || values.Count == 0) { WriteSimpleField(fieldName, null, false); return; @@ -2136,18 +2137,18 @@ namespace Opc.Ua { PushArray(fieldName); - // check the length. - if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count) - { - throw new ServiceResultException(StatusCodes.BadEncodingLimitsExceeded); - } + // check the length. + if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count) + { + throw new ServiceResultException(StatusCodes.BadEncodingLimitsExceeded); + } - for (int ii = 0; ii < values.Count; ii++) - { - WriteEncodeable(null, values[ii], systemType); - } + for (int ii = 0; ii < values.Count; ii++) + { + WriteEncodeable(null, values[ii], systemType); + } - PopArray(); + PopArray(); } } @@ -2156,7 +2157,7 @@ namespace Opc.Ua /// public void WriteEnumeratedArray(string fieldName, Array values, System.Type systemType) { - if (values == null) + if (values == null || values.Length == 0) { WriteSimpleField(fieldName, null, false); return; @@ -2382,6 +2383,12 @@ namespace Opc.Ua /// public void WriteObjectArray(string fieldName, IList values) { + if (values == null || values.Count == 0) + { + WriteSimpleField(fieldName, null, false); + return; + } + PushArray(fieldName); if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count) diff --git a/Stack/Opc.Ua.Core/Types/Encoders/XmlEncoder.cs b/Stack/Opc.Ua.Core/Types/Encoders/XmlEncoder.cs index a4a2a8506b..ec9f8566e3 100644 --- a/Stack/Opc.Ua.Core/Types/Encoders/XmlEncoder.cs +++ b/Stack/Opc.Ua.Core/Types/Encoders/XmlEncoder.cs @@ -39,6 +39,8 @@ namespace Opc.Ua XmlWriterSettings settings = new XmlWriterSettings(); settings.CheckCharacters = false; settings.ConformanceLevel = ConformanceLevel.Auto; + settings.NamespaceHandling = NamespaceHandling.OmitDuplicates; + settings.NewLineHandling = NewLineHandling.Replace; m_writer = XmlWriter.Create(m_destination, settings); } @@ -443,7 +445,11 @@ namespace Opc.Ua throw new ServiceResultException(StatusCodes.BadEncodingLimitsExceeded); } - m_writer.WriteString(value); + if (!String.IsNullOrWhiteSpace(value)) + { + m_writer.WriteString(value); + } + EndField(fieldName); } } @@ -504,7 +510,7 @@ namespace Opc.Ua throw new ServiceResultException(StatusCodes.BadEncodingLimitsExceeded); } - m_writer.WriteValue(Convert.ToBase64String(value)); + m_writer.WriteValue(Convert.ToBase64String(value, Base64FormattingOptions.InsertLineBreaks)); EndField(fieldName); } } @@ -684,8 +690,15 @@ namespace Opc.Ua if (value != null) { - WriteString("Locale", value.Locale); - WriteString("Text", value.Text); + if (!String.IsNullOrEmpty(value.Locale)) + { + WriteString("Locale", value.Locale); + } + + if (!String.IsNullOrEmpty(value.Text)) + { + WriteString("Text", value.Text); + } } PopNamespace(); @@ -1817,6 +1830,7 @@ namespace Opc.Ua ints[ii] = (int)(object)enums[ii]; } } + WriteInt32Array("ListOfInt32", ints); return; } @@ -1882,7 +1896,7 @@ namespace Opc.Ua if (bytes != null) { m_writer.WriteStartElement("ByteString", Namespaces.OpcUaXsd); - m_writer.WriteString(Convert.ToBase64String(bytes)); + m_writer.WriteString(Convert.ToBase64String(bytes, Base64FormattingOptions.InsertLineBreaks)); m_writer.WriteEndElement(); return; } @@ -1977,6 +1991,11 @@ namespace Opc.Ua // specifying a null field name means the start/end tags should not be written. if (!String.IsNullOrEmpty(fieldName)) { + if (isNillable && isDefault) + { + return false; + } + m_writer.WriteStartElement(fieldName, m_namespaces.Peek()); if (isDefault) From c22ecec8f5e7361742a9d05db44ce982b6fc29f1 Mon Sep 17 00:00:00 2001 From: Randy Armstrong Date: Fri, 5 Feb 2021 19:14:10 +0900 Subject: [PATCH 2/3] Fix XmlEncoder. --- .../Opc.Ua.Core/Types/Encoders/XmlEncoder.cs | 64 +++++++++---------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/Stack/Opc.Ua.Core/Types/Encoders/XmlEncoder.cs b/Stack/Opc.Ua.Core/Types/Encoders/XmlEncoder.cs index ec9f8566e3..8693a1edf6 100644 --- a/Stack/Opc.Ua.Core/Types/Encoders/XmlEncoder.cs +++ b/Stack/Opc.Ua.Core/Types/Encoders/XmlEncoder.cs @@ -897,7 +897,7 @@ namespace Opc.Ua /// public void WriteBooleanArray(string fieldName, IList values) { - if (BeginField(fieldName, values == null, true)) + if (BeginField(fieldName, values == null, true, true)) { // check the length. if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count) @@ -926,7 +926,7 @@ namespace Opc.Ua /// public void WriteSByteArray(string fieldName, IList values) { - if (BeginField(fieldName, values == null, true)) + if (BeginField(fieldName, values == null, true, true)) { // check the length. if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count) @@ -955,7 +955,7 @@ namespace Opc.Ua /// public void WriteByteArray(string fieldName, IList values) { - if (BeginField(fieldName, values == null, true)) + if (BeginField(fieldName, values == null, true, true)) { // check the length. if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count) @@ -984,7 +984,7 @@ namespace Opc.Ua /// public void WriteInt16Array(string fieldName, IList values) { - if (BeginField(fieldName, values == null, true)) + if (BeginField(fieldName, values == null, true, true)) { // check the length. if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count) @@ -1013,7 +1013,7 @@ namespace Opc.Ua /// public void WriteUInt16Array(string fieldName, IList values) { - if (BeginField(fieldName, values == null, true)) + if (BeginField(fieldName, values == null, true, true)) { // check the length. if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count) @@ -1042,7 +1042,7 @@ namespace Opc.Ua /// public void WriteInt32Array(string fieldName, IList values) { - if (BeginField(fieldName, values == null, true)) + if (BeginField(fieldName, values == null, true, true)) { // check the length. if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count) @@ -1071,7 +1071,7 @@ namespace Opc.Ua /// public void WriteUInt32Array(string fieldName, IList values) { - if (BeginField(fieldName, values == null, true)) + if (BeginField(fieldName, values == null, true, true)) { // check the length. if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count) @@ -1100,7 +1100,7 @@ namespace Opc.Ua /// public void WriteInt64Array(string fieldName, IList values) { - if (BeginField(fieldName, values == null, true)) + if (BeginField(fieldName, values == null, true, true)) { // check the length. if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count) @@ -1129,7 +1129,7 @@ namespace Opc.Ua /// public void WriteUInt64Array(string fieldName, IList values) { - if (BeginField(fieldName, values == null, true)) + if (BeginField(fieldName, values == null, true, true)) { // check the length. if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count) @@ -1158,7 +1158,7 @@ namespace Opc.Ua /// public void WriteFloatArray(string fieldName, IList values) { - if (BeginField(fieldName, values == null, true)) + if (BeginField(fieldName, values == null, true, true)) { // check the length. if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count) @@ -1187,7 +1187,7 @@ namespace Opc.Ua /// public void WriteDoubleArray(string fieldName, IList values) { - if (BeginField(fieldName, values == null, true)) + if (BeginField(fieldName, values == null, true, true)) { // check the length. if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count) @@ -1216,7 +1216,7 @@ namespace Opc.Ua /// public void WriteStringArray(string fieldName, IList values) { - if (BeginField(fieldName, values == null, true)) + if (BeginField(fieldName, values == null, true, true)) { // check the length. if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count) @@ -1245,7 +1245,7 @@ namespace Opc.Ua /// public void WriteDateTimeArray(string fieldName, IList values) { - if (BeginField(fieldName, values == null, true)) + if (BeginField(fieldName, values == null, true, true)) { // check the length. if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count) @@ -1274,7 +1274,7 @@ namespace Opc.Ua /// public void WriteGuidArray(string fieldName, IList values) { - if (BeginField(fieldName, values == null, true)) + if (BeginField(fieldName, values == null, true, true)) { // check the length. if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count) @@ -1303,7 +1303,7 @@ namespace Opc.Ua /// public void WriteGuidArray(string fieldName, IList values) { - if (BeginField(fieldName, values == null, true)) + if (BeginField(fieldName, values == null, true, true)) { // check the length. if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count) @@ -1332,7 +1332,7 @@ namespace Opc.Ua /// public void WriteByteStringArray(string fieldName, IList values) { - if (BeginField(fieldName, values == null, true)) + if (BeginField(fieldName, values == null, true, true)) { // check the length. if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count) @@ -1361,7 +1361,7 @@ namespace Opc.Ua /// public void WriteXmlElementArray(string fieldName, IList values) { - if (BeginField(fieldName, values == null, true)) + if (BeginField(fieldName, values == null, true, true)) { // check the length. if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count) @@ -1390,7 +1390,7 @@ namespace Opc.Ua /// public void WriteNodeIdArray(string fieldName, IList values) { - if (BeginField(fieldName, values == null, true)) + if (BeginField(fieldName, values == null, true, true)) { // check the length. if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count) @@ -1419,7 +1419,7 @@ namespace Opc.Ua /// public void WriteExpandedNodeIdArray(string fieldName, IList values) { - if (BeginField(fieldName, values == null, true)) + if (BeginField(fieldName, values == null, true, true)) { // check the length. if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count) @@ -1448,7 +1448,7 @@ namespace Opc.Ua /// public void WriteStatusCodeArray(string fieldName, IList values) { - if (BeginField(fieldName, values == null, true)) + if (BeginField(fieldName, values == null, true, true)) { // check the length. if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count) @@ -1477,7 +1477,7 @@ namespace Opc.Ua /// public void WriteDiagnosticInfoArray(string fieldName, IList values) { - if (BeginField(fieldName, values == null, true)) + if (BeginField(fieldName, values == null, true, true)) { // check the length. if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count) @@ -1506,7 +1506,7 @@ namespace Opc.Ua /// public void WriteQualifiedNameArray(string fieldName, IList values) { - if (BeginField(fieldName, values == null, true)) + if (BeginField(fieldName, values == null, true, true)) { // check the length. if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count) @@ -1535,7 +1535,7 @@ namespace Opc.Ua /// public void WriteLocalizedTextArray(string fieldName, IList values) { - if (BeginField(fieldName, values == null, true)) + if (BeginField(fieldName, values == null, true, true)) { // check the length. if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count) @@ -1564,7 +1564,7 @@ namespace Opc.Ua /// public void WriteVariantArray(string fieldName, IList values) { - if (BeginField(fieldName, values == null, true)) + if (BeginField(fieldName, values == null, true, true)) { // check the length. if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count) @@ -1593,7 +1593,7 @@ namespace Opc.Ua /// public void WriteDataValueArray(string fieldName, IList values) { - if (BeginField(fieldName, values == null, true)) + if (BeginField(fieldName, values == null, true, true)) { // check the length. if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count) @@ -1622,7 +1622,7 @@ namespace Opc.Ua /// public void WriteExtensionObjectArray(string fieldName, IList values) { - if (BeginField(fieldName, values == null, true)) + if (BeginField(fieldName, values == null, true, true)) { // check the length. if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count) @@ -1651,7 +1651,7 @@ namespace Opc.Ua /// public void WriteEncodeableArray(string fieldName, IList values, System.Type systemType) { - if (BeginField(fieldName, values == null, true)) + if (BeginField(fieldName, values == null, true, true)) { // check the length. if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count) @@ -1698,7 +1698,7 @@ namespace Opc.Ua /// public void WriteEnumeratedArray(string fieldName, Array values, System.Type systemType) { - if (BeginField(fieldName, values == null, true)) + if (BeginField(fieldName, values == null, true, true)) { // check the length. if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Length) @@ -1935,7 +1935,7 @@ namespace Opc.Ua /// private void WriteMatrix(string fieldName, Matrix value) { - if (BeginField(fieldName, value == null, true)) + if (BeginField(fieldName, value == null, true, true)) { PushNamespace(Namespaces.OpcUaXsd); @@ -1959,7 +1959,7 @@ namespace Opc.Ua /// public void WriteObjectArray(string fieldName, IList values) { - if (BeginField(fieldName, values == null, true)) + if (BeginField(fieldName, values == null, true, true)) { // check the length. if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count) @@ -1986,12 +1986,12 @@ namespace Opc.Ua /// /// Writes the start element for a field. /// - private bool BeginField(string fieldName, bool isDefault, bool isNillable) + private bool BeginField(string fieldName, bool isDefault, bool isNillable, bool isArrayElement = false) { // specifying a null field name means the start/end tags should not be written. if (!String.IsNullOrEmpty(fieldName)) { - if (isNillable && isDefault) + if (isNillable && isDefault && !isArrayElement) { return false; } From e016a9bb298fa60671ada928b85a604e90f2b99c Mon Sep 17 00:00:00 2001 From: Randy Armstrong Date: Fri, 5 Feb 2021 23:53:30 +0900 Subject: [PATCH 3/3] Fix unit tests errors. --- Stack/Opc.Ua.Core/Schema/UANodeSetHelpers.cs | 17 +- .../Opc.Ua.Core/Types/Encoders/JsonEncoder.cs | 302 +++++++++--------- .../Opc.Ua.Core/Types/Encoders/XmlDecoder.cs | 11 +- .../Opc.Ua.Core/Types/Encoders/XmlEncoder.cs | 27 +- .../Types/Schemas/SchemaValidator.cs | 6 +- .../Types/Encoders/EncoderCommon.cs | 7 +- 6 files changed, 209 insertions(+), 161 deletions(-) diff --git a/Stack/Opc.Ua.Core/Schema/UANodeSetHelpers.cs b/Stack/Opc.Ua.Core/Schema/UANodeSetHelpers.cs index a7e19357a1..9d0573ce50 100644 --- a/Stack/Opc.Ua.Core/Schema/UANodeSetHelpers.cs +++ b/Stack/Opc.Ua.Core/Schema/UANodeSetHelpers.cs @@ -295,6 +295,7 @@ namespace Opc.Ua.Export exportedNode.Description = new LocalizedText[0]; } + exportedNode.Documentation = node.NodeSetDocumentation; exportedNode.Category = (node.Categories != null && node.Categories.Count > 0) ? new List(node.Categories).ToArray() : null; exportedNode.ReleaseStatus = node.ReleaseStatus; exportedNode.WriteMask = (uint)node.WriteMask; @@ -624,6 +625,7 @@ namespace Opc.Ua.Export } importedNode.Description = Import(node.Description); + importedNode.NodeSetDocumentation = node.Documentation; importedNode.Categories = (node.Category != null && node.Category.Length > 0) ? node.Category : null; importedNode.ReleaseStatus = node.ReleaseStatus; importedNode.WriteMask = (AttributeWriteMask)node.WriteMask; @@ -909,8 +911,10 @@ namespace Opc.Ua.Export { List fields = new List(); - foreach (StructureField field in structureDefinition.Fields) + for (int ii = structureDefinition.FirstExplicitFieldIndex; ii < structureDefinition.Fields.Count; ii++) { + StructureField field = structureDefinition.Fields[ii]; + Opc.Ua.Export.DataTypeField output = new Opc.Ua.Export.DataTypeField(); output.Name = field.Name; @@ -948,7 +952,16 @@ namespace Opc.Ua.Export Opc.Ua.Export.DataTypeField output = new Opc.Ua.Export.DataTypeField(); output.Name = field.Name; - output.DisplayName = Export(new Opc.Ua.LocalizedText[] { field.Name }); + + if (field.DisplayName != null && output.Name != field.DisplayName.Text) + { + output.DisplayName = Export(new Opc.Ua.LocalizedText[] { field.DisplayName }); + } + else + { + output.DisplayName = new LocalizedText[0]; + } + output.Description = Export(new Opc.Ua.LocalizedText[] { field.Description }); output.ValueRank = ValueRanks.Scalar; output.Value = (int)field.Value; diff --git a/Stack/Opc.Ua.Core/Types/Encoders/JsonEncoder.cs b/Stack/Opc.Ua.Core/Types/Encoders/JsonEncoder.cs index 4e5886851e..03cc09ee48 100644 --- a/Stack/Opc.Ua.Core/Types/Encoders/JsonEncoder.cs +++ b/Stack/Opc.Ua.Core/Types/Encoders/JsonEncoder.cs @@ -29,6 +29,7 @@ namespace Opc.Ua private StreamWriter m_writer; private Stack m_namespaces; private bool m_commaRequired; + private bool m_inVariantWithEncoding; private ServiceMessageContext m_context; private ushort[] m_namespaceMappings; private ushort[] m_serverMappings; @@ -1377,7 +1378,7 @@ namespace Opc.Ua /// public void WriteBooleanArray(string fieldName, IList values) { - if (values == null || values.Count == 0) + if (values == null || (values.Count == 0 && !m_inVariantWithEncoding)) { WriteSimpleField(fieldName, null, false); return; @@ -1404,7 +1405,7 @@ namespace Opc.Ua /// public void WriteSByteArray(string fieldName, IList values) { - if (values == null || values.Count == 0) + if (values == null || (values.Count == 0 && !m_inVariantWithEncoding)) { WriteSimpleField(fieldName, null, false); return; @@ -1431,7 +1432,7 @@ namespace Opc.Ua /// public void WriteByteArray(string fieldName, IList values) { - if (values == null || values.Count == 0) + if (values == null || (values.Count == 0 && !m_inVariantWithEncoding)) { WriteSimpleField(fieldName, null, false); return; @@ -1458,7 +1459,7 @@ namespace Opc.Ua /// public void WriteInt16Array(string fieldName, IList values) { - if (values == null || values.Count == 0) + if (values == null || (values.Count == 0 && !m_inVariantWithEncoding)) { WriteSimpleField(fieldName, null, false); return; @@ -1485,7 +1486,7 @@ namespace Opc.Ua /// public void WriteUInt16Array(string fieldName, IList values) { - if (values == null || values.Count == 0) + if (values == null || (values.Count == 0 && !m_inVariantWithEncoding)) { WriteSimpleField(fieldName, null, false); return; @@ -1512,7 +1513,7 @@ namespace Opc.Ua /// public void WriteInt32Array(string fieldName, IList values) { - if (values == null || values.Count == 0) + if (values == null || (values.Count == 0 && !m_inVariantWithEncoding)) { WriteSimpleField(fieldName, null, false); return; @@ -1539,7 +1540,7 @@ namespace Opc.Ua /// public void WriteUInt32Array(string fieldName, IList values) { - if (values == null || values.Count == 0) + if (values == null || (values.Count == 0 && !m_inVariantWithEncoding)) { WriteSimpleField(fieldName, null, false); return; @@ -1566,7 +1567,7 @@ namespace Opc.Ua /// public void WriteInt64Array(string fieldName, IList values) { - if (values == null || values.Count == 0) + if (values == null || (values.Count == 0 && !m_inVariantWithEncoding)) { WriteSimpleField(fieldName, null, false); return; @@ -1593,7 +1594,7 @@ namespace Opc.Ua /// public void WriteUInt64Array(string fieldName, IList values) { - if (values == null || values.Count == 0) + if (values == null || (values.Count == 0 && !m_inVariantWithEncoding)) { WriteSimpleField(fieldName, null, false); return; @@ -1620,7 +1621,7 @@ namespace Opc.Ua /// public void WriteFloatArray(string fieldName, IList values) { - if (values == null || values.Count == 0) + if (values == null || (values.Count == 0 && !m_inVariantWithEncoding)) { WriteSimpleField(fieldName, null, false); return; @@ -1647,7 +1648,7 @@ namespace Opc.Ua /// public void WriteDoubleArray(string fieldName, IList values) { - if (values == null || values.Count == 0) + if (values == null || (values.Count == 0 && !m_inVariantWithEncoding)) { WriteSimpleField(fieldName, null, false); return; @@ -1674,7 +1675,7 @@ namespace Opc.Ua /// public void WriteStringArray(string fieldName, IList values) { - if (values == null || values.Count == 0) + if (values == null || (values.Count == 0 && !m_inVariantWithEncoding)) { WriteSimpleField(fieldName, null, false); return; @@ -1701,7 +1702,7 @@ namespace Opc.Ua /// public void WriteDateTimeArray(string fieldName, IList values) { - if (values == null || values.Count == 0) + if (values == null || (values.Count == 0 && !m_inVariantWithEncoding)) { WriteSimpleField(fieldName, null, false); return; @@ -1735,7 +1736,7 @@ namespace Opc.Ua /// public void WriteGuidArray(string fieldName, IList values) { - if (values == null || values.Count == 0) + if (values == null || (values.Count == 0 && !m_inVariantWithEncoding)) { WriteSimpleField(fieldName, null, false); return; @@ -1762,7 +1763,7 @@ namespace Opc.Ua /// public void WriteGuidArray(string fieldName, IList values) { - if (values == null || values.Count == 0) + if (values == null || (values.Count == 0 && !m_inVariantWithEncoding)) { WriteSimpleField(fieldName, null, false); return; @@ -1789,7 +1790,7 @@ namespace Opc.Ua /// public void WriteByteStringArray(string fieldName, IList values) { - if (values == null || values.Count == 0) + if (values == null || (values.Count == 0 && !m_inVariantWithEncoding)) { WriteSimpleField(fieldName, null, false); return; @@ -1816,7 +1817,7 @@ namespace Opc.Ua /// public void WriteXmlElementArray(string fieldName, IList values) { - if (values == null || values.Count == 0) + if (values == null || (values.Count == 0 && !m_inVariantWithEncoding)) { WriteSimpleField(fieldName, null, false); return; @@ -1843,7 +1844,7 @@ namespace Opc.Ua /// public void WriteNodeIdArray(string fieldName, IList values) { - if (values == null || values.Count == 0) + if (values == null || (values.Count == 0 && !m_inVariantWithEncoding)) { WriteSimpleField(fieldName, null, false); return; @@ -1870,7 +1871,7 @@ namespace Opc.Ua /// public void WriteExpandedNodeIdArray(string fieldName, IList values) { - if (values == null || values.Count == 0) + if (values == null || (values.Count == 0 && !m_inVariantWithEncoding)) { WriteSimpleField(fieldName, null, false); return; @@ -1897,7 +1898,7 @@ namespace Opc.Ua /// public void WriteStatusCodeArray(string fieldName, IList values) { - if (values == null || values.Count == 0) + if (values == null || (values.Count == 0 && !m_inVariantWithEncoding)) { WriteSimpleField(fieldName, null, false); return; @@ -1932,7 +1933,7 @@ namespace Opc.Ua /// public void WriteDiagnosticInfoArray(string fieldName, IList values) { - if (values == null || values.Count == 0) + if (values == null || (values.Count == 0 && !m_inVariantWithEncoding)) { WriteSimpleField(fieldName, null, false); return; @@ -1959,7 +1960,7 @@ namespace Opc.Ua /// public void WriteQualifiedNameArray(string fieldName, IList values) { - if (values == null || values.Count == 0) + if (values == null || (values.Count == 0 && !m_inVariantWithEncoding)) { WriteSimpleField(fieldName, null, false); return; @@ -1986,7 +1987,7 @@ namespace Opc.Ua /// public void WriteLocalizedTextArray(string fieldName, IList values) { - if (values == null || values.Count == 0) + if (values == null || (values.Count == 0 && !m_inVariantWithEncoding)) { WriteSimpleField(fieldName, null, false); return; @@ -2013,7 +2014,7 @@ namespace Opc.Ua /// public void WriteVariantArray(string fieldName, IList values) { - if (values == null || values.Count == 0) + if (values == null || (values.Count == 0 && !m_inVariantWithEncoding)) { WriteSimpleField(fieldName, null, false); return; @@ -2046,7 +2047,7 @@ namespace Opc.Ua /// public void WriteDataValueArray(string fieldName, IList values) { - if (values == null || values.Count == 0) + if (values == null || (values.Count == 0 && !m_inVariantWithEncoding)) { WriteSimpleField(fieldName, null, false); return; @@ -2073,7 +2074,7 @@ namespace Opc.Ua /// public void WriteExtensionObjectArray(string fieldName, IList values) { - if (values == null || values.Count == 0) + if (values == null || (values.Count == 0 && !m_inVariantWithEncoding)) { WriteSimpleField(fieldName, null, false); return; @@ -2100,7 +2101,7 @@ namespace Opc.Ua /// public void WriteEncodeableArray(string fieldName, IList values, System.Type systemType) { - if (values == null || values.Count == 0) + if (values == null || (values.Count == 0 && !m_inVariantWithEncoding)) { WriteSimpleField(fieldName, null, false); return; @@ -2204,130 +2205,139 @@ namespace Opc.Ua /// public void WriteVariantContents(object value, TypeInfo typeInfo) { - // check for null. - if (value == null) + try { - return; - } + m_inVariantWithEncoding = UseReversibleEncoding; - m_commaRequired = false; - - // write scalar. - if (typeInfo.ValueRank < 0) - { - switch (typeInfo.BuiltInType) + // check for null. + if (value == null) { - case BuiltInType.Boolean: { WriteBoolean(null, (bool)value); return; } - case BuiltInType.SByte: { WriteSByte(null, (sbyte)value); return; } - case BuiltInType.Byte: { WriteByte(null, (byte)value); return; } - case BuiltInType.Int16: { WriteInt16(null, (short)value); return; } - case BuiltInType.UInt16: { WriteUInt16(null, (ushort)value); return; } - case BuiltInType.Int32: { WriteInt32(null, (int)value); return; } - case BuiltInType.UInt32: { WriteUInt32(null, (uint)value); return; } - case BuiltInType.Int64: { WriteInt64(null, (long)value); return; } - case BuiltInType.UInt64: { WriteUInt64(null, (ulong)value); return; } - case BuiltInType.Float: { WriteFloat(null, (float)value); return; } - case BuiltInType.Double: { WriteDouble(null, (double)value); return; } - case BuiltInType.String: { WriteString(null, (string)value); return; } - case BuiltInType.DateTime: { WriteDateTime(null, (DateTime)value); return; } - case BuiltInType.Guid: { WriteGuid(null, (Uuid)value); return; } - case BuiltInType.ByteString: { WriteByteString(null, (byte[])value); return; } - case BuiltInType.XmlElement: { WriteXmlElement(null, (XmlElement)value); return; } - case BuiltInType.NodeId: { WriteNodeId(null, (NodeId)value); return; } - case BuiltInType.ExpandedNodeId: { WriteExpandedNodeId(null, (ExpandedNodeId)value); return; } - case BuiltInType.StatusCode: { WriteStatusCode(null, (StatusCode)value); return; } - case BuiltInType.QualifiedName: { WriteQualifiedName(null, (QualifiedName)value); return; } - case BuiltInType.LocalizedText: { WriteLocalizedText(null, (LocalizedText)value); return; } - case BuiltInType.ExtensionObject: { WriteExtensionObject(null, (ExtensionObject)value); return; } - case BuiltInType.DataValue: { WriteDataValue(null, (DataValue)value); return; } - case BuiltInType.Enumeration: { WriteEnumerated(null, (Enum)value); return; } - } - } - - // write array. - else if (typeInfo.ValueRank <= 1) - { - switch (typeInfo.BuiltInType) - { - case BuiltInType.Boolean: { WriteBooleanArray(null, (bool[])value); return; } - case BuiltInType.SByte: { WriteSByteArray(null, (sbyte[])value); return; } - case BuiltInType.Byte: { WriteByteArray(null, (byte[])value); return; } - case BuiltInType.Int16: { WriteInt16Array(null, (short[])value); return; } - case BuiltInType.UInt16: { WriteUInt16Array(null, (ushort[])value); return; } - case BuiltInType.Int32: { WriteInt32Array(null, (int[])value); return; } - case BuiltInType.UInt32: { WriteUInt32Array(null, (uint[])value); return; } - case BuiltInType.Int64: { WriteInt64Array(null, (long[])value); return; } - case BuiltInType.UInt64: { WriteUInt64Array(null, (ulong[])value); return; } - case BuiltInType.Float: { WriteFloatArray(null, (float[])value); return; } - case BuiltInType.Double: { WriteDoubleArray(null, (double[])value); return; } - case BuiltInType.String: { WriteStringArray(null, (string[])value); return; } - case BuiltInType.DateTime: { WriteDateTimeArray(null, (DateTime[])value); return; } - case BuiltInType.Guid: { WriteGuidArray(null, (Uuid[])value); return; } - case BuiltInType.ByteString: { WriteByteStringArray(null, (byte[][])value); return; } - case BuiltInType.XmlElement: { WriteXmlElementArray(null, (XmlElement[])value); return; } - case BuiltInType.NodeId: { WriteNodeIdArray(null, (NodeId[])value); return; } - case BuiltInType.ExpandedNodeId: { WriteExpandedNodeIdArray(null, (ExpandedNodeId[])value); return; } - case BuiltInType.StatusCode: { WriteStatusCodeArray(null, (StatusCode[])value); return; } - case BuiltInType.QualifiedName: { WriteQualifiedNameArray(null, (QualifiedName[])value); return; } - case BuiltInType.LocalizedText: { WriteLocalizedTextArray(null, (LocalizedText[])value); return; } - case BuiltInType.ExtensionObject: { WriteExtensionObjectArray(null, (ExtensionObject[])value); return; } - case BuiltInType.DataValue: { WriteDataValueArray(null, (DataValue[])value); return; } - case BuiltInType.Enumeration: - { - Array array = value as Array; - WriteEnumeratedArray(null, array, array.GetType().GetElementType()); - return; - } - - case BuiltInType.Variant: - { - Variant[] variants = value as Variant[]; - - if (variants != null) - { - WriteVariantArray(null, variants); - return; - } - - object[] objects = value as object[]; - - if (objects != null) - { - WriteObjectArray(null, objects); - return; - } - - throw ServiceResultException.Create( - StatusCodes.BadEncodingError, - "Unexpected type encountered while encoding an array of Variants: {0}", - value.GetType()); - } - } - } - - // write matrix. - else if (typeInfo.ValueRank > 1) - { - Matrix matrix = value as Matrix; - if (matrix != null) - { - if (UseReversibleEncoding) - { - WriteVariantContents(matrix.Elements, new TypeInfo(typeInfo.BuiltInType, 1)); - } - else - { - int index = 0; - WriteStructureMatrix(matrix, 0, ref index, typeInfo); - } return; } - } - // oops - should never happen. - throw new ServiceResultException( - StatusCodes.BadEncodingError, - Utils.Format("Type '{0}' is not allowed in an Variant.", value.GetType().FullName)); + m_commaRequired = false; + + // write scalar. + if (typeInfo.ValueRank < 0) + { + switch (typeInfo.BuiltInType) + { + case BuiltInType.Boolean: { WriteBoolean(null, (bool)value); return; } + case BuiltInType.SByte: { WriteSByte(null, (sbyte)value); return; } + case BuiltInType.Byte: { WriteByte(null, (byte)value); return; } + case BuiltInType.Int16: { WriteInt16(null, (short)value); return; } + case BuiltInType.UInt16: { WriteUInt16(null, (ushort)value); return; } + case BuiltInType.Int32: { WriteInt32(null, (int)value); return; } + case BuiltInType.UInt32: { WriteUInt32(null, (uint)value); return; } + case BuiltInType.Int64: { WriteInt64(null, (long)value); return; } + case BuiltInType.UInt64: { WriteUInt64(null, (ulong)value); return; } + case BuiltInType.Float: { WriteFloat(null, (float)value); return; } + case BuiltInType.Double: { WriteDouble(null, (double)value); return; } + case BuiltInType.String: { WriteString(null, (string)value); return; } + case BuiltInType.DateTime: { WriteDateTime(null, (DateTime)value); return; } + case BuiltInType.Guid: { WriteGuid(null, (Uuid)value); return; } + case BuiltInType.ByteString: { WriteByteString(null, (byte[])value); return; } + case BuiltInType.XmlElement: { WriteXmlElement(null, (XmlElement)value); return; } + case BuiltInType.NodeId: { WriteNodeId(null, (NodeId)value); return; } + case BuiltInType.ExpandedNodeId: { WriteExpandedNodeId(null, (ExpandedNodeId)value); return; } + case BuiltInType.StatusCode: { WriteStatusCode(null, (StatusCode)value); return; } + case BuiltInType.QualifiedName: { WriteQualifiedName(null, (QualifiedName)value); return; } + case BuiltInType.LocalizedText: { WriteLocalizedText(null, (LocalizedText)value); return; } + case BuiltInType.ExtensionObject: { WriteExtensionObject(null, (ExtensionObject)value); return; } + case BuiltInType.DataValue: { WriteDataValue(null, (DataValue)value); return; } + case BuiltInType.Enumeration: { WriteEnumerated(null, (Enum)value); return; } + } + } + + // write array. + else if (typeInfo.ValueRank <= 1) + { + switch (typeInfo.BuiltInType) + { + case BuiltInType.Boolean: { WriteBooleanArray(null, (bool[])value); return; } + case BuiltInType.SByte: { WriteSByteArray(null, (sbyte[])value); return; } + case BuiltInType.Byte: { WriteByteArray(null, (byte[])value); return; } + case BuiltInType.Int16: { WriteInt16Array(null, (short[])value); return; } + case BuiltInType.UInt16: { WriteUInt16Array(null, (ushort[])value); return; } + case BuiltInType.Int32: { WriteInt32Array(null, (int[])value); return; } + case BuiltInType.UInt32: { WriteUInt32Array(null, (uint[])value); return; } + case BuiltInType.Int64: { WriteInt64Array(null, (long[])value); return; } + case BuiltInType.UInt64: { WriteUInt64Array(null, (ulong[])value); return; } + case BuiltInType.Float: { WriteFloatArray(null, (float[])value); return; } + case BuiltInType.Double: { WriteDoubleArray(null, (double[])value); return; } + case BuiltInType.String: { WriteStringArray(null, (string[])value); return; } + case BuiltInType.DateTime: { WriteDateTimeArray(null, (DateTime[])value); return; } + case BuiltInType.Guid: { WriteGuidArray(null, (Uuid[])value); return; } + case BuiltInType.ByteString: { WriteByteStringArray(null, (byte[][])value); return; } + case BuiltInType.XmlElement: { WriteXmlElementArray(null, (XmlElement[])value); return; } + case BuiltInType.NodeId: { WriteNodeIdArray(null, (NodeId[])value); return; } + case BuiltInType.ExpandedNodeId: { WriteExpandedNodeIdArray(null, (ExpandedNodeId[])value); return; } + case BuiltInType.StatusCode: { WriteStatusCodeArray(null, (StatusCode[])value); return; } + case BuiltInType.QualifiedName: { WriteQualifiedNameArray(null, (QualifiedName[])value); return; } + case BuiltInType.LocalizedText: { WriteLocalizedTextArray(null, (LocalizedText[])value); return; } + case BuiltInType.ExtensionObject: { WriteExtensionObjectArray(null, (ExtensionObject[])value); return; } + case BuiltInType.DataValue: { WriteDataValueArray(null, (DataValue[])value); return; } + case BuiltInType.Enumeration: + { + Array array = value as Array; + WriteEnumeratedArray(null, array, array.GetType().GetElementType()); + return; + } + + case BuiltInType.Variant: + { + Variant[] variants = value as Variant[]; + + if (variants != null) + { + WriteVariantArray(null, variants); + return; + } + + object[] objects = value as object[]; + + if (objects != null) + { + WriteObjectArray(null, objects); + return; + } + + throw ServiceResultException.Create( + StatusCodes.BadEncodingError, + "Unexpected type encountered while encoding an array of Variants: {0}", + value.GetType()); + } + } + } + + // write matrix. + else if (typeInfo.ValueRank > 1) + { + Matrix matrix = value as Matrix; + if (matrix != null) + { + if (UseReversibleEncoding) + { + WriteVariantContents(matrix.Elements, new TypeInfo(typeInfo.BuiltInType, 1)); + } + else + { + int index = 0; + WriteStructureMatrix(matrix, 0, ref index, typeInfo); + } + return; + } + } + + // oops - should never happen. + throw new ServiceResultException( + StatusCodes.BadEncodingError, + Utils.Format("Type '{0}' is not allowed in an Variant.", value.GetType().FullName)); + } + finally + { + m_inVariantWithEncoding = false; + } } #endregion @@ -2383,7 +2393,7 @@ namespace Opc.Ua /// public void WriteObjectArray(string fieldName, IList values) { - if (values == null || values.Count == 0) + if (values == null || (values.Count == 0 && !m_inVariantWithEncoding)) { WriteSimpleField(fieldName, null, false); return; diff --git a/Stack/Opc.Ua.Core/Types/Encoders/XmlDecoder.cs b/Stack/Opc.Ua.Core/Types/Encoders/XmlDecoder.cs index 6406f3b1af..4d1a03f682 100644 --- a/Stack/Opc.Ua.Core/Types/Encoders/XmlDecoder.cs +++ b/Stack/Opc.Ua.Core/Types/Encoders/XmlDecoder.cs @@ -1403,9 +1403,16 @@ namespace Opc.Ua /// public ExtensionObject ReadExtensionObject(string fieldName) { - if (!BeginField(fieldName, true)) + bool isNil; + + if (!BeginField(fieldName, true, out isNil)) { - return null; + if (isNil) + { + return null; + } + + return ExtensionObject.Null; } PushNamespace(Namespaces.OpcUaXsd); diff --git a/Stack/Opc.Ua.Core/Types/Encoders/XmlEncoder.cs b/Stack/Opc.Ua.Core/Types/Encoders/XmlEncoder.cs index 8693a1edf6..6d1fe53498 100644 --- a/Stack/Opc.Ua.Core/Types/Encoders/XmlEncoder.cs +++ b/Stack/Opc.Ua.Core/Types/Encoders/XmlEncoder.cs @@ -437,7 +437,12 @@ namespace Opc.Ua /// public void WriteString(string fieldName, string value) { - if (BeginField(fieldName, value == null, true)) + WriteString(fieldName, value, false); + } + + private void WriteString(string fieldName, string value, bool isArrayElement) + { + if (BeginField(fieldName, value == null, true, isArrayElement)) { // check the length. if (m_context.MaxStringLength > 0 && m_context.MaxStringLength < value.Length) @@ -502,7 +507,12 @@ namespace Opc.Ua /// public void WriteByteString(string fieldName, byte[] value) { - if (BeginField(fieldName, value == null, true)) + WriteByteString(fieldName, value, false); + } + + private void WriteByteString(string fieldName, byte[] value, bool isArrayElement = false) + { + if (BeginField(fieldName, value == null, true, isArrayElement)) { // check the length. if (m_context.MaxByteStringLength > 0 && m_context.MaxByteStringLength < value.Length) @@ -520,7 +530,12 @@ namespace Opc.Ua /// public void WriteXmlElement(string fieldName, XmlElement value) { - if (BeginField(fieldName, value == null, true)) + WriteXmlElement(fieldName, value, false); + } + + private void WriteXmlElement(string fieldName, XmlElement value, bool isArrayElement) + { + if (BeginField(fieldName, value == null, true, isArrayElement)) { m_writer.WriteRaw(value.OuterXml); EndField(fieldName); @@ -1230,7 +1245,7 @@ namespace Opc.Ua { for (int ii = 0; ii < values.Count; ii++) { - WriteString("String", values[ii]); + WriteString("String", values[ii], true); } } @@ -1346,7 +1361,7 @@ namespace Opc.Ua { for (int ii = 0; ii < values.Count; ii++) { - WriteByteString("ByteString", values[ii]); + WriteByteString("ByteString", values[ii], true); } } @@ -1375,7 +1390,7 @@ namespace Opc.Ua { for (int ii = 0; ii < values.Count; ii++) { - WriteXmlElement("XmlElement", values[ii]); + WriteXmlElement("XmlElement", values[ii], true); } } diff --git a/Stack/Opc.Ua.Core/Types/Schemas/SchemaValidator.cs b/Stack/Opc.Ua.Core/Types/Schemas/SchemaValidator.cs index 10301a1679..d833cecdf4 100644 --- a/Stack/Opc.Ua.Core/Types/Schemas/SchemaValidator.cs +++ b/Stack/Opc.Ua.Core/Types/Schemas/SchemaValidator.cs @@ -144,7 +144,7 @@ namespace Opc.Ua.Schema /// /// Loads the dictionary from a file. /// - protected object Load(System.Type type, string namespaceUri, string path) + protected object Load(System.Type type, string namespaceUri, string path, Assembly assembly = null) { // check if already loaded. if (m_loadedFiles.ContainsKey(namespaceUri)) @@ -178,7 +178,7 @@ namespace Opc.Ua.Schema } // load embedded resource. - return LoadResource(type, location, null); + return LoadResource(type, location, assembly); } if (!String.IsNullOrEmpty(path)) @@ -186,7 +186,7 @@ namespace Opc.Ua.Schema if (!File.Exists(path)) { // load embedded resource. - return LoadResource(type, path, null); + return LoadResource(type, path, assembly); } // check for file in the same directory as the input file. diff --git a/Tests/Opc.Ua.Core.Tests/Types/Encoders/EncoderCommon.cs b/Tests/Opc.Ua.Core.Tests/Types/Encoders/EncoderCommon.cs index 42820cf081..32a03365b1 100644 --- a/Tests/Opc.Ua.Core.Tests/Types/Encoders/EncoderCommon.cs +++ b/Tests/Opc.Ua.Core.Tests/Types/Encoders/EncoderCommon.cs @@ -209,11 +209,14 @@ namespace Opc.Ua.Core.Tests.Types.Encoders Encode(encoder, builtInType, builtInType.ToString(), expected); Dispose(encoder); var buffer = encoderStream.ToArray(); - string jsonFormatted; + string formatted; switch (encoderType) { case EncodingType.Json: - jsonFormatted = PrettifyAndValidateJson(Encoding.UTF8.GetString(buffer)); + formatted = PrettifyAndValidateJson(Encoding.UTF8.GetString(buffer)); + break; + default: + formatted = Encoding.UTF8.GetString(buffer); break; } var decoderStream = new MemoryStream(buffer);