Skip to content
This repository was archived by the owner on Dec 19, 2023. It is now read-only.

Commit c6524b8

Browse files
authored
support for enums (#45)
* support for enums * reworked how description for enums is fetched * items.html * reverted unnecessary changes
1 parent f757f33 commit c6524b8

File tree

18 files changed

+257
-83
lines changed

18 files changed

+257
-83
lines changed

docs/index.html

Lines changed: 55 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -428,33 +428,34 @@ <h1>Spring Auto REST Docs</h1>
428428
<div id="toc" class="toc2">
429429
<div id="toctitle">Table of Contents</div>
430430
<ul class="sectlevel1">
431-
<li><a href="#_faq">FAQ</a></li>
432-
<li><a href="#_getting_started">Getting started</a>
431+
<li><a href="#faq">FAQ</a></li>
432+
<li><a href="#gettingstarted">Getting started</a>
433433
<ul class="sectlevel2">
434-
<li><a href="#_requirements">Requirements</a></li>
435-
<li><a href="#_usage">Usage</a></li>
436-
<li><a href="#_sample_application">Sample application</a></li>
434+
<li><a href="#gettingstarted-requirements">Requirements</a></li>
435+
<li><a href="#gettingstarted-usage">Usage</a></li>
436+
<li><a href="#gettingstarted-sample">Sample application</a></li>
437437
</ul>
438438
</li>
439-
<li><a href="#_snippets">Snippets</a>
439+
<li><a href="#snippets">Snippets</a>
440440
<ul class="sectlevel2">
441-
<li><a href="#_authorization_snippet">Authorization snippet</a></li>
442-
<li><a href="#_path_parameter_snippet">Path parameter snippet</a></li>
443-
<li><a href="#_request_parameter_snippet">Request parameter snippet</a></li>
444-
<li><a href="#_section_snippet">Section snippet</a></li>
441+
<li><a href="#snippets-authorization">Authorization snippet</a></li>
442+
<li><a href="#snippets-path-parameters">Path parameter snippet</a></li>
443+
<li><a href="#snippets-request-parameters">Request parameter snippet</a></li>
444+
<li><a href="#snippets-section">Section snippet</a></li>
445445
</ul>
446446
</li>
447-
<li><a href="#_documenting_constraints">Documenting constraints</a>
447+
<li><a href="#constraints">Documenting constraints</a>
448448
<ul class="sectlevel2">
449-
<li><a href="#_constraint_that_determine_optionality">Constraint that determine optionality</a></li>
450-
<li><a href="#_custom_constraints">Custom constraints</a></li>
451-
<li><a href="#_readable_constraint_values">Readable constraint values</a></li>
452-
<li><a href="#_constraint_groups">Constraint groups</a></li>
449+
<li><a href="#constraints-optionality">Constraint that determine optionality</a></li>
450+
<li><a href="#constraints-custom">Custom constraints</a></li>
451+
<li><a href="#constraints-enums">Enums</a></li>
452+
<li><a href="#constraints-readable-values">Readable constraint values</a></li>
453+
<li><a href="#constraints-groups">Constraint groups</a></li>
453454
</ul>
454455
</li>
455-
<li><a href="#_contributing">Contributing</a>
456+
<li><a href="#contributing">Contributing</a>
456457
<ul class="sectlevel2">
457-
<li><a href="#_building_from_source">Building from source</a></li>
458+
<li><a href="#contributing-building">Building from source</a></li>
458459
</ul>
459460
</li>
460461
</ul>
@@ -503,7 +504,7 @@ <h1>Spring Auto REST Docs</h1>
503504
</div>
504505
</div>
505506
<div class="sect1">
506-
<h2 id="_faq"><a class="link" href="#_faq">FAQ</a></h2>
507+
<h2 id="faq"><a class="link" href="#faq">FAQ</a></h2>
507508
<div class="sectionbody">
508509
<div class="qlist qanda">
509510
<ol>
@@ -524,10 +525,10 @@ <h2 id="_faq"><a class="link" href="#_faq">FAQ</a></h2>
524525
</div>
525526
</div>
526527
<div class="sect1">
527-
<h2 id="_getting_started"><a class="link" href="#_getting_started">Getting started</a></h2>
528+
<h2 id="gettingstarted"><a class="link" href="#gettingstarted">Getting started</a></h2>
528529
<div class="sectionbody">
529530
<div class="sect2">
530-
<h3 id="_requirements"><a class="link" href="#_requirements">Requirements</a></h3>
531+
<h3 id="gettingstarted-requirements"><a class="link" href="#gettingstarted-requirements">Requirements</a></h3>
531532
<div class="paragraph">
532533
<p>Spring Auto REST Docs has the following minimum requirements:</p>
533534
</div>
@@ -546,7 +547,7 @@ <h3 id="_requirements"><a class="link" href="#_requirements">Requirements</a></h
546547
</div>
547548
</div>
548549
<div class="sect2">
549-
<h3 id="_usage"><a class="link" href="#_usage">Usage</a></h3>
550+
<h3 id="gettingstarted-usage"><a class="link" href="#gettingstarted-usage">Usage</a></h3>
550551
<div class="olist arabic">
551552
<ol class="arabic">
552553
<li>
@@ -655,7 +656,7 @@ <h3 id="_usage"><a class="link" href="#_usage">Usage</a></h3>
655656
</div>
656657
</div>
657658
<div class="sect2">
658-
<h3 id="_sample_application"><a class="link" href="#_sample_application">Sample application</a></h3>
659+
<h3 id="gettingstarted-sample"><a class="link" href="#gettingstarted-sample">Sample application</a></h3>
659660
<div class="paragraph">
660661
<p><a href="https://github.com/ScaCap/spring-auto-restdocs/tree/master/spring-auto-restdocs-example">This project</a> includes a sample application that demonstrates most features:</p>
661662
</div>
@@ -666,10 +667,10 @@ <h3 id="_sample_application"><a class="link" href="#_sample_application">Sample
666667
</div>
667668
</div>
668669
<div class="sect1">
669-
<h2 id="_snippets"><a class="link" href="#_snippets">Snippets</a></h2>
670+
<h2 id="snippets"><a class="link" href="#snippets">Snippets</a></h2>
670671
<div class="sectionbody">
671672
<div class="sect2">
672-
<h3 id="_authorization_snippet"><a class="link" href="#_authorization_snippet">Authorization snippet</a></h3>
673+
<h3 id="snippets-authorization"><a class="link" href="#snippets-authorization">Authorization snippet</a></h3>
673674
<div class="paragraph">
674675
<p>The authorization snippet does not help in adding authorization to your tests, but it makes it easy to document your authorization information.
675676
Usually, a custom <code>RequestPostProcessor</code> is used to add authorization and this is also the place where you add the documentation.</p>
@@ -691,7 +692,7 @@ <h3 id="_authorization_snippet"><a class="link" href="#_authorization_snippet">A
691692
</div>
692693
</div>
693694
<div class="sect2">
694-
<h3 id="_path_parameter_snippet"><a class="link" href="#_path_parameter_snippet">Path parameter snippet</a></h3>
695+
<h3 id="snippets-path-parameters"><a class="link" href="#snippets-path-parameters">Path parameter snippet</a></h3>
695696
<div class="paragraph">
696697
<p>The path parameter snippet automatically lists parameters in the path including their type, whether they are optional, and their JavaDoc.</p>
697698
</div>
@@ -738,7 +739,7 @@ <h3 id="_path_parameter_snippet"><a class="link" href="#_path_parameter_snippet"
738739
</table>
739740
</div>
740741
<div class="sect2">
741-
<h3 id="_request_parameter_snippet"><a class="link" href="#_request_parameter_snippet">Request parameter snippet</a></h3>
742+
<h3 id="snippets-request-parameters"><a class="link" href="#snippets-request-parameters">Request parameter snippet</a></h3>
742743
<div class="paragraph">
743744
<p>The request parameter snippet automatically lists query parameters including their type, whether they are optional, and their JavaDoc.</p>
744745
</div>
@@ -779,7 +780,7 @@ <h3 id="_request_parameter_snippet"><a class="link" href="#_request_parameter_sn
779780
</table>
780781
</div>
781782
<div class="sect2">
782-
<h3 id="_section_snippet"><a class="link" href="#_section_snippet">Section snippet</a></h3>
783+
<h3 id="snippets-section"><a class="link" href="#snippets-section">Section snippet</a></h3>
783784
<div class="paragraph">
784785
<p>The section snippet combines all snippets in this REST Docs extensions and also includes unmodified snippets from Spring REST Docs.
785786
It helps you being even more lazy, because a single line of AsciiDoc is sufficient to document one endpoint.
@@ -903,7 +904,7 @@ <h3 id="_section_snippet"><a class="link" href="#_section_snippet">Section snipp
903904
</div>
904905
</div>
905906
<div class="sect1">
906-
<h2 id="_documenting_constraints"><a class="link" href="#_documenting_constraints">Documenting constraints</a></h2>
907+
<h2 id="constraints"><a class="link" href="#constraints">Documenting constraints</a></h2>
907908
<div class="sectionbody">
908909
<div class="paragraph">
909910
<p>Spring REST Docs has support for documenting constraints,
@@ -913,7 +914,7 @@ <h2 id="_documenting_constraints"><a class="link" href="#_documenting_constraint
913914
and to add the constraint descriptions to the field descriptions.</p>
914915
</div>
915916
<div class="sect2">
916-
<h3 id="_constraint_that_determine_optionality"><a class="link" href="#_constraint_that_determine_optionality">Constraint that determine optionality</a></h3>
917+
<h3 id="constraints-optionality"><a class="link" href="#constraints-optionality">Constraint that determine optionality</a></h3>
917918
<div class="paragraph">
918919
<p>The following three constraints are used to determine whether a field is optional.
919920
Their descriptions are not included in the field descriptions.</p>
@@ -933,13 +934,14 @@ <h3 id="_constraint_that_determine_optionality"><a class="link" href="#_constrai
933934
</div>
934935
</div>
935936
<div class="sect2">
936-
<h3 id="_custom_constraints"><a class="link" href="#_custom_constraints">Custom constraints</a></h3>
937+
<h3 id="constraints-custom"><a class="link" href="#constraints-custom">Custom constraints</a></h3>
937938
<div class="paragraph">
938939
<p>Descriptions for custom constraints can be provided in <code>org.springframework.restdocs.constraints.ConstraintDescriptions.properties</code>.
939940
If this file can be loaded as a resource, descriptions are extracted.
940941
Each description is a property where the key is the full class name of the annotation suffixed with <code>.description</code>.
941942
The value is the description and can contain placeholders for annotation methods,
942-
e.g. <code>${value}</code> to get the content of <code>value()</code>.</p>
943+
e.g. <code>${value}</code> to get the content of <code>value()</code>.
944+
For more details, see original documentation of <a href="http://docs.spring.io/spring-restdocs/docs/1.1.2.RELEASE/reference/html5/#documenting-your-api-constraints-describing">here</a>.</p>
943945
</div>
944946
<div class="paragraph">
945947
<p>Example for the constraint annotation <code>myproject.constraints.OneOf</code>:</p>
@@ -952,7 +954,15 @@ <h3 id="_custom_constraints"><a class="link" href="#_custom_constraints">Custom
952954
</div>
953955
</div>
954956
<div class="sect2">
955-
<h3 id="_readable_constraint_values"><a class="link" href="#_readable_constraint_values">Readable constraint values</a></h3>
957+
<h3 id="constraints-enums"><a class="link" href="#constraints-enums">Enums</a></h3>
958+
<div class="paragraph">
959+
<p>Constraint message for enum is appended to description field as list of allowed values, e.g. <code>Must be one of [A, B]</code>.
960+
If you want to customize this message, use <a href="#constraints-custom">above mentioned</a> <code>ConstraintDescriptions.properties</code> approach.
961+
The list of values is represented by the <code>${value}</code> placeholder.</p>
962+
</div>
963+
</div>
964+
<div class="sect2">
965+
<h3 id="constraints-readable-values"><a class="link" href="#constraints-readable-values">Readable constraint values</a></h3>
956966
<div class="paragraph">
957967
<p>Spring REST Docs just calls <code>toString()</code> objects extracted from
958968
the constraint for documentation.
@@ -973,16 +983,16 @@ <h3 id="_readable_constraint_values"><a class="link" href="#_readable_constraint
973983
</div>
974984
</div>
975985
<div class="sect2">
976-
<h3 id="_constraint_groups"><a class="link" href="#_constraint_groups">Constraint groups</a></h3>
986+
<h3 id="constraints-groups"><a class="link" href="#constraints-groups">Constraint groups</a></h3>
977987
<div class="paragraph">
978988
<p>Constraint groups are also included in the documentation if
979989
a description is provided for them.
980990
The descriptions are provided in the same way as for custom constraints.</p>
981991
</div>
982992
<div class="sect3">
983-
<h4 id="_examples"><a class="link" href="#_examples">Examples</a></h4>
993+
<h4 id="constraints-examples"><a class="link" href="#constraints-examples">Examples</a></h4>
984994
<div class="sect4">
985-
<h5 id="_descriptions_for_the_examples"><a class="link" href="#_descriptions_for_the_examples">Descriptions for the examples</a></h5>
995+
<h5 id="constraints-examples-descriptions"><a class="link" href="#constraints-examples-descriptions">Descriptions for the examples</a></h5>
986996
<div class="listingblock secondary">
987997
<div class="title">ConstraintDescriptions.properties</div>
988998
<div class="content">
@@ -993,7 +1003,7 @@ <h5 id="_descriptions_for_the_examples"><a class="link" href="#_descriptions_for
9931003
</div>
9941004
</div>
9951005
<div class="sect4">
996-
<h5 id="_optionality_description"><a class="link" href="#_optionality_description">Optionality description</a></h5>
1006+
<h5 id="constraints-examples-optionality"><a class="link" href="#constraints-examples-optionality">Optionality description</a></h5>
9971007
<div class="listingblock secondary">
9981008
<div class="title">Code</div>
9991009
<div class="content">
@@ -1021,14 +1031,15 @@ <h5 id="_optionality_description"><a class="link" href="#_optionality_descriptio
10211031
<tr>
10221032
<td class="tableblock halign-left valign-top"><p class="tableblock">field</p></td>
10231033
<td class="tableblock halign-left valign-top"><p class="tableblock">String</p></td>
1024-
<td class="tableblock halign-left valign-top"><p class="tableblock">true, EN: false</p></td>
1034+
<td class="tableblock halign-left valign-top"><p class="tableblock">true<br>
1035+
EN: false</p></td>
10251036
<td class="tableblock halign-left valign-top"></td>
10261037
</tr>
10271038
</tbody>
10281039
</table>
10291040
</div>
10301041
<div class="sect4">
1031-
<h5 id="_field_description_example"><a class="link" href="#_field_description_example">Field description example</a></h5>
1042+
<h5 id="constraints-examples-fields"><a class="link" href="#constraints-examples-fields">Field description example</a></h5>
10321043
<div class="listingblock secondary">
10331044
<div class="title">Code</div>
10341045
<div class="content">
@@ -1057,7 +1068,7 @@ <h5 id="_field_description_example"><a class="link" href="#_field_description_ex
10571068
<td class="tableblock halign-left valign-top"><p class="tableblock">field</p></td>
10581069
<td class="tableblock halign-left valign-top"><p class="tableblock">String</p></td>
10591070
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
1060-
<td class="tableblock halign-left valign-top"><p class="tableblock">EN: Must be one of [big, small]</p></td>
1071+
<td class="tableblock halign-left valign-top"><p class="tableblock">EN: Must be one of [big, small]</p></td>
10611072
</tr>
10621073
</tbody>
10631074
</table>
@@ -1067,12 +1078,12 @@ <h5 id="_field_description_example"><a class="link" href="#_field_description_ex
10671078
</div>
10681079
</div>
10691080
<div class="sect1">
1070-
<h2 id="_contributing"><a class="link" href="#_contributing">Contributing</a></h2>
1081+
<h2 id="contributing"><a class="link" href="#contributing">Contributing</a></h2>
10711082
<div class="sectionbody">
10721083
<div class="sect2">
1073-
<h3 id="_building_from_source"><a class="link" href="#_building_from_source">Building from source</a></h3>
1084+
<h3 id="contributing-building"><a class="link" href="#contributing-building">Building from source</a></h3>
10741085
<div class="sect3">
1075-
<h4 id="_get_spring_restdocs_core_test_jar"><a class="link" href="#_get_spring_restdocs_core_test_jar">Get spring-restdocs-core test JAR</a></h4>
1086+
<h4 id="contributing-building-testjar"><a class="link" href="#contributing-building-testjar">Get spring-restdocs-core test JAR</a></h4>
10761087
<div class="paragraph">
10771088
<p>The test JAR is not published, but this project relies on it.
10781089
If you want to build this project yourself, you first have to build and copy the test JAR on your system.</p>
@@ -1117,7 +1128,7 @@ <h4 id="_get_spring_restdocs_core_test_jar"><a class="link" href="#_get_spring_r
11171128
</div>
11181129
</div>
11191130
<div class="sect3">
1120-
<h4 id="_build"><a class="link" href="#_build">Build</a></h4>
1131+
<h4 id="contributing-building-build"><a class="link" href="#contributing-building-build">Build</a></h4>
11211132
<div class="listingblock secondary">
11221133
<div class="title">Bash (in root folder)</div>
11231134
<div class="content">
@@ -1131,7 +1142,7 @@ <h4 id="_build"><a class="link" href="#_build">Build</a></h4>
11311142
</div>
11321143
<div id="footer">
11331144
<div id="footer-text">
1134-
Last updated 2016-09-15 15:25:01 CEST
1145+
Last updated 2016-09-26 17:14:36 CEST
11351146
</div>
11361147
</div>
11371148
<link rel="stylesheet" href="highlight/styles/github.min.css">

spring-auto-restdocs-core/src/main/java/capital/scalable/restdocs/constraints/ConstraintAndGroupDescriptionResolver.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ public List<Class> getGroups(Constraint constraint) {
8181
public String resolveGroupDescription(Class group, String constraintDescription) {
8282
// Pretending that the group class is a constraint to use the same logic for getting
8383
// a description.
84-
Constraint groupConstraint = new Constraint(group.getName(),
84+
Constraint groupConstraint = new Constraint(group.getCanonicalName(),
8585
singletonMap(VALUE, (Object) constraintDescription));
8686
String result = resolvePlainDescription(groupConstraint);
8787
return isBlank(result) ? fallbackGroupDescription(group, constraintDescription) : result;

spring-auto-restdocs-core/src/main/java/capital/scalable/restdocs/constraints/ConstraintReaderImpl.java

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,22 @@
1616

1717
package capital.scalable.restdocs.constraints;
1818

19+
import static capital.scalable.restdocs.constraints.ConstraintAndGroupDescriptionResolver.VALUE;
1920
import static capital.scalable.restdocs.constraints.SkippableConstraintResolver
2021
.MANDATORY_VALUE_ANNOTATIONS;
22+
import static capital.scalable.restdocs.util.ObjectUtil.arrayToString;
23+
import static java.util.Collections.emptyList;
24+
import static java.util.Collections.singletonList;
25+
import static java.util.Collections.singletonMap;
2126
import static org.apache.commons.lang3.ArrayUtils.contains;
27+
import static org.apache.commons.lang3.StringUtils.isBlank;
28+
import static org.springframework.util.ReflectionUtils.findField;
2229

2330
import java.util.ArrayList;
2431
import java.util.List;
2532

2633
import org.springframework.core.MethodParameter;
34+
import org.springframework.restdocs.constraints.Constraint;
2735
import org.springframework.restdocs.constraints.ConstraintDescriptions;
2836
import org.springframework.restdocs.constraints.ConstraintResolver;
2937
import org.springframework.restdocs.constraints.ResourceBundleConstraintDescriptionResolver;
@@ -55,11 +63,34 @@ public boolean isMandatory(Class<?> annotation) {
5563
public List<String> getConstraintMessages(Class<?> javaBaseClass, String javaFieldName) {
5664
ConstraintDescriptions constraints = new ConstraintDescriptions(javaBaseClass,
5765
constraintResolver, constraintDescriptionResolver);
58-
return constraints.descriptionsForProperty(javaFieldName);
66+
List<String> constraintMessages = new ArrayList<>();
67+
constraintMessages.addAll(constraints.descriptionsForProperty(javaFieldName));
68+
constraintMessages.addAll(getEnumConstraintMessage(javaBaseClass, javaFieldName));
69+
return constraintMessages;
5970
}
6071

6172
@Override
6273
public List<String> getConstraintMessages(MethodParameter param) {
6374
return new ArrayList<>(); // TODO method parameter constraints
6475
}
76+
77+
private List<String> getEnumConstraintMessage(Class<?> javaBaseClass, String javaFieldName) {
78+
// could be getter actually
79+
Class<?> rawClass = findField(javaBaseClass, javaFieldName).getType();
80+
if (rawClass == null || !rawClass.isEnum()) {
81+
return emptyList();
82+
}
83+
Class<Enum> enumClass = (Class<Enum>) rawClass;
84+
85+
String value = arrayToString(enumClass.getEnumConstants());
86+
String enumName = enumClass.getCanonicalName();
87+
String message = constraintDescriptionResolver.resolveDescription(
88+
new Constraint(enumName, singletonMap(VALUE, (Object) value)));
89+
90+
// fallback
91+
if (isBlank(message) || message.equals(enumName)) {
92+
message = "Must be one of " + value;
93+
}
94+
return singletonList(message);
95+
}
6596
}

spring-auto-restdocs-core/src/main/java/capital/scalable/restdocs/constraints/HumanReadableConstraintResolver.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616

1717
package capital.scalable.restdocs.constraints;
1818

19+
import static capital.scalable.restdocs.util.ObjectUtil.arrayToString;
1920
import static org.slf4j.LoggerFactory.getLogger;
20-
import static org.springframework.util.StringUtils.arrayToDelimitedString;
2121

2222
import java.util.ArrayList;
2323
import java.util.Collections;
@@ -70,7 +70,7 @@ private Map<String, Object> extendConfiguration(Map<String, Object> configuratio
7070

7171
private String humanReadableString(Object o) {
7272
if (o instanceof Object[]) {
73-
return "[" + arrayToDelimitedString((Object[]) o, ", ") + "]";
73+
return arrayToString((Object[]) o);
7474
} else if (o instanceof Class) {
7575
try {
7676
return ((Class) o).newInstance().toString();

0 commit comments

Comments
 (0)