private static DataVariableNodeIdMap GetDataVariableNodeIds(List <DataVariableModel> dataVariables, List <DataVariableModel> typeDataVariables)
        {
            if (dataVariables?.Any() != true || typeDataVariables?.Any() != true)
            {
                return(null);
            }
            var dataVariableNodeIdMap = new DataVariableNodeIdMap();

            foreach (var typeDataVariable in typeDataVariables)
            {
                var dataVariable = dataVariables.FirstOrDefault(dv => dv.BrowseName.EndsWith(typeDataVariable.BrowseName));
                var map          = new DataVariableNodeIdMapEntry
                {
                    NodeId = dataVariable.NodeId,
                    Map    = GetDataVariableNodeIds(dataVariable.DataVariables, typeDataVariable.DataVariables)
                };
                dataVariableNodeIdMap.DataVariableNodeIdsByBrowseName.Add(dataVariable.BrowseName, map);
            }
            return(dataVariableNodeIdMap);
        }
        public static string GetMapAsString(DataVariableNodeIdMap dataVariableNodeIdsByBrowseName)
        {
            var map = JsonSerializer.Serialize <DataVariableNodeIdMap>(dataVariableNodeIdsByBrowseName);

            return(map);
        }
        public void AddVariableToProfileModel(ProfileTypeDefinitionModel profileItem, IDALContext dalContext)
        {
            string description         = _model.Description?.FirstOrDefault()?.Text;
            var    typeDefinitionModel = _model.TypeDefinition?.ImportProfileItem(dalContext);

            // TODO Capture the DataVariable TypeDefinition somewhere in the ProfileItem
            var attributeDataType = _model.DataType.GetAttributeDataType(profileItem, dalContext);

            if (attributeDataType != null)
            {
                int attributeTypeId = 0;
                if (this._model is PropertyModel)
                {
                    attributeTypeId = (int)AttributeTypeIdEnum.Property;
                }
                else if (this._model is DataVariableModel)
                {
                    attributeTypeId = (int)AttributeTypeIdEnum.DataVariable;
                }
                else
                {
                    throw new Exception($"Unexpected child item {_model?.DisplayName} of type {this.GetType().Name} on item {profileItem.Name} ({profileItem.ID})");
                }


                string dataVariableNodeIds = null;
                if (_model.DataVariables?.Any() == true && _model?.TypeDefinition?.DataVariables?.Any() == true)
                {
                    var map = GetDataVariableNodeIds(_model.DataVariables, _model.TypeDefinition.DataVariables);
                    dataVariableNodeIds = DataVariableNodeIdMap.GetMapAsString(map);
                }
                var attribute = new ProfileAttributeModel
                {
                    IsActive        = true,
                    Name            = _model.DisplayName?.FirstOrDefault()?.Text,
                    SymbolicName    = _model.SymbolicName,
                    BrowseName      = _model.BrowseName,
                    Namespace       = NodeModelUtils.GetNamespaceFromNodeId(_model.NodeId),
                    IsRequired      = ObjectModelImportProfile.GetModelingRuleForProfile(_model.ModelingRule),
                    ModelingRule    = _model.ModelingRule,
                    IsArray         = (_model.ValueRank ?? -1) != -1,
                    ValueRank       = _model.ValueRank,
                    ArrayDimensions = _model.ArrayDimensions,
                    Description     = description,
                    AttributeType   = new LookupItemModel {
                        ID = attributeTypeId
                    },
                    DataType                 = attributeDataType,
                    DataVariableNodeIds      = dataVariableNodeIds,
                    TypeDefinitionId         = profileItem.ID,
                    TypeDefinition           = profileItem,
                    VariableTypeDefinitionId = typeDefinitionModel?.ID,
                    VariableTypeDefinition   = typeDefinitionModel,
                    OpcNodeId                = NodeModelUtils.GetNodeIdIdentifier(_model.NodeId),
                    AdditionalData           = _model.Value,
                    AccessLevel              = _model.AccessLevel,
                    UserAccessLevel          = _model.UserAccessLevel,
                    AccessRestrictions       = _model.AccessRestrictions,
                    WriteMask                = _model.WriteMask,
                    UserWriteMask            = _model.UserWriteMask,
                };

                var euInfo = NodeModelOpcExtensions.GetEUInformation(_model.EngineeringUnit);
                if (euInfo != null)
                {
                    var engUnit = new EngineeringUnitModel
                    {
                        DisplayName  = euInfo.DisplayName.Text,
                        Description  = euInfo.Description.Text,
                        UnitId       = euInfo.UnitId,
                        NamespaceUri = euInfo.NamespaceUri,
                    };
                    engUnit           = dalContext.GetOrCreateEngineeringUnitAsync(engUnit);
                    attribute.EngUnit = engUnit;
                }
                attribute.EngUnitOpcNodeId   = _model.EngUnitNodeId;
                attribute.MinValue           = (decimal?)_model.MinValue;
                attribute.MaxValue           = (decimal?)_model.MaxValue;
                attribute.InstrumentMinValue = (decimal?)_model.InstrumentMinValue;
                attribute.InstrumentMaxValue = (decimal?)_model.InstrumentMaxValue;

                if (profileItem.Attributes == null)
                {
                    profileItem.Attributes = new List <ProfileAttributeModel>();
                }
                profileItem.Attributes.Add(attribute);
            }
            else
            {
                throw new Exception($"Data type {_model.DataType} not resolved.");
            }
        }