Skip to content

Commit

Permalink
added annotation reader support, tests for #695
Browse files Browse the repository at this point in the history
  • Loading branch information
fehguy committed Jan 20, 2015
1 parent 2274693 commit 5445716
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 97 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,9 @@
* A sample value for the property
**/
String example() default "";

/**
* Allows a model property to be designated as read only
**/
boolean readOnly() default false;
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,126 +41,134 @@ public abstract class AbstractModelConverter implements ModelConverter {


protected AbstractModelConverter(ObjectMapper mapper) {
mapper.registerModule(
new SimpleModule("swagger", Version.unknownVersion()) {
@Override
public void setupModule(SetupContext context) {
context.insertAnnotationIntrospector(new SwaggerAnnotationIntrospector());
}
});
_mapper = mapper;
_intr = mapper.getSerializationConfig().getAnnotationIntrospector();
mapper.registerModule(
new SimpleModule("swagger", Version.unknownVersion()) {
@Override
public void setupModule(SetupContext context) {
context.insertAnnotationIntrospector(new SwaggerAnnotationIntrospector());
}
});
_mapper = mapper;
_intr = mapper.getSerializationConfig().getAnnotationIntrospector();

}

protected static Comparator<Property> getPropertyComparator() {
return new Comparator<Property>() {
@Override
public int compare(Property one, Property two) {
if (one.getPosition() == null && two.getPosition() == null)
return 0;
if (one.getPosition() == null)
return -1;
if (two.getPosition() == null)
return 1;
return one.getPosition().compareTo(two.getPosition());
}
};
}
return new Comparator<Property>() {
@Override
public int compare(Property one, Property two) {
if (one.getPosition() == null && two.getPosition() == null)
return 0;
if (one.getPosition() == null)
return -1;
if (two.getPosition() == null)
return 1;
return one.getPosition().compareTo(two.getPosition());
}
};
}

@Override
public Property resolveProperty(Type type, ModelConverterContext context) {
return null;
}

protected Property getPrimitiveProperty(String typeName) {
Property property = null;
if("boolean".equals(typeName)) {
property = new BooleanProperty();
}
if("string".equals(typeName)) {
property = new StringProperty();
}
else if("integer".equals(typeName)) {
property = new IntegerProperty();
}
else if("long".equals(typeName)) {
property = new LongProperty();
}
else if("float".equals(typeName)) {
property = new FloatProperty();
}
else if("double".equals(typeName)) {
property = new DoubleProperty();
}
else if("dateTime".equals(typeName)) {
property = new DateTimeProperty();
}
return property;
}
Property property = null;
if("boolean".equals(typeName)) {
property = new BooleanProperty();
}
if("string".equals(typeName)) {
property = new StringProperty();
}
else if("integer".equals(typeName)) {
property = new IntegerProperty();
}
else if("long".equals(typeName)) {
property = new LongProperty();
}
else if("float".equals(typeName)) {
property = new FloatProperty();
}
else if("double".equals(typeName)) {
property = new DoubleProperty();
}
else if("dateTime".equals(typeName)) {
property = new DateTimeProperty();
}
return property;
}

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

protected String _typeName(JavaType type) {
return _typeName(type, null);
}
return _typeName(type, null);
}

protected String _typeName(JavaType type, BeanDescription beanDesc) {
String name = _resolvedTypeNames.get(type);
if (name != null) {
return name;
}
name = _findTypeName(type, beanDesc);
_resolvedTypeNames.put(type, name);
return name;
}
String name = _resolvedTypeNames.get(type);
if (name != null) {
return name;
}
name = _findTypeName(type, beanDesc);
_resolvedTypeNames.put(type, name);
return name;
}

protected String _findTypeName(JavaType type, BeanDescription beanDesc) {
// First, handle container types; they require recursion
if (type.isArrayType())
return "Array";
if (type.isMapLikeType())
return "Map";
if (type.isContainerType()) {
if (Set.class.isAssignableFrom(type.getRawClass()))
return "Set";
return "List";
}
if (beanDesc == null) {
beanDesc = _mapper.getSerializationConfig().introspectClassAnnotations(type);
}
PropertyName rootName = _intr.findRootName(beanDesc.getClassInfo());
if (rootName != null && rootName.hasSimpleName()) {
return rootName.getSimpleName();
}
return _typeNameResolver.nameForType(type);
}
// First, handle container types; they require recursion
if (type.isArrayType())
return "Array";

if (type.isMapLikeType())
return "Map";

if (type.isContainerType()) {
if (Set.class.isAssignableFrom(type.getRawClass()))
return "Set";
return "List";
}
if (beanDesc == null) {
beanDesc = _mapper.getSerializationConfig().introspectClassAnnotations(type);
}

PropertyName rootName = _intr.findRootName(beanDesc.getClassInfo());
if (rootName != null && rootName.hasSimpleName()) {
return rootName.getSimpleName();
}
return _typeNameResolver.nameForType(type);
}

protected String _typeQName(JavaType type) {
return type.getRawClass().getName();
}
return type.getRawClass().getName();
}

protected String _subTypeName(NamedType type) {
// !!! TODO: should this use 'name' instead?
return type.getType().getName();
}
// !!! TODO: should this use 'name' instead?
return type.getType().getName();
}

protected String _findExampleValue(Annotated a) {
ApiModelProperty prop = a.getAnnotation(ApiModelProperty.class);
if (prop != null) {
if (!prop.example().isEmpty()) {
return prop.example();
}
}
return null;
}
ApiModelProperty prop = a.getAnnotation(ApiModelProperty.class);
if (prop != null) {
if (!prop.example().isEmpty()) {
return prop.example();
}
}
return null;
}

protected Boolean _findReadOnly(Annotated a) {
ApiModelProperty prop = a.getAnnotation(ApiModelProperty.class);
if (prop != null) {
return prop.readOnly();
}
return null;
}

@Override
public Model resolve(Type type, ModelConverterContext context) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ else if (altName.startsWith("is")) {
property.setPosition(index);
}
property.setExample(_findExampleValue(member));
property.setReadOnly(_findReadOnly(member));

if(property != null) {
// check for XML annotations
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,6 @@ class ModelConverterTest extends FlatSpec with Matchers {
}
}
}""")

}

it should "honor the ApiModel name" in {
Expand Down
6 changes: 6 additions & 0 deletions modules/swagger-core/src/test/scala/ModelSerializerTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import com.wordnik.swagger.models._
import com.wordnik.swagger.models.properties._
import com.wordnik.swagger.converter._

import models._
import com.wordnik.swagger.util.Json

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

Json.mapper().writeValueAsString(model) should be ("""{"$ref":"#/definitions/Monster"}""")
}

it should "make a field readOnly by annotation" in {
val schemas = ModelConverters.getInstance().read(classOf[Car])
Json.mapper().writeValueAsString(schemas) should be ("""{"Car":{"properties":{"wheelCount":{"type":"integer","format":"int32","readOnly":true}}}}""")
}
}
15 changes: 15 additions & 0 deletions modules/swagger-core/src/test/scala/models/Car.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package models;

import models.composition.Pet;

import com.wordnik.swagger.annotations.*;

public class Car {
@ApiModelProperty(readOnly = true)
public Integer getWheelCount() {
return new Integer(4);
}
public void setWheelCount(Integer wheelCount) {
// does nothing
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ public interface Property {
String getExample();
void setExample(String example);

// @JsonIgnore
Boolean getReadOnly();
void setReadOnly(Boolean example);

void setPosition(Integer position);
Integer getPosition();

Expand Down

0 comments on commit 5445716

Please sign in to comment.