diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceHandler.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceHandler.java index 8a9c6108b..621f0debd 100644 --- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceHandler.java +++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceHandler.java @@ -194,19 +194,19 @@ public interface ServiceHandler extends Processor { throws ODataTranslatedException, ODataApplicationException; /** - * Add references (relationships) to Entity. + * Add references (relationships) to Entity. This is always on collection valued navigation property * @param request * @param entityETag - entity etag to match before add operation, "*" allows all. - * @param idReferences - references to add + * @param referenceId - references to add * @param response - return always should be 204 * @throws ODataTranslatedException * @throws ODataApplicationException */ - void addReference(DataRequest request, String entityETag, List idReferences, NoContentResponse response) + void addReference(DataRequest request, String entityETag, URI referenceId, NoContentResponse response) throws ODataTranslatedException, ODataApplicationException; /** - * Update references (relationships) in an Entity + * Update references (relationships) in an Entity; This is always against single valued navigation property * @param request * @param entityETag * @param referenceId @@ -220,7 +220,8 @@ public interface ServiceHandler extends Processor { /** * Delete references (relationships) in an Entity * @param request - * @param deleteId + * @param deleteId; for collection valued navigation this will be non-null value; for single valued + * navigation property, this will be null. * @param entityETag * @param response - always should be 204 * @throws ODataTranslatedException diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/legacy/ProcessorServiceHandler.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/legacy/ProcessorServiceHandler.java index fa8f44557..3a2c14483 100644 --- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/legacy/ProcessorServiceHandler.java +++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/legacy/ProcessorServiceHandler.java @@ -389,7 +389,7 @@ public class ProcessorServiceHandler implements ServiceHandler { } @Override - public void addReference(DataRequest request, String entityETag, List idReferences, + public void addReference(DataRequest request, String entityETag, URI referenceId, NoContentResponse response) throws ODataTranslatedException, ODataApplicationException { selectProcessor(ReferenceProcessor.class).createReference( request.getODataRequest(), response.getODataResponse(), request.getUriInfo(), diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/DataRequest.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/DataRequest.java index fd3aa25a0..b3be91c15 100644 --- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/DataRequest.java +++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/DataRequest.java @@ -80,6 +80,7 @@ import org.apache.olingo.server.core.responses.NoContentResponse; import org.apache.olingo.server.core.responses.PrimitiveValueResponse; import org.apache.olingo.server.core.responses.PropertyResponse; import org.apache.olingo.server.core.responses.StreamResponse; +import org.apache.olingo.server.core.uri.parser.UriParserSemanticException; public class DataRequest extends ServiceRequest { protected UriResourceEntitySet uriResourceEntitySet; @@ -423,6 +424,10 @@ public class DataRequest extends ServiceRequest { } else if (isDELETE()) { // if this against the collection, user need to look at $id param for entity ref #11.4.6.2 String id = getQueryParameter("$id"); + if (id == null && isCollection()) { + throw new UriParserSemanticException("$id not specified for delete of reference", + UriParserSemanticException.MessageKeys.RESOURCE_NOT_FOUND); + } if (id == null) { handler.deleteReference(DataRequest.this, null, getETag(), new NoContentResponse( getServiceMetaData(), response)); @@ -440,7 +445,7 @@ public class DataRequest extends ServiceRequest { getServiceMetaData(), response)); } else if (isPOST()) { // this needs to be against collection of references - handler.addReference(DataRequest.this, getETag(), getPayload(), new NoContentResponse( + handler.addReference(DataRequest.this, getETag(), getPayload().get(0), new NoContentResponse( getServiceMetaData(), response)); } } diff --git a/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/ServiceDispatcherTest.java b/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/ServiceDispatcherTest.java index 34232509c..6156c1b39 100644 --- a/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/ServiceDispatcherTest.java +++ b/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/ServiceDispatcherTest.java @@ -25,7 +25,6 @@ import java.io.FileReader; import java.io.IOException; import java.net.URI; import java.util.Collections; -import java.util.List; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; @@ -409,7 +408,7 @@ public class ServiceDispatcherTest { public void validate() throws Exception { ArgumentCaptor arg1 = ArgumentCaptor.forClass(DataRequest.class); ArgumentCaptor arg2 = ArgumentCaptor.forClass(String.class); - ArgumentCaptor arg3 = ArgumentCaptor.forClass(List.class); + ArgumentCaptor arg3 = ArgumentCaptor.forClass(URI.class); ArgumentCaptor arg4 = ArgumentCaptor .forClass(NoContentResponse.class); Mockito.verify(handler).addReference(arg1.capture(), arg2.capture(), arg3.capture(), diff --git a/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinHandler.java b/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinHandler.java index c721325fd..c180a0692 100644 --- a/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinHandler.java +++ b/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinHandler.java @@ -434,18 +434,16 @@ public class TripPinHandler implements ServiceHandler { } @Override - public void addReference(DataRequest request, String entityETag, List references, + public void addReference(DataRequest request, String entityETag, URI referenceId, NoContentResponse response) throws ODataTranslatedException, ODataApplicationException { final EntityDetails details = process(request); try { - for (URI reference : references) { - DataRequest bindingRequest = request.parseLink(reference); + DataRequest bindingRequest = request.parseLink(referenceId); Entity linkEntity = this.dataModel.getEntity(bindingRequest.getEntitySet().getName(), bindingRequest.getKeyPredicates()); this.dataModel.addNavigationLink(details.navigationProperty, details.entity, linkEntity); - } } catch (URISyntaxException e) { throw new ODataApplicationException(e.getMessage(), 500, Locale.getDefault(), e); } diff --git a/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServiceTest.java b/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServiceTest.java index 017b072c8..c64bfb575 100644 --- a/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServiceTest.java +++ b/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServiceTest.java @@ -344,12 +344,9 @@ public class TripPinServiceTest { //ADD String payload = "{\n" + - " \"@odata.context\": \""+baseURL+"/$metadata#Collection($ref)\",\n" + - " \"value\": [\n" + - " { \"@odata.id\": \"People('russellwhyte')\" },\n" + - " { \"@odata.id\": \"People('scottketchum')\" } \n" + - " ]\n" + + "\"@odata.id\": \"/People('scottketchum')\"\n" + "}"; + HttpPost postRequest = new HttpPost(baseURL + "/People('kristakemp')/Friends/$ref"); postRequest.setEntity(new StringEntity(payload, ContentType.APPLICATION_JSON)); response = httpSend(postRequest, 204); @@ -360,8 +357,7 @@ public class TripPinServiceTest { assertTrue(node.get("value").isArray()); assertEquals("/People('genevievereeves')", ((ArrayNode)node.get("value")).get(0).get("@odata.id").asText()); - assertEquals("/People('russellwhyte')", ((ArrayNode)node.get("value")).get(1).get("@odata.id").asText()); - assertEquals("/People('scottketchum')", ((ArrayNode)node.get("value")).get(2).get("@odata.id").asText()); + assertEquals("/People('scottketchum')", ((ArrayNode)node.get("value")).get(1).get("@odata.id").asText()); }