Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2192dda

Browse files
committed
Added support for xml traits in properties
Modified the sample contract test and also handled the case where names and namespaces were not specified. (1907)
1 parent 90d8089 commit 2192dda

7 files changed

Lines changed: 269 additions & 14 deletions

File tree

springfox-schema/src/main/java/springfox/documentation/schema/XmlModelPlugin.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,16 @@ public void apply(ModelContext context) {
4747

4848
private Xml buildXml(XmlType annotation) {
4949
return new Xml()
50-
.name(annotation.name())
50+
.name(defaultToNull(annotation.name()))
5151
.attribute(false)
52-
.namespace(annotation.namespace())
52+
.namespace(defaultToNull(annotation.namespace()))
5353
.wrapped(false);
5454
}
5555

56+
private String defaultToNull(String value) {
57+
return "##default".equalsIgnoreCase(value) ? null : value;
58+
}
59+
5660
private Class<?> forClass(ModelContext context) {
5761
return typeResolver.resolve(context.getType()).getErasedType();
5862
}
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/*
2+
*
3+
* Copyright 2017-2018 the original author or authors.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*
17+
*
18+
*/
19+
package springfox.documentation.schema.property;
20+
21+
import com.google.common.base.Optional;
22+
import org.springframework.core.annotation.AnnotationUtils;
23+
import org.springframework.stereotype.Component;
24+
import springfox.documentation.schema.Xml;
25+
import springfox.documentation.spi.DocumentationType;
26+
import springfox.documentation.spi.schema.ModelPropertyBuilderPlugin;
27+
import springfox.documentation.spi.schema.contexts.ModelPropertyContext;
28+
29+
import javax.xml.bind.annotation.XmlAttribute;
30+
import javax.xml.bind.annotation.XmlElement;
31+
import javax.xml.bind.annotation.XmlElementWrapper;
32+
import java.lang.annotation.Annotation;
33+
import java.lang.reflect.AnnotatedElement;
34+
35+
import static com.google.common.base.Strings.*;
36+
import static springfox.documentation.schema.Annotations.*;
37+
38+
@Component
39+
public class XmlPropertyPlugin implements ModelPropertyBuilderPlugin {
40+
41+
@Override
42+
public void apply(ModelPropertyContext context) {
43+
Optional<XmlElement> elementAnnotation = Optional.absent();
44+
Optional<XmlAttribute> attributeAnnotation = Optional.absent();
45+
46+
if (context.getAnnotatedElement().isPresent()) {
47+
elementAnnotation = elementAnnotation.or(findAnnotation(
48+
context.getAnnotatedElement().get(),
49+
XmlElement.class));
50+
attributeAnnotation = attributeAnnotation.or(findAnnotation(
51+
context.getAnnotatedElement().get(),
52+
XmlAttribute.class));
53+
}
54+
55+
if (context.getBeanPropertyDefinition().isPresent()) {
56+
elementAnnotation = elementAnnotation.or(findPropertyAnnotation(
57+
context.getBeanPropertyDefinition().get(),
58+
XmlElement.class));
59+
attributeAnnotation = attributeAnnotation.or(findPropertyAnnotation(
60+
context.getBeanPropertyDefinition().get(),
61+
XmlAttribute.class));
62+
}
63+
64+
if (elementAnnotation.isPresent()) {
65+
Optional<XmlElementWrapper> wrapper = findPropertyAnnotation(
66+
context.getBeanPropertyDefinition().get(),
67+
XmlElementWrapper.class);
68+
69+
context.getBuilder()
70+
.xml(new Xml()
71+
.attribute(false)
72+
.namespace(defaultToNull(elementAnnotation.get().namespace()))
73+
.name(wrapperName(wrapper, elementAnnotation))
74+
.wrapped(wrapper.isPresent()));
75+
} else if (attributeAnnotation.isPresent()) {
76+
context.getBuilder()
77+
.xml(new Xml()
78+
.attribute(true)
79+
.namespace(defaultToNull(attributeAnnotation.get().namespace()))
80+
.name(attributeName(attributeAnnotation))
81+
.wrapped(false));
82+
}
83+
}
84+
85+
public static <T extends Annotation> Optional<T> findAnnotation(
86+
AnnotatedElement annotated,
87+
Class<T> annotation) {
88+
return Optional.fromNullable(AnnotationUtils.getAnnotation(annotated, annotation));
89+
}
90+
91+
private String wrapperName(Optional<XmlElementWrapper> wrapper, Optional<XmlElement> element) {
92+
if (wrapper.isPresent()) {
93+
return Optional.fromNullable(defaultToNull(emptyToNull(wrapper.get().name())))
94+
.or(Optional.fromNullable(elementName(element)))
95+
.orNull();
96+
}
97+
return elementName(element);
98+
}
99+
100+
private String elementName(Optional<XmlElement> element) {
101+
if (element.isPresent()) {
102+
return defaultToNull(emptyToNull(element.get().name()));
103+
}
104+
return null;
105+
}
106+
107+
private String attributeName(Optional<XmlAttribute> attribute) {
108+
if (attribute.isPresent()) {
109+
return defaultToNull(emptyToNull(attribute.get().name()));
110+
}
111+
return null;
112+
}
113+
114+
private String defaultToNull(String value) {
115+
return "##default".equalsIgnoreCase(value) ? null : value;
116+
}
117+
118+
@Override
119+
public boolean supports(DocumentationType delimiter) {
120+
return true;
121+
}
122+
}

springfox-spring-web/src/test/java/springfox/documentation/spring/web/dummy/controllers/BugsController.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545
import javax.servlet.http.HttpServletResponse;
4646
import javax.validation.Valid;
4747
import javax.validation.constraints.NotNull;
48+
import javax.xml.bind.annotation.XmlAttribute;
49+
import javax.xml.bind.annotation.XmlElement;
4850
import javax.xml.bind.annotation.XmlType;
4951
import java.net.MalformedURLException;
5052
import java.net.URL;
@@ -445,14 +447,27 @@ public Model1907() {
445447
}
446448

447449
@NotNull
450+
@XmlAttribute
448451
private String somename;
449452

453+
@NotNull
454+
@XmlElement
455+
private Example example;
456+
450457
public String getSomename() {
451458
return somename;
452459
}
453460

454461
public void setSomename(String somename) {
455462
this.somename = somename;
456463
}
464+
465+
public Example getExample() {
466+
return example;
467+
}
468+
469+
public void setExample(Example example) {
470+
this.example = example;
471+
}
457472
}
458473
}

swagger-contract-tests/src/test/resources/contract/swagger2/declaration-bugs-different-service.json

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1081,11 +1081,25 @@
10811081
"Model1907": {
10821082
"type": "object",
10831083
"required": [
1084+
"example",
10841085
"somename"
10851086
],
10861087
"properties": {
1088+
"example": {
1089+
"xml": {
1090+
"name": "example",
1091+
"attribute": false,
1092+
"wrapped": false
1093+
},
1094+
"$ref": "#/definitions/Example"
1095+
},
10871096
"somename": {
1088-
"type": "string"
1097+
"type": "string",
1098+
"xml": {
1099+
"name": "somename",
1100+
"attribute": true,
1101+
"wrapped": false
1102+
}
10891103
}
10901104
},
10911105
"xml": {
@@ -1108,6 +1122,12 @@
11081122
"properties": {
11091123
"links": {
11101124
"type": "object",
1125+
"xml": {
1126+
"name": "link",
1127+
"namespace": "http://www.w3.org/2005/Atom",
1128+
"attribute": false,
1129+
"wrapped": false
1130+
},
11111131
"additionalProperties": {
11121132
"$ref": "#/definitions/LinkAlternate"
11131133
}

swagger-contract-tests/src/test/resources/contract/swagger2/declaration-bugs-service.json

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1100,11 +1100,25 @@
11001100
"Model1907": {
11011101
"type": "object",
11021102
"required": [
1103+
"example",
11031104
"somename"
11041105
],
11051106
"properties": {
1107+
"example": {
1108+
"xml": {
1109+
"name": "example",
1110+
"attribute": false,
1111+
"wrapped": false
1112+
},
1113+
"$ref": "#/definitions/Example"
1114+
},
11061115
"somename": {
1107-
"type": "string"
1116+
"type": "string",
1117+
"xml": {
1118+
"name": "somename",
1119+
"attribute": true,
1120+
"wrapped": false
1121+
}
11081122
}
11091123
},
11101124
"xml": {
@@ -1127,6 +1141,12 @@
11271141
"properties": {
11281142
"links": {
11291143
"type": "object",
1144+
"xml": {
1145+
"name": "link",
1146+
"namespace": "http://www.w3.org/2005/Atom",
1147+
"attribute": false,
1148+
"wrapped": false
1149+
},
11301150
"additionalProperties": {
11311151
"$ref": "#/definitions/LinkAlternate"
11321152
}

swagger-contract-tests/src/test/resources/contract/swagger2/declaration-concrete-controller.json

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,20 @@
146146
"type": "object",
147147
"properties": {
148148
"href": {
149-
"type": "string"
149+
"type": "string",
150+
"xml": {
151+
"name": "href",
152+
"attribute": true,
153+
"wrapped": false
154+
}
150155
},
151156
"rel": {
152-
"type": "string"
157+
"type": "string",
158+
"xml": {
159+
"name": "rel",
160+
"attribute": true,
161+
"wrapped": false
162+
}
153163
},
154164
"templated": {
155165
"type": "boolean"
@@ -174,19 +184,19 @@
174184
"Resource«Pet»": {
175185
"type": "object",
176186
"properties": {
177-
"links": {
178-
"type": "array",
179-
"items": {
180-
"$ref": "#/definitions/Link"
181-
}
182-
},
183187
"age": {
184188
"type": "integer",
185189
"format": "int32"
186190
},
187191
"id": {
188192
"type": "string"
189193
},
194+
"links": {
195+
"type": "array",
196+
"items": {
197+
"$ref": "#/definitions/Link"
198+
}
199+
},
190200
"name": {
191201
"type": "string"
192202
}

0 commit comments

Comments
 (0)