Exemple #1
0
        private static string XDataConstructorFromCode(int code)
        {
            var expectedType = DxfCodePair.ExpectedType(code);

            if (expectedType == typeof(string))
            {
                return("DxfXDataString");
            }

            if (expectedType == typeof(double))
            {
                return("DxfXDataReal");
            }

            if (expectedType == typeof(short))
            {
                return("DxfXDataInteger");
            }

            if (expectedType == typeof(int) ||
                expectedType == typeof(long))
            {
                return("DxfXDataLong");
            }

            if (expectedType == typeof(bool))
            {
                return("DxfXDataInteger");
            }

            throw new NotSupportedException($"Unable to generate XData from code {code}");
        }
Exemple #2
0
        private IEnumerable <DxfCodePair> GeneratePairsFromCode(int code, object value)
        {
            var expectedType = DxfCodePair.ExpectedType(code);

            if (expectedType == typeof(bool))
            {
                return(new[] { new DxfCodePair(code, BoolShort((bool)value)) });
            }
            else if (expectedType == typeof(int))
            {
                return(new[] { new DxfCodePair(code, (int)value) });
            }
            else if (code == 40)
            {
                return(new[] { new DxfCodePair(code, (double)value) });
            }
            else if (expectedType == typeof(string))
            {
                return(new[] { new DxfCodePair(code, (string)value) });
            }
            else if (code == 10 || code == 11)
            {
                var point = (DxfPoint)value;
                return(new[]
                {
                    new DxfCodePair(code, point.X),
                    new DxfCodePair(code + 10, point.Y),
                    new DxfCodePair(code + 20, point.Z),
                });
            }
            else if (expectedType == typeof(string) && code >= 330)
            {
                // TODO: differentiate between handle types
                return(new[] { new DxfCodePair(code, HandleString((DxfHandle)value)) });
            }
            else
            {
                throw new ArgumentOutOfRangeException(nameof(code));
            }
        }
Exemple #3
0
        private void OutputTableItems()
        {
            foreach (var table in _tables)
            {
                var tableItem  = table.Element(XName.Get("TableItem", _xmlns));
                var properties = tableItem.Elements(XName.Get("Property", _xmlns));
                CreateNewFile("IxMilia.Dxf", "System", "System.Linq", "System.Collections.Generic", "IxMilia.Dxf.Collections", "IxMilia.Dxf.Sections", "IxMilia.Dxf.Tables");

                IncreaseIndent();
                AppendLine($"public partial class {Name(tableItem)} : DxfSymbolTableFlags");
                AppendLine("{");
                IncreaseIndent();

                AppendLine($"internal const string AcDbText = \"{ClassName(tableItem)}\";");
                AppendLine();
                AppendLine($"protected override DxfTableType TableType {{ get {{ return DxfTableType.{Type(table)}; }} }}");

                //
                // Properties
                //
                if (properties.Any())
                {
                    AppendLine();
                }

                var seenProperties = new HashSet <string>();
                foreach (var property in properties)
                {
                    var name = Name(property);
                    if (!seenProperties.Contains(name))
                    {
                        seenProperties.Add(name);
                        var propertyType = Type(property);
                        if (AllowMultiples(property))
                        {
                            propertyType = $"IList<{propertyType}>";
                        }

                        var getset = $"{{ get; {SetterAccessibility(property)}set; }}";

                        var comment = Comment(property);
                        var headerVar = ExpandCommentOrNull(HeaderVariable(property), "Corresponds to header variable {0}.");
                        var minVersion = ExpandCommentOrNull(MinVersion(property), "Minimum drawing version {0}.");
                        var maxVersion = ExpandCommentOrNull(MaxVersion(property), "Maximum drawing version {0}.");
                        var commentParts = new[] { comment, headerVar, minVersion, maxVersion }.Where(x => x != null).ToList();

                        AppendLine();
                        if (commentParts.Count > 0)
                        {
                            AppendLine("/// <summary>");
                            AppendLine("/// " + string.Join("  ", commentParts));
                            AppendLine("/// </summary>");
                        }

                        AppendLine($"{Accessibility(property)} {propertyType} {name} {getset}");
                    }
                }

                AppendLine();
                AppendLine("public IDictionary<string, DxfXDataApplicationItemCollection> XData { get; } = new DictionaryWithPredicate<string, DxfXDataApplicationItemCollection>((_key, value) => value != null);");

                //
                // Constructors
                //
                AppendLine();
                AppendLine($"public {Name(tableItem)}(string name)");
                AppendLine("    : this()");
                AppendLine("{");
                AppendLine("    if (string.IsNullOrEmpty(name))");
                AppendLine("    {");
                AppendLine("        throw new ArgumentException(nameof(name), $\"Parameter '{nameof(name)}' must have a value.\");");
                AppendLine("    }");
                AppendLine();
                AppendLine("    Name = name;");
                AppendLine("}");
                AppendLine();
                AppendLine($"internal {Name(tableItem)}()");
                AppendLine("    : base()");
                AppendLine("{");
                IncreaseIndent();
                foreach (var property in properties)
                {
                    var defaultValue = DefaultValue(property);
                    if (AllowMultiples(property))
                    {
                        defaultValue = $"new ListNonNull<{Type(property)}>()";
                    }

                    AppendLine($"{Name(property)} = {defaultValue};");
                }

                DecreaseIndent();
                AppendLine("}"); // end constructor

                //
                // AddValuePairs
                //
                if (GenerateWriterFunction(tableItem))
                {
                    AppendLine();
                    AppendLine("internal override void AddValuePairs(List<DxfCodePair> pairs, DxfAcadVersion version, bool outputHandles)");
                    AppendLine("{");
                    IncreaseIndent();
                    AppendLine("if (version >= DxfAcadVersion.R13)");
                    AppendLine("{");
                    AppendLine("    pairs.Add(new DxfCodePair(100, AcDbText));");
                    AppendLine("}");
                    AppendLine();
                    AppendLine("pairs.Add(new DxfCodePair(2, Name));");
                    if (HasFlags(tableItem))
                    {
                        AppendLine("pairs.Add(new DxfCodePair(70, (short)StandardFlags));");
                    }

                    foreach (var property in properties)
                    {
                        var    disableWritingDefault = DisableWritingDefault(property);
                        var    writeCondition        = WriteCondition(property);
                        var    minVersion            = MinVersion(property);
                        var    maxVersion            = MaxVersion(property);
                        var    hasPredicate          = disableWritingDefault || writeCondition != null || minVersion != null || maxVersion != null;
                        string predicate             = null;
                        if (hasPredicate)
                        {
                            var parts = new List <string>();
                            if (disableWritingDefault)
                            {
                                parts.Add(string.Format("{0} != {1}", Name(property), DefaultValue(property)));
                            }

                            if (writeCondition != null)
                            {
                                parts.Add(writeCondition);
                            }

                            if ((minVersion != null || maxVersion != null) && minVersion == maxVersion)
                            {
                                parts.Add("version == DxfAcadVersion." + minVersion);
                            }
                            else
                            {
                                if (minVersion != null)
                                {
                                    parts.Add("version >= DxfAcadVersion." + minVersion);
                                }

                                if (maxVersion != null)
                                {
                                    parts.Add("version <= DxfAcadVersion." + maxVersion);
                                }
                            }

                            predicate = string.Join(" && ", parts);
                        }

                        if (AllowMultiples(property))
                        {
                            if (hasPredicate)
                            {
                                AppendLine($"if ({predicate})");
                                AppendLine("{");
                                IncreaseIndent();
                            }

                            AppendLine($"pairs.AddRange({Name(property)}.Select(value => new DxfCodePair({Code(property)}, value)));");

                            if (hasPredicate)
                            {
                                DecreaseIndent();
                                AppendLine("}");
                                AppendLine();
                            }
                        }
                        else
                        {
                            var codeOverrides  = CodeOverrides(property);
                            var writeConverter = WriteConverter(property);
                            if (Code(property) < 0 && codeOverrides != null)
                            {
                                char prop = 'X';
                                for (int i = 0; i < codeOverrides.Length; i++, prop++)
                                {
                                    if (hasPredicate)
                                    {
                                        AppendLine($"if ({predicate})");
                                        AppendLine("{");
                                        IncreaseIndent();
                                    }

                                    AppendLine($"pairs.Add(new DxfCodePair({codeOverrides[i]}, {string.Format(writeConverter, $"{Name(property)}.{prop}")}));");

                                    if (hasPredicate)
                                    {
                                        DecreaseIndent();
                                        AppendLine("}");
                                        AppendLine();
                                    }
                                }
                            }
                            else
                            {
                                if (hasPredicate)
                                {
                                    AppendLine($"if ({predicate})");
                                    AppendLine("{");
                                    IncreaseIndent();
                                }

                                AppendLine($"pairs.Add(new DxfCodePair({Code(property)}, {string.Format(writeConverter, $"{Name(property)}")}));");

                                if (hasPredicate)
                                {
                                    DecreaseIndent();
                                    AppendLine("}");
                                    AppendLine();
                                }
                            }
                        }
                    }

                    AppendLine("DxfXData.AddValuePairs(XData, pairs, version, outputHandles);");

                    DecreaseIndent();
                    AppendLine("}"); // end method
                }

                //
                // Reader
                //
                if (GenerateReaderFunction(tableItem))
                {
                    //
                    // FromBuffer
                    //
                    AppendLine();
                    AppendLine($"internal static {Name(tableItem)} FromBuffer(DxfCodePairBufferReader buffer)");
                    AppendLine("{");
                    IncreaseIndent();
                    AppendLine($"var item = new {Name(tableItem)}();");
                    AppendLine("while (buffer.ItemsRemain)");
                    AppendLine("{");
                    IncreaseIndent();
                    AppendLine("var pair = buffer.Peek();");
                    AppendLine("if (pair.Code == 0)");
                    AppendLine("{");
                    AppendLine("    break;");
                    AppendLine("}");
                    AppendLine();
                    AppendLine("buffer.Advance();");
                    AppendLine("switch (pair.Code)");
                    AppendLine("{");
                    IncreaseIndent();
                    AppendLine("case DxfCodePairGroup.GroupCodeNumber:");
                    AppendLine("    var groupName = DxfCodePairGroup.GetGroupName(pair.StringValue);");
                    AppendLine("    item.ExtensionDataGroups.Add(DxfCodePairGroup.FromBuffer(buffer, groupName));");
                    AppendLine("    break;");
                    AppendLine("case (int)DxfXDataType.ApplicationName:");
                    AppendLine("    DxfXData.PopulateFromBuffer(buffer, item.XData, pair.StringValue);");
                    AppendLine("    break;");
                    AppendLine("default:");
                    AppendLine("    item.ApplyCodePair(pair);");
                    AppendLine("    break;");
                    DecreaseIndent();
                    AppendLine("}"); // end switch
                    DecreaseIndent();
                    AppendLine("}"); // end while
                    AppendLine();
                    AppendLine("return item;");
                    DecreaseIndent();
                    AppendLine("}");// end method

                    //
                    // ApplyCodePair
                    //
                    AppendLine();
                    AppendLine("private void ApplyCodePair(DxfCodePair pair)");
                    AppendLine("{");
                    IncreaseIndent();

                    AppendLine("switch (pair.Code)");
                    AppendLine("{");
                    IncreaseIndent();
                    if (HasFlags(tableItem))
                    {
                        AppendLine("case 70:");
                        AppendLine("    StandardFlags = (int)pair.ShortValue;");
                        AppendLine("    break;");
                    }

                    foreach (var property in properties)
                    {
                        var codeOverrides = CodeOverrides(property);
                        if (Code(property) < 0 && codeOverrides != null)
                        {
                            char prop = 'X';
                            for (int i = 0; i < codeOverrides.Length; i++, prop++)
                            {
                                var codeType      = DxfCodePair.ExpectedType(codeOverrides[i]);
                                var codeTypeValue = TypeToString(codeType);
                                AppendLine($"case {codeOverrides[i]}:");
                                AppendLine($"    {Name(property)} = {Name(property)}.WithUpdated{prop}(pair.{codeTypeValue});");
                                AppendLine("    break;");
                            }
                        }
                        else
                        {
                            var code          = Code(property);
                            var codeType      = DxfCodePair.ExpectedType(code);
                            var codeTypeValue = TypeToString(codeType);
                            var readConverter = ReadConverter(property);
                            AppendLine($"case {Code(property)}:");
                            if (AllowMultiples(property))
                            {
                                AppendLine($"    {Name(property)}.Add({string.Format(readConverter, $"pair.{codeTypeValue}")});");
                            }
                            else
                            {
                                AppendLine($"    {Name(property)} = {string.Format(readConverter, $"pair.{codeTypeValue}")};");
                            }

                            AppendLine("    break;");
                        }
                    }

                    AppendLine("default:");
                    AppendLine("    TrySetPair(pair);");
                    AppendLine("    break;");

                    DecreaseIndent();
                    AppendLine("}"); // end switch
                    DecreaseIndent();
                    AppendLine("}"); // end method
                }

                //
                // Clone
                //
                AppendLine();
                AppendLine($"public {Name(tableItem)} Clone()");
                AppendLine("{");
                IncreaseIndent();
                AppendLine($"return ({Name(tableItem)})this.MemberwiseClone();");
                DecreaseIndent();
                AppendLine("}");

                if (Name(tableItem) == "DxfDimStyle")
                {
                    //
                    // DxfDimStyle.SetVariable
                    //
                    AppendLine();
                    AppendLine("public void SetVariable(string name, object value)");
                    AppendLine("{");
                    IncreaseIndent();
                    AppendLine("switch (name?.ToUpper())");
                    AppendLine("{");
                    IncreaseIndent();
                    var setProperties = new HashSet <string>();
                    foreach (var property in properties)
                    {
                        if (setProperties.Add(HeaderVariable(property)))
                        {
                            AppendLine($"case \"{HeaderVariable(property)}\":");
                            AppendLine($"    {Name(property)} = ({Type(property)})value;");
                            AppendLine("    break;");
                        }
                    }

                    DecreaseIndent();
                    AppendLine("}"); // end switch
                    DecreaseIndent();
                    AppendLine("}"); // end method

                    //
                    // DxfDimStyle.GetVariable
                    //
                    AppendLine();
                    AppendLine("public object GetVariable(string name)");
                    AppendLine("{");
                    IncreaseIndent();
                    AppendLine("switch (name?.ToUpper())");
                    AppendLine("{");
                    IncreaseIndent();
                    var getProperties = new HashSet <string>();
                    foreach (var property in properties)
                    {
                        if (getProperties.Add(HeaderVariable(property)))
                        {
                            AppendLine($"case \"{HeaderVariable(property)}\":");
                            AppendLine($"    return {Name(property)};");
                        }
                    }

                    AppendLine("default:");
                    AppendLine("    return null;");
                    DecreaseIndent();
                    AppendLine("}"); // end switch
                    DecreaseIndent();
                    AppendLine("}"); // end method

                    //
                    // DxfDimStyle.GenerateStyleDifferenceAsXData
                    //
                    AppendLine();
                    AppendLine("/// <summary>Generates <see cref=\"DxfXDataApplicationItemCollection\"/> of the difference between the styles.  Result may be <see langword=\"null\"/>.</summary>");
                    AppendLine("public static DxfXDataApplicationItemCollection GenerateStyleDifferenceAsXData(DxfDimStyle primaryStyle, DxfDimStyle modifiedStyle)");
                    AppendLine("{");
                    IncreaseIndent();

                    AppendLine("var itemList = new DxfXDataItemList();");
                    AppendLine();

                    foreach (var property in properties)
                    {
                        AppendLine($"if (primaryStyle.{Name(property)} != modifiedStyle.{Name(property)})");
                        AppendLine("{");
                        AppendLine($"    itemList.Items.Add(new DxfXDataInteger({Code(property)}));");
                        AppendLine($"    itemList.Items.Add({XDataValueFromProperty(property, "modifiedStyle")});");
                        AppendLine("}");
                        AppendLine();
                    }

                    AppendLine("return itemList.Items.Count > 0");
                    AppendLine("    ? new DxfXDataApplicationItemCollection(new DxfXDataString(XDataStyleName), itemList)");
                    AppendLine("    : null;");
                    DecreaseIndent();
                    AppendLine("}");
                }

                DecreaseIndent();
                AppendLine("}"); // end class
                DecreaseIndent();

                FinishFile();
                WriteFile(Path.Combine(_outputDir, $"{Name(tableItem)}Generated.cs"));
            }
        }
Exemple #4
0
        private void OutputDxfEntity()
        {
            var baseEntity = _xml.Elements(XName.Get("Entity", _xmlns)).Where(x => Name(x) == "DxfEntity").Single();

            CreateNewFile(EntityNamespace, "System", "System.Collections.Generic", "System.Linq", "IxMilia.Dxf.Collections");
            IncreaseIndent();
            AppendLine("/// <summary>");
            AppendLine("/// DxfEntity class");
            AppendLine("/// </summary>");
            AppendLine("public partial class DxfEntity : IDxfItemInternal");
            AppendLine("{");
            IncreaseIndent();
            AppendLine("uint IDxfItemInternal.Handle { get; set; }");
            AppendLine("uint IDxfItemInternal.OwnerHandle { get; set; }");
            AppendLine("public IDxfItem Owner { get; private set;}");
            AppendLine();
            AppendLine("void IDxfItemInternal.SetOwner(IDxfItem owner)");
            AppendLine("{");
            AppendLine("    Owner = owner;");
            AppendLine("}");
            AppendLine();
            AppendLine("protected void SetOwner(IDxfItem owner)");
            AppendLine("{");
            AppendLine("    ((IDxfItemInternal)this).SetOwner(owner);");
            AppendLine("}");

            AppendPointers(baseEntity);
            AppendProperties(baseEntity);

            AppendLine();
            AppendLine("public string EntityTypeString");
            AppendLine("{");
            AppendLine("    get");
            AppendLine("    {");
            AppendLine("        switch (EntityType)");
            AppendLine("        {");
            foreach (var entity in _entities)
            {
                var typeString = TypeString(entity);
                var commaIndex = typeString.IndexOf(',');
                if (commaIndex >= 0)
                {
                    typeString = typeString.Substring(0, commaIndex);
                }

                if (!string.IsNullOrEmpty(typeString))
                {
                    AppendLine($"            case DxfEntityType.{EntityType(entity)}:");
                    AppendLine($"                return \"{typeString}\";");
                }
            }

            AppendLine("            default:");
            AppendLine("                throw new NotImplementedException();");
            AppendLine("        }"); // end switch
            AppendLine("    }");     // end getter
            AppendLine("}");         // end method
            AppendLine();

            //
            // Constructors
            //
            AppendLine("protected DxfEntity(DxfEntity other)");
            AppendLine("    : this()");
            AppendLine("{");
            AppendLine("    ((IDxfItemInternal)this).Handle = ((IDxfItemInternal)other).Handle;");
            AppendLine("    ((IDxfItemInternal)this).OwnerHandle = ((IDxfItemInternal)other).OwnerHandle;");
            AppendLine("    ((IDxfItemInternal)this).SetOwner(((IDxfItemInternal)other).Owner);");
            foreach (var property in GetPropertiesAndPointers(baseEntity))
            {
                var name = Name(property);
                if (IsPointer(property))
                {
                    name += "Pointer";
                    AppendLine($"    this.{name}.Handle = other.{name}.Handle;");
                    AppendLine($"    this.{name}.Item = other.{name}.Item;");
                }
                else
                {
                    AppendLine($"    this.{name} = other.{name};");
                }
            }

            AppendLine("}"); // end method

            //
            // Initialize
            //
            AppendLine();
            AppendLine("protected virtual void Initialize()");
            AppendLine("{");
            foreach (var property in GetProperties(baseEntity))
            {
                var defaultValue = AllowMultiples(property)
                    ? string.Format("new ListNonNull<{0}>()", Type(property))
                    : DefaultValue(property);
                AppendLine($"    this.{Name(property)} = {defaultValue};");
            }

            AppendLine("}"); // end method

            //
            // AddValuePairs
            //
            AppendLine();
            AppendLine("protected virtual void AddValuePairs(List<DxfCodePair> pairs, DxfAcadVersion version, bool outputHandles)");
            AppendLine("{");
            AppendLine("    pairs.Add(new DxfCodePair(0, EntityTypeString));");
            IncreaseIndent();
            foreach (var line in GetWriteCommands(baseEntity))
            {
                if (string.IsNullOrWhiteSpace(line))
                {
                    AppendLine();
                }
                else
                {
                    AppendLine(line);
                }
            }

            DecreaseIndent();
            AppendLine("}"); // end method

            //
            // TrySetPair
            //
            AppendLine();
            AppendLine("internal virtual bool TrySetPair(DxfCodePair pair)");
            AppendLine("{");
            AppendLine("    switch (pair.Code)");
            AppendLine("    {");
            AppendLine("        case 5:");
            AppendLine("            ((IDxfItemInternal)this).Handle = UIntHandle(pair.StringValue);");
            AppendLine("            break;");
            AppendLine("        case 330:");
            AppendLine("            ((IDxfItemInternal)this).OwnerHandle = UIntHandle(pair.StringValue);");
            AppendLine("            break;");
            foreach (var propertyGroup in GetPropertiesAndPointers(baseEntity).Where(p => !ProtectedSet(p)).GroupBy(p => Code(p)).OrderBy(p => p.Key))
            {
                var code = propertyGroup.Key;
                if (propertyGroup.Count() == 1)
                {
                    var property = propertyGroup.Single();
                    var name     = Name(property);
                    var codes    = GetCodeOverrides(property);
                    if (codes != null)
                    {
                        var suffix = 'X';
                        for (int i = 0; i < codes.Length; i++, suffix++)
                        {
                            AppendLine($"        case {codes[i]}:");
                            AppendLine($"            this.{name} = this.{name}.WithUpdated{suffix}(pair.DoubleValue);");
                            AppendLine("            break;");
                        }
                    }
                    else
                    {
                        if (IsPointer(property))
                        {
                            name += "Pointer.Handle";
                        }

                        var codeType      = DxfCodePair.ExpectedType(code);
                        var codeTypeValue = TypeToString(codeType);
                        var assignCode    = AllowMultiples(property)
                            ? string.Format("this.{0}.Add(", name)
                            : string.Format("this.{0} = ", name);
                        var assignSuffix = AllowMultiples(property)
                            ? ")"
                            : "";
                        var readConverter = ReadConverter(property);
                        AppendLine($"        case {code}:");
                        AppendLine($"            {assignCode}{string.Format(readConverter, $"pair.{codeTypeValue}")}{assignSuffix};");
                        AppendLine($"            break;");
                    }
                }
                else
                {
                    AppendLine($"        case {code}:");
                    AppendLine($"            // TODO: code is shared by properties {string.Join(", ", propertyGroup.Select(p => Name(p)))}");
                    AppendLine("            break;");
                }
            }

            AppendLine("        default:");
            AppendLine("            return false;");
            AppendLine("    }"); // end switch
            AppendLine();
            AppendLine("    return true;");
            AppendLine("}"); // end method

            //
            // FromBuffer
            //
            AppendLine();
            AppendLine("internal static DxfEntity FromBuffer(DxfCodePairBufferReader buffer)");
            AppendLine("{");
            AppendLine("    var first = buffer.Peek();");
            AppendLine("    buffer.Advance();");
            AppendLine("    DxfEntity entity;");
            AppendLine("    switch (first.StringValue)");
            AppendLine("    {");
            foreach (var entity in _entities)
            {
                var typeString = TypeString(entity);
                if (!string.IsNullOrEmpty(typeString))
                {
                    var typeStrings = typeString.Split(',');
                    foreach (var singleTypeString in typeStrings)
                    {
                        AppendLine($"        case \"{singleTypeString}\":");
                    }

                    AppendLine($"            entity = new {Name(entity)}();");
                    AppendLine("            break;");
                }
            }

            AppendLine("        default:");
            AppendLine("            SwallowEntity(buffer);");
            AppendLine("            entity = null;");
            AppendLine("            break;");
            AppendLine("    }"); // end switch
            AppendLine();
            AppendLine("    if (entity != null)");
            AppendLine("    {");
            AppendLine("        entity = entity.PopulateFromBuffer(buffer);");
            AppendLine("    }");
            AppendLine();
            AppendLine("    return entity;");
            AppendLine("}"); // end method

            DecreaseIndent();
            AppendLine("}"); // end class
            DecreaseIndent();
            FinishFile();
            WriteFile(Path.Combine(_outputDir, "DxfEntityGenerated.cs"));
        }
        private void OutputTableItems()
        {
            foreach (var table in _tables)
            {
                var tableItem  = table.Element(XName.Get("TableItem", _xmlns));
                var properties = tableItem.Elements(XName.Get("Property", _xmlns));
                CreateNewFile("IxMilia.Dxf", "System.Linq", "System.Collections.Generic", "IxMilia.Dxf.Collections", "IxMilia.Dxf.Sections", "IxMilia.Dxf.Tables");

                IncreaseIndent();
                AppendLine($"public partial class {Name(tableItem)} : DxfSymbolTableFlags");
                AppendLine("{");
                IncreaseIndent();

                AppendLine($"internal const string AcDbText = \"{ClassName(tableItem)}\";");
                AppendLine();
                AppendLine($"protected override DxfTableType TableType {{ get {{ return DxfTableType.{Type(table)}; }} }}");

                //
                // Properties
                //
                if (properties.Any())
                {
                    AppendLine();
                }

                var seenProperties = new HashSet <string>();
                foreach (var property in properties)
                {
                    var name = Name(property);
                    if (!seenProperties.Contains(name))
                    {
                        seenProperties.Add(name);
                        var propertyType = Type(property);
                        if (AllowMultiples(property))
                        {
                            propertyType = $"IList<{propertyType}>";
                        }

                        var getset = $"{{ get; {SetterAccessibility(property)}set; }}";
                        AppendLine($"{Accessibility(property)} {propertyType} {name} {getset}");
                    }
                }

                AppendLine();
                AppendLine("public DxfXData XData { get; set; }");

                //
                // Constructor
                //
                AppendLine();
                AppendLine($"public {Name(tableItem)}()");
                AppendLine("    : base()");
                AppendLine("{");
                IncreaseIndent();
                foreach (var property in properties)
                {
                    var defaultValue = DefaultValue(property);
                    if (AllowMultiples(property))
                    {
                        defaultValue = $"new ListNonNull<{Type(property)}>()";
                    }

                    AppendLine($"{Name(property)} = {defaultValue};");
                }

                DecreaseIndent();
                AppendLine("}"); // end constructor

                //
                // AddValuePairs
                //
                if (GenerateWriterFunction(tableItem))
                {
                    AppendLine();
                    AppendLine("internal override void AddValuePairs(List<DxfCodePair> pairs, DxfAcadVersion version, bool outputHandles)");
                    AppendLine("{");
                    IncreaseIndent();
                    AppendLine("if (version >= DxfAcadVersion.R13)");
                    AppendLine("{");
                    AppendLine("    pairs.Add(new DxfCodePair(100, AcDbText));");
                    AppendLine("}");
                    AppendLine();
                    AppendLine("pairs.Add(new DxfCodePair(2, Name));");
                    if (HasFlags(tableItem))
                    {
                        AppendLine("pairs.Add(new DxfCodePair(70, (short)StandardFlags));");
                    }

                    foreach (var property in properties)
                    {
                        var    disableWritingDefault = DisableWritingDefault(property);
                        var    writeCondition        = WriteCondition(property);
                        var    minVersion            = MinVersion(property);
                        var    maxVersion            = MaxVersion(property);
                        var    hasPredicate          = disableWritingDefault || writeCondition != null || minVersion != null || maxVersion != null;
                        string predicate             = null;
                        if (hasPredicate)
                        {
                            var parts = new List <string>();
                            if (disableWritingDefault)
                            {
                                parts.Add(string.Format("{0} != {1}", Name(property), DefaultValue(property)));
                            }

                            if (writeCondition != null)
                            {
                                parts.Add(writeCondition);
                            }

                            if ((minVersion != null || maxVersion != null) && minVersion == maxVersion)
                            {
                                parts.Add("version == DxfAcadVersion." + minVersion);
                            }
                            else
                            {
                                if (minVersion != null)
                                {
                                    parts.Add("version >= DxfAcadVersion." + minVersion);
                                }

                                if (maxVersion != null)
                                {
                                    parts.Add("version <= DxfAcadVersion." + maxVersion);
                                }
                            }

                            predicate = string.Join(" && ", parts);
                        }

                        if (AllowMultiples(property))
                        {
                            if (hasPredicate)
                            {
                                AppendLine($"if ({predicate})");
                                AppendLine("{");
                                IncreaseIndent();
                            }

                            AppendLine($"pairs.AddRange({Name(property)}.Select(value => new DxfCodePair({Code(property)}, value)));");

                            if (hasPredicate)
                            {
                                DecreaseIndent();
                                AppendLine("}");
                                AppendLine();
                            }
                        }
                        else
                        {
                            var codeOverrides  = CodeOverrides(property);
                            var writeConverter = WriteConverter(property);
                            if (Code(property) < 0 && codeOverrides != null)
                            {
                                char prop = 'X';
                                for (int i = 0; i < codeOverrides.Length; i++, prop++)
                                {
                                    if (hasPredicate)
                                    {
                                        AppendLine($"if ({predicate})");
                                        AppendLine("{");
                                        IncreaseIndent();
                                    }

                                    AppendLine($"pairs.Add(new DxfCodePair({codeOverrides[i]}, {string.Format(writeConverter, $"{Name(property)}.{prop}")}));");

                                    if (hasPredicate)
                                    {
                                        DecreaseIndent();
                                        AppendLine("}");
                                        AppendLine();
                                    }
                                }
                            }
                            else
                            {
                                if (hasPredicate)
                                {
                                    AppendLine($"if ({predicate})");
                                    AppendLine("{");
                                    IncreaseIndent();
                                }

                                AppendLine($"pairs.Add(new DxfCodePair({Code(property)}, {string.Format(writeConverter, $"{Name(property)}")}));");

                                if (hasPredicate)
                                {
                                    DecreaseIndent();
                                    AppendLine("}");
                                    AppendLine();
                                }
                            }
                        }
                    }

                    AppendLine("if (XData != null)");
                    AppendLine("{");
                    AppendLine("    XData.AddValuePairs(pairs, version, outputHandles);");
                    AppendLine("}");

                    DecreaseIndent();
                    AppendLine("}"); // end method
                }

                //
                // FromBuffer
                //
                if (GenerateReaderFunction(tableItem))
                {
                    AppendLine();
                    AppendLine($"internal static {Name(tableItem)} FromBuffer(DxfCodePairBufferReader buffer)");
                    AppendLine("{");
                    IncreaseIndent();
                    AppendLine($"var item = new {Name(tableItem)}();");
                    AppendLine("while (buffer.ItemsRemain)");
                    AppendLine("{");
                    IncreaseIndent();
                    AppendLine("var pair = buffer.Peek();");
                    AppendLine("if (pair.Code == 0)");
                    AppendLine("{");
                    AppendLine("    break;");
                    AppendLine("}");
                    AppendLine();
                    AppendLine("buffer.Advance();");
                    AppendLine("switch (pair.Code)");
                    AppendLine("{");
                    IncreaseIndent();
                    if (HasFlags(tableItem))
                    {
                        AppendLine("case 70:");
                        AppendLine("    item.StandardFlags = (int)pair.ShortValue;");
                        AppendLine("    break;");
                    }

                    AppendLine("case DxfCodePairGroup.GroupCodeNumber:");
                    AppendLine("    var groupName = DxfCodePairGroup.GetGroupName(pair.StringValue);");
                    AppendLine("    item.ExtensionDataGroups.Add(DxfCodePairGroup.FromBuffer(buffer, groupName));");
                    AppendLine("    break;");

                    foreach (var property in properties)
                    {
                        var codeOverrides = CodeOverrides(property);
                        if (Code(property) < 0 && codeOverrides != null)
                        {
                            char prop = 'X';
                            for (int i = 0; i < codeOverrides.Length; i++, prop++)
                            {
                                var codeType      = DxfCodePair.ExpectedType(codeOverrides[i]);
                                var codeTypeValue = TypeToString(codeType);
                                AppendLine($"case {codeOverrides[i]}:");
                                AppendLine($"    item.{Name(property)} = item.{Name(property)}.WithUpdated{prop}(pair.{codeTypeValue});");
                                AppendLine("    break;");
                            }
                        }
                        else
                        {
                            var code          = Code(property);
                            var codeType      = DxfCodePair.ExpectedType(code);
                            var codeTypeValue = TypeToString(codeType);
                            var readConverter = ReadConverter(property);
                            AppendLine($"case {Code(property)}:");
                            if (AllowMultiples(property))
                            {
                                AppendLine($"    item.{Name(property)}.Add({string.Format(readConverter, $"pair.{codeTypeValue}")});");
                            }
                            else
                            {
                                AppendLine($"    item.{Name(property)} = {string.Format(readConverter, $"pair.{codeTypeValue}")};");
                            }

                            AppendLine("    break;");
                        }
                    }

                    AppendLine("case (int)DxfXDataType.ApplicationName:");
                    AppendLine("    item.XData = DxfXData.FromBuffer(buffer, pair.StringValue);");
                    AppendLine("    break;");
                    AppendLine("default:");
                    AppendLine("    item.TrySetPair(pair);");
                    AppendLine("    break;");

                    DecreaseIndent();
                    AppendLine("}"); // end switch
                    DecreaseIndent();
                    AppendLine("}"); // end while
                    AppendLine();
                    AppendLine("return item;");
                    DecreaseIndent();
                    AppendLine("}"); // end method
                }

                DecreaseIndent();
                AppendLine("}"); // end class
                DecreaseIndent();

                FinishFile();
                WriteFile(Path.Combine(_outputDir, $"{Name(tableItem)}Generated.cs"));
            }
        }
Exemple #6
0
        public void AppendTrySetPairMethod(XElement item)
        {
            if (GetPropertiesAndPointers(item).Any() && GenerateReaderFunction(item))
            {
                AppendLine();
                AppendLine("internal override bool TrySetPair(DxfCodePair pair)");
                AppendLine("{");
                IncreaseIndent();
                AppendLine("switch (pair.Code)");
                AppendLine("{");
                IncreaseIndent();
                foreach (var propertyGroup in GetPropertiesAndPointers(item).Where(p => !ProtectedSet(p)).GroupBy(p => Code(p)).OrderBy(p => p.Key))
                {
                    var code = propertyGroup.Key;
                    if (propertyGroup.Count() == 1)
                    {
                        var property = propertyGroup.Single();
                        var name     = Name(property);
                        var codes    = GetCodeOverrides(property);
                        if (codes != null)
                        {
                            var suffix = 'X';
                            for (int i = 0; i < codes.Length; i++, suffix++)
                            {
                                AppendLine($"case {codes[i]}:");
                                AppendLine($"    this.{name} = this.{name}.WithUpdated{suffix}(pair.DoubleValue);");
                                AppendLine("    break;");
                            }
                        }
                        else
                        {
                            var codeType      = DxfCodePair.ExpectedType(code);
                            var codeTypeValue = TypeToString(codeType);
                            if (IsPointer(property))
                            {
                                name += AllowMultiples(property) ? "Pointers.Pointers" : "Pointer.Handle";
                            }

                            var assignCode = AllowMultiples(property)
                                ? string.Format("this.{0}.Add(", name)
                                : string.Format("this.{0} = ", name);
                            var assignSuffix = AllowMultiples(property)
                                ? ")"
                                : "";
                            var readConverter = ReadConverter(property);
                            var value         = string.Format(readConverter, $"pair.{codeTypeValue}");
                            if (IsPointer(property) && AllowMultiples(property))
                            {
                                value = "new DxfPointer(" + value + ")";
                            }

                            AppendLine($"case {code}:");
                            AppendLine($"    {assignCode}{value}{assignSuffix};");
                            AppendLine("    break;");
                        }
                    }
                    else
                    {
                        AppendLine($"case {code}:");
                        if (item.Name.LocalName == "Object" && code > 0)
                        {
                            IncreaseIndent();
                            AppendLine($"switch (_code_{code}_index)");
                            AppendLine("{");
                            IncreaseIndent();
                            for (int i = 0; i < propertyGroup.Count(); i++)
                            {
                                var property      = propertyGroup.ElementAt(i);
                                var readConverter = ReadConverter(property);
                                var value         = string.Format(readConverter, $"pair.{TypeToString(DxfCodePair.ExpectedType(code))}");
                                AppendLine($"case {i}:");
                                AppendLine($"    this.{Name(property)} = {value};");
                                AppendLine($"    _code_{code}_index++;");
                                AppendLine("    break;");
                            }

                            AppendLine("default:");
                            AppendLine($"    Debug.Assert(false, \"Unexpected extra values for code {code}\");");
                            AppendLine("    break;");
                            DecreaseIndent();
                            AppendLine("}");
                            DecreaseIndent();
                        }
                        else
                        {
                            AppendLine($"    // code is custom-handled and shared by properties {string.Join(", ", propertyGroup.Select(p => Name(p)))}");
                        }

                        AppendLine("    break;");
                    }
                }

                AppendLine("default:");
                AppendLine("    return base.TrySetPair(pair);");
                DecreaseIndent();
                AppendLine("}"); // end switch
                AppendLine();
                AppendLine("return true;");
                DecreaseIndent();
                AppendLine("}"); // end method
            }
        }
        private void OutputHeader()
        {
            CreateNewFile(SectionNamespace, "System", "System.Collections.Generic", "System.Diagnostics", "IxMilia.Dxf.Entities");

            IncreaseIndent();
            AppendLine("public partial class DxfHeader");
            AppendLine("{");
            IncreaseIndent();

            //
            // Key names
            //
            var seenKeys = new HashSet <string>();

            foreach (var property in _variables)
            {
                var name = Name(property).ToUpper();
                if (!seenKeys.Contains(name))
                {
                    seenKeys.Add(name);
                    AppendLine($"private const string {Identifier(name)} = \"${name}\";");
                }
            }

            //
            // Properties
            //
            var seenProperties = new HashSet <string>();

            foreach (var property in _variables)
            {
                var propertyName = Property(property);
                if (!seenProperties.Contains(propertyName))
                {
                    seenProperties.Add(propertyName); // don't write duplicate properties
                    var comment    = $"/// {$"The ${Name(property)} header variable.  {Comment(property)}"}";
                    var minVersion = MinVersion(property);
                    if (minVersion != null)
                    {
                        comment += $"  Minimum AutoCAD version: {minVersion}.";
                    }

                    var maxVersion = MaxVersion(property);
                    if (maxVersion != null)
                    {
                        comment += $"  Maximum AutoCAD version: {maxVersion}.";
                    }

                    AppendLine();
                    AppendLine("/// <summary>");
                    AppendLine(comment);
                    AppendLine("/// </summary>");
                    AppendLine($"public {Type(property)} {Property(property)} {{ get; set; }}");
                }
            }

            //
            // SetDefaults
            //
            AppendLine();
            AppendLine("public void SetDefaults()");
            AppendLine("{");
            IncreaseIndent();
            AppendLine("SetManualDefaults();");
            seenProperties.Clear();
            foreach (var property in _variables)
            {
                var propertyName = Property(property);
                if (!seenProperties.Contains(propertyName))
                {
                    seenProperties.Add(propertyName);
                    var defaultValue = DefaultValue(property);
                    if (Type(property) == "string" && defaultValue != "null" && (!defaultValue.StartsWith("\"") && !defaultValue.EndsWith("\"")))
                    {
                        defaultValue = string.Format("\"{0}\"", defaultValue);
                    }
                    else if (Type(property) == "char" && defaultValue.Length == 1)
                    {
                        if (defaultValue == "\"")
                        {
                            defaultValue = "\\\"";
                        }

                        defaultValue = string.Format("'{0}'", defaultValue);
                    }

                    AppendLine($"this.{propertyName} = {defaultValue}; // {Name(property)}");
                }
            }

            DecreaseIndent();
            AppendLine("}"); // end method

            //
            // AddValueToList
            //
            AppendLine();
            AppendLine("internal void AddValueToList(List<DxfCodePair> list)");
            AppendLine("{");
            IncreaseIndent();
            foreach (var property in _variables.Where(p => !SuppressWriting(p)))
            {
                var converter           = WriteConverter(property);
                var type                = Type(property);
                var dontWriteDefaultAtt = property.Attribute("DontWriteDefault");
                var minVersionAtt       = property.Attribute("MinVersion");
                var maxVersionAtt       = property.Attribute("MaxVersion");
                var dontWriteDefault    = dontWriteDefaultAtt == null ? false : bool.Parse(dontWriteDefaultAtt.Value);
                var usingIf             = dontWriteDefault || minVersionAtt != null || maxVersionAtt != null;
                AppendLine();
                AppendLine($"// {Name(property)}");
                if (usingIf)
                {
                    var ifParts = new List <string>();
                    if (minVersionAtt != null && maxVersionAtt != null && minVersionAtt.Value == maxVersionAtt.Value)
                    {
                        ifParts.Add(string.Format("Version == DxfAcadVersion.{0}", minVersionAtt.Value));
                    }
                    else
                    {
                        if (minVersionAtt != null)
                        {
                            ifParts.Add(string.Format("Version >= DxfAcadVersion.{0}", minVersionAtt.Value));
                        }
                        if (maxVersionAtt != null)
                        {
                            ifParts.Add(string.Format("Version <= DxfAcadVersion.{0}", maxVersionAtt.Value));
                        }
                    }
                    if (dontWriteDefault)
                    {
                        ifParts.Add(string.Format("this.{0} != {1}", Property(property), DefaultValue(property)));
                    }

                    var allIfText = string.Join(" && ", ifParts);

                    AppendLine($"if ({allIfText})");
                    AppendLine("{");
                    IncreaseIndent();
                }

                AppendLine($"list.Add(new DxfCodePair(9, {Identifier(Name(property))}));");
                if (type == "DxfPoint" || type == "DxfVector")
                {
                    var prop = Property(property);
                    AppendLine($"list.Add(new DxfCodePair(10, this.{prop}?.X ?? default(double)));");
                    AppendLine($"list.Add(new DxfCodePair(20, this.{prop}?.Y ?? default(double)));");
                    if (Math.Abs(Code(property)) >= 3)
                    {
                        AppendLine($"list.Add(new DxfCodePair(30, this.{prop}?.Z ?? default(double)));");
                    }
                }
                else
                {
                    AppendLine($"list.Add(new DxfCodePair({Code(property)}, {converter}(this.{Property(property)})));");
                }

                if (usingIf)
                {
                    DecreaseIndent();
                    AppendLine("}");
                }
            }

            DecreaseIndent();
            AppendLine("}"); // end method

            //
            // SetHeaderVariable
            //
            AppendLine();
            AppendLine("internal void SetHeaderVariable(string keyName, DxfCodePair pair)");
            AppendLine("{");
            IncreaseIndent();
            AppendLine("switch (keyName)");
            AppendLine("{");
            IncreaseIndent();
            foreach (var propertyGroup in _variables.GroupBy(v => Name(v)))
            {
                AppendLine($"case {Identifier(propertyGroup.Key)}:");
                IncreaseIndent();
                var type = Type(propertyGroup.First());
                var prop = Property(propertyGroup.First());
                if (type == "DxfPoint" || type == "DxfVector")
                {
                    AppendLine($"SetPoint(pair, this.{prop});");
                    AppendLine("break;");
                }
                else
                {
                    if (propertyGroup.Count() > 1)
                    {
                        AppendLine("switch (pair.Code)");
                        AppendLine("{");
                        IncreaseIndent();
                        foreach (var property in propertyGroup)
                        {
                            var code          = Code(property);
                            var codeType      = DxfCodePair.ExpectedType(code);
                            var codeTypeValue = TypeToString(codeType);
                            var converter     = ReadConverter(property);
                            AppendLine($"case {code}:");
                            AppendLine($"    this.{prop} = {converter}(pair.{codeTypeValue});");
                            AppendLine("    break;");
                        }

                        AppendLine("default:");
                        AppendLine($"    Debug.Assert(false, $\"Expected code [{string.Join(", ", propertyGroup.Select(p => Code(p)))}], got {{pair.Code}}\");");
                        AppendLine("    break;");
                        DecreaseIndent();
                        AppendLine("}"); // end switch
                    }
                    else
                    {
                        var code          = Code(propertyGroup.First());
                        var codeType      = DxfCodePair.ExpectedType(code);
                        var codeTypeValue = TypeToString(codeType);
                        var converter     = ReadConverter(propertyGroup.First());
                        AppendLine($"EnsureCode(pair, {code});");
                        AppendLine($"this.{prop} = {converter}(pair.{codeTypeValue});");
                    }

                    AppendLine("break;");
                }

                DecreaseIndent();
            }

            AppendLine("default:");
            AppendLine("    // unsupported variable");
            AppendLine("    break;");
            DecreaseIndent();
            AppendLine("}"); // end switch
            DecreaseIndent();
            AppendLine("}"); // end method

            //
            // Flags
            //
            var flagElement = XName.Get("Flag", _xmlns);

            foreach (var property in _variables)
            {
                var flags = property.Elements(flagElement);
                if (flags.Any())
                {
                    AppendLine();
                    AppendLine($"// {Name(property)} flags");
                    foreach (var flag in flags)
                    {
                        AppendLine();
                        var comment    = Comment(flag);
                        var minVersion = MinVersion(property);
                        if (minVersion != null)
                        {
                            comment += $"  Minimum AutoCAD version: {minVersion}.";
                        }

                        var maxVersion = MaxVersion(property);
                        if (maxVersion != null)
                        {
                            comment += $"  Maximum AutoCAD version: {maxVersion}.";
                        }

                        AppendLine("/// <summary>");
                        AppendLine($"/// {comment}");
                        AppendLine("/// </summary>");
                        AppendLine($"public bool {Name(flag)}");
                        AppendLine("{");
                        AppendLine($"    get {{ return DxfHelpers.GetFlag({Property(property)}, {Mask(flag)}); }}");
                        AppendLine("    set");
                        AppendLine("    {");
                        AppendLine($"        var flags = {Property(property)};");
                        AppendLine($"        DxfHelpers.SetFlag(value, ref flags, {Mask(flag)});");
                        AppendLine($"        {Property(property)} = flags;");
                        AppendLine("    }");
                        AppendLine("}");
                    }
                }
            }

            //
            // GetValue
            //
            AppendLine();
            AppendLine("private object GetValue(string variableName)");
            AppendLine("{");
            IncreaseIndent();
            AppendLine("switch (variableName.ToUpper())");
            AppendLine("{");
            IncreaseIndent();
            seenProperties.Clear();
            foreach (var property in _variables)
            {
                var propertyName = Name(property);
                if (!seenProperties.Contains(propertyName))
                {
                    seenProperties.Add(propertyName);
                    AppendLine($"case {Identifier(propertyName)}:");
                    AppendLine($"    return this.{Property(property)};");
                }
            }

            AppendLine("default:");
            AppendLine("    throw new ArgumentException(\"Unrecognized variable\", nameof(variableName));");
            DecreaseIndent();
            AppendLine("}"); // end switch
            DecreaseIndent();
            AppendLine("}"); // end method

            //
            // SetValue
            //
            AppendLine();
            AppendLine("private void SetValue(string variableName, object value)");
            AppendLine("{");
            IncreaseIndent();
            AppendLine("switch (variableName.ToUpper())");
            AppendLine("{");
            IncreaseIndent();
            seenProperties.Clear();
            foreach (var property in _variables)
            {
                var propertyName = Name(property);
                if (!seenProperties.Contains(propertyName))
                {
                    seenProperties.Add(propertyName);
                    AppendLine($"case {Identifier(propertyName)}:");
                    AppendLine($"    this.{Property(property)} = ({Type(property)})value;");
                    AppendLine("    break;");
                }
            }

            AppendLine("default:");
            AppendLine("    throw new ArgumentException(\"Unrecognized variable\", nameof(variableName));");
            DecreaseIndent();
            AppendLine("}"); // end switch
            DecreaseIndent();
            AppendLine("}"); // end method

            DecreaseIndent();
            AppendLine("}"); // end class
            DecreaseIndent();

            FinishFile();
            WriteFile(Path.Combine(_outputDir, "DxfHeaderGenerated.cs"));
        }
Exemple #8
0
        private void OutputDxfObject()
        {
            var baseObject = _xml.Elements(XName.Get("Object", _xmlns)).Where(x => Name(x) == "DxfObject").Single();

            CreateNewFile(ObjectNamespace, "System", "System.Collections.Generic", "System.Linq", "IxMilia.Dxf.Collections");
            IncreaseIndent();
            AppendLine("/// <summary>");
            AppendLine("/// DxfObject class");
            AppendLine("/// </summary>");
            AppendLine("public partial class DxfObject : IDxfItemInternal");
            AppendLine("{");
            IncreaseIndent();
            AppendLine("uint IDxfItemInternal.Handle { get; set; }");
            AppendLine("uint IDxfItemInternal.OwnerHandle { get; set; }");
            AppendLine("public IDxfItem Owner { get; private set;}");
            AppendLine();
            AppendLine("void IDxfItemInternal.SetOwner(IDxfItem owner)");
            AppendLine("{");
            AppendLine("    Owner = owner;");
            AppendLine("}");
            AppendLine();
            AppendLine("IEnumerable<DxfPointer> IDxfItemInternal.GetPointers()");
            AppendLine("{");
            AppendLine("    yield break;");
            AppendLine("}");
            AppendLine();
            AppendLine("IEnumerable<IDxfItemInternal> IDxfItemInternal.GetChildItems()");
            AppendLine("{");
            AppendLine("    return ((IDxfItemInternal)this).GetPointers().Select(p => (IDxfItemInternal)p.Item);");
            AppendLine("}");

            //
            // ObjectTypeString
            //
            AppendLine();
            AppendLine("public string ObjectTypeString");
            AppendLine("{");
            AppendLine("    get");
            AppendLine("    {");
            AppendLine("        switch (ObjectType)");
            AppendLine("        {");
            foreach (var obj in _objects)
            {
                var typeString = TypeString(obj);
                var commaIndex = typeString.IndexOf(',');
                if (commaIndex >= 0)
                {
                    typeString = typeString.Substring(0, commaIndex);
                }

                if (!string.IsNullOrEmpty(typeString))
                {
                    AppendLine($"            case DxfObjectType.{ObjectType(obj)}:");
                    AppendLine($"                return \"{typeString}\";");
                }
            }

            AppendLine("            default:");
            AppendLine("                throw new NotImplementedException();");
            AppendLine("        }");
            AppendLine("    }");
            AppendLine("}");

            //
            // Copy constructor
            //
            AppendLine();
            AppendLine("protected DxfObject(DxfObject other)");
            AppendLine("    : this()");
            AppendLine("{");
            AppendLine("}");

            //
            // Initialize
            //
            AppendLine();
            AppendLine("protected virtual void Initialize()");
            AppendLine("{");
            AppendLine("}");

            //
            // AddValuePairs
            //
            AppendLine();
            AppendLine("protected virtual void AddValuePairs(List<DxfCodePair> pairs, DxfAcadVersion version, bool outputHandles)");
            AppendLine("{");
            AppendLine("    pairs.Add(new DxfCodePair(0, ObjectTypeString));");
            foreach (var line in GetWriteCommands(baseObject))
            {
                if (string.IsNullOrWhiteSpace(line))
                {
                    AppendLine();
                }
                else
                {
                    AppendLine("    " + line);
                }
            }

            AppendLine("}");

            //
            // TrySetPair
            //
            AppendLine();
            AppendLine("internal virtual bool TrySetPair(DxfCodePair pair)");
            AppendLine("{");
            IncreaseIndent();
            AppendLine("switch (pair.Code)");
            AppendLine("{");
            IncreaseIndent();
            AppendLine("case 5:");
            AppendLine("    ((IDxfItemInternal)this).Handle = UIntHandle(pair.StringValue);");
            AppendLine("    break;");
            AppendLine("case 330:");
            AppendLine("    ((IDxfItemInternal)this).OwnerHandle = UIntHandle(pair.StringValue);");
            AppendLine("    break;");
            foreach (var propertyGroup in GetProperties(baseObject).Where(p => !ProtectedSet(p)).GroupBy(p => Code(p)).OrderBy(p => p.Key))
            {
                var code          = propertyGroup.Key;
                var property      = propertyGroup.Single();
                var name          = Name(property);
                var codeType      = DxfCodePair.ExpectedType(code);
                var codeTypeValue = TypeToString(codeType);
                var assignCode    = AllowMultiples(property)
                    ? string.Format("this.{0}.Add(", Name(property))
                    : string.Format("this.{0} = ", Name(property));
                var assignSuffix = AllowMultiples(property)
                    ? ")"
                    : "";
                var readConverter = ReadConverter(property);
                AppendLine($"case {code}:");
                AppendLine($"    {assignCode}{string.Format(readConverter, $"pair.{codeTypeValue}")}{assignSuffix};");
                AppendLine("    break;");
            }

            AppendLine("default:");
            AppendLine("    return false;");
            DecreaseIndent();
            AppendLine("}"); // end switch
            AppendLine();
            AppendLine("return true;");
            DecreaseIndent();
            AppendLine("}"); // end method

            //
            // FromBuffer
            //
            AppendLine();
            AppendLine("internal static DxfObject FromBuffer(DxfCodePairBufferReader buffer)");
            AppendLine("{");
            IncreaseIndent();
            AppendLine("var first = buffer.Peek();");
            AppendLine("buffer.Advance();");
            AppendLine("DxfObject obj;");
            AppendLine("switch (first.StringValue)");
            AppendLine("{");
            IncreaseIndent();
            foreach (var obj in _objects)
            {
                var typeString = TypeString(obj);
                if (!string.IsNullOrEmpty(typeString))
                {
                    AppendLine($"case \"{typeString}\":");
                    AppendLine($"    obj = new {Name(obj)}();");
                    AppendLine("    break;");
                }
            }

            AppendLine("default:");
            AppendLine("    SwallowObject(buffer);");
            AppendLine("    obj = null;");
            AppendLine("    break;");
            DecreaseIndent();
            AppendLine("}"); // end switch
            AppendLine();
            AppendLine("if (obj != null)");
            AppendLine("{");
            AppendLine("    obj = obj.PopulateFromBuffer(buffer);");
            AppendLine("}");
            AppendLine();
            AppendLine("return obj;");
            DecreaseIndent();
            AppendLine("}"); // end method

            DecreaseIndent();
            AppendLine("}"); // end class
            DecreaseIndent();
            FinishFile();
            WriteFile(Path.Combine(_outputDir, "DxfObjectGenerated.cs"));
        }