8190295: Introduce a new Table builder class
authorjjg
Thu, 16 Nov 2017 15:01:45 -0800
changeset 47846 4e78aba768f0
parent 47845 2ac93efc62ed
child 47847 7640bc1eb94f
8190295: Introduce a new Table builder class Reviewed-by: bpatel, ksrini
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractIndexWriter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractModuleIndexWriter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractPackageIndexWriter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractTreeWriter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeFieldWriterImpl.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeOptionalMemberWriterImpl.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriterImpl.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DeprecatedListWriter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/EnumConstantWriterImpl.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FieldWriterImpl.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FrameOutputWriter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HelpWriter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialFieldWriter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialMethodWriter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleFrameWriter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleIndexWriter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/NestedClassWriterImpl.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageFrameWriter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexWriter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageTreeWriter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SerializedFormWriterImpl.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SingleIndexWriter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SourceToHTMLConverter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SplitIndexWriter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SubWriterHolderWriter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TableHeader.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TreeWriter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Table.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/TableHeader.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/package-info.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/MemberSummaryWriter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MemberSummaryBuilder.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/GroupTypes.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/MethodTypes.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/ModulePackageTypes.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/TableTabTypes.java
test/langtools/jdk/javadoc/doclet/testDeprecatedDocs/TestDeprecatedDocs.java
test/langtools/jdk/javadoc/doclet/testModules/TestModules.java
test/langtools/jdk/javadoc/doclet/testOptions/help.html
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractIndexWriter.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractIndexWriter.java	Thu Nov 16 15:01:45 2017 -0800
@@ -364,7 +364,7 @@
         List<? extends DocTree> tags;
         Content span = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, getDeprecatedPhrase(element));
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
-        div.addStyle(HtmlStyle.deprecationBlock);
+        div.setStyle(HtmlStyle.deprecationBlock);
         if (utils.isDeprecated(element)) {
             div.addContent(span);
             tags = utils.getBlockTags(element, DocTree.Kind.DEPRECATED);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java	Thu Nov 16 15:01:45 2017 -0800
@@ -25,6 +25,9 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
+
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -36,7 +39,7 @@
 import javax.lang.model.type.TypeMirror;
 
 import com.sun.source.doctree.DocTree;
-import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr;
+import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
@@ -46,7 +49,6 @@
 import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter;
 import jdk.javadoc.internal.doclets.toolkit.Resources;
 import jdk.javadoc.internal.doclets.toolkit.taglets.DeprecatedTaglet;
-import jdk.javadoc.internal.doclets.toolkit.util.MethodTypes;
 import jdk.javadoc.internal.doclets.toolkit.util.Utils;
 import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
 
@@ -74,9 +76,6 @@
     protected final Resources resources;
 
     protected final TypeElement typeElement;
-    protected Map<String, Integer> typeMap = new LinkedHashMap<>();
-    protected Set<MethodTypes> methodTypes = EnumSet.noneOf(MethodTypes.class);
-    private int methodTypesOr = 0;
     public final boolean nodepr;
 
     protected boolean printedSummaryHeader = false;
@@ -109,14 +108,7 @@
      *
      * @return a string for the table summary
      */
-    public abstract String getTableSummary();
-
-    /**
-     * Get the caption for the member summary table.
-     *
-     * @return a string for the table caption
-     */
-    public abstract Content getCaption();
+    private String getTableSummaryX() { return null; }
 
     /**
      * Get the summary table header for the member.
@@ -126,6 +118,27 @@
      */
     public abstract TableHeader getSummaryTableHeader(Element member);
 
+    private Table summaryTable;
+
+    private Table getSummaryTable() {
+        if (summaryTable == null) {
+            summaryTable = createSummaryTable();
+        }
+        return summaryTable;
+    }
+
+    /**
+     * Create the summary table for this element.
+     * The table should be created and initialized if needed, and configured
+     * so that it is ready to add content with {@link Table#addRows(Content[])}
+     * and similar methods.
+     *
+     * @return the summary table
+     */
+    protected abstract Table createSummaryTable();
+
+
+
     /**
      * Add inherited summary label for the member.
      *
@@ -229,7 +242,7 @@
      * Add the modifier for the member. The modifiers are ordered as specified
      * by <em>The Java Language Specification</em>.
      *
-     * @param member the member for which teh modifier will be added.
+     * @param member the member for which the modifier will be added.
      * @param htmltree the content tree to which the modifier information will be added.
      */
     protected void addModifiers(Element member, Content htmltree) {
@@ -420,51 +433,41 @@
         List<? extends Element> members = mems;
         boolean printedUseTableHeader = false;
         if (members.size() > 0) {
-            Content caption = writer.getTableCaption(heading);
-            Content table = (configuration.isOutputHtml5())
-                    ? HtmlTree.TABLE(HtmlStyle.useSummary, caption)
-                    : HtmlTree.TABLE(HtmlStyle.useSummary, tableSummary, caption);
-            Content tbody = new HtmlTree(HtmlTag.TBODY);
-            boolean altColor = true;
+            Table useTable = new Table(configuration.htmlVersion, HtmlStyle.useSummary)
+                    .setSummary(tableSummary)
+                    .setCaption(heading)
+                    .setRowScopeColumn(1)
+                    .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colSecond, HtmlStyle.colLast);
             for (Element element : members) {
-                TypeElement te = utils.getEnclosingTypeElement(element);
+                TypeElement te = (typeElement == null)
+                        ? utils.getEnclosingTypeElement(element)
+                        : typeElement;
                 if (!printedUseTableHeader) {
-                    table.addContent(getSummaryTableHeader(element).toContent());
+                    useTable.setHeader(getSummaryTableHeader(element));
                     printedUseTableHeader = true;
                 }
-                HtmlTree tr = new HtmlTree(HtmlTag.TR);
-                tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
-                altColor = !altColor;
-                HtmlTree tdFirst = new HtmlTree(HtmlTag.TD);
-                tdFirst.addStyle(HtmlStyle.colFirst);
-                writer.addSummaryType(this, element, tdFirst);
-                tr.addContent(tdFirst);
-                HtmlTree thType = new HtmlTree(HtmlTag.TH);
-                thType.addStyle(HtmlStyle.colSecond);
-                thType.addAttr(HtmlAttr.SCOPE, "row");
+                Content summaryType = new ContentBuilder();
+                addSummaryType(element, summaryType);
+                Content typeContent = new ContentBuilder();
                 if (te != null
                         && !utils.isConstructor(element)
                         && !utils.isClass(element)
                         && !utils.isInterface(element)
                         && !utils.isAnnotationType(element)) {
                     HtmlTree name = new HtmlTree(HtmlTag.SPAN);
-                    name.addStyle(HtmlStyle.typeNameLabel);
+                    name.setStyle(HtmlStyle.typeNameLabel);
                     name.addContent(name(te) + ".");
-                    thType.addContent(name);
+                    typeContent.addContent(name);
                 }
                 addSummaryLink(utils.isClass(element) || utils.isInterface(element)
                         ? LinkInfoImpl.Kind.CLASS_USE
                         : LinkInfoImpl.Kind.MEMBER,
-                        te, element, thType);
-                tr.addContent(thType);
-                HtmlTree tdDesc = new HtmlTree(HtmlTag.TD);
-                tdDesc.addStyle(HtmlStyle.colLast);
-                writer.addSummaryLinkComment(this, element, tdDesc);
-                tr.addContent(tdDesc);
-                tbody.addContent(tr);
+                        te, element, typeContent);
+                Content desc = new ContentBuilder();
+                writer.addSummaryLinkComment(this, element, desc);
+                useTable.addRow(summaryType, typeContent, desc);
             }
-            table.addContent(tbody);
-            contentTree.addContent(table);
+            contentTree.addContent(useTable.toContent());
         }
     }
 
@@ -515,81 +518,25 @@
      * @param tElement the class that is being documented
      * @param member the member being documented
      * @param firstSentenceTags the first sentence tags to be added to the summary
-     * @param tableContents the list of contents to which the documentation will be added
-     * @param counter the counter for determining id and style for the table row
      */
     public void addMemberSummary(TypeElement tElement, Element member,
-            List<? extends DocTree> firstSentenceTags, List<Content> tableContents, int counter,
-            VisibleMemberMap.Kind vmmKind) {
-        HtmlTree tdSummaryType = new HtmlTree(HtmlTag.TD);
-        tdSummaryType.addStyle(HtmlStyle.colFirst);
-        writer.addSummaryType(this, member, tdSummaryType);
-        HtmlTree tr = HtmlTree.TR(tdSummaryType);
-        HtmlTree thSummaryLink = new HtmlTree(HtmlTag.TH);
-        setSummaryColumnStyleAndScope(thSummaryLink);
-        addSummaryLink(tElement, member, thSummaryLink);
-        tr.addContent(thSummaryLink);
-        HtmlTree tdDesc = new HtmlTree(HtmlTag.TD);
-        tdDesc.addStyle(HtmlStyle.colLast);
-        writer.addSummaryLinkComment(this, member, firstSentenceTags, tdDesc);
-        tr.addContent(tdDesc);
-        if (utils.isMethod(member) && !utils.isAnnotationType(member)
-                && vmmKind != VisibleMemberMap.Kind.PROPERTIES) {
-            int methodType = utils.isStatic(member) ? MethodTypes.STATIC.tableTabs().value() :
-                    MethodTypes.INSTANCE.tableTabs().value();
-            if (utils.isInterface(member.getEnclosingElement())) {
-                methodType = utils.isAbstract(member)
-                        ? methodType | MethodTypes.ABSTRACT.tableTabs().value()
-                        : methodType | MethodTypes.DEFAULT.tableTabs().value();
-            } else {
-                methodType = utils.isAbstract(member)
-                        ? methodType | MethodTypes.ABSTRACT.tableTabs().value()
-                        : methodType | MethodTypes.CONCRETE.tableTabs().value();
-            }
-            if (utils.isDeprecated(member) || utils.isDeprecated(typeElement)) {
-                methodType = methodType | MethodTypes.DEPRECATED.tableTabs().value();
-            }
-            methodTypesOr = methodTypesOr | methodType;
-            String tableId = "i" + counter;
-            typeMap.put(tableId, methodType);
-            tr.addAttr(HtmlAttr.ID, tableId);
+            List<? extends DocTree> firstSentenceTags) {
+        if (tElement != typeElement) {
+            throw new IllegalStateException();
         }
-        if (counter%2 == 0)
-            tr.addStyle(HtmlStyle.altColor);
-        else
-            tr.addStyle(HtmlStyle.rowColor);
-        tableContents.add(tr);
-    }
-
-    /**
-     * Generate the method types set and return true if the method summary table
-     * needs to show tabs.
-     *
-     * @return true if the table should show tabs
-     */
-    public boolean showTabs() {
-        int value;
-        for (MethodTypes type : EnumSet.allOf(MethodTypes.class)) {
-            value = type.tableTabs().value();
-            if ((value & methodTypesOr) == value) {
-                methodTypes.add(type);
-            }
-        }
-        boolean showTabs = methodTypes.size() > 1;
-        if (showTabs) {
-            methodTypes.add(MethodTypes.ALL);
-        }
-        return showTabs;
-    }
-
-    /**
-     * Set the style and scope attribute for the summary column.
-     *
-     * @param thTree the column for which the style and scope attribute will be set
-     */
-    public void setSummaryColumnStyleAndScope(HtmlTree thTree) {
-        thTree.addStyle(HtmlStyle.colSecond);
-        thTree.addAttr(HtmlAttr.SCOPE, "row");
+        Table table = getSummaryTable();
+        List<Content> rowContents = new ArrayList<>();
+        Content summaryType = new ContentBuilder();
+        addSummaryType(member, summaryType);
+        if (!summaryType.isEmpty())
+            rowContents.add(summaryType);
+        Content summaryLink = new ContentBuilder();
+        addSummaryLink(tElement, member, summaryLink);
+        rowContents.add(summaryLink);
+        Content desc = new ContentBuilder();
+        writer.addSummaryLinkComment(this, member, firstSentenceTags, desc);
+        rowContents.add(desc);
+        table.addRow(member, rowContents);
     }
 
     /**
@@ -601,6 +548,7 @@
      * @param isLast true if this is the last member in the list
      * @param linksTree the content tree to which the summary will be added
      */
+    @Override
     public void addInheritedMemberSummary(TypeElement tElement,
             Element nestedClass, boolean isFirst, boolean isLast,
             Content linksTree) {
@@ -614,6 +562,7 @@
      * @param tElement the class the inherited member belongs to
      * @return a content tree for the inherited summary header
      */
+    @Override
     public Content getInheritedSummaryHeader(TypeElement tElement) {
         Content inheritedTree = writer.getMemberTreeHeader();
         writer.addInheritedSummaryHeader(this, tElement, inheritedTree);
@@ -625,6 +574,7 @@
      *
      * @return a content tree for the inherited summary links
      */
+    @Override
     public Content getInheritedSummaryLinksTree() {
         return new HtmlTree(HtmlTag.CODE);
     }
@@ -633,11 +583,18 @@
      * Get the summary table tree for the given class.
      *
      * @param tElement the class for which the summary table is generated
-     * @param tableContents list of contents to be displayed in the summary table
      * @return a content tree for the summary table
      */
-    public Content getSummaryTableTree(TypeElement tElement, List<Content> tableContents) {
-        return writer.getSummaryTableTree(this, tElement, tableContents, showTabs());
+    @Override
+    public Content getSummaryTableTree(TypeElement tElement) {
+        if (tElement != typeElement) {
+            throw new IllegalStateException();
+        }
+        Table table = getSummaryTable();
+        if (table.needsScript()) {
+            writer.getScript().addContent(table.getScript());
+        }
+        return table.toContent();
     }
 
     /**
@@ -646,6 +603,7 @@
      * @param memberTree the content tree of member to be documented
      * @return a content tree that will be added to the class documentation
      */
+    @Override
     public Content getMemberTree(Content memberTree) {
         return writer.getMemberTree(memberTree);
     }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractModuleIndexWriter.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractModuleIndexWriter.java	Thu Nov 16 15:01:45 2017 -0800
@@ -203,7 +203,7 @@
         HtmlTree htmlTree = (configuration.allowTag(HtmlTag.NAV))
                 ? HtmlTree.NAV()
                 : new HtmlTree(HtmlTag.DIV);
-        htmlTree.addStyle(HtmlStyle.indexNav);
+        htmlTree.setStyle(HtmlStyle.indexNav);
         HtmlTree ul = new HtmlTree(HtmlTag.UL);
         addAllClassesLink(ul);
         addAllPackagesLink(ul);
@@ -226,7 +226,7 @@
         HtmlTree htmlTree = (configuration.allowTag(HtmlTag.NAV))
                 ? HtmlTree.NAV()
                 : new HtmlTree(HtmlTag.DIV);
-        htmlTree.addStyle(HtmlStyle.indexNav);
+        htmlTree.setStyle(HtmlStyle.indexNav);
         HtmlTree ul = new HtmlTree(HtmlTag.UL);
         addAllClassesLink(ul);
         addAllPackagesLink(ul);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractPackageIndexWriter.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractPackageIndexWriter.java	Thu Nov 16 15:01:45 2017 -0800
@@ -146,7 +146,7 @@
             HtmlTree htmlTree = (configuration.allowTag(HtmlTag.NAV))
                     ? HtmlTree.NAV()
                     : new HtmlTree(HtmlTag.DIV);
-            htmlTree.addStyle(HtmlStyle.indexNav);
+            htmlTree.setStyle(HtmlStyle.indexNav);
             HtmlTree ul = new HtmlTree(HtmlTag.UL);
             addAllClassesLink(ul);
             if (configuration.showModules  && configuration.modules.size() > 1) {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractTreeWriter.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractTreeWriter.java	Thu Nov 16 15:01:45 2017 -0800
@@ -88,7 +88,7 @@
             Content ul = new HtmlTree(HtmlTag.UL);
             for (TypeElement local : collection) {
                 HtmlTree li = new HtmlTree(HtmlTag.LI);
-                li.addStyle(HtmlStyle.circle);
+                li.setStyle(HtmlStyle.circle);
                 addPartialInfo(local, li);
                 addExtendsImplements(parent, local, li);
                 addLevelInfo(local, classtree.directSubClasses(local, isEnum),
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeFieldWriterImpl.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeFieldWriterImpl.java	Thu Nov 16 15:01:45 2017 -0800
@@ -25,12 +25,16 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+
+import java.util.Arrays;
+
 import javax.lang.model.element.Element;
 import javax.lang.model.element.ExecutableElement;
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.type.TypeMirror;
 
-import jdk.javadoc.internal.doclets.formats.html.TableHeader;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
@@ -200,28 +204,31 @@
     /**
      * {@inheritDoc}
      */
-    public String getTableSummary() {
-        return configuration.getText("doclet.Member_Table_Summary",
-                configuration.getText("doclet.Field_Summary"),
-                configuration.getText("doclet.fields"));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Content getCaption() {
-        return configuration.getContent("doclet.Fields");
-    }
-
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public TableHeader getSummaryTableHeader(Element member) {
         return new TableHeader(contents.modifierAndTypeLabel, contents.fields,
                 contents.descriptionLabel);
     }
 
+    @Override
+    protected Table createSummaryTable() {
+        String summary = resources.getText("doclet.Member_Table_Summary",
+            resources.getText("doclet.Field_Summary"),
+            resources.getText("doclet.fields"));
+        Content caption = contents.getContent("doclet.Fields");
+
+        TableHeader header = new TableHeader(contents.modifierAndTypeLabel, contents.fields,
+            contents.descriptionLabel);
+
+        return new Table(configuration.htmlVersion, HtmlStyle.memberSummary)
+                .setSummary(summary)
+                .setCaption(caption)
+                .setHeader(header)
+                .setRowScopeColumn(1)
+                .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colSecond, HtmlStyle.colLast)
+                .setUseTBody(false);  // temporary? compatibility mode for TBody
+    }
+
     /**
      * {@inheritDoc}
      */
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeOptionalMemberWriterImpl.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeOptionalMemberWriterImpl.java	Thu Nov 16 15:01:45 2017 -0800
@@ -25,15 +25,14 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
-import java.util.Arrays;
-import java.util.List;
+
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
 
 import javax.lang.model.element.AnnotationValue;
 import javax.lang.model.element.Element;
 import javax.lang.model.element.ExecutableElement;
 import javax.lang.model.element.TypeElement;
 
-import jdk.javadoc.internal.doclets.formats.html.TableHeader;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
@@ -71,6 +70,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public Content getMemberSummaryHeader(TypeElement typeElement,
             Content memberSummaryTree) {
         memberSummaryTree.addContent(
@@ -83,6 +83,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addMemberTree(Content memberSummaryTree, Content memberTree) {
         writer.addMemberTree(memberSummaryTree, memberTree);
     }
@@ -90,6 +91,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addDefaultValueInfo(Element member, Content annotationDocTree) {
         if (utils.isAnnotationType(member)) {
             ExecutableElement ee = (ExecutableElement)member;
@@ -107,6 +109,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addSummaryLabel(Content memberTree) {
         Content label = HtmlTree.HEADING(HtmlConstants.SUMMARY_HEADING,
                 contents.annotateTypeOptionalMemberSummaryLabel);
@@ -116,7 +119,8 @@
     /**
      * {@inheritDoc}
      */
-    public String getTableSummary() {
+    @Override
+    protected String getTableSummary() {
         return resources.getText("doclet.Member_Table_Summary",
                 resources.getText("doclet.Annotation_Type_Optional_Member_Summary"),
                 resources.getText("doclet.annotation_type_optional_members"));
@@ -125,8 +129,9 @@
     /**
      * {@inheritDoc}
      */
-    public Content getCaption() {
-        return configuration.getContent("doclet.Annotation_Type_Optional_Members");
+    @Override
+    protected Content getCaption() {
+        return contents.getContent("doclet.Annotation_Type_Optional_Members");
     }
 
     /**
@@ -141,6 +146,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addSummaryAnchor(TypeElement typeElement, Content memberTree) {
         memberTree.addContent(writer.getMarkerAnchor(
                 SectionName.ANNOTATION_TYPE_OPTIONAL_ELEMENT_SUMMARY));
@@ -149,6 +155,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     protected Content getNavSummaryLink(TypeElement typeElement, boolean link) {
         if (link) {
             return writer.getHyperLink(
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java	Thu Nov 16 15:01:45 2017 -0800
@@ -25,6 +25,8 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+
 import java.util.Arrays;
 import java.util.List;
 
@@ -33,7 +35,7 @@
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.type.TypeMirror;
 
-import jdk.javadoc.internal.doclets.formats.html.TableHeader;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
@@ -203,27 +205,47 @@
     }
 
     /**
-     * {@inheritDoc}
+     * Get the summary for the member summary table.
+     *
+     * @return a string for the table summary
      */
-    public String getTableSummary() {
-        return configuration.getText("doclet.Member_Table_Summary",
-                configuration.getText("doclet.Annotation_Type_Required_Member_Summary"),
-                configuration.getText("doclet.annotation_type_required_members"));
+    // Overridden by AnnotationTypeOptionalMemberWriterImpl
+    protected String getTableSummary() {
+        return resources.getText("doclet.Member_Table_Summary",
+                resources.getText("doclet.Annotation_Type_Required_Member_Summary"),
+                resources.getText("doclet.annotation_type_required_members"));
+    }
+
+    /**
+     * Get the caption for the summary table.
+     * @return the caption
+     */
+    // Overridden by AnnotationTypeOptionalMemberWriterImpl
+    protected Content getCaption() {
+        return contents.getContent("doclet.Annotation_Type_Required_Members");
     }
 
     /**
      * {@inheritDoc}
      */
-    public Content getCaption() {
-        return configuration.getContent("doclet.Annotation_Type_Required_Members");
+    @Override
+    public TableHeader getSummaryTableHeader(Element member) {
+        return new TableHeader(contents.modifierAndTypeLabel,
+                contents.annotationTypeRequiredMemberLabel, contents.descriptionLabel);
     }
 
     /**
      * {@inheritDoc}
      */
-    public TableHeader getSummaryTableHeader(Element member) {
-        return new TableHeader(contents.modifierAndTypeLabel,
-                contents.annotationTypeRequiredMemberLabel, contents.descriptionLabel);
+    @Override
+    protected Table createSummaryTable() {
+        return new Table(configuration.htmlVersion, HtmlStyle.memberSummary)
+                .setSummary(getTableSummary())
+                .setCaption(getCaption())
+                .setHeader(getSummaryTableHeader(typeElement))
+                .setRowScopeColumn(1)
+                .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colSecond, HtmlStyle.colLast)
+                .setUseTBody(false);  // temporary? compatibility mode for TBody
     }
 
     /**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java	Thu Nov 16 15:01:45 2017 -0800
@@ -191,7 +191,7 @@
         }
         bodyTree.addContent(HtmlConstants.START_OF_CLASS_DATA);
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
-        div.addStyle(HtmlStyle.header);
+        div.setStyle(HtmlStyle.header);
         if (configuration.showModules) {
             ModuleElement mdle = configuration.docEnv.getElementUtils().getModuleOf(annotationType);
             Content typeModuleLabel = HtmlTree.SPAN(HtmlStyle.moduleLabelInType, contents.moduleLabel);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java	Thu Nov 16 15:01:45 2017 -0800
@@ -25,6 +25,8 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+
 import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -245,7 +247,7 @@
     protected void generateClassUseFile() throws DocFileIOException {
         HtmlTree body = getClassUseHeader();
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
-        div.addStyle(HtmlStyle.classUseContainer);
+        div.setStyle(HtmlStyle.classUseContainer);
         if (pkgSet.size() > 0) {
             addClassUse(div);
         } else {
@@ -276,7 +278,7 @@
      */
     protected void addClassUse(Content contentTree) {
         HtmlTree ul = new HtmlTree(HtmlTag.UL);
-        ul.addStyle(HtmlStyle.blockList);
+        ul.setStyle(HtmlStyle.blockList);
         if (configuration.packages.size() > 1) {
             addPackageList(ul);
             addPackageAnnotationList(ul);
@@ -291,25 +293,19 @@
      * @param contentTree the content tree to which the packages elements will be added
      */
     protected void addPackageList(Content contentTree) {
-        Content caption = getTableCaption(configuration.getContent(
+        Content caption = getTableCaption(contents.getContent(
                 "doclet.ClassUse_Packages.that.use.0",
                 getLink(new LinkInfoImpl(configuration,
                         LinkInfoImpl.Kind.CLASS_USE_HEADER, typeElement))));
-        Content table = (configuration.isOutputHtml5())
-                ? HtmlTree.TABLE(HtmlStyle.useSummary, caption)
-                : HtmlTree.TABLE(HtmlStyle.useSummary, packageUseTableSummary, caption);
-        table.addContent(getPackageTableHeader().toContent());
-        Content tbody = new HtmlTree(HtmlTag.TBODY);
-        boolean altColor = true;
+        Table table = new Table(configuration.htmlVersion, HtmlStyle.useSummary)
+                .setSummary(packageUseTableSummary)
+                .setCaption(caption)
+                .setHeader(getPackageTableHeader())
+                .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colLast);
         for (PackageElement pkg : pkgSet) {
-            HtmlTree tr = new HtmlTree(HtmlTag.TR);
-            tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
-            altColor = !altColor;
-            addPackageUse(pkg, tr);
-            tbody.addContent(tr);
+            addPackageUse(pkg, table);
         }
-        table.addContent(tbody);
-        Content li = HtmlTree.LI(HtmlStyle.blockList, table);
+        Content li = HtmlTree.LI(HtmlStyle.blockList, table.toContent());
         contentTree.addContent(li);
     }
 
@@ -324,30 +320,22 @@
                 pkgToPackageAnnotations.isEmpty()) {
             return;
         }
-        Content caption = getTableCaption(configuration.getContent(
+        Content caption = getTableCaption(contents.getContent(
                 "doclet.ClassUse_PackageAnnotation",
                 getLink(new LinkInfoImpl(configuration,
                         LinkInfoImpl.Kind.CLASS_USE_HEADER, typeElement))));
-        Content table = (configuration.isOutputHtml5())
-                ? HtmlTree.TABLE(HtmlStyle.useSummary, caption)
-                : HtmlTree.TABLE(HtmlStyle.useSummary, packageUseTableSummary, caption);
-        table.addContent(getPackageTableHeader().toContent());
-        Content tbody = new HtmlTree(HtmlTag.TBODY);
-        boolean altColor = true;
+
+        Table table = new Table(configuration.htmlVersion, HtmlStyle.useSummary)
+                .setSummary(packageUseTableSummary)
+                .setCaption(caption)
+                .setHeader(getPackageTableHeader())
+                .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colLast);
         for (PackageElement pkg : pkgToPackageAnnotations) {
-            HtmlTree tr = new HtmlTree(HtmlTag.TR);
-            tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
-            altColor = !altColor;
-            Content thFirst = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, getPackageLink(pkg));
-            tr.addContent(thFirst);
-            HtmlTree tdLast = new HtmlTree(HtmlTag.TD);
-            tdLast.addStyle(HtmlStyle.colLast);
-            addSummaryComment(pkg, tdLast);
-            tr.addContent(tdLast);
-            tbody.addContent(tr);
+            Content summary = new ContentBuilder();
+            addSummaryComment(pkg, summary);
+            table.addRow(getPackageLink(pkg), summary);
         }
-        table.addContent(tbody);
-        Content li = HtmlTree.LI(HtmlStyle.blockList, table);
+        Content li = HtmlTree.LI(HtmlStyle.blockList, table.toContent());
         contentTree.addContent(li);
     }
 
@@ -358,7 +346,7 @@
      */
     protected void addClassList(Content contentTree) {
         HtmlTree ul = new HtmlTree(HtmlTag.UL);
-        ul.addStyle(HtmlStyle.blockList);
+        ul.setStyle(HtmlStyle.blockList);
         for (PackageElement pkg : pkgSet) {
             Content markerAnchor = getMarkerAnchor(getPackageAnchorName(pkg));
             HtmlTree htmlTree = (configuration.allowTag(HtmlTag.SECTION))
@@ -385,16 +373,14 @@
      * Add the package use information.
      *
      * @param pkg the package that uses the given class
-     * @param contentTree the content tree to which the package use information will be added
+     * @param table the table to which the package use information will be added
      */
-    protected void addPackageUse(PackageElement pkg, Content contentTree) {
-        Content thFirst = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst,
-                getHyperLink(getPackageAnchorName(pkg), new StringContent(utils.getPackageName(pkg))));
-        contentTree.addContent(thFirst);
-        HtmlTree tdLast = new HtmlTree(HtmlTag.TD);
-        tdLast.addStyle(HtmlStyle.colLast);
-        addSummaryComment(pkg, tdLast);
-        contentTree.addContent(tdLast);
+    protected void addPackageUse(PackageElement pkg, Table table) {
+        Content pkgLink =
+                getHyperLink(getPackageAnchorName(pkg), new StringContent(utils.getPackageName(pkg)));
+        Content summary = new ContentBuilder();
+        addSummaryComment(pkg, summary);
+        table.addRow(pkgLink, summary);
     }
 
     /**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java	Thu Nov 16 15:01:45 2017 -0800
@@ -202,7 +202,7 @@
         }
         bodyTree.addContent(HtmlConstants.START_OF_CLASS_DATA);
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
-        div.addStyle(HtmlStyle.header);
+        div.setStyle(HtmlStyle.header);
         if (configuration.showModules) {
             ModuleElement mdle = configuration.docEnv.getElementUtils().getModuleOf(typeElement);
             Content classModuleLabel = HtmlTree.SPAN(HtmlStyle.moduleLabelInType, contents.moduleLabel);
@@ -380,13 +380,13 @@
     private Content getClassInheritenceTree(TypeMirror type) {
         TypeMirror sup;
         HtmlTree classTreeUl = new HtmlTree(HtmlTag.UL);
-        classTreeUl.addStyle(HtmlStyle.inheritance);
+        classTreeUl.setStyle(HtmlStyle.inheritance);
         Content liTree = null;
         do {
             sup = utils.getFirstVisibleSuperClass(type);
             if (sup != null) {
                 HtmlTree ul = new HtmlTree(HtmlTag.UL);
-                ul.addStyle(HtmlStyle.inheritance);
+                ul.setStyle(HtmlStyle.inheritance);
                 ul.addContent(getTreeForClassHelper(type));
                 if (liTree != null)
                     ul.addContent(liTree);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java	Thu Nov 16 15:01:45 2017 -0800
@@ -25,6 +25,9 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
+
 import java.util.*;
 
 import javax.lang.model.element.Modifier;
@@ -75,7 +78,7 @@
     /**
      * The HTML tree for main tag.
      */
-    private HtmlTree mainTree = HtmlTree.MAIN();
+    private final HtmlTree mainTree = HtmlTree.MAIN();
 
     /**
      * The HTML tree for constant values summary.
@@ -99,6 +102,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public Content getHeader() {
         String label = configuration.getText("doclet.Constants_Summary");
         HtmlTree bodyTree = getBody(true, getWindowTitle(label));
@@ -116,6 +120,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public Content getContentsHeader() {
         return new HtmlTree(HtmlTag.UL);
     }
@@ -123,6 +128,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addLinkToPackageContent(PackageElement pkg,
             Set<PackageElement> printedPackageHeaders, Content contentListTree) {
         //add link to summary
@@ -146,6 +152,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addContentsList(Content contentTree, Content contentListTree) {
         Content titleContent = contents.constantsSummaryTitle;
         Content pHeading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, true,
@@ -169,15 +176,17 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public Content getConstantSummaries() {
         HtmlTree summariesDiv = new HtmlTree(HtmlTag.DIV);
-        summariesDiv.addStyle(HtmlStyle.constantValuesContainer);
+        summariesDiv.setStyle(HtmlStyle.constantValuesContainer);
         return summariesDiv;
     }
 
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addPackageName(PackageElement pkg, Content summariesTree, boolean first) {
         Content pkgNameContent;
         if (!first && configuration.allowTag(HtmlTag.SECTION)) {
@@ -206,15 +215,17 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public Content getClassConstantHeader() {
         HtmlTree ul = new HtmlTree(HtmlTag.UL);
-        ul.addStyle(HtmlStyle.blockList);
+        ul.setStyle(HtmlStyle.blockList);
         return ul;
     }
 
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addClassConstant(Content summariesTree, Content classConstantTree) {
         if (configuration.allowTag(HtmlTag.SECTION)) {
             summaryTree.addContent(classConstantTree);
@@ -224,12 +235,13 @@
     }
 
     /**
-     * Get the table caption and header for the constant summary table
-     *
-     * @param typeElement the TypeElement to be documented
-     * @return constant members header content
+     * {@inheritDoc}
      */
-    public Content getConstantMembersHeader(TypeElement typeElement) {
+    @Override
+    public void addConstantMembers(TypeElement typeElement, Collection<VariableElement> fields,
+            Content classConstantTree) {
+        currentTypeElement = typeElement;
+
         //generate links backward only to public classes.
         Content classlink = (utils.isPublic(typeElement) || utils.isProtected(typeElement)) ?
             getLink(new LinkInfoImpl(configuration,
@@ -237,66 +249,28 @@
             new StringContent(utils.getFullyQualifiedName(typeElement));
 
         PackageElement enclosingPackage  = utils.containingPackage(typeElement);
+        Content caption = new ContentBuilder();
         if (!enclosingPackage.isUnnamed()) {
-            Content cb = new ContentBuilder();
-            cb.addContent(enclosingPackage.getQualifiedName());
-            cb.addContent(".");
-            cb.addContent(classlink);
-            return getClassName(cb);
-        } else {
-            return getClassName(classlink);
+            caption.addContent(enclosingPackage.getQualifiedName());
+            caption.addContent(".");
         }
-    }
-
-    /**
-     * Get the class name in the table caption and the table header.
-     *
-     * @param classStr the class name to print.
-     * @return the table caption and header
-     */
-    protected Content getClassName(Content classStr) {
-        Content caption = getTableCaption(classStr);
-        Content table = (configuration.isOutputHtml5())
-                ? HtmlTree.TABLE(HtmlStyle.constantsSummary, caption)
-                : HtmlTree.TABLE(HtmlStyle.constantsSummary, constantsTableSummary, caption);
-        table.addContent(constantsTableHeader.toContent());
-        return table;
-    }
+        caption.addContent(classlink);
 
-    /**
-     * {@inheritDoc}
-     */
-    public void addConstantMembers(TypeElement typeElement, Collection<VariableElement> fields,
-            Content classConstantTree) {
-        currentTypeElement = typeElement;
-        Content tbody = new HtmlTree(HtmlTag.TBODY);
-        boolean altColor = true;
+        Table table = new Table(configuration.htmlVersion, HtmlStyle.constantsSummary)
+                .setSummary(constantsTableSummary)
+                .setCaption(caption)
+                .setHeader(constantsTableHeader)
+                .setRowScopeColumn(1)
+                .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colSecond, HtmlStyle.colLast);
+
         for (VariableElement field : fields) {
-            HtmlTree tr = new HtmlTree(HtmlTag.TR);
-            tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
-            addConstantMember(field, tr);
-            tbody.addContent(tr);
-            altColor = !altColor;
+            table.addRow(getTypeColumn(field), getNameColumn(field), getValue(field));
         }
-        Content table = getConstantMembersHeader(typeElement);
-        table.addContent(tbody);
-        Content li = HtmlTree.LI(HtmlStyle.blockList, table);
+        Content li = HtmlTree.LI(HtmlStyle.blockList, table.toContent());
         classConstantTree.addContent(li);
     }
 
     /**
-     * Add the row for the constant summary table.
-     *
-     * @param member the field to be documented.
-     * @param trTree an htmltree object for the table row
-     */
-    private void addConstantMember(VariableElement member, HtmlTree trTree) {
-        trTree.addContent(getTypeColumn(member));
-        trTree.addContent(getNameColumn(member));
-        trTree.addContent(getValue(member));
-    }
-
-    /**
      * Get the type column for the constant summary table row.
      *
      * @param member the field to be documented.
@@ -305,7 +279,8 @@
     private Content getTypeColumn(VariableElement member) {
         Content anchor = getMarkerAnchor(currentTypeElement.getQualifiedName() +
                 "." + member.getSimpleName());
-        Content tdType = HtmlTree.TD(HtmlStyle.colFirst, anchor);
+        Content typeContent = new ContentBuilder();
+        typeContent.addContent(anchor);
         Content code = new HtmlTree(HtmlTag.CODE);
         for (Modifier mod : member.getModifiers()) {
             Content modifier = new StringContent(mod.toString());
@@ -315,8 +290,8 @@
         Content type = getLink(new LinkInfoImpl(configuration,
                 LinkInfoImpl.Kind.CONSTANT_SUMMARY, member.asType()));
         code.addContent(type);
-        tdType.addContent(code);
-        return tdType;
+        typeContent.addContent(code);
+        return typeContent;
     }
 
     /**
@@ -328,8 +303,7 @@
     private Content getNameColumn(VariableElement member) {
         Content nameContent = getDocLink(LinkInfoImpl.Kind.CONSTANT_SUMMARY,
                 member, member.getSimpleName(), false);
-        Content code = HtmlTree.CODE(nameContent);
-        return HtmlTree.TH_ROW_SCOPE(HtmlStyle.colSecond, code);
+        return HtmlTree.CODE(nameContent);
     }
 
     /**
@@ -341,13 +315,13 @@
     private Content getValue(VariableElement member) {
         String value = utils.constantValueExpresion(member);
         Content valueContent = new StringContent(value);
-        Content code = HtmlTree.CODE(valueContent);
-        return HtmlTree.TD(HtmlStyle.colLast, code);
+        return HtmlTree.CODE(valueContent);
     }
 
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addConstantSummaries(Content contentTree, Content summariesTree) {
         if (configuration.allowTag(HtmlTag.SECTION) && summaryTree != null) {
             summariesTree.addContent(summaryTree);
@@ -363,6 +337,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addFooter(Content contentTree) {
         Content htmlTree = (configuration.allowTag(HtmlTag.FOOTER))
                 ? HtmlTree.FOOTER()
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriterImpl.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriterImpl.java	Thu Nov 16 15:01:45 2017 -0800
@@ -25,14 +25,15 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
+
 import java.util.*;
 
 import javax.lang.model.element.Element;
 import javax.lang.model.element.ExecutableElement;
 import javax.lang.model.element.TypeElement;
 
-import jdk.javadoc.internal.doclets.formats.html.TableHeader;
-import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
@@ -105,6 +106,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addMemberTree(Content memberSummaryTree, Content memberTree) {
         writer.addMemberTree(memberSummaryTree, memberTree);
     }
@@ -169,15 +171,6 @@
      * {@inheritDoc}
      */
     @Override
-    public void setSummaryColumnStyleAndScope(HtmlTree thTree) {
-        thTree.addStyle(HtmlStyle.colConstructorName);
-        thTree.addAttr(HtmlAttr.SCOPE, "row");
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
     public void addDeprecated(ExecutableElement constructor, Content constructorDocTree) {
         addDeprecatedInfo(constructor, constructorDocTree);
     }
@@ -243,24 +236,6 @@
      * {@inheritDoc}
      */
     @Override
-    public String getTableSummary() {
-        return resources.getText("doclet.Member_Table_Summary",
-                resources.getText("doclet.Constructor_Summary"),
-                resources.getText("doclet.constructors"));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public Content getCaption() {
-        return contents.constructors;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
     public TableHeader getSummaryTableHeader(Element member) {
         if (foundNonPubConstructor) {
             return new TableHeader(contents.modifierLabel, contents.constructorLabel,
@@ -270,6 +245,33 @@
         }
     }
 
+    @Override
+    protected Table createSummaryTable() {
+        List<HtmlStyle> bodyRowStyles;
+        int rowScopeColumn;
+
+        if (foundNonPubConstructor) {
+            bodyRowStyles = Arrays.asList(HtmlStyle.colFirst, HtmlStyle.colConstructorName,
+                    HtmlStyle.colLast);
+            rowScopeColumn = 1;
+        } else {
+            bodyRowStyles = Arrays.asList(HtmlStyle.colConstructorName, HtmlStyle.colLast);
+            rowScopeColumn = 0;
+        }
+
+        String summary =  resources.getText("doclet.Member_Table_Summary",
+                resources.getText("doclet.Constructor_Summary"),
+                resources.getText("doclet.constructors"));
+
+        return new Table(configuration.htmlVersion, HtmlStyle.memberSummary)
+                .setSummary(summary)
+                .setCaption(contents.constructors)
+                .setHeader(getSummaryTableHeader(typeElement))
+                .setRowScopeColumn(rowScopeColumn)
+                .setColumnStyles(bodyRowStyles)
+                .setUseTBody(false);  // temporary? compatibility mode for TBody
+    }
+
     /**
      * {@inheritDoc}
      */
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DeprecatedListWriter.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DeprecatedListWriter.java	Thu Nov 16 15:01:45 2017 -0800
@@ -25,6 +25,9 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
+
 import java.util.EnumMap;
 import java.util.List;
 import java.util.SortedSet;
@@ -34,6 +37,7 @@
 import javax.lang.model.element.PackageElement;
 
 import com.sun.source.doctree.DocTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
@@ -281,7 +285,7 @@
         htmlTree.addContent(getContentsList(deprapi));
         String memberTableSummary;
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
-        div.addStyle(HtmlStyle.contentContainer);
+        div.setStyle(HtmlStyle.contentContainer);
         for (DeprElementKind kind : DeprElementKind.values()) {
             if (deprapi.hasDocumentation(kind)) {
                 addAnchor(deprapi, kind, div);
@@ -404,49 +408,42 @@
     protected void addDeprecatedAPI(SortedSet<Element> deprList, String headingKey,
             String tableSummary, TableHeader tableHeader, Content contentTree) {
         if (deprList.size() > 0) {
-            Content caption = getTableCaption(configuration.getContent(headingKey));
-            Content table = (configuration.isOutputHtml5())
-                    ? HtmlTree.TABLE(HtmlStyle.deprecatedSummary, caption)
-                    : HtmlTree.TABLE(HtmlStyle.deprecatedSummary, tableSummary, caption);
-            table.addContent(tableHeader.toContent());
-            Content tbody = new HtmlTree(HtmlTag.TBODY);
-            boolean altColor = true;
+            Content caption = contents.getContent(headingKey);
+            Table table = new Table(configuration.htmlVersion, HtmlStyle.deprecatedSummary)
+                    .setSummary(tableSummary)
+                    .setCaption(caption)
+                    .setHeader(tableHeader)
+                    .setColumnStyles(HtmlStyle.colDeprecatedItemName, HtmlStyle.colLast);
             for (Element e : deprList) {
-                HtmlTree thRow;
+                Content link;
                 switch (e.getKind()) {
                     case MODULE:
-                        ModuleElement m = (ModuleElement)e;
-                        thRow = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst,
-                        getModuleLink(m, new StringContent(m.getQualifiedName())));
+                        ModuleElement m = (ModuleElement) e;
+                        link = getModuleLink(m, new StringContent(m.getQualifiedName()));
                         break;
                     case PACKAGE:
-                        PackageElement pkg = (PackageElement)e;
-                        thRow = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst,
-                        getPackageLink(pkg, getPackageName(pkg)));
+                        PackageElement pkg = (PackageElement) e;
+                        link = getPackageLink(pkg, getPackageName(pkg));
                         break;
                     default:
-                        thRow = getDeprecatedLink(e);
+                        link = getDeprecatedLink(e);
                 }
-                HtmlTree tr = HtmlTree.TR(thRow);
-                HtmlTree tdDesc = new HtmlTree(HtmlTag.TD);
-                tdDesc.addStyle(HtmlStyle.colLast);
+                Content desc = new ContentBuilder();
                 List<? extends DocTree> tags = utils.getDeprecatedTrees(e);
                 if (!tags.isEmpty()) {
-                    addInlineDeprecatedComment(e, tags.get(0), tdDesc);
+                    addInlineDeprecatedComment(e, tags.get(0), desc);
+                } else {
+                    desc.addContent(HtmlTree.EMPTY);
                 }
-                tr.addContent(tdDesc);
-                tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
-                altColor = !altColor;
-                tbody.addContent(tr);
+                table.addRow(link, desc);
             }
-            table.addContent(tbody);
-            Content li = HtmlTree.LI(HtmlStyle.blockList, table);
+            Content li = HtmlTree.LI(HtmlStyle.blockList, table.toContent());
             Content ul = HtmlTree.UL(HtmlStyle.blockList, li);
             contentTree.addContent(ul);
         }
     }
 
-    protected HtmlTree getDeprecatedLink(Element e) {
+    protected Content getDeprecatedLink(Element e) {
         AbstractMemberWriter writer;
         switch (e.getKind()) {
             case INTERFACE:
@@ -470,6 +467,6 @@
             default:
                 writer = new AnnotationTypeOptionalMemberWriterImpl(this, null);
         }
-        return HtmlTree.TH_ROW_SCOPE(HtmlStyle.colDeprecatedItemName, writer.getDeprecatedLink(e));
+        return writer.getDeprecatedLink(e);
     }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/EnumConstantWriterImpl.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/EnumConstantWriterImpl.java	Thu Nov 16 15:01:45 2017 -0800
@@ -25,16 +25,14 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
+
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
 
 import javax.lang.model.element.Element;
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.element.VariableElement;
 
-import jdk.javadoc.internal.doclets.formats.html.TableHeader;
-import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
@@ -81,6 +79,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addMemberTree(Content memberSummaryTree, Content memberTree) {
         writer.addMemberTree(memberSummaryTree, memberTree);
     }
@@ -196,26 +195,25 @@
      * {@inheritDoc}
      */
     @Override
-    public String getTableSummary() {
-        return resources.getText("doclet.Member_Table_Summary",
-                resources.getText("doclet.Enum_Constant_Summary"),
-                resources.getText("doclet.enum_constants"));
+    public TableHeader getSummaryTableHeader(Element member) {
+        return new TableHeader(contents.enumConstantLabel, contents.descriptionLabel);
     }
 
     /**
      * {@inheritDoc}
      */
     @Override
-    public Content getCaption() {
-        return configuration.getContent("doclet.Enum_Constants");
-    }
+    protected Table createSummaryTable() {
+        String summary = resources.getText("doclet.Member_Table_Summary",
+            resources.getText("doclet.Enum_Constant_Summary"),
+            resources.getText("doclet.enum_constants"));
 
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public TableHeader getSummaryTableHeader(Element member) {
-        return new TableHeader(contents.enumConstantLabel, contents.descriptionLabel);
+        return new Table(configuration.htmlVersion, HtmlStyle.memberSummary)
+                .setSummary(summary)
+                .setCaption(contents.getContent("doclet.Enum_Constants"))
+                .setHeader(getSummaryTableHeader(typeElement))
+                .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colLast)
+                .setUseTBody(false);
     }
 
     /**
@@ -257,15 +255,6 @@
      * {@inheritDoc}
      */
     @Override
-    public void setSummaryColumnStyleAndScope(HtmlTree thTree) {
-        thTree.addStyle(HtmlStyle.colFirst);
-        thTree.addAttr(HtmlAttr.SCOPE, "row");
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
     protected void addInheritedSummaryLink(TypeElement typeElement, Element member, Content linksTree) {
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FieldWriterImpl.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FieldWriterImpl.java	Thu Nov 16 15:01:45 2017 -0800
@@ -25,11 +25,16 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
+
+import java.util.Arrays;
+import java.util.List;
+
 import javax.lang.model.element.Element;
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.element.VariableElement;
 
-import jdk.javadoc.internal.doclets.formats.html.TableHeader;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
@@ -78,6 +83,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addMemberTree(Content memberSummaryTree, Content memberTree) {
         writer.addMemberTree(memberSummaryTree, memberTree);
     }
@@ -192,29 +198,29 @@
      * {@inheritDoc}
      */
     @Override
-    public String getTableSummary() {
-        return resources.getText("doclet.Member_Table_Summary",
-                resources.getText("doclet.Field_Summary"),
-                resources.getText("doclet.fields"));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public Content getCaption() {
-        return contents.fields;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
     public TableHeader getSummaryTableHeader(Element member) {
         return new TableHeader(contents.modifierAndTypeLabel, contents.fieldLabel,
                 contents.descriptionLabel);
     }
 
+    @Override
+    protected Table createSummaryTable() {
+        String summary =  resources.getText("doclet.Member_Table_Summary",
+                resources.getText("doclet.Field_Summary"),
+                resources.getText("doclet.fields"));
+
+        List<HtmlStyle> bodyRowStyles = Arrays.asList(HtmlStyle.colFirst, HtmlStyle.colSecond,
+                HtmlStyle.colLast);
+
+        return new Table(configuration.htmlVersion, HtmlStyle.memberSummary)
+                .setSummary(summary)
+                .setCaption(contents.fields)
+                .setHeader(getSummaryTableHeader(typeElement))
+                .setRowScopeColumn(1)
+                .setColumnStyles(bodyRowStyles)
+                .setUseTBody(false);  // temporary? compatibility mode for TBody
+    }
+
     /**
      * {@inheritDoc}
      */
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FrameOutputWriter.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FrameOutputWriter.java	Thu Nov 16 15:01:45 2017 -0800
@@ -156,8 +156,8 @@
     protected Content getFrameDetails() {
         HtmlTree leftContainerDiv = new HtmlTree(HtmlTag.DIV);
         HtmlTree rightContainerDiv = new HtmlTree(HtmlTag.DIV);
-        leftContainerDiv.addStyle(HtmlStyle.leftContainer);
-        rightContainerDiv.addStyle(HtmlStyle.rightContainer);
+        leftContainerDiv.setStyle(HtmlStyle.leftContainer);
+        rightContainerDiv.setStyle(HtmlStyle.rightContainer);
         if (configuration.showModules && configuration.modules.size() > 1) {
             addAllModulesFrameTag(leftContainerDiv);
         } else if (noOfPackages > 1) {
@@ -214,7 +214,7 @@
     private void addClassFrameTag(Content contentTree) {
         HtmlTree frame = HtmlTree.IFRAME(configuration.topFile.getPath(), "classFrame",
                 configuration.getText("doclet.Package_class_and_interface_descriptions"));
-        frame.addStyle(HtmlStyle.rightIframe);
+        frame.setStyle(HtmlStyle.rightIframe);
         contentTree.addContent(frame);
     }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HelpWriter.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HelpWriter.java	Thu Nov 16 15:01:45 2017 -0800
@@ -124,7 +124,7 @@
         }
         HtmlTree htmlTree;
         HtmlTree ul = new HtmlTree(HtmlTag.UL);
-        ul.addStyle(HtmlStyle.blockList);
+        ul.setStyle(HtmlStyle.blockList);
         if (configuration.createoverview) {
             Content overviewHeading = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING,
                 contents.overviewLabel);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java	Thu Nov 16 15:01:45 2017 -0800
@@ -25,6 +25,8 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
+
 import java.text.SimpleDateFormat;
 import java.util.*;
 import java.util.regex.Matcher;
@@ -92,9 +94,7 @@
 import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
 import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
-import jdk.javadoc.internal.doclets.toolkit.util.GroupTypes;
 import jdk.javadoc.internal.doclets.toolkit.util.ImplementedMethods;
-import jdk.javadoc.internal.doclets.toolkit.util.TableTabTypes.TableTabs;
 import jdk.javadoc.internal.doclets.toolkit.util.Utils;
 import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
 
@@ -503,11 +503,11 @@
                     : htmlTree;
             String allClassesId = "allclasses_";
             HtmlTree navDiv = new HtmlTree(HtmlTag.DIV);
-            fixedNavDiv.addStyle(HtmlStyle.fixedNav);
+            fixedNavDiv.setStyle(HtmlStyle.fixedNav);
             Content skipNavLinks = configuration.getContent("doclet.Skip_navigation_links");
             if (header) {
                 fixedNavDiv.addContent(HtmlConstants.START_OF_TOP_NAVBAR);
-                navDiv.addStyle(HtmlStyle.topNav);
+                navDiv.setStyle(HtmlStyle.topNav);
                 allClassesId += "navbar_top";
                 Content a = getMarkerAnchor(SectionName.NAVBAR_TOP);
                 //WCAG - Hyperlinks should contain text or an image with alt text - for AT tools
@@ -518,7 +518,7 @@
                 navDiv.addContent(skipLinkContent);
             } else {
                 tree.addContent(HtmlConstants.START_OF_BOTTOM_NAVBAR);
-                navDiv.addStyle(HtmlStyle.bottomNav);
+                navDiv.setStyle(HtmlStyle.bottomNav);
                 allClassesId += "navbar_bottom";
                 Content a = getMarkerAnchor(SectionName.NAVBAR_BOTTOM);
                 navDiv.addContent(a);
@@ -533,7 +533,7 @@
                 navDiv.addContent(getMarkerAnchor(SectionName.NAVBAR_BOTTOM_FIRSTROW));
             }
             HtmlTree navList = new HtmlTree(HtmlTag.UL);
-            navList.addStyle(HtmlStyle.navList);
+            navList.setStyle(HtmlStyle.navList);
             navList.addAttr(HtmlAttr.TITLE,
                             configuration.getText("doclet.Navigation"));
             if (configuration.createoverview) {
@@ -914,73 +914,6 @@
     }
 
     /**
-     * Get table header.
-     *
-     * @param caption the table caption
-     * @param tableSummary the summary for the table
-     * @param tableStyle the table style
-     * @return a content object
-     */
-    public Content getTableHeader(Content caption, String tableSummary, HtmlStyle tableStyle) {
-        Content table = (configuration.isOutputHtml5())
-                ? HtmlTree.TABLE(tableStyle, caption)
-                : HtmlTree.TABLE(tableStyle, tableSummary, caption);
-        return table;
-    }
-
-    /**
-     * Get the summary table caption.
-     *
-     * @param groupTypes the group types for table tabs
-     * @return the caption for the summary table
-     */
-    public Content getTableCaption(GroupTypes groupTypes) {
-        Content tabbedCaption = new HtmlTree(HtmlTag.CAPTION);
-        Map<String, TableTabs> groups = groupTypes.getGroupTypes();
-        for (String group : groups.keySet()) {
-            Content captionSpan;
-            Content span;
-            TableTabs tab = groups.get(group);
-            if (tab.isDefaultTab()) {
-                captionSpan = HtmlTree.SPAN(new StringContent(tab.resourceKey()));
-                span = HtmlTree.SPAN(tab.tabId(),
-                        HtmlStyle.activeTableTab, captionSpan);
-            } else {
-                captionSpan = HtmlTree.SPAN(getGroupTypeLinks(groupTypes, group));
-                span = HtmlTree.SPAN(tab.tabId(),
-                        HtmlStyle.tableTab, captionSpan);
-            }
-            Content tabSpan = HtmlTree.SPAN(HtmlStyle.tabEnd, Contents.SPACE);
-            span.addContent(tabSpan);
-            tabbedCaption.addContent(span);
-        }
-        return tabbedCaption;
-    }
-
-    /**
-     * Get the group type links for the table caption.
-     *
-     * @param groupTypes the group types for table tabs
-     * @param groupName the group name to be displayed as link
-     * @return the content tree for the group type link
-     */
-    public Content getGroupTypeLinks(GroupTypes groupTypes, String groupName) {
-        String jsShow = "javascript:showGroups(" + groupTypes.getTableTab(groupName).value() + ");";
-        HtmlTree link = HtmlTree.A(jsShow, new StringContent(groupTypes.getTableTab(groupName).resourceKey()));
-        return link;
-    }
-
-    /**
-     * Returns true if the table tabs needs to be displayed.
-     *
-     * @param groupTypes the group types for table tabs
-     * @return true if the tabs should be displayed
-     */
-    public boolean showTabs(GroupTypes groupTypes) {
-        return groupTypes.getGroupTypes().size() > 1;
-    }
-
-    /**
      * Get the marker anchor which will be added to the documentation tree.
      *
      * @param anchorName the anchor name attribute
@@ -2201,9 +2134,9 @@
      * @param filePath the DocPath of the file that needs to be added
      */
     private void addJQueryFile(Content head, DocPath filePath) {
-        HtmlTree jqyeryScriptFile = HtmlTree.SCRIPT(
+        HtmlTree jqueryScriptFile = HtmlTree.SCRIPT(
                 pathToRoot.resolve(DocPaths.JQUERY_FILES.resolve(filePath)).getPath());
-        head.addContent(jqyeryScriptFile);
+        head.addContent(jqueryScriptFile);
     }
 
     /**
@@ -2614,4 +2547,8 @@
     protected TableHeader getPackageTableHeader() {
         return new TableHeader(contents.packageLabel, contents.descriptionLabel);
     }
+
+    Content getScript() {
+        return script;
+    }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialFieldWriter.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialFieldWriter.java	Thu Nov 16 15:01:45 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -75,7 +75,7 @@
      */
     public Content getSerializableFieldsHeader() {
         HtmlTree ul = new HtmlTree(HtmlTag.UL);
-        ul.addStyle(HtmlStyle.blockList);
+        ul.setStyle(HtmlStyle.blockList);
         return ul;
     }
 
@@ -88,9 +88,9 @@
     public Content getFieldsContentHeader(boolean isLastContent) {
         HtmlTree li = new HtmlTree(HtmlTag.LI);
         if (isLastContent)
-            li.addStyle(HtmlStyle.blockListLast);
+            li.setStyle(HtmlStyle.blockListLast);
         else
-            li.addStyle(HtmlStyle.blockList);
+            li.setStyle(HtmlStyle.blockList);
         return li;
     }
 
@@ -104,7 +104,7 @@
      */
     public Content getSerializableFields(String heading, Content serializableFieldsTree) {
         HtmlTree li = new HtmlTree(HtmlTag.LI);
-        li.addStyle(HtmlStyle.blockList);
+        li.setStyle(HtmlStyle.blockList);
         if (serializableFieldsTree.isValid()) {
             Content headingContent = new StringContent(heading);
             Content serialHeading = HtmlTree.HEADING(HtmlConstants.SERIALIZED_MEMBER_HEADING,
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialMethodWriter.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialMethodWriter.java	Thu Nov 16 15:01:45 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -66,7 +66,7 @@
      */
     public Content getSerializableMethodsHeader() {
         HtmlTree ul = new HtmlTree(HtmlTag.UL);
-        ul.addStyle(HtmlStyle.blockList);
+        ul.setStyle(HtmlStyle.blockList);
         return ul;
     }
 
@@ -79,9 +79,9 @@
     public Content getMethodsContentHeader(boolean isLastContent) {
         HtmlTree li = new HtmlTree(HtmlTag.LI);
         if (isLastContent)
-            li.addStyle(HtmlStyle.blockListLast);
+            li.setStyle(HtmlStyle.blockListLast);
         else
-            li.addStyle(HtmlStyle.blockList);
+            li.setStyle(HtmlStyle.blockList);
         return li;
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java	Thu Nov 16 15:01:45 2017 -0800
@@ -25,8 +25,9 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
-import java.util.Arrays;
-import java.util.List;
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
+
 import java.util.SortedSet;
 import java.util.TreeSet;
 
@@ -35,7 +36,6 @@
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.type.TypeMirror;
 
-import jdk.javadoc.internal.doclets.formats.html.TableHeader;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
@@ -96,6 +96,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addMemberTree(Content memberSummaryTree, Content memberTree) {
         writer.addMemberTree(memberSummaryTree, memberTree);
     }
@@ -242,29 +243,38 @@
      * {@inheritDoc}
      */
     @Override
-    public String getTableSummary() {
-        return resources.getText("doclet.Member_Table_Summary",
-                resources.getText("doclet.Method_Summary"),
-                resources.getText("doclet.methods"));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public Content getCaption() {
-        return contents.methods;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
     public TableHeader getSummaryTableHeader(Element member) {
         return new TableHeader(contents.modifierAndTypeLabel, contents.methodLabel,
                 contents.descriptionLabel);
     }
 
+    @Override
+    protected Table createSummaryTable() {
+        String summary =  resources.getText("doclet.Member_Table_Summary",
+                resources.getText("doclet.Method_Summary"),
+                resources.getText("doclet.methods"));
+
+        return new Table(configuration.htmlVersion, HtmlStyle.memberSummary)
+                .setSummary(summary)
+                .setHeader(getSummaryTableHeader(typeElement))
+                .setRowScopeColumn(1)
+                .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colSecond, HtmlStyle.colLast)
+                .setDefaultTab(resources.getText("doclet.All_Methods"))
+                .addTab(resources.getText("doclet.Static_Methods"), utils::isStatic)
+                .addTab(resources.getText("doclet.Instance_Methods"), e -> !utils.isStatic(e))
+                .addTab(resources.getText("doclet.Abstract_Methods"), utils::isAbstract)
+                .addTab(resources.getText("doclet.Concrete_Methods"),
+                        e -> !utils.isAbstract(e) && !utils.isInterface(e.getEnclosingElement()))
+                .addTab(resources.getText("doclet.Default_Methods"),
+                        e -> !utils.isAbstract(e) && utils.isInterface(e.getEnclosingElement()))
+                .addTab(resources.getText("doclet.Deprecated_Methods"),
+                        e -> utils.isDeprecated(e) || utils.isDeprecated(typeElement))
+                .setTabScriptVariable("methods")
+                .setTabScript(i -> "show(" + i + ");")
+                .setUseTBody(false)
+                .setPutIdFirst(true);
+    }
+
     /**
      * {@inheritDoc}
      */
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleFrameWriter.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleFrameWriter.java	Thu Nov 16 15:01:45 2017 -0800
@@ -103,7 +103,7 @@
                 mdlgen.getHyperLink(DocPaths.moduleSummary(moduleElement), mdlLabel, "", "classFrame"));
         htmlTree.addContent(heading);
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
-        div.addStyle(HtmlStyle.indexContainer);
+        div.setStyle(HtmlStyle.indexContainer);
         mdlgen.addClassListing(div);
         htmlTree.addContent(div);
         if (configuration.allowTag(HtmlTag.MAIN)) {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleIndexWriter.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleIndexWriter.java	Thu Nov 16 15:01:45 2017 -0800
@@ -25,13 +25,15 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
+
 import java.util.*;
 
 import javax.lang.model.element.ModuleElement;
 import javax.lang.model.element.PackageElement;
 
-
-import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr;
+import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
@@ -40,8 +42,6 @@
 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
 import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
-import jdk.javadoc.internal.doclets.toolkit.util.Group;
-import jdk.javadoc.internal.doclets.toolkit.util.GroupTypes;
 
 /**
  * Generate the module index page "overview-summary.html" for the right-hand
@@ -57,28 +57,6 @@
 public class ModuleIndexWriter extends AbstractModuleIndexWriter {
 
     /**
-     * Map representing the group of modules as specified on the command line.
-     *
-     * @see Group
-     */
-    private final Map<String, SortedSet<ModuleElement>> groupModuleMap;
-
-    /**
-     * List to store the order groups, which has elements to be displayed, as specified on the command line.
-     */
-    private final List<String> groupList = new ArrayList<>();
-
-    private final GroupTypes groupTypes;
-
-    private int groupTypesOr = 0;
-
-    protected Map<String, Integer> groupTypeMap = new LinkedHashMap<>();
-
-    boolean altColor = true;
-
-    int counter = 0;
-
-    /**
      * HTML tree for main tag.
      */
     private final HtmlTree htmlTree = HtmlTree.MAIN();
@@ -90,11 +68,6 @@
      */
     public ModuleIndexWriter(HtmlConfiguration configuration, DocPath filename) {
         super(configuration, filename);
-        groupModuleMap = configuration.group.groupModules(configuration.modules);
-        configuration.group.getGroupList().stream()
-                .filter(groupModuleMap::containsKey)
-                .forEach(groupList::add);
-        groupTypes = new GroupTypes(groupList, resources.getText("doclet.All_Modules"));
     }
 
     /**
@@ -128,7 +101,7 @@
         HtmlTree htmltree = (configuration.allowTag(HtmlTag.NAV))
                 ? HtmlTree.NAV()
                 : new HtmlTree(HtmlTag.DIV);
-        htmltree.addStyle(HtmlStyle.indexNav);
+        htmltree.setStyle(HtmlStyle.indexNav);
         HtmlTree ul = new HtmlTree(HtmlTag.UL);
         addAllClassesLink(ul);
         if (configuration.showModules) {
@@ -144,68 +117,53 @@
      *
      * @param body the content tree to which the module list will be added
      */
+    @Override
     protected void addModulesList(Content body) {
-        if (!groupList.isEmpty()) {
-            Content caption;
-            TreeMap<ModuleElement, String> groupMap = new TreeMap<>(utils.makeModuleComparator());
-            Content tbody = new HtmlTree(HtmlTag.TBODY);
+        Map<String, SortedSet<ModuleElement>> groupModuleMap
+                = configuration.group.groupModules(configuration.modules);
+
+        if (!groupModuleMap.keySet().isEmpty()) {
             String tableSummary = configuration.getText("doclet.Member_Table_Summary",
                     configuration.getText("doclet.Module_Summary"), configuration.getText("doclet.modules"));
-            for (String groupname : groupList) {
-                for (ModuleElement mdle : groupModuleMap.get(groupname)) {
-                    groupMap.put(mdle, groupname);
+            TableHeader header = new TableHeader(contents.moduleLabel, contents.descriptionLabel);
+            Table table =  new Table(configuration.htmlVersion, HtmlStyle.overviewSummary)
+                    .setSummary(tableSummary)
+                    .setHeader(header)
+                    .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colLast)
+                    .setDefaultTab(resources.getText("doclet.All_Modules"))
+                    .setTabScriptVariable("groups")
+                    .setTabScript(i -> "showGroups(" + i + ");")
+                    .setTabId(i -> (i == 0) ? "t0" : ("t" + (1 << (i - 1))));
+
+            // add the tabs in command-line order
+            for (String groupName : configuration.group.getGroupList()) {
+                Set<ModuleElement> groupModules = groupModuleMap.get(groupName);
+                if (groupModules != null) {
+                    table.addTab(groupName, groupModules::contains);
                 }
             }
-            if (!groupMap.isEmpty()) {
-                addModulesList(groupMap, tbody);
+
+            for (ModuleElement mdle : configuration.modules) {
+                if (!mdle.isUnnamed()) {
+                    if (!(configuration.nodeprecated && utils.isDeprecated(mdle))) {
+                        Content moduleLinkContent = getModuleLink(mdle, new StringContent(mdle.getQualifiedName().toString()));
+                        Content summaryContent = new ContentBuilder();
+                        addSummaryComment(mdle, summaryContent);
+                        table.addRow(mdle, moduleLinkContent, summaryContent);
+                    }
+                }
             }
-            if (showTabs(groupTypes)) {
-                caption = getTableCaption(groupTypes);
-                generateGroupTypesScript(groupTypeMap, groupTypes.getGroupTypes());
-            } else {
-                caption = getTableCaption((groupList.size() == 1) ? new StringContent(groupList.get(0)) : contents.modulesLabel);
-            }
-            Content table = getTableHeader(caption, tableSummary, HtmlStyle.overviewSummary);
-            Content header = new TableHeader(contents.moduleLabel, contents.descriptionLabel).toContent();
-            table.addContent(header);
-            table.addContent(tbody);
-            Content div = HtmlTree.DIV(HtmlStyle.contentContainer, table);
+
+            Content div = HtmlTree.DIV(HtmlStyle.contentContainer, table.toContent());
             if (configuration.allowTag(HtmlTag.MAIN)) {
                 htmlTree.addContent(div);
             } else {
                 body.addContent(div);
             }
-        }
-    }
 
-    /**
-     * Adds list of modules in the index table. Generate link to each module.
-     *
-     * @param map map of module elements and group names
-     * @param tbody the documentation tree to which the list will be added
-     */
-    protected void addModulesList(TreeMap<ModuleElement, String> map, Content tbody) {
-        String groupname;
-        for (ModuleElement mdle : map.keySet()) {
-            if (!mdle.isUnnamed()) {
-                groupname = map.get(mdle);
-                Content moduleLinkContent = getModuleLink(mdle, new StringContent(mdle.getQualifiedName().toString()));
-                Content thModule = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, moduleLinkContent);
-                HtmlTree tdSummary = new HtmlTree(HtmlTag.TD);
-                tdSummary.addStyle(HtmlStyle.colLast);
-                addSummaryComment(mdle, tdSummary);
-                HtmlTree tr = HtmlTree.TR(thModule);
-                tr.addContent(tdSummary);
-                tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
-                int groupType = groupTypes.getTableTab(groupname).value();
-                groupTypesOr = groupTypesOr | groupType;
-                String tableId = "i" + counter;
-                counter++;
-                groupTypeMap.put(tableId, groupType);
-                tr.addAttr(HtmlAttr.ID, tableId);
-                tbody.addContent(tr);
+            if (table.needsScript()) {
+                getScript().addContent(table.getScript());
             }
-            altColor = !altColor;
         }
     }
 
@@ -221,7 +179,7 @@
         addConfigurationTitle(body);
         if (!utils.getFullBody(configuration.overviewElement).isEmpty()) {
             HtmlTree div = new HtmlTree(HtmlTag.DIV);
-            div.addStyle(HtmlStyle.contentContainer);
+            div.setStyle(HtmlStyle.contentContainer);
             addOverviewComment(div);
             if (configuration.allowTag(HtmlTag.MAIN)) {
                 htmlTree.addContent(div);
@@ -265,13 +223,13 @@
      */
     @Override
     protected void addNavigationBarHeader(Content body) {
-        Content htmlTree = (configuration.allowTag(HtmlTag.HEADER))
+        Content tree = (configuration.allowTag(HtmlTag.HEADER))
                 ? HtmlTree.HEADER()
                 : body;
-        addTop(htmlTree);
-        addNavLinks(true, htmlTree);
+        addTop(tree);
+        addNavLinks(true, tree);
         if (configuration.allowTag(HtmlTag.HEADER)) {
-            body.addContent(htmlTree);
+            body.addContent(tree);
         }
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java	Thu Nov 16 15:01:45 2017 -0800
@@ -25,9 +25,11 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
+
+import java.util.ArrayList;
 import java.util.Collections;
-import java.util.EnumSet;
-import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -43,7 +45,7 @@
 
 import com.sun.source.doctree.DocTree;
 import jdk.javadoc.doclet.DocletEnvironment.ModuleMode;
-import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr;
+import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
@@ -55,7 +57,6 @@
 import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
-import jdk.javadoc.internal.doclets.toolkit.util.ModulePackageTypes;
 
 /**
  * Class to generate file for each module contents in the right-hand frame. This will list all the
@@ -157,12 +158,6 @@
     private final Map<TypeElement, Content> providesTrees
             = new TreeMap<>(utils.makeAllClassesComparator());
 
-    private int packageTypesOr = 0;
-
-    protected Set<ModulePackageTypes> modulePackageTypes = EnumSet.noneOf(ModulePackageTypes.class);
-
-    protected Map<String, Integer> typeMap = new LinkedHashMap<>();
-
     /**
      * The HTML tree for main tag.
      */
@@ -208,7 +203,7 @@
             bodyTree.addContent(htmlTree);
         }
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
-        div.addStyle(HtmlStyle.header);
+        div.setStyle(HtmlStyle.header);
         Content annotationContent = new HtmlTree(HtmlTag.P);
         addAnnotationInfo(mdle, annotationContent);
         div.addContent(annotationContent);
@@ -234,7 +229,7 @@
     @Override
     public Content getContentHeader() {
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
-        div.addStyle(HtmlStyle.contentContainer);
+        div.setStyle(HtmlStyle.contentContainer);
         return div;
     }
 
@@ -244,7 +239,7 @@
     @Override
     public Content getSummaryHeader() {
         HtmlTree li = new HtmlTree(HtmlTag.LI);
-        li.addStyle(HtmlStyle.blockList);
+        li.setStyle(HtmlStyle.blockList);
         return li;
     }
 
@@ -465,21 +460,7 @@
     }
 
     /**
-     * Get a table.
-     *
-     * @param text the table caption
-     * @param tableSummary the summary for the table
-     * @param tableStyle the table style
-     * @param tableHeader the table header
-     * @return a content object
-     */
-    Content getTable(String text, String tableSummary, HtmlStyle tableStyle,
-            TableHeader tableHeader) {
-        return getTable(getTableCaption(new RawHtml(text)), tableSummary, tableStyle, tableHeader);
-    }
-
-    /**
-     * Get a table.
+     * Get a table, with two columns.
      *
      * @param caption the table caption
      * @param tableSummary the summary for the table
@@ -487,13 +468,32 @@
      * @param tableHeader the table header
      * @return a content object
      */
-    Content getTable(Content caption, String tableSummary, HtmlStyle tableStyle,
+    private Table getTable2(Content caption, String tableSummary, HtmlStyle tableStyle,
             TableHeader tableHeader) {
-        Content table = (configuration.isOutputHtml5())
-                ? HtmlTree.TABLE(tableStyle, caption)
-                : HtmlTree.TABLE(tableStyle, tableSummary, caption);
-        table.addContent(tableHeader.toContent());
-        return table;
+        return new Table(configuration.htmlVersion, tableStyle)
+                .setSummary(tableSummary)
+                .setCaption(caption)
+                .setHeader(tableHeader)
+                .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colLast);
+    }
+
+    /**
+     * Get a table, with three columns, with the second column being the defining column.
+     *
+     * @param caption the table caption
+     * @param tableSummary the summary for the table
+     * @param tableStyle the table style
+     * @param tableHeader the table header
+     * @return a content object
+     */
+    private Table getTable3(Content caption, String tableSummary, HtmlStyle tableStyle,
+            TableHeader tableHeader) {
+        return new Table(configuration.htmlVersion, tableStyle)
+                .setSummary(tableSummary)
+                .setCaption(caption)
+                .setHeader(tableHeader)
+                .setRowScopeColumn(1)
+                .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colSecond, HtmlStyle.colLast);
     }
 
     /**
@@ -506,33 +506,31 @@
                     new TableHeader(contents.modifierLabel, contents.moduleLabel,
                             contents.descriptionLabel);
             HtmlTree li = new HtmlTree(HtmlTag.LI);
-            li.addStyle(HtmlStyle.blockList);
+            li.setStyle(HtmlStyle.blockList);
             addSummaryHeader(HtmlConstants.START_OF_MODULES_SUMMARY, SectionName.MODULES,
                     contents.navModules, li);
             if (display(requires)) {
-                String text = configuration.getText("doclet.Requires_Summary");
-                String tableSummary = configuration.getText("doclet.Member_Table_Summary",
+                String text = resources.getText("doclet.Requires_Summary");
+                String tableSummary = resources.getText("doclet.Member_Table_Summary",
                         text,
-                        configuration.getText("doclet.modules"));
-                Content table = getTable(text, tableSummary, HtmlStyle.requiresSummary,
-                        requiresTableHeader);
-                Content tbody = new HtmlTree(HtmlTag.TBODY);
-                addModulesList(requires, tbody);
-                table.addContent(tbody);
-                li.addContent(table);
+                        resources.getText("doclet.modules"));
+                Content caption = getTableCaption(new StringContent(text));
+                Table table = getTable3(caption, tableSummary, HtmlStyle.requiresSummary,
+                            requiresTableHeader);
+                addModulesList(requires, table);
+                li.addContent(table.toContent());
             }
             // Display indirect modules table in both "api" and "all" mode.
             if (display(indirectModules)) {
-                String amrText = configuration.getText("doclet.Indirect_Requires_Summary");
-                String amrTableSummary = configuration.getText("doclet.Member_Table_Summary",
+                String amrText = resources.getText("doclet.Indirect_Requires_Summary");
+                String amrTableSummary = resources.getText("doclet.Member_Table_Summary",
                         amrText,
                         configuration.getText("doclet.modules"));
-                Content amrTable = getTable(amrText, amrTableSummary, HtmlStyle.requiresSummary,
-                        requiresTableHeader);
-                Content amrTbody = new HtmlTree(HtmlTag.TBODY);
-                addModulesList(indirectModules, amrTbody);
-                amrTable.addContent(amrTbody);
-                li.addContent(amrTable);
+                Content amrCaption = getTableCaption(new StringContent(amrText));
+                Table amrTable = getTable3(amrCaption, amrTableSummary, HtmlStyle.requiresSummary,
+                            requiresTableHeader);
+                addModulesList(indirectModules, amrTable);
+                li.addContent(amrTable.toContent());
             }
             HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, li);
             summaryContentTree.addContent(ul);
@@ -545,21 +543,13 @@
      * @param mdleMap map of modules and modifiers
      * @param tbody the content tree to which the list will be added
      */
-    public void addModulesList(Map<ModuleElement, Content> mdleMap, Content tbody) {
-        boolean altColor = true;
+    private void addModulesList(Map<ModuleElement, Content> mdleMap, Table table) {
         for (ModuleElement m : mdleMap.keySet()) {
-            Content tdModifiers = HtmlTree.TD(HtmlStyle.colFirst, mdleMap.get(m));
-            Content moduleLinkContent = getModuleLink(m, new StringContent(m.getQualifiedName()));
-            Content thModule = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colSecond, moduleLinkContent);
-            HtmlTree tdSummary = new HtmlTree(HtmlTag.TD);
-            tdSummary.addStyle(HtmlStyle.colLast);
-            addSummaryComment(m, tdSummary);
-            HtmlTree tr = HtmlTree.TR(tdModifiers);
-            tr.addContent(thModule);
-            tr.addContent(tdSummary);
-            tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
-            tbody.addContent(tr);
-            altColor = !altColor;
+            Content modifiers = mdleMap.get(m);
+            Content moduleLink = getModuleLink(m, new StringContent(m.getQualifiedName()));
+            Content moduleSummary = new ContentBuilder();
+            addSummaryComment(m, moduleSummary);
+            table.addRow(modifiers, moduleLink, moduleSummary);
         }
     }
 
@@ -568,42 +558,38 @@
         if (display(exportedPackages) || display(openedPackages) || display(concealedPackages)
                 || display(indirectPackages) || display(indirectOpenPackages)) {
             HtmlTree li = new HtmlTree(HtmlTag.LI);
-            li.addStyle(HtmlStyle.blockList);
+            li.setStyle(HtmlStyle.blockList);
             addSummaryHeader(HtmlConstants.START_OF_PACKAGES_SUMMARY, SectionName.PACKAGES,
                     contents.navPackages, li);
-            String tableSummary = configuration.getText("doclet.Member_Table_Summary",
-                    configuration.getText("doclet.Packages_Summary"),
-                    configuration.getText("doclet.packages"));
             if (display(exportedPackages) || display(openedPackages) || display(concealedPackages)) {
+                String tableSummary = resources.getText("doclet.Member_Table_Summary",
+                        resources.getText("doclet.Packages_Summary"),
+                        resources.getText("doclet.packages"));
                 addPackageSummary(tableSummary, li);
             }
             TableHeader indirectPackagesHeader =
                     new TableHeader(contents.fromLabel, contents.packagesLabel);
             if (display(indirectPackages)) {
-                String aepText = configuration.getText("doclet.Indirect_Exports_Summary");
-                String aepTableSummary = configuration.getText("doclet.Indirect_Packages_Table_Summary",
+                String aepText = resources.getText("doclet.Indirect_Exports_Summary");
+                String aepTableSummary = resources.getText("doclet.Indirect_Packages_Table_Summary",
                         aepText,
-                        configuration.getText("doclet.modules"),
-                        configuration.getText("doclet.packages"));
-                Content aepTable = getTable(aepText, aepTableSummary, HtmlStyle.packagesSummary,
-                        indirectPackagesHeader);
-                Content aepTbody = new HtmlTree(HtmlTag.TBODY);
-                addIndirectPackages(aepTbody, indirectPackages);
-                aepTable.addContent(aepTbody);
-                li.addContent(aepTable);
+                        resources.getText("doclet.modules"),
+                        resources.getText("doclet.packages"));
+                Table aepTable = getTable2(new StringContent(aepText), aepTableSummary,
+                        HtmlStyle.packagesSummary, indirectPackagesHeader);
+                addIndirectPackages(aepTable, indirectPackages);
+                li.addContent(aepTable.toContent());
             }
             if (display(indirectOpenPackages)) {
-                String aopText = configuration.getText("doclet.Indirect_Opens_Summary");
-                String aopTableSummary = configuration.getText("doclet.Indirect_Packages_Table_Summary",
+                String aopText = resources.getText("doclet.Indirect_Opens_Summary");
+                String aopTableSummary = resources.getText("doclet.Indirect_Packages_Table_Summary",
                         aopText,
-                        configuration.getText("doclet.modules"),
-                        configuration.getText("doclet.packages"));
-                Content aopTable = getTable(aopText, aopTableSummary, HtmlStyle.packagesSummary,
-                        indirectPackagesHeader);
-                Content aopTbody = new HtmlTree(HtmlTag.TBODY);
-                addIndirectPackages(aopTbody, indirectOpenPackages);
-                aopTable.addContent(aopTbody);
-                li.addContent(aopTable);
+                        resources.getText("doclet.modules"),
+                        resources.getText("doclet.packages"));
+                Table aopTable = getTable2(new StringContent(aopText), aopTableSummary,
+                        HtmlStyle.packagesSummary, indirectPackagesHeader);
+                addIndirectPackages(aopTable, indirectOpenPackages);
+                li.addContent(aopTable.toContent());
             }
             HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, li);
             summaryContentTree.addContent(ul);
@@ -617,79 +603,31 @@
      * @param li
      */
     public void addPackageSummary(String tableSummary, HtmlTree li) {
-        Content caption;
-        Content tbody = getPackageTableRows();
-        if (showTabs()) {
-            caption = getTableCaption();
-            generateTableTabTypesScript(typeMap, modulePackageTypes, "packages");
-        } else {
-            ModulePackageTypes type = modulePackageTypes.iterator().next();
-            caption = getTableCaption(configuration.getContent(type.tableTabs().resourceKey()));
-        }
-        TableHeader header = (configuration.docEnv.getModuleMode() == ModuleMode.ALL)
-                ? new TableHeader(contents.packageLabel, contents.moduleLabel, contents.descriptionLabel)
-                : new TableHeader(contents.packageLabel, contents.descriptionLabel);
-        Content table = getTable(caption, tableSummary, HtmlStyle.packagesSummary, header);
-        table.addContent(tbody);
-        li.addContent(table);
-    }
-
-    /**
-     * Returns true if the table tabs needs to be displayed.
-     *
-     * @return true if the tabs should be displayed
-     */
-    public boolean showTabs() {
-        int value;
-        for (ModulePackageTypes type : EnumSet.allOf(ModulePackageTypes.class)) {
-            value = type.tableTabs().value();
-            if ((value & packageTypesOr) == value) {
-                modulePackageTypes.add(type);
-            }
-        }
-        boolean showTabs = modulePackageTypes.size() > 1;
-        if (showTabs) {
-            modulePackageTypes.add(ModulePackageTypes.ALL);
-        }
-        return showTabs;
-    }
+        Table table = new Table(configuration.htmlVersion, HtmlStyle.packagesSummary)
+                .setSummary(tableSummary)
+                .setDefaultTab(resources.getText("doclet.All_Packages"))
+                .addTab(resources.getText("doclet.Exported_Packages_Summary"),
+                        e -> exportedPackages.containsKey((PackageElement) e))
+                .addTab(resources.getText("doclet.Opened_Packages_Summary"),
+                        e -> openedPackages.containsKey((PackageElement) e))
+                .addTab(resources.getText("doclet.Concealed_Packages_Summary"),
+                        e -> concealedPackages.contains((PackageElement) e))
+                .setTabScript(i -> String.format("showPkgs(%d);", i))
+                .setTabScriptVariable("packages");
 
-    /**
-     * Get the summary table caption.
-     *
-     * @return the caption for the summary table
-     */
-    public Content getTableCaption() {
-        Content tabbedCaption = new HtmlTree(HtmlTag.CAPTION);
-        for (ModulePackageTypes type : modulePackageTypes) {
-            Content captionSpan;
-            Content span;
-            if (type.tableTabs().isDefaultTab()) {
-                captionSpan = HtmlTree.SPAN(configuration.getContent(type.tableTabs().resourceKey()));
-                span = HtmlTree.SPAN(type.tableTabs().tabId(),
-                        HtmlStyle.activeTableTab, captionSpan);
-            } else {
-                captionSpan = HtmlTree.SPAN(getPackageTypeLinks(type));
-                span = HtmlTree.SPAN(type.tableTabs().tabId(),
-                        HtmlStyle.tableTab, captionSpan);
-            }
-            Content tabSpan = HtmlTree.SPAN(HtmlStyle.tabEnd, Contents.SPACE);
-            span.addContent(tabSpan);
-            tabbedCaption.addContent(span);
+        if (configuration.docEnv.getModuleMode() == ModuleMode.API) {
+            table.setHeader(new TableHeader(contents.packageLabel, contents.descriptionLabel))
+                    .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colLast);
+        } else {
+            table.setHeader(new TableHeader(contents.packageLabel, contents.moduleLabel, contents.descriptionLabel))
+                    .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colSecond, HtmlStyle.colLast);
         }
-        return tabbedCaption;
-    }
 
-    /**
-     * Get the package type links for the table caption.
-     *
-     * @param packageType the package type to be displayed as link
-     * @return the content tree for the package type link
-     */
-    public Content getPackageTypeLinks(ModulePackageTypes packageType) {
-        String jsShow = "javascript:showPkgs(" + packageType.tableTabs().value() + ");";
-        HtmlTree link = HtmlTree.A(jsShow, configuration.getContent(packageType.tableTabs().resourceKey()));
-        return link;
+        addPackageTableRows(table);
+        li.addContent(table.toContent());
+        if (table.needsScript()) {
+            script.addContent(new RawHtml(table.getScript()));
+        }
     }
 
     /**
@@ -697,109 +635,70 @@
      *
      * @return a content object
      */
-    public Content getPackageTableRows() {
-        Content tbody = new HtmlTree(HtmlTag.TBODY);
-        boolean altColor = true;
-        int counter = 0;
-        counter = addPackageTableRows(tbody, counter, ModulePackageTypes.EXPORTED, exportedPackages);
-        counter = addPackageTableRows(tbody, counter, ModulePackageTypes.OPENED, openedPackages);
+    private void addPackageTableRows(Table table) {
+        addPackageTableRows(table, exportedPackages);
+        addPackageTableRows(table, openedPackages);
         // Show concealed packages only in "all" mode.
         if (moduleMode == ModuleMode.ALL) {
             for (PackageElement pkg : concealedPackages) {
                 Content pkgLinkContent = getPackageLink(pkg, new StringContent(utils.getPackageName(pkg)));
-                Content thPackage = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, pkgLinkContent);
-                HtmlTree tdModules = new HtmlTree(HtmlTag.TD);
-                tdModules.addStyle(HtmlStyle.colSecond);
-                tdModules.addContent(configuration.getText("doclet.None"));
-                HtmlTree tdSummary = new HtmlTree(HtmlTag.TD);
-                tdSummary.addStyle(HtmlStyle.colLast);
-                addSummaryComment(pkg, tdSummary);
-                HtmlTree tr = HtmlTree.TR(thPackage);
-                tr.addContent(tdModules);
-                tr.addContent(tdSummary);
-                tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
-                int pkgType = ModulePackageTypes.CONCEALED.tableTabs().value();
-                packageTypesOr = packageTypesOr | pkgType;
-                String tableId = "i" + counter;
-                counter++;
-                typeMap.put(tableId, pkgType);
-                tr.addAttr(HtmlAttr.ID, tableId);
-                tbody.addContent(tr);
-                altColor = !altColor;
+                Content noModules = new StringContent(resources.getText("doclet.None"));
+                Content summary = new ContentBuilder();
+                addSummaryComment(pkg, summary);
+                table.addRow(pkg, pkgLinkContent, noModules, summary);
             }
         }
-        return tbody;
     }
 
-    public int addPackageTableRows(Content tbody, int counter, ModulePackageTypes pType,
-            Map<PackageElement,SortedSet<ModuleElement>> ap) {
-        boolean altColor = true;
+    private void addPackageTableRows(Table table, Map<PackageElement,SortedSet<ModuleElement>> ap) {
         for (Map.Entry<PackageElement, SortedSet<ModuleElement>> entry : ap.entrySet()) {
+            List<Content> row = new ArrayList<>();
             PackageElement pkg = entry.getKey();
             SortedSet<ModuleElement> mdleList = entry.getValue();
             Content pkgLinkContent = getPackageLink(pkg, new StringContent(utils.getPackageName(pkg)));
-            Content thPackage = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, pkgLinkContent);
-            HtmlTree tr = HtmlTree.TR(thPackage);
+            row.add(pkgLinkContent);
+
             if (moduleMode == ModuleMode.ALL) {
-                HtmlTree tdModules = new HtmlTree(HtmlTag.TD);
-                tdModules.addStyle(HtmlStyle.colSecond);
+                Content modules = new ContentBuilder();
                 if (!mdleList.isEmpty()) {
-                    int sep = 0;
                     for (ModuleElement m : mdleList) {
-                        if (sep > 0) {
-                            tdModules.addContent(new HtmlTree(HtmlTag.BR));
+                        if (!modules.isEmpty()) {
+                            modules.addContent(new HtmlTree(HtmlTag.BR));
                         }
-                        tdModules.addContent(getModuleLink(m, new StringContent(m.getQualifiedName())));
-                        sep++;
+                        modules.addContent(getModuleLink(m, new StringContent(m.getQualifiedName())));
                     }
                 } else {
-                    tdModules.addContent(configuration.getText("doclet.All_Modules"));
+                    Content allModules = new StringContent(resources.getText("doclet.All_Modules"));
+                    modules.addContent(allModules);
                 }
-                tr.addContent(tdModules);
+                row.add(modules);
             }
-            HtmlTree tdSummary = new HtmlTree(HtmlTag.TD);
-            tdSummary.addStyle(HtmlStyle.colLast);
-            addSummaryComment(pkg, tdSummary);
-            tr.addContent(tdSummary);
-            tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
-            int pkgType = pType.tableTabs().value();
-            packageTypesOr = packageTypesOr | pkgType;
-            String tableId = "i" + counter;
-            counter++;
-            typeMap.put(tableId, pkgType);
-            tr.addAttr(HtmlAttr.ID, tableId);
-            tbody.addContent(tr);
-            altColor = !altColor;
+            Content summary = new ContentBuilder();
+            addSummaryComment(pkg, summary);
+            row.add(summary);
+            table.addRow(pkg, row);
         }
-        return counter;
     }
 
     /**
      * Add the indirect packages for the module being documented.
      *
-     * @param tbody the content tree to which the table will be added
+     * @param table the table to which the content rows will be added
      * @param ip indirect packages to be added
      */
-    public void addIndirectPackages(Content tbody, Map<ModuleElement, SortedSet<PackageElement>> ip) {
-        boolean altColor = true;
+    public void addIndirectPackages(Table table, Map<ModuleElement, SortedSet<PackageElement>> ip) {
         for (Map.Entry<ModuleElement, SortedSet<PackageElement>> entry : ip.entrySet()) {
             ModuleElement m = entry.getKey();
             SortedSet<PackageElement> pkgList = entry.getValue();
             Content moduleLinkContent = getModuleLink(m, new StringContent(m.getQualifiedName()));
-            Content thModule = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, moduleLinkContent);
-            HtmlTree tdPackages = new HtmlTree(HtmlTag.TD);
-            tdPackages.addStyle(HtmlStyle.colLast);
+            Content packages = new ContentBuilder();
             String sep = "";
             for (PackageElement pkg : pkgList) {
-                tdPackages.addContent(sep);
-                tdPackages.addContent(getPackageLink(pkg, new StringContent(utils.getPackageName(pkg))));
+                packages.addContent(sep);
+                packages.addContent(getPackageLink(pkg, new StringContent(utils.getPackageName(pkg))));
                 sep = " ";
             }
-            HtmlTree tr = HtmlTree.TR(thModule);
-            tr.addContent(tdPackages);
-            tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
-            tbody.addContent(tr);
-            altColor = !altColor;
+            table.addRow(moduleLinkContent, packages);
         }
     }
 
@@ -814,7 +713,7 @@
 
         if (haveProvides || haveUses) {
             HtmlTree li = new HtmlTree(HtmlTag.LI);
-            li.addStyle(HtmlStyle.blockList);
+            li.setStyle(HtmlStyle.blockList);
             addSummaryHeader(HtmlConstants.START_OF_SERVICES_SUMMARY, SectionName.SERVICES,
                     contents.navServices, li);
             TableHeader usesProvidesTableHeader =
@@ -822,27 +721,25 @@
             if (haveProvides) {
                 String label = resources.getText("doclet.Provides_Summary");
                 String tableSummary = resources.getText("doclet.Member_Table_Summary",
-                        label, resources.getText("doclet.types"));
-                Content table = getTable(label, tableSummary, HtmlStyle.providesSummary,
+                        label,
+                        resources.getText("doclet.types"));
+                Table table = getTable2(new StringContent(label), tableSummary, HtmlStyle.providesSummary,
                         usesProvidesTableHeader);
-                Content tbody = new HtmlTree(HtmlTag.TBODY);
-                addProvidesList(tbody);
-                if (!tbody.isEmpty()) {
-                    table.addContent(tbody);
-                    li.addContent(table);
+                addProvidesList(table);
+                if (!table.isEmpty()) {
+                    li.addContent(table.toContent());
                 }
             }
             if (haveUses){
                 String label = resources.getText("doclet.Uses_Summary");
                 String tableSummary = resources.getText("doclet.Member_Table_Summary",
-                        label, resources.getText("doclet.types"));
-                Content table = getTable(label, tableSummary, HtmlStyle.usesSummary,
+                        label,
+                        resources.getText("doclet.types"));
+                Table table = getTable2(new StringContent(label), tableSummary, HtmlStyle.usesSummary,
                         usesProvidesTableHeader);
-                Content tbody = new HtmlTree(HtmlTag.TBODY);
-                addUsesList(tbody);
-                if (!tbody.isEmpty()) {
-                    table.addContent(tbody);
-                    li.addContent(table);
+                addUsesList(table);
+                if (!table.isEmpty()) {
+                    li.addContent(table.toContent());
                 }
             }
             HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, li);
@@ -853,44 +750,34 @@
     /**
      * Add the uses list for the module.
      *
-     * @param tbody the content tree to which the directive will be added
+     * @param table the table to which the services used will be added
      */
-    public void addUsesList(Content tbody) {
-        boolean altColor = true;
+    public void addUsesList(Table table) {
         Content typeLinkContent;
-        Content thType;
-        HtmlTree tdSummary;
         Content description;
         for (TypeElement t : uses) {
             if (!displayServiceDirective(t, usesTrees)) {
                 continue;
             }
             typeLinkContent = getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.PACKAGE, t));
-            thType = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, typeLinkContent);
-            tdSummary = new HtmlTree(HtmlTag.TD);
-            tdSummary.addStyle(HtmlStyle.colLast);
+            Content summary = new ContentBuilder();
             if (display(usesTrees)) {
                 description = usesTrees.get(t);
                 if (description != null) {
-                    tdSummary.addContent(description);
+                    summary.addContent(description);
                 }
             }
-            addSummaryComment(t, tdSummary);
-            HtmlTree tr = HtmlTree.TR(thType);
-            tr.addContent(tdSummary);
-            tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
-            tbody.addContent(tr);
-            altColor = !altColor;
+            addSummaryComment(t, summary);
+            table.addRow(typeLinkContent, summary);
         }
     }
 
     /**
      * Add the provides list for the module.
      *
-     * @param tbody the content tree to which the directive will be added
+     * @param table the table to which the services provided will be added
      */
-    public void addProvidesList(Content tbody) {
-        boolean altColor = true;
+    public void addProvidesList(Table table) {
         SortedSet<TypeElement> implSet;
         Content description;
         for (Map.Entry<TypeElement, SortedSet<TypeElement>> entry : provides.entrySet()) {
@@ -900,36 +787,30 @@
             }
             implSet = entry.getValue();
             Content srvLinkContent = getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.PACKAGE, srv));
-            HtmlTree thType = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, srvLinkContent);
-            HtmlTree tdDesc = new HtmlTree(HtmlTag.TD);
-            tdDesc.addStyle(HtmlStyle.colLast);
+            Content desc = new ContentBuilder();
             if (display(providesTrees)) {
                 description = providesTrees.get(srv);
                 if (description != null) {
-                    tdDesc.addContent(description);
+                    desc.addContent(description);
                 }
             }
-            addSummaryComment(srv, tdDesc);
+            addSummaryComment(srv, desc);
             // Only display the implementation details in the "all" mode.
             if (moduleMode == ModuleMode.ALL && !implSet.isEmpty()) {
-                tdDesc.addContent(new HtmlTree(HtmlTag.BR));
-                tdDesc.addContent("(");
+                desc.addContent(new HtmlTree(HtmlTag.BR));
+                desc.addContent("(");
                 HtmlTree implSpan = HtmlTree.SPAN(HtmlStyle.implementationLabel, contents.implementation);
-                tdDesc.addContent(implSpan);
-                tdDesc.addContent(Contents.SPACE);
+                desc.addContent(implSpan);
+                desc.addContent(Contents.SPACE);
                 String sep = "";
                 for (TypeElement impl : implSet) {
-                    tdDesc.addContent(sep);
-                    tdDesc.addContent(getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.PACKAGE, impl)));
+                    desc.addContent(sep);
+                    desc.addContent(getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.PACKAGE, impl)));
                     sep = ", ";
                 }
-                tdDesc.addContent(")");
+                desc.addContent(")");
             }
-            HtmlTree tr = HtmlTree.TR(thType);
-            tr.addContent(tdDesc);
-            tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
-            tbody.addContent(tr);
-            altColor = !altColor;
+            table.addRow(srvLinkContent, desc);
         }
     }
 
@@ -943,7 +824,7 @@
         if (utils.isDeprecated(mdle)) {
             CommentHelper ch = utils.getCommentHelper(mdle);
             HtmlTree deprDiv = new HtmlTree(HtmlTag.DIV);
-            deprDiv.addStyle(HtmlStyle.deprecationBlock);
+            deprDiv.setStyle(HtmlStyle.deprecationBlock);
             Content deprPhrase = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, getDeprecatedPhrase(mdle));
             deprDiv.addContent(deprPhrase);
             if (!deprs.isEmpty()) {
@@ -1078,7 +959,7 @@
         if (utils.isDeprecated(pkg)) {
             deprs = utils.getDeprecatedTrees(pkg);
             HtmlTree deprDiv = new HtmlTree(HtmlTag.DIV);
-            deprDiv.addStyle(HtmlStyle.deprecationBlock);
+            deprDiv.setStyle(HtmlStyle.deprecationBlock);
             Content deprPhrase = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, getDeprecatedPhrase(pkg));
             deprDiv.addContent(deprPhrase);
             if (!deprs.isEmpty()) {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/NestedClassWriterImpl.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/NestedClassWriterImpl.java	Thu Nov 16 15:01:45 2017 -0800
@@ -25,10 +25,15 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
+
+import java.util.Arrays;
+import java.util.List;
+
 import javax.lang.model.element.Element;
 import javax.lang.model.element.TypeElement;
 
-import jdk.javadoc.internal.doclets.formats.html.TableHeader;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
@@ -94,33 +99,29 @@
      * {@inheritDoc}
      */
     @Override
-    public String getTableSummary() {
-        return resources.getText("doclet.Member_Table_Summary",
-                resources.getText("doclet.Nested_Class_Summary"),
-                resources.getText("doclet.nested_classes"));
-    }
+    public TableHeader getSummaryTableHeader(Element member) {
+        Content label = utils.isInterface(member) ?
+                contents.interfaceLabel : contents.classLabel;
 
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public Content getCaption() {
-        return configuration.getContent("doclet.Nested_Classes");
+        return new TableHeader(contents.modifierAndTypeLabel, label, contents.descriptionLabel);
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
-    public TableHeader getSummaryTableHeader(Element member) {
-        if (utils.isInterface(member)) {
-            return new TableHeader(contents.modifierAndTypeLabel, contents.interfaceLabel,
-                    contents.descriptionLabel);
+    protected Table createSummaryTable() {
+        String summary =  resources.getText("doclet.Member_Table_Summary",
+                resources.getText("doclet.Nested_Class_Summary"),
+                resources.getText("doclet.nested_classes"));
+
+        List<HtmlStyle> bodyRowStyles = Arrays.asList(HtmlStyle.colFirst, HtmlStyle.colSecond,
+                HtmlStyle.colLast);
 
-        } else {
-            return new TableHeader(contents.modifierAndTypeLabel, contents.classLabel,
-                    contents.descriptionLabel);
-        }
+        return new Table(configuration.htmlVersion, HtmlStyle.memberSummary)
+                .setSummary(summary)
+                .setCaption(contents.getContent("doclet.Nested_Classes"))
+                .setHeader(getSummaryTableHeader(typeElement))
+                .setRowScopeColumn(1)
+                .setColumnStyles(bodyRowStyles)
+                .setUseTBody(false);  // temporary? compatibility mode for TBody
     }
 
     /**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageFrameWriter.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageFrameWriter.java	Thu Nov 16 15:01:45 2017 -0800
@@ -108,7 +108,7 @@
                 packgen.getTargetPackageLink(packageElement, "classFrame", pkgNameContent));
         htmlTree.addContent(heading);
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
-        div.addStyle(HtmlStyle.indexContainer);
+        div.setStyle(HtmlStyle.indexContainer);
         packgen.addClassListing(div);
         htmlTree.addContent(div);
         if (configuration.allowTag(HtmlTag.MAIN)) {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexWriter.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexWriter.java	Thu Nov 16 15:01:45 2017 -0800
@@ -25,21 +25,21 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+
 import java.util.*;
 
 import javax.lang.model.element.PackageElement;
 
-import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr;
+import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
-import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
 import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
 import jdk.javadoc.internal.doclets.toolkit.util.Group;
-import jdk.javadoc.internal.doclets.toolkit.util.GroupTypes;
 
 /**
  * Generate the package index page "overview-summary.html" for the right-hand
@@ -56,29 +56,6 @@
  */
 public class PackageIndexWriter extends AbstractPackageIndexWriter {
 
-
-    /**
-     * Map representing the group of packages as specified on the command line.
-     *
-     * @see Group
-     */
-    private final Map<String, SortedSet<PackageElement>> groupPackageMap;
-
-    /**
-     * List to store the order groups, which has elements to be displayed, as specified on the command line.
-     */
-    private final List<String> groupList = new ArrayList<>();
-
-    private final GroupTypes groupTypes;
-
-    private int groupTypesOr = 0;
-
-    protected Map<String, Integer> groupTypeMap = new LinkedHashMap<>();
-
-    boolean altColor = true;
-
-    int counter = 0;
-
     /**
      * HTML tree for main tag.
      */
@@ -95,11 +72,6 @@
      */
     public PackageIndexWriter(HtmlConfiguration configuration, DocPath filename) {
         super(configuration, filename);
-        groupPackageMap = configuration.group.groupPackages(packages);
-        configuration.group.getGroupList().stream()
-                .filter(groupPackageMap::containsKey)
-                .forEachOrdered(groupList::add);
-        groupTypes = new GroupTypes(groupList, resources.getText("doclet.All_Packages"));
     }
 
     /**
@@ -130,68 +102,50 @@
      */
     @Override
     protected void addPackagesList(Content body) {
-        if (!groupList.isEmpty()) {
-            Content caption;
-            TreeMap<PackageElement, String> groupMap = new TreeMap<>(utils.makePackageComparator());
-            Content tbody = new HtmlTree(HtmlTag.TBODY);
+        Map<String, SortedSet<PackageElement>> groupPackageMap
+                = configuration.group.groupPackages(packages);
+
+        if (!groupPackageMap.keySet().isEmpty()) {
             String tableSummary = configuration.getText("doclet.Member_Table_Summary",
                     configuration.getText("doclet.Package_Summary"), configuration.getText("doclet.packages"));
-            for (String groupname : groupList) {
-                for (PackageElement pkg : groupPackageMap.get(groupname)) {
-                    groupMap.put(pkg, groupname);
+            Table table =  new Table(configuration.htmlVersion, HtmlStyle.overviewSummary)
+                    .setSummary(tableSummary)
+                    .setHeader(getPackageTableHeader())
+                    .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colLast)
+                    .setDefaultTab(resources.getText("doclet.All_Packages"))
+                    .setTabScriptVariable("groups")
+                    .setTabScript(i -> "showGroups(" + i + ");")
+                    .setTabId(i -> (i == 0) ? "t0" : ("t" + (1 << (i - 1))));
+
+            // add the tabs in command-line order
+            for (String groupName : configuration.group.getGroupList()) {
+                Set<PackageElement> groupPackages = groupPackageMap.get(groupName);
+                if (groupPackages != null) {
+                    table.addTab(groupName, groupPackages::contains);
                 }
             }
-            if (!groupMap.isEmpty()) {
-                addPackagesList(groupMap, tbody);
+
+            for (PackageElement pkg : configuration.packages) {
+                if (!pkg.isUnnamed()) {
+                    if (!(configuration.nodeprecated && utils.isDeprecated(pkg))) {
+                        Content packageLinkContent = getPackageLink(pkg, getPackageName(pkg));
+                        Content summaryContent = new ContentBuilder();
+                        addSummaryComment(pkg, summaryContent);
+                        table.addRow(pkg, packageLinkContent, summaryContent);
+                    }
+                }
             }
-            if (showTabs(groupTypes)) {
-                caption = getTableCaption(groupTypes);
-                generateGroupTypesScript(groupTypeMap, groupTypes.getGroupTypes());
-            } else {
-                caption = getTableCaption((groupList.size() == 1) ? new StringContent(groupList.get(0)) : contents.packagesLabel);
-            }
-            Content table = getTableHeader(caption, tableSummary, HtmlStyle.overviewSummary);
-            table.addContent(getPackageTableHeader().toContent());
-            table.addContent(tbody);
-            Content div = HtmlTree.DIV(HtmlStyle.contentContainer, table);
+
+            Content div = HtmlTree.DIV(HtmlStyle.contentContainer, table.toContent());
             if (configuration.allowTag(HtmlTag.MAIN)) {
                 htmlTree.addContent(div);
             } else {
                 body.addContent(div);
             }
-        }
-    }
 
-    /**
-     * Adds list of packages in the index table. Generate link to each package.
-     *
-     * @param map map of package elements and group names
-     * @param tbody the documentation tree to which the list will be added
-     */
-    protected void addPackagesList(TreeMap<PackageElement, String> map, Content tbody) {
-        String groupname;
-        for (PackageElement pkg : map.keySet()) {
-            if (!pkg.isUnnamed()) {
-                if (!(configuration.nodeprecated && utils.isDeprecated(pkg))) {
-                    groupname = map.get(pkg);
-                    Content packageLinkContent = getPackageLink(pkg, getPackageName(pkg));
-                    Content thPackage = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, packageLinkContent);
-                    HtmlTree tdSummary = new HtmlTree(HtmlTag.TD);
-                    tdSummary.addStyle(HtmlStyle.colLast);
-                    addSummaryComment(pkg, tdSummary);
-                    HtmlTree tr = HtmlTree.TR(thPackage);
-                    tr.addContent(tdSummary);
-                    tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
-                    int groupType = groupTypes.getTableTab(groupname).value();
-                    groupTypesOr = groupTypesOr | groupType;
-                    String tableId = "i" + counter;
-                    counter++;
-                    groupTypeMap.put(tableId, groupType);
-                    tr.addAttr(HtmlAttr.ID, tableId);
-                    tbody.addContent(tr);
-                }
+            if (table.needsScript()) {
+                getScript().addContent(table.getScript());
             }
-            altColor = !altColor;
         }
     }
 
@@ -207,7 +161,7 @@
         addConfigurationTitle(body);
         if (!utils.getFullBody(configuration.overviewElement).isEmpty()) {
             HtmlTree div = new HtmlTree(HtmlTag.DIV);
-            div.addStyle(HtmlStyle.contentContainer);
+            div.setStyle(HtmlStyle.contentContainer);
             addOverviewComment(div);
             if (configuration.allowTag(HtmlTag.MAIN)) {
                 htmlTree.addContent(div);
@@ -251,13 +205,13 @@
      */
     @Override
     protected void addNavigationBarHeader(Content body) {
-        Content htmlTree = (configuration.allowTag(HtmlTag.HEADER))
+        Content tree = (configuration.allowTag(HtmlTag.HEADER))
                 ? HtmlTree.HEADER()
                 : body;
-        addTop(htmlTree);
-        addNavLinks(true, htmlTree);
+        addTop(tree);
+        addNavLinks(true, tree);
         if (configuration.allowTag(HtmlTag.HEADER)) {
-            body.addContent(htmlTree);
+            body.addContent(tree);
         }
     }
 
@@ -269,13 +223,13 @@
      */
     @Override
     protected void addNavigationBarFooter(Content body) {
-        Content htmlTree = (configuration.allowTag(HtmlTag.FOOTER))
+        Content tree = (configuration.allowTag(HtmlTag.FOOTER))
                 ? HtmlTree.FOOTER()
                 : body;
-        addNavLinks(false, htmlTree);
-        addBottom(htmlTree);
+        addNavLinks(false, tree);
+        addBottom(tree);
         if (configuration.allowTag(HtmlTag.FOOTER)) {
-            body.addContent(htmlTree);
+            body.addContent(tree);
         }
     }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageTreeWriter.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageTreeWriter.java	Thu Nov 16 15:01:45 2017 -0800
@@ -126,7 +126,7 @@
         }
         htmlTree.addContent(div);
         HtmlTree divTree = new HtmlTree(HtmlTag.DIV);
-        divTree.addStyle(HtmlStyle.contentContainer);
+        divTree.setStyle(HtmlStyle.contentContainer);
         addTree(classtree.baseClasses(), "doclet.Class_Hierarchy", divTree);
         addTree(classtree.baseInterfaces(), "doclet.Interface_Hierarchy", divTree);
         addTree(classtree.baseAnnotationTypes(), "doclet.Annotation_Type_Hierarchy", divTree);
@@ -176,7 +176,7 @@
                 contents.packageHierarchies);
         div.addContent(span);
         HtmlTree ul = new HtmlTree (HtmlTag.UL);
-        ul.addStyle(HtmlStyle.horizontal);
+        ul.setStyle(HtmlStyle.horizontal);
         ul.addContent(getNavLinkMainTree(configuration.getText("doclet.All_Packages")));
         div.addContent(ul);
     }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java	Thu Nov 16 15:01:45 2017 -0800
@@ -25,6 +25,9 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
+
 import java.util.*;
 
 import javax.lang.model.element.PackageElement;
@@ -121,7 +124,7 @@
     protected void generatePackageUseFile() throws DocFileIOException {
         HtmlTree body = getPackageUseHeader();
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
-        div.addStyle(HtmlStyle.contentContainer);
+        div.setStyle(HtmlStyle.contentContainer);
         if (usingPackageToUsedClasses.isEmpty()) {
             div.addContent(contents.getContent("doclet.ClassUse_No.usage.of.0", utils.getPackageName(packageElement)));
         } else {
@@ -151,7 +154,7 @@
      */
     protected void addPackageUse(Content contentTree) {
         HtmlTree ul = new HtmlTree(HtmlTag.UL);
-        ul.addStyle(HtmlStyle.blockList);
+        ul.setStyle(HtmlStyle.blockList);
         if (configuration.packages.size() > 1) {
             addPackageList(ul);
         }
@@ -165,25 +168,27 @@
      * @param contentTree the content tree to which the package list will be added
      */
     protected void addPackageList(Content contentTree) {
-        Content caption = getTableCaption(configuration.getContent(
+        Content caption = contents.getContent(
                 "doclet.ClassUse_Packages.that.use.0",
-                getPackageLink(packageElement, utils.getPackageName(packageElement))));
-        Content table = (configuration.isOutputHtml5())
-                ? HtmlTree.TABLE(HtmlStyle.useSummary, caption)
-                : HtmlTree.TABLE(HtmlStyle.useSummary, packageUseTableSummary, caption);
-        table.addContent(getPackageTableHeader().toContent());
-        Content tbody = new HtmlTree(HtmlTag.TBODY);
-        boolean altColor = true;
+                getPackageLink(packageElement, utils.getPackageName(packageElement)));
+        Table table = new Table(configuration.htmlVersion, HtmlStyle.useSummary)
+                .setSummary(packageUseTableSummary)
+                .setCaption(caption)
+                .setHeader(getPackageTableHeader())
+                .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colLast);
         for (String pkgname: usingPackageToUsedClasses.keySet()) {
             PackageElement pkg = utils.elementUtils.getPackageElement(pkgname);
-            HtmlTree tr = new HtmlTree(HtmlTag.TR);
-            tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
-            altColor = !altColor;
-            addPackageUse(pkg, tr);
-            tbody.addContent(tr);
+            Content packageLink = getHyperLink(utils.getPackageName(pkg),
+                    new StringContent(utils.getPackageName(pkg)));
+            Content summary = new ContentBuilder();
+            if (pkg != null && !pkg.isUnnamed()) {
+                addSummaryComment(pkg, summary);
+            } else {
+                summary.addContent(Contents.SPACE);
+            }
+            table.addRow(packageLink, summary);
         }
-        table.addContent(tbody);
-        Content li = HtmlTree.LI(HtmlStyle.blockList, table);
+        Content li = HtmlTree.LI(HtmlStyle.blockList, table.toContent());
         contentTree.addContent(li);
     }
 
@@ -198,86 +203,46 @@
         for (String packageName : usingPackageToUsedClasses.keySet()) {
             PackageElement usingPackage = utils.elementUtils.getPackageElement(packageName);
             HtmlTree li = new HtmlTree(HtmlTag.LI);
-            li.addStyle(HtmlStyle.blockList);
+            li.setStyle(HtmlStyle.blockList);
             if (usingPackage != null) {
                 li.addContent(getMarkerAnchor(utils.getPackageName(usingPackage)));
             }
-            String tableSummary = configuration.getText("doclet.Use_Table_Summary",
-                                                        configuration.getText("doclet.classes"));
-            Content caption = getTableCaption(configuration.getContent(
+            String tableSummary = resources.getText("doclet.Use_Table_Summary",
+                                                        resources.getText("doclet.classes"));
+            Content caption = contents.getContent(
                     "doclet.ClassUse_Classes.in.0.used.by.1",
                     getPackageLink(packageElement, utils.getPackageName(packageElement)),
-                    getPackageLink(usingPackage, utils.getPackageName(usingPackage))));
-            Content table = (configuration.isOutputHtml5())
-                    ? HtmlTree.TABLE(HtmlStyle.useSummary, caption)
-                    : HtmlTree.TABLE(HtmlStyle.useSummary, tableSummary, caption);
-            table.addContent(classTableHeader.toContent());
-            Content tbody = new HtmlTree(HtmlTag.TBODY);
-            boolean altColor = true;
+                    getPackageLink(usingPackage, utils.getPackageName(usingPackage)));
+            Table table = new Table(configuration.htmlVersion, HtmlStyle.useSummary)
+                    .setSummary(tableSummary)
+                    .setCaption(caption)
+                    .setHeader(classTableHeader)
+                    .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colLast);
             for (TypeElement te : usingPackageToUsedClasses.get(packageName)) {
-                HtmlTree tr = new HtmlTree(HtmlTag.TR);
-                tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
-                altColor = !altColor;
-                addClassRow(te, usingPackage, tr);
-                tbody.addContent(tr);
+                DocPath dp = pathString(te,
+                        DocPaths.CLASS_USE.resolve(DocPath.forName(utils, te)));
+                Content stringContent = new StringContent(utils.getSimpleName(te));
+                Content typeContent = getHyperLink(dp.fragment(getPackageAnchorName(usingPackage)),
+                        stringContent);
+                Content summary = new ContentBuilder();
+                addIndexComment(te, summary);
+
+                table.addRow(typeContent, summary);
             }
-            table.addContent(tbody);
-            li.addContent(table);
+            li.addContent(table.toContent());
             contentTree.addContent(li);
         }
     }
 
     /**
-     * Add a row for the class that uses the given package.
-     *
-     * @param usedClass the class that uses the given package
-     * @param pkg  the package to which the class belongs
-     * @param contentTree the content tree to which the row will be added
-     */
-    protected void addClassRow(TypeElement usedClass, PackageElement pkg,
-            Content contentTree) {
-        DocPath dp = pathString(usedClass,
-                DocPaths.CLASS_USE.resolve(DocPath.forName(utils, usedClass)));
-        StringContent stringContent = new StringContent(utils.getSimpleName(usedClass));
-        Content thType = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst,
-                getHyperLink(dp.fragment(getPackageAnchorName(pkg)), stringContent));
-        contentTree.addContent(thType);
-        HtmlTree tdDesc = new HtmlTree(HtmlTag.TD);
-        tdDesc.addStyle(HtmlStyle.colLast);
-        addIndexComment(usedClass, tdDesc);
-        contentTree.addContent(tdDesc);
-    }
-
-    /**
-     * Add the package use information.
-     *
-     * @param pkg the package that used the given package
-     * @param contentTree the content tree to which the information will be added
-     */
-    protected void addPackageUse(PackageElement pkg, Content contentTree) {
-        Content thFirst = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst,
-                getHyperLink(utils.getPackageName(pkg),
-                new StringContent(utils.getPackageName(pkg))));
-        contentTree.addContent(thFirst);
-        HtmlTree tdLast = new HtmlTree(HtmlTag.TD);
-        tdLast.addStyle(HtmlStyle.colLast);
-        if (pkg != null && !pkg.isUnnamed()) {
-            addSummaryComment(pkg, tdLast);
-        } else {
-            tdLast.addContent(Contents.SPACE);
-        }
-        contentTree.addContent(tdLast);
-    }
-
-    /**
      * Get the header for the package use listing.
      *
      * @return a content tree representing the package use header
      */
-    protected HtmlTree getPackageUseHeader() {
-        String packageText = configuration.getText("doclet.Package");
+    private HtmlTree getPackageUseHeader() {
+        String packageText = resources.getText("doclet.Package");
         String name = packageElement.isUnnamed() ? "" : utils.getPackageName(packageElement);
-        String title = configuration.getText("doclet.Window_ClassUse_Header", packageText, name);
+        String title = resources.getText("doclet.Window_ClassUse_Header", packageText, name);
         HtmlTree bodyTree = getBody(true, getWindowTitle(title));
         HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER))
                 ? HtmlTree.HEADER()
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java	Thu Nov 16 15:01:45 2017 -0800
@@ -25,6 +25,9 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
+
 import java.util.*;
 
 import javax.lang.model.element.ModuleElement;
@@ -32,11 +35,11 @@
 import javax.lang.model.element.TypeElement;
 
 import com.sun.source.doctree.DocTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
-import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.PackageSummaryWriter;
@@ -124,7 +127,7 @@
             bodyTree.addContent(htmlTree);
         }
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
-        div.addStyle(HtmlStyle.header);
+        div.setStyle(HtmlStyle.header);
         if (configuration.showModules) {
             ModuleElement mdle = configuration.docEnv.getElementUtils().getModuleOf(packageElement);
             Content classModuleLabel = HtmlTree.SPAN(HtmlStyle.moduleLabelInPackage, contents.moduleLabel);
@@ -157,7 +160,7 @@
     @Override
     public Content getContentHeader() {
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
-        div.addStyle(HtmlStyle.contentContainer);
+        div.setStyle(HtmlStyle.contentContainer);
         return div;
     }
 
@@ -171,7 +174,7 @@
         if (utils.isDeprecated(packageElement)) {
             CommentHelper ch = utils.getCommentHelper(packageElement);
             HtmlTree deprDiv = new HtmlTree(HtmlTag.DIV);
-            deprDiv.addStyle(HtmlStyle.deprecationBlock);
+            deprDiv.setStyle(HtmlStyle.deprecationBlock);
             Content deprPhrase = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, getDeprecatedPhrase(packageElement));
             deprDiv.addContent(deprPhrase);
             if (!deprs.isEmpty()) {
@@ -190,7 +193,7 @@
     @Override
     public Content getSummaryHeader() {
         HtmlTree ul = new HtmlTree(HtmlTag.UL);
-        ul.addStyle(HtmlStyle.blockList);
+        ul.setStyle(HtmlStyle.blockList);
         return ul;
     }
 
@@ -278,47 +281,34 @@
         addClassesSummary(annoTypes, label, tableSummary, tableHeader, summaryContentTree);
     }
 
-    /**
-     * {@inheritDoc}
-     */
     public void addClassesSummary(SortedSet<TypeElement> classes, String label,
             String tableSummary, TableHeader tableHeader, Content summaryContentTree) {
         if(!classes.isEmpty()) {
-            Content caption = getTableCaption(new RawHtml(label));
-            Content table = (configuration.isOutputHtml5())
-                    ? HtmlTree.TABLE(HtmlStyle.typeSummary, caption)
-                    : HtmlTree.TABLE(HtmlStyle.typeSummary, tableSummary, caption);
-            table.addContent(tableHeader.toContent());
-            Content tbody = new HtmlTree(HtmlTag.TBODY);
-            boolean altColor = false;
+            Table table = new Table(configuration.htmlVersion, HtmlStyle.typeSummary)
+                    .setSummary(tableSummary)
+                    .setCaption(getTableCaption(new StringContent(label)))
+                    .setHeader(tableHeader)
+                    .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colLast);
+
             for (TypeElement klass : classes) {
-                if (!utils.isCoreClass(klass) ||
-                    !configuration.isGeneratedDoc(klass)) {
+                if (!utils.isCoreClass(klass) || !configuration.isGeneratedDoc(klass)) {
                     continue;
                 }
-                altColor = !altColor;
-                Content classContent = getLink(new LinkInfoImpl(
+                Content classLink = getLink(new LinkInfoImpl(
                         configuration, LinkInfoImpl.Kind.PACKAGE, klass));
-                Content thClass = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, classContent);
-                HtmlTree tr = HtmlTree.TR(thClass);
-                tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
-
-                HtmlTree tdClassDescription = new HtmlTree(HtmlTag.TD);
-                tdClassDescription.addStyle(HtmlStyle.colLast);
+                ContentBuilder description = new ContentBuilder();
                 if (utils.isDeprecated(klass)) {
-                    tdClassDescription.addContent(getDeprecatedPhrase(klass));
+                    description.addContent(getDeprecatedPhrase(klass));
                     List<? extends DocTree> tags = utils.getDeprecatedTrees(klass);
                     if (!tags.isEmpty()) {
-                        addSummaryDeprecatedComment(klass, tags.get(0), tdClassDescription);
+                        addSummaryDeprecatedComment(klass, tags.get(0), description);
                     }
                 } else {
-                    addSummaryComment(klass, tdClassDescription);
+                    addSummaryComment(klass, description);
                 }
-                tr.addContent(tdClassDescription);
-                tbody.addContent(tr);
+                table.addRow(classLink, description);
             }
-            table.addContent(tbody);
-            Content li = HtmlTree.LI(HtmlStyle.blockList, table);
+            Content li = HtmlTree.LI(HtmlStyle.blockList, table.toContent());
             summaryContentTree.addContent(li);
         }
     }
@@ -411,8 +401,8 @@
         if (prev == null) {
             li = HtmlTree.LI(contents.prevPackageLabel);
         } else {
-            DocPath path = DocPath.relativePath(packageElement, prev);
-            li = HtmlTree.LI(getHyperLink(path.resolve(DocPaths.PACKAGE_SUMMARY),
+            DocPath p = DocPath.relativePath(packageElement, prev);
+            li = HtmlTree.LI(getHyperLink(p.resolve(DocPaths.PACKAGE_SUMMARY),
                 contents.prevPackageLabel, "", ""));
         }
         return li;
@@ -429,8 +419,8 @@
         if (next == null) {
             li = HtmlTree.LI(contents.nextPackageLabel);
         } else {
-            DocPath path = DocPath.relativePath(packageElement, next);
-            li = HtmlTree.LI(getHyperLink(path.resolve(DocPaths.PACKAGE_SUMMARY),
+            DocPath p = DocPath.relativePath(packageElement, next);
+            li = HtmlTree.LI(getHyperLink(p.resolve(DocPaths.PACKAGE_SUMMARY),
                 contents.nextPackageLabel, "", ""));
         }
         return li;
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java	Thu Nov 16 15:01:45 2017 -0800
@@ -26,11 +26,13 @@
 package jdk.javadoc.internal.doclets.formats.html;
 
 
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
+
 import javax.lang.model.element.Element;
 import javax.lang.model.element.ExecutableElement;
 import javax.lang.model.element.TypeElement;
 
-import jdk.javadoc.internal.doclets.formats.html.TableHeader;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
@@ -72,11 +74,6 @@
         return memberTree;
     }
 
-    @Override
-    public boolean showTabs() {
-        return false;
-    }
-
     /**
      * {@inheritDoc}
      */
@@ -218,27 +215,27 @@
      * {@inheritDoc}
      */
     @Override
-    public String getTableSummary() {
-        return resources.getText("doclet.Member_Table_Summary",
-                resources.getText("doclet.Property_Summary"),
-                resources.getText("doclet.properties"));
+    public TableHeader getSummaryTableHeader(Element member) {
+        return new TableHeader(contents.typeLabel, contents.propertyLabel,
+                contents.descriptionLabel);
     }
 
     /**
      * {@inheritDoc}
      */
     @Override
-    public Content getCaption() {
-        return contents.properties;
-    }
+    protected Table createSummaryTable() {
+        String summary = resources.getText("doclet.Member_Table_Summary",
+            resources.getText("doclet.Property_Summary"),
+            resources.getText("doclet.properties"));
 
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public TableHeader getSummaryTableHeader(Element member) {
-        return new TableHeader(contents.typeLabel, contents.propertyLabel,
-                contents.descriptionLabel);
+        return new Table(configuration.htmlVersion, HtmlStyle.memberSummary)
+                .setSummary(summary)
+                .setCaption(contents.properties)
+                .setHeader(getSummaryTableHeader(typeElement))
+                .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colSecond, HtmlStyle.colLast)
+                .setRowScopeColumn(1)
+                .setUseTBody(false);
     }
 
     /**
@@ -270,12 +267,12 @@
         Content label;
         if (configuration.summarizeOverriddenMethods) {
             label = new StringContent(utils.isClass(typeElement)
-                    ? configuration.getText("doclet.Properties_Declared_In_Class")
-                    : configuration.getText("doclet.Properties_Declared_In_Interface"));
+                    ? resources.getText("doclet.Properties_Declared_In_Class")
+                    : resources.getText("doclet.Properties_Declared_In_Interface"));
         } else {
             label = new StringContent(utils.isClass(typeElement)
-                    ? configuration.getText("doclet.Properties_Inherited_From_Class")
-                    : configuration.getText("doclet.Properties_Inherited_From_Interface"));
+                    ? resources.getText("doclet.Properties_Inherited_From_Class")
+                    : resources.getText("doclet.Properties_Inherited_From_Interface"));
         }
         Content labelHeading = HtmlTree.HEADING(HtmlConstants.INHERITED_SUMMARY_HEADING,
                 label);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SerializedFormWriterImpl.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SerializedFormWriterImpl.java	Thu Nov 16 15:01:45 2017 -0800
@@ -102,7 +102,7 @@
      */
     public Content getSerializedSummariesHeader() {
         HtmlTree ul = new HtmlTree(HtmlTag.UL);
-        ul.addStyle(HtmlStyle.blockList);
+        ul.setStyle(HtmlStyle.blockList);
         return ul;
     }
 
@@ -117,7 +117,7 @@
             htmlTree = HtmlTree.SECTION();
         } else {
             htmlTree = new HtmlTree(HtmlTag.LI);
-            htmlTree.addStyle(HtmlStyle.blockList);
+            htmlTree.setStyle(HtmlStyle.blockList);
         }
         return htmlTree;
     }
@@ -143,7 +143,7 @@
      */
     public Content getClassSerializedHeader() {
         HtmlTree ul = new HtmlTree(HtmlTag.UL);
-        ul.addStyle(HtmlStyle.blockList);
+        ul.setStyle(HtmlStyle.blockList);
         return ul;
     }
 
@@ -194,7 +194,7 @@
      */
     public Content getSerialUIDInfoHeader() {
         HtmlTree dl = new HtmlTree(HtmlTag.DL);
-        dl.addStyle(HtmlStyle.nameValue);
+        dl.setStyle(HtmlStyle.nameValue);
         return dl;
     }
 
@@ -221,7 +221,7 @@
      */
     public Content getClassContentHeader() {
         HtmlTree ul = new HtmlTree(HtmlTag.UL);
-        ul.addStyle(HtmlStyle.blockList);
+        ul.setStyle(HtmlStyle.blockList);
         return ul;
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SingleIndexWriter.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SingleIndexWriter.java	Thu Nov 16 15:01:45 2017 -0800
@@ -102,7 +102,7 @@
             body.addContent(htmlTree);
         }
         HtmlTree divTree = new HtmlTree(HtmlTag.DIV);
-        divTree.addStyle(HtmlStyle.contentContainer);
+        divTree.setStyle(HtmlStyle.contentContainer);
         elements = new TreeSet<>(indexbuilder.getIndexMap().keySet());
         elements.addAll(configuration.tagSearchIndexKeys);
         addLinksForIndexes(divTree);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SourceToHTMLConverter.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SourceToHTMLConverter.java	Thu Nov 16 15:01:45 2017 -0800
@@ -275,7 +275,7 @@
      */
     private static void addLineNo(Content pre, int lineno) {
         HtmlTree span = new HtmlTree(HtmlTag.SPAN);
-        span.addStyle(HtmlStyle.sourceLineNo);
+        span.setStyle(HtmlStyle.sourceLineNo);
         if (lineno < 10) {
             span.addContent("00" + Integer.toString(lineno));
         } else if (lineno < 100) {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SplitIndexWriter.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SplitIndexWriter.java	Thu Nov 16 15:01:45 2017 -0800
@@ -145,7 +145,7 @@
             body.addContent(htmlTree);
         }
         HtmlTree divTree = new HtmlTree(HtmlTag.DIV);
-        divTree.addStyle(HtmlStyle.contentContainer);
+        divTree.setStyle(HtmlStyle.contentContainer);
         addLinksForIndexes(divTree);
         if (configuration.tagSearchIndexMap.get(unicode) == null) {
             addContents(unicode, indexbuilder.getMemberList(unicode), divTree);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SubWriterHolderWriter.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SubWriterHolderWriter.java	Thu Nov 16 15:01:45 2017 -0800
@@ -36,7 +36,6 @@
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
-import jdk.javadoc.internal.doclets.toolkit.util.MethodTypes;
 
 /**
  * This abstract class exists to provide functionality needed in the
@@ -73,7 +72,7 @@
      * Add the summary header.
      *
      * @param mw the writer for the member being documented
-     * @param typeElement the te to be documented
+     * @param typeElement the type element to be documented
      * @param memberTree the content tree to which the summary header will be added
      */
     public void addSummaryHeader(AbstractMemberWriter mw, TypeElement typeElement,
@@ -83,74 +82,6 @@
     }
 
     /**
-     * Get the summary table.
-     *
-     * @param mw the writer for the member being documented
-     * @param typeElement the te to be documented
-     * @param tableContents list of summary table contents
-     * @param showTabs true if the table needs to show tabs
-     * @return the content tree for the summary table
-     */
-    public Content getSummaryTableTree(AbstractMemberWriter mw, TypeElement typeElement,
-            List<Content> tableContents, boolean showTabs) {
-        Content caption;
-        if (showTabs) {
-            caption = getTableCaption(mw.methodTypes);
-            generateTableTabTypesScript(mw.typeMap, mw.methodTypes, "methods");
-        }
-        else {
-            caption = getTableCaption(mw.getCaption());
-        }
-        Content table = (configuration.isOutputHtml5())
-                ? HtmlTree.TABLE(HtmlStyle.memberSummary, caption)
-                : HtmlTree.TABLE(HtmlStyle.memberSummary, mw.getTableSummary(), caption);
-        table.addContent(mw.getSummaryTableHeader(typeElement).toContent());
-        for (Content tableContent : tableContents) {
-            table.addContent(tableContent);
-        }
-        return table;
-    }
-
-    /**
-     * Get the summary table caption.
-     *
-     * @param methodTypes set comprising of method types to show as table caption
-     * @return the caption for the summary table
-     */
-    public Content getTableCaption(Set<MethodTypes> methodTypes) {
-        Content tabbedCaption = new HtmlTree(HtmlTag.CAPTION);
-        for (MethodTypes type : methodTypes) {
-            Content captionSpan;
-            Content span;
-            if (type.tableTabs().isDefaultTab()) {
-                captionSpan = HtmlTree.SPAN(configuration.getContent(type.tableTabs().resourceKey()));
-                span = HtmlTree.SPAN(type.tableTabs().tabId(),
-                        HtmlStyle.activeTableTab, captionSpan);
-            } else {
-                captionSpan = HtmlTree.SPAN(getMethodTypeLinks(type));
-                span = HtmlTree.SPAN(type.tableTabs().tabId(),
-                        HtmlStyle.tableTab, captionSpan);
-            }
-            Content tabSpan = HtmlTree.SPAN(HtmlStyle.tabEnd, Contents.SPACE);
-            span.addContent(tabSpan);
-            tabbedCaption.addContent(span);
-        }
-        return tabbedCaption;
-    }
-
-    /**
-     * Get the method type links for the table caption.
-     *
-     * @param methodType the method type to be displayed as link
-     * @return the content tree for the method type link
-     */
-    public Content getMethodTypeLinks(MethodTypes methodType) {
-        String jsShow = "javascript:show(" + methodType.tableTabs().value() +");";
-        HtmlTree link = HtmlTree.A(jsShow, configuration.getContent(methodType.tableTabs().resourceKey()));
-        return link;
-    }
-
-    /**
      * Add the inherited summary header.
      *
      * @param mw the writer for the member being documented
@@ -205,17 +136,6 @@
     }
 
     /**
-     * Add the summary type for the member.
-     *
-     * @param mw the writer for the member being documented
-     * @param member the member to be documented
-     * @param tdSummaryType the content tree to which the type will be added
-     */
-    public void addSummaryType(AbstractMemberWriter mw, Element member, Content tdSummaryType) {
-        mw.addSummaryType(member, tdSummaryType);
-    }
-
-    /**
      * Add the summary link for the member.
      *
      * @param mw the writer for the member being documented
@@ -264,7 +184,7 @@
      */
     public Content getContentHeader() {
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
-        div.addStyle(HtmlStyle.contentContainer);
+        div.setStyle(HtmlStyle.contentContainer);
         return div;
     }
 
@@ -300,7 +220,7 @@
      */
     public Content getMemberTreeHeader() {
         HtmlTree li = new HtmlTree(HtmlTag.LI);
-        li.addStyle(HtmlStyle.blockList);
+        li.setStyle(HtmlStyle.blockList);
         return li;
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TableHeader.java	Thu Nov 16 20:25:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.javadoc.internal.doclets.formats.html;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.stream.Collectors;
-
-import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
-import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
-import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
-import jdk.javadoc.internal.doclets.toolkit.Content;
-
-/**
- * A row header for an HTML table.
- *
- * The header contains a list of {@code <th>} cells, providing the column headers.
- * The attribute {@code scope="col"} is automatically added to each header cell.
- * In addition, a series of style class names can be specified, to be applied one per cell.
- *
- */
-public class TableHeader {
-
-    /**
-     * The content to be put in each of the {@code <th>} cells in the header row.
-     */
-    private final List<Content> cellContents;
-    /**
-     * The style class names for each of the {@code <th>} cells in the header row.
-     * If not set, default style names will be used.
-     */
-    private List<HtmlStyle> styles;
-
-    /**
-     * Creates a header row, with localized content for each cell.
-     * Resources keys will be converted to content using {@link Contents#getContent(String)}.
-     * @param contents a factory to get the content for each header cell.
-     * @param colHeaderKeys the resource keys for the content in each cell.
-     */
-    TableHeader(Contents contents, String... colHeaderKeys) {
-        this.cellContents = Arrays.stream(colHeaderKeys)
-                .map((key) -> contents.getContent(key))
-                .collect(Collectors.toList());
-    }
-
-    /**
-     * Creates a header row, with specified content for each cell.
-     * @param headerCellContents a content object for each header cell
-     */
-    TableHeader(Content... headerCellContents) {
-        this.cellContents = Arrays.asList(headerCellContents);
-    }
-
-    /**
-     * Set the style class names for each header cell.
-     * The number of names must match the number of cells given to the constructor.
-     * @param styles the style class names
-     * @return this object
-     */
-    TableHeader styles(HtmlStyle... styles) {
-        if (styles.length != cellContents.size()) {
-            throw new IllegalStateException();
-        }
-        this.styles = Arrays.asList(styles);
-        return this;
-    }
-
-    /**
-     * Converts this header to a {@link Content} object, for use in an {@link HtmlTree}.
-     * @returns a Content object
-     */
-    Content toContent() {
-        String scope = "col";
-        Content tr = new HtmlTree(HtmlTag.TR);
-        int i = 0;
-        for (Content cellContent : cellContents) {
-            HtmlStyle style = (styles != null) ? styles.get(i)
-                    : (i == 0) ? HtmlStyle.colFirst
-                    : (i == (cellContents.size() - 1)) ? HtmlStyle.colLast
-                    : (i == 1) ? HtmlStyle.colSecond : null;
-            Content cell = (style == null) ? HtmlTree.TH(scope, cellContent)
-                    : HtmlTree.TH(style, scope, cellContent);
-            tr.addContent(cell);
-            i++;
-        }
-        return tr;
-    }
-
-}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TreeWriter.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TreeWriter.java	Thu Nov 16 15:01:45 2017 -0800
@@ -112,7 +112,7 @@
                 : body;
         htmlTree.addContent(div);
         HtmlTree divTree = new HtmlTree(HtmlTag.DIV);
-        divTree.addStyle(HtmlStyle.contentContainer);
+        divTree.setStyle(HtmlStyle.contentContainer);
         addTree(classtree.baseClasses(), "doclet.Class_Hierarchy", divTree);
         addTree(classtree.baseInterfaces(), "doclet.Interface_Hierarchy", divTree);
         addTree(classtree.baseAnnotationTypes(), "doclet.Annotation_Type_Hierarchy", divTree);
@@ -149,7 +149,7 @@
                     contents.packageHierarchies);
             contentTree.addContent(span);
             HtmlTree ul = new HtmlTree(HtmlTag.UL);
-            ul.addStyle(HtmlStyle.horizontal);
+            ul.setStyle(HtmlStyle.horizontal);
             int i = 0;
             for (PackageElement pkg : packages) {
                 // If the package name length is 0 or if -nodeprecated option
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java	Thu Nov 16 15:01:45 2017 -0800
@@ -52,7 +52,7 @@
  */
 public class HtmlTree extends Content {
 
-    private HtmlTag htmlTag;
+    public final HtmlTag htmlTag;
     private Map<HtmlAttr,String> attrs = Collections.emptyMap();
     private List<Content> content = Collections.emptyList();
     public static final Content EMPTY = new StringContent("");
@@ -79,32 +79,63 @@
     }
 
     /**
+     * Constructor to construct HtmlTree object.
+     *
+     * @param tag HTML tag for the HtmlTree object
+     * @param contents contents to be added to the tree
+     */
+    public HtmlTree(HtmlTag tag, List<Content> contents) {
+        this(tag);
+        for (Content content: contents)
+            addContent(content);
+    }
+
+    /**
      * Adds an attribute for the HTML tag.
      *
      * @param attrName name of the attribute
      * @param attrValue value of the attribute
+     * @return this object
      */
-    public void addAttr(HtmlAttr attrName, String attrValue) {
+    public HtmlTree addAttr(HtmlAttr attrName, String attrValue) {
         if (attrs.isEmpty())
             attrs = new LinkedHashMap<>(3);
         attrs.put(nullCheck(attrName), escapeHtmlChars(attrValue));
+        return this;
     }
 
-    public void setTitle(Content body) {
+    /**
+     * Sets the "title" attribute for this tag.
+     * Any HTML tags in the content will be removed.
+     *
+     * @param body the content for the title attribute
+     * @return this object
+     */
+    public HtmlTree setTitle(Content body) {
         addAttr(HtmlAttr.TITLE, stripHtml(body));
-    }
-
-    public void setRole(Role role) {
-        addAttr(HtmlAttr.ROLE, role.toString());
+        return this;
     }
 
     /**
-     * Adds a style for the HTML tag.
+     * Sets the "role" attribute for this tag.
+     *
+     * @param role the role
+     * @return this object
+     */
+    public HtmlTree setRole(Role role) {
+        addAttr(HtmlAttr.ROLE, role.toString());
+        return this;
+    }
+
+    /**
+     * Sets the style for the HTML tag.
      *
      * @param style style to be added
+     * @return this object
      */
-    public void addStyle(HtmlStyle style) {
+    public HtmlTree setStyle(HtmlStyle style) {
         addAttr(HtmlAttr.CLASS, style.toString());
+        return this;
     }
 
     /**
@@ -112,6 +143,7 @@
      *
      * @param tagContent tag content to be added
      */
+    @Override
     public void addContent(Content tagContent) {
         if (tagContent instanceof ContentBuilder) {
             for (Content content: ((ContentBuilder)tagContent).contents) {
@@ -302,7 +334,7 @@
     public static HtmlTree A_ID(HtmlStyle styleClass, String id, Content body) {
         HtmlTree htmltree = A_ID(id, body);
         if (styleClass != null)
-            htmltree.addStyle(styleClass);
+            htmltree.setStyle(styleClass);
         return htmltree;
     }
 
@@ -361,7 +393,7 @@
     public static HtmlTree DIV(HtmlStyle styleClass, Content body) {
         HtmlTree htmltree = new HtmlTree(HtmlTag.DIV, nullCheck(body));
         if (styleClass != null)
-            htmltree.addStyle(styleClass);
+            htmltree.setStyle(styleClass);
         return htmltree;
     }
 
@@ -424,7 +456,7 @@
         if (printTitle)
             htmltree.setTitle(body);
         if (styleClass != null)
-            htmltree.addStyle(styleClass);
+            htmltree.setStyle(styleClass);
         return htmltree;
     }
 
@@ -546,7 +578,7 @@
     public static HtmlTree LI(HtmlStyle styleClass, Content body) {
         HtmlTree htmltree = new HtmlTree(HtmlTag.LI, nullCheck(body));
         if (styleClass != null)
-            htmltree.addStyle(styleClass);
+            htmltree.setStyle(styleClass);
         return htmltree;
     }
 
@@ -601,7 +633,7 @@
     public static HtmlTree MAIN(HtmlStyle styleClass, Content body) {
         HtmlTree htmltree = HtmlTree.MAIN(body);
         if (styleClass != null) {
-            htmltree.addStyle(styleClass);
+            htmltree.setStyle(styleClass);
         }
         return htmltree;
     }
@@ -678,7 +710,7 @@
     public static HtmlTree P(HtmlStyle styleClass, Content body) {
         HtmlTree htmltree = new HtmlTree(HtmlTag.P, nullCheck(body));
         if (styleClass != null)
-            htmltree.addStyle(styleClass);
+            htmltree.setStyle(styleClass);
         return htmltree;
     }
 
@@ -760,7 +792,7 @@
     public static HtmlTree SPAN(HtmlStyle styleClass, Content body) {
         HtmlTree htmltree = new HtmlTree(HtmlTag.SPAN, nullCheck(body));
         if (styleClass != null)
-            htmltree.addStyle(styleClass);
+            htmltree.setStyle(styleClass);
         return htmltree;
     }
 
@@ -777,7 +809,7 @@
         HtmlTree htmltree = new HtmlTree(HtmlTag.SPAN, nullCheck(body));
         htmltree.addAttr(HtmlAttr.ID, nullCheck(id));
         if (styleClass != null)
-            htmltree.addStyle(styleClass);
+            htmltree.setStyle(styleClass);
         return htmltree;
     }
 
@@ -792,7 +824,7 @@
     public static HtmlTree TABLE(HtmlStyle styleClass, String summary, Content body) {
         HtmlTree htmltree = new HtmlTree(HtmlTag.TABLE, nullCheck(body));
         if (styleClass != null)
-            htmltree.addStyle(styleClass);
+            htmltree.setStyle(styleClass);
         htmltree.addAttr(HtmlAttr.SUMMARY, nullCheck(summary));
         return htmltree;
     }
@@ -807,7 +839,7 @@
     public static HtmlTree TABLE(HtmlStyle styleClass, Content body) {
         HtmlTree htmltree = new HtmlTree(HtmlTag.TABLE, nullCheck(body));
         if (styleClass != null) {
-            htmltree.addStyle(styleClass);
+            htmltree.setStyle(styleClass);
         }
         return htmltree;
     }
@@ -822,7 +854,7 @@
     public static HtmlTree TD(HtmlStyle styleClass, Content body) {
         HtmlTree htmltree = new HtmlTree(HtmlTag.TD, nullCheck(body));
         if (styleClass != null)
-            htmltree.addStyle(styleClass);
+            htmltree.setStyle(styleClass);
         return htmltree;
     }
 
@@ -847,7 +879,7 @@
     public static HtmlTree TH(HtmlStyle styleClass, String scope, Content body) {
         HtmlTree htmltree = new HtmlTree(HtmlTag.TH, nullCheck(body));
         if (styleClass != null)
-            htmltree.addStyle(styleClass);
+            htmltree.setStyle(styleClass);
         htmltree.addAttr(HtmlAttr.SCOPE, nullCheck(scope));
         return htmltree;
     }
@@ -910,7 +942,7 @@
         for (Content c : more) {
             htmlTree.addContent(nullCheck(c));
         }
-        htmlTree.addStyle(nullCheck(styleClass));
+        htmlTree.setStyle(nullCheck(styleClass));
         return htmlTree;
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java	Thu Nov 16 15:01:45 2017 -0800
@@ -26,7 +26,6 @@
 package jdk.javadoc.internal.doclets.formats.html.markup;
 
 import java.io.*;
-import java.util.*;
 
 import jdk.javadoc.internal.doclets.formats.html.HtmlConfiguration;
 import jdk.javadoc.internal.doclets.toolkit.Content;
@@ -35,8 +34,6 @@
 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
 import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
 import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
-import jdk.javadoc.internal.doclets.toolkit.util.TableTabTypes;
-import jdk.javadoc.internal.doclets.toolkit.util.TableTabTypes.TableTabs;
 
 
 /**
@@ -252,110 +249,6 @@
     }
 
     /**
-     * Generated javascript variables for the document.
-     *
-     * @param typeMap map comprising of method and type relationship
-     * @param tabTypes set comprising of all table tab types for this class
-     * @param elementName packages or methods table for which tabs need to be displayed
-     */
-    public void generateTableTabTypesScript(Map<String,Integer> typeMap,
-            Set<? extends TableTabTypes> tabTypes, String elementName) {
-        String sep = "";
-        StringBuilder vars = new StringBuilder("var ");
-        vars.append(elementName)
-                .append(" = {");
-        for (Map.Entry<String,Integer> entry : typeMap.entrySet()) {
-            vars.append(sep);
-            sep = ",";
-            vars.append("\"")
-                    .append(entry.getKey())
-                    .append("\":")
-                    .append(entry.getValue());
-        }
-        vars.append("};").append(DocletConstants.NL);
-        sep = "";
-        vars.append("var tabs = {");
-        for (TableTabTypes entry : tabTypes) {
-            vars.append(sep);
-            sep = ",";
-            vars.append(entry.tableTabs().value())
-                    .append(":")
-                    .append("[")
-                    .append("\"")
-                    .append(entry.tableTabs().tabId())
-                    .append("\"")
-                    .append(sep)
-                    .append("\"")
-                    .append(configuration.getText(entry.tableTabs().resourceKey()))
-                    .append("\"]");
-        }
-        vars.append("};")
-                .append(DocletConstants.NL);
-        addStyles(HtmlStyle.altColor, vars);
-        addStyles(HtmlStyle.rowColor, vars);
-        addStyles(HtmlStyle.tableTab, vars);
-        addStyles(HtmlStyle.activeTableTab, vars);
-        script.addContent(new RawHtml(vars));
-    }
-
-    /**
-     * Generated javascript variables for the document.
-     *
-     * @param groupTypeMap map comprising of group relationship
-     * @param groupTypes map comprising of all table tab types
-     */
-    public void generateGroupTypesScript(Map<String,Integer> groupTypeMap,
-            Map<String,TableTabs> groupTypes) {
-        String sep = "";
-        StringBuilder vars = new StringBuilder("var groups");
-        vars.append(" = {");
-        for (Map.Entry<String,Integer> entry : groupTypeMap.entrySet()) {
-            vars.append(sep);
-            sep = ",";
-            vars.append("\"")
-                    .append(entry.getKey())
-                    .append("\":")
-                    .append(entry.getValue());
-        }
-        vars.append("};").append(DocletConstants.NL);
-        sep = "";
-        vars.append("var tabs = {");
-        for (String group : groupTypes.keySet()) {
-            TableTabs tab = groupTypes.get(group);
-            vars.append(sep);
-            sep = ",";
-            vars.append(tab.value())
-                    .append(":")
-                    .append("[")
-                    .append("\"")
-                    .append(tab.tabId())
-                    .append("\"")
-                    .append(sep)
-                    .append("\"")
-                    .append(new StringContent(tab.resourceKey()))
-                    .append("\"]");
-        }
-        vars.append("};")
-                .append(DocletConstants.NL);
-        addStyles(HtmlStyle.altColor, vars);
-        addStyles(HtmlStyle.rowColor, vars);
-        addStyles(HtmlStyle.tableTab, vars);
-        addStyles(HtmlStyle.activeTableTab, vars);
-        script.addContent(new RawHtml(vars));
-    }
-
-    /**
-     * Adds javascript style variables to the document.
-     *
-     * @param style style to be added as a javascript variable
-     * @param vars variable string to which the style variable will be added
-     */
-    public void addStyles(HtmlStyle style, StringBuilder vars) {
-        vars.append("var ").append(style).append(" = \"").append(style)
-                .append("\";").append(DocletConstants.NL);
-    }
-
-    /**
      * Returns an HtmlTree for the TITLE tag.
      *
      * @return an HtmlTree for the TITLE tag
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Table.java	Thu Nov 16 15:01:45 2017 -0800
@@ -0,0 +1,589 @@
+/*
+ * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.javadoc.internal.doclets.formats.html.markup;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.function.IntFunction;
+import java.util.function.Predicate;
+
+import javax.lang.model.element.Element;
+
+import jdk.javadoc.internal.doclets.formats.html.Contents;
+import jdk.javadoc.internal.doclets.toolkit.Content;
+import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
+
+/**
+ * A builder for HTML tables, such as the summary tables for various
+ * types of element.
+ *
+ * <p>The table should be used in three phases:
+ * <ol>
+ * <li>Configuration: the overall characteristics of the table should be specified
+ * <li>Population: the content for the cells in each row should be added
+ * <li>Generation: the HTML content and any associated JavaScript can be accessed
+ * </ol>
+ *
+ * Many methods return the current object, to facilitate fluent builder-style usage.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+public class Table {
+    private final HtmlVersion version;
+    private final HtmlStyle tableStyle;
+    private String summary;
+    private Content caption;
+    private Map<String, Predicate<Element>> tabMap;
+    private String defaultTab;
+    private Set<String> tabs;
+    private HtmlStyle activeTabStyle = HtmlStyle.activeTableTab;
+    private HtmlStyle tabStyle = HtmlStyle.tableTab;
+    private HtmlStyle tabEnd = HtmlStyle.tabEnd;
+    private IntFunction<String> tabScript;
+    private String tabScriptVariable;
+    private Function<Integer, String> tabId = (i -> "t" + i);
+    private TableHeader header;
+    private List<HtmlStyle> columnStyles;
+    private int rowScopeColumnIndex;
+    private List<HtmlStyle> stripedStyles = Arrays.asList(HtmlStyle.altColor, HtmlStyle.rowColor);
+    private final List<Content> bodyRows;
+    private final List<Integer> bodyRowMasks;
+    private String rowIdPrefix = "i";
+
+    // compatibility flags
+    private boolean putIdFirst = false;
+    private boolean useTBody = true;
+
+    /**
+     * Creates a builder for an HTML table.
+     *
+     * @param version   the version of HTML, used to determine is a {@code summary}
+     *                  attribute is needed
+     * @param style     the style class for the {@code <table>} tag
+     */
+    public Table(HtmlVersion version, HtmlStyle style) {
+        this.version = version;
+        this.tableStyle = style;
+        bodyRows = new ArrayList<>();
+        bodyRowMasks = new ArrayList<>();
+    }
+
+    /**
+     * Sets the summary for the table.
+     * This is ignored if the HTML version for the table is not {@link HtmlVersion#HTML4}.
+     *
+     * @param summary the summary
+     * @return this object
+     */
+    public Table setSummary(String summary) {
+        if (version == HtmlVersion.HTML4) {
+            this.summary = summary;
+        }
+        return this;
+    }
+
+    /**
+     * Sets the caption for the table.
+     * This is ignored if the table is configured to provide tabs to select
+     * different subsets of rows within the table.
+     * The caption should be suitable for use as the content of a {@code <caption>}
+     * element.
+     *
+     * <b>For compatibility, the code currently accepts a {@code <caption>} element
+     * as well. This should be removed when all clients rely on using the {@code <caption>}
+     * element being generated by this class.</b>
+     *
+     * @param captionContent the caption
+     * @return this object
+     */
+    public Table setCaption(Content captionContent) {
+        if (captionContent instanceof HtmlTree
+                && ((HtmlTree) captionContent).htmlTag == HtmlTag.CAPTION) {
+            caption = captionContent;
+        } else {
+            caption = getCaption(captionContent);
+        }
+        return this;
+    }
+
+    /**
+     * Adds a tab to the table.
+     * Tabs provide a way to display subsets of rows, as determined by a
+     * predicate for the tab, and an element associated with each row.
+     * Tabs will appear left-to-right in the order they are added.
+     *
+     * @param name      the name of the tab
+     * @param predicate the predicate
+     * @return this object
+     */
+    public Table addTab(String name, Predicate<Element> predicate) {
+        if (tabMap == null) {
+            tabMap = new LinkedHashMap<>();     // preserves order that tabs are added
+            tabs = new HashSet<>();             // order not significant
+        }
+        tabMap.put(name, predicate);
+        return this;
+    }
+
+    /**
+     * Sets the name for the default tab, which displays all the rows in the table.
+     * This tab will appear first in the left-to-right list of displayed tabs.
+     *
+     * @param name the name
+     * @return this object
+     */
+    public Table setDefaultTab(String name) {
+        defaultTab = name;
+        return this;
+    }
+
+    /**
+     * Sets the function used to generate the JavaScript to be used when a tab is selected.
+     * When the function is invoked, the argument will be an integer value containing
+     * the bit mask identifying the rows to be selected.
+     *
+     * @param f the function
+     * @return this object
+     */
+    public Table setTabScript(IntFunction<String> f) {
+        tabScript = f;
+        return this;
+    }
+
+    /**
+     * Sets the name of the JavaScript variable used to contain the data for each tab.
+     *
+     * @param name the name
+     * @return this object
+     */
+    public Table setTabScriptVariable(String name) {
+        tabScriptVariable = name;
+        return this;
+    }
+
+    /**
+     * Sets the name of the styles used to display the tabs.
+     *
+     * @param activeTabStyle    the style for the active tab
+     * @param tabStyle          the style for other tabs
+     * @param tabEnd            the style for the padding that appears within each tab
+     * @return  this object
+     */
+    public Table setTabStyles(HtmlStyle activeTabStyle, HtmlStyle tabStyle, HtmlStyle tabEnd) {
+        this.activeTabStyle = activeTabStyle;
+        this.tabStyle = tabStyle;
+        this.tabEnd = tabEnd;
+        return this;
+    }
+
+    /**
+     * Sets the JavaScript function used to generate the {@code id} attribute for each tag.
+     * The default is to use <code>t</code><i>N</i> where <i>N</i> is the index of the tab,
+     * counting from 0 (for the default tab), and then from 1 upwards for additional tabs.
+     *
+     * @param f the function
+     * @return this object
+     */
+    public Table setTabId(Function<Integer,String> f) {
+        tabId = f;
+        return this;
+    }
+
+    /**
+     * Sets the header for the table.
+     *
+     * <p>Notes:
+     * <ul>
+     * <liThis currently does not use a {@code <thead>} tag, but probably should, eventually
+     * <li>The column styles are not currently applied to the header, but probably should, eventually
+     * </ul>
+     *
+     * @param header the header
+     * @return this object
+     */
+    public Table setHeader(TableHeader header) {
+        this.header = header;
+        return this;
+    }
+
+    /**
+     * Sets the styles used for {@code <tr>} tags, to give a "striped" appearance.
+     * The defaults are currently {@code rowColor} and {@code altColor}.
+     *
+     * @param evenRowStyle  the style to use for even-numbered rows
+     * @param oddRowStyle   the style to use for odd-numbered rows
+     * @return
+     */
+    public Table setStripedStyles(HtmlStyle evenRowStyle, HtmlStyle oddRowStyle) {
+        stripedStyles = Arrays.asList(evenRowStyle, oddRowStyle);
+        return this;
+    }
+
+    /**
+     * Sets the column used to indicate which cell in a row should be declared
+     * as a header cell with the {@code scope} attribute set to {@code row}.
+     *
+     * @param columnIndex the column index
+     * @return this object
+     */
+    public Table setRowScopeColumn(int columnIndex) {
+        rowScopeColumnIndex = columnIndex;
+        return this;
+    }
+
+    /**
+     * Sets the styles for be used for the cells in each row.
+     *
+     * <p>Note:
+     * <ul>
+     * <li>The column styles are not currently applied to the header, but probably should, eventually
+     * </ul>
+     *
+     * @param styles the styles
+     * @return this object
+     */
+    public Table setColumnStyles(HtmlStyle... styles) {
+        return setColumnStyles(Arrays.asList(styles));
+    }
+
+    /**
+     * Sets the styles for be used for the cells in each row.
+     *
+     * <p>Note:
+     * <ul>
+     * <li>The column styles are not currently applied to the header, but probably should, eventually
+     * </ul>
+     *
+     * @param styles the styles
+     * @return this object
+     */
+    public Table setColumnStyles(List<HtmlStyle> styles) {
+        columnStyles = styles;
+        return this;
+    }
+
+    /**
+     * Sets the prefix used for the {@code id} attribute for each row in the table.
+     * The default is "i".
+     *
+     * <p>Note:
+     * <ul>
+     * <li>The prefix should probably be a value such that the generated ids cannot
+     *      clash with any other id, such as those that might be created for fields within
+     *      a class.
+     * </ul>
+     *
+     * @param prefix the prefix
+     * @return  this object
+     */
+    public Table setRowIdPrefix(String prefix) {
+        rowIdPrefix = prefix;
+        return this;
+    }
+
+    /**
+     * Sets whether the {@code id} attribute should appear first in a {@code <tr>} tag.
+     * The default is {@code false}.
+     *
+     * <b>This is a compatibility feature that should be removed when all tables use a
+     * consistent policy.</b>
+     *
+     * @param first whether to put {@code id} attributes first
+     * @return this object
+     */
+    public Table setPutIdFirst(boolean first) {
+        this.putIdFirst = first;
+        return this;
+    }
+
+    /**
+     * Sets whether or not to use an explicit {@code <tbody>} element to enclose the rows
+     * of a table.
+     * The default is {@code true}.
+     *
+     * <b>This is a compatibility feature that should be removed when all tables use a
+     * consistent policy.</b>
+     *
+     * @param use whether o use a {@code <tbody> element
+     * @return this object
+     */
+    public Table setUseTBody(boolean use) {
+        this.useTBody = use;
+        return this;
+    }
+
+    /**
+     * Add a row of data to the table.
+     * Each item of content should be suitable for use as the content of a
+     * {@code <th>} or {@code <td>} cell.
+     * This method should not be used when the table has tabs: use a method
+     * that takes an {@code Element} parameter instead.
+     *
+     * @param contents the contents for the row
+     */
+    public void addRow(Content... contents) {
+        addRow(null, Arrays.asList(contents));
+    }
+
+    /**
+     * Add a row of data to the table.
+     * Each item of content should be suitable for use as the content of a
+     * {@code <th>} or {@code <td> cell}.
+     * This method should not be used when the table has tabs: use a method
+     * that takes an {@code element} parameter instead.
+     *
+     * @param contents the contents for the row
+     */
+    public void addRow(List<Content> contents) {
+        addRow(null, contents);
+    }
+
+    /**
+     * Add a row of data to the table.
+     * Each item of content should be suitable for use as the content of a
+     * {@code <th>} or {@code <td>} cell.
+     *
+     * If tabs have been added to the table, the specified element will be used
+     * to determine whether the row should be displayed when any particular tab
+     * is selected, using the predicate specified when the tab was
+     * {@link #add(String,Predicate) added}.
+     *
+     * @param element the element
+     * @param contents the contents for the row
+     * @throws NullPointerException if tabs have previously been added to the table
+     *      and {@code element} is null
+     */
+    public void addRow(Element element, Content... contents) {
+        addRow(element, Arrays.asList(contents));
+    }
+
+    /**
+     * Add a row of data to the table.
+     * Each item of content should be suitable for use as the content of a
+     * {@code <th>} or {@code <td>} cell.
+     *
+     * If tabs have been added to the table, the specified element will be used
+     * to determine whether the row should be displayed when any particular tab
+     * is selected, using the predicate specified when the tab was
+     * {@link #add(String,Predicate) added}.
+     *
+     * @param element the element
+     * @param contents the contents for the row
+     * @throws NullPointerException if tabs have previously been added to the table
+     *      and {@code element} is null
+     */
+    public void addRow(Element element, List<Content> contents) {
+        if (tabMap != null && element == null) {
+            throw new NullPointerException();
+        }
+
+        HtmlTree row = new HtmlTree(HtmlTag.TR);
+
+        if (putIdFirst && tabMap != null) {
+            int index = bodyRows.size();
+            row.addAttr(HtmlAttr.ID, (rowIdPrefix + index));
+        }
+
+        if (stripedStyles != null) {
+            int rowIndex = bodyRows.size();
+            row.addAttr(HtmlAttr.CLASS, stripedStyles.get(rowIndex % 2).name());
+        }
+        int colIndex = 0;
+        for (Content c : contents) {
+            HtmlStyle cellStyle = (columnStyles == null || colIndex > columnStyles.size())
+                    ? null
+                    : columnStyles.get(colIndex);
+            HtmlTree cell = (colIndex == rowScopeColumnIndex)
+                    ? HtmlTree.TH(cellStyle, "row", c)
+                    : HtmlTree.TD(cellStyle, c);
+            row.addContent(cell);
+            colIndex++;
+        }
+        bodyRows.add(row);
+
+        if (tabMap != null) {
+            if (!putIdFirst) {
+                int index = bodyRows.size() - 1;
+                row.addAttr(HtmlAttr.ID, (rowIdPrefix + index));
+            }
+            int mask = 0;
+            int maskBit = 1;
+            for (Map.Entry<String, Predicate<Element>> e : tabMap.entrySet()) {
+                String name = e.getKey();
+                Predicate<Element> predicate = e.getValue();
+                if (predicate.test(element)) {
+                    tabs.add(name);
+                    mask |= maskBit;
+                }
+                maskBit = (maskBit << 1);
+            }
+            bodyRowMasks.add(mask);
+        }
+    }
+
+    /**
+     * Returns whether or not the table is empty.
+     * The table is empty if it has no (body) rows.
+     *
+     * @return true if the table has no rows
+     */
+    public boolean isEmpty() {
+        return bodyRows.isEmpty();
+    }
+
+    /**
+     * Returns the HTML for the table.
+     *
+     * @return the HTML
+     */
+    public Content toContent() {
+        HtmlTree table = new HtmlTree(HtmlTag.TABLE);
+        table.setStyle(tableStyle);
+        if (summary != null) {
+            table.addAttr(HtmlAttr.SUMMARY, summary);
+        }
+        if (tabMap != null) {
+            if (tabs.size() == 1) {
+                String tabName = tabs.iterator().next();
+                table.addContent(getCaption(new StringContent(tabName)));
+            } else {
+                ContentBuilder cb = new ContentBuilder();
+                int tabIndex = 0;
+                HtmlTree defaultTabSpan = new HtmlTree(HtmlTag.SPAN,
+                            HtmlTree.SPAN(new StringContent(defaultTab)),
+                            HtmlTree.SPAN(tabEnd, Contents.SPACE))
+                        .addAttr(HtmlAttr.ID, tabId.apply(tabIndex))
+                        .setStyle(activeTabStyle);
+                cb.addContent(defaultTabSpan);
+                for (String tabName : tabMap.keySet()) {
+                    tabIndex++;
+                    if (tabs.contains(tabName)) {
+                        String script = "javascript:" + tabScript.apply(1 << (tabIndex - 1));
+                        HtmlTree link = HtmlTree.A(script, new StringContent(tabName));
+                        HtmlTree tabSpan = new HtmlTree(HtmlTag.SPAN,
+                                    HtmlTree.SPAN(link), HtmlTree.SPAN(tabEnd, Contents.SPACE))
+                                .addAttr(HtmlAttr.ID, tabId.apply(tabIndex))
+                                .setStyle(tabStyle);
+                        cb.addContent(tabSpan);
+                    }
+                }
+                table.addContent(HtmlTree.CAPTION(cb));
+            }
+        } else {
+            table.addContent(caption);
+        }
+        table.addContent(header.toContent());
+        if (useTBody) {
+            Content tbody = new HtmlTree(HtmlTag.TBODY);
+            bodyRows.forEach(row -> tbody.addContent(row));
+            table.addContent(tbody);
+        } else {
+            bodyRows.forEach(row -> table.addContent(row));
+        }
+        return table;
+    }
+
+    /**
+     * Returns whether or not the table needs JavaScript support.
+     * It requires such support if tabs have been added.
+     *
+     * @return true if JavaScript is required
+     */
+    public boolean needsScript() {
+        return (tabs != null) && (tabs.size() > 1);
+    }
+
+    /**
+     * Returns the script to be used in conjunction with the table.
+     *
+     * @return the script
+     */
+    public String getScript() {
+        if (tabMap == null)
+            throw new IllegalStateException();
+
+        StringBuilder sb = new StringBuilder();
+
+        // Add the variable defining the bitmask for each row
+        sb.append("var ").append(tabScriptVariable).append(" = {");
+        int rowIndex = 0;
+        for (int mask : bodyRowMasks) {
+            if (rowIndex > 0) {
+                sb.append(",");
+            }
+            sb.append("\"").append(rowIdPrefix).append(rowIndex).append("\":").append(mask);
+            rowIndex++;
+        }
+        sb.append("};").append(DocletConstants.NL);
+
+        // Add the variable defining the tabs
+        sb.append("var tabs = {");
+        appendTabInfo(sb, 65535, tabId.apply(0), defaultTab);
+        int tabIndex = 1;
+        int maskBit = 1;
+        for (String tabName: tabMap.keySet()) {
+            if (tabs.contains(tabName)) {
+                sb.append(",");
+                appendTabInfo(sb, maskBit, tabId.apply(tabIndex), tabName);
+            }
+            tabIndex++;
+            maskBit = (maskBit << 1);
+        }
+        sb.append("};").append(DocletConstants.NL);
+
+        // Add the variables defining the stylenames
+        appendStyleInfo(sb,
+                stripedStyles.get(0), stripedStyles.get(1), tabStyle, activeTabStyle);
+        return sb.toString();
+    }
+
+    private void appendTabInfo(StringBuilder sb, int value, String id, String name) {
+        sb.append(value).append(":[\"").append(id).append("\",").append("\"").append(name).append("\"]");
+    }
+
+    private void appendStyleInfo(StringBuilder sb, HtmlStyle... styles) {
+        for (HtmlStyle style : styles) {
+            sb.append("var ").append(style).append(" = \"").append(style)
+                    .append("\";").append(DocletConstants.NL);
+        }
+
+    }
+
+    private HtmlTree getCaption(Content title) {
+        return new HtmlTree(HtmlTag.CAPTION,
+                HtmlTree.SPAN(title),
+                HtmlTree.SPAN(tabEnd, Contents.SPACE));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/TableHeader.java	Thu Nov 16 15:01:45 2017 -0800
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.javadoc.internal.doclets.formats.html.markup;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import jdk.javadoc.internal.doclets.formats.html.Contents;
+import jdk.javadoc.internal.doclets.toolkit.Content;
+
+/**
+ * A row header for an HTML table.
+ *
+ * The header contains a list of {@code <th>} cells, providing the column headers.
+ * The attribute {@code scope="col"} is automatically added to each header cell.
+ * In addition, a series of style class names can be specified, to be applied one per cell.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+public class TableHeader {
+
+    /**
+     * The content to be put in each of the {@code <th>} cells in the header row.
+     */
+    private final List<Content> cellContents;
+    /**
+     * The style class names for each of the {@code <th>} cells in the header row.
+     * If not set, default style names will be used.
+     */
+    private List<HtmlStyle> styles;
+
+    /**
+     * Creates a header row, with localized content for each cell.
+     * Resources keys will be converted to content using {@link Contents#getContent(String)}.
+     * @param contents a factory to get the content for each header cell.
+     * @param colHeaderKeys the resource keys for the content in each cell.
+     */
+    public TableHeader(Contents contents, String... colHeaderKeys) {
+        this.cellContents = Arrays.stream(colHeaderKeys)
+                .map((key) -> contents.getContent(key))
+                .collect(Collectors.toList());
+    }
+
+    /**
+     * Creates a header row, with specified content for each cell.
+     * @param headerCellContents a content object for each header cell
+     */
+    public TableHeader(Content... headerCellContents) {
+        this.cellContents = Arrays.asList(headerCellContents);
+    }
+
+    /**
+     * Set the style class names for each header cell.
+     * The number of names must match the number of cells given to the constructor.
+     * @param styles the style class names
+     * @return this object
+     */
+    public TableHeader styles(HtmlStyle... styles) {
+        if (styles.length != cellContents.size()) {
+            throw new IllegalStateException();
+        }
+        this.styles = Arrays.asList(styles);
+        return this;
+    }
+
+    /**
+     * Converts this header to a {@link Content} object, for use in an {@link HtmlTree}.
+     * @return a Content object
+     */
+    public Content toContent() {
+        String scope = "col";
+        Content tr = new HtmlTree(HtmlTag.TR);
+        int i = 0;
+        for (Content cellContent : cellContents) {
+            HtmlStyle style = (styles != null) ? styles.get(i)
+                    : (i == 0) ? HtmlStyle.colFirst
+                    : (i == (cellContents.size() - 1)) ? HtmlStyle.colLast
+                    : (i == 1) ? HtmlStyle.colSecond : null;
+            Content cell = (style == null) ? HtmlTree.TH(scope, cellContent)
+                    : HtmlTree.TH(style, scope, cellContent);
+            tr.addContent(cell);
+            i++;
+        }
+        return tr;
+    }
+
+}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/package-info.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/package-info.java	Thu Nov 16 15:01:45 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,12 +24,17 @@
  */
 
 /**
-    This package contains classes that write HTML markup tags.
-
-    <p><b>This is NOT part of any supported API.
-    If you write code that depends on this, you do so at your own risk.
-    This code and its internal interfaces are subject to change or
-    deletion without notice.</b>
+ * This package contains classes that create and write HTML markup tags.
+ *
+ * The primary low level classes are {@link HtmlTree} and subtypes
+ * of {@code Content}. In addition, there are mid-level builders
+ * like {@link TableHeader} and {@link Table} to help build more
+ * complex HTML trees.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
  */
 
 package jdk.javadoc.internal.doclets.formats.html.markup;
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/MemberSummaryWriter.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/MemberSummaryWriter.java	Thu Nov 16 15:01:45 2017 -0800
@@ -25,7 +25,6 @@
 
 package jdk.javadoc.internal.doclets.toolkit;
 
-import java.io.*;
 import java.util.*;
 
 import javax.lang.model.element.Element;
@@ -62,11 +61,9 @@
      * Get the summary table for the given class.
      *
      * @param typeElement the class the summary table belongs to
-     * @param tableContents list of contents that will be added to the summary table
      * @return a content tree for the member summary table
      */
-    public Content getSummaryTableTree(TypeElement typeElement,
-            List<Content> tableContents);
+    public Content getSummaryTableTree(TypeElement typeElement);
 
     /**
      * Add the member summary for the given class and member.
@@ -74,12 +71,9 @@
      * @param typeElement the class the summary belongs to
      * @param member the member that is documented
      * @param firstSentenceTags the tags for the sentence being documented
-     * @param tableContents list of contents to which the summary will be added
-     * @param counter the counter for determining id and style for the table row
      */
     public void addMemberSummary(TypeElement typeElement, Element member,
-            List<? extends DocTree> firstSentenceTags, List<Content> tableContents, int counter,
-            VisibleMemberMap.Kind vmmKind);
+            List<? extends DocTree> firstSentenceTags);
 
     /**
      * Get the inherited member summary header for the given class.
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MemberSummaryBuilder.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MemberSummaryBuilder.java	Thu Nov 16 15:01:45 2017 -0800
@@ -333,8 +333,6 @@
             VisibleMemberMap visibleMemberMap, LinkedList<Content> summaryTreeList) {
         SortedSet<Element> members = asSortedSet(visibleMemberMap.getLeafMembers());
         if (!members.isEmpty()) {
-            List<Content> tableContents = new LinkedList<>();
-            int counter = 0;
             for (Element member : members) {
                 final Element property = visibleMemberMap.getPropertyElement(member);
                 if (property != null) {
@@ -355,11 +353,9 @@
                         firstSentenceTags = utils.getFirstSentenceTrees(inheritedDoc.holder);
                     }
                 }
-                writer.addMemberSummary(typeElement, member, firstSentenceTags,
-                        tableContents, counter, visibleMemberMap.kind);
-                counter++;
+                writer.addMemberSummary(typeElement, member, firstSentenceTags);
             }
-            summaryTreeList.add(writer.getSummaryTableTree(typeElement, tableContents));
+            summaryTreeList.add(writer.getSummaryTableTree(typeElement));
         }
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/GroupTypes.java	Thu Nov 16 20:25:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.javadoc.internal.doclets.toolkit.util;
-
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-import jdk.javadoc.internal.doclets.toolkit.util.TableTabTypes.TableTabs;
-
-/**
- * Enum representing group types.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Bhavesh Patel
- */
-public class GroupTypes {
-
-    private final Map<String,TableTabs> tabs = new LinkedHashMap<>();
-
-    private int value = 1;
-
-    public GroupTypes(List<String> groupList, String allLabel) {
-        if (groupList.size() > 1) {
-            tabs.put(allLabel, TableTabs.tab(65535, allLabel, "t0", true));
-        }
-        groupList.forEach((groupname) -> {
-            tabs.put(groupname, TableTabs.tab(value, groupname, "t" + value, false));
-            value = 2 * value;
-        });
-    }
-
-    public Map<String,TableTabs> getGroupTypes() {
-        return tabs;
-    }
-
-    public TableTabs getTableTab(String groupName) {
-        return tabs.get(groupName);
-    }
-}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/MethodTypes.java	Thu Nov 16 20:25:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.javadoc.internal.doclets.toolkit.util;
-
-/**
- * Enum representing method types.
- *
- * @author Bhavesh Patel
- */
-public enum MethodTypes implements TableTabTypes {
-
-    ALL(TableTabs.tab(0xffff, "doclet.All_Methods", "t0", true)),
-    STATIC(TableTabs.tab(0x1, "doclet.Static_Methods", "t1", false)),
-    INSTANCE(TableTabs.tab(0x2, "doclet.Instance_Methods", "t2", false)),
-    ABSTRACT(TableTabs.tab(0x4, "doclet.Abstract_Methods", "t3", false)),
-    CONCRETE(TableTabs.tab(0x8, "doclet.Concrete_Methods", "t4", false)),
-    DEFAULT(TableTabs.tab(0x10, "doclet.Default_Methods", "t5", false)),
-    DEPRECATED(TableTabs.tab(0x20, "doclet.Deprecated_Methods", "t6", false));
-
-    private final TableTabs tabs;
-
-    private MethodTypes(TableTabs t) {
-        this.tabs = t;
-    }
-
-    public TableTabs tableTabs() {
-        return this.tabs;
-    }
-    }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/ModulePackageTypes.java	Thu Nov 16 20:25:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.javadoc.internal.doclets.toolkit.util;
-
-import jdk.javadoc.internal.doclets.toolkit.util.TableTabTypes.TableTabs;
-
-/**
- * Enum representing module package types.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Bhavesh Patel
- */
-public enum ModulePackageTypes implements TableTabTypes {
-    ALL(TableTabs.tab(0xffff, "doclet.All_Packages", "t0", true)),
-    EXPORTED(TableTabs.tab(0x1, "doclet.Exported_Packages_Summary", "t1", false)),
-    OPENED(TableTabs.tab(0x2, "doclet.Opened_Packages_Summary", "t2", false)),
-    CONCEALED(TableTabs.tab(0x4, "doclet.Concealed_Packages_Summary", "t3", false));
-
-    private final TableTabs tabs;
-
-    private ModulePackageTypes(TableTabs t) {
-        this.tabs = t;
-    }
-
-    public TableTabs tableTabs() {
-        return this.tabs;
-    }
-}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/TableTabTypes.java	Thu Nov 16 20:25:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.javadoc.internal.doclets.toolkit.util;
-
-/**
- * Interface representing table tab types.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Bhavesh Patel
- */
-public interface TableTabTypes {
-
-    TableTabs tableTabs();
-
-    public static final class TableTabs {
-
-        private final int value;
-        private final String resourceKey;
-        private final String tabId;
-        private final boolean isDefaultTab;
-
-        private TableTabs(int v, String k, String id, boolean dt) {
-            this.value = v;
-            this.resourceKey = k;
-            this.tabId = id;
-            this.isDefaultTab = dt;
-        }
-
-        public static TableTabs tab(int value, String resourceKey, String tabId, boolean isDefaultTab) {
-            return new TableTabs(value, resourceKey, tabId, isDefaultTab);
-        }
-
-        public int value() {
-            return this.value;
-        }
-
-        public String resourceKey() {
-            return this.resourceKey;
-        }
-
-        public String tabId() {
-            return this.tabId;
-        }
-
-        public boolean isDefaultTab() {
-            return this.isDefaultTab;
-        }
-    }
-}
--- a/test/langtools/jdk/javadoc/doclet/testDeprecatedDocs/TestDeprecatedDocs.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testDeprecatedDocs/TestDeprecatedDocs.java	Thu Nov 16 15:01:45 2017 -0800
@@ -24,7 +24,7 @@
 /*
  * @test
  * @bug      4927552 8026567 8071982 8162674 8175200 8175218 8183511 8186332 8169819 8074407
- * @summary  <DESC>
+ * @summary  test generated docs for deprecated items
  * @author   jamieh
  * @library  ../lib
  * @modules jdk.javadoc/jdk.javadoc.internal.tool
@@ -254,6 +254,7 @@
                 + "<tbody>\n"
                 + "<tr class=\"altColor\">\n"
                 + "<th class=\"colDeprecatedItemName\" scope=\"row\"><a href=\"pkg/DeprecatedClassByAnnotation.html#field\">pkg.DeprecatedClassByAnnotation.field</a></th>\n"
+                + "<td class=\"colLast\"></td>\n"
                 + "</tr>\n"
                 + "<tr class=\"rowColor\">\n"
                 + "<th class=\"colDeprecatedItemName\" scope=\"row\"><a href=\"pkg/TestClass.html#field\">pkg.TestClass.field</a></th>\n"
--- a/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java	Thu Nov 16 20:25:45 2017 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java	Thu Nov 16 15:01:45 2017 -0800
@@ -1050,7 +1050,7 @@
                 + "<li><a href=\"#module\">Modules</a></li>\n"
                 + "</ul>",
                 "<tr class=\"altColor\">\n"
-                + "<th class=\"colFirst\" scope=\"row\"><a href=\"moduleA-summary.html\">moduleA</a></th>\n"
+                + "<th class=\"colDeprecatedItemName\" scope=\"row\"><a href=\"moduleA-summary.html\">moduleA</a></th>\n"
                 + "<td class=\"colLast\">\n"
                 + "<div class=\"deprecationComment\">This module is deprecated.</div>\n"
                 + "</td>\n"
--- a/test/langtools/jdk/javadoc/doclet/testOptions/help.html	Thu Nov 16 20:25:45 2017 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testOptions/help.html	Thu Nov 16 15:01:45 2017 -0800
@@ -2,10 +2,10 @@
 <!-- NewPage -->
 <html lang="ru">
 <head>
-<!-- Generated by javadoc (9-internal) on Mon Jan 04 22:47:26 MSK 2016 -->
+<!-- Generated by javadoc (removed) -->
 <title>API Help</title>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-<meta name="date" content="2016-01-04">
+<meta name="date" content="(removed)">
 <link rel="stylesheet" type="text/css" href="stylesheet.css" title="Style">
 <link rel="stylesheet" type="text/css" href="jquery/jquery-ui.css" title="Style">
 <script type="text/javascript" src="script.js"></script>