You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by ch...@apache.org on 2016/03/01 14:04:05 UTC
olingo-odata4 git commit: [OLINGO-890] fix expanding to a contained
entity set results in an error
Repository: olingo-odata4
Updated Branches:
refs/heads/master 6c2676452 -> d566b186a
[OLINGO-890] fix expanding to a contained entity set results in an error
Signed-off-by: Christian Amend <ch...@sap.com>
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/d566b186
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/d566b186
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/d566b186
Branch: refs/heads/master
Commit: d566b186aeef42a20e02de0f176f054e27960733
Parents: 6c26764
Author: Frederik Zimmer <fr...@partake.de>
Authored: Mon Feb 22 18:21:11 2016 +0100
Committer: Christian Amend <ch...@sap.com>
Committed: Tue Mar 1 14:03:23 2016 +0100
----------------------------------------------------------------------
.../commons/AbstractInvocationHandler.java | 5 +-
.../AbstractStructuredInvocationHandler.java | 30 ++--
.../InlineEntitySetInvocationHandler.java | 163 +++++++++++++++++++
.../olingo/ext/proxy/utils/ProxyUtils.java | 53 ++++--
.../main/resources/V40/Accounts/103/entity.xml | 55 +++++++
.../Accounts/103/links/MyPaymentInstruments.xml | 24 +++
.../V40/MyPaymentInstruments/101901/entity.xml | 41 +++++
.../fit/proxy/APIBasicDesignTestITCase.java | 48 ++++--
8 files changed, 383 insertions(+), 36 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/d566b186/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractInvocationHandler.java
----------------------------------------------------------------------
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 ff4663e..d3aa3fc 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();
}
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/d566b186/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractStructuredInvocationHandler.java
----------------------------------------------------------------------
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 6f2527c..3a3020f 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());
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/d566b186/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/InlineEntitySetInvocationHandler.java
----------------------------------------------------------------------
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 0000000..53e9501
--- /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<T, ?, ?>>
+ extends AbstractEntityCollectionInvocationHandler<T, EC>
+ implements AbstractEntitySet<T, KEY, EC> {
+
+ private static final long serialVersionUID = 2629912294765040027L;
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ public static InlineEntitySetInvocationHandler getInstance(final Class<?> ref, final AbstractService<?> service,
+ final URI uri,
+ final List<Object> 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<T> 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 extends T> S getByKey(final KEY key, final Class<S> typeRef) throws IllegalArgumentException {
+ throw new UnsupportedOperationException("getByKey not supported on inline entity set");
+ }
+
+ @Override
+ public EC execute() {
+ return execute(collItemRef);
+ }
+
+ public <S extends T, SEC extends EntityCollection<S, ?, ?>> Future<SEC> executeAsync(final Class<SEC> collTypeRef) {
+ return service.getClient().getConfiguration().getExecutor().submit(new Callable<SEC>() {
+ @Override
+ public SEC call() throws Exception {
+ return execute(collTypeRef);
+ }
+ });
+ }
+
+ @SuppressWarnings("unchecked")
+ public <S extends T, SEC extends EntityCollection<S, ?, ?>> SEC execute(final Class<SEC> collTypeRef) {
+ final Class<S> ref = (Class<S>) ClassUtils.extractTypeArg(collTypeRef,
+ AbstractEntitySet.class, AbstractSingleton.class, EntityCollection.class);
+ final Class<S> oref = (Class<S>) 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<S> entityCollectionHandler = new EntityCollectionInvocationHandler<S>(
+ service, (Collection<S>) items, collTypeRef, baseURI, uri);
+
+ return (SEC) Proxy.newProxyInstance(
+ Thread.currentThread().getContextClassLoader(),
+ new Class<?>[] { collTypeRef },
+ entityCollectionHandler);
+ }
+
+ @Override
+ public Search<T, EC> createSearch() {
+ throw new UnsupportedOperationException("Search not supported on inline entity set");
+ }
+
+ @Override
+ public <S extends T, SEC extends EntityCollection<S, ?, ?>> Search<S, SEC> createSearch(final Class<SEC> 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 <S extends T> void delete(final S entity) {
+ throw new UnsupportedOperationException("Delete not supported on inline entity set");
+ }
+
+ @Override
+ public <S extends T> void delete(final Iterable<S> entities) {
+ throw new UnsupportedOperationException("Delete not supported on inline entity set");
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/d566b186/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/utils/ProxyUtils.java
----------------------------------------------------------------------
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 1800b1f..59a9537 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<Object> 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<Object> extractItems(final AbstractService<?> service, final Class<?> typeRef,
+ final ClientEntitySet entitySet, final URI uri, final boolean checkInTheContext) {
final List<Object> items = new ArrayList<Object>();
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<Object> 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(
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/d566b186/fit/src/main/resources/V40/Accounts/103/entity.xml
----------------------------------------------------------------------
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 0000000..bfa67ff
--- /dev/null
+++ b/fit/src/main/resources/V40/Accounts/103/entity.xml
@@ -0,0 +1,55 @@
+<?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/$entity">
+ <id>http://localhost:${tomcat.servlet.port}/stub/StaticService/V40/Static.svc/Accounts(103)</id>
+ <category term="#Microsoft.Test.OData.Services.ODataWCFService.Account" scheme="http://docs.oasis-open.org/odata/ns/scheme"/>
+ <link rel="edit" href="http://localhost:${tomcat.servlet.port}/stub/StaticService/V40/Static.svc/Accounts(103)"/>
+ <link rel="http://docs.oasis-open.org/odata/ns/related/MyGiftCard" type="application/atom+xml;type=entry" title="MyGiftCard" href="http://localhost:${tomcat.servlet.port}/stub/StaticService/V40/Static.svc/Accounts(103)/MyGiftCard"/>
+ <link rel="http://docs.oasis-open.org/odata/ns/related/MyPaymentInstruments" type="application/atom+xml;type=feed" title="MyPaymentInstruments" href="http://localhost:${tomcat.servlet.port}/stub/StaticService/V40/Static.svc/Accounts(103)/MyPaymentInstruments"/>
+ <link rel="http://docs.oasis-open.org/odata/ns/related/ActiveSubscriptions" type="application/atom+xml;type=feed" title="ActiveSubscriptions" href="http://localhost:${tomcat.servlet.port}/stub/StaticService/V40/Static.svc/Accounts(103)/ActiveSubscriptions"/>
+ <link rel="http://docs.oasis-open.org/odata/ns/related/AvailableSubscriptionTemplatess" type="application/atom+xml;type=feed" title="AvailableSubscriptionTemplatess" href="http://localhost:${tomcat.servlet.port}/stub/StaticService/V40/Static.svc/Accounts(103)/AvailableSubscriptionTemplatess"/>
+ <title/>
+ <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>
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/d566b186/fit/src/main/resources/V40/Accounts/103/links/MyPaymentInstruments.xml
----------------------------------------------------------------------
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 0000000..953bf62
--- /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
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/d566b186/fit/src/main/resources/V40/MyPaymentInstruments/101901/entity.xml
----------------------------------------------------------------------
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 0000000..fa6a14a
--- /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
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/d566b186/fit/src/test/java/org/apache/olingo/fit/proxy/APIBasicDesignTestITCase.java
----------------------------------------------------------------------
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 a66192b..d395268 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() {