Configuration options for document generation
        public string ExportToHtml(Database db, TextWriter textWriter, DocumentGeneratorConfiguration docGenConfig)
        {
            if (db == null)
                {
                    throw new ArgumentNullException("db");
                }

                if (textWriter == null)
                {
                    throw new ArgumentNullException("textWriter");
                }

                if (docGenConfig == null)
                {
                    throw new ArgumentNullException("docGenConfig");
                }

                //var sw = new StringWriter();

                using(var hw = new HtmlTextWriter(textWriter))
                {
                    hw.WriteLine("<!DOCTYPE HTML>");
                    hw.RenderBeginTag(HtmlTextWriterTag.Html);

                    hw.RenderBeginTag(HtmlTextWriterTag.Head);

                    hw.RenderBeginTag(HtmlTextWriterTag.Title);

                    hw.WriteEncodedText(db.DatabaseName); //TODO: does Write method escape HTML entities???

                    hw.RenderEndTag(); //title

                    hw.Write("<!-- ");
                    hw.WriteEncodedText(@"
            Bootstrap CSS is included.  Bootstrap is released under the MIT license and is copyright 2014 Twitter.
            The MIT License (MIT)

            Copyright (c) 2011-2014 Twitter, Inc

            Permission is hereby granted, free of charge, to any person obtaining a copy
            of this software and associated documentation files (the ""Software""), to deal
            in the Software without restriction, including without limitation the rights
            to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
            copies of the Software, and to permit persons to whom the Software is
            furnished to do so, subject to the following conditions:

            The above copyright notice and this permission notice shall be included in
            all copies or substantial portions of the Software.

            THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
            IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
            FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
            AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
            LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
            OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
            THE SOFTWARE.");
                    hw.Write(" -->");
                    hw.AddAttribute(HtmlTextWriterAttribute.Type, "text/css");
                    hw.RenderBeginTag(HtmlTextWriterTag.Style);
                    hw.Write(this.baseCss);
                    hw.RenderEndTag(); //style

                    hw.RenderEndTag(); //head

                    hw.RenderBeginTag(HtmlTextWriterTag.Body);

                    hw.RenderBeginTag(HtmlTextWriterTag.H1);

                    hw.WriteEncodedText(String.Format("{0} Database", db.DatabaseName));

                    hw.RenderEndTag(); //h1

                    if (!String.IsNullOrWhiteSpace(db.Description))
                    {
                        hw.RenderBeginTag(HtmlTextWriterTag.P);
                        hw.WriteEncodedText(db.Description);
                        hw.RenderEndTag(); //p
                    }

                    if (db.Schemas != null && db.Schemas.Count > 0)
                    {

                        for (int s = 0; s < db.Schemas.Count; s++)
                        {
                            var schema = db.Schemas[s];
                            bool hasTables = (schema.Tables != null && schema.Tables.Count > 0);

                            if (s > 0)
                            {
                                hw.RenderBeginTag(HtmlTextWriterTag.Hr);
                                hw.RenderEndTag(); //hr
                            }

                            hw.RenderBeginTag(HtmlTextWriterTag.H2);
                            hw.WriteEncodedText(String.Format("{0} (schema)", schema.SchemaName));
                            hw.RenderEndTag(); //h2

                            if (!String.IsNullOrWhiteSpace(schema.Description))
                            {
                                hw.RenderBeginTag(HtmlTextWriterTag.P);
                                hw.WriteEncodedText(schema.Description);
                                hw.RenderEndTag(); //p

                            }

                            hw.AddAttribute(HtmlTextWriterAttribute.Class, "table table-bordered table-striped table-condensed schema-objects-list-container");
                            hw.RenderBeginTag(HtmlTextWriterTag.Table);

                            hw.RenderBeginTag(HtmlTextWriterTag.Thead);

                            hw.RenderBeginTag(HtmlTextWriterTag.Tr);
                            hw.RenderBeginTag(HtmlTextWriterTag.Th);
                            hw.Write("Object Type");
                            hw.RenderEndTag(); //th

                            hw.RenderBeginTag(HtmlTextWriterTag.Th);
                            hw.Write("Count");
                            hw.RenderEndTag(); //th

                            hw.RenderEndTag(); //tr

                            hw.RenderEndTag(); //thead

                            hw.RenderBeginTag(HtmlTextWriterTag.Tbody);

                            hw.RenderBeginTag(HtmlTextWriterTag.Tr);

                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                            hw.Write("Tables");
                            hw.RenderEndTag(); //td

                            hw.AddAttribute(HtmlTextWriterAttribute.Class, "text-right");
                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                            if (hasTables)
                            {
                                hw.WriteEncodedText(schema.Tables.Count.ToString());
                            }
                            else
                            {
                                hw.Write("0");
                            }

                            hw.RenderEndTag(); //td

                            hw.RenderEndTag(); //tr

                            hw.RenderBeginTag(HtmlTextWriterTag.Tr);

                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                            hw.Write("Views");
                            hw.RenderEndTag(); //td

                            hw.AddAttribute(HtmlTextWriterAttribute.Class, "text-right");
                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                            if (schema.Views != null)
                            {
                                hw.WriteEncodedText(schema.Views.Count.ToString());
                            }
                            else
                            {
                                hw.Write("0");
                            }

                            hw.RenderEndTag(); //td

                            hw.RenderEndTag(); //tr

                            hw.RenderBeginTag(HtmlTextWriterTag.Tr);

                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                            hw.Write("Stored procedures");
                            hw.RenderEndTag(); //td

                            hw.AddAttribute(HtmlTextWriterAttribute.Class, "text-right");
                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                            if (schema.StoredProcedures != null)
                            {
                                hw.WriteEncodedText(schema.StoredProcedures.Count.ToString());
                            }
                            else
                            {
                                hw.Write("0");
                            }

                            hw.RenderEndTag(); //td

                            hw.RenderEndTag(); //tr

                            hw.RenderBeginTag(HtmlTextWriterTag.Tr);

                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                            hw.Write("Scalar functions");
                            hw.RenderEndTag(); //td

                            hw.AddAttribute(HtmlTextWriterAttribute.Class, "text-right");
                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                            if (schema.ScalarFunctions != null)
                            {
                                hw.WriteEncodedText(schema.ScalarFunctions.Count.ToString());
                            }
                            else
                            {
                                hw.Write("0");
                            }

                            hw.RenderEndTag(); //td

                            hw.RenderEndTag(); //tr

                            hw.RenderBeginTag(HtmlTextWriterTag.Tr);

                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                            hw.Write("Table functions");
                            hw.RenderEndTag(); //td

                            hw.AddAttribute(HtmlTextWriterAttribute.Class, "text-right");
                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                            if (schema.TableFunctions != null)
                            {
                                hw.WriteEncodedText(schema.TableFunctions.Count.ToString());
                            }
                            else
                            {
                                hw.Write("0");
                            }

                            hw.RenderEndTag(); //td

                            hw.RenderEndTag(); //tr

                            hw.RenderEndTag(); //tbody

                            hw.RenderEndTag(); //table

                            //Render tables
                            if (hasTables)
                            {

                                for (int t = 0; t < schema.Tables.Count; t++)
                                {
                                    var table = schema.Tables[t];

                                    if (docGenConfig.ForeignKeyToTableHyperLink)
                                    {
                                        // create internel hyperlink target
                                        hw.AddAttribute("id", table.GetObjectAnchorId());
                                        hw.RenderBeginTag(HtmlTextWriterTag.A);
                                        hw.RenderEndTag(); //a
                                    }

                                    bool hasIndexes = (table.Indexes != null && table.Indexes.Count > 0);

                                    hw.RenderBeginTag(HtmlTextWriterTag.H3);
                                    hw.WriteEncodedText(String.Format("{0}.{1} (table)", schema.SchemaName, table.TableName));
                                    hw.RenderEndTag(); //h3

                                    hw.AddAttribute(HtmlTextWriterAttribute.Class, "table table-bordered table-striped table-condensed");
                                    hw.RenderBeginTag(HtmlTextWriterTag.Table);

                                    if (!String.IsNullOrWhiteSpace(table.Description))
                                    {
                                        hw.RenderBeginTag(HtmlTextWriterTag.Caption);
                                        hw.WriteEncodedText(table.Description);
                                        hw.RenderEndTag(); //caption
                                    }

                                    hw.RenderBeginTag(HtmlTextWriterTag.Thead);
                                    hw.RenderBeginTag(HtmlTextWriterTag.Tr);

                                    hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                    hw.Write("Column Name");
                                    hw.RenderEndTag(); //th

                                    hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                    hw.Write("System Data Type");

                                    if (table.ContainsColumnsWithUserDefinedDataType())
                                    {
                                        hw.Write(" / User Defined Type");
                                    }

                                    hw.RenderEndTag(); //th

                                    hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                    hw.Write("Size");
                                    hw.RenderEndTag(); //th

                                    hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                    hw.Write("Allow Null");
                                    hw.RenderEndTag(); //th

                                    hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                    hw.Write("Default");
                                    hw.RenderEndTag(); //th

                                    hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                    hw.Write("Is Computed");
                                    hw.RenderEndTag(); //th

                                    hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                    hw.Write("Description");
                                    hw.RenderEndTag(); //th

                                    hw.RenderEndTag(); //tr

                                    hw.RenderEndTag(); //thead

                                    hw.RenderBeginTag(HtmlTextWriterTag.Tbody);

                                    for (int c = 0; c < table.Columns.Count; c++)
                                    {

                                        var col = table.Columns[c];

                                        bool colHasDefaultValue = (col.DefaultValue != null);

                                        hw.RenderBeginTag(HtmlTextWriterTag.Tr);

                                        hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                        hw.WriteEncodedText(col.ColumnName);
                                        hw.RenderEndTag();  //td

                                        hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                        hw.WriteEncodedText(col.BaseDataTypeName);
                                        if (col.IsIdentity)
                                        {
                                            hw.WriteEncodedText(" (identity)");
                                        }

                                        if (col.IsUserDefinedType)
                                        {
                                            hw.Write(" / ");
                                            hw.WriteEncodedText(col.TypeName);
                                        }

                                        hw.RenderEndTag();  //td

                                        hw.AddAttribute(HtmlTextWriterAttribute.Class, "text-right");
                                        hw.RenderBeginTag(HtmlTextWriterTag.Td);

                                        //show precision, scale when appliable, else use maxlength
                                        if (col.Precision.HasValue && col.Scale.HasValue && col.Precision > 0)
                                        {
                                            hw.WriteEncodedText(String.Format("{0},{1}",col.Precision.Value, col.Scale.Value));
                                        }
                                        else
                                        {
                                            if (col.MaximumLength.HasValue && col.MaximumLength.Value != -1)
                                            {
                                                hw.WriteEncodedText(col.MaximumLength.ToString());
                                            }

                                        }

                                        hw.RenderEndTag();  //td

                                        hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                        hw.WriteEncodedText(col.AllowNull ? "Yes" : "No");
                                        hw.RenderEndTag(); //td

                                        if (!colHasDefaultValue)
                                        {
                                            hw.AddAttribute(HtmlTextWriterAttribute.Class, "no-default");
                                        }

                                        hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                        hw.WriteEncodedText(colHasDefaultValue ? col.DefaultValue : "none");
                                        hw.RenderEndTag(); //td

                                        hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                        hw.WriteEncodedText(col.IsComputed ? "Yes" : "No");
                                        hw.RenderEndTag(); //td

                                        hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                        hw.WriteEncodedText(col.Description ?? String.Empty);
                                        hw.RenderEndTag(); //td

                                        hw.RenderEndTag(); //tr

                                    } //for column loop

                                    hw.RenderEndTag(); //tbody

                                    hw.RenderEndTag(); //table

                                    if (hasIndexes)
                                    {
                                        hw.AddAttribute(HtmlTextWriterAttribute.Class, "table table-bordered table-striped table-condensed");
                                        hw.RenderBeginTag(HtmlTextWriterTag.Table);

                                        hw.RenderBeginTag(HtmlTextWriterTag.Caption);
                                        hw.WriteEncodedText(String.Format("Indexes on {0}", table.TableName));
                                        hw.RenderEndTag(); //caption

                                        hw.RenderBeginTag(HtmlTextWriterTag.Thead);
                                        hw.RenderBeginTag(HtmlTextWriterTag.Tr);

                                        hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                        hw.Write("Index Name");
                                        hw.RenderEndTag(); //th

                                        hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                        hw.Write("Description");
                                        hw.RenderEndTag(); //th

                                        hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                        hw.Write("Is Primary Key");
                                        hw.RenderEndTag(); //th

                                        hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                        hw.Write("Is Unique");
                                        hw.RenderEndTag(); //th

                                        hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                        hw.Write("Index Type");
                                        hw.RenderEndTag(); //th

                                        hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                        hw.Write("Columns");
                                        hw.RenderEndTag(); //th

                                        hw.RenderEndTag(); //tr
                                        hw.RenderEndTag(); //thead

                                        hw.RenderBeginTag(HtmlTextWriterTag.Tbody);

                                        for (int i = 0; i < table.Indexes.Count; i++)
                                        {
                                            var index = table.Indexes[i];

                                            hw.RenderBeginTag(HtmlTextWriterTag.Tr);

                                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                            hw.WriteEncodedText(index.IndexName);
                                            hw.RenderEndTag(); //td

                                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                            hw.WriteEncodedText(index.Description ?? String.Empty);
                                            hw.RenderEndTag(); //td

                                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                            hw.WriteEncodedText(index.IsPrimaryKey.ToYesNo());
                                            hw.RenderEndTag(); //td

                                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                            hw.WriteEncodedText(index.IsUnique.ToYesNo());
                                            hw.RenderEndTag(); //td

                                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                            hw.WriteEncodedText(index.IndexTypeDescription);
                                            hw.RenderEndTag(); //td

                                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                            hw.WriteEncodedText(String.Join(", ", index.ColumnNames.ToArray()));
                                            hw.RenderEndTag(); //td

                                            hw.RenderEndTag(); //tr
                                        }

                                        hw.RenderEndTag(); //tbody

                                        hw.RenderEndTag(); //table

                                    } //end indexes

                                    if (table.ForeignKeys != null && table.ForeignKeys.Count > 0)
                                    {
                                        hw.AddAttribute(HtmlTextWriterAttribute.Class, "table table-bordered table-striped table-condensed");
                                        hw.RenderBeginTag(HtmlTextWriterTag.Table);

                                        hw.RenderBeginTag(HtmlTextWriterTag.Caption);
                                        hw.WriteEncodedText(String.Format("Foreign Keys in {0}", table.TableName));
                                        hw.RenderEndTag(); //caption

                                        hw.RenderBeginTag(HtmlTextWriterTag.Thead);

                                        hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                        hw.Write("Foreign Key Name");
                                        hw.RenderEndTag(); //th

                                        hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                        hw.Write("Columns");
                                        hw.RenderEndTag(); //th

                                        hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                        hw.Write("References Table (Columns)");
                                        hw.RenderEndTag(); //th

                                        hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                        hw.Write("Description");
                                        hw.RenderEndTag(); //th

                                        hw.RenderEndTag(); //thead

                                        hw.RenderBeginTag(HtmlTextWriterTag.Tbody);

                                        for (int f = 0; f < table.ForeignKeys.Count; f++)
                                        {
                                            var fk = table.ForeignKeys[f];

                                            hw.RenderBeginTag(HtmlTextWriterTag.Tr);

                                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                            hw.WriteEncodedText(fk.ForeignKeyName);
                                            hw.RenderEndTag(); //td

                                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                            hw.WriteEncodedText(String.Join(", ", fk.GetForeignKeyParentColumnNames()));
                                            hw.RenderEndTag(); //td

                                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                            //hw.WriteEncodedText(String.Format("{0}.{1} ({2})", fk.ReferencedObjectSchemaName, fk.ReferencedObjectName, String.Join(", ",fk.GetForeignKeyReferenceColumnNames())));

                                            if (docGenConfig.ForeignKeyToTableHyperLink)
                                            {
                                                hw.AddAttribute("href", fk.GetFkTargetAnchorId());
                                                hw.RenderBeginTag(HtmlTextWriterTag.A);
                                                hw.WriteEncodedText(String.Format("{0}.{1} ({2})", fk.ReferencedObjectSchemaName, fk.ReferencedObjectName, String.Join(", ", fk.GetForeignKeyReferenceColumnNames())));
                                                //hw.WriteEncodedText("table ->");
                                                hw.RenderEndTag(); //a
                                            }
                                            else
                                            {
                                                hw.WriteEncodedText(String.Format("{0}.{1} ({2})", fk.ReferencedObjectSchemaName, fk.ReferencedObjectName, String.Join(", ", fk.GetForeignKeyReferenceColumnNames())));
                                            }

                                            hw.RenderEndTag(); //td

                                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                            hw.WriteEncodedText(fk.Description ?? String.Empty);
                                            hw.RenderEndTag(); //td

                                            hw.RenderEndTag(); //tr
                                        }

                                        hw.RenderEndTag(); //tbody

                                        hw.RenderEndTag(); //table

                                    } //end foreign keys

                                } //end for table loop

                            }

                            if (schema.Views != null && schema.Views.Count > 0)
                            {
                                for (int v = 0; v < schema.Views.Count; v++)
                                {
                                    var view = schema.Views[v];

                                    hw.RenderBeginTag(HtmlTextWriterTag.H3);
                                    hw.WriteEncodedText(String.Format("{0}.{1} (view)", schema.SchemaName, view.ViewName));
                                    hw.RenderEndTag(); //h3

                                    //TODO: add columns and indexes for view, use view.Description as table caption
                                    hw.AddAttribute(HtmlTextWriterAttribute.Class, "table table-bordered table-striped table-condensed");
                                    hw.RenderBeginTag(HtmlTextWriterTag.Table);

                                    if (!String.IsNullOrWhiteSpace(view.Description))
                                    {
                                        hw.RenderBeginTag(HtmlTextWriterTag.Caption);
                                        hw.WriteEncodedText(view.Description);
                                        hw.RenderEndTag(); //caption
                                    }

                                    hw.RenderBeginTag(HtmlTextWriterTag.Thead);
                                    hw.RenderBeginTag(HtmlTextWriterTag.Tr);

                                    hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                    hw.Write("Column Name");
                                    hw.RenderEndTag(); //th

                                    hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                    hw.Write("System Data Type");

                                    if (view.ContainsColumnsWithUserDefinedDataType())
                                    {
                                        hw.Write(" / User Defined Type");
                                    }

                                    hw.RenderEndTag(); //th

                                    hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                    hw.Write("Size");
                                    hw.RenderEndTag(); //th

                                    hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                    hw.Write("Allow Null");
                                    hw.RenderEndTag(); //th

                                    hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                    hw.Write("Default");
                                    hw.RenderEndTag(); //th

                                    hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                    hw.Write("Is Computed");
                                    hw.RenderEndTag(); //th

                                    hw.RenderEndTag(); //tr

                                    hw.RenderEndTag(); //thead

                                    hw.RenderBeginTag(HtmlTextWriterTag.Tbody);

                                    for (int c = 0; c < view.Columns.Count; c++)
                                    {

                                        var col = view.Columns[c];

                                        bool colHasDefaultValue = (col.DefaultValue != null);

                                        hw.RenderBeginTag(HtmlTextWriterTag.Tr);

                                        hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                        hw.WriteEncodedText(col.ColumnName);
                                        hw.RenderEndTag();  //td

                                        hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                        hw.WriteEncodedText(col.BaseDataTypeName);
                                        if (col.IsIdentity)
                                        {
                                            hw.WriteEncodedText(" (identity)");
                                        }

                                        if (col.IsUserDefinedType)
                                        {
                                            hw.Write(" / ");
                                            hw.WriteEncodedText(col.TypeName);
                                        }
                                        hw.RenderEndTag();  //td

                                        hw.AddAttribute(HtmlTextWriterAttribute.Class, "text-right");
                                        hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                        //show precision, scale when appliable
                                        if (col.Precision.HasValue && col.Scale.HasValue && col.Precision > 0)
                                        {
                                            hw.WriteEncodedText(String.Format("{0},{1}",col.Precision.Value, col.Scale.Value));
                                        }
                                        else
                                        {
                                            if (col.MaximumLength.HasValue && col.MaximumLength.Value != -1)
                                            {
                                                hw.WriteEncodedText(col.MaximumLength.ToString());
                                            }
                                            //else
                                            //{
                                            //    hw.Write("n/a");
                                            //}
                                        }

                                        hw.RenderEndTag();  //td

                                        hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                        hw.WriteEncodedText(col.AllowNull.ToYesNo());
                                        hw.RenderEndTag(); //td

                                        if (!colHasDefaultValue)
                                        {
                                            hw.AddAttribute(HtmlTextWriterAttribute.Class, "no-default");
                                        }

                                        hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                        hw.WriteEncodedText(colHasDefaultValue ? col.DefaultValue : "none");
                                        hw.RenderEndTag(); //td

                                        hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                        hw.WriteEncodedText(col.IsComputed.ToYesNo());
                                        hw.RenderEndTag(); //td

                                        hw.RenderEndTag(); //tr

                                    } //for column loop

                                    hw.RenderEndTag(); //tbody

                                    hw.RenderEndTag(); //table

                                    if (view.IsIndexedView)
                                    {
                                        hw.AddAttribute(HtmlTextWriterAttribute.Class, "table table-bordered table-striped table-condensed");
                                        hw.RenderBeginTag(HtmlTextWriterTag.Table);

                                        hw.RenderBeginTag(HtmlTextWriterTag.Caption);
                                        hw.WriteEncodedText(String.Format("Indexes on {0}", view.ViewName));
                                        hw.RenderEndTag(); //caption

                                        hw.RenderBeginTag(HtmlTextWriterTag.Thead);
                                        hw.RenderBeginTag(HtmlTextWriterTag.Tr);

                                        hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                        hw.Write("Index Name");
                                        hw.RenderEndTag(); //th

                                        hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                        hw.Write("Description");
                                        hw.RenderEndTag(); //th

                                        hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                        hw.Write("Is Unique");
                                        hw.RenderEndTag(); //th

                                        hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                        hw.Write("Index Type");
                                        hw.RenderEndTag(); //th

                                        hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                        hw.Write("Columns");
                                        hw.RenderEndTag(); //th

                                        hw.RenderEndTag(); //tr
                                        hw.RenderEndTag(); //thead

                                        hw.RenderBeginTag(HtmlTextWriterTag.Tbody);

                                        for (int i = 0; i < view.Indexes.Count; i++)
                                        {
                                            var index = view.Indexes[i];

                                            hw.RenderBeginTag(HtmlTextWriterTag.Tr);

                                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                            hw.WriteEncodedText(index.IndexName);
                                            hw.RenderEndTag(); //td

                                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                            hw.WriteEncodedText(index.Description ?? String.Empty);
                                            hw.RenderEndTag(); //td

                                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                            hw.WriteEncodedText(index.IsUnique.ToYesNo());
                                            hw.RenderEndTag(); //td

                                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                            hw.WriteEncodedText(index.IndexTypeDescription);
                                            hw.RenderEndTag(); //td

                                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                            hw.WriteEncodedText(String.Join(", ", index.ColumnNames.ToArray()));
                                            hw.RenderEndTag(); //td

                                            hw.RenderEndTag(); //tr
                                        }

                                        hw.RenderEndTag(); //tbody

                                        hw.RenderEndTag(); //table

                                    } //end indexes

                                } //end views loop

                            }//end views

                            if (schema.StoredProcedures != null && schema.StoredProcedures.Count > 0)
                            {
                                for (int r = 0; r < schema.StoredProcedures.Count; r++)
                                {
                                    var sproc = schema.StoredProcedures[r];

                                    hw.RenderBeginTag(HtmlTextWriterTag.H3);
                                    hw.WriteEncodedText(String.Format("{0}.{1} (stored procedure)", schema.SchemaName,sproc.ProcedureName) );
                                    hw.RenderEndTag(); //h3

                                    if (!String.IsNullOrWhiteSpace(sproc.Description))
                                    {
                                        hw.RenderBeginTag(HtmlTextWriterTag.P);
                                        hw.WriteEncodedText(sproc.Description);
                                        hw.RenderEndTag(); //p
                                    }

                                    if (sproc.Parameters != null && sproc.Parameters.Count > 0)
                                    {
                                        hw.AddAttribute(HtmlTextWriterAttribute.Class, "table table-bordered table-striped table-condensed");
                                        hw.RenderBeginTag(HtmlTextWriterTag.Table);

                                        hw.RenderBeginTag(HtmlTextWriterTag.Caption);
                                        hw.Write("Parameters");
                                        hw.RenderEndTag();//caption

                                        hw.RenderBeginTag(HtmlTextWriterTag.Thead);

                                        hw.RenderBeginTag(HtmlTextWriterTag.Tr);

                                        hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                        hw.Write("Paramater Name");
                                        hw.RenderEndTag(); //th

                                        hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                        hw.Write("System Data Type");
                                        hw.RenderEndTag(); //th

                                        hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                        hw.Write("Size");
                                        hw.RenderEndTag(); //th

                                        hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                        hw.Write("Direction");
                                        hw.RenderEndTag(); //th

                                        hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                        hw.Write("Description");
                                        hw.RenderEndTag(); //th

                                        hw.RenderEndTag(); //tr

                                        hw.RenderEndTag(); //thead

                                        hw.RenderBeginTag(HtmlTextWriterTag.Tbody);

                                        for (int m = 0; m < sproc.Parameters.Count; m++)
                                        {
                                            var param = sproc.Parameters[m];

                                            hw.RenderBeginTag(HtmlTextWriterTag.Tr);

                                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                            hw.WriteEncodedText(param.ParameterName);
                                            hw.RenderEndTag(); //td

                                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                            hw.WriteEncodedText(param.DataType);
                                            hw.RenderEndTag(); //td

                                            hw.AddAttribute(HtmlTextWriterAttribute.Class, "text-right");
                                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                            //show precision, scale when appliable
                                            if (param.Precision.HasValue && param.Scale.HasValue && param.Precision > 0)
                                            {
                                                hw.WriteEncodedText(String.Format("{0},{1}", param.Precision.Value, param.Scale.Value));
                                            }
                                            else
                                            {
                                                if (param.MaximumLength.HasValue && param.MaximumLength.Value != -1)
                                                {
                                                    hw.WriteEncodedText(param.MaximumLength.ToString());
                                                }
                                                //else
                                                //{
                                                //    hw.Write("n/a");
                                                //}
                                            }

                                            hw.RenderEndTag(); //td

                                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                            hw.WriteEncodedText(param.Direction);
                                            hw.RenderEndTag(); //td

                                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                            hw.WriteEncodedText(param.Description ?? String.Empty);
                                            hw.RenderEndTag(); //td

                                            hw.RenderEndTag(); //tr

                                        } //end parameter loop

                                        hw.RenderEndTag(); //tbody

                                        hw.RenderEndTag(); //table

                                    }  //end sproc parameters

                                } //end sproc loop

                            }// end stored procedures

                            if (schema.ScalarFunctions != null && schema.ScalarFunctions.Count > 0)
                            {
                                for (int f = 0; f < schema.ScalarFunctions.Count; f++)
                                {
                                    var func = schema.ScalarFunctions[f];

                                    hw.RenderBeginTag(HtmlTextWriterTag.H3);
                                    hw.WriteEncodedText(String.Format("{0}.{1} (scalar function)", schema.SchemaName, func.FunctionName));
                                    hw.RenderEndTag(); //h3

                                    if (!String.IsNullOrWhiteSpace(func.Description))
                                    {
                                        hw.RenderBeginTag(HtmlTextWriterTag.P);
                                        hw.WriteEncodedText(func.Description);
                                        hw.RenderEndTag(); //p
                                    }

                                    if (!String.IsNullOrEmpty(func.ReturnDataType))
                                    {

                                        hw.RenderBeginTag(HtmlTextWriterTag.P);
                                        hw.Write("Returns ");
                                        hw.AddAttribute(HtmlTextWriterAttribute.Class, "return-type");
                                        hw.RenderBeginTag(HtmlTextWriterTag.Span);
                                        hw.WriteEncodedText(func.GetReturnTypeDisplayText());
                                        hw.RenderEndTag(); //span
                                        hw.RenderEndTag(); //p

                                    }

                                    if (func.Parameters != null && func.Parameters.Count > 0)
                                    {
                                        hw.AddAttribute(HtmlTextWriterAttribute.Class, "table table-bordered table-striped table-condensed");
                                        hw.RenderBeginTag(HtmlTextWriterTag.Table);

                                        hw.RenderBeginTag(HtmlTextWriterTag.Caption);
                                        hw.Write("Parameters");
                                        hw.RenderEndTag();//caption

                                        hw.RenderBeginTag(HtmlTextWriterTag.Thead);

                                        hw.RenderBeginTag(HtmlTextWriterTag.Tr);

                                        hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                        hw.Write("Paramater Name");
                                        hw.RenderEndTag(); //th

                                        hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                        hw.Write("System Data Type");
                                        hw.RenderEndTag(); //th

                                        hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                        hw.Write("Size");
                                        hw.RenderEndTag(); //th

                                        hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                        hw.Write("Description");
                                        hw.RenderEndTag(); //th

                                        hw.RenderEndTag(); //tr

                                        hw.RenderEndTag(); //thead

                                        hw.RenderBeginTag(HtmlTextWriterTag.Tbody);

                                        for (int m = 0; m < func.Parameters.Count; m++)
                                        {
                                            var param = func.Parameters[m];

                                            hw.RenderBeginTag(HtmlTextWriterTag.Tr);

                                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                            hw.WriteEncodedText(param.ParameterName);
                                            hw.RenderEndTag(); //td

                                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                            hw.WriteEncodedText(param.DataType);
                                            hw.RenderEndTag(); //td

                                            hw.AddAttribute(HtmlTextWriterAttribute.Class, "text-right");
                                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                            //show precision, scale when appliable
                                            if (param.Precision.HasValue && param.Scale.HasValue && param.Precision > 0)
                                            {
                                                hw.WriteEncodedText(String.Format("{0},{1}", param.Precision.Value, param.Scale.Value));
                                            }
                                            else
                                            {
                                                if (param.MaximumLength.HasValue && param.MaximumLength.Value != -1)
                                                {
                                                    hw.WriteEncodedText(param.MaximumLength.ToString());
                                                }

                                            }

                                            hw.RenderEndTag(); //td

                                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                            hw.WriteEncodedText(param.Description ?? String.Empty);
                                            hw.RenderEndTag(); //td

                                            hw.RenderEndTag(); //tr

                                        } //end scalar func parameter loop

                                        hw.RenderEndTag(); //tbody

                                        hw.RenderEndTag(); //table

                                    } //end scalar params
                                }

                            } //end scalar functions

                            if (schema.TableFunctions != null && schema.TableFunctions.Count > 0)
                            {
                                for (int t = 0; t < schema.TableFunctions.Count; t++)
                                {
                                    var tFunc = schema.TableFunctions[t];

                                    hw.RenderBeginTag(HtmlTextWriterTag.H3);
                                    hw.WriteEncodedText(String.Format("{0}.{1} (table function)", schema.SchemaName, tFunc.FunctionName));
                                    hw.RenderEndTag(); //h3

                                    if (!String.IsNullOrWhiteSpace(tFunc.Description))
                                    {
                                        hw.RenderBeginTag(HtmlTextWriterTag.P);
                                        hw.WriteEncodedText(tFunc.Description);
                                        hw.RenderEndTag(); //p
                                    }

                                    if (tFunc.Parameters != null && tFunc.Parameters.Count > 0)
                                    {
                                        if (tFunc.Parameters != null && tFunc.Parameters.Count > 0)
                                        {
                                            hw.AddAttribute(HtmlTextWriterAttribute.Class, "table table-bordered table-striped table-condensed");
                                            hw.RenderBeginTag(HtmlTextWriterTag.Table);

                                            hw.RenderBeginTag(HtmlTextWriterTag.Caption);
                                            hw.Write("Parameters");
                                            hw.RenderEndTag();//caption

                                            hw.RenderBeginTag(HtmlTextWriterTag.Thead);

                                            hw.RenderBeginTag(HtmlTextWriterTag.Tr);

                                            hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                            hw.Write("Paramater Name");
                                            hw.RenderEndTag(); //th

                                            hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                            hw.Write("System Data Type");
                                            hw.RenderEndTag(); //th

                                            hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                            hw.Write("Size");
                                            hw.RenderEndTag(); //th

                                            hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                            hw.Write("Description");
                                            hw.RenderEndTag(); //th

                                            hw.RenderEndTag(); //tr

                                            hw.RenderEndTag(); //thead

                                            hw.RenderBeginTag(HtmlTextWriterTag.Tbody);

                                            for (int m = 0; m < tFunc.Parameters.Count; m++)
                                            {
                                                var param = tFunc.Parameters[m];

                                                hw.RenderBeginTag(HtmlTextWriterTag.Tr);

                                                hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                                hw.WriteEncodedText(param.ParameterName);
                                                hw.RenderEndTag(); //td

                                                hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                                hw.WriteEncodedText(param.DataType);
                                                hw.RenderEndTag(); //td

                                                hw.AddAttribute(HtmlTextWriterAttribute.Class, "text-right");
                                                hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                                //show precision, scale when appliable
                                                if (param.Precision.HasValue && param.Scale.HasValue && param.Precision > 0)
                                                {
                                                    hw.WriteEncodedText(String.Format("{0},{1}", param.Precision.Value, param.Scale.Value));
                                                }
                                                else
                                                {
                                                    if (param.MaximumLength.HasValue && param.MaximumLength.Value != -1)
                                                    {
                                                        hw.WriteEncodedText(param.MaximumLength.ToString());
                                                    }

                                                }

                                                hw.RenderEndTag(); //td

                                                hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                                hw.WriteEncodedText(param.Description ?? String.Empty);
                                                hw.RenderEndTag(); //td

                                                hw.RenderEndTag(); //tr

                                            } //end table func parameter loop

                                            hw.RenderEndTag(); //tbody

                                            hw.RenderEndTag(); //table

                                        }

                                    }//end table function parameter

                                    if (tFunc.Columns != null && tFunc.Columns.Count > 0)
                                    {

                                        hw.AddAttribute(HtmlTextWriterAttribute.Class, "table table-bordered table-striped table-condensed schema-objects-list-container");
                                        hw.RenderBeginTag(HtmlTextWriterTag.Table);

                                        hw.RenderBeginTag(HtmlTextWriterTag.Thead);

                                        hw.RenderBeginTag(HtmlTextWriterTag.Tr);

                                        hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                        hw.Write("Column Name");
                                        hw.RenderEndTag(); //th

                                        hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                        hw.Write("System Data Type");
                                        hw.RenderEndTag(); //th

                                        hw.RenderBeginTag(HtmlTextWriterTag.Th);
                                        hw.Write("Allow Null");
                                        hw.RenderEndTag(); //th

                                        hw.RenderEndTag(); //tr

                                        hw.RenderEndTag(); //thead

                                        hw.RenderBeginTag(HtmlTextWriterTag.Tbody);

                                        for (int c = 0; c < tFunc.Columns.Count; c++)
                                        {
                                            var col = tFunc.Columns[c];

                                            hw.RenderBeginTag(HtmlTextWriterTag.Tr);

                                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                            hw.WriteEncodedText(col.ColumnName);
                                            hw.RenderEndTag(); //td

                                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                            hw.WriteEncodedText(col.BaseDataTypeName);
                                            hw.RenderEndTag(); //td

                                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                                            hw.WriteEncodedText(col.AllowNull.ToYesNo());
                                            hw.RenderEndTag(); //td

                                            hw.RenderEndTag(); //tr

                                        } //end table function column loop

                                        hw.RenderEndTag(); //tbody

                                        hw.RenderEndTag(); //table

                                    } //end table function columns

                                }

                            } //end table functions

                        }// end for schema loop

                    }

                    //display design issues
                    if (docGenConfig.CheckForDesignIssues && db.DesignIssueWarnings.HasAny())
                    {
                        hw.RenderBeginTag(HtmlTextWriterTag.H2);
                        hw.WriteEncodedText(String.Format("Design Issue Warnings ({0})", db.DesignIssueWarnings.Count));
                        hw.RenderEndTag(); //h2

                        hw.AddAttribute(HtmlTextWriterAttribute.Class, "table table-bordered table-striped table-condensed");
                        hw.RenderBeginTag(HtmlTextWriterTag.Table);

                         hw.RenderBeginTag(HtmlTextWriterTag.Thead);

                        hw.RenderBeginTag(HtmlTextWriterTag.Tr);

                        hw.RenderBeginTag(HtmlTextWriterTag.Th);
                        hw.Write("Warning Description");
                        hw.RenderEndTag(); //th

                        hw.RenderBeginTag(HtmlTextWriterTag.Th);
                        hw.Write("Reference URL");
                        hw.RenderEndTag(); //th

                        hw.RenderBeginTag(HtmlTextWriterTag.Th);
                        hw.Write("Object(s)");
                        hw.RenderEndTag(); //th

                        hw.RenderEndTag(); //tr

                        hw.RenderEndTag(); //thead

                        hw.RenderBeginTag(HtmlTextWriterTag.Tbody);

                        foreach(var warn in db.DesignIssueWarnings)
                        {

                            hw.RenderBeginTag(HtmlTextWriterTag.Tr);

                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                            hw.WriteEncodedText(warn.Description);
                            hw.RenderEndTag(); //td

                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                            if(warn.ReferenceUrl != null)
                            {
                                hw.AddAttribute("href", warn.ReferenceUrl.ToString());
                                hw.RenderBeginTag(HtmlTextWriterTag.A);
                                hw.WriteEncodedText(warn.ReferenceUrl.ToString());
                                hw.RenderEndTag(); //a
                            }
                            hw.RenderEndTag(); //td

                            hw.RenderBeginTag(HtmlTextWriterTag.Td);
                            foreach(IDbObject obj in warn.DatabaseObjects)
                            {
                                //hw.WriteEncodedText(obj.ObjectFullDisplayName);  //TODO: add internal hyperlinking
                                hw.WriteEncodedText(String.Format("{0} ( {1} )", obj.ObjectFullDisplayName, obj.ObjectTypeDisplayText));
                                hw.WriteBreak(); //br

                            }
                            //hw.WriteEncodedText(warn.Description);
                            hw.RenderEndTag(); //td

                            hw.RenderEndTag(); //tr
                        }

                        hw.RenderEndTag(); // tbody

                        hw.RenderEndTag(); //table
                    }

                    //footer
                    hw.RenderBeginTag(HtmlTextWriterTag.P);
                    hw.WriteEncodedText(String.Format("Documentation created using SQL Server Database Documentation Generator version {0}", this.appVersion));

                    hw.WriteBreak(); //br

                    hw.AddAttribute(HtmlTextWriterAttribute.Href, this.projectUrl);
                    hw.RenderBeginTag(HtmlTextWriterTag.A);
                    hw.WriteEncodedText(this.projectUrl);
                    hw.RenderEndTag(); //a

                    hw.RenderEndTag(); //p

                    hw.RenderEndTag(); //body

                    hw.RenderEndTag(); //html
                }

                return textWriter.ToString();
        }
コード例 #2
0
        private DocumentGeneratorConfiguration createDocumentGeneratorConfigurationFroUi()
        {
            var config = new DocumentGeneratorConfiguration();

            config.ForeignKeyToTableHyperLink = this.chkFkToTableHyperLink.Checked;

            config.CheckForDesignIssues = this.chkCheckForDatabaseDesignIssues.Checked;

            return config;
        }