diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractInvocationHandler.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractInvocationHandler.java index ff4663e3f..d3aa3fca5 100644 --- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractInvocationHandler.java +++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractInvocationHandler.java @@ -20,6 +20,7 @@ package org.apache.olingo.ext.proxy.commons; import java.lang.annotation.Annotation; import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.lang.reflect.UndeclaredThrowableException; @@ -31,9 +32,9 @@ import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apache.commons.lang3.builder.ReflectionToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.olingo.client.api.EdmEnabledODataClient; -import org.apache.olingo.client.api.uri.URIBuilder; import org.apache.olingo.client.api.domain.ClientEntity; import org.apache.olingo.client.api.domain.ClientValue; +import org.apache.olingo.client.api.uri.URIBuilder; import org.apache.olingo.commons.api.edm.FullQualifiedName; import org.apache.olingo.ext.proxy.AbstractService; import org.apache.olingo.ext.proxy.api.ComplexType; @@ -89,6 +90,8 @@ abstract class AbstractInvocationHandler implements InvocationHandler { return getClass().getMethod(method.getName(), method.getParameterTypes()).invoke(this, args); } catch (UndeclaredThrowableException e) { throw e.getCause(); + } catch(InvocationTargetException e) { + throw e.getTargetException(); } } diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractStructuredInvocationHandler.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractStructuredInvocationHandler.java index 6f2527c8f..3a3020f84 100644 --- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractStructuredInvocationHandler.java +++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractStructuredInvocationHandler.java @@ -38,9 +38,6 @@ import java.util.concurrent.Callable; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.olingo.client.api.uri.QueryOption; -import org.apache.olingo.client.api.uri.URIBuilder; -import org.apache.olingo.client.core.uri.URIUtils; import org.apache.olingo.client.api.domain.ClientEntity; import org.apache.olingo.client.api.domain.ClientInlineEntity; import org.apache.olingo.client.api.domain.ClientInlineEntitySet; @@ -48,6 +45,9 @@ import org.apache.olingo.client.api.domain.ClientLink; import org.apache.olingo.client.api.domain.ClientLinked; import org.apache.olingo.client.api.domain.ClientProperty; import org.apache.olingo.client.api.domain.ClientValue; +import org.apache.olingo.client.api.uri.QueryOption; +import org.apache.olingo.client.api.uri.URIBuilder; +import org.apache.olingo.client.core.uri.URIUtils; import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind; import org.apache.olingo.commons.api.edm.FullQualifiedName; import org.apache.olingo.ext.proxy.AbstractService; @@ -457,15 +457,21 @@ public abstract class AbstractStructuredInvocationHandler extends AbstractInvoca null, false); } else if (link instanceof ClientInlineEntitySet) { - // return entity set - navPropValue = ProxyUtils.getEntityCollectionProxy( - service, - collItemType, - type, - targetEntitySetURI, - ((ClientInlineEntitySet) link).getEntitySet(), - targetEntitySetURI, - false); + if (AbstractEntitySet.class.isAssignableFrom(type)) { + navPropValue = + ProxyUtils.getEntitySetProxy(service, type, ((ClientInlineEntitySet) link).getEntitySet(), + targetEntitySetURI, false); + } else { + // return entity set + navPropValue = ProxyUtils.getEntityCollectionProxy( + service, + collItemType, + type, + targetEntitySetURI, + ((ClientInlineEntitySet) link).getEntitySet(), + targetEntitySetURI, + false); + } } else { // navigate final URI targetURI = URIUtils.getURI(getEntityHandler().getEntityURI(), property.name()); diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/InlineEntitySetInvocationHandler.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/InlineEntitySetInvocationHandler.java new file mode 100644 index 000000000..53e950176 --- /dev/null +++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/InlineEntitySetInvocationHandler.java @@ -0,0 +1,163 @@ +/* + * 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.ext.proxy.commons; + +import java.io.Serializable; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.net.URI; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.Future; + +import org.apache.olingo.client.api.uri.URIBuilder; +import org.apache.olingo.commons.api.edm.FullQualifiedName; +import org.apache.olingo.ext.proxy.AbstractService; +import org.apache.olingo.ext.proxy.api.AbstractEntitySet; +import org.apache.olingo.ext.proxy.api.AbstractSingleton; +import org.apache.olingo.ext.proxy.api.EntityCollection; +import org.apache.olingo.ext.proxy.api.EntityType; +import org.apache.olingo.ext.proxy.api.Search; +import org.apache.olingo.ext.proxy.utils.ClassUtils; + +public class InlineEntitySetInvocationHandler< + T extends EntityType, KEY extends Serializable, EC extends EntityCollection> + extends AbstractEntityCollectionInvocationHandler + implements AbstractEntitySet { + + private static final long serialVersionUID = 2629912294765040027L; + + @SuppressWarnings({ "rawtypes", "unchecked" }) + public static InlineEntitySetInvocationHandler getInstance(final Class ref, final AbstractService service, + final URI uri, + final List items) { + return new InlineEntitySetInvocationHandler(ref, service, service.getClient().newURIBuilder(uri.toASCIIString()), + items); + } + + protected InlineEntitySetInvocationHandler( + final Class ref, + final AbstractService service, + final URIBuilder uri, + final Collection items) { + + super(ref, service, uri); + + this.items = items; + } + + @Override + public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { + if ("filter".equals(method.getName()) + || "orderBy".equals(method.getName()) + || "top".equals(method.getName()) + || "skip".equals(method.getName()) + || "expand".equals(method.getName()) + || "select".equals(method.getName())) { + + invokeSelfMethod(method, args); + return proxy; + } else if (isSelfMethod(method)) { + return invokeSelfMethod(method, args); + } else { + throw new NoSuchMethodException(method.getName()); + } + } + + @Override + public Long count() { + return Long.valueOf(size()); + } + + @Override + public Boolean exists(final KEY key) throws IllegalArgumentException { + throw new UnsupportedOperationException("exists not supported on inline entity set"); + } + + @Override + public T getByKey(final KEY key) throws IllegalArgumentException { + return getByKey(key, itemRef); + } + + @Override + public S getByKey(final KEY key, final Class typeRef) throws IllegalArgumentException { + throw new UnsupportedOperationException("getByKey not supported on inline entity set"); + } + + @Override + public EC execute() { + return execute(collItemRef); + } + + public > Future executeAsync(final Class collTypeRef) { + return service.getClient().getConfiguration().getExecutor().submit(new Callable() { + @Override + public SEC call() throws Exception { + return execute(collTypeRef); + } + }); + } + + @SuppressWarnings("unchecked") + public > SEC execute(final Class collTypeRef) { + final Class ref = (Class) ClassUtils.extractTypeArg(collTypeRef, + AbstractEntitySet.class, AbstractSingleton.class, EntityCollection.class); + final Class oref = (Class) ClassUtils.extractTypeArg(collItemRef, + AbstractEntitySet.class, AbstractSingleton.class, EntityCollection.class); + + if (!oref.equals(ref)) { + uri.appendDerivedEntityTypeSegment(new FullQualifiedName( + ClassUtils.getNamespace(ref), ClassUtils.getEntityTypeName(ref)).toString()); + } + + final EntityCollectionInvocationHandler entityCollectionHandler = new EntityCollectionInvocationHandler( + service, (Collection) items, collTypeRef, baseURI, uri); + + return (SEC) Proxy.newProxyInstance( + Thread.currentThread().getContextClassLoader(), + new Class[] { collTypeRef }, + entityCollectionHandler); + } + + @Override + public Search createSearch() { + throw new UnsupportedOperationException("Search not supported on inline entity set"); + } + + @Override + public > Search createSearch(final Class reference) { + throw new UnsupportedOperationException("Search not supported on inline entity set"); + } + + @Override + public void delete(final KEY key) throws IllegalArgumentException { + throw new UnsupportedOperationException("Delete not supported on inline entity set"); + } + + @Override + public void delete(final S entity) { + throw new UnsupportedOperationException("Delete not supported on inline entity set"); + } + + @Override + public void delete(final Iterable entities) { + throw new UnsupportedOperationException("Delete not supported on inline entity set"); + } +} diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/utils/ProxyUtils.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/utils/ProxyUtils.java index 1800b1fc6..59a9537d3 100644 --- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/utils/ProxyUtils.java +++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/utils/ProxyUtils.java @@ -21,28 +21,42 @@ import java.util.ArrayList; import java.util.List; import org.apache.commons.lang3.StringUtils; -import org.apache.olingo.client.api.uri.URIBuilder; import org.apache.olingo.client.api.domain.ClientEntity; import org.apache.olingo.client.api.domain.ClientEntitySet; import org.apache.olingo.client.api.domain.ClientValue; +import org.apache.olingo.client.api.uri.URIBuilder; import org.apache.olingo.ext.proxy.AbstractService; +import org.apache.olingo.ext.proxy.api.AbstractEntitySet; +import org.apache.olingo.ext.proxy.api.AbstractSingleton; import org.apache.olingo.ext.proxy.commons.ComplexInvocationHandler; import org.apache.olingo.ext.proxy.commons.EntityCollectionInvocationHandler; import org.apache.olingo.ext.proxy.commons.EntityInvocationHandler; import org.apache.olingo.ext.proxy.commons.EntitySetInvocationHandler; +import org.apache.olingo.ext.proxy.commons.InlineEntitySetInvocationHandler; public class ProxyUtils { - @SuppressWarnings({"unchecked", "rawtypes"}) + @SuppressWarnings({ "unchecked", "rawtypes" }) public static Object getEntityCollectionProxy( - final AbstractService service, - final Class typeRef, - final Class typeCollectionRef, - final URI targetEntitySetURI, - final ClientEntitySet entitySet, - final URI uri, - final boolean checkInTheContext) { + final AbstractService service, + final Class typeRef, + final Class typeCollectionRef, + final URI targetEntitySetURI, + final ClientEntitySet entitySet, + final URI uri, + final boolean checkInTheContext) { + final List items = extractItems(service, typeRef, entitySet, uri, checkInTheContext); + + return Proxy.newProxyInstance( + Thread.currentThread().getContextClassLoader(), + new Class[] { typeCollectionRef }, + new EntityCollectionInvocationHandler(service, items, typeCollectionRef, targetEntitySetURI, + uri == null ? null : service.getClient().newURIBuilder(uri.toASCIIString()))); + } + + private static List extractItems(final AbstractService service, final Class typeRef, + final ClientEntitySet entitySet, final URI uri, final boolean checkInTheContext) { final List items = new ArrayList(); if (entitySet != null) { @@ -50,12 +64,25 @@ public class ProxyUtils { items.add(getEntityProxy(service, entityFromSet, uri, typeRef, null, checkInTheContext)); } } + return items; + } + + public static Object getEntitySetProxy( + final AbstractService service, + final Class typeRef, + final ClientEntitySet entitySet, + final URI uri, + final boolean checkInTheContext) { + + final Class entityTypeRef = ClassUtils.extractTypeArg(typeRef, AbstractEntitySet.class, + AbstractSingleton.class); + + final List items = extractItems(service, entityTypeRef, entitySet, uri, checkInTheContext); return Proxy.newProxyInstance( - Thread.currentThread().getContextClassLoader(), - new Class[] {typeCollectionRef}, - new EntityCollectionInvocationHandler(service, items, typeCollectionRef, targetEntitySetURI, - uri == null ? null : service.getClient().newURIBuilder(uri.toASCIIString()))); + Thread.currentThread().getContextClassLoader(), + new Class[] { typeRef }, + InlineEntitySetInvocationHandler.getInstance(typeRef, service, uri, items)); } public static Object getEntitySetProxy( diff --git a/fit/src/main/resources/V40/Accounts/103/entity.xml b/fit/src/main/resources/V40/Accounts/103/entity.xml new file mode 100644 index 000000000..bfa67ffde --- /dev/null +++ b/fit/src/main/resources/V40/Accounts/103/entity.xml @@ -0,0 +1,55 @@ + + + + http://localhost:${tomcat.servlet.port}/stub/StaticService/V40/Static.svc/Accounts(103) + + + + + + + + <updated>2014-04-14T12:45:00Z</updated> + <author> + <name/> + </author> + <m:action metadata="http://localhost:${tomcat.servlet.port}/stub/StaticService/V40/Static.svc/$metadata#Microsoft.Test.OData.Services.ODataWCFService.RefreshDefaultPI" + title="Microsoft.Test.OData.Services.ODataWCFService.RefreshDefaultPI" + target="http://localhost:${tomcat.servlet.port}/stub/StaticService/V40/Static.svc/Accounts(103)/Microsoft.Test.OData.Services.ODataWCFService.RefreshDefaultPI"/> + <m:action metadata="http://localhost:${tomcat.servlet.port}/stub/StaticService/V40/Static.svc/$metadata#Microsoft.Test.OData.Services.ODataWCFService.GetDefaultPI" + title="Microsoft.Test.OData.Services.ODataWCFService.GetDefaultPI" + target="http://localhost:${tomcat.servlet.port}/stub/StaticService/V40/Static.svc/Accounts(103)/Microsoft.Test.OData.Services.ODataWCFService.GetDefaultPI"/> + <m:action metadata="http://localhost:${tomcat.servlet.port}/stub/StaticService/V40/Static.svc/$metadata#Microsoft.Test.OData.Services.ODataWCFService.GetAccountInfo" + title="Microsoft.Test.OData.Services.ODataWCFService.GetAccountInfo" + target="http://localhost:${tomcat.servlet.port}/stub/StaticService/V40/Static.svc/Accounts(103)/Microsoft.Test.OData.Services.ODataWCFService.GetAccountInfo"/> + <content type="application/xml"> + <m:properties> + <d:AccountID m:type="Int32">103</d:AccountID> + <d:Country>US</d:Country> + <d:AccountInfo m:type="#Microsoft.Test.OData.Services.ODataWCFService.AccountInfo"> + <d:FirstName>Alex</d:FirstName> + <d:LastName>Green</d:LastName> + <d:MiddleName>Hood</d:MiddleName> + </d:AccountInfo> + </m:properties> + </content> +</entry> diff --git a/fit/src/main/resources/V40/Accounts/103/links/MyPaymentInstruments.xml b/fit/src/main/resources/V40/Accounts/103/links/MyPaymentInstruments.xml new file mode 100644 index 000000000..953bf62ea --- /dev/null +++ b/fit/src/main/resources/V40/Accounts/103/links/MyPaymentInstruments.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + + 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. + +--> +<links xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices"> + <uri>http://localhost:${tomcat.servlet.port}/stub/StaticService/V30/Static.svc/Accounts(103)/MyPaymentInstruments(101901)</uri> +</links> \ No newline at end of file diff --git a/fit/src/main/resources/V40/MyPaymentInstruments/101901/entity.xml b/fit/src/main/resources/V40/MyPaymentInstruments/101901/entity.xml new file mode 100644 index 000000000..fa6a14a39 --- /dev/null +++ b/fit/src/main/resources/V40/MyPaymentInstruments/101901/entity.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + + 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. + +--> +<entry xml:base="http://localhost:${tomcat.servlet.port}/stub/StaticService/V40/Static.svc/" xmlns="http://www.w3.org/2005/Atom" xmlns:d="http://docs.oasis-open.org/odata/ns/data" xmlns:m="http://docs.oasis-open.org/odata/ns/metadata" xmlns:georss="http://www.georss.org/georss" xmlns:gml="http://www.opengis.net/gml" m:context="http://localhost:${tomcat.servlet.port}/stub/StaticService/V40/Static.svc/$metadata#Accounts(101)/MyPaymentInstruments/$entity"> + <category term="#Microsoft.Test.OData.Services.ODataWCFService.PaymentInstrument" scheme="http://docs.oasis-open.org/odata/ns/scheme"/> + <link rel="edit" href="http://localhost:${tomcat.servlet.port}/stub/StaticService/V40/Static.svc/Accounts(101)/MyPaymentInstruments(101901)"/> + <link rel="http://docs.oasis-open.org/odata/ns/related/TheStoredPI" type="application/atom+xml;type=entry" title="TheStoredPI" href="http://localhost:${tomcat.servlet.port}/stub/StaticService/V40/Static.svc/Accounts(101)/MyPaymentInstruments(101901)/TheStoredPI"/> + <link rel="http://docs.oasis-open.org/odata/ns/related/BillingStatements" type="application/atom+xml;type=feed" title="BillingStatements" href="http://localhost:${tomcat.servlet.port}/stub/StaticService/V40/Static.svc/Accounts(101)/MyPaymentInstruments(101901)/BillingStatements"/> + <link rel="http://docs.oasis-open.org/odata/ns/related/BackupStoredPI" type="application/atom+xml;type=entry" title="BackupStoredPI" href="http://localhost:${tomcat.servlet.port}/stub/StaticService/V40/Static.svc/Accounts(101)/MyPaymentInstruments(101901)/BackupStoredPI"/> + <id/> + <title/> + <updated>2014-04-14T12:47:37Z</updated> + <author> + <name/> + </author> + <content type="application/xml"> + <m:properties> + <d:PaymentInstrumentID m:type="Int32">101901</d:PaymentInstrumentID> + <d:FriendlyName>101 first PI</d:FriendlyName> + <d:CreatedDate m:type="DateTimeOffset">2014-04-09T00:00:00Z</d:CreatedDate> + </m:properties> + </content> +</entry> \ No newline at end of file diff --git a/fit/src/test/java/org/apache/olingo/fit/proxy/APIBasicDesignTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/proxy/APIBasicDesignTestITCase.java index a66192ba5..d39526824 100644 --- a/fit/src/test/java/org/apache/olingo/fit/proxy/APIBasicDesignTestITCase.java +++ b/fit/src/test/java/org/apache/olingo/fit/proxy/APIBasicDesignTestITCase.java @@ -44,28 +44,31 @@ import org.apache.olingo.ext.proxy.commons.AbstractCollectionInvocationHandler; import org.apache.olingo.fit.proxy.demo.Service; import org.apache.olingo.fit.proxy.demo.odatademo.DemoService; import org.apache.olingo.fit.proxy.demo.odatademo.types.PersonDetail; +import org.apache.olingo.fit.proxy.staticservice.microsoft.test.odata.services.odatawcfservice.InMemoryEntities; +import org.apache.olingo.fit.proxy.staticservice.microsoft.test.odata.services.odatawcfservice.types.AccessLevel; +import org.apache.olingo.fit.proxy.staticservice.microsoft.test.odata.services.odatawcfservice.types.Account; +import org.apache.olingo.fit.proxy.staticservice.microsoft.test.odata.services.odatawcfservice.types.Account.MyPaymentInstruments; +import org.apache.olingo.fit.proxy.staticservice.microsoft.test.odata.services.odatawcfservice.types.Address; import org.apache.olingo.fit.proxy.staticservice.microsoft.test.odata.services.odatawcfservice.types.AddressCollection; import org.apache.olingo.fit.proxy.staticservice.microsoft.test.odata.services.odatawcfservice.types.Color; import org.apache.olingo.fit.proxy.staticservice.microsoft.test.odata.services.odatawcfservice.types.Customer; import org.apache.olingo.fit.proxy.staticservice.microsoft.test.odata.services.odatawcfservice.types.CustomerCollection; +import org.apache.olingo.fit.proxy.staticservice.microsoft.test.odata.services.odatawcfservice.types.HomeAddress; import org.apache.olingo.fit.proxy.staticservice.microsoft.test.odata.services.odatawcfservice.types.Order; +import org.apache.olingo.fit.proxy.staticservice.microsoft.test.odata.services.odatawcfservice.types.OrderCollection; +import org.apache.olingo.fit.proxy.staticservice.microsoft.test.odata.services.odatawcfservice.types.PaymentInstrument; +import org.apache.olingo.fit.proxy.staticservice.microsoft.test.odata.services.odatawcfservice.types.PaymentInstrumentCollection; +import org.apache.olingo.fit.proxy.staticservice.microsoft.test.odata.services.odatawcfservice.types.Person; +import org.apache.olingo.fit.proxy.staticservice.microsoft.test.odata.services.odatawcfservice.types.PersonCollection; import org.apache.olingo.fit.proxy.staticservice.microsoft.test.odata.services.odatawcfservice.types.PersonComposableInvoker; import org.apache.olingo.fit.proxy.staticservice.microsoft.test.odata.services.odatawcfservice.types.Product; import org.apache.olingo.fit.proxy.staticservice.microsoft.test.odata.services.odatawcfservice.types.ProductCollection; import org.apache.olingo.fit.proxy.staticservice.microsoft.test.odata.services.odatawcfservice.types .ProductCollectionComposableInvoker; -import org.apache.olingo.fit.proxy.staticservice.microsoft.test.odata.services.odatawcfservice.types - .ProductDetailCollectionComposableInvoker; -import org.apache.olingo.fit.proxy.staticservice.microsoft.test.odata.services.odatawcfservice.InMemoryEntities; -import org.apache.olingo.fit.proxy.staticservice.microsoft.test.odata.services.odatawcfservice.types.AccessLevel; -import org.apache.olingo.fit.proxy.staticservice.microsoft.test.odata.services.odatawcfservice.types.Address; -import org.apache.olingo.fit.proxy.staticservice.microsoft.test.odata.services.odatawcfservice.types.HomeAddress; -import org.apache.olingo.fit.proxy.staticservice.microsoft.test.odata.services.odatawcfservice.types.OrderCollection; -import org.apache.olingo.fit.proxy.staticservice.microsoft.test.odata.services.odatawcfservice.types.Person; -import org.apache.olingo.fit.proxy.staticservice.microsoft.test.odata.services.odatawcfservice.types.PersonCollection; import org.apache.olingo.fit.proxy.staticservice.microsoft.test.odata.services.odatawcfservice.types.ProductDetail; import org.apache.olingo.fit.proxy.staticservice.microsoft.test.odata.services.odatawcfservice.types.ProductDetailCollection; - +import org.apache.olingo.fit.proxy.staticservice.microsoft.test.odata.services.odatawcfservice.types + .ProductDetailCollectionComposableInvoker; // CHECKSTYLE:ON (Maven checkstyle) import org.junit.Test; @@ -96,6 +99,31 @@ public class APIBasicDesignTestITCase extends AbstractTestITCase { assertNotNull(customer.getLastName()); } } + + @Test + public void expandToContainedEntitySet() { + Account account = container.getAccounts().getByKey(103).expand("MyPaymentInstruments").load(); + assertNotNull(account); + assertNotNull(account.getAccountID()); + MyPaymentInstruments myPaymentInstruments = account.getMyPaymentInstruments(); + assertNotNull(myPaymentInstruments); + PaymentInstrument paymentInstrument = myPaymentInstruments.iterator().next(); + assertNotNull(paymentInstrument); + assertNotNull(paymentInstrument.getFriendlyName()); + + PaymentInstrumentCollection myPaymentInstrumentCol = myPaymentInstruments.execute(); + assertNotNull(myPaymentInstrumentCol); + assertFalse(myPaymentInstrumentCol.isEmpty()); + paymentInstrument = myPaymentInstrumentCol.iterator().next(); + assertNotNull(paymentInstrument); + assertNotNull(paymentInstrument.getFriendlyName()); + } + + @Test(expected = UnsupportedOperationException.class) + public void expandToContainedEntitySetWithUnsupportedOperation() { + Account account = container.getAccounts().getByKey(103).expand("MyPaymentInstruments").load(); + account.getMyPaymentInstruments().delete(101901); + } @Test public void readWithReferences() {