protected override void UpdateProfileItem(ProfileTypeDefinitionModel profileItem, IDALContext dalContext)
 {
     profileItem.TypeId = (int)ProfileItemTypeEnum.Object;
     base.UpdateProfileItem(profileItem, dalContext);
     if (profileItem.TypeId != (int)ProfileItemTypeEnum.Object)
     {
         throw new Exception();
     }
 }
 protected override void UpdateProfileItem(ProfileTypeDefinitionModel profileItem, IDALContext dalContext)
 {
     if (_model.SuperType != null)
     {
         var superTypeProfile = _model.SuperType.ImportProfileItem(dalContext);
         profileItem.Parent = dalContext.MapToModelProfileSimple(superTypeProfile);
     }
     profileItem.IsAbstract = _model.IsAbstract;
     base.UpdateProfileItem(profileItem, dalContext);
 }
        private ProfileTypeDefinitionModel ExtendTypeDefinitionInternal(ProfileTypeDefinitionModel parent, int?profileId, bool isExtend, UserToken userToken)
        {
            //used to populate author info
            var user = _dalUser.GetById(userToken.UserId, userToken);

            //update the new profile to clean out and update some key parts of the item
            //make clean copy of parent and then remove some lingering parent data items
            var result = JsonConvert.DeserializeObject <ProfileTypeDefinitionModel>(JsonConvert.SerializeObject(parent));

            result.ID           = null;
            result.OpcNodeId    = null;
            result.BrowseName   = null;
            result.SymbolicName = null;
            result.DocumentUrl  = null;
            result.Name         = isExtend ? "[Extend]" : "[New]"; //name useful in ancestory tree. After that is built, we clear name.
            result.Parent       = _profileUtils.MapToModelProfileSimple(parent);
            result.AuthorId     = User.GetUserID();
            result.Author       = new UserSimpleModel()
            {
                ID           = user.ID,
                FirstName    = user.FirstName,
                LastName     = user.LastName,
                Organization = user.Organization
            };
            result.CreatedBy = result.Author;
            result.Created   = DateTime.UtcNow;
            result.UpdatedBy = result.Author;
            result.Updated   = DateTime.UtcNow;
            //return dependencies, ancestory for this profile as part of this response to reduce volume of calls for a profile.
            result.Dependencies              = new List <ProfileTypeDefinitionSimpleModel>();
            result.Ancestory                 = _profileUtils.GenerateAncestoryLineage(result, userToken);
            result.ProfileAttributes         = new List <ProfileAttributeModel>();
            result.Interfaces                = new List <ProfileTypeDefinitionModel>();
            result.Compositions              = new List <ProfileTypeDefinitionRelatedModel>();
            result.ExtendedProfileAttributes = _profileUtils.GetExtendedAttributes(result, userToken);

            //clear name, profile fk before returning...
            result.Name        = "";
            result.Description = "";
            result.IsFavorite  = false;

            //for normal extend, new, profileId is null. For wizard, profile Id will be selected by user in upstream step
            if (profileId.HasValue)
            {
                result.Profile   = _dalProfile.GetById(profileId.Value, userToken);
                result.ProfileId = profileId;
            }
            else
            {
                result.Profile   = null;
                result.ProfileId = 0;
            }

            return(result);
        }
        protected override void UpdateProfileItem(ProfileTypeDefinitionModel profileItem, IDALContext dalContext)
        {
            base.UpdateProfileItem(profileItem, dalContext);

            if (_model.TypeDefinition != null)
            {
                var objectType = _model.TypeDefinition?.ImportProfileItem(dalContext);
                if (objectType == null)
                {
                    throw new Exception($"Undefined object type {_model.TypeDefinition.DisplayName?.FirstOrDefault()?.Text} {_model.TypeDefinition.NodeId}");
                }
                profileItem.Parent = dalContext.MapToModelProfileSimple(objectType);
            }
        }
 public static void AddVariableToProfileModel(this VariableModel model, ProfileTypeDefinitionModel profileItem, IDALContext dalContext)
 {
     if (model is PropertyModel property)
     {
         property.AddVariableToProfileModel(profileItem, dalContext);
     }
     else if (model is DataVariableModel variable)
     {
         variable.AddVariableToProfileModel(profileItem, dalContext);
     }
     else
     {
         throw new Exception($"Unexpected variable type {model.GetType()}");
     }
 }
예제 #6
0
        /// <summary>
        ///
        /// </summary>
        /// <remarks>
        /// TBD - handle scenario where user implemented same interface in ancestor profile.
        /// Prevent this from happening by not allowing this as an interface selection.
        ///</remarks>
        /// <param name="profile"></param>
        /// <returns></returns>
        public List <ProfileTypeDefinitionModel> BuildInterfaceLookup(ProfileTypeDefinitionModel profile, UserToken userToken)
        {
            //remove items of a different type, remove self
            //remove interfaces already used by profile.
            //Note: interfaces also must only derive from BaseInterfaceType - by selecting only interface profile types, we satisfy this.
            var items = profile == null?
                        _dal.Where(p => p.ProfileType.Name.ToLower().Equals("interface"), userToken, null, null, false) :
                            _dal.Where(p => p.ProfileType.Name.ToLower().Equals("interface") &&
                                       !p.ID.Equals(profile.ID) &&
                                       !profile.Interfaces.Select(x => x.ID).ToList().Contains(p.ID), userToken, null, null, false);

            var result  = new List <ProfileTypeDefinitionModel>();
            int counter = 0;

            foreach (var p in items.Data)
            {
                //pull extended attributes from ancestory AND interface attributes
                p.ExtendedProfileAttributes = this.GetExtendedAttributes(p, userToken);
                //merge profile attributes, compositions, variable types
                p.ProfileAttributes = this.MergeProfileAttributes(p);

                //add some special indicators these attrs are interface attr
                foreach (var a in p.ProfileAttributes)
                {
                    a.Interface = new ProfileTypeDefinitionRelatedModel()
                    {
                        ID = p.ID, Name = p.Name, BrowseName = p.BrowseName, OpcNodeId = p.OpcNodeId
                    };;
                    a.InterfaceGroupId = counter;
                }

                //add some special indicators the ancestor attrs are interface attr associated with this interface
                foreach (var a in p.ExtendedProfileAttributes)
                {
                    a.Interface = new ProfileTypeDefinitionRelatedModel()
                    {
                        ID = p.ID, Name = p.Name, BrowseName = p.BrowseName, OpcNodeId = p.OpcNodeId
                    };;
                    a.InterfaceGroupId = counter;
                }

                result.Add(p);

                counter++;
            }

            return(result);
        }
예제 #7
0
        /// <summary>
        /// An ordered representation of the profile's lineage. This is a flat collection
        /// </summary>
        /// <param name="profile"></param>
        /// <returns></returns>
        public List <ProfileTypeDefinitionSimpleModel> GenerateAncestoryLineage(ProfileTypeDefinitionModel profile, UserToken userToken)
        {
            //navigate up the inheritance tree until the root.
            List <ProfileTypeDefinitionSimpleModel> result = new List <ProfileTypeDefinitionSimpleModel>();
            int counter  = 0;
            var ancestor = profile;

            while (ancestor != null)
            {
                result.Add(MapToModelProfileSimple(ancestor, counter));
                ancestor = ancestor.Parent?.ID == null ? null : _dal.GetById(ancestor.Parent.ID.Value, userToken);
                counter--;
            }
            //sort the result grandaprent / parent / profile
            return(result.OrderBy(p => p.Level).ThenBy(p => p.Name).ToList());
        }
예제 #8
0
        /// <summary>
        /// Get the list of profiles that depend on this profile
        /// </summary>
        /// <param name="profile"></param>
        /// <returns></returns>
        public List <ProfileTypeDefinitionSimpleModel> GenerateDependencies(ProfileTypeDefinitionModel profile, UserToken userToken)
        {
            //find all descendants that may be related...go n levels deep
            var result = new List <ProfileTypeDefinitionSimpleModel>();

            BuildDescendantsTree(ref result, profile.ID, 1, userToken);
            var count = result.Count();

            //find compositions, variable types which depend on this profile
            var dependencies = _dal.Where(p => !ProfileMapperUtil.ExcludedProfileTypes.Contains(p.ProfileTypeId) /*p.ProfileTypeId != (int)ProfileItemTypeEnum.Object*/ &&
                                          (p.ParentId.Equals(profile.ID) ||
                                           p.Compositions.Any(p => p.CompositionId.Equals(profile.ID)) ||
                                           p.Attributes.Any(a => a.DataType.CustomTypeId.HasValue &&
                                                            a.DataType.CustomTypeId.Equals(profile.ID)))
                                          , userToken, null, null).Data
                               .Select(s => MapToModelProfileAncestory(s, count + 1));

            return(result.Concat(dependencies).OrderBy(p => p.Level).ThenBy(p => p.Name).ToList());
        }
예제 #9
0
        /// <summary>
        /// A nested representation of the profile's place relative to its ancestors and siblings
        /// This is a recursive represenation for ancestors and siblings.
        /// </summary>
        /// <param name="profile"></param>
        /// <param name="includeSiblings"></param>
        /// <returns></returns>
        public List <ProfileTypeDefinitionAncestoryModel> GenerateAncestoryTree(ProfileTypeDefinitionModel profile, UserToken userToken, bool includeSiblings = false)
        {
            //navigate up the inheritance tree until the root. this is sorted properly. Should be at least one.
            var lineage = this.GenerateAncestoryLineage(profile, userToken);
            //build a nested loop from root to profile item
            ProfileTypeDefinitionAncestoryModel root        = null;
            ProfileTypeDefinitionAncestoryModel curItem     = null;
            ProfileTypeDefinitionAncestoryModel finalParent = null;

            foreach (var p in lineage)
            {
                var pConverted = new ProfileTypeDefinitionAncestoryModel()
                {
                    ID = p.ID, Author = p.Author, Description = p.Description, Level = p.Level, Name = p.Name, Type = p.Type
                    , /*Namespace = p.Namespace,*/ IsAbstract = p.IsAbstract, OpcNodeId = p.OpcNodeId
                    , Profile = new ProfileModel()
                    {
                        ID = p.Profile.ID, Namespace = p.Profile.Namespace, Version = p.Profile.Version
                    }
                };
                //1st iteration
                if (root == null)
                {
                    root          = pConverted;
                    root.Children = new List <ProfileTypeDefinitionAncestoryModel>();
                    finalParent   = root;
                }
                else //all other iterations
                {
                    curItem.Children.Add(pConverted);
                    finalParent = curItem;
                }
                curItem          = pConverted;
                curItem.Children = new List <ProfileTypeDefinitionAncestoryModel>();
            }

            var result = new List <ProfileTypeDefinitionAncestoryModel>();

            result.Add(root);

            //build out a list and siblings will go on same level as the profile

            //find siblings - profiles with same parent.
            //Append to cur item if there is a multi-gen scenario. append as sibling if profile is the root
            if (includeSiblings)
            {
                var siblings = _dal.Where(p => !ProfileMapperUtil.ExcludedProfileTypes.Contains(p.ProfileTypeId) /*p.ProfileTypeId != (int)ProfileItemTypeEnum.Object*/ && profile.Parent != null &&
                                          p.ParentId.Equals(profile.Parent.ID) &&
                                          p.ID != profile.ID, userToken, null, null, false).Data
                               .Select(s => MapToModelProfileAncestory(s, 1));

                if (lineage.Count == 1)
                {
                    result = result.Concat(siblings).ToList();
                }
                else
                {
                    //append siblings to final parent
                    finalParent.Children = finalParent.Children.Concat(siblings).ToList();
                }
            }
            return(result);
        }
 public static LookupDataTypeModel GetAttributeDataType(this BaseTypeModel model, ProfileTypeDefinitionModel profileItem, IDALContext dalContext)
 {
     if (model is ObjectTypeModel objectType)
     {
         return(new ObjectTypeModelImportProfile {
             _model = objectType
         }.GetAttributeDataType(profileItem, dalContext));
     }
     else if (model is VariableTypeModel variableType)
     {
         return(new VariableTypeModelImportProfile {
             _model = variableType
         }.GetAttributeDataType(profileItem, dalContext));
     }
     else if (model is DataTypeModel dataType)
     {
         return(new DataTypeModelImportProfile {
             _model = dataType
         }.GetAttributeDataType(profileItem, dalContext));
     }
     throw new Exception($"Unexpected variable type {model.GetType()}");
     //var nodeModelFactory = new BaseTypeModelImportProfile<BaseTypeModel> { _model = model };
     //return nodeModelFactory.GetAttributeDataType(profileItem, dalContext);
 }
        protected override void UpdateProfileItem(ProfileTypeDefinitionModel profileItem, IDALContext dalContext)
        {
            profileItem.TypeId = (int)ProfileItemTypeEnum.CustomDataType;
            base.UpdateProfileItem(profileItem, dalContext);
            if (profileItem.TypeId != (int)ProfileItemTypeEnum.CustomDataType)
            {
                throw new Exception();
            }
            var attributeNamespace = NodeModelUtils.GetNamespaceFromNodeId(_model.NodeId);

            if (_model.StructureFields?.Any() == true || _model.HasBaseType("nsu=http://opcfoundation.org/UA/;i=22"))
            {
                profileItem.TypeId = (int)ProfileItemTypeEnum.Structure;

                if (profileItem.Attributes == null)
                {
                    profileItem.Attributes = new List <ProfileAttributeModel>();
                }
                foreach (var field in _model.StructureFields ?? new List <DataTypeModel.StructureField>())
                {
                    var fieldDataType = field.DataType;
                    if (fieldDataType == null)
                    {
                        throw new Exception($"Unable to resolve data type {field.DataType?.DisplayName}");
                    }
                    var attributeDataType = fieldDataType.GetAttributeDataType(profileItem, dalContext);
                    if (attributeDataType == null)
                    {
                        throw new Exception($"{fieldDataType} not resolved");
                    }
                    var attribute = new ProfileAttributeModel
                    {
                        IsActive   = true,
                        Name       = field.Name,
                        BrowseName = $"{attributeNamespace};{field.Name}",
                        //No SymbolicName for structure fields
                        Namespace     = attributeNamespace,
                        IsRequired    = !field.IsOptional,
                        Description   = field.Description?.FirstOrDefault()?.Text,
                        AttributeType = new LookupItemModel {
                            ID = (int)AttributeTypeIdEnum.StructureField
                        },
                        DataType  = attributeDataType,
                        OpcNodeId = NodeModelUtils.GetNodeIdIdentifier(_model.NodeId),
                    };
                    profileItem.Attributes.Add(attribute);
                }
            }
            if (_model.EnumFields?.Any() == true)
            {
                profileItem.TypeId = (int)ProfileItemTypeEnum.Enumeration;
                if (profileItem.Attributes == null)
                {
                    profileItem.Attributes = new List <ProfileAttributeModel>();
                }
                foreach (var field in _model.EnumFields)
                {
                    var int64DataType = dalContext.GetDataType("Int64");
                    if (int64DataType == null /* || int64DataType.ID == 0*/)
                    {
                        throw new Exception($"Unable to resolve Int64 data type.");
                    }
                    var attribute = new ProfileAttributeModel
                    {
                        IsActive   = true,
                        Name       = field.Name,
                        BrowseName = $"{attributeNamespace};{field.Name}",
                        // No SymbolicName for enum fields
                        DisplayName   = field.DisplayName?.FirstOrDefault()?.Text,
                        Description   = field.Description?.FirstOrDefault()?.Text,
                        AttributeType = new LookupItemModel {
                            ID = (int)AttributeTypeIdEnum.EnumField
                        },
                        DataType  = int64DataType,
                        EnumValue = field.Value,
                        Namespace = attributeNamespace,
                    };
                    profileItem.Attributes.Add(attribute);
                }
            }
        }
        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.");
            }
        }
예제 #13
0
        public bool ExportInternal(CESMII.ProfileDesigner.DAL.Models.ProfileModel profileModel, ProfileTypeDefinitionModel profileItem, Stream xmlNodeSet, UserToken userToken, UserToken authorId)
        {
            if (profileItem?.ProfileId != null)
            {
                profileModel = _nsDal.GetById(profileItem.ProfileId.Value, userToken);
                //if (!(profileModel.AuthorId == null || profileModel.AuthorId == userId))
                //{
                //    throw new Exception($"User does not have access to profile on profileItem {profileItem}");
                //}
            }
            //var uriToExport = nodeSetModel?.Namespace ?? profileItem.Namespace;
            var dalContext = new DALContext(this, userToken, authorId, false);

            _lastDalContext = dalContext;
            if (!NodesetModels.ContainsKey(strOpcNamespaceUri))
            {
                try
                {
                    // TODO find the right OPC version references in the nodeSet?
                    var opcNodeSetModel = _nsDal.Where(ns => ns.Namespace == strOpcNamespaceUri /*&& (ns.AuthorId == null || ns.AuthorId == userId)*/, userToken, null, null, false, true).Data.OrderByDescending(m => m.PublishDate).FirstOrDefault();
                    // workaround for bug https://github.com/dotnet/runtime/issues/67622
                    var fileCachePatched = opcNodeSetModel.NodeSetFiles[0].FileCache.Replace("<Value/>", "<Value xsi:nil='true' />");
                    using (MemoryStream nodeSetStream = new MemoryStream(Encoding.UTF8.GetBytes(fileCachePatched)))
                    //var nodeSetFilePath = Path.Combine(Path.GetDirectoryName(this.GetType().Assembly.Location), "Nodesets", "Opc.Ua.NodeSet2.xml");
                    //using (Stream nodeSetStream = new FileStream(nodeSetFilePath, FileMode.Open))
                    {
                        UANodeSet nodeSet = UANodeSet.Read(nodeSetStream);
                        _importedNodesByNodeId = null;
                        // Get aliases from base UA model
                        // TODO remove unused aliases later
                        //foreach (var alias in nodeSet.Aliases)
                        //{
                        //    this.Aliases[alias.Value] = alias.Alias;
                        //}
                        // TODO find a more elegant way to load OPC base data types (needed by DataTypeModel.GetBuiltinDataType)
                        var opcModel   = nodeSet.Models[0];
                        var opcProfile = _nsDal.Where(ns => ns.Namespace == opcModel.ModelUri /*&& ns.PublicationDate == opcModel.PublicationDate*/ /*&& (ns.AuthorId == null || ns.AuthorId == userId)*/, userToken, null, null).Data?.FirstOrDefault();
                        //TBD - this next line is time consuming.
                        this.LoadNodeSetAsync(nodeSet, opcProfile
                                              //    new OPCUANodeSetHelpers.ModelNameAndVersion
                                              //{
                                              //    ModelUri = opcModel.ModelUri,
                                              //    ModelVersion = opcModel.Version,
                                              //    PublicationDate = opcModel.PublicationDate,
                                              //    CacheId = opcNodeSetModel.ID,
                                              //}
                                              , true).Wait();
                    }
                }
                catch { }
            }

            if (profileItem == null)
            {
                var profileItemsResult = _dal.Where(pi => pi.ProfileId == profileModel.ID /*&& (pi.AuthorId == null || pi.AuthorId == userId)*/, userToken, null, null, false, true);
                if (profileItemsResult.Data != null)
                {
                    foreach (var profile in profileItemsResult.Data)
                    {
                        var nodeModel = NodeModelFromProfileFactory.Create(profile, this, dalContext);
                    }
                }
            }
            else
            {
                var nodeModel = NodeModelFromProfileFactory.Create(profileItem, this, dalContext);
            }

            // Export the nodesets
            var exportedNodeSet = new UANodeSet();

            foreach (var model in this.NodesetModels.Values.Where(model =>
                                                                  ((ProfileModel)model.CustomState).Namespace == profileModel.Namespace &&
                                                                  ((ProfileModel)model.CustomState).PublishDate == profileModel.PublishDate))
            {
                model.UpdateIndices();

                ExportNodeSet(exportedNodeSet, model, this.NodesetModels, this.Aliases);
            }
            // .Net6 changed the default to no-identation: https://github.com/dotnet/runtime/issues/64885
            using (StreamWriter writer = new StreamWriter(xmlNodeSet, Encoding.UTF8))
            {
                try
                {
                    var xmlWriter = XmlWriter.Create(writer, new XmlWriterSettings {
                        Indent = true,
                    });
                    XmlSerializer serializer = new XmlSerializer(typeof(UANodeSet));
                    serializer.Serialize(xmlWriter, exportedNodeSet);
                }
                finally
                {
                    writer.Flush();
                }
            }
            //exportedNodeSet.Write(xmlNodeSet);
            return(true);
        }
 public async Task <IActionResult> Update([FromBody] ProfileTypeDefinitionModel model)
 {
     return(await UpdateInternal(model, false));
 }
예제 #15
0
        /// <summary>
        /// For a given profile, map the custom data type attributes to a unified model
        /// structure (ProfileAttributeModel) that can be used downstream when merging
        /// all sttributes into a single collection. This will add some data to distinguish
        /// these as custom data type attributes.
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        //[System.Obsolete("This is going away. TBD - Remove once we cut over custom data types.")]
        //protected List<ProfileAttributeModel> MapCustomDataTypesToProfileAttributeModels(ProfileItemModel item)
        //{
        //    var result = new List<ProfileAttributeModel>();
        //    if (item == null || item.CustomDataTypes == null) return result;

        //    //get lookup data type for custom data type
        //    var dataTypeCustom = _dalDataType.Where(x => x.Code.ToLower().Equals("customdatatype"), null, null).Data.FirstOrDefault();

        //    foreach (var cdt in item.CustomDataTypes)
        //    {
        //        result.Add(new ProfileAttributeModel
        //        {
        //            CustomDataType = cdt,
        //            CustomDataTypeId = cdt.RelatedId,
        //            ID = cdt.ID,
        //            Name = cdt.Name,
        //            Description = cdt.Description,
        //            ProfileId = item.ID,
        //            TypeId = dataTypeCustom.ID,
        //            DataType = dataTypeCustom
        //        });
        //    }
        //    return result;
        //}

        /// <summary>
        /// For each interface associated with the profile, append the interface attribute into the
        /// profile attributes list. These would be read only and show how the profile is virtually implementing
        /// the attributes for each interface.
        /// </summary>
        /// <remarks>
        /// TBD - need to get the ancestor attributes of each interface as well.
        /// </remarks>
        /// <param name="item"></param>
        /// <returns></returns>
        protected List <ProfileAttributeModel> MapInterfaceAttributesToProfileAttributeModels(ProfileTypeDefinitionModel item, UserToken userToken)
        {
            var result = new List <ProfileAttributeModel>();

            if (item == null || item.Interfaces == null)
            {
                return(result);
            }

            var counter = 0;

            foreach (var p in item.Interfaces)
            {
                var attrs = this.MergeProfileAttributes(p);

                //get the ancestor attribs which are also now a part of this interface implementation
                attrs = attrs.Concat(this.GetExtendedAttributes(p, userToken)).ToList();

                //add some special indicators these attrs are interface attr all associated with this interface
                //even acncestor attribs should be associated with this interface.
                foreach (var a in attrs)
                {
                    a.Interface = new ProfileTypeDefinitionRelatedModel()
                    {
                        ID = p.ID, Name = p.Name, BrowseName = p.BrowseName, OpcNodeId = p.OpcNodeId
                    };;
                    a.InterfaceGroupId = counter;
                }

                result = result.Concat(attrs).ToList();
                counter++;
            }
            return(result);
        }
예제 #16
0
        /// <summary>
        /// For a given profile, map the composition attributes to a unified model
        /// structure (ProfileAttributeModel) that can be used downstream when merging
        /// all sttributes into a single collection. This will add some data to distinguish
        /// these as composition type attributes.
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        protected List <ProfileAttributeModel> MapCompositionsToProfileAttributeModels(ProfileTypeDefinitionModel item)
        {
            var result = new List <ProfileAttributeModel>();

            if (item == null || item.Compositions == null)
            {
                return(result);
            }

            //get lookup data type for composition
            var dataTypeComp = _dalDataType.Where(x => x.Code.ToLower().Equals("composition"), new UserToken(), null, null).Data.FirstOrDefault();
            //get lookup data type for attr type composition
            var attrTypeComp = _dalLookup.Where(x => x.Code.ToLower().Equals("composition"), new UserToken(), null, null).Data.FirstOrDefault();

            foreach (var comp in item.Compositions)
            {
                result.Add(new ProfileAttributeModel
                {
                    Composition      = comp,
                    CompositionId    = comp.RelatedProfileTypeDefinitionId,
                    ID               = comp.ID,
                    Name             = comp.Name,
                    BrowseName       = comp.BrowseName,
                    SymbolicName     = comp.SymbolicName,
                    Description      = comp.Description,
                    TypeDefinitionId = item.ID,
                    //TypeDefinition = item, // Results in cycle during serialization
                    // No VariableTypeDefinition for compositions
                    DataTypeId    = dataTypeComp.ID,
                    DataType      = dataTypeComp,
                    AttributeType = attrTypeComp
                });
            }
            return(result);
        }
예제 #17
0
 public ProfileTypeDefinitionSimpleWithAttrsModel MapToModelProfileSimpleWithAttrs(ProfileTypeDefinitionModel item, int level = 0)
 {
     if (item != null)
     {
         return(new ProfileTypeDefinitionSimpleWithAttrsModel
         {
             ID = item.ID,
             Name = item.Name,
             BrowseName = item.BrowseName,
             /*Namespace = item.Profile.Namespace,*/
             Profile = new ProfileModel()
             {
                 ID = item.Profile.ID, Namespace = item.Profile.Namespace, Version = item.Profile.Version
             },
             Description = item.Description,
             Type = item.Type,
             Author = item.Author,
             OpcNodeId = item.OpcNodeId,
             IsAbstract = item.IsAbstract,
             Level = level,
             ProfileAttributes = item.Attributes
         });
     }
     else
     {
         return(null);
     }
 }
        /// <summary>
        /// Add or update a profile type def from the front end. This is different than importing a nodeset XML file.
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        private async Task <IActionResult> UpdateInternal(ProfileTypeDefinitionModel model, bool isAdd)
        {
            var userToken = UserExtension.DalUserToken(User);

            //For front end, set Profile to null to ensure that the DAL does not see this as a changed object that must be updated.
            //Setting ProfileId will suffice.
            if (model.ProfileId.HasValue && model.ProfileId.Value > 0)
            {
                model.Profile = null;
            }
            if (isAdd)
            {
                model.ID = 0; //satisfy required field and set to 0 will indicate new item
            }
            //clean up stuff - set new ids to 0 rather than -1 for server side handling
            if (model.ProfileAttributes != null)
            {
                foreach (var attrib in model.ProfileAttributes)
                {
                    if (attrib.TypeDefinitionId <= 0)
                    {
                        attrib.TypeDefinitionId = model.ID;
                    }
                    if (attrib.ID < 0)
                    {
                        attrib.ID = null;
                    }
                    if (attrib.CompositionId < 0)
                    {
                        attrib.CompositionId = null;
                    }
                    //if (attrib.CustomDataTypeId < 0) attrib.CustomDataTypeId = null;
                }
                //on front end, all attributes stored in single collection.
                // split out compositions, primitive attributes
                // into individual lists for DAL, DB.
                model.Attributes = model.ProfileAttributes.Where(a => (!a.CompositionId.HasValue || a.CompositionId < 0)).ToList();
                //    (!a.CustomDataTypeId.HasValue || a.CustomDataTypeId < 0)).ToList();
                var comps = model.ProfileAttributes.Where(a => a.CompositionId.HasValue && a.CompositionId >= 0).ToList();
                model.Compositions = _profileUtils.MapProfileAttributeToCompositionModels(comps);
                //var varTypes = model.ProfileAttributes.Where(a => a.CustomDataTypeId.HasValue && a.CustomDataTypeId >= 0).ToList();
                //model.CustomDataTypes = _profileUtils.MapProfileAttributeToCustomDataTypeModels(varTypes);
            }

            //clear out stuff unrelated to the save of the item. There is lots of related stuff that we use in the display
            //that will trip up validation but is not central to the profile save operation.
            model.Ancestory = null;
            model.TypeId    = model.Type.ID;
            //moved to DAL...set this to null to ensure that the DAL does not see this as a changed object that must be updated. Setting ProfileId will suffice.
            //model.Profile = null;

            //re-validate
            ModelState.Clear();
            TryValidateModel(model);

            //required
            if (!model.ProfileId.HasValue)
            {
                ModelState.AddModelError("Profile", "Profile type definition must be assigned to a profile");
            }

            if (!ModelState.IsValid)
            {
                var errors = ExtractModelStateErrors();
                return(BadRequest("The item is invalid. Please correct the following: " + errors.ToString()));
            }

            int?id = 0;

            if (isAdd)
            {
                id = await _dal.Add(model, userToken);

                //increment extend count for this item's parent
                var analytic = _dalAnalytics.Where(x => x.ProfileTypeDefinitionId == model.Parent.ID, userToken, null, null, false).Data.FirstOrDefault();
                if (analytic == null)
                {
                    await _dalAnalytics.Add(new ProfileTypeDefinitionAnalyticModel()
                    {
                        ProfileTypeDefinitionId = model.Parent.ID.Value, ExtendCount = 1
                    }, userToken);
                }
                else
                {
                    analytic.ExtendCount += 1;
                    await _dalAnalytics.Update(analytic, null);
                }
            }
            else
            {
                id = await _dal.Update(model, userToken);
            }

            if (id < 0)
            {
                _logger.LogWarning($"ProfileTypeDefinitionController|UpdateInternal|Could not {(isAdd ? "add" : "update")} profile type definition.");
                return(BadRequest($"Could not {(isAdd ? "add" : "update")} profile type definition."));
            }
            _logger.LogInformation($"ProfileTypeDefinitionController|UpdateInternal|{(isAdd ? "Added" : "Updated")} profile type definition. Id:{id}.");

            //return result object plus id.
            return(Ok(new ResultMessageWithDataModel()
            {
                IsSuccess = true,
                Message = $"Item was {(isAdd ? "added" : "updated")}.",
                //Data = new JRaw(JsonConvert.SerializeObject(this.GetItem(model.ID))
                //Data = new JRaw(JsonConvert.SerializeObject(new IdIntModel() { ID = id }))
                Data = id
            }));
        }
예제 #19
0
 public bool ExportProfileItem(ProfileTypeDefinitionModel profileItem, Stream xmlNodeSet, UserToken userToken, UserToken authorId)
 {
     return(ExportInternal(null, profileItem, xmlNodeSet, userToken, authorId));
 }