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].