List <FieldDefinition> MessageFields(Fix.Repository.Version version, Fix.Repository.Message message)
        {
            var definitions = new List <FieldDefinition>();

            PopulateFieldDefinitions(message.ComponentID, version, definitions, 0);
            return(definitions);
        }
        static CodeTypeDeclaration GenerateDataTypes(Fix.Repository.Version version)
        {
            var dictionaryType = new CodeTypeDeclaration("Dictionary")
            {
                Attributes = MemberAttributes.Public,
                IsPartial  = true
            };

            var versionType = new CodeTypeDeclaration(version.BeginString.Replace(".", "_"))
            {
                Attributes = MemberAttributes.Public,
                IsPartial  = true
            };

            var dataTypeCollectionMember = new CodeMemberField(versionType.Name + "DataTypeCollection", "_dataTypeCollection")
            {
                Attributes     = MemberAttributes.Private | MemberAttributes.Static,
                InitExpression = new CodeObjectCreateExpression(versionType.Name + "DataTypeCollection")
            };

            versionType.Members.Add(dataTypeCollectionMember);

            var dataTypesProperty = new CodeMemberProperty
            {
                Attributes =
                    MemberAttributes.Public | MemberAttributes.Static,
                Name          = "DataTypes",
                Type          = new CodeTypeReference(versionType.Name + "DataTypeCollection"),
                GetStatements =
                {
                    new CodeMethodReturnStatement
                    {
                        Expression =
                            new CodeVariableReferenceExpression(
                                "_dataTypeCollection")
                    }
                }
            };

            versionType.Members.Add(dataTypesProperty);

            var dataTypesType = new CodeTypeDeclaration(versionType.Name + "DataTypeCollection")
            {
                Attributes = MemberAttributes.Public,
                IsPartial  = false
            };

            dataTypesType.BaseTypes.Add(new CodeTypeReference("DataTypeCollection"));

            foreach (string dataType in version.DataTypes)
            {
                string typeName = dataType[0].ToString().ToUpper() + dataType[1..];
Ejemplo n.º 3
0
        public void Run()
        {
            GenerateFile(string.Empty, new[] { GenerateVersions() });

            foreach (Fix.Repository.Version version in Repository.Versions)
            {
                GenerateFile(version.BeginString + "_Messages", new[] { GenerateMessages(version) });

                foreach (Fix.Repository.Message message in version.Messages)
                {
                    string name = message.Name;

                    if (name == "SecurityStatus")
                    {
                        name += "Message";
                    }

                    GenerateFile(version.BeginString + "_Messages_" + name, new[] { GenerateMessage(version, message) });
                }
            }

            foreach (Fix.Repository.Version version in Repository.Versions)
            {
                GenerateFile(version.BeginString + "_Fields", new[] { GenerateFields(version) });
            }

            Fix.Repository.Version last = null;
            foreach (Fix.Repository.Version version in Repository.Versions)
            {
                GenerateFile(version.BeginString + "_Enums", GenerateEnums(version));
                if (last == null || !version.BeginString.StartsWith("FIXT"))
                {
                    last = version;
                }
            }

            if (last != null)
            {
                GenerateFile("Enums", GenerateEnums(last, false));
            }

            foreach (Fix.Repository.Version version in Repository.Versions)
            {
                GenerateFile(version.BeginString + "_DataTypes", new[] { GenerateDataTypes(version) });
            }
        }
        void PopulateFieldDefinitions(string componentId, Fix.Repository.Version version, List <FieldDefinition> definitions, int parentIndent)
        {
            if (!version.MsgContents.TryGetValue(componentId, out List <Fix.Repository.MsgContent> msgContents))
            {
                // TODO
                return;
            }

            foreach (Fix.Repository.MsgContent content in msgContents)
            {
                int indent = Convert.ToInt32(content.Indent);

                if (int.TryParse(content.TagText, out int tag))
                {
                    if (!version.Fields.TryGetValue(tag, out Fix.Repository.Field field))
                    {
                        // TODO - better tell someone.
                        continue;
                    }

                    definitions.Add(new FieldDefinition
                    {
                        Field    = field,
                        Required = Convert.ToInt32(content.Reqd) != 0,
                        Indent   = parentIndent + indent,
                        Added    = content.Added
                    });
                }
                else
                {
                    if (!version.Components.TryGetValue(content.TagText, out Fix.Repository.Component component))
                    {
                        // TODO - better tell someone
                        continue;
                    }

                    PopulateFieldDefinitions(component.ComponentID, version, definitions, indent);
                }
            }
        }
        static IEnumerable <CodeTypeDeclaration> GenerateEnums(Fix.Repository.Version version, bool includeNamespace = true)
        {
            var declarations = new List <CodeTypeDeclaration>();
            CodeTypeDeclaration versionType = null;

            if (includeNamespace)
            {
                var dictionaryType = new CodeTypeDeclaration("Dictionary")
                {
                    Attributes = MemberAttributes.Public,
                    IsPartial  = true
                };

                versionType = new CodeTypeDeclaration(version.BeginString.Replace(".", "_"))
                {
                    Attributes = MemberAttributes.Public,
                    IsPartial  = true
                };

                dictionaryType.Members.Add(versionType);
                declarations.Add(dictionaryType);
            }

            foreach (int tag in version.Enums.Keys)
            {
                if (!version.Fields.TryGetValue(tag, out Fix.Repository.Field field))
                {
                    continue;
                }

                var type = new CodeTypeDeclaration(field.Name)
                {
                    IsEnum = true
                };

                List <Fix.Repository.Enum> values = version.Enums[tag];

                if (field.Name == "SessionStatus")
                {
                    foreach (Fix.Repository.Enum value in values)
                    {
                        string symbolicName = value.SymbolicName;

                        var f = new CodeMemberField(field.Name, symbolicName)
                        {
                            CustomAttributes =
                            {
                                new CodeAttributeDeclaration("Description",
                                                             new CodeAttributeArgument(
                                                                 new CodePrimitiveExpression(
                                                                     value.Description)))
                            },
                            InitExpression = new CodeSnippetExpression(string.Format("{0}", value.Value))
                        };
                        type.Members.Add(f);
                    }
                    // These are HKEX Orion custom values
                    var passwordChangeRequired = new CodeMemberField(field.Name, "PasswordChangeIsRequired")
                    {
                        CustomAttributes =
                        {
                            new CodeAttributeDeclaration("Description",
                                                         new CodeAttributeArgument(
                                                             new CodePrimitiveExpression(
                                                                 "Password change is required")))
                        },
                        InitExpression = new CodeSnippetExpression("100")
                    };
                    type.Members.Add(passwordChangeRequired);

                    var other = new CodeMemberField(field.Name, "Other")
                    {
                        CustomAttributes =
                        {
                            new CodeAttributeDeclaration("Description",
                                                         new CodeAttributeArgument(
                                                             new CodePrimitiveExpression(
                                                                 "Other")))
                        },
                        InitExpression = new CodeSnippetExpression("101")
                    };
                    type.Members.Add(other);
                }
                else if (field.Name == "TrdType")
                {
                    foreach (Fix.Repository.Enum value in values)
                    {
                        string symbolicName = value.SymbolicName;

                        var f = new CodeMemberField(field.Name, symbolicName)
                        {
                            CustomAttributes =
                            {
                                new CodeAttributeDeclaration("Description",
                                                             new CodeAttributeArgument(
                                                                 new CodePrimitiveExpression(
                                                                     value.Description)))
                            },
                            InitExpression = new CodeSnippetExpression(string.Format("{0}", value.Value))
                        };
                        type.Members.Add(f);
                    }
                    // These are HKEX Orion custom values
                    var oddLotTrade = new CodeMemberField(field.Name, "OddLotTrade")
                    {
                        CustomAttributes =
                        {
                            new CodeAttributeDeclaration("Description",
                                                         new CodeAttributeArgument(
                                                             new CodePrimitiveExpression(
                                                                 "Odd Lot Trade")))
                        },
                        InitExpression = new CodeSnippetExpression("102")
                    };
                    type.Members.Add(oddLotTrade);

                    var overseasTrade = new CodeMemberField(field.Name, "OverseasTrade")
                    {
                        CustomAttributes =
                        {
                            new CodeAttributeDeclaration("Description",
                                                         new CodeAttributeArgument(
                                                             new CodePrimitiveExpression(
                                                                 "Overseas Trade")))
                        },
                        InitExpression = new CodeSnippetExpression("104")
                    };
                    type.Members.Add(overseasTrade);
                }
                else
                {
                    //
                    // TODO -   just avoid multi character values for now as we would need to encode
                    //          them to fit into an int for an enum value
                    //
                    var singleCharacterValues = from e in values where e.Value.Length == 1 select e;

                    foreach (Fix.Repository.Enum value in singleCharacterValues)
                    {
                        string symbolicName = value.SymbolicName;

                        if (version.BeginString == "FIX.5.0SP2")
                        {
                            if (field.Name == "ApplReqType" && value.Value == "5")
                            {
                                symbolicName = "CancelRetransmission"; // FIX.5.0SP2 name clash with value 0
                            }
                            else if (field.Name == "MassCancelRequestType" && value.Value == "B")
                            {
                                symbolicName = "CancelForSecurityIssuer"; // FIX.5.0SP2 name clash with value 1
                            }
                            else if (field.Name == "UnderlyingPriceDeterminationMethod" && value.Value == "4")
                            {
                                symbolicName = "AverageValue";
                            }
                        }

                        var f = new CodeMemberField(field.Name, symbolicName)
                        {
                            CustomAttributes =
                            {
                                new CodeAttributeDeclaration("Description",
                                                             new CodeAttributeArgument(
                                                                 new CodePrimitiveExpression(
                                                                     value.Description)))
                            },
                            InitExpression = new CodeSnippetExpression(string.Format("'{0}'", value.Value))
                        };

                        if (!string.IsNullOrEmpty(value.Added))
                        {
                            f.CustomAttributes.Add(
                                new CodeAttributeDeclaration("Added",
                                                             new CodeAttributeArgument(
                                                                 new CodePrimitiveExpression(value.Added))));
                        }

                        type.Members.Add(f);
                    }
                }

                if (includeNamespace)
                {
                    versionType.Members.Add(type);
                }
                else
                {
                    declarations.Add(type);
                }
            }

            return(declarations);
        }
        static CodeTypeDeclaration GenerateFields(Fix.Repository.Version version)
        {
            var dictionaryType = new CodeTypeDeclaration("Dictionary")
            {
                Attributes = MemberAttributes.Public,
                IsPartial  = true
            };

            var versionType = new CodeTypeDeclaration(version.BeginString.Replace(".", "_"))
            {
                Attributes = MemberAttributes.Public,
                IsPartial  = true
            };

            var fieldsProperty = new CodeMemberProperty
            {
                Attributes =
                    MemberAttributes.Public | MemberAttributes.Static,
                Name          = "Fields",
                Type          = new CodeTypeReference(versionType.Name + "FieldCollection"),
                GetStatements =
                {
                    new CodeMethodReturnStatement
                    {
                        Expression =
                            new CodeVariableReferenceExpression(
                                "_fieldCollection")
                    }
                }
            };

            versionType.Members.Add(fieldsProperty);

            var fieldsType = new CodeTypeDeclaration(versionType.Name + "FieldCollection")
            {
                Attributes = MemberAttributes.Public,
                IsPartial  = false
            };

            fieldsType.BaseTypes.Add(new CodeTypeReference("VersionFieldCollection"));

            var fieldCollectionConstructor = new CodeConstructor
            {
                Attributes = MemberAttributes.Public
            };

            var itemsCreate = new CodeArrayCreateExpression("Field");
            //
            // We want to be able to index fields directly in the array using the numeric value of their tag, there are
            // however some missing tags ie. 101, so we need to generate a null in it's place.
            //
            int expectedTag = 1;

            foreach (Fix.Repository.Field field in version.Fields.Values)
            {
                int actualTag = Convert.ToInt32(field.Tag);

                while (actualTag > expectedTag)
                {
                    itemsCreate.Initializers.Add(new CodePrimitiveExpression(null));
                    expectedTag++;
                }

                itemsCreate.Initializers.Add(new CodeTypeReferenceExpression(field.Name));
                expectedTag++;
            }

            var assign = new CodeAssignStatement(new CodeVariableReferenceExpression("_fields"), itemsCreate);

            fieldCollectionConstructor.Statements.Add(assign);

            fieldsType.Members.Add(fieldCollectionConstructor);
            //
            // private FieldDefinition Account = new FieldDefinition(1, "Account", "Account mnemonic as agreed between broker and institution.", 0);
            //
            foreach (Fix.Repository.Field field in version.Fields.Values)
            {
                string enumType = null;

                if (version.Enums.TryGetValue(field.Tag, out List <Fix.Repository.Enum> _))
                {
                    //
                    // TODO -   just avoid multi character values for now as we would need to encode
                    //          them to fit into an int for an enum value
                    //

                    /*
                     * int longValues = (from e in enumeratedValues
                     *                where e.Value.Length > 1
                     *                select e).Count();
                     *
                     * if (longValues == 0)
                     * {
                     *  enumType = dictionaryType.Name + "." + versionType.Name + "." + field.Name;
                     * }
                     */
                    enumType = dictionaryType.Name + "." + versionType.Name + "." + field.Name;
                }

                CodeExpression enumExpression = enumType == null
                                                    ? (CodeExpression) new CodePrimitiveExpression(null)
                                                    : new CodeTypeOfExpression(enumType);

                string typeName = field.Type[0].ToString().ToUpper() + field.Type[1..];
        int GenerateMessageFields(Fix.Repository.Version version,
                                  Fix.Repository.Message message,
                                  CodeTypeDeclaration messageType)
        {
            var fieldCollectionMember = new CodeMemberField(message.Name + "FieldCollection", "_fieldCollection")
            {
                Attributes = MemberAttributes.Private
            };

            messageType.Members.Add(fieldCollectionMember);

            var fieldsProperty = new CodeMemberProperty
            {
                Attributes    = MemberAttributes.Public | MemberAttributes.New,
                Name          = "Fields",
                Type          = new CodeTypeReference(message.Name + "FieldCollection"),
                GetStatements =
                {
                    new CodeMethodReturnStatement(new CodeCastExpression(new CodeTypeReference(message.Name + "FieldCollection"), new CodeMethodInvokeExpression(new CodeMethodReferenceExpression(null, "GetFields"))))
                }
            };

            messageType.Members.Add(fieldsProperty);

            /*
             *  public class HeartbeatFieldCollection : MessageFieldCollection {
             *      public HeartbeatFieldCollection()
             *      :   base(new Field[] {
             *                  new Field(FIX_4_0.BeginStringDefinition, true, 0, "FIX.2.7"),
             *                  new Field(FIX_4_0.BodyLengthDefinition, true, 0, "FIX.2.7")
             *               })
             *      {
             *      }
             *  }
             */
            var fieldsType = new CodeTypeDeclaration(message.Name + "FieldCollection")
            {
                Attributes = MemberAttributes.Public,
                IsPartial  = false
            };

            fieldsType.BaseTypes.Add(new CodeTypeReference("MessageFieldCollection"));

            var itemsCreate = new CodeArrayCreateExpression("Field");

            List <FieldDefinition> fieldDefinitions = MessageFields(version, message);

            string versionName = version.BeginString.Replace(".", "_");

            foreach (FieldDefinition definition in fieldDefinitions)
            {
                // ITG customisation
                if (message.MsgType == "UWO" && definition.Field.Tag == 67)
                {
                    continue;
                }

                itemsCreate.Initializers.Add(new CodeObjectCreateExpression("Field",
                                                                            new CodeVariableReferenceExpression(versionName + "." + definition.Field.Name + "Definition"),
                                                                            new CodePrimitiveExpression(definition.Required),
                                                                            new CodePrimitiveExpression(definition.Indent),
                                                                            new CodePrimitiveExpression(definition.Added)));
            }

            var fieldCollectionConstructor = new CodeConstructor
            {
                Attributes          = MemberAttributes.Public,
                BaseConstructorArgs = { itemsCreate }
            };

            fieldsType.Members.Add(fieldCollectionConstructor);

            messageType.Members.Add(fieldsType);

            return(itemsCreate.Initializers.Count);
        }
        public static CodeTypeDeclaration GenerateMessages(Fix.Repository.Version version)
        {
            var dictionaryType = new CodeTypeDeclaration("Dictionary")
            {
                Attributes = MemberAttributes.Public,
                IsPartial  = true
            };

            var versionType = new CodeTypeDeclaration(version.BeginString.Replace(".", "_"))
            {
                Attributes = MemberAttributes.Public,
                IsPartial  = true
            };

            var messageCollectionMember = new CodeMemberField(versionType.Name + "MessageCollection", "_messageCollection")
            {
                Attributes     = MemberAttributes.Private | MemberAttributes.Static,
                InitExpression = new CodeObjectCreateExpression(versionType.Name + "MessageCollection")
            };

            versionType.Members.Add(messageCollectionMember);

            var messagesProperty = new CodeMemberProperty
            {
                Attributes =
                    MemberAttributes.Public | MemberAttributes.Static,
                Name          = "Messages",
                Type          = new CodeTypeReference(versionType.Name + "MessageCollection"),
                GetStatements =
                {
                    new CodeMethodReturnStatement
                    {
                        Expression =
                            new CodeVariableReferenceExpression(
                                "_messageCollection")
                    }
                }
            };

            versionType.Members.Add(messagesProperty);

            //
            // public static class Messages : IEnumerable<Message>
            //    {
            //
            var messagesType = new CodeTypeDeclaration(versionType.Name + "MessageCollection")
            {
                Attributes = MemberAttributes.Public,
                IsPartial  = false
            };

            messagesType.BaseTypes.Add(new CodeTypeReference("MessageCollection"));

            var messageCollectionConstructor = new CodeConstructor
            {
                Attributes = MemberAttributes.Public
            };

            var itemsCreate = new CodeArrayCreateExpression("Message");

            foreach (Fix.Repository.Message message in version.Messages)
            {
                string name = message.Name;

                if (name == "SecurityStatus")
                {
                    name += "Message";
                }

                itemsCreate.Initializers.Add(new CodeTypeReferenceExpression(name));
            }

            var assign = new CodeAssignStatement(new CodeVariableReferenceExpression("_messages"), itemsCreate);

            messageCollectionConstructor.Statements.Add(assign);

            messagesType.Members.Add(messageCollectionConstructor);

            //
            // public static HeartbeatMessage Heartbeat = new HeartbeatMessage();
            //
            foreach (Fix.Repository.Message message in version.Messages)
            {
                //
                // readonly is C# specific so not supported by CodeDom.
                //
                string name = message.Name;

                if (name == "SecurityStatus")
                {
                    name += "Message";
                }

                var messageField = new CodeMemberField("readonly " + name, name)
                {
                    Attributes     = MemberAttributes.Public,
                    InitExpression = new CodeObjectCreateExpression(name)
                };

                messagesType.Members.Add(messageField);
            }

            versionType.Members.Add(messagesType);
            dictionaryType.Members.Add(versionType);

            return(dictionaryType);
        }
        public CodeTypeDeclaration GenerateMessage(Fix.Repository.Version version, Fix.Repository.Message message)
        {
            var dictionaryType = new CodeTypeDeclaration("Dictionary")
            {
                Attributes = MemberAttributes.Public,
                IsPartial  = true
            };

            var versionType = new CodeTypeDeclaration(version.BeginString.Replace(".", "_"))
            {
                Attributes = MemberAttributes.Public,
                IsPartial  = true
            };

            dictionaryType.Members.Add(versionType);
            //
            //  private class Hearbeat : Message
            //  {
            //      HearbeatMessage()
            //      :   Message("0", "Heartbeat", "The Heartbeat monitors the status of the communication link and identifies when t" +
            //                       "he last of a string of messages was not received.", "FIX.2.7")
            //      {
            //      }
            //  }
            //
            string name = message.Name;

            if (name == "SecurityStatus")
            {
                name += "Message";
            }

            var messageType = new CodeTypeDeclaration(name)
            {
                BaseTypes = { new CodeTypeReference("Message") }
            };

            int fieldCount = GenerateMessageFields(version, message, messageType);

            var messageConstructor = new CodeConstructor
            {
                Attributes          = MemberAttributes.Assembly,
                BaseConstructorArgs = { new CodePrimitiveExpression(message.MsgType),
                                        new CodePrimitiveExpression(name),
                                        new CodePrimitiveExpression(message.Description),
                                        new CodePrimitiveExpression(message.Added) }
            };

            messageType.Members.Add(messageConstructor);

            // protected abstract FieldCollection GetFields();
            var fieldsMember = new CodeMemberMethod
            {
                Name       = "GetFields",
                Attributes = MemberAttributes.Override | MemberAttributes.Family,
                ReturnType = new CodeTypeReference("MessageFieldCollection")
            };

            fieldsMember.Statements.Add(
                new CodeConditionStatement(new CodeSnippetExpression("_fieldCollection == null"),
                                           new CodeStatement[]
            {
                new CodeAssignStatement(
                    new CodeVariableReferenceExpression("_fieldCollection"),
                    new CodeObjectCreateExpression(message.Name + "FieldCollection"))
            }));
            fieldsMember.Statements.Add(
                new CodeMethodReturnStatement
            {
                Expression = new CodeVariableReferenceExpression("_fieldCollection")
            }
                );
            messageType.Members.Add(fieldsMember);

            // public int FieldCount { get { return 55; } }
            var fieldCountProperty = new CodeMemberProperty
            {
                Attributes    = MemberAttributes.Public | MemberAttributes.Override,
                Name          = "FieldCount",
                Type          = new CodeTypeReference(typeof(int)),
                GetStatements =
                {
                    new CodeMethodReturnStatement(new CodePrimitiveExpression(fieldCount))
                }
            };

            messageType.Members.Add(fieldCountProperty);

            versionType.Members.Add(messageType);

            return(dictionaryType);
        }