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

Commit 308f04c

Browse files
authored
Custom subtypes (#317)
Ability to set specifier for fields in subtypes. It's then shown after optional, description or constraints message. Works for Jackson mapped subtypes or manually mapped.
1 parent 9112c82 commit 308f04c

File tree

26 files changed

+453
-87
lines changed

26 files changed

+453
-87
lines changed

samples/java-webmvc/src/test/java/capital/scalable/restdocs/example/testsupport/MockMvcBase.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
* Licensed under the Apache License, Version 2.0 (the "License");
88
* you may not use this file except in compliance with the License.
99
* You may obtain a copy of the License at
10-
*
10+
*
1111
* http://www.apache.org/licenses/LICENSE-2.0
12-
*
12+
*
1313
* Unless required by applicable law or agreed to in writing, software
1414
* distributed under the License is distributed on an "AS IS" BASIS,
1515
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -51,6 +51,9 @@
5151

5252
import javax.servlet.Filter;
5353

54+
import capital.scalable.restdocs.example.items.Metadata;
55+
import capital.scalable.restdocs.example.items.Metadata3;
56+
import capital.scalable.restdocs.jackson.TypeMapping;
5457
import com.fasterxml.jackson.databind.ObjectMapper;
5558
import org.junit.Before;
5659
import org.junit.Rule;
@@ -97,7 +100,8 @@ public void setUp() throws Exception {
97100
this.mockMvc = MockMvcBuilders
98101
.webAppContextSetup(context)
99102
.addFilters(springSecurityFilterChain)
100-
.alwaysDo(prepareJackson(objectMapper))
103+
.alwaysDo(prepareJackson(objectMapper, new TypeMapping()
104+
.mapSubtypes(Metadata.class, Metadata3.class))) // custom
101105
.alwaysDo(commonDocumentation())
102106
.apply(documentationConfiguration(restDocumentation)
103107
.uris()

samples/shared/src/main/java/capital/scalable/restdocs/example/items/Metadata1.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
public class Metadata1 extends Metadata {
2424
/**
25-
* Tag attribute. Available only if metadata type=1
25+
* Tag attribute.
2626
*/
2727
private String tag;
2828

samples/shared/src/main/java/capital/scalable/restdocs/example/items/Metadata2.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
public class Metadata2 extends Metadata {
2626
/**
27-
* Order attribute. Available only if metadata type=2
27+
* Order attribute.
2828
*/
2929
private Integer order;
3030

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*-
2+
* #%L
3+
* Spring Auto REST Docs Shared POJOs Example Project
4+
* %%
5+
* Copyright (C) 2015 - 2019 Scalable Capital GmbH
6+
* %%
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
* #L%
19+
*/
20+
21+
package capital.scalable.restdocs.example.items;
22+
23+
public class Metadata3 extends Metadata {
24+
/**
25+
* Tag attribute.
26+
*/
27+
private String tag;
28+
29+
/**
30+
* Info attribute.
31+
*/
32+
private String info;
33+
}
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
capital.scalable.restdocs.example.constraints.OneOf.description=Must be one of ${value}
22
capital.scalable.restdocs.example.constraints.English.description=EN: ${value}
33
capital.scalable.restdocs.example.constraints.German.description=DE: ${value}
4-
capital.scalable.restdocs.example.constraints.Id.description=Must be a valid ID
4+
capital.scalable.restdocs.example.constraints.Id.description=Must be a valid ID
5+
capital.scalable.restdocs.example.items.Metadata1.description=Available if metadata type=1
6+
capital.scalable.restdocs.example.items.Metadata2.description=Available if metadata type=2
7+
capital.scalable.restdocs.example.items.Metadata3.description=Available in specific conditions

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import java.util.Map;
3131

3232
import capital.scalable.restdocs.constraints.ConstraintReader;
33+
import capital.scalable.restdocs.jackson.TypeMapping;
3334
import capital.scalable.restdocs.javadoc.JavadocReader;
3435
import capital.scalable.restdocs.misc.AuthorizationSnippet;
3536
import capital.scalable.restdocs.util.TemplateFormatting;
@@ -119,6 +120,16 @@ public static void setConstraintReader(MockHttpServletRequest request,
119120
.put(ConstraintReader.class.getName(), constraintReader);
120121
}
121122

123+
public static TypeMapping getTypeMapping(Operation operation) {
124+
TypeMapping typeMapping = (TypeMapping) operation.getAttributes().get(TypeMapping.class.getName());
125+
return typeMapping != null ? typeMapping : new TypeMapping();
126+
}
127+
128+
public static void setTypeMapping(MockHttpServletRequest request, TypeMapping typeMapping) {
129+
((Map) request.getAttribute(ATTRIBUTE_NAME_CONFIGURATION))
130+
.put(TypeMapping.class.getName(), typeMapping);
131+
}
132+
122133
public static TemplateFormat getTemplateFormat(Operation operation) {
123134
StandardWriterResolver writerResolver = (StandardWriterResolver) operation.getAttributes()
124135
.get(WriterResolver.class.getName());

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,13 @@
2525

2626
public interface ConstraintReader {
2727
String CONSTRAINTS_ATTRIBUTE = "constraints";
28+
String TYPE_ATTRIBUTE = "type";
2829
String OPTIONAL_ATTRIBUTE = "optionals";
2930
String DEPRECATED_ATTRIBUTE = "deprecated";
3031
String DEFAULT_VALUE_ATTRIBUTE = "default-value";
3132

33+
String getTypeSpecifier(Class<?> javaBaseClass);
34+
3235
List<String> getConstraintMessages(Class<?> javaBaseClass, String javaFieldName);
3336

3437
List<String> getConstraintMessages(MethodParameter param);

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import static capital.scalable.restdocs.i18n.SnippetTranslationResolver.translate;
2525
import static capital.scalable.restdocs.util.FormatUtil.collectionToString;
2626
import static java.util.Collections.emptyList;
27+
import static java.util.Collections.emptyMap;
2728
import static java.util.Collections.singletonList;
2829
import static java.util.Collections.singletonMap;
2930
import static org.apache.commons.lang3.StringUtils.isBlank;
@@ -82,6 +83,19 @@ public List<String> getOptionalMessages(Class<?> javaBaseClass, String javaField
8283
return skippableConstraintResolver.getOptionalMessages(javaFieldName, javaBaseClass);
8384
}
8485

86+
@Override
87+
public String getTypeSpecifier(Class<?> javaBaseClass) {
88+
String message = constraintDescriptionResolver.resolveDescription(
89+
new Constraint(javaBaseClass.getCanonicalName(), emptyMap()));
90+
91+
// fallback
92+
if (message.equals(javaBaseClass.getCanonicalName())) {
93+
return "";
94+
}
95+
96+
return message;
97+
}
98+
8599
@Override
86100
public List<String> getConstraintMessages(Class<?> javaBaseClass, String javaFieldName) {
87101
ConstraintDescriptions constraints = new ConstraintDescriptions(javaBaseClass,
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*-
2+
* #%L
3+
* Spring Auto REST Docs Core
4+
* %%
5+
* Copyright (C) 2015 - 2019 Scalable Capital GmbH
6+
* %%
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
* #L%
19+
*/
20+
package capital.scalable.restdocs.jackson;
21+
22+
import java.util.List;
23+
24+
public class DeprecatedAttribute {
25+
private boolean isDeprecated;
26+
private List<String> values;
27+
28+
public DeprecatedAttribute(boolean isDeprecated, List<String> values) {
29+
this.isDeprecated = isDeprecated;
30+
this.values = values;
31+
}
32+
33+
public boolean isDeprecated() {
34+
return isDeprecated;
35+
}
36+
37+
public List<String> getValues() {
38+
return values;
39+
}
40+
}

spring-auto-restdocs-core/src/main/java/capital/scalable/restdocs/jackson/FieldDocumentationGenerator.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,26 +43,29 @@ public class FieldDocumentationGenerator {
4343
private final DeserializationConfig deserializationConfig;
4444
private final JavadocReader javadocReader;
4545
private final ConstraintReader constraintReader;
46+
private final TypeMapping typeMapping;
4647

4748
public FieldDocumentationGenerator(ObjectWriter writer,
4849
DeserializationConfig deserializationConfig,
4950
JavadocReader javadocReader,
50-
ConstraintReader constraintReader) {
51+
ConstraintReader constraintReader,
52+
TypeMapping typeMapping) {
5153
this.writer = writer;
5254
this.deserializationConfig = deserializationConfig;
5355
this.javadocReader = javadocReader;
5456
this.constraintReader = constraintReader;
57+
this.typeMapping = typeMapping;
5558
}
5659

5760
public FieldDescriptors generateDocumentation(Type baseType, TypeFactory typeFactory)
5861
throws JsonMappingException {
5962
JavaType javaBaseType = typeFactory.constructType(baseType);
60-
List<JavaType> types = resolveAllTypes(javaBaseType, typeFactory);
63+
List<JavaType> types = resolveAllTypes(javaBaseType, typeFactory, typeMapping);
6164
FieldDescriptors result = new FieldDescriptors();
6265

6366
FieldDocumentationVisitorWrapper visitorWrapper = FieldDocumentationVisitorWrapper.create(
6467
javadocReader, constraintReader, deserializationConfig,
65-
new TypeRegistry(types), typeFactory);
68+
new TypeRegistry(typeMapping, types), typeFactory);
6669

6770
for (JavaType type : types) {
6871
log.debug("(TOP) {}", type.getRawClass().getSimpleName());

0 commit comments

Comments
 (0)