Skip to content

Commit

Permalink
Address Issue 85 - Convertor should support arrays for DisplayName an…
Browse files Browse the repository at this point in the history
…d Description (#87)

* Setup Test file for testing

* Write test files

Fix test files that were broken by accident

* Testing complete for Localized Texts
  • Loading branch information
Archie-Miller authored Jan 7, 2025
1 parent 8181cfd commit 72aac8c
Show file tree
Hide file tree
Showing 4 changed files with 476 additions and 19 deletions.
114 changes: 101 additions & 13 deletions NodeSetToAML.cs
Original file line number Diff line number Diff line change
Expand Up @@ -586,27 +586,109 @@ private void AddBaseNodeClassAttributes( AttributeSequence seq, UANode uanode, U
uriatt.Value = myuri;
}

if (uanode.DisplayName != null &&
uanode.DisplayName.Length > 0 &&
uanode.DisplayName[0].Value != uanode.DecodedBrowseName.Name)
BuildLocalizedTextAttribute( seq, "DisplayName", uanode.DisplayName,
uanode.DecodedBrowseName.Name, ignoreEqual: true );
BuildLocalizedTextAttribute( seq, "Description", uanode.Description,
uanode.DecodedBrowseName.Name, ignoreEqual: false );

UAType uaType = uanode as UAType;
if ( uaType != null && uaType.IsAbstract )
{
AddModifyAttribute(seq, "DisplayName", "LocalizedText",
uanode.DisplayName[0].Value);
AddModifyAttribute(seq, "IsAbstract", "Boolean", uaType.IsAbstract);
}
}

if (uanode.Description != null &&
uanode.Description.Length > 0 &&
uanode.Description[0].Value.Length > 0)
private void BuildLocalizedTextAttribute(
AttributeSequence seq,
string attributeName,
NodeSet.LocalizedText[] localizedTexts,
string equalityString, bool ignoreEqual )
{
if( localizedTexts != null )
{
AddModifyAttribute(seq, "Description", "LocalizedText",
uanode.Description[0].Value);
if( localizedTexts.Length > 1 )
{
AddModifyAttribute( seq, attributeName, "LocalizedText", localizedTexts[ 0 ].Value );

AttributeType displayNameAttribute = seq[ attributeName ];
if( displayNameAttribute != null )
{
string previousLocaleId = string.Empty;
string defaultLocaleId = GetLocaleId( localizedTexts[ 0 ], ref previousLocaleId );
AttributeType arrayRoot = AddModifyAttribute( displayNameAttribute.Attribute, defaultLocaleId, "String",
localizedTexts[ 0 ].Value );

// Redo first element
previousLocaleId = string.Empty;
for( int index = 0; index < localizedTexts.Length; index++ )
{
string localeId = GetLocaleId( localizedTexts[ index ], ref previousLocaleId );
AddModifyAttribute( arrayRoot.Attribute, "aml-lang=" + localeId,
"String", localizedTexts[ index ].Value );
}
}
}
else if( localizedTexts.Length > 0 )
{
NodeSet.LocalizedText localizedText = localizedTexts[ 0 ];
if( ignoreEqual == false ||
localizedText.Value != equalityString )
{
AttributeType root = AddModifyAttribute( seq, attributeName, "LocalizedText", localizedText.Value );

if( !String.IsNullOrEmpty( localizedText.Locale ) )
{
AddModifyAttribute( root.Attribute, localizedText.Locale, "LocalizedText", localizedText.Value );
}
}
}
}
}

UAType uaType = uanode as UAType;
if ( uaType != null && uaType.IsAbstract )
private string GetLocaleId( NodeSet.LocalizedText localizedText, ref string lastUnknownLocale )
{
string localeId = string.Empty;

if ( localizedText != null )
{
AddModifyAttribute(seq, "IsAbstract", "Boolean", uaType.IsAbstract);
if ( String.IsNullOrEmpty( localizedText.Locale ) )
{
if ( String.IsNullOrEmpty( lastUnknownLocale ) )
{
localeId = "qaa";
}
else
{
if ( lastUnknownLocale.Length == 3 && lastUnknownLocale[0] == 'q' )
{
char secondChar = lastUnknownLocale[1];
char lastChar = lastUnknownLocale[ 2 ];
if ( lastChar == 'z' )
{
// It's pretty impractical to have 20*26 unknown locales for a single node.
if( secondChar < 't' )
{
secondChar++;
localeId = "q" + secondChar + 'a';
}
}
else
{
localeId = "q" + secondChar + (char)( lastChar + 1 );
}
}
}
lastUnknownLocale = localeId;
}
else
{
localeId = localizedText.Locale;
}

return localeId;
}

return localeId;
}

private AttributeType AddModifyAttribute(AttributeSequence seq, string name, string refDataType, Variant val, bool bListOf = false, string sURI = uaNamespaceURI)
Expand Down Expand Up @@ -910,7 +992,13 @@ private AttributeType AddModifyAttribute(AttributeSequence seq, string name, str
if( localizedText != null && localizedText.Text != null )
{
a.DefaultAttributeValue = a.AttributeValue = localizedText.Text;
if ( !string.IsNullOrEmpty( localizedText.Locale ) )
{
AddModifyAttribute(a.Attribute, localizedText.Locale,
"String", localizedText.Text);
}
}

break;
}

Expand Down
3 changes: 2 additions & 1 deletion Opc2AmlConsole/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"profiles": {
"Opc2AmlConsole": {
"commandName": "Project"
"commandName": "Project",
"commandLineArgs": "--Nodeset TestAml.xml"
}
}
}
147 changes: 142 additions & 5 deletions SystemTest/NodeSetFiles/TestAml.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2126,7 +2126,8 @@
</References>
</UAObject>
<UAVariable DataType="Int32" ValueRank="1" NodeId="ns=1;i=6126" ArrayDimensions="10" BrowseName="1:OneDimension" ParentNodeId="ns=1;i=5011" UserAccessLevel="3" AccessLevel="3">
<DisplayName>OneDimension</DisplayName>
<DisplayName>OneDimensionArray</DisplayName>
<Description>A One Dimensional Array</Description>
<References>
<Reference ReferenceType="Organizes" IsForward="false">ns=1;i=5011</Reference>
<Reference ReferenceType="HasTypeDefinition">i=63</Reference>
Expand All @@ -2147,7 +2148,10 @@
</Value>
</UAVariable>
<UAVariable DataType="Int32" ValueRank="2" NodeId="ns=1;i=6127" ArrayDimensions="2,5" BrowseName="1:TwoDimensions" ParentNodeId="ns=1;i=5011" UserAccessLevel="3" AccessLevel="3">
<DisplayName>TwoDimensions</DisplayName>
<DisplayName>TwoDimensionArray</DisplayName>
<DisplayName>aTwoDimensionalArray</DisplayName>
<Description>A Different Two Dimension Array </Description>
<Description>Another Two Dimension Array </Description>
<References>
<Reference ReferenceType="Organizes" IsForward="false">ns=1;i=5011</Reference>
<Reference ReferenceType="HasTypeDefinition">i=63</Reference>
Expand All @@ -2168,7 +2172,10 @@
</Value>
</UAVariable>
<UAVariable DataType="Int32" ValueRank="5" NodeId="ns=1;i=6128" ArrayDimensions="2,2,2,2,2" BrowseName="1:FiveDimensions" ParentNodeId="ns=1;i=5011" UserAccessLevel="3" AccessLevel="3">
<DisplayName>FiveDimensions</DisplayName>
<DisplayName Locale="en">FiveDimensionArray</DisplayName>
<Description Locale="fr">A Five DimensionArray</Description>
<Description>Another Five Dimension Array </Description>

<References>
<Reference ReferenceType="Organizes" IsForward="false">ns=1;i=5011</Reference>
<Reference ReferenceType="HasTypeDefinition">i=63</Reference>
Expand Down Expand Up @@ -3087,13 +3094,143 @@
</uax:ExtensionObject>
</Value>
</UAVariable>
<UAObject SymbolicName="LocalizedTextAttributes" NodeId="ns=1;i=5024" BrowseName="1:LocalizedTextAttributes" ParentNodeId="i=85">
<DisplayName>Localized Text Attributes</DisplayName>
<References>
<Reference ReferenceType="Organizes" IsForward="false">i=85</Reference>
<Reference ReferenceType="HasTypeDefinition">i=61</Reference>
</References>
</UAObject>

<UAVariable NodeId="ns=1;i=6227" BrowseName="1:NoLocalizedText" DataType="LocalizedText" ValueRank="-1" ArrayDimensions="" ParentNodeId="ns=1;i=5024" UserAccessLevel="3" AccessLevel="3" >
<References>
<Reference ReferenceType="HasTypeDefinition" BrowseName="PropertyType">i=63</Reference>
<Reference ReferenceType="Organizes" IsForward="false">ns=1;i=5024</Reference>
</References>
</UAVariable>

<UAVariable NodeId="ns=1;i=6228" BrowseName="1:SingleLocalizedText" DataType="LocalizedText" ValueRank="-1" ArrayDimensions="" ParentNodeId="ns=1;i=5024" UserAccessLevel="3" AccessLevel="3" >
<DisplayName>Single Localized Text</DisplayName>
<Description>A Single Description with no Locale</Description>
<References>
<Reference ReferenceType="HasTypeDefinition" BrowseName="PropertyType">i=63</Reference>
<Reference ReferenceType="Organizes" IsForward="false">ns=1;i=5024</Reference>
</References>
<Value>
<uax:LocalizedText>
<uax:Text>Attributes have display name and description, but no Locale</uax:Text>
</uax:LocalizedText>
</Value>
</UAVariable>

<UAVariable NodeId="ns=1;i=6229" BrowseName="1:SingleLocalizedTextLocale" DataType="LocalizedText" ValueRank="-1" ArrayDimensions="" ParentNodeId="ns=1;i=5024" UserAccessLevel="3" AccessLevel="3" >
<DisplayName Locale="en">Single Localized Text with Locale</DisplayName>
<Description Locale="en">A Single Description with a Locale</Description>
<References>
<Reference ReferenceType="HasTypeDefinition" BrowseName="PropertyType">i=63</Reference>
<Reference ReferenceType="Organizes" IsForward="false">ns=1;i=5024</Reference>
</References>
<Value>
<uax:LocalizedText>
<uax:Locale>en</uax:Locale>
<uax:Text>Attributes have display name and description with a single Locale</uax:Text>
</uax:LocalizedText>
</Value>
</UAVariable>

<UAVariable NodeId="ns=1;i=6230" BrowseName="1:MultipleFirstNoLocale" DataType="LocalizedText" ValueRank="1" ArrayDimensions="1" ParentNodeId="ns=1;i=5024" UserAccessLevel="3" AccessLevel="3" >
<DisplayName>First DisplayName with no Locale</DisplayName>
<Description>First Description with no Locale</Description>
<DisplayName Locale="en">Second DisplayName with a Locale</DisplayName>
<Description Locale="en">Second Description with a Locale</Description>
<DisplayName Locale="fr">Troisième texte localisé avec paramètres régionaux</DisplayName>
<Description Locale="fr">Troisième description avec un paramètre régional</Description>
<DisplayName Locale="de">Letzter lokalisierter Text mit Gebietsschema</DisplayName>
<Description Locale="de">Letzte Beschreibung mit einem Gebietsschema</Description>
<References>
<Reference ReferenceType="HasTypeDefinition" BrowseName="PropertyType">i=63</Reference>
<Reference ReferenceType="Organizes" IsForward="false">ns=1;i=5024</Reference>
</References>
<Value>
<uax:ListOfLocalizedText>
<uax:LocalizedText>
<uax:Text>Multiple</uax:Text>
</uax:LocalizedText>
<uax:LocalizedText>
<uax:Locale>en</uax:Locale>
<uax:Text>DisplayNames and Descriptions</uax:Text>
</uax:LocalizedText>
<uax:LocalizedText>
<uax:Locale>en</uax:Locale>
<uax:Text>first without a locale</uax:Text>
</uax:LocalizedText>
</uax:ListOfLocalizedText>
</Value>
</UAVariable>

<UAVariable NodeId="ns=1;i=6231" BrowseName="1:MultipleLastNoLocale" DataType="LocalizedText" ValueRank="1" ArrayDimensions="1" ParentNodeId="ns=1;i=5024" UserAccessLevel="3" AccessLevel="3" >
<DisplayName Locale="en">First DisplayName with a Locale</DisplayName>
<Description Locale="en">First Description with a Locale</Description>
<DisplayName Locale="fr">Deuxième DisplayName avec une locale</DisplayName>
<Description Locale="fr">Deuxième description avec une locale</Description>
<DisplayName Locale="de">Dritter DisplayName mit einem Gebietsschema</DisplayName>
<Description Locale="de">Dritte Beschreibung mit einem Gebietsschema</Description>
<DisplayName>Last DisplayName with no Locale</DisplayName>
<Description>Last Description with no Locale</Description>
<References>
<Reference ReferenceType="HasTypeDefinition" BrowseName="PropertyType">i=63</Reference>
<Reference ReferenceType="Organizes" IsForward="false">ns=1;i=5024</Reference>
</References>
<Value>
<uax:ListOfLocalizedText>
<uax:LocalizedText>
<uax:Locale>en</uax:Locale>
<uax:Text>Multiple</uax:Text>
</uax:LocalizedText>
<uax:LocalizedText>
<uax:Locale>en</uax:Locale>
<uax:Text>DisplayNames and Descriptions</uax:Text>
</uax:LocalizedText>
<uax:LocalizedText>
<uax:Text>last without a locale</uax:Text>
</uax:LocalizedText>
</uax:ListOfLocalizedText>
</Value>
</UAVariable>

<UAVariable NodeId="ns=1;i=6232" BrowseName="1:MultipleNoLocale" DataType="LocalizedText" ValueRank="1" ArrayDimensions="1" ParentNodeId="ns=1;i=5024" UserAccessLevel="3" AccessLevel="3" >
<DisplayName>First DisplayName with no Locale</DisplayName>
<Description>First Description with no Locale</Description>
<DisplayName>Second DisplayName with no Locale</DisplayName>
<Description>Second Description with no Locale</Description>
<DisplayName>Third DisplayName with no Locale</DisplayName>
<Description>Third Description with no Locale</Description>
<DisplayName>Last DisplayName with no Locale</DisplayName>
<Description>Last Description with no Locale</Description>
<References>
<Reference ReferenceType="HasTypeDefinition" BrowseName="PropertyType">i=63</Reference>
<Reference ReferenceType="Organizes" IsForward="false">ns=1;i=5024</Reference>
</References>
<Value>
<uax:ListOfLocalizedText>
<uax:LocalizedText>
<uax:Text>Multiple</uax:Text>
</uax:LocalizedText>
<uax:LocalizedText>
<uax:Text>DisplayNames and Descriptions</uax:Text>
</uax:LocalizedText>
<uax:LocalizedText>
<uax:Text>all without a locale</uax:Text>
</uax:LocalizedText>
</uax:ListOfLocalizedText>
</Value>
</UAVariable>

<!-- Next Numbers
ObjectType 1009
VariableType 2001
DataType 3004
Object 5024
Variable 6227
Object 5025
Variable 6232
-->
</UANodeSet>
Loading

0 comments on commit 72aac8c

Please sign in to comment.