66import com .contentgrid .appserver .application .model .Application ;
77import com .contentgrid .appserver .application .model .Entity ;
88import com .contentgrid .appserver .application .model .relations .ManyToManyRelation ;
9- import com .contentgrid .appserver .application .model .relations .ManyToOneRelation ;
109import com .contentgrid .appserver .application .model .relations .OneToManyRelation ;
11- import com .contentgrid .appserver .application .model .relations .OneToOneRelation ;
1210import com .contentgrid .appserver .application .model .relations .Relation ;
1311import com .contentgrid .appserver .application .model .values .PathSegmentName ;
1412import com .contentgrid .appserver .domain .DatamodelApi ;
1513import com .contentgrid .appserver .query .engine .api .data .EntityId ;
1614import com .contentgrid .appserver .query .engine .api .data .XToManyRelationData ;
17- import com .contentgrid .appserver .query .engine .api .data .XToOneRelationData ;
1815import com .contentgrid .appserver .query .engine .api .exception .ConstraintViolationException ;
1916import com .contentgrid .appserver .query .engine .api .exception .EntityNotFoundException ;
2017import com .contentgrid .appserver .rest .EntityRestController ;
2421import java .util .Map ;
2522import java .util .Optional ;
2623import java .util .UUID ;
24+ import lombok .NonNull ;
2725import org .springframework .beans .factory .annotation .Autowired ;
28- import org .springframework .hateoas .server .mvc .WebMvcLinkBuilder ;
2926import org .springframework .http .HttpMethod ;
3027import org .springframework .http .HttpStatus ;
3128import org .springframework .http .ResponseEntity ;
3229import org .springframework .stereotype .Component ;
3330import org .springframework .web .server .ResponseStatusException ;
3431
3532@ Component
36- public class RelationRequestHandler extends AbstractPropertyItemRequestHandler <List <URI >, Relation > {
33+ public class XToManyRelationRequestHandler extends AbstractPropertyItemRequestHandler <List <URI >, Relation > {
3734
38- private static final HttpMethod [] SINGLE_TARGET_PROPERTY_METHODS = {HttpMethod .GET , HttpMethod .HEAD , HttpMethod .PUT , HttpMethod .DELETE };
39- private static final HttpMethod [] MULTI_TARGET_PROPERTY_METHODS = {HttpMethod .GET , HttpMethod .HEAD , HttpMethod .POST , HttpMethod .DELETE };
40- private static final HttpMethod [] MULTI_TARGET_PROPERTY_ITEM_METHODS = {HttpMethod .GET , HttpMethod .HEAD , HttpMethod .DELETE };
41-
42- private static HttpMethod [] supportedPropertyMethods (Relation relation ) {
43- if (relation instanceof OneToManyRelation || relation instanceof ManyToManyRelation ) {
44- return MULTI_TARGET_PROPERTY_METHODS ;
45- } else {
46- return SINGLE_TARGET_PROPERTY_METHODS ;
47- }
48- }
49-
50- private static ResponseEntity <Object > propertyItemUnsupportedMethodResponse (Relation relation ) {
51- if (relation instanceof OneToManyRelation || relation instanceof ManyToManyRelation ) {
52- // *-to-many relation
53- return ResponseEntity .status (HttpStatus .METHOD_NOT_ALLOWED )
54- .allow (MULTI_TARGET_PROPERTY_ITEM_METHODS )
55- .build ();
56- } else {
57- // *-to-one relation
58- return ResponseEntity .notFound ().build ();
59- }
60- }
35+ private static final HttpMethod [] SUPPORTED_PROPERTY_METHODS = {HttpMethod .GET , HttpMethod .HEAD , HttpMethod .POST , HttpMethod .DELETE };
36+ private static final HttpMethod [] SUPPORTED_PROPERTY_ITEM_METHODS = {HttpMethod .GET , HttpMethod .HEAD , HttpMethod .DELETE };
6137
38+ @ NonNull
6239 private final DatamodelApi datamodelApi ;
6340
6441 @ Autowired
65- public RelationRequestHandler ( DatamodelApi datamodelApi ) {
42+ public XToManyRelationRequestHandler ( @ NonNull DatamodelApi datamodelApi ) {
6643 super (new UriListHttpServletRequestConverter ());
6744 this .datamodelApi = datamodelApi ;
6845 }
6946
7047 @ Override
7148 protected Optional <Relation > findProperty (Application application , Entity entity , PathSegmentName propertyName ) {
72- return application .getRelationForPath (entity .getPathSegment (), propertyName );
49+ return application .getRelationForPath (entity .getPathSegment (), propertyName )
50+ .filter (relation -> relation instanceof OneToManyRelation || relation instanceof ManyToManyRelation );
7351 }
7452
7553 @ Override
@@ -81,31 +59,11 @@ protected ResponseEntity<Object> getProperty(
8159 ) {
8260 var targetPathSegment = property .getTargetEndPoint ().getEntity ().getPathSegment ();
8361 try {
84- URI redirectUrl ;
85- switch (property ) {
86- case OneToOneRelation oneToOneRelation -> {
87- var targetId = datamodelApi .findRelationTarget (application , oneToOneRelation , instanceId )
88- .orElseThrow (() -> new ResponseStatusException (HttpStatus .NOT_FOUND , "Target of %s not found" .formatted (property .getSourceEndPoint ().getName ())));
89- redirectUrl = WebMvcLinkBuilder .linkTo (methodOn (EntityRestController .class ).getEntity (application , targetPathSegment , targetId )).toUri ();
90- }
91- case ManyToOneRelation manyToOneRelation -> {
92- var targetId = datamodelApi .findRelationTarget (application , manyToOneRelation , instanceId )
93- .orElseThrow (() -> new ResponseStatusException (HttpStatus .NOT_FOUND , "Target of %s not found" .formatted (property .getSourceEndPoint ().getName ())));
94- redirectUrl = linkTo (methodOn (EntityRestController .class ).getEntity (application , targetPathSegment , targetId )).toUri ();
95- }
96- case OneToManyRelation oneToManyRelation -> {
97- datamodelApi .findById (application , oneToManyRelation .getSourceEndPoint ().getEntity (), instanceId )
98- .orElseThrow (() -> new ResponseStatusException (HttpStatus .NOT_FOUND , "Entity with id %s not found" .formatted (instanceId )));
99- redirectUrl = linkTo (methodOn (EntityRestController .class ).listEntity (application , targetPathSegment , 0 ,
100- Map .of (property .getTargetEndPoint ().getName ().getValue (), instanceId .toString ()))).toUri (); // TODO: use RelationSearchFilter
101- }
102- case ManyToManyRelation manyToManyRelation -> {
103- datamodelApi .findById (application , manyToManyRelation .getSourceEndPoint ().getEntity (), instanceId )
104- .orElseThrow (() -> new ResponseStatusException (HttpStatus .NOT_FOUND , "Entity with id %s not found" .formatted (instanceId )));
105- redirectUrl = linkTo (methodOn (EntityRestController .class ).listEntity (application , targetPathSegment , 0 ,
106- Map .of (property .getTargetEndPoint ().getName ().getValue (), instanceId .toString ()))).toUri (); // TODO: use RelationSearchFilter
107- }
108- }
62+ datamodelApi .findById (application , property .getSourceEndPoint ().getEntity (), instanceId )
63+ .orElseThrow (() -> new ResponseStatusException (HttpStatus .NOT_FOUND , "Entity with id %s not found" .formatted (instanceId )));
64+ var redirectUrl = linkTo (methodOn (EntityRestController .class ).listEntity (application , targetPathSegment , 0 ,
65+ Map .of (property .getTargetEndPoint ().getName ().getValue (), instanceId .toString ()))).toUri (); // TODO: use RelationSearchFilter
66+
10967 return ResponseEntity .status (HttpStatus .FOUND ).location (redirectUrl ).build ();
11068 } catch (EntityNotFoundException e ) {
11169 throw new ResponseStatusException (HttpStatus .NOT_FOUND , e .getMessage (), e );
@@ -142,13 +100,6 @@ protected ResponseEntity<Object> postProperty(
142100 throw new ResponseStatusException (HttpStatus .BAD_REQUEST , "No entity url provided." );
143101 }
144102 var targetPathSegment = property .getTargetEndPoint ().getEntity ().getPathSegment ();
145-
146- if (!(property instanceof OneToManyRelation || property instanceof ManyToManyRelation )) {
147- return ResponseEntity .status (HttpStatus .METHOD_NOT_ALLOWED )
148- .allow (SINGLE_TARGET_PROPERTY_METHODS )
149- .build ();
150- }
151-
152103 var dataBuilder = XToManyRelationData .builder ()
153104 .entity (property .getSourceEndPoint ().getEntity ().getName ())
154105 .name (property .getSourceEndPoint ().getName ());
@@ -180,46 +131,21 @@ protected ResponseEntity<Object> putProperty(
180131 Relation property ,
181132 List <URI > body
182133 ) {
183- if (body .isEmpty ()) {
184- throw new ResponseStatusException (HttpStatus .BAD_REQUEST , "No entity url provided." );
185- }
186- if (body .size () > 1 ) {
187- throw new ResponseStatusException (HttpStatus .BAD_REQUEST , "Multiple targets not supported." );
188- }
189- var targetPathSegment = property .getTargetEndPoint ().getEntity ().getPathSegment ();
190-
191- if (property instanceof OneToManyRelation || property instanceof ManyToManyRelation ) {
192- return ResponseEntity .status (HttpStatus .METHOD_NOT_ALLOWED )
193- .allow (MULTI_TARGET_PROPERTY_METHODS )
194- .build ();
195- }
196- var element = body .getFirst ();
197-
198- var pathSegment = parseEntityPathSegment (element );
199- if (!targetPathSegment .equals (pathSegment )) {
200- throw new ResponseStatusException (HttpStatus .BAD_REQUEST , "Invalid target entity. Expected %s, got %s." .formatted (targetPathSegment , pathSegment ));
201- }
202- var targetId = parseEntityId (element );
203- var data = XToOneRelationData .builder ()
204- .entity (property .getSourceEndPoint ().getEntity ().getName ())
205- .name (property .getSourceEndPoint ().getName ())
206- .ref (targetId )
134+ return ResponseEntity .status (HttpStatus .METHOD_NOT_ALLOWED )
135+ .allow (SUPPORTED_PROPERTY_METHODS )
207136 .build ();
208- try {
209- datamodelApi .setRelation (application , data , instanceId );
210- } catch (EntityNotFoundException e ) {
211- throw new ResponseStatusException (HttpStatus .NOT_FOUND , e .getMessage (), e );
212- } catch (ConstraintViolationException e ) {
213- throw new ResponseStatusException (HttpStatus .BAD_REQUEST , e .getMessage (), e );
214- }
215- return ResponseEntity .noContent ().build ();
216137 }
217138
218139 @ Override
219- protected ResponseEntity <Object > patchProperty (Application application , Entity entity , EntityId instanceId ,
220- Relation property , List <URI > body ) {
140+ protected ResponseEntity <Object > patchProperty (
141+ Application application ,
142+ Entity entity ,
143+ EntityId instanceId ,
144+ Relation property ,
145+ List <URI > body
146+ ) {
221147 return ResponseEntity .status (HttpStatus .METHOD_NOT_ALLOWED )
222- .allow (supportedPropertyMethods ( property ) )
148+ .allow (SUPPORTED_PROPERTY_METHODS )
223149 .build ();
224150 }
225151
@@ -248,10 +174,6 @@ protected ResponseEntity<Object> getPropertyItem(
248174 Relation property ,
249175 EntityId itemId
250176 ) {
251- if (!(property instanceof OneToManyRelation || property instanceof ManyToManyRelation )) {
252- return ResponseEntity .notFound ().build ();
253- }
254-
255177 if (datamodelApi .hasRelationTarget (application , property , instanceId , itemId )) {
256178 var uri = linkTo (methodOn (EntityRestController .class ).getEntity (application , property .getTargetEndPoint ().getEntity ().getPathSegment (), itemId )).toUri ();
257179 return ResponseEntity .status (HttpStatus .FOUND ).location (uri ).build ();
@@ -269,7 +191,9 @@ protected ResponseEntity<Object> postPropertyItem(
269191 EntityId itemId ,
270192 List <URI > body
271193 ) {
272- return propertyItemUnsupportedMethodResponse (property );
194+ return ResponseEntity .status (HttpStatus .METHOD_NOT_ALLOWED )
195+ .allow (SUPPORTED_PROPERTY_ITEM_METHODS )
196+ .build ();
273197 }
274198
275199 @ Override
@@ -281,7 +205,9 @@ protected ResponseEntity<Object> putPropertyItem(
281205 EntityId itemId ,
282206 List <URI > body
283207 ) {
284- return propertyItemUnsupportedMethodResponse (property );
208+ return ResponseEntity .status (HttpStatus .METHOD_NOT_ALLOWED )
209+ .allow (SUPPORTED_PROPERTY_ITEM_METHODS )
210+ .build ();
285211 }
286212
287213 @ Override
@@ -293,7 +219,9 @@ protected ResponseEntity<Object> patchPropertyItem(
293219 EntityId itemId ,
294220 List <URI > body
295221 ) {
296- return propertyItemUnsupportedMethodResponse (property );
222+ return ResponseEntity .status (HttpStatus .METHOD_NOT_ALLOWED )
223+ .allow (SUPPORTED_PROPERTY_ITEM_METHODS )
224+ .build ();
297225 }
298226
299227 @ Override
@@ -304,10 +232,6 @@ protected ResponseEntity<Object> deletePropertyItem(
304232 Relation property ,
305233 EntityId itemId
306234 ) {
307- if (!(property instanceof OneToManyRelation || property instanceof ManyToManyRelation )) {
308- return ResponseEntity .notFound ().build ();
309- }
310-
311235 try {
312236 datamodelApi .removeRelationItem (application , property , instanceId , itemId );
313237 } catch (EntityNotFoundException e ) {
0 commit comments