Skip to content

Commit 5445716

Browse files
committed
added annotation reader support, tests for #695
1 parent 2274693 commit 5445716

File tree

7 files changed

+133
-97
lines changed

7 files changed

+133
-97
lines changed

modules/swagger-annotations/src/main/java/com/wordnik/swagger/annotations/ApiModelProperty.java

+5
Original file line numberDiff line numberDiff line change
@@ -78,4 +78,9 @@
7878
* A sample value for the property
7979
**/
8080
String example() default "";
81+
82+
/**
83+
* Allows a model property to be designated as read only
84+
**/
85+
boolean readOnly() default false;
8186
}

modules/swagger-core/src/main/java/com/wordnik/swagger/jackson/AbstractModelConverter.java

+103-95
Original file line numberDiff line numberDiff line change
@@ -41,126 +41,134 @@ public abstract class AbstractModelConverter implements ModelConverter {
4141

4242

4343
protected AbstractModelConverter(ObjectMapper mapper) {
44-
mapper.registerModule(
45-
new SimpleModule("swagger", Version.unknownVersion()) {
46-
@Override
47-
public void setupModule(SetupContext context) {
48-
context.insertAnnotationIntrospector(new SwaggerAnnotationIntrospector());
49-
}
50-
});
51-
_mapper = mapper;
52-
_intr = mapper.getSerializationConfig().getAnnotationIntrospector();
44+
mapper.registerModule(
45+
new SimpleModule("swagger", Version.unknownVersion()) {
46+
@Override
47+
public void setupModule(SetupContext context) {
48+
context.insertAnnotationIntrospector(new SwaggerAnnotationIntrospector());
49+
}
50+
});
51+
_mapper = mapper;
52+
_intr = mapper.getSerializationConfig().getAnnotationIntrospector();
5353

5454
}
5555

5656
protected static Comparator<Property> getPropertyComparator() {
57-
return new Comparator<Property>() {
58-
@Override
59-
public int compare(Property one, Property two) {
60-
if (one.getPosition() == null && two.getPosition() == null)
61-
return 0;
62-
if (one.getPosition() == null)
63-
return -1;
64-
if (two.getPosition() == null)
65-
return 1;
66-
return one.getPosition().compareTo(two.getPosition());
67-
}
68-
};
69-
}
57+
return new Comparator<Property>() {
58+
@Override
59+
public int compare(Property one, Property two) {
60+
if (one.getPosition() == null && two.getPosition() == null)
61+
return 0;
62+
if (one.getPosition() == null)
63+
return -1;
64+
if (two.getPosition() == null)
65+
return 1;
66+
return one.getPosition().compareTo(two.getPosition());
67+
}
68+
};
69+
}
7070

7171
@Override
7272
public Property resolveProperty(Type type, ModelConverterContext context) {
7373
return null;
7474
}
7575

7676
protected Property getPrimitiveProperty(String typeName) {
77-
Property property = null;
78-
if("boolean".equals(typeName)) {
79-
property = new BooleanProperty();
80-
}
81-
if("string".equals(typeName)) {
82-
property = new StringProperty();
83-
}
84-
else if("integer".equals(typeName)) {
85-
property = new IntegerProperty();
86-
}
87-
else if("long".equals(typeName)) {
88-
property = new LongProperty();
89-
}
90-
else if("float".equals(typeName)) {
91-
property = new FloatProperty();
92-
}
93-
else if("double".equals(typeName)) {
94-
property = new DoubleProperty();
95-
}
96-
else if("dateTime".equals(typeName)) {
97-
property = new DateTimeProperty();
98-
}
99-
return property;
100-
}
77+
Property property = null;
78+
if("boolean".equals(typeName)) {
79+
property = new BooleanProperty();
80+
}
81+
if("string".equals(typeName)) {
82+
property = new StringProperty();
83+
}
84+
else if("integer".equals(typeName)) {
85+
property = new IntegerProperty();
86+
}
87+
else if("long".equals(typeName)) {
88+
property = new LongProperty();
89+
}
90+
else if("float".equals(typeName)) {
91+
property = new FloatProperty();
92+
}
93+
else if("double".equals(typeName)) {
94+
property = new DoubleProperty();
95+
}
96+
else if("dateTime".equals(typeName)) {
97+
property = new DateTimeProperty();
98+
}
99+
return property;
100+
}
101101

102102
protected String _description(Annotated ann) {
103-
// while name suggests it's only for properties, should work for any Annotated thing.
104-
// also; with Swagger introspector's help, should get it from ApiModel/ApiModelProperty
105-
return _intr.findPropertyDescription(ann);
106-
}
103+
// while name suggests it's only for properties, should work for any Annotated thing.
104+
// also; with Swagger introspector's help, should get it from ApiModel/ApiModelProperty
105+
return _intr.findPropertyDescription(ann);
106+
}
107107

108108
protected String _typeName(JavaType type) {
109-
return _typeName(type, null);
110-
}
109+
return _typeName(type, null);
110+
}
111111

112112
protected String _typeName(JavaType type, BeanDescription beanDesc) {
113-
String name = _resolvedTypeNames.get(type);
114-
if (name != null) {
115-
return name;
116-
}
117-
name = _findTypeName(type, beanDesc);
118-
_resolvedTypeNames.put(type, name);
119-
return name;
120-
}
113+
String name = _resolvedTypeNames.get(type);
114+
if (name != null) {
115+
return name;
116+
}
117+
name = _findTypeName(type, beanDesc);
118+
_resolvedTypeNames.put(type, name);
119+
return name;
120+
}
121121

122122
protected String _findTypeName(JavaType type, BeanDescription beanDesc) {
123-
// First, handle container types; they require recursion
124-
if (type.isArrayType())
125-
return "Array";
126-
127-
if (type.isMapLikeType())
128-
return "Map";
129-
130-
if (type.isContainerType()) {
131-
if (Set.class.isAssignableFrom(type.getRawClass()))
132-
return "Set";
133-
return "List";
134-
}
135-
if (beanDesc == null) {
136-
beanDesc = _mapper.getSerializationConfig().introspectClassAnnotations(type);
137-
}
138-
139-
PropertyName rootName = _intr.findRootName(beanDesc.getClassInfo());
140-
if (rootName != null && rootName.hasSimpleName()) {
141-
return rootName.getSimpleName();
142-
}
143-
return _typeNameResolver.nameForType(type);
144-
}
123+
// First, handle container types; they require recursion
124+
if (type.isArrayType())
125+
return "Array";
126+
127+
if (type.isMapLikeType())
128+
return "Map";
129+
130+
if (type.isContainerType()) {
131+
if (Set.class.isAssignableFrom(type.getRawClass()))
132+
return "Set";
133+
return "List";
134+
}
135+
if (beanDesc == null) {
136+
beanDesc = _mapper.getSerializationConfig().introspectClassAnnotations(type);
137+
}
138+
139+
PropertyName rootName = _intr.findRootName(beanDesc.getClassInfo());
140+
if (rootName != null && rootName.hasSimpleName()) {
141+
return rootName.getSimpleName();
142+
}
143+
return _typeNameResolver.nameForType(type);
144+
}
145145

146146
protected String _typeQName(JavaType type) {
147-
return type.getRawClass().getName();
148-
}
147+
return type.getRawClass().getName();
148+
}
149149

150150
protected String _subTypeName(NamedType type) {
151-
// !!! TODO: should this use 'name' instead?
152-
return type.getType().getName();
153-
}
151+
// !!! TODO: should this use 'name' instead?
152+
return type.getType().getName();
153+
}
154154

155155
protected String _findExampleValue(Annotated a) {
156-
ApiModelProperty prop = a.getAnnotation(ApiModelProperty.class);
157-
if (prop != null) {
158-
if (!prop.example().isEmpty()) {
159-
return prop.example();
160-
}
161-
}
162-
return null;
163-
}
156+
ApiModelProperty prop = a.getAnnotation(ApiModelProperty.class);
157+
if (prop != null) {
158+
if (!prop.example().isEmpty()) {
159+
return prop.example();
160+
}
161+
}
162+
return null;
163+
}
164+
165+
protected Boolean _findReadOnly(Annotated a) {
166+
ApiModelProperty prop = a.getAnnotation(ApiModelProperty.class);
167+
if (prop != null) {
168+
return prop.readOnly();
169+
}
170+
return null;
171+
}
164172

165173
@Override
166174
public Model resolve(Type type, ModelConverterContext context) {

modules/swagger-core/src/main/java/com/wordnik/swagger/jackson/ModelResolver.java

+1
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ else if (altName.startsWith("is")) {
217217
property.setPosition(index);
218218
}
219219
property.setExample(_findExampleValue(member));
220+
property.setReadOnly(_findReadOnly(member));
220221

221222
if(property != null) {
222223
// check for XML annotations

modules/swagger-core/src/test/scala/ModelConverterTest.scala

-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,6 @@ class ModelConverterTest extends FlatSpec with Matchers {
113113
}
114114
}
115115
}""")
116-
117116
}
118117

119118
it should "honor the ApiModel name" in {

modules/swagger-core/src/test/scala/ModelSerializerTest.scala

+6
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import com.wordnik.swagger.models._
22
import com.wordnik.swagger.models.properties._
33
import com.wordnik.swagger.converter._
44

5+
import models._
56
import com.wordnik.swagger.util.Json
67

78
import scala.collection.mutable.HashMap
@@ -57,4 +58,9 @@ class ModelSerializerTest extends FlatSpec with Matchers {
5758

5859
Json.mapper().writeValueAsString(model) should be ("""{"$ref":"#/definitions/Monster"}""")
5960
}
61+
62+
it should "make a field readOnly by annotation" in {
63+
val schemas = ModelConverters.getInstance().read(classOf[Car])
64+
Json.mapper().writeValueAsString(schemas) should be ("""{"Car":{"properties":{"wheelCount":{"type":"integer","format":"int32","readOnly":true}}}}""")
65+
}
6066
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package models;
2+
3+
import models.composition.Pet;
4+
5+
import com.wordnik.swagger.annotations.*;
6+
7+
public class Car {
8+
@ApiModelProperty(readOnly = true)
9+
public Integer getWheelCount() {
10+
return new Integer(4);
11+
}
12+
public void setWheelCount(Integer wheelCount) {
13+
// does nothing
14+
}
15+
}

modules/swagger-models/src/main/java/com/wordnik/swagger/models/properties/Property.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ public interface Property {
2828
String getExample();
2929
void setExample(String example);
3030

31-
// @JsonIgnore
31+
Boolean getReadOnly();
32+
void setReadOnly(Boolean example);
33+
3234
void setPosition(Integer position);
3335
Integer getPosition();
3436

0 commit comments

Comments
 (0)