This is an automated email from the ASF dual-hosted git repository.

jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git


The following commit(s) were added to refs/heads/master by this push:
     new 5a9e0fc  Swagger UI enhancements.
5a9e0fc is described below

commit 5a9e0fc85a8d94d4780239f964beae5486473a72
Author: JamesBognar <[email protected]>
AuthorDate: Fri Apr 6 09:02:23 2018 -0400

    Swagger UI enhancements.
---
 .../org/apache/juneau/dto/swagger/Swagger.java     | 18 +++++++
 .../apache/juneau/dto/swagger/SwaggerElement.java  | 62 +++++++++++++---------
 .../apache/juneau/dto/swagger/ui/SwaggerUI.java    | 36 ++++++++++++-
 .../org/apache/juneau/dto/swagger/ui/SwaggerUI.css | 33 ++++++------
 .../src/main/java/org/apache/juneau/ClassMeta.java |  9 ++++
 .../apache/juneau/rest/BasicRestInfoProvider.java  | 54 +++++++++++++++++--
 .../org/apache/juneau/rest/BasicRestServlet.java   |  7 +++
 7 files changed, 172 insertions(+), 47 deletions(-)

diff --git 
a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Swagger.java
 
b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Swagger.java
index 27afa97..004eaa8 100644
--- 
a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Swagger.java
+++ 
b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Swagger.java
@@ -765,6 +765,15 @@ public class Swagger extends SwaggerElement {
        }
 
        /**
+        * Convenience method for testing whether this Swagger has one or more 
definitions defined.
+        * 
+        * @return <jk>true</jk> if this Swagger has one or more definitions 
defined.
+        */
+       public boolean hasDefinitions() {
+               return definitions != null && ! definitions.isEmpty();
+       }
+
+       /**
         * Bean property getter:  <property>parameters</property>.
         * 
         * <p>
@@ -1201,6 +1210,15 @@ public class Swagger extends SwaggerElement {
        }
 
        /**
+        * Convenience method for testing whether this Swagger has one or more 
tags defined.
+        * 
+        * @return <jk>true</jk> if this Swagger has one or more tags defined.
+        */
+       public boolean hasTags() {
+               return tags != null && ! tags.isEmpty();
+       }
+
+       /**
         * Bean property getter:  <property>externalDocs</property>.
         * 
         * <p>
diff --git 
a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/SwaggerElement.java
 
b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/SwaggerElement.java
index b5aef00..aca2626 100644
--- 
a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/SwaggerElement.java
+++ 
b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/SwaggerElement.java
@@ -18,6 +18,7 @@ import java.util.*;
 
 import org.apache.juneau.annotation.*;
 import org.apache.juneau.json.*;
+import org.apache.juneau.utils.*;
 
 /**
  * Root class for all Swagger beans.
@@ -73,28 +74,6 @@ public abstract class SwaggerElement {
        }
 
        /**
-        * The map used to store 'extra' properties on the swagger element.
-        * 
-        * <p>
-        * For example, the <js>"$ref"</js> field is not a part of the Swagger 
doc, but is often
-        * found since it is a part of the JSON-Schema spec. 
-        * <br>This map allows you to store such properties.
-        * 
-        * <p>
-        * This map is lazy-created once this method is called.
-        * 
-        * @return 
-        *      The extra properties map.
-        *      <br>It's an instance of {@link LinkedHashMap}.
-        */
-       @BeanProperty("*")
-       public Map<String,Object> getExtraProperties() {
-               if (extra == null || extra.isEmpty())
-                       return null;
-               return extra;
-       }
-       
-       /**
         * Generic property getter.
         * 
         * <p>
@@ -109,11 +88,27 @@ public abstract class SwaggerElement {
                        return null;
                switch (property) {
                        case "strict": return toType(isStrict(), type);
-                       default: return extra == null ? null : 
toType(getExtraProperties().get(property), type);
+                       default: return toType(get(property), type);
                }
        };
        
        /**
+        * Generic property getter.
+        * 
+        * <p>
+        * Can be used to retrieve non-standard Swagger fields such as 
<js>"$ref"</js>.
+        * 
+        * @param property The property name to retrieve.
+        * @return The property value, or <jk>null</jk> if the property does 
not exist or is not set.
+        */
+       @BeanProperty("*")
+       public Object get(String property) {
+               if (property == null || extra == null)
+                       return null;
+               return extra.get(property);
+       };
+
+       /**
         * Generic property setter.
         * 
         * <p>
@@ -138,12 +133,29 @@ public abstract class SwaggerElement {
        }
        
        /**
+        * Generic property keyset.
+        * 
+        * @return 
+        *      All the non-standard keys on this element.
+        *      <br>Never <jk>null</jk>.
+        */
+       @BeanProperty("*")
+       public Set<String> extraKeys() {
+               return extra == null ? Collections.EMPTY_SET : extra.keySet();
+       }
+       
+       /**
         * Returns all the keys on this element.
         * 
-        * @return All the keys on this element.
+        * @return 
+        *      All the keys on this element.
+        *      <br>Never <jk>null</jk>.
         */
        public Set<String> keySet() {
-               return extra == null ? Collections.EMPTY_SET : extra.keySet();
+               ASet<String> s = new ASet<String>()
+                       .appendIf(strict, "strict");
+               s.addAll(extraKeys());
+               return s;
        }
        
        @Override /* Object */
diff --git 
a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ui/SwaggerUI.java
 
b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ui/SwaggerUI.java
index 26e418e..d5e76c8 100644
--- 
a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ui/SwaggerUI.java
+++ 
b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ui/SwaggerUI.java
@@ -51,7 +51,7 @@ public class SwaggerUI extends PojoSwap<Swagger,Div> {
                // Operations without tags are rendered first.
                outer.child(div()._class("tag-block 
tag-block-open").children(tagBlockContents(s, null)));
 
-               if (s.getTags() != null) {
+               if (s.hasTags()) {
                        for (Tag t : s.getTags()) {
                                Div tagBlock = div()._class("tag-block 
tag-block-open").children(
                                        tagBlockSummary(t),
@@ -61,6 +61,14 @@ public class SwaggerUI extends PojoSwap<Swagger,Div> {
                        }
                }
                
+               if (s.hasDefinitions()) {
+                       Div modelBlock = div()._class("tag-block").children(
+                               modelsBlockSummary(),
+                               modelsBlockContents(s)
+                       );
+                       outer.child(modelBlock);
+               }
+               
                return outer;
        }
        
@@ -264,4 +272,30 @@ public class SwaggerUI extends PojoSwap<Swagger,Div> {
                
                return div;
        }
+       
+       // Creates the "Model" header.
+       private HtmlElement modelsBlockSummary() {
+               return 
div()._class("tag-block-summary").children(span("Models")._class("name")).onclick("toggleTagBlock(this)");
+       }
+       
+       // Creates the contents under the "Model" header.
+       private Div modelsBlockContents(Swagger s) {
+               Div modelBlockContents = div()._class("tag-block-contents");
+               for (Map.Entry<String,ObjectMap> e : 
s.getDefinitions().entrySet()) 
+                       modelBlockContents.child(modelBlock(e.getKey(), 
e.getValue()));
+               return modelBlockContents;
+       }
+
+       private Div modelBlock(String modelName, ObjectMap model) {
+               return div()._class("op-block op-block-closed model").children(
+                       modelBlockSummary(modelName, model),
+                       div(model)._class("op-block-contents")
+               );
+       }
+       private HtmlElement modelBlockSummary(String modelName, ObjectMap 
model) {
+               return div()._class("op-block-summary").children(
+                       span(modelName)._class("method-button"),
+                       model.containsKey("description") ? 
span(model.remove("description"))._class("summary") : null
+               ).onclick("toggleOpBlock(this)");
+       }
 }
diff --git 
a/juneau-core/juneau-dto/src/main/resources/org/apache/juneau/dto/swagger/ui/SwaggerUI.css
 
b/juneau-core/juneau-dto/src/main/resources/org/apache/juneau/dto/swagger/ui/SwaggerUI.css
index 51d13e1..7a80655 100644
--- 
a/juneau-core/juneau-dto/src/main/resources/org/apache/juneau/dto/swagger/ui/SwaggerUI.css
+++ 
b/juneau-core/juneau-dto/src/main/resources/org/apache/juneau/dto/swagger/ui/SwaggerUI.css
@@ -21,13 +21,12 @@
  
----------------------------------------------------------------------------------------------------------*/
 
 .swagger-ui table.header {
-    margin-bottom: 20px;
+    margin-bottom: 15px;
        width: 95%;
        border: none;
 }
 
 .swagger-ui table.header * {
-       font-size: 14px;
        vertical-align: middle;
 }
 
@@ -52,7 +51,6 @@
  
----------------------------------------------------------------------------------------------------------*/
 .method-button {
        display: inline-block;
-       font-size: 14px;
     font-weight: bold;
     min-width: 60px;
     padding: 6px 15px;
@@ -67,8 +65,10 @@
 .delete .method-button     { background: rgb(249,62,62); }
 .options .method-button    { background: rgb(153,102,255); }
 .deprecated .method-button { background: rgb(170,170,170); }
+.model .method-button      { background: rgb(150,150,150); min-width: 120px;}
 .other .method-button      { background: rgb(230,230,0); }
 
+
 
/*-----------------------------------------------------------------------------------------------------------
  - Tag block                                                                   
                             -
  - Encapsulates one or more op-blocks.
@@ -80,18 +80,23 @@
 
 .tag-block-summary {
        margin: 10px 0px;
-       padding: 10px 0px;
+       padding: 5px 0px;
     align-items: center;
     cursor: pointer;
        border-bottom: 1px solid rgba(59,65,81,.2);
        user-select: none;
+       transition: all .2s;
+}
+.tag-block-summary:hover {
+       background-color: rgba(59,65,81,.1);
 }
+
 .tag-block-summary .name {
-       font-size: 22px;
+       font-size: 18px;
        padding: 0px 20px;
 }
 .tag-block-summary .description {
-       font-size: 16px;
+       font-size: 14px;
        padding: 0px 20px;
 }
 .tag-block-summary .extdocs {
@@ -120,6 +125,7 @@
 .op-block.options    { background: rgba(153,102,255,.1); border: 1px solid 
rgb(153,102,255); }
 .op-block.delete     { background: rgba(249,62,62,.1); border: 1px solid 
rgb(249,62,62); }
 .op-block.deprecated { background: rgba(170,170,170,.1); border: 1px solid 
rgb(170,170,170); }
+.op-block.model      { background: rgba(0,0,0,.05); border: 1px solid 
rgb(170,170,170); }
 .op-block.other      { background: rgba(230,230,0,0.1); border: 1px solid 
rgb(230,230,0); }
 
 .op-block-summary {    
@@ -129,7 +135,7 @@
 }
 
 .op-block-summary .path {
-       font-size: 16px;
+       font-size: 14px;
        word-break: break-all;
     font-family: monospace;
     font-weight: bold;
@@ -159,7 +165,7 @@
  
----------------------------------------------------------------------------------------------------------*/
 
 .op-block-section-header {
-    padding: 8px 20px;
+    padding: 8px 15px;
     background: hsla(0,0%,100%,.3);
     box-shadow: 1px 2px 3px rgba(0,0,0,.3);
     margin: 10px;
@@ -185,7 +191,6 @@ table.parameters, table.responses {
 th.parameter-key, th.response-key {
        font-size: 12px;
     font-weight: bold;
-    padding: 10px;
     text-align: left;
        border: none;
     border-bottom: 1px solid rgba(59,65,81,.2);
@@ -220,7 +225,7 @@ td.parameter-value, td.response-value {
 }
 
 .parameter-key .name {
-       font-size: 16px;
+       font-size: 14px;
 }
 
 .parameter-key .name.required {
@@ -245,10 +250,9 @@ td.parameter-value, td.response-value {
  
----------------------------------------------------------------------------------------------------------*/
  
 .op-block-contents .example-select {
-    margin: 20px 0 10px 0;
+    margin: 10px 0 5px 0;
        border-width: 1px;
        font-weight:bold;
-       font-size: 14px;
     padding: 5px 40px 5px 10px;
     border: 1px solid #41444e;
     border-radius: 4px;
@@ -262,7 +266,6 @@ td.parameter-value, td.response-value {
 }
 
 .op-block-contents .example {
-    font-size: 12px;
     margin: 0;
     padding: 5px 20px;
     white-space: pre-wrap;
@@ -297,14 +300,12 @@ td.parameter-value, td.response-value {
  
----------------------------------------------------------------------------------------------------------*/
 
 .section {
-       font-size: 12px;
     font-weight: bold;
     padding: 5px 0;
     text-align: left;
 }
 
 .headers .name {
-    font-size: 12px;
     padding: 5px 0;
     font-family: monospace;
     font-weight: bold;
@@ -315,7 +316,6 @@ div.headers {
 }
 
 .headers .type {
-    font-size: 12px;
     padding: 5px 0;
     font-family: monospace;
     font-weight: bold;
@@ -325,7 +325,6 @@ div.headers {
        display: inline-block;
        vertical-align: top;
        margin-right: 20px;
-       font-size: 12px;
     font-weight: bold;
     padding: 5px 0;
     text-align: left;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
index 45c6800..57132de 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
@@ -1969,6 +1969,15 @@ public final class ClassMeta<T> implements Type {
        }
 
        /**
+        * Shortcut for calling {@link Class#getName()} on the inner class of 
this metadata.
+        * 
+        * @return The  name of the inner class.
+        */
+       public String getName() {
+               return innerClass.getName();
+       }
+
+       /**
         * Shortcut for calling {@link Class#getSimpleName()} on the inner 
class of this metadata.
         * 
         * @return The simple name of the inner class.
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestInfoProvider.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestInfoProvider.java
index 1788f15..8f18b2b 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestInfoProvider.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestInfoProvider.java
@@ -14,14 +14,15 @@ package org.apache.juneau.rest;
 
 import static org.apache.juneau.internal.ReflectionUtils.*;
 import static org.apache.juneau.internal.StringUtils.*;
+import static org.apache.juneau.jsonschema.JsonSchemaSerializer.*;
 import static org.apache.juneau.rest.RestParamType.*;
 import static org.apache.juneau.serializer.OutputStreamSerializer.*;
-import static org.apache.juneau.serializer.WriterSerializer.*;
 
 import java.lang.reflect.*;
 import java.lang.reflect.Method;
 import java.util.*;
 import java.util.concurrent.*;
+import java.util.regex.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.dto.swagger.*;
@@ -49,12 +50,48 @@ import org.apache.juneau.utils.*;
  * </ul>
  */
 public class BasicRestInfoProvider implements RestInfoProvider {
+       
+       
//-------------------------------------------------------------------------------------------------------------------
+       // Configurable properties
+       
//-------------------------------------------------------------------------------------------------------------------
+
+       private static final String PREFIX = "BasicRestInfoProvider.";
+       
+       /**
+        * Configuration property:  Ignore types from schema definitions.
+        * 
+        * <h5 class='section'>Property:</h5>
+        * <ul>
+        *      <li><b>Name:</b>  <js>"BasicRestInfoProvider.ignoreTypes.b"</js>
+        *      <li><b>Data type:</b>  <code>String</code> (comma-delimited)
+        *      <li><b>Default:</b>  <jk>null</jk>.
+        *      <li><b>Session-overridable:</b>  <jk>false</jk>
+        * </ul>
+        * 
+        * <h5 class='section'>Description:</h5>
+        * <p>
+        * Defines class name patterns that should be ignored when generating 
schema definitions in the generated 
+        * Swagger documentation.
+        * 
+        * <h5 class='section'>Example:</h5>
+        * <p class='bcode'>
+        *      <jc>// Don't generate schema for any prototype packages or the 
class named 'Swagger'.
+        *      <ja>@RestResource</ja>(
+        *                      properties={
+        *                              
<ja>@Property</ja>(name=<jsf>INFOPROVIDER_ignoreTypes</jsf>, 
value=<js>"Swagger,*.proto.*"</js>)
+        *                      }
+        *      <jk>public class</jk> MyResource {...}
+        * </p>
+        */
+       public static final String INFOPROVIDER_ignoreTypes = PREFIX + 
"ignoreTypes.s";
+       
 
        private final RestContext context;
        private final String
                siteName,
                title,
                description;
+       private final Set<Pattern> ignoreTypes;
        private final 
ConcurrentHashMap<Locale,ConcurrentHashMap<Integer,Swagger>> swaggers = new 
ConcurrentHashMap<>();
 
        /**
@@ -64,7 +101,12 @@ public class BasicRestInfoProvider implements 
RestInfoProvider {
         */
        public BasicRestInfoProvider(RestContext context) {
                this.context = context;
-
+               
+               PropertyStore ps = context.getPropertyStore();
+               this.ignoreTypes = new LinkedHashSet<>();
+               for (String s : split(ps.getProperty(INFOPROVIDER_ignoreTypes, 
String.class, ""))) 
+                       ignoreTypes.add(Pattern.compile(s.replace(".", 
"\\.").replace("*", ".*")));
+               
                Builder b = new Builder(context);
                this.siteName = b.siteName;
                this.title = b.title;
@@ -484,6 +526,10 @@ public class BasicRestInfoProvider implements 
RestInfoProvider {
                if (schema.containsKey("type") || schema.containsKey("$ref")) 
                        return schema;
                
+               for (Pattern p : ignoreTypes) 
+                       if (p.matcher(cm.getSimpleName()).matches() || 
p.matcher(cm.getName()).matches())
+                               return null;
+               
                return fixSwaggerExtensions(schema.appendAll(js.getSchema(cm)));
        }
        
@@ -502,11 +548,11 @@ public class BasicRestInfoProvider implements 
RestInfoProvider {
        private void addXExamples(RestRequest req, RestJavaMethod sm, ObjectMap 
piri, String in, JsonSchemaSerializerSession js, Type type) throws Exception {
                
                Object example = piri.get("x-example");
-
+               
                if (example == null) {
                        ObjectMap schema = resolve(js, 
piri.getObjectMap("schema"));
                        if (schema != null)
-                               example = schema.get("x-example");
+                               example = schema.get("example");
                }
 
                if (example == null)
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestServlet.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestServlet.java
index 7c9a5d0..34dc46e 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestServlet.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestServlet.java
@@ -14,6 +14,7 @@ package org.apache.juneau.rest;
 
 import static org.apache.juneau.http.HttpMethodName.*;
 import static org.apache.juneau.jsonschema.JsonSchemaSerializer.*;
+import static org.apache.juneau.rest.BasicRestInfoProvider.*;
 
 import org.apache.juneau.dto.swagger.*;
 import org.apache.juneau.dto.swagger.ui.*;
@@ -177,8 +178,14 @@ import org.apache.juneau.xmlschema.*;
                SwaggerUI.class
        },
        properties={
+               // Add descriptions to the following types when not specified:
                @Property(name=JSONSCHEMA_addDescriptionsTo, 
value="bean,collection,array,map,enum"),
+               
+               // Add x-example to the following types:
                @Property(name=JSONSCHEMA_addExamplesTo, 
value="bean,collection,array,map"),
+               
+               // Don't generate schema information on the Swagger bean itself.
+               @Property(name=INFOPROVIDER_ignoreTypes, value="Swagger")
        },
        flags={ 
                JSONSCHEMA_useBeanDefs

-- 
To stop receiving notification emails like this one, please contact
[email protected].

Reply via email to