[OLINGO-365] provided more tests

This commit is contained in:
fmartelli 2014-07-28 17:48:57 +02:00
parent 05e41557f5
commit 72dc69dc8e
19 changed files with 492 additions and 49 deletions

View File

@ -23,4 +23,19 @@ import java.util.Collection;
public interface EntityCollection<
T extends StructuredType<?>, EC extends Collection<T>, CT extends StructuredCollection<T, EC, ?>>
extends StructuredCollection<T, EC, CT> {
/**
* Appends ref segment to the URI.
*
* @return the same query instance.
*/
CT refs();
/**
* Add entity by its reference ID.
*
* @param element entity to be linked.
* @return <tt>TRUE</tt> if correctly added; <tt>FALSE</tt> otherwise.
*/
<ET extends EntityType<?>> boolean addRef(ET element);
}

View File

@ -19,4 +19,18 @@
package org.apache.olingo.ext.proxy.api;
public interface EntityType<T extends StructuredType<?>> extends StructuredType<T> {
/**
* Appends ref segment to the URI.
*
* @return the same query instance.
*/
T refs();
/**
* Gets entity reference ID.
*
* @return entity reference ID.
*/
String getEntityReferenceID();
}

View File

@ -26,4 +26,6 @@ public interface PrimitiveCollection<T extends Serializable>
CollectionQuery<PrimitiveCollection<T>>,
Collection<T>,
Serializable {
void delete();
}

View File

@ -33,9 +33,13 @@ import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import org.apache.commons.lang3.tuple.Triple;
import org.apache.olingo.client.api.uri.URIFilter;
import org.apache.olingo.client.api.uri.v4.URIBuilder;
import org.apache.olingo.commons.api.domain.v4.ODataAnnotation;
import org.apache.olingo.commons.api.domain.v4.ODataEntity;
import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
import org.apache.olingo.ext.proxy.AbstractService;
import org.apache.olingo.ext.proxy.api.AbstractTerm;
import org.apache.olingo.ext.proxy.api.EntityType;
import org.apache.olingo.ext.proxy.api.Sort;
import org.apache.olingo.ext.proxy.api.annotations.Namespace;
import org.apache.olingo.ext.proxy.api.annotations.Term;
@ -50,6 +54,8 @@ public abstract class AbstractCollectionInvocationHandler<T extends Serializable
protected Collection<T> items;
protected Collection<String> referenceItems;
protected final URI baseURI;
protected CommonURIBuilder<?> uri;
@ -71,13 +77,13 @@ public abstract class AbstractCollectionInvocationHandler<T extends Serializable
this.itemRef = itemRef;
this.items = items;
this.referenceItems = new ArrayList<String>();
this.uri = uri;
this.baseURI = this.uri == null ? null : this.uri.build();
}
public Future<Collection<T>> executeAsync() {
return service.getClient().getConfiguration().getExecutor().submit(new Callable<Collection<T>>() {
@Override
public Collection<T> call() throws Exception {
return execute();
@ -173,6 +179,30 @@ public abstract class AbstractCollectionInvocationHandler<T extends Serializable
return items.add(element);
}
public <ET extends EntityType<?>> boolean addRef(final ET element) {
if (getClient().getServiceVersion().compareTo(ODataServiceVersion.V30) <= 0) {
return false;
}
if (element instanceof Proxy && Proxy.getInvocationHandler(element) instanceof EntityInvocationHandler) {
final EntityInvocationHandler handler = EntityInvocationHandler.class.cast(Proxy.getInvocationHandler(element));
final URI id = ((ODataEntity) handler.getEntity()).getId();
if (id == null) {
return false;
}
return referenceItems.add(id.toASCIIString());
}
return false;
}
public void refs() {
if (getClient().getServiceVersion().compareTo(ODataServiceVersion.V40) >= 0) {
((URIBuilder) this.uri).appendRefSegment();
}
}
@Override
public int size() {
return items.size();

View File

@ -18,6 +18,7 @@
*/
package org.apache.olingo.ext.proxy.commons;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.net.URI;
import java.util.ArrayList;
@ -33,6 +34,7 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.olingo.client.api.communication.header.ODataPreferences;
import org.apache.olingo.client.api.communication.request.cud.ODataDeleteRequest;
import org.apache.olingo.client.api.communication.request.cud.ODataEntityUpdateRequest;
import org.apache.olingo.client.api.communication.request.cud.v4.ODataReferenceAddingRequest;
import org.apache.olingo.client.api.communication.request.streamed.ODataMediaEntityUpdateRequest;
import org.apache.olingo.client.api.communication.request.streamed.ODataStreamUpdateRequest;
import org.apache.olingo.client.core.uri.URIUtils;
@ -71,7 +73,6 @@ abstract class AbstractPersistenceManager implements PersistenceManager {
@Override
public Future<List<ODataRuntimeException>> flushAsync() {
return service.getClient().getConfiguration().getExecutor().submit(new Callable<List<ODataRuntimeException>>() {
@Override
public List<ODataRuntimeException> call() throws Exception {
return flush();
@ -93,7 +94,6 @@ abstract class AbstractPersistenceManager implements PersistenceManager {
if (((status != AttachedEntityStatus.ATTACHED
&& status != AttachedEntityStatus.LINKED) || attachedEntity.getEntity().isChanged())
&& !items.contains(attachedEntity.getEntity())) {
pos++;
pos = processEntityContext(attachedEntity.getEntity(), pos, items, delayedUpdates, changes);
}
@ -224,6 +224,16 @@ abstract class AbstractPersistenceManager implements PersistenceManager {
if (!toBeLinked.isEmpty()) {
delayedUpdates.add(new EntityLinkDesc(property.getKey().name(), handler, toBeLinked, type));
}
if (property.getValue() instanceof Proxy) {
final InvocationHandler target = Proxy.getInvocationHandler(property.getValue());
if (target instanceof EntityCollectionInvocationHandler) {
for (String ref : ((EntityCollectionInvocationHandler<?>) target).referenceItems) {
delayedUpdates.add(new EntityLinkDesc(property.getKey().name(), handler, ref));
}
}
}
}
if (entity instanceof ODataEntity) {
@ -253,7 +263,7 @@ abstract class AbstractPersistenceManager implements PersistenceManager {
final URI targetURI = currentStatus == AttachedEntityStatus.NEW
? URI.create("$" + startingPos)
: URIUtils.getURI(
service.getClient().getServiceRoot(), handler.getEntity().getEditLink().toASCIIString());
service.getClient().getServiceRoot(), handler.getEntity().getEditLink().toASCIIString());
queueUpdate(handler, targetURI, entity, changeset);
pos++;
items.put(handler, pos);
@ -265,8 +275,8 @@ abstract class AbstractPersistenceManager implements PersistenceManager {
final URI targetURI = currentStatus == AttachedEntityStatus.NEW
? URI.create("$" + startingPos + "/$value")
: URIUtils.getURI(
service.getClient().getServiceRoot(),
handler.getEntity().getEditLink().toASCIIString() + "/$value");
service.getClient().getServiceRoot(),
handler.getEntity().getEditLink().toASCIIString() + "/$value");
queueUpdateMediaEntity(handler, targetURI, handler.getStreamChanges(), changeset);
@ -280,8 +290,8 @@ abstract class AbstractPersistenceManager implements PersistenceManager {
for (Map.Entry<String, EdmStreamValue> streamedChanges : handler.getStreamedPropertyChanges().entrySet()) {
final URI targetURI = currentStatus == AttachedEntityStatus.NEW
? URI.create("$" + startingPos) : URIUtils.getURI(
service.getClient().getServiceRoot(),
CoreUtils.getMediaEditLink(streamedChanges.getKey(), entity).toASCIIString());
service.getClient().getServiceRoot(),
CoreUtils.getMediaEditLink(streamedChanges.getKey(), entity).toASCIIString());
queueUpdateMediaResource(handler, targetURI, streamedChanges.getValue(), changeset);
@ -302,46 +312,60 @@ abstract class AbstractPersistenceManager implements PersistenceManager {
final PersistenceChanges changeset) {
for (EntityLinkDesc delayedUpdate : delayedUpdates) {
pos++;
items.put(delayedUpdate.getSource(), pos);
if (StringUtils.isBlank(delayedUpdate.getReference())) {
final CommonODataEntity changes =
service.getClient().getObjectFactory().newEntity(delayedUpdate.getSource().getEntity().getTypeName());
pos++;
items.put(delayedUpdate.getSource(), pos);
AttachedEntityStatus status = service.getContext().entityContext().getStatus(delayedUpdate.getSource());
final CommonODataEntity changes =
service.getClient().getObjectFactory().newEntity(delayedUpdate.getSource().getEntity().getTypeName());
final URI sourceURI;
if (status == AttachedEntityStatus.CHANGED) {
sourceURI = URIUtils.getURI(
service.getClient().getServiceRoot(),
delayedUpdate.getSource().getEntity().getEditLink().toASCIIString());
} else {
int sourcePos = items.get(delayedUpdate.getSource());
sourceURI = URI.create("$" + sourcePos);
}
AttachedEntityStatus status = service.getContext().entityContext().getStatus(delayedUpdate.getSource());
for (EntityInvocationHandler target : delayedUpdate.getTargets()) {
status = service.getContext().entityContext().getStatus(target);
final URI targetURI;
final URI sourceURI;
if (status == AttachedEntityStatus.CHANGED) {
targetURI = URIUtils.getURI(
service.getClient().getServiceRoot(), target.getEntity().getEditLink().toASCIIString());
sourceURI = URIUtils.getURI(
service.getClient().getServiceRoot(),
delayedUpdate.getSource().getEntity().getEditLink().toASCIIString());
} else {
int targetPos = items.get(target);
targetURI = URI.create("$" + targetPos);
int sourcePos = items.get(delayedUpdate.getSource());
sourceURI = URI.create("$" + sourcePos);
}
changes.addLink(delayedUpdate.getType() == ODataLinkType.ENTITY_NAVIGATION
? service.getClient().getObjectFactory().
newEntityNavigationLink(delayedUpdate.getSourceName(), targetURI)
: service.getClient().getObjectFactory().
newEntitySetNavigationLink(delayedUpdate.getSourceName(), targetURI));
for (EntityInvocationHandler target : delayedUpdate.getTargets()) {
status = service.getContext().entityContext().getStatus(target);
LOG.debug("'{}' from {} to {}", delayedUpdate.getType().name(), sourceURI, targetURI);
final URI targetURI;
if (status == AttachedEntityStatus.CHANGED) {
targetURI = URIUtils.getURI(
service.getClient().getServiceRoot(), target.getEntity().getEditLink().toASCIIString());
} else {
int targetPos = items.get(target);
targetURI = URI.create("$" + targetPos);
}
changes.addLink(delayedUpdate.getType() == ODataLinkType.ENTITY_NAVIGATION
? service.getClient().getObjectFactory().
newEntityNavigationLink(delayedUpdate.getSourceName(), targetURI)
: service.getClient().getObjectFactory().
newEntitySetNavigationLink(delayedUpdate.getSourceName(), targetURI));
LOG.debug("'{}' from {} to {}", delayedUpdate.getType().name(), sourceURI, targetURI);
}
queueUpdate(delayedUpdate.getSource(), sourceURI, changes, changeset);
} else {
URI sourceURI = URIUtils.getURI(
service.getClient().getServiceRoot(),
delayedUpdate.getSource().getEntity().getEditLink().toASCIIString()
+ "/" + delayedUpdate.getSourceName() + "/$ref");
if (queueUpdateLinkViaRef(
delayedUpdate.getSource(), sourceURI, URI.create(delayedUpdate.getReference()), changeset)) {
pos++;
items.put(delayedUpdate.getSource(), pos);
}
}
queueUpdate(delayedUpdate.getSource(), sourceURI, changes, changeset);
}
}
@ -435,10 +459,10 @@ abstract class AbstractPersistenceManager implements PersistenceManager {
service.getClient().getServiceVersion().compareTo(ODataServiceVersion.V30) <= 0
? ((org.apache.olingo.client.api.v3.EdmEnabledODataClient) service.getClient()).getCUDRequestFactory().
getEntityUpdateRequest(handler.getEntityURI(),
org.apache.olingo.client.api.communication.request.cud.v3.UpdateType.PATCH, changes)
org.apache.olingo.client.api.communication.request.cud.v3.UpdateType.PATCH, changes)
: ((org.apache.olingo.client.api.v4.EdmEnabledODataClient) service.getClient()).getCUDRequestFactory().
getEntityUpdateRequest(handler.getEntityURI(),
org.apache.olingo.client.api.communication.request.cud.v4.UpdateType.PATCH, changes);
org.apache.olingo.client.api.communication.request.cud.v4.UpdateType.PATCH, changes);
req.setPrefer(new ODataPreferences(service.getClient().getServiceVersion()).returnContent());
@ -449,6 +473,30 @@ abstract class AbstractPersistenceManager implements PersistenceManager {
changeset.addChange(req, handler);
}
private boolean queueUpdateLinkViaRef(
final EntityInvocationHandler handler,
final URI source,
final URI targetRef,
final PersistenceChanges changeset) {
LOG.debug("Update '{}'", targetRef);
if (service.getClient().getServiceVersion().compareTo(ODataServiceVersion.V30) >= 1) {
final ODataReferenceAddingRequest req =
((org.apache.olingo.client.api.v4.EdmEnabledODataClient) service.getClient()).getCUDRequestFactory().
getReferenceAddingRequest(source, targetRef);
req.setPrefer(new ODataPreferences(service.getClient().getServiceVersion()).returnContent());
if (StringUtils.isNotBlank(handler.getETag())) {
req.setIfMatch(handler.getETag());
}
changeset.addChange(req, handler);
return true;
}
return false;
}
private void queueUpdate(
final EntityInvocationHandler handler,
final URI uri,
@ -461,10 +509,10 @@ abstract class AbstractPersistenceManager implements PersistenceManager {
service.getClient().getServiceVersion().compareTo(ODataServiceVersion.V30) <= 0
? ((org.apache.olingo.client.api.v3.EdmEnabledODataClient) service.getClient()).getCUDRequestFactory().
getEntityUpdateRequest(uri,
org.apache.olingo.client.api.communication.request.cud.v3.UpdateType.PATCH, changes)
org.apache.olingo.client.api.communication.request.cud.v3.UpdateType.PATCH, changes)
: ((org.apache.olingo.client.api.v4.EdmEnabledODataClient) service.getClient()).getCUDRequestFactory().
getEntityUpdateRequest(uri,
org.apache.olingo.client.api.communication.request.cud.v4.UpdateType.PATCH, changes);
org.apache.olingo.client.api.communication.request.cud.v4.UpdateType.PATCH, changes);
req.setPrefer(new ODataPreferences(service.getClient().getServiceVersion()).returnContent());

View File

@ -37,6 +37,7 @@ import java.util.concurrent.Callable;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.olingo.client.api.uri.CommonURIBuilder;
import org.apache.olingo.client.api.uri.v4.URIBuilder;
import org.apache.olingo.client.core.uri.URIUtils;
import org.apache.olingo.commons.api.domain.CommonODataEntity;
import org.apache.olingo.commons.api.domain.CommonODataProperty;
@ -47,6 +48,7 @@ import org.apache.olingo.commons.api.domain.ODataLinked;
import org.apache.olingo.commons.api.domain.ODataValue;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
import org.apache.olingo.commons.api.edm.FullQualifiedName;
import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
import org.apache.olingo.ext.proxy.AbstractService;
import org.apache.olingo.ext.proxy.api.AbstractEntitySet;
import org.apache.olingo.ext.proxy.api.ComplexCollection;
@ -156,7 +158,9 @@ public abstract class AbstractStructuredInvocationHandler extends AbstractInvoca
@Override
public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
if ("expand".equals(method.getName()) || "select".equals(method.getName())) {
if ("expand".equals(method.getName())
|| "select".equals(method.getName())
|| "refs".equals(method.getName())) {
invokeSelfMethod(method, args);
return proxy;
} else if (isSelfMethod(method, args)) {
@ -238,7 +242,8 @@ public abstract class AbstractStructuredInvocationHandler extends AbstractInvoca
public void delete(final String name) {
if (baseURI != null) {
getContext().entityContext().addFurtherDeletes(
getClient().newURIBuilder(baseURI.toASCIIString()).appendPropertySegment(name).build());
getClient().newURIBuilder(baseURI.toASCIIString()).appendPropertySegment(name).appendValueSegment().
build());
}
}
@ -254,7 +259,8 @@ public abstract class AbstractStructuredInvocationHandler extends AbstractInvoca
entityContext.attach(handler, AttachedEntityStatus.DELETED);
}
} else if (baseURI != null) {
entityContext.addFurtherDeletes(baseURI);
entityContext.addFurtherDeletes(
getClient().newURIBuilder(baseURI.toASCIIString()).appendValueSegment().build());
}
}
@ -632,6 +638,12 @@ public abstract class AbstractStructuredInvocationHandler extends AbstractInvoca
this.uri.select(select);
}
public void refs() {
if (getClient().getServiceVersion().compareTo(ODataServiceVersion.V40) >= 0) {
((URIBuilder) this.uri).appendRefSegment();
}
}
public void clearQueryOptions() {
this.uri = baseURI == null ? null : getClient().newURIBuilder(baseURI.toASCIIString());
}

View File

@ -59,8 +59,8 @@ public class EntityCollectionInvocationHandler<T extends EntityType<?>>
|| "expand".equals(method.getName())
|| "select".equals(method.getName())
|| "nextPage".equals(method.getName())
|| "refs".equals(method.getName())
|| "execute".equals(method.getName())) {
invokeSelfMethod(method, args);
return proxy;
} else if (isSelfMethod(method, args)) {

View File

@ -508,6 +508,15 @@ public class EntityInvocationHandler extends AbstractStructuredInvocationHandler
return getEntity() == null ? null : getEntity().getProperty(name);
}
public String getEntityReferenceID() {
URI id = getEntity() == null ? null
: getClient().getServiceVersion().compareTo(ODataServiceVersion.V30) <= 0
? ((org.apache.olingo.commons.api.domain.v3.ODataEntity) getEntity()).getLink()
: ((org.apache.olingo.commons.api.domain.v4.ODataEntity) getEntity()).getId();
return id == null ? null : id.toASCIIString();
}
@Override
public String toString() {
return uuid.toString();

View File

@ -114,6 +114,13 @@ public class PrimitiveCollectionInvocationHandler<T extends Serializable>
resItems, null, Collections.<ODataAnnotation>emptyList());
}
public void delete() {
if (baseURI != null) {
getContext().entityContext().addFurtherDeletes(
getClient().newURIBuilder(baseURI.toASCIIString()).appendValueSegment().build());
}
}
@Override
public boolean equals(final Object obj) {
if (obj instanceof Proxy) {

View File

@ -41,6 +41,8 @@ public class EntityLinkDesc implements Serializable {
private final ODataLinkType type;
private final String reference;
public EntityLinkDesc(
final String sourceName,
final EntityInvocationHandler source,
@ -50,6 +52,7 @@ public class EntityLinkDesc implements Serializable {
this.source = source;
this.targets = target;
this.type = type;
this.reference = null;
}
public EntityLinkDesc(
@ -61,6 +64,18 @@ public class EntityLinkDesc implements Serializable {
this.source = source;
this.targets = Collections.<EntityInvocationHandler>singleton(target);
this.type = type;
this.reference = null;
}
public EntityLinkDesc(
final String sourceName,
final EntityInvocationHandler source,
final String targetRef) {
this.sourceName = sourceName;
this.source = source;
this.targets = null;
this.type = null;
this.reference = targetRef;
}
public String getSourceName() {
@ -79,6 +94,10 @@ public class EntityLinkDesc implements Serializable {
return type;
}
public String getReference() {
return reference;
}
/**
* {@inheritDoc }
*/

View File

@ -1365,6 +1365,17 @@ public class V4Services extends AbstractServices {
return xml.createResponse(null, null, null, Status.NO_CONTENT);
}
@POST
@Path("/Customers(1)/Orders/$ref")
public Response linkOrderViaRef(
@HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept,
@HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) final String contentType,
@QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format,
final String entity) {
return xml.createResponse(null, null, null, Status.NO_CONTENT);
}
@DELETE
@Path("/Products({productId})/Categories({categoryId})/$ref")
public Response deleteLinked(

View File

@ -0,0 +1,8 @@
{
"@odata.context": "http://localhost:${cargo.servlet.port}/stub/StaticService/V40/Static.svc/$metadata#$ref",
"value":
[
{"@odata.id": "http://localhost:${cargo.servlet.port}/stub/StaticService/V40/Static.svc/Orders(7)"},
{"@odata.id": "http://localhost:${cargo.servlet.port}/stub/StaticService/V40/Static.svc/Orders(8)"}
]
}

View File

@ -54,8 +54,10 @@ import org.apache.olingo.fit.proxy.v4.staticservice.microsoft.test.odata.service
import org.apache.olingo.fit.proxy.v4.staticservice.microsoft.test.odata.services.odatawcfservice.types.AddressCollection;
import org.apache.olingo.fit.proxy.v4.staticservice.microsoft.test.odata.services.odatawcfservice.types.Color;
import org.apache.olingo.fit.proxy.v4.staticservice.microsoft.test.odata.services.odatawcfservice.types.Customer;
import org.apache.olingo.fit.proxy.v4.staticservice.microsoft.test.odata.services.odatawcfservice.types.CustomerCollection;
import org.apache.olingo.fit.proxy.v4.staticservice.microsoft.test.odata.services.odatawcfservice.types.HomeAddress;
import org.apache.olingo.fit.proxy.v4.staticservice.microsoft.test.odata.services.odatawcfservice.types.Order;
import org.apache.olingo.fit.proxy.v4.staticservice.microsoft.test.odata.services.odatawcfservice.types.OrderCollection;
import org.apache.olingo.fit.proxy.v4.staticservice.microsoft.test.odata.services.odatawcfservice.types.Person;
import org.apache.olingo.fit.proxy.v4.staticservice.microsoft.test.odata.services.odatawcfservice.types.PersonCollection;
import org.apache.olingo.fit.proxy.v4.staticservice.microsoft.test.odata.services.odatawcfservice.types.Product;
@ -74,6 +76,46 @@ public class APIBasicDesignTestITCase extends AbstractTestITCase {
return container;
}
@Test
public void readEntitySet() {
final OrderCollection orders = container.getOrders().execute();
assertFalse(orders.isEmpty());
final CustomerCollection customers = container.getCustomers().
orderBy("PersonID").
select("FirstName", "LastName", "Orders").
expand("Orders").
execute();
assertEquals(2, customers.size());
for (Customer customer : customers) {
assertNotNull(customer.getFirstName());
assertNotNull(customer.getLastName());
}
}
@Test
public void readWithReferences() {
final Person person = container.getOrders().getByKey(8).getCustomerForOrder().refs().load();
assertEquals("http://localhost:9080/stub/StaticService/V40/Static.svc/Customers(PersonID=1)",
person.getEntityReferenceID());
final OrderCollection orders = container.getCustomers().getByKey(1).getOrders().refs().execute();
assertEquals("http://localhost:9080/stub/StaticService/V40/Static.svc/Orders(7)",
orders.iterator().next().getEntityReferenceID());
}
@Test
public void addViaReference() {
final Order order = container.getOrders().getByKey(8).load();
final OrderCollection orders = container.newEntityCollection(OrderCollection.class);
orders.addRef(order);
container.getCustomers().getByKey(1).setOrders(orders);
container.flush();
}
@Test
public void readAndCheckForPrimitive() {
final Customer customer = getContainer().getCustomers().getByKey(1);
@ -243,6 +285,42 @@ public class APIBasicDesignTestITCase extends AbstractTestITCase {
service.getContext().detachAll(); // avoid influences
}
@Test
public void deleteSingleProperty() {
container.getCustomers().getByKey(1).delete("City");
container.flush();
}
@Test
public void deleteComplex() {
container.getCustomers().getByKey(1).getHomeAddress().delete();
container.flush();
}
@Test
public void deleteCollection() {
container.getCustomers().getByKey(1).getEmails().delete();
container.flush();
}
@Test
public void deleteEdmStreamProperty() throws IOException {
// ---------------------------------------
// Instantiate Demo Service
// ---------------------------------------
final org.apache.olingo.fit.proxy.v4.demo.Service<EdmEnabledODataClient> dservice =
org.apache.olingo.fit.proxy.v4.demo.Service.getV4(testDemoServiceRootURL);
dservice.getClient().getConfiguration().setDefaultBatchAcceptFormat(ContentType.APPLICATION_OCTET_STREAM);
final DemoService dcontainer = dservice.getEntityContainer(DemoService.class);
assertNotNull(dcontainer);
dservice.getContext().detachAll();
// ---------------------------------------
dcontainer.getPersonDetails().getByKey(1).delete("Photo");
dcontainer.flush();
dservice.getContext().detachAll(); // avoid influences
}
@Test
public void updateComplexProperty() {
Address homeAddress = container.getCustomers().getByKey(1).getHomeAddress();
@ -327,7 +405,7 @@ public class APIBasicDesignTestITCase extends AbstractTestITCase {
// ---------------------------------------
org.apache.olingo.fit.proxy.v3.staticservice.Service<org.apache.olingo.client.api.v3.EdmEnabledODataClient> v3serv =
org.apache.olingo.fit.proxy.v3.staticservice.Service.getV3(
"http://localhost:9080/stub/StaticService/V30/Static.svc");
"http://localhost:9080/stub/StaticService/V30/Static.svc");
v3serv.getClient().getConfiguration().setDefaultBatchAcceptFormat(ContentType.APPLICATION_OCTET_STREAM);
final DefaultContainer v3cont = v3serv.getEntityContainer(DefaultContainer.class);
assertNotNull(v3cont);
@ -378,11 +456,32 @@ public class APIBasicDesignTestITCase extends AbstractTestITCase {
// container.getOrders().getByKey(1).getCustomerForOrder().getEmails().execute().isEmpty());
// Not supported by the test service BTW generates a single request as expected:
// <service root>/Orders(1)/CustomerForOrder/Emails
emails.add("fabio.martelli@tirasa.net");
container.getPeople().getByKey(1).setEmails(emails);
container.flush();
boolean found = false;
for (String email : container.getPeople().getByKey(1).getEmails().execute()) {
if (email.equals("fabio.martelli@tirasa.net")) {
found = true;
}
}
assertTrue(found);
getService().getContext().detachAll();
}
@Test
public void workingWithSingletons() {
assertNotNull(container.getCompany().getVipCustomer().load().getPersonID());
container.getCompany().setName("new name");
container.flush();
assertEquals("new name", container.getCompany().load().getName());
}
@Test
@ -424,7 +523,7 @@ public class APIBasicDesignTestITCase extends AbstractTestITCase {
final AddressCollection ac = container.newComplexCollection(AddressCollection.class);
final Person updated = container.getCustomers().getByKey(2).operations().
resetAddress(ac, 0).select("Name").expand("Orders").execute();
assertNotNull(person);
assertNotNull(updated);
}
@Test

View File

@ -62,7 +62,7 @@ public class EntityUpdateTestITCase extends AbstractTestITCase {
@Test
public void update() {
Person person = getContainer().getPeople().getByKey(1).load();
Person person = getContainer().getPeople().getByKey(1);
final Address address = person.getHomeAddress();
address.setCity("XXX");

View File

@ -32,4 +32,16 @@ public interface CUDRequestFactory extends CommonCUDRequestFactory<UpdateType> {
ODataEntityUpdateRequest<ODataSingleton> getSingletonUpdateRequest(
UpdateType type, ODataSingleton entity);
/**
* A successful POST request to a navigation property's references collection adds a relationship to an existing
* entity. The request body MUST contain a single entity reference that identifies the entity to be added. See the
* appropriate format document for details. On successful completion, the response MUST be 204 No Content and contain
* an empty body.
*
* @param <E> concrete ODataEntity implementation
* @param targetURI entity set URI.
* @param entity entity to be created.
* @return new ODataEntityCreateRequest instance.
*/
ODataReferenceAddingRequest getReferenceAddingRequest(URI targetURI, URI reference);
}

View File

@ -0,0 +1,30 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.olingo.client.api.communication.request.cud.v4;
import org.apache.olingo.client.api.communication.request.ODataBasicRequest;
import org.apache.olingo.client.api.communication.request.ODataBatchableRequest;
import org.apache.olingo.client.api.communication.response.v4.ODataReferenceAddingResponse;
/**
* This class implements an OData delete request.
*/
public interface ODataReferenceAddingRequest
extends ODataBasicRequest<ODataReferenceAddingResponse>, ODataBatchableRequest {
}

View File

@ -0,0 +1,29 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.olingo.client.api.communication.response.v4;
import org.apache.olingo.client.api.communication.response.*;
/**
* This class implements the response to an OData delete request.
*
* @see org.apache.olingo.client.core.communication.request.cud.ODataDeleteRequest
*/
public interface ODataReferenceAddingResponse extends ODataResponse {
}

View File

@ -22,7 +22,9 @@ import java.net.URI;
import org.apache.olingo.client.api.communication.request.cud.ODataEntityUpdateRequest;
import org.apache.olingo.client.api.communication.request.cud.v4.CUDRequestFactory;
import org.apache.olingo.client.api.communication.request.cud.v4.ODataReferenceAddingRequest;
import org.apache.olingo.client.api.communication.request.cud.v4.UpdateType;
import org.apache.olingo.client.api.http.HttpMethod;
import org.apache.olingo.client.api.v4.ODataClient;
import org.apache.olingo.client.core.communication.request.cud.AbstractCUDRequestFactory;
import org.apache.olingo.commons.api.domain.v4.ODataSingleton;
@ -47,4 +49,8 @@ public class CUDRequestFactoryImpl extends AbstractCUDRequestFactory<UpdateType>
return super.getEntityUpdateRequest(targetURI, type, changes);
}
@Override
public ODataReferenceAddingRequest getReferenceAddingRequest(final URI targetURI, final URI reference) {
return new ODataReferenceAddingRequestImpl(client, HttpMethod.POST, targetURI, reference);
}
}

View File

@ -0,0 +1,92 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.olingo.client.core.communication.request.cud.v4;
import java.io.IOException;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.olingo.client.api.CommonODataClient;
import org.apache.olingo.client.api.http.HttpMethod;
import org.apache.olingo.client.core.communication.request.AbstractODataBasicRequest;
import org.apache.olingo.client.core.communication.response.AbstractODataResponse;
import org.apache.olingo.commons.api.format.ODataFormat;
import java.io.InputStream;
import java.net.URI;
import org.apache.commons.io.IOUtils;
import org.apache.olingo.client.api.communication.request.cud.v4.ODataReferenceAddingRequest;
import org.apache.olingo.client.api.communication.response.v4.ODataReferenceAddingResponse;
import org.apache.olingo.commons.api.Constants;
/**
* This class implements an OData delete request.
*/
public class ODataReferenceAddingRequestImpl extends AbstractODataBasicRequest<ODataReferenceAddingResponse>
implements ODataReferenceAddingRequest {
final URI reference;
ODataReferenceAddingRequestImpl(
final CommonODataClient<?> odataClient, final HttpMethod method, final URI uri, final URI reference) {
super(odataClient, method, uri);
this.reference = reference;
}
@Override
public ODataFormat getDefaultFormat() {
return odataClient.getConfiguration().getDefaultPubFormat();
}
/**
* No payload: null will be returned.
*/
@Override
protected InputStream getPayload() {
if (reference == null) {
return null;
} else {
try {
return IOUtils.toInputStream(reference.toASCIIString(), Constants.UTF8);
} catch (IOException e) {
LOG.warn("Error serializing reference {}", reference);
throw new IllegalArgumentException(e);
}
}
}
@Override
public ODataReferenceAddingResponse execute() {
return new ODataReferenceAddingResponseImpl(odataClient, httpClient, doExecute());
}
/**
* Response class about an ODataDeleteRequest.
*/
private class ODataReferenceAddingResponseImpl extends AbstractODataResponse implements ODataReferenceAddingResponse {
private ODataReferenceAddingResponseImpl(
final CommonODataClient<?> odataClient, final HttpClient httpClient, final HttpResponse res) {
super(odataClient, httpClient, res);
this.close();
}
}
}