Skip to content

Commit e6a5ba4

Browse files
98 type only for attributes (#113)
* Remove NodeId from InterfaceFamilyType IsAbstract Similar to what was done for InverseName. Also done for Symmetrical, and recursively into the InverseName attribute, which had the same problem * Add Typeonly to all attributes in Interface Libraries.
1 parent 6e4bb74 commit e6a5ba4

File tree

4 files changed

+169
-34
lines changed

4 files changed

+169
-34
lines changed

NodeSetToAML.cs

Lines changed: 59 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1553,9 +1553,17 @@ private AttributeType AddModifyAttribute(AttributeSequence seq, string name, Nod
15531553
}
15541554

15551555

1556-
private void OverrideBooleanAttribute(AttributeSequence seq, string AttributeName, Boolean value)
1556+
private AttributeType OverrideBooleanAttribute(AttributeSequence seq,
1557+
string AttributeName,
1558+
Boolean value,
1559+
bool typeOnly = false)
15571560
{
15581561
var at = AddModifyAttribute(seq, AttributeName, "Boolean", value);
1562+
if (at != null && typeOnly)
1563+
{
1564+
at.AdditionalInformation.Append("OpcUa:TypeOnly");
1565+
}
1566+
return at;
15591567
}
15601568

15611569

@@ -2560,14 +2568,17 @@ private void SetArrayDimensions( AttributeSequence attributes, string arrayDimen
25602568

25612569
#region ICL
25622570

2563-
private void OverrideAttribute(IClassWithBaseClassReference owner, string Name, string AttType, object val)
2571+
private void OverrideAttribute(IClassWithBaseClassReference owner,
2572+
string Name,
2573+
string AttType,
2574+
object value)
25642575
{
25652576
var atts = owner.GetInheritedAttributes();
25662577
foreach (var aa in atts)
25672578
{
25682579
if (aa.Name == Name)
25692580
{
2570-
if (aa.AttributeDataType == AttType && aa.AttributeValue.Equals(val))
2581+
if (aa.AttributeDataType == AttType && aa.AttributeValue.Equals(value))
25712582
{
25722583
return; // no need to override
25732584
}
@@ -2577,7 +2588,9 @@ private void OverrideAttribute(IClassWithBaseClassReference owner, string Name,
25772588
AttributeType a = owner.Attribute.Append();
25782589
a.Name = Name;
25792590
a.AttributeDataType = AttType;
2580-
a.AttributeValue = val;
2591+
a.AttributeValue = value;
2592+
2593+
a.AdditionalInformation.Append("OpcUa:TypeOnly");
25812594
}
25822595

25832596
private void ProcessReferenceType(ref InterfaceClassLibType icl, NodeId nodeId)
@@ -2621,43 +2634,54 @@ private void ProcessReferenceType(ref InterfaceClassLibType icl, NodeId nodeId)
26212634
// Only sets it if it is true -
26222635
// It doesn't matter if 'References' is set x times,
26232636
// it would take more time to look it up each time
2624-
OverrideBooleanAttribute( added.Attribute, "IsAbstract", refnode.IsAbstract );
2637+
RemoveUnwantedNodeIdAttribute(
2638+
OverrideBooleanAttribute(
2639+
added.Attribute, "IsAbstract", refnode.IsAbstract, typeOnly: true));
26252640

26262641
// override any attribute values
26272642
if (BaseNodeId != null)
26282643
{
26292644
var basenode = FindNode<NodeSet.UAReferenceType>(BaseNodeId);
2630-
2631-
if (basenode.IsAbstract != refnode.IsAbstract)
2632-
OverrideBooleanAttribute(added.Attribute, "IsAbstract", refnode.IsAbstract);
2645+
26332646
if (basenode.Symmetric != refnode.Symmetric)
2634-
OverrideBooleanAttribute(added.Attribute, "Symmetric", refnode.Symmetric);
2647+
{
2648+
RemoveUnwantedNodeIdAttribute(
2649+
OverrideBooleanAttribute(
2650+
added.Attribute, "Symmetric", refnode.Symmetric, typeOnly: true));
2651+
}
26352652

26362653
if (refnode.InverseName != null)
26372654
{
26382655
AttributeType inverseNameAttribute = AddModifyAttribute(added.Attribute,
26392656
"InverseName", "LocalizedText", refnode.InverseName[0].Value);
2640-
2641-
if ( inverseNameAttribute != null )
2642-
{
2643-
AttributeType unwantedNodeIdAttribute = inverseNameAttribute.Attribute["NodeId"];
2644-
if ( unwantedNodeIdAttribute != null )
2645-
{
2646-
inverseNameAttribute.Attribute.RemoveElement(unwantedNodeIdAttribute);
2647-
}
2648-
}
2657+
RemoveUnwantedNodeIdAttribute(inverseNameAttribute);
2658+
inverseNameAttribute.AdditionalInformation.Append("OpcUa:TypeOnly");
26492659
}
26502660

2651-
OverrideAttribute(added, IsSource, "xs:boolean", true);
2652-
OverrideAttribute(added, RefClassConnectsToPath, "xs:string", (inverseAdded != null ? inverseAdded.CAEXPath() : added.CAEXPath()));
2661+
// Need typeonly here
2662+
OverrideAttribute(added, IsSource, "xs:boolean", value: true);
2663+
OverrideAttribute(added, RefClassConnectsToPath, "xs:string",
2664+
(inverseAdded != null ? inverseAdded.CAEXPath() : added.CAEXPath()));
26532665

26542666
if (inverseAdded != null)
26552667
{
26562668
if (basenode.IsAbstract != refnode.IsAbstract)
2657-
OverrideBooleanAttribute(inverseAdded.Attribute, "IsAbstract", refnode.IsAbstract);
2669+
{
2670+
RemoveUnwantedNodeIdAttribute(
2671+
OverrideBooleanAttribute(
2672+
inverseAdded.Attribute, "IsAbstract", refnode.IsAbstract, typeOnly: true));
2673+
}
26582674
if (basenode.Symmetric != refnode.Symmetric)
2659-
OverrideBooleanAttribute(inverseAdded.Attribute, "Symmetric", refnode.Symmetric);
2660-
AddModifyAttribute(inverseAdded.Attribute, "InverseName", "LocalizedText", refnode.DecodedBrowseName.Name);
2675+
{
2676+
RemoveUnwantedNodeIdAttribute(
2677+
OverrideBooleanAttribute(
2678+
inverseAdded.Attribute, "Symmetric", refnode.Symmetric, typeOnly: true));
2679+
}
2680+
2681+
AttributeType inverseNameAttribute = AddModifyAttribute(
2682+
inverseAdded.Attribute, "InverseName", "LocalizedText", refnode.DecodedBrowseName.Name);
2683+
RemoveUnwantedNodeIdAttribute(inverseNameAttribute);
2684+
inverseNameAttribute.AdditionalInformation.Append("OpcUa:TypeOnly");
26612685

26622686
OverrideAttribute(inverseAdded, IsSource, "xs:boolean", false);
26632687
OverrideAttribute(inverseAdded, RefClassConnectsToPath, "xs:string", added.CAEXPath());
@@ -2669,6 +2693,18 @@ private void ProcessReferenceType(ref InterfaceClassLibType icl, NodeId nodeId)
26692693
MinimizeNodeId( nodeIdAttribute );
26702694
}
26712695

2696+
private void RemoveUnwantedNodeIdAttribute( AttributeType attribute )
2697+
{
2698+
if (attribute != null)
2699+
{
2700+
AttributeType unwantedNodeIdAttribute = attribute.Attribute["NodeId"];
2701+
if (unwantedNodeIdAttribute != null)
2702+
{
2703+
attribute.Attribute.RemoveElement(unwantedNodeIdAttribute);
2704+
}
2705+
}
2706+
}
2707+
26722708
#endregion
26732709

26742710

SystemTest/TestCommandLine.cs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
11
using Microsoft.VisualStudio.TestTools.UnitTesting;
22
using System;
33
using System.Collections.Generic;
4-
using System.Diagnostics;
54
using System.IO;
65
using System.Linq;
76
using System.Reflection;
87
using System.Runtime.Versioning;
9-
using System.Text;
10-
using System.Threading.Tasks;
11-
using static Org.BouncyCastle.Math.EC.ECCurve;
128

139
namespace SystemTest
1410
{
15-
[TestClass]
11+
12+
// Disable for development
13+
// [TestClass]
1614

1715
public class TestCommandLine
1816
{

SystemTest/TestInverseNameNodeId.cs

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,49 @@ public class TestInverseNameNodeId
1717
// The Namespaces of BrowseNames differ between the generated AML file and the original Nodeset file.
1818
// Test Both NodeId NamespaceUris and BrowseNameUris
1919

20-
private const string FxIdPrefix = "nsu%3Dhttp%3A%2F%2Fopcfoundation.org%2FUA%2FFX%2FAC%2F%3Bi%3D";
21-
private const string AmlFxTestPrefix = "nsu%3Dhttp%3A%2F%2Fopcfoundation.org%2FUA%2FFX%2FAML%2FTESTING%2FAmlFxTest%2F%3Bi%3D";
22-
public const string TestAmlUri = "http://opcfoundation.org/UA/FX/AML/TESTING/AmlFxTest/";
23-
private const string FxAcUri = "http://opcfoundation.org/UA/FX/AC/";
24-
private const string DiUri = "http://opcfoundation.org/UA/DI/";
25-
2620
CAEXDocument m_document = null;
2721

2822
#region Tests
2923

24+
[TestMethod]
25+
public void TestAllReferenceAttributes()
26+
{
27+
CAEXDocument document = GetDocument();
28+
29+
foreach (InterfaceClassLibType classLibType in document.InterfaceClassLib)
30+
{
31+
foreach (InterfaceFamilyType interfaceType in classLibType)
32+
{
33+
string name = classLibType.Name + "_" + interfaceType.Name + "_" + interfaceType.Name;
34+
TestInterfaceType( interfaceType, name);
35+
}
36+
}
37+
}
38+
39+
private void TestInterfaceType( InterfaceFamilyType interfaceFamilyType, string name)
40+
{
41+
foreach (AttributeType attribute in interfaceFamilyType.Attribute)
42+
{
43+
TestAttribute(attribute, interfaceFamilyType.Name + "_" + attribute.Name);
44+
}
45+
46+
foreach (InterfaceFamilyType interfaceType in interfaceFamilyType)
47+
{
48+
TestInterfaceType(interfaceType, name + "_" + interfaceType.Name);
49+
}
50+
}
51+
52+
private void TestAttribute(AttributeType attribute, string name)
53+
{
54+
AttributeType subAttribute = attribute.Attribute["NodeId"];
55+
Assert.IsNull(subAttribute, name + " should not have NodeId");
56+
57+
foreach (AttributeType sub in attribute.Attribute)
58+
{
59+
TestAttribute(sub, name + "_" + sub.Name);
60+
}
61+
}
62+
3063
[TestMethod]
3164
public void TestAll()
3265
{

SystemTest/TestTypeOnly.cs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,30 @@ public void TestLibraryAttributes()
7474
Debug.WriteLine( $"Attributes tested: {attributesTested} Interfaces {interfacesTested} RoleClasses {roleClassesTested}" );
7575
}
7676

77+
78+
[TestMethod, Timeout(TestHelper.UnitTestTimeout)]
79+
public void TestTypeOnlyInterface()
80+
{
81+
CAEXDocument document = GetDocument();
82+
83+
int badCount = 0;
84+
85+
int interfacesTested = 0;
86+
foreach (InterfaceClassLibType libType in document.CAEXFile.InterfaceClassLib)
87+
{
88+
if (libType.Name.StartsWith("ICL_http", StringComparison.OrdinalIgnoreCase))
89+
{
90+
foreach (InterfaceFamilyType interfaceFamilyType in libType)
91+
{
92+
badCount += TestAttributeForTypeOnly(interfaceFamilyType.Attribute);
93+
}
94+
}
95+
}
96+
97+
Assert.AreEqual(0, badCount, "There are " + badCount.ToString() + " attributes without TypeOnly in the additional information");
98+
}
99+
100+
77101
private int count = 0;
78102

79103
[TestMethod, Timeout( TestHelper.UnitTestTimeout )]
@@ -322,7 +346,51 @@ private void TestForNonExistingNodeId( AttributeSequence attributes )
322346
}
323347
}
324348

349+
private int TestAttributeForTypeOnly(AttributeSequence attributes)
350+
{
351+
int badCount = 0;
352+
353+
foreach (AttributeType attributeType in attributes)
354+
{
355+
if (attributeType.Name != "NodeId")
356+
{
357+
badCount += TestAttributeForTypeOnly(attributeType.Attribute);
358+
}
325359

360+
if (attributeType.AdditionalInformation != null)
361+
{
362+
if (attributeType.AdditionalInformation.Count == 1)
363+
{
364+
foreach (object info in attributeType.AdditionalInformation)
365+
{
366+
if (info.GetType().Name == "String")
367+
{
368+
string value = (string)info;
369+
if (value != TypeOnly)
370+
{
371+
badCount++;
372+
}
373+
}
374+
else
375+
{
376+
badCount++;
377+
}
378+
}
379+
}
380+
else
381+
{
382+
badCount++;
383+
Console.WriteLine("AttributeType: " + attributeType.Name + " has " + attributeType.AdditionalInformation.Count + " additional information");
384+
}
385+
}
386+
else
387+
{
388+
badCount++;
389+
}
390+
}
391+
392+
return badCount;
393+
}
326394

327395
#endregion
328396
}

0 commit comments

Comments
 (0)