2727import java .lang .reflect .Type ;
2828import java .lang .reflect .WildcardType ;
2929import java .util .Arrays ;
30+ import java .util .Map ;
3031import java .util .Objects ;
3132import java .util .Set ;
3233
34+ import com .fasterxml .jackson .annotation .JsonAnyGetter ;
3335import io .swagger .v3 .oas .models .OpenAPI ;
3436import io .swagger .v3 .oas .models .Operation ;
3537import io .swagger .v3 .oas .models .media .Content ;
3840import org .springdoc .core .GenericResponseService ;
3941import org .springdoc .core .MethodAttributes ;
4042import org .springdoc .core .ReturnTypeParser ;
41- import org .springdoc .data .rest .SpringRepositoryRestResourceProvider ;
4243
4344import org .springframework .core .MethodParameter ;
4445import org .springframework .core .ResolvableType ;
4546import org .springframework .data .rest .core .mapping .MethodResourceMapping ;
4647import org .springframework .hateoas .CollectionModel ;
4748import org .springframework .hateoas .EntityModel ;
49+ import org .springframework .hateoas .Link ;
4850import org .springframework .hateoas .PagedModel ;
4951import org .springframework .hateoas .RepresentationModel ;
5052import org .springframework .http .HttpEntity ;
@@ -123,11 +125,12 @@ public void buildSearchResponse(Operation operation, HandlerMethod handlerMethod
123125 * @param operationPath the operation path
124126 * @param domainType the domain type
125127 * @param methodAttributes the method attributes
128+ * @param dataRestRepository the data rest repository
126129 */
127130 public void buildEntityResponse (Operation operation , HandlerMethod handlerMethod , OpenAPI openAPI , RequestMethod requestMethod ,
128- String operationPath , Class <?> domainType , MethodAttributes methodAttributes ) {
131+ String operationPath , Class <?> domainType , MethodAttributes methodAttributes , DataRestRepository dataRestRepository ) {
129132 MethodParameter methodParameterReturn = handlerMethod .getReturnType ();
130- Type returnType = getType (methodParameterReturn , domainType , requestMethod );
133+ Type returnType = getType (methodParameterReturn , domainType , requestMethod , dataRestRepository );
131134 ApiResponses apiResponses = new ApiResponses ();
132135 ApiResponse apiResponse = new ApiResponse ();
133136 Content content = genericResponseService .buildContent (openAPI .getComponents (), methodParameterReturn .getParameterAnnotations (), methodAttributes .getMethodProduces (), null , returnType );
@@ -204,34 +207,40 @@ else if (ClassUtils.isPrimitiveOrWrapper(methodResourceMapping.getReturnedDomain
204207 * @param methodParameterReturn the method parameter return
205208 * @param domainType the domain type
206209 * @param requestMethod the request method
210+ * @param dataRestRepository the data rest repository
207211 * @return the type
208212 */
209- private Type getType (MethodParameter methodParameterReturn , Class <?> domainType , RequestMethod requestMethod ) {
213+ private Type getType (MethodParameter methodParameterReturn , Class <?> domainType , RequestMethod requestMethod , DataRestRepository dataRestRepository ) {
210214 Type returnType = ReturnTypeParser .resolveType (methodParameterReturn .getGenericParameterType (), methodParameterReturn .getContainingClass ());
215+ Class returnedEntityType = domainType ;
216+
217+ if (dataRestRepository !=null && ControllerType .PROPERTY .equals (dataRestRepository .getControllerType ()))
218+ returnedEntityType = dataRestRepository .getPropertyType ();
219+
211220 if (returnType instanceof ParameterizedType ) {
212221 ParameterizedType parameterizedType = (ParameterizedType ) returnType ;
213222 if ((ResponseEntity .class .equals (parameterizedType .getRawType ()))) {
214223 if (Object .class .equals (parameterizedType .getActualTypeArguments ()[0 ])) {
215- return ResolvableType .forClassWithGenerics (ResponseEntity .class , domainType ).getType ();
224+ return ResolvableType .forClassWithGenerics (ResponseEntity .class , returnedEntityType ).getType ();
216225 }
217226 else if (parameterizedType .getActualTypeArguments ()[0 ] instanceof ParameterizedType ) {
218227 ParameterizedType parameterizedType1 = (ParameterizedType ) parameterizedType .getActualTypeArguments ()[0 ];
219228 Class <?> rawType = ResolvableType .forType (parameterizedType1 .getRawType ()).getRawClass ();
220229 if (rawType != null && rawType .isAssignableFrom (RepresentationModel .class )) {
221- Class <?> type = findType (methodParameterReturn , requestMethod );
222- return resolveGenericType (ResponseEntity .class , type , domainType );
230+ Class <?> type = findType (requestMethod , dataRestRepository );
231+ return resolveGenericType (ResponseEntity .class , type , returnedEntityType );
223232 }
224233 else if (EntityModel .class .equals (parameterizedType1 .getRawType ())) {
225- return resolveGenericType (ResponseEntity .class , EntityModel .class , domainType );
234+ return resolveGenericType (ResponseEntity .class , EntityModel .class , returnedEntityType );
226235 }
227236 }
228237 else if (parameterizedType .getActualTypeArguments ()[0 ] instanceof WildcardType ) {
229238 WildcardType wildcardType = (WildcardType ) parameterizedType .getActualTypeArguments ()[0 ];
230239 if (wildcardType .getUpperBounds ()[0 ] instanceof ParameterizedType ) {
231240 ParameterizedType wildcardTypeUpperBound = (ParameterizedType ) wildcardType .getUpperBounds ()[0 ];
232241 if (RepresentationModel .class .equals (wildcardTypeUpperBound .getRawType ())) {
233- Class <?> type = findType (methodParameterReturn , requestMethod );
234- return resolveGenericType (ResponseEntity .class , type , domainType );
242+ Class <?> type = findType (requestMethod , dataRestRepository );
243+ return resolveGenericType (ResponseEntity .class , type , returnedEntityType );
235244 }
236245 }
237246 }
@@ -240,12 +249,12 @@ else if ((HttpEntity.class.equals(parameterizedType.getRawType())
240249 && parameterizedType .getActualTypeArguments ()[0 ] instanceof ParameterizedType )) {
241250 ParameterizedType wildcardTypeUpperBound = (ParameterizedType ) parameterizedType .getActualTypeArguments ()[0 ];
242251 if (RepresentationModel .class .equals (wildcardTypeUpperBound .getRawType ())) {
243- return resolveGenericType (HttpEntity .class , RepresentationModel .class , domainType );
252+ return resolveGenericType (HttpEntity .class , RepresentationModel .class , returnedEntityType );
244253 }
245254 }
246255 else if ((CollectionModel .class .equals (parameterizedType .getRawType ())
247256 && Object .class .equals (parameterizedType .getActualTypeArguments ()[0 ]))) {
248- return ResolvableType .forClassWithGenerics (CollectionModel .class , domainType ).getType ();
257+ return ResolvableType .forClassWithGenerics (CollectionModel .class , returnedEntityType ).getType ();
249258 }
250259 }
251260 return returnType ;
@@ -254,14 +263,22 @@ else if ((CollectionModel.class.equals(parameterizedType.getRawType())
254263 /**
255264 * Find type class.
256265 *
257- * @param methodParameterReturn the method parameter return
258266 * @param requestMethod the request method
267+ * @param dataRestRepository the data rest repository
259268 * @return the class
260269 */
261- private Class findType (MethodParameter methodParameterReturn , RequestMethod requestMethod ) {
262- if (SpringRepositoryRestResourceProvider . REPOSITORY_ENTITY_CONTROLLER .equals (methodParameterReturn . getContainingClass (). getCanonicalName ())
270+ private Class findType (RequestMethod requestMethod , DataRestRepository dataRestRepository ) {
271+ if (ControllerType . ENTITY .equals (dataRestRepository . getControllerType ())
263272 && Arrays .stream (requestMethodsEntityModel ).anyMatch (requestMethod ::equals ))
264273 return EntityModel .class ;
274+ else if (dataRestRepository !=null && ControllerType .PROPERTY .equals (dataRestRepository .getControllerType ())) {
275+ if (dataRestRepository .isCollectionLike ())
276+ return CollectionModel .class ;
277+ else if (dataRestRepository .isMap ())
278+ return MapModel .class ;
279+ else
280+ return EntityModel .class ;
281+ }
265282 else
266283 return RepresentationModel .class ;
267284 }
@@ -306,4 +323,37 @@ private void addResponse204(ApiResponses apiResponses) {
306323 private void addResponse404 (ApiResponses apiResponses ) {
307324 apiResponses .put (String .valueOf (HttpStatus .NOT_FOUND .value ()), new ApiResponse ().description (HttpStatus .NOT_FOUND .getReasonPhrase ()));
308325 }
326+
327+ /**
328+ * The type Map model.
329+ * @author bnasslashen
330+ */
331+ private static class MapModel extends RepresentationModel <MapModel > {
332+ /**
333+ * The Content.
334+ */
335+ private Map <? extends Object , ? extends Object > content ;
336+
337+ /**
338+ * Instantiates a new Map model.
339+ *
340+ * @param content the content
341+ * @param links the links
342+ */
343+ public MapModel (Map <? extends Object , ? extends Object > content , Link ... links ) {
344+ super (Arrays .asList (links ));
345+ this .content = content ;
346+ }
347+
348+ /**
349+ * Gets content.
350+ *
351+ * @return the content
352+ */
353+ @ JsonAnyGetter
354+ public Map <? extends Object , ? extends Object > getContent () {
355+ return content ;
356+ }
357+ }
358+
309359}
0 commit comments