Skip to content

Commit 5576aba

Browse files
committed
Merge pull request #1498 from iushankin/issue-1372
Fixed #1372: Derived classes without @apimodel annotation are not added to Swagger definition
2 parents 81ed7a0 + 48375f8 commit 5576aba

File tree

6 files changed

+111
-13
lines changed

6 files changed

+111
-13
lines changed

modules/swagger-core/src/main/java/io/swagger/jackson/ModelResolver.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ public Model resolve(JavaType type, ModelConverterContext context, Iterator<Mode
303303
annotations = annotationList.toArray(new Annotation[annotationList.size()]);
304304

305305
ApiModelProperty mp = member.getAnnotation(ApiModelProperty.class);
306-
306+
307307
if(mp != null && mp.readOnly()) {
308308
isReadOnly = mp.readOnly();
309309
}
@@ -650,15 +650,22 @@ private boolean resolveSubtypes(ModelImpl model, BeanDescription bean, ModelConv
650650
int count = 0;
651651
final Class<?> beanClass = bean.getClassInfo().getAnnotated();
652652
for (NamedType subtype : types) {
653-
if (!beanClass.isAssignableFrom(subtype.getType())) {
653+
final Class<?> subtypeType = subtype.getType();
654+
if (!beanClass.isAssignableFrom(subtypeType)) {
654655
continue;
655656
}
656657

657-
final Model subtypeModel = context.resolve(subtype.getType());
658+
final Model subtypeModel = context.resolve(subtypeType);
658659

659660
if (subtypeModel instanceof ModelImpl) {
660661
final ModelImpl impl = (ModelImpl) subtypeModel;
661662

663+
// check if model name was inherited
664+
if (impl.getName().equals(model.getName())) {
665+
impl.setName(_typeNameResolver.nameForType(_mapper.constructType(subtypeType),
666+
TypeNameResolver.Options.SKIP_API_MODEL));
667+
}
668+
662669
// remove shared properties defined in the parent
663670
final Map<String, Property> baseProps = model.getProperties();
664671
final Map<String, Property> subtypeProps = impl.getProperties();
Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
package io.swagger.jackson;
22

3-
import com.fasterxml.jackson.databind.JavaType;
43
import io.swagger.annotations.ApiModel;
54
import io.swagger.util.PrimitiveType;
5+
6+
import com.fasterxml.jackson.databind.JavaType;
67
import org.apache.commons.lang3.StringUtils;
78
import org.apache.commons.lang3.text.WordUtils;
89

10+
import java.util.Arrays;
11+
import java.util.Collections;
12+
import java.util.EnumSet;
13+
import java.util.Set;
14+
915
/**
1016
* Helper class used for converting well-known (property) types into
1117
* Swagger type names.
@@ -16,30 +22,39 @@ public class TypeNameResolver {
1622
protected TypeNameResolver() {
1723
}
1824

19-
public String nameForType(JavaType type) {
25+
public String nameForType(JavaType type, Options... options) {
26+
return nameForType(type, options.length == 0 ? Collections.<Options>emptySet() :
27+
EnumSet.copyOf(Arrays.asList(options)));
28+
}
29+
30+
public String nameForType(JavaType type, Set<Options> options) {
2031
if (type.hasGenericTypes()) {
21-
return nameForGenericType(type);
32+
return nameForGenericType(type, options);
2233
}
2334
final String name = findStdName(type);
24-
return (name == null) ? nameForClass(type) : name;
35+
return (name == null) ? nameForClass(type, options) : name;
2536
}
2637

27-
protected String nameForClass(JavaType type) {
28-
return nameForClass(type.getRawClass());
38+
protected String nameForClass(JavaType type, Set<Options> options) {
39+
return nameForClass(type.getRawClass(), options);
2940
}
3041

31-
protected String nameForClass(Class<?> cls) {
42+
protected String nameForClass(Class<?> cls, Set<Options> options) {
43+
if (options.contains(Options.SKIP_API_MODEL)) {
44+
return cls.getSimpleName();
45+
}
3246
final ApiModel model = cls.getAnnotation(ApiModel.class);
3347
final String modelName = model == null ? null : StringUtils.trimToNull(model.value());
3448
return modelName == null ? cls.getSimpleName() : modelName;
3549
}
3650

37-
protected String nameForGenericType(JavaType type) {
38-
final StringBuilder generic = new StringBuilder(nameForClass(type));
51+
protected String nameForGenericType(JavaType type, Set<Options> options) {
52+
final StringBuilder generic = new StringBuilder(nameForClass(type, options));
3953
final int count = type.containedTypeCount();
4054
for (int i = 0; i < count; ++i) {
4155
final JavaType arg = type.containedType(i);
42-
final String argName = PrimitiveType.fromType(arg) != null ? nameForClass(arg) : nameForType(arg);
56+
final String argName = PrimitiveType.fromType(arg) != null ? nameForClass(arg, options) :
57+
nameForType(arg, options);
4358
generic.append(WordUtils.capitalize(argName));
4459
}
4560
return generic.toString();
@@ -48,4 +63,8 @@ protected String nameForGenericType(JavaType type) {
4863
protected String findStdName(JavaType type) {
4964
return PrimitiveType.getCommonName(type);
5065
}
66+
67+
public enum Options {
68+
SKIP_API_MODEL;
69+
}
5170
}

modules/swagger-core/src/test/java/io/swagger/ModelConverterTest.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
import io.swagger.models.ModelWithNumbers;
2828
import io.swagger.models.ModelWithTuple2;
2929
import io.swagger.models.Person;
30+
import io.swagger.models.composition.AbstractModelWithApiModel;
31+
import io.swagger.models.composition.ModelWithUrlProperty;
3032
import io.swagger.models.composition.Pet;
3133
import io.swagger.models.properties.ArrayProperty;
3234
import io.swagger.models.properties.BaseIntegerProperty;
@@ -100,6 +102,19 @@ public void honorApiModelName() {
100102
assertEquals(model, "MyModel");
101103
}
102104

105+
@Test(description = "it should override an inherited model's name")
106+
public void overrideInheritedModelName() {
107+
final Map<String, Model> rootSchemas = readAll(AbstractModelWithApiModel.class);
108+
assertEquals(rootSchemas.size(), 3);
109+
assertTrue(rootSchemas.containsKey("MyProperty"));
110+
assertTrue(rootSchemas.containsKey("ModelWithUrlProperty"));
111+
assertTrue(rootSchemas.containsKey("ModelWithValueProperty"));
112+
113+
final Map<String, Model> nestedSchemas = readAll(ModelWithUrlProperty.class);
114+
assertEquals(nestedSchemas.size(), 1);
115+
assertTrue(nestedSchemas.containsKey("MyProperty"));
116+
}
117+
103118
@Test(description = "it should maintain property names")
104119
public void maintainPropertyNames() {
105120
final Map<String, Model> schemas = readAll(ModelPropertyName.class);
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package io.swagger.models.composition;
2+
3+
import io.swagger.annotations.ApiModel;
4+
5+
import com.fasterxml.jackson.annotation.JsonSubTypes;
6+
7+
@ApiModel("MyProperty")
8+
@JsonSubTypes({@JsonSubTypes.Type(value = ModelWithUrlProperty.class), @JsonSubTypes.Type(value = ModelWithValueProperty.class)})
9+
public abstract class AbstractModelWithApiModel {
10+
11+
private final String type;
12+
13+
protected AbstractModelWithApiModel(String type) {
14+
this.type = type;
15+
}
16+
17+
public String getType() {
18+
return type;
19+
}
20+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package io.swagger.models.composition;
2+
3+
import java.net.MalformedURLException;
4+
import java.net.URL;
5+
6+
public class ModelWithUrlProperty extends AbstractModelWithApiModel {
7+
8+
private final URL url;
9+
10+
public ModelWithUrlProperty(String type, String url) {
11+
super(type);
12+
try {
13+
this.url = new URL(url);
14+
} catch (MalformedURLException e) {
15+
throw new IllegalArgumentException(e);
16+
}
17+
}
18+
19+
public URL getUrl() {
20+
return url;
21+
}
22+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package io.swagger.models.composition;
2+
3+
public class ModelWithValueProperty extends AbstractModelWithApiModel {
4+
5+
private final String value;
6+
7+
public ModelWithValueProperty(String type, String value) {
8+
super(type);
9+
this.value = value;
10+
}
11+
12+
public String getValue() {
13+
return value;
14+
}
15+
}

0 commit comments

Comments
 (0)