protected virtual void SanitizeMessageTemplateData(MessageTemplateData data)
        {
            // Sanitize possible identifier duplicates resulting from name identifier mapping
            // Fall back to ROS identifier name in this case.
            var duplicateIdentifiers = data.Fields.Select(f => f.Identifier)
                                       .Union(data.Constants.Select(c => c.Identifier))
                                       .GroupBy(identifier => identifier)
                                       .Select(x => new { x.Key, Count = x.Count() })
                                       .Where(x => x.Count > 1)
                                       .Select(x => x.Key)
                                       .ToList();

            foreach (var field in data.Fields.Where(x => duplicateIdentifiers.Contains(x.Identifier)))
            {
                field.Identifier = field.RosIdentifier;
            }

            foreach (var constant in data.Constants.Where(x => duplicateIdentifiers.Contains(x.Identifier)))
            {
                constant.Identifier = constant.RosIdentifier;
            }


            // Sanitize possible CS0542: Members cannot be the same as their enclosing type.
            // Rename those field to PreferredIdentifierIfEqualsTypeName. If the name is already used fall back to
            // the original ROS identifier.
            var cs0542Field = data.Fields
                              .FirstOrDefault(x => x.Identifier == data.TypeName);

            if (cs0542Field != null)
            {
                var alternativeIdentifier = PreferredIdentifierIfEqualsTypeName;
                alternativeIdentifier = NameMapper.GetFieldName(alternativeIdentifier);

                if (data.Fields.Any(x => x.Identifier == alternativeIdentifier))
                {
                    alternativeIdentifier = cs0542Field.RosIdentifier;
                }

                cs0542Field.Identifier = alternativeIdentifier;
            }

            var cs0542Const = data.Constants
                              .FirstOrDefault(x => x.Identifier == data.TypeName);

            if (cs0542Const != null)
            {
                var alternativeIdentifier = PreferredIdentifierIfEqualsTypeName;
                alternativeIdentifier = NameMapper.GetConstantName(alternativeIdentifier);

                if (data.Constants.Any(x => x.Identifier == alternativeIdentifier))
                {
                    alternativeIdentifier = cs0542Const.RosIdentifier;
                }

                cs0542Const.Identifier = alternativeIdentifier;
            }
        }
        protected virtual MessageTemplateData GetMessageTemplateData(RosTypeInfo rosType, DetailedRosMessageType messageType,
                                                                     MessageDescriptor message)
        {
            var fields = message.Fields
                         .Select(x => new FieldTemplateData
            {
                Index = message.Items
                        .Select((item, index) => new { Item = item, Index = index })
                        .First(f => f.Item == x)
                        .Index + 1, // Index of this field in serialized message (starting at 1)
                RosType       = x.TypeInfo,
                RosIdentifier = x.Identifier,
                Type          = new FieldTypeTemplateData(NameMapper.ResolveFullQualifiedInterfaceName(x.TypeInfo),
                                                          NameMapper.ResolveFullQualifiedTypeName(x.TypeInfo),
                                                          x.TypeInfo)
                ,
                Identifier = NameMapper.GetFieldName(x.Identifier)
            })
                         .ToList();

            var constants = message.Constants
                            .Select(c => new ConstantTemplateData
            {
                Index = message.Items
                        .Select((item, index) => new { item, index })
                        .First(x => x.item == c)
                        .index + 1,
                RosType       = c.TypeInfo,
                RosIdentifier = c.Identifier,
                TypeName      = NameMapper.ResolveFullQualifiedTypeName(c.TypeInfo),
                Identifier    = NameMapper.GetConstantName(c.Identifier),
                Value         = c.Value
            })
                            .ToList();

            var data = new MessageTemplateData
            {
                Package             = PackageTemplateData,
                RosTypeName         = NameMapper.GetRosTypeName(rosType.TypeName, messageType),
                RosAbstractTypeName = rosType.TypeName,
                TypeName            = NameMapper.GetTypeName(rosType.TypeName, messageType),
                AbstractTypeName    = NameMapper.GetTypeName(rosType.TypeName, DetailedRosMessageType.None),
                Fields      = fields,
                Constants   = constants,
                MessageType = new MessageTypeTemplateData(messageType)
            };

            return(data);
        }