changeset 23:e2d02e8742be

usasr-1307: for render tables for properties and reportable properties with label and group names
author smith@nwoca.org
date Wed, 16 Mar 2016 23:24:26 +0100
parents b3282a66cc05
children cfbdbeba877f
files build.gradle gradle.properties src/main/groovy/org/ssdt_ohio/gradle/doc/tools/UserClassDocProxy.groovy src/main/groovy/org/ssdt_ohio/gradle/tasks/UserDoc.groovy src/main/resources/org/ssdt_ohio/gradle/userdoc/templates/classDocName.html src/main/resources/org/ssdt_ohio/gradle/userdoc/templates/stylesheet.css
diffstat 6 files changed, 208 insertions(+), 75 deletions(-) [+]
line wrap: on
line diff
--- a/build.gradle	Mon Jan 11 16:55:32 2016 +0000
+++ b/build.gradle	Wed Mar 16 23:24:26 2016 +0100
@@ -17,6 +17,9 @@
 dependencies {
     compile     localGroovy()
     compile     gradleApi()
+    compile     "org.asciidoctor:asciidoctorj:1.5.4"
+    compile     'org.apache.commons:commons-lang3:3.4'
+
     testCompile 'junit:junit:4.10'
 }
 
--- a/gradle.properties	Mon Jan 11 16:55:32 2016 +0000
+++ b/gradle.properties	Wed Mar 16 23:24:26 2016 +0100
@@ -1,2 +1,2 @@
-version=0.4.1.SNAPSHOT
+version=0.4.2.SNAPSHOT
 group=org.ssdt_ohio
--- a/src/main/groovy/org/ssdt_ohio/gradle/doc/tools/UserClassDocProxy.groovy	Mon Jan 11 16:55:32 2016 +0000
+++ b/src/main/groovy/org/ssdt_ohio/gradle/doc/tools/UserClassDocProxy.groovy	Wed Mar 16 23:24:26 2016 +0100
@@ -7,11 +7,16 @@
 package org.ssdt_ohio.gradle.doc.tools
 
 import org.codehaus.groovy.groovydoc.GroovyFieldDoc
+import org.codehaus.groovy.groovydoc.GroovyProgramElementDoc
+
+import static org.apache.commons.lang3.StringUtils.splitByCharacterTypeCamelCase
 
 class UserClassDocProxy extends groovy.util.Proxy {
 
+    private static LABEL_PATTERN = ~/.*label = '([\w\s]*)'.*/
+    private static GROUP_PATTERN = ~/.*group = '([\w\s]*)'.*/
+
     GroovyFieldDoc[] properties() {
-        println "getting properties for $adaptee"
         getAdaptee().properties().findAll { GroovyFieldDoc p ->
             !p.isTransient() &&
                     p.name() != 'version' &&
@@ -22,4 +27,42 @@
 
     def propertyMissing(String name) { getAdaptee()."$name" }
 
+    def getLabel(GroovyProgramElementDoc p) {
+        def result
+        def d = p.annotations().find {
+            it.name() == 'Display'
+        }
+        if (d) {
+             def m =  LABEL_PATTERN.matcher(d.description())
+            if (m.matches()) {
+                result = m.group(1)
+            }
+        }
+
+        return  result ?: labelFromCamelCase(p.name() - "get")
+
+    }
+
+    def getGroup(GroovyProgramElementDoc p) {
+        def result
+        def d = p.annotations().find {
+            it.name() == 'Display'
+        }
+        if (d) {
+            def m =  GROUP_PATTERN.matcher(d.description())
+            if (m.matches()) {
+                result = m.group(1)
+            }
+        }
+
+        return  labelFromCamelCase(result) ?: ''
+
+    }
+
+
+    static String labelFromCamelCase(String s) {
+        splitByCharacterTypeCamelCase(s).collect { it.trim() }.findAll { it }.join(' ').capitalize()
+
+    }
+
 }
--- a/src/main/groovy/org/ssdt_ohio/gradle/tasks/UserDoc.groovy	Mon Jan 11 16:55:32 2016 +0000
+++ b/src/main/groovy/org/ssdt_ohio/gradle/tasks/UserDoc.groovy	Wed Mar 16 23:24:26 2016 +0100
@@ -75,7 +75,9 @@
 //        properties.setProperty("charset", charset != null ? charset : "");
 //        properties.setProperty("fileEncoding", fileEncoding != null ? fileEncoding : "");
 
-        properties.put('userdocHelper',new UserDocHelper())
+//        properties.put('doctor',Asciidoctor.Factory.create())
+
+        properties.put('userdocHelper', new UserDocHelper())
 
         def tool = new GroovyDocTool(new ClasspathResourceManager(this.getClass().getClassLoader()),
                 [tmpDir.getPath()] as String[],
--- a/src/main/resources/org/ssdt_ohio/gradle/userdoc/templates/classDocName.html	Mon Jan 11 16:55:32 2016 +0000
+++ b/src/main/resources/org/ssdt_ohio/gradle/userdoc/templates/classDocName.html	Wed Mar 16 23:24:26 2016 +0100
@@ -1,9 +1,23 @@
 <!--
-  ~ Copyright (c) 2014.  Ohio Department of Education. - All Rights Reserved.
-  ~ Unauthorized copying of this file, in any medium, is strictly prohibited.
-  ~ Written by State Software Development Team (http://ssdt.oecn.k12.oh.us/)
-  -->
+
+     Licensed to the Apache Software Foundation (ASF) under one
+     or more contributor license agreements.  See the NOTICE file
+     distributed with this work for additional information
+     regarding copyright ownership.  The ASF licenses this file
+     to you under the Apache License, Version 2.0 (the
+     "License"); you may not use this file except in compliance
+     with the License.  You may obtain a copy of the License at
 
+       http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing,
+     software distributed under the License is distributed on an
+     "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+     KIND, either express or implied.  See the License for the
+     specific language governing permissions and limitations
+     under the License.
+
+-->
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 <!-- **************************************************************** -->
 <!-- *  PLEASE KEEP COMPLICATED EXPRESSIONS OUT OF THESE TEMPLATES, * -->
@@ -11,15 +25,17 @@
 <!-- **************************************************************** -->
 <%
 
-    println "Generating for $classDoc (${classDoc.class})"
     classDoc = props.get('userdocHelper').wrap(classDoc)
 
     def title = classDoc.name() + (props.docTitle ? " (${props.docTitle})" : "")
     def isVisible = { it.isPublic() || (it.isProtected() && props.protectedScope == 'true') || (!it.isProtected() && !it.isPrivate() && props.packageScope == 'true') || props.privateScope == 'true' }
     def isVisibleExt = { t -> java.lang.reflect.Modifier.isPublic(t.modifiers) || java.lang.reflect.Modifier.isProtected(t.modifiers) }
     def visibleFields = classDoc.fields().findAll(isVisible)
-    def visibleProperties = classDoc.properties() // props visible be defn
+    def visibleProperties = classDoc.properties() // props visible be def
     def visibleMethods = classDoc.methods().findAll(isVisible)
+    def getterMethods = visibleMethods.findAll { it.name().startsWith('get') }
+    def nonGetterMethods = visibleMethods - getterMethods
+
     def visibleConstructors = classDoc.constructors().findAll(isVisible)
     def visibleNested = classDoc.innerClasses().findAll(isVisible)
     boolean hasFields = !classDoc.isAnnotationType() && visibleFields
@@ -31,7 +47,7 @@
     def dolink = { t, boolean b ->
         boolean isArray = false
         if (!t || t instanceof String) {
-            return (classDoc.getDocUrl(t, b)  -'java.util.' - 'java.lang.')
+            return classDoc.getDocUrl(t, b)
         }
         if (t instanceof org.codehaus.groovy.tools.groovydoc.ArrayClassDocWrapper) {
             t = t.delegate
@@ -39,12 +55,13 @@
         }
         if (t instanceof org.codehaus.groovy.tools.groovydoc.SimpleGroovyClassDoc) {
             if (t.fullPathName == 'def') return classDoc.getDocUrl("java.lang.Object def", b)
-            return "<a href='" + classDoc.relativeRootPath + t.fullPathName + ".html'>" + ( (b ? t.qualifiedTypeName() : t.name() ) - "java.lang." - "java.util." ) + "</a>" + (isArray ? "[]" : "")
+            if (!t.qualifiedTypeName().contains("<") && t.name().size() > 1)
+                return "<a href='" + classDoc.relativeRootPath + t.fullPathName + ".html'>" + (b ? t.qualifiedTypeName() : t.name()) + "</a>" + (isArray ? "[]" : "")
         }
-        return ( classDoc.getDocUrl(t.qualifiedTypeName(), b) - 'java.util.' - 'java.lang.' ) + (isArray ? "[]" : "")
+        return classDoc.getDocUrl(t.qualifiedTypeName(), b) + (isArray ? "[]" : "")
     }
-    def linkfull = { t -> dolink(t, true) }
-    def linkable = { t -> dolink(t, false) }
+    def linkfull = { t -> dolink(t, true) - "java.lang." - "java.util." }
+    def linkable = { t -> dolink(t, false) - "java.lang." - "java.util." }
     def modifiersWithIgnore = { t, boolean ignorePublic ->
         (t.isPrivate()?"private&nbsp;":"") +
         (t.isPublic() && !ignorePublic?"public&nbsp;":"") +
@@ -60,22 +77,19 @@
         (t.isStatic()?"static&nbsp;":"")
     }
     def annotations = { t, sepChar ->
-        t.annotations() ? t.annotations().collect {
-//        it.isTypeAvailable() ? '@'+linkable(it.type().name())+(it.description()-('@'+it.type().name())): it.description()
-            it.description()
-        }.join(sepChar) + sepChar : ''
+        t.annotations() ? t.annotations().collect{it.isTypeAvailable()?'@'+linkable(it.type().name())+(it.description()-('@'+it.type().name())):it.description()}.join(sepChar) + sepChar : ''
     }
     def elementTypes = [
         "required":"true",
         "optional":"false"
     ]
-    def isRequired = { f, v ->
-        def req = f.constantValueExpression() == null; req.toString() == v
-    }
+    def isRequired = { f, v -> def req = f.constantValueExpression() == null; req.toString() == v }
     def upcase = { n -> n[0].toUpperCase() + n[1..-1] }
+    def lowcase = { n -> n ? n[0].toLowerCase() + n[1..-1] : "" }
     def paramsOf = { n, boolean brief -> n.parameters().collect{ param -> (brief?'':annotations(param, ' ')) + linkable(param.isTypeAvailable()?param.type():param.typeName()) + (param.vararg()?'... ':' ') + param.name() + (param.defaultValue() ? " = " + param.defaultValue():"") }.join(", ") }
     def nameFromParams = { n -> n.name() + '(' + n.parameters().collect{ param -> param.isTypeAvailable()?param.type().qualifiedTypeName():param.typeName() }.join(', ') + ')' }
     def nameFromJavaParams = { n -> n.name + '(' + n.parameterTypes.collect{ param -> param.name }.join(', ') + ')' }
+    def asPropertyName = { lowcase(it - 'get') }
 %>
 <html>
 <head>
@@ -127,19 +141,19 @@
     if (classDoc.isAnnotationType()) {
         def hasReq = classDoc.fields().any{ isRequired(it, "true") }
         def hasOpt = classDoc.fields().any{ isRequired(it, "false") }
-        if (hasReq) { %><li><a href="#required_element_summary"><% } %>Required<% if (hasReq) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<% 
-        if (hasOpt) { %><li><a href="#optional_element_summary"><% } %>Optional<% if (hasOpt) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<% 
+        if (hasReq) { %><li><a href="#required_element_summary"><% } %>Required<% if (hasReq) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<%
+        if (hasOpt) { %><li><a href="#optional_element_summary"><% } %>Optional<% if (hasOpt) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<%
     } else {
-        if (visibleNested) { %><li><a href="#nested_summary"><% } %>Nested<% if (visibleNested) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<% 
+        if (visibleNested) { %><li><a href="#nested_summary"><% } %>Nested<% if (visibleNested) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<%
         if (classDoc.isEnum()) {
-            if (hasEnumConstants) { %><li><a href="#enum_constant_summary"><% } %>Enum constants<% if (hasEnumConstants) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<% 
+            if (hasEnumConstants) { %><li><a href="#enum_constant_summary"><% } %>Enum constants<% if (hasEnumConstants) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<%
         }
-        if (hasFields) { %><li><a href="#field_summary"><% } %>Field<% if (hasFields) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<% 
-        if (hasProperties) { %><li><a href="#property_summary">Property</a></li><% } %>&nbsp;&nbsp;&nbsp;<% 
+        if (hasFields) { %><li><a href="#field_summary"><% } %>Field<% if (hasFields) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<%
+        if (hasProperties) { %><li><a href="#property_summary">Property</a></li><% } %>&nbsp;&nbsp;&nbsp;<%
         if (classDoc.isClass()) {
-            if (visibleConstructors) { %><li><a href="#constructor_summary"><% } %>Constructor<% if (visibleConstructors) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<% 
+            if (visibleConstructors) { %><li><a href="#constructor_summary"><% } %>Constructor<% if (visibleConstructors) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<%
         }
-        if (visibleMethods) { %><li><a href="#method_summary"><% } %>Method<% if (visibleMethods) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<% 
+        if (visibleMethods) { %><li><a href="#method_summary"><% } %>Method<% if (visibleMethods) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<%
     }
     %>
         </ul>
@@ -147,17 +161,17 @@
             <li>&nbsp;|&nbsp;Detail:&nbsp;</li>
             <%
             if (classDoc.isAnnotationType()) {
-                if (hasElements) { %><li><a href="#element_detail"><% } %>Element<% if (hasElements) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<% 
+                if (hasElements) { %><li><a href="#element_detail"><% } %>Element<% if (hasElements) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<%
             } else {
                 if (classDoc.isEnum()) {
-                    if (hasEnumConstants) { %><li><a href="#enum_constant_detail"><% } %>Enum constants<% if (hasEnumConstants) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<% 
+                    if (hasEnumConstants) { %><li><a href="#enum_constant_detail"><% } %>Enum constants<% if (hasEnumConstants) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<%
                 }
-                if (hasFields) { %><li><a href="#field_detail"><% } %>Field<% if (hasFields) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<% 
-                if (hasProperties) { %><li><a href="#prop_detail">Property</a></li><% } %>&nbsp;&nbsp;&nbsp;<% 
+                if (hasFields) { %><li><a href="#field_detail"><% } %>Field<% if (hasFields) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<%
+                if (hasProperties) { %><li><a href="#prop_detail">Property</a></li><% } %>&nbsp;&nbsp;&nbsp;<%
                 if (classDoc.isClass()) {
-                    if (visibleConstructors) { %><li><a href="#constructor_detail"><% } %>Constructor<% if (visibleConstructors) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<% 
+                    if (visibleConstructors) { %><li><a href="#constructor_detail"><% } %>Constructor<% if (visibleConstructors) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<%
                 }
-                if (visibleMethods) { %><li><a href="#method_detail"><% } %>Method<% if (visibleMethods) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<% 
+                if (visibleMethods) { %><li><a href="#method_detail"><% } %>Method<% if (visibleMethods) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<%
             }
             %>
         </ul>
@@ -176,7 +190,9 @@
 %>
     <div class="subTitle">Package: <strong>${pkg}</strong></div>
 <%}%>
-    <h2 title="${classDesc}" class="title">${classDesc}</h2>
+    <h2 title="${classDesc}" class="title">${classDesc}
+    <% if (classDoc.superclass()) { %>  extends ${linkable(classDoc.superclass())} <% } %>
+    </h2>
 </div>
 <div class="contentContainer">
 <ul class="inheritance">
@@ -220,11 +236,12 @@
             <!-- todo: direct known subclasses -->
             <hr>
             <br>
-<pre>${annotations(classDoc, '\n') + modifiers(classDoc) + classDoc.typeSourceDescription + ' ' + classDoc.name()}
-<% if (classDoc.isInterface() && classDoc.interfaces()) {
-%>extends ${classDoc.interfaces().collect{ linkable(it) }.join(', ')}
-<% } else if (classDoc.superclass()) {
-%>extends ${linkable(classDoc.superclass())}
+<div>
+${ annotations(classDoc, '<br/>')}
+</div>
+<pre>${modifiers(classDoc) + classDoc.typeSourceDescription + ' ' + classDoc.name()}
+<% if (classDoc.isInterface() && classDoc.interfaces()) {%>extends ${classDoc.interfaces().collect{ linkable(it) }.join(', ')}
+<% } else if (classDoc.superclass()) { %>extends ${linkable(classDoc.superclass())}
 <% } %>
 </pre>
 <% } %>
@@ -232,7 +249,7 @@
 <% if (classDoc.commentText()) { %>
     <p>${classDoc.commentText()}</p>
 <% } %>
-          </li>
+      </li>
     </ul>
 </div>
 
@@ -379,13 +396,19 @@
                     <table class="overviewSummary" border="0" cellpadding="3" cellspacing="0" summary="Properties Summary table, listing nested classes, and an explanation">
                         <caption><span>Properties</span><span class="tabEnd">&nbsp;</span></caption>
                         <tr>
-                            <th class="colFirst" scope="col">Type</th>
-                            <th class="colLast" scope="col">Name and description</th>
+                            <th class="colFirst" scope="col">Name</th>
+                            <th class="col" scope="col">Type</th>
+                            <th class="col" scope="col">Label</th>
+                            <th class="col" scope="col">Group</th>
+                            <th class="colLast" scope="col">Description</th>
                         </tr>
                         <% visibleProperties.eachWithIndex { prop, i -> %>
                         <tr class="${i%2==0?'altColor':'rowColor'}">
-                            <td class="colFirst"><code><strong>${modifiersBrief(prop) + linkable(prop.type())}</strong></code>&nbsp;</td>
-                            <td class="colLast"><code><a href="#${prop.name()}"></a>${prop.name()}</code><br>${prop.firstSentenceCommentText()}</td>
+                            <td class="colFirst"><code><a href="#${prop.name()}">${prop.name()}</a></code></td>
+                            <td class="col"><code><strong>${modifiersBrief(prop) + linkable(prop.type())}</strong></code>&nbsp;</td>
+                            <td class="col"> ${classDoc.getLabel(prop)} </td>
+                            <td class="col"> ${classDoc.getGroup(prop)} </td>
+                            <td class="colLast">${prop.firstSentenceCommentText()}</td>
                         </tr>
                         <% } %>
                     </table>
@@ -488,7 +511,34 @@
         if (visibleMethods || buffer.length()>0) { %>
         <!-- ========== METHOD SUMMARY =========== -->
         <ul class="blockList">
-            <% if (visibleMethods) { %>
+            <% if (getterMethods) { %>
+            <li class="blockList"><a name="method_summary"><!--   --></a>
+                <h3>Reportable Properties Summary</h3>
+                <ul class="blockList">
+                    <table class="overviewSummary" border="0" cellpadding="3" cellspacing="0" summary="Reportable Properties Summary table">
+                        <caption><span>Reportable Properties</span><span class="tabEnd">&nbsp;</span></caption>
+                        <tr>
+                            <th class="colFirst" scope="col">Name</th>
+                            <th class="col" scope="col">Type</th>
+                            <th class="col" scope="col">Label</th>
+                            <th class="col" scope="col">Group</th>
+                            <th class="colLast" scope="col">Description</th>
+                        </tr>
+                        <% getterMethods.eachWithIndex { method, i -> %>
+                        <tr class="${i%2==0?'altColor':'rowColor'}">
+                            <td class="colFirst"><code><strong><a href="#${nameFromParams(method)}">${asPropertyName(method.name())}</a></strong></code></td>
+                            <td class="col"><code>${modifiersBrief(method)}${linkable(method.returnType())}</strong></code></td>
+                            <td class="col">${classDoc.getLabel(method)}</td>
+                            <td class="col">${classDoc.getGroup(method)}</td>
+                            <td class="colLast">${method.firstSentenceCommentText()}</td>
+                        </tr>
+                        <% } %>
+                    </table>
+                </ul>
+            </li>
+            <% } // if (getterMethods) %>
+
+            <% if (nonGetterMethods) { %>
             <li class="blockList"><a name="method_summary"><!--   --></a>
                     <h3>Methods Summary</h3>
                     <ul class="blockList">
@@ -498,7 +548,7 @@
                             <th class="colFirst" scope="col">Type</th>
                             <th class="colLast" scope="col">Name and description</th>
                         </tr>
-                        <% visibleMethods.eachWithIndex { method, i -> %>
+                        <% nonGetterMethods.eachWithIndex { method, i -> %>
                         <tr class="${i%2==0?'altColor':'rowColor'}">
                             <td class="colFirst"><code>${modifiersBrief(method)}${linkable(method.returnType())}</strong></code></td>
                             <td class="colLast"><code><strong><a href="#${nameFromParams(method)}">${method.name()}</a></strong>(${paramsOf(method, true)})</code><br>${method.firstSentenceCommentText()}</td>
@@ -507,9 +557,9 @@
                     </table>
                    </ul>
               </li>
-            <% } // if (visibleMethods)
+            <% } // if (nonGetterMethods)
             if (buffer.length()>0) {
-                %>
+            %>
             <li class="blockList"><a name="method_summary"><!--   --></a>
                     <h3>Inherited Methods Summary</h3>
                     <ul class="blockList">
@@ -585,8 +635,9 @@
                         <a name="${prop.name()}"><!-- --></a>
                         <ul class="blockListLast">
                             <li class="blockList">
-                                <h4>${modifiers(prop) + linkable(prop.type())} <strong>${prop.name()}</strong></h4>
-                                <blockquote><pre>${annotations(prop, '\n')}</pre></blockquote>
+                                <h4>${prop.name()}</h4>
+                                <h5>Type: ${ modifiers(prop) + linkable(prop.type()) }</h5>
+                                <div>${annotations(prop, '<br/>') } </div>
                                 <p>${prop.commentText()}</p>
                             </li>
                         </ul>
@@ -647,8 +698,9 @@
                         <a name="${nameFromParams(method)}"><!-- --></a>
                         <ul class="blockListLast">
                             <li class="blockList">
-                                <h4>${modifiers(method)}${linkable(method.returnType())} <strong>${method.name()}</strong>(${paramsOf(method, false)})</h4>
-                                <blockquote><pre>${annotations(method, '\n')}</pre></blockquote>
+                                <h4>${method.name()}(${paramsOf(method, false)}) </h4>
+                                <h5>Type: ${ modifiers(method) + linkable(method.returnType()) }</h5>
+                                <div>${annotations(method, '<br/>') } </div>
                                 <p>${method.commentText()}</p>
                             </li>
                         </ul>
@@ -691,19 +743,19 @@
     if (classDoc.isAnnotationType()) {
         def hasReq = classDoc.fields().any{ isRequired(it, "true") }
         def hasOpt = classDoc.fields().any{ isRequired(it, "false") }
-        if (hasReq) { %><li><a href="#required_element_summary"><% } %>Required<% if (hasReq) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<% 
-        if (hasOpt) { %><li><a href="#optional_element_summary"><% } %>Optional<% if (hasOpt) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<% 
+        if (hasReq) { %><li><a href="#required_element_summary"><% } %>Required<% if (hasReq) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<%
+        if (hasOpt) { %><li><a href="#optional_element_summary"><% } %>Optional<% if (hasOpt) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<%
     } else {
-        if (visibleNested) { %><li><a href="#nested_summary"><% } %>Nested<% if (visibleNested) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<% 
+        if (visibleNested) { %><li><a href="#nested_summary"><% } %>Nested<% if (visibleNested) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<%
         if (classDoc.isEnum()) {
-            if (hasEnumConstants) { %><li><a href="#enum_constant_summary"><% } %>Enum constants<% if (hasEnumConstants) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<% 
+            if (hasEnumConstants) { %><li><a href="#enum_constant_summary"><% } %>Enum constants<% if (hasEnumConstants) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<%
         }
-        if (hasFields) { %><li><a href="#field_summary"><% } %>Field<% if (hasFields) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<% 
-        if (hasProperties) { %><li><a href="#property_summary">Property</a></li><% } %>&nbsp;&nbsp;&nbsp;<% 
+        if (hasFields) { %><li><a href="#field_summary"><% } %>Field<% if (hasFields) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<%
+        if (hasProperties) { %><li><a href="#property_summary">Property</a></li><% } %>&nbsp;&nbsp;&nbsp;<%
         if (classDoc.isClass()) {
-            if (visibleConstructors) { %><li><a href="#constructor_summary"><% } %>Constructor<% if (visibleConstructors) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<% 
+            if (visibleConstructors) { %><li><a href="#constructor_summary"><% } %>Constructor<% if (visibleConstructors) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<%
         }
-        if (visibleMethods) { %><li><a href="#method_summary"><% } %>Method<% if (visibleMethods) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<% 
+        if (visibleMethods) { %><li><a href="#method_summary"><% } %>Method<% if (visibleMethods) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<%
     }
     %>
         </ul>
@@ -711,17 +763,17 @@
             <li>&nbsp;|&nbsp;Detail:&nbsp;</li>
             <%
             if (classDoc.isAnnotationType()) {
-                if (hasElements) { %><li><a href="#element_detail"><% } %>Element<% if (hasElements) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<% 
+                if (hasElements) { %><li><a href="#element_detail"><% } %>Element<% if (hasElements) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<%
             } else {
                 if (classDoc.isEnum()) {
-                    if (hasEnumConstants) { %><li><a href="#enum_constant_detail"><% } %>Enum constants<% if (hasEnumConstants) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<% 
+                    if (hasEnumConstants) { %><li><a href="#enum_constant_detail"><% } %>Enum constants<% if (hasEnumConstants) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<%
                 }
-                if (hasFields) { %><li><a href="#field_detail"><% } %>Field<% if (hasFields) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<% 
-                if (hasProperties) { %><li><a href="#prop_detail">Property</a></li><% } %>&nbsp;&nbsp;&nbsp;<% 
+                if (hasFields) { %><li><a href="#field_detail"><% } %>Field<% if (hasFields) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<%
+                if (hasProperties) { %><li><a href="#prop_detail">Property</a></li><% } %>&nbsp;&nbsp;&nbsp;<%
                 if (classDoc.isClass()) {
-                    if (visibleConstructors) { %><li><a href="#constructor_detail"><% } %>Constructor<% if (visibleConstructors) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<% 
+                    if (visibleConstructors) { %><li><a href="#constructor_detail"><% } %>Constructor<% if (visibleConstructors) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<%
                 }
-                if (visibleMethods) { %><li><a href="#method_detail"><% } %>Method<% if (visibleMethods) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<% 
+                if (visibleMethods) { %><li><a href="#method_detail"><% } %>Method<% if (visibleMethods) { %></a></li><% } %>&nbsp;&nbsp;&nbsp;<%
             }
             %>
         </ul>
--- a/src/main/resources/org/ssdt_ohio/gradle/userdoc/templates/stylesheet.css	Mon Jan 11 16:55:32 2016 +0000
+++ b/src/main/resources/org/ssdt_ohio/gradle/userdoc/templates/stylesheet.css	Wed Mar 16 23:24:26 2016 +0100
@@ -1,3 +1,21 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
 @charset "${props.charset}";
 
 /*! normalize.css v2.1.0 | MIT License | git.io/normalize */
@@ -2159,6 +2177,20 @@
     display: inline
 }
 
+table.overviewSummary tr {
+    border-left: 1px solid #EEE;
+    border-right: 1px solid #EEE;
+}
+
+table.overviewSummary tr:first-child {
+    border-top: 1px solid #EEE;
+    border-bottom: 1px solid #EEE;
+}
+
+table.overviewSummary tr:last-child {
+    border-bottom: 1px solid #EEE;
+}
+
 table.overviewSummary, .contentContainer ul li table {
     width: 100%;
     margin: 20px 0
@@ -2171,22 +2203,23 @@
     float: left;
     padding: 0 10px;
     margin-top: 10px;
-    background: #db4800;
+    background: #6884db;
     color: white
 }
 
 table.overviewSummary tr th, .contentContainer ul li table tr th {
-    padding: 10px;
+    padding: 5px 10px;
     font-weight: bold;
     font-size: 1em;
-    text-align: left
+    text-align: left;
+    white-space: nowrap;
+    background: #f2f2f2
 }
 
 table.overviewSummary tr td, .contentContainer ul li table tr td {
     vertical-align: top;
     font-size: .9em;
-    padding: 5px 10px;
-    border-top: 1px solid #EEE
+    padding: 5px 10px
 }
 
 table.overviewSummary tbody > tr:nth-child(odd) > td, .contentContainer ul li table tbody > tr:nth-child(odd) > td {
@@ -2205,7 +2238,7 @@
     margin: 0 10px;
     padding: 3px 10px;
     margin-top: 10px;
-    background: #db4800;
+    background: #6884DB;
     color: white;
     line-height: 40px
 }
@@ -2303,4 +2336,4 @@
 
 a span.strong {
     font-weight: normal
-}
\ No newline at end of file
+}