You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by il...@apache.org on 2014/05/22 13:22:28 UTC

[4/9] git commit: [OLINGO-260] Merge from master

[OLINGO-260] Merge from master


Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/1abd8e7e
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/1abd8e7e
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/1abd8e7e

Branch: refs/heads/master
Commit: 1abd8e7e30460ac3fb46762c95bf10d968a28502
Parents: e897cf2 f228204
Author: Francesco Chicchiriccò <--global>
Authored: Sun May 18 09:01:59 2014 +0200
Committer: Francesco Chicchiriccò <--global>
Committed: Sun May 18 09:01:59 2014 +0200

----------------------------------------------------------------------
 .../ext/proxy/api/annotations/EntitySet.java    |   5 +-
 .../api/annotations/NavigationProperty.java     |   2 +
 .../commons/AbstractInvocationHandler.java      |  37 +-
 .../AbstractStructuredInvocationHandler.java    | 304 ++++++++++++++++
 .../commons/AbstractTypeInvocationHandler.java  | 297 ---------------
 .../ComplexFactoryInvocationHandler.java        |  18 +-
 .../proxy/commons/ComplexInvocationHandler.java | 162 +++++++++
 .../commons/ComplexTypeInvocationHandler.java   | 162 ---------
 .../olingo/ext/proxy/commons/ContainerImpl.java |  75 ++--
 .../EntityContainerInvocationHandler.java       |   4 +-
 .../proxy/commons/EntityInvocationHandler.java  | 358 +++++++++++++++++++
 .../commons/EntitySetInvocationHandler.java     |  72 ++--
 .../commons/EntityTypeInvocationHandler.java    | 348 ------------------
 .../commons/OperationInvocationHandler.java     |   8 +-
 .../commons/SingletonInvocationHandler.java     |  12 +-
 .../ext/proxy/context/AttachedEntity.java       |   8 +-
 .../olingo/ext/proxy/context/EntityContext.java |  28 +-
 .../ext/proxy/context/EntityLinkDesc.java       |  20 +-
 .../olingo/ext/proxy/context/EntityUUID.java    |  15 +-
 .../olingo/ext/proxy/utils/CoreUtils.java       |  32 +-
 .../olingo/ext/pojogen/AbstractPOJOGenMojo.java |  29 ++
 .../olingo/ext/pojogen/AbstractUtility.java     |  39 +-
 .../ext/pojogen/NavPropertyContainsTarget.java  |  16 +-
 .../src/main/resources/containedEntitySet.vm    |  65 ++++
 .../src/main/resources/container.vm             |   1 -
 .../src/main/resources/entitySet.vm             |   2 +-
 .../src/main/resources/entityType.vm            |  18 +-
 .../src/main/resources/entityTypeKey.vm         |   2 +-
 .../src/main/resources/v30/complexType.vm       |   2 +-
 .../src/main/resources/v30/entitySet.vm         |  19 -
 .../src/main/resources/v40/complexType.vm       |   4 +-
 .../src/main/resources/v40/entitySet.vm         |  19 -
 .../org/apache/olingo/fit/AbstractServices.java |   1 -
 .../MyPaymentInstruments(101902).full.json      |  16 +
 .../101/links/MyPaymentInstruments(101902).xml  |  40 +++
 .../olingo/fit/proxy/v3/ContextTestITCase.java  |  90 ++---
 .../fit/proxy/v3/EntityRetrieveTestITCase.java  |   4 +-
 .../fit/proxy/v3/EntityUpdateTestITCase.java    |   4 +-
 .../olingo/fit/proxy/v4/AsyncTestITCase.java    |   2 +-
 .../fit/proxy/v4/DerivedTypeTestITCase.java     |  13 +-
 .../fit/proxy/v4/EntityCreateTestITCase.java    |  70 ++++
 .../fit/proxy/v4/EntityRetrieveTestITCase.java  |  14 +-
 .../fit/proxy/v4/EntityUpdateTestITCase.java    |  20 +-
 .../odata/services/opentypesservicev4/Row.java  |   2 +-
 .../services/opentypesservicev4/RowIndex.java   |   2 +-
 .../services/odatawcfservice/Accounts.java      |   4 +-
 .../odatawcfservice/ActiveSubscriptions.java    |  51 +++
 .../odata/services/odatawcfservice/Assets.java  |  51 +++
 .../odatawcfservice/BillingStatements.java      |  51 +++
 .../odata/services/odatawcfservice/Boss.java    |   1 -
 .../odata/services/odatawcfservice/Club.java    |  51 +++
 .../odata/services/odatawcfservice/Company.java |   1 -
 .../services/odatawcfservice/CreditRecords.java |  51 +++
 .../services/odatawcfservice/Customers.java     |   4 +-
 .../odatawcfservice/DefaultStoredPI.java        |   1 -
 .../services/odatawcfservice/Departments.java   |   4 +-
 .../services/odatawcfservice/Employees.java     |   4 +-
 .../odatawcfservice/InMemoryEntities.java       |  13 -
 .../services/odatawcfservice/LabourUnion.java   |   1 -
 .../services/odatawcfservice/MyGiftCard.java    |  51 +++
 .../odatawcfservice/MyPaymentInstruments.java   |  53 +++
 .../services/odatawcfservice/OrderDetails.java  |   4 +-
 .../odata/services/odatawcfservice/Orders.java  |   4 +-
 .../odata/services/odatawcfservice/People.java  |   4 +-
 .../odatawcfservice/ProductDetails.java         |   4 +-
 .../odatawcfservice/ProductReviews.java         |   4 +-
 .../services/odatawcfservice/Products.java      |   4 +-
 .../services/odatawcfservice/PublicCompany.java |   1 -
 .../services/odatawcfservice/StoredPIs.java     |   4 +-
 .../odatawcfservice/SubscriptionTemplates.java  |   4 +-
 .../services/odatawcfservice/VipCustomer.java   |   1 -
 .../services/odatawcfservice/package-info.java  |   1 -
 .../odatawcfservice/types/AccessLevel.java      |   1 -
 .../services/odatawcfservice/types/Account.java |  43 ++-
 .../types/AccountCollection.java                |   1 -
 .../odatawcfservice/types/AccountInfo.java      |   5 +-
 .../services/odatawcfservice/types/Address.java |   7 +-
 .../services/odatawcfservice/types/Asset.java   |   7 +-
 .../odatawcfservice/types/AssetCollection.java  |   1 -
 .../services/odatawcfservice/types/Club.java    |   5 +-
 .../odatawcfservice/types/ClubCollection.java   |   1 -
 .../services/odatawcfservice/types/Color.java   |   1 -
 .../services/odatawcfservice/types/Company.java |  43 ++-
 .../odatawcfservice/types/CompanyAddress.java   |   9 +-
 .../odatawcfservice/types/CompanyCategory.java  |   1 -
 .../types/CompanyCollection.java                |   1 -
 .../odatawcfservice/types/CreditCardPI.java     |  53 ++-
 .../types/CreditCardPICollection.java           |   1 -
 .../odatawcfservice/types/CreditRecord.java     |   9 +-
 .../types/CreditRecordCollection.java           |   1 -
 .../odatawcfservice/types/Customer.java         |  47 ++-
 .../types/CustomerCollection.java               |   1 -
 .../odatawcfservice/types/Department.java       |  15 +-
 .../types/DepartmentCollection.java             |   1 -
 .../odatawcfservice/types/Employee.java         |  37 +-
 .../types/EmployeeCollection.java               |   1 -
 .../odatawcfservice/types/GiftCard.java         |  11 +-
 .../types/GiftCardCollection.java               |   1 -
 .../odatawcfservice/types/HomeAddress.java      |   9 +-
 .../odatawcfservice/types/LabourUnion.java      |   5 +-
 .../types/LabourUnionCollection.java            |   1 -
 .../services/odatawcfservice/types/Order.java   |  33 +-
 .../odatawcfservice/types/OrderCollection.java  |   1 -
 .../odatawcfservice/types/OrderDetail.java      |  27 +-
 .../types/OrderDetailCollection.java            |   1 -
 .../odatawcfservice/types/OrderDetailKey.java   |   5 +-
 .../types/PaymentInstrument.java                |  33 +-
 .../types/PaymentInstrumentCollection.java      |   1 -
 .../services/odatawcfservice/types/Person.java  |  25 +-
 .../odatawcfservice/types/PersonCollection.java |   1 -
 .../services/odatawcfservice/types/Product.java |  27 +-
 .../types/ProductCollection.java                |   1 -
 .../odatawcfservice/types/ProductDetail.java    |  25 +-
 .../types/ProductDetailCollection.java          |   1 -
 .../odatawcfservice/types/ProductDetailKey.java |   5 +-
 .../odatawcfservice/types/ProductReview.java    |  13 +-
 .../types/ProductReviewCollection.java          |   1 -
 .../odatawcfservice/types/ProductReviewKey.java |   9 +-
 .../odatawcfservice/types/PublicCompany.java    |  71 ++--
 .../types/PublicCompanyCollection.java          |   1 -
 .../odatawcfservice/types/Statement.java        |   9 +-
 .../types/StatementCollection.java              |   1 -
 .../odatawcfservice/types/StoredPI.java         |   9 +-
 .../types/StoredPICollection.java               |   1 -
 .../odatawcfservice/types/Subscription.java     |  11 +-
 .../types/SubscriptionCollection.java           |   1 -
 .../odatawcfservice/types/package-info.java     |   1 -
 .../apache/olingo/fit/v4/AsyncTestITCase.java   |   2 +-
 .../olingo/fit/v4/EntityRetrieveTestITCase.java |   4 +-
 .../core/edm/primitivetype/EdmDuration.java     |   1 -
 130 files changed, 2029 insertions(+), 1499 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/1abd8e7e/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractInvocationHandler.java
----------------------------------------------------------------------
diff --cc ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractInvocationHandler.java
index e16c96e,e3a2bc9..cc7eb36
--- 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
@@@ -140,11 -146,11 +152,11 @@@ abstract class AbstractInvocationHandle
        handler.setETag(eTag);
      }
  
 -    if (checkInTheContext && EntityContainerFactory.getContext().entityContext().isAttached(handler)) {
 -      handler = EntityContainerFactory.getContext().entityContext().getEntity(handler.getUUID());
 +    if (checkInTheContext && getContext().entityContext().isAttached(handler)) {
 +      handler = getContext().entityContext().getEntity(handler.getUUID());
      }
  
-     return (T) Proxy.newProxyInstance(
+     return Proxy.newProxyInstance(
              Thread.currentThread().getContextClassLoader(),
              new Class<?>[] {type},
              handler);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/1abd8e7e/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractStructuredInvocationHandler.java
----------------------------------------------------------------------
diff --cc ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractStructuredInvocationHandler.java
index 0000000,2e6103e..8a1155a
mode 000000,100644..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
@@@ -1,0 -1,313 +1,304 @@@
+ /*
+  * 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.lang.reflect.InvocationHandler;
+ import java.lang.reflect.Method;
+ import java.lang.reflect.ParameterizedType;
+ import java.lang.reflect.Proxy;
+ import java.lang.reflect.Type;
+ import java.net.URI;
 -import java.util.Collection;
+ import java.util.Collections;
+ import org.apache.commons.lang3.ArrayUtils;
 -import org.apache.olingo.client.api.CommonEdmEnabledODataClient;
+ import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse;
+ import org.apache.olingo.client.core.uri.URIUtils;
+ import org.apache.olingo.commons.api.domain.CommonODataEntity;
+ import org.apache.olingo.commons.api.domain.ODataInlineEntity;
+ import org.apache.olingo.commons.api.domain.ODataInlineEntitySet;
+ import org.apache.olingo.commons.api.domain.ODataLink;
+ import org.apache.olingo.commons.api.domain.ODataLinked;
 -import org.apache.olingo.ext.proxy.EntityContainerFactory;
+ import org.apache.olingo.ext.proxy.api.AbstractEntityCollection;
+ import org.apache.olingo.ext.proxy.api.AbstractEntitySet;
+ import org.apache.olingo.ext.proxy.api.annotations.EntityType;
+ import org.apache.olingo.ext.proxy.api.annotations.NavigationProperty;
+ import org.apache.olingo.ext.proxy.api.annotations.Property;
+ import org.apache.olingo.ext.proxy.context.AttachedEntityStatus;
 -import org.apache.olingo.ext.proxy.context.EntityContext;
+ import org.apache.olingo.ext.proxy.utils.ClassUtils;
+ import org.slf4j.Logger;
+ import org.slf4j.LoggerFactory;
+ 
+ public abstract class AbstractStructuredInvocationHandler extends AbstractInvocationHandler {
+ 
+   private static final long serialVersionUID = 2629912294765040037L;
+ 
+   /**
+    * Logger.
+    */
+   protected static final Logger LOG = LoggerFactory.getLogger(AbstractStructuredInvocationHandler.class);
+ 
+   protected final Class<?> typeRef;
+ 
 -  protected final EntityContext entityContext = EntityContainerFactory.getContext().entityContext();
 -
+   protected EntityInvocationHandler entityHandler;
+ 
+   protected Object internal;
+ 
+   protected AbstractStructuredInvocationHandler(
 -          final CommonEdmEnabledODataClient<?> client,
+           final Class<?> typeRef,
+           final Object internal,
+           final EntityContainerInvocationHandler containerHandler) {
+ 
 -    super(client, containerHandler);
++    super(containerHandler);
+     this.internal = internal;
+     this.typeRef = typeRef;
+     this.entityHandler = EntityInvocationHandler.class.cast(this);
+   }
+ 
+   protected AbstractStructuredInvocationHandler(
 -          final CommonEdmEnabledODataClient<?> client,
+           final Class<?> typeRef,
+           final Object internal,
+           final EntityInvocationHandler entityHandler) {
+ 
 -    super(client, entityHandler == null ? null : entityHandler.containerHandler);
++    super(entityHandler == null ? null : entityHandler.containerHandler);
+     this.internal = internal;
+     this.typeRef = typeRef;
+     this.entityHandler = entityHandler;
+   }
+ 
+   public EntityInvocationHandler getEntityHandler() {
+     return entityHandler;
+   }
+ 
 -  public void setEntityHandler(EntityInvocationHandler entityHandler) {
++  public void setEntityHandler(final EntityInvocationHandler entityHandler) {
+     this.entityHandler = entityHandler;
+   }
+ 
+   public Class<?> getTypeRef() {
+     return typeRef;
+   }
+ 
+   @Override
+   public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
+     if (isSelfMethod(method, args)) {
+       return invokeSelfMethod(method, args);
+     } else if ("operations".equals(method.getName()) && ArrayUtils.isEmpty(args)) {
+       final Class<?> returnType = method.getReturnType();
+ 
+       return Proxy.newProxyInstance(
+               Thread.currentThread().getContextClassLoader(),
+               new Class<?>[] {returnType},
+               OperationInvocationHandler.getInstance(entityHandler));
+     } else if ("factory".equals(method.getName()) && ArrayUtils.isEmpty(args)) {
+       final Class<?> returnType = method.getReturnType();
+ 
+       return Proxy.newProxyInstance(
+               Thread.currentThread().getContextClassLoader(),
+               new Class<?>[] {returnType},
+               ComplexFactoryInvocationHandler.getInstance(entityHandler, this));
+     } else if (method.getName().startsWith("get")) {
+       // Assumption: for each getter will always exist a setter and viceversa.
+       // get method annotation and check if it exists as expected
+       final Object res;
+       final Method getter = typeRef.getMethod(method.getName());
+ 
+       final Property property = ClassUtils.getAnnotation(Property.class, getter);
+       if (property == null) {
+         final NavigationProperty navProp = ClassUtils.getAnnotation(NavigationProperty.class, getter);
+         if (navProp == null) {
+           throw new UnsupportedOperationException("Unsupported method " + method.getName());
+         } else {
+           // if the getter refers to a navigation property ... navigate and follow link if necessary
+           res = getNavigationPropertyValue(navProp, getter);
+         }
+       } else {
+         // if the getter refers to a property .... get property from wrapped entity
+         res = getPropertyValue(property, getter.getGenericReturnType());
+       }
+ 
+       // attach the current handler
+       attach();
+ 
+       return res;
+     } else if (method.getName().startsWith("set")) {
+       // get the corresponding getter method (see assumption above)
+       final String getterName = method.getName().replaceFirst("set", "get");
+       final Method getter = typeRef.getMethod(getterName);
+ 
+       final Property property = ClassUtils.getAnnotation(Property.class, getter);
+       if (property == null) {
+         final NavigationProperty navProp = ClassUtils.getAnnotation(NavigationProperty.class, getter);
+         if (navProp == null) {
+           throw new UnsupportedOperationException("Unsupported method " + method.getName());
+         } else {
+           // if the getter refers to a navigation property ... 
+           if (ArrayUtils.isEmpty(args) || args.length != 1) {
+             throw new IllegalArgumentException("Invalid argument");
+           }
+ 
+           setNavigationPropertyValue(navProp, args[0]);
+         }
+       } else {
+         setPropertyValue(property, args[0]);
+       }
+ 
+       return ClassUtils.returnVoid();
+     } else {
+       throw new NoSuchMethodException(method.getName());
+     }
+   }
+ 
+   protected void attach() {
 -    if (entityHandler != null && !entityContext.isAttached(entityHandler)) {
 -      entityContext.attach(entityHandler, AttachedEntityStatus.ATTACHED);
++    if (entityHandler != null && !getContext().entityContext().isAttached(entityHandler)) {
++      getContext().entityContext().attach(entityHandler, AttachedEntityStatus.ATTACHED);
+     }
+   }
+ 
+   protected void attach(final AttachedEntityStatus status) {
+     attach(status, true);
+   }
+ 
+   protected void attach(final AttachedEntityStatus status, final boolean override) {
 -    if (entityContext.isAttached(entityHandler)) {
++    if (getContext().entityContext().isAttached(entityHandler)) {
+       if (override) {
 -        entityContext.setStatus(entityHandler, status);
++        getContext().entityContext().setStatus(entityHandler, status);
+       }
+     } else {
 -      entityContext.attach(entityHandler, status);
++      getContext().entityContext().attach(entityHandler, status);
+     }
+   }
+ 
+   protected abstract Object getNavigationPropertyValue(final NavigationProperty property, final Method getter);
+ 
+   protected Object retrieveNavigationProperty(
+           final NavigationProperty property, final Method getter, final String serviceRoot) {
+ 
+     final Class<?> type = getter.getReturnType();
+     final Class<?> collItemType;
+     if (AbstractEntityCollection.class.isAssignableFrom(type)) {
+       final Type[] entityCollectionParams =
+               ((ParameterizedType) type.getGenericInterfaces()[0]).getActualTypeArguments();
+       collItemType = (Class<?>) entityCollectionParams[0];
+     } else {
+       collItemType = type;
+     }
+ 
+     final Object navPropValue;
+ 
+     final ODataLink link = ((ODataLinked) internal).getNavigationLink(property.name());
+     if (link instanceof ODataInlineEntity) {
+       // return entity
+       navPropValue = getEntityProxy(
+               null,
+               ((ODataInlineEntity) link).getEntity(),
+               property.targetContainer(),
 -              client.getURIBuilder(serviceRoot).appendEntitySetSegment(property.targetEntitySet()).build(),
++              getClient().getURIBuilder(serviceRoot).appendEntitySetSegment(property.targetEntitySet()).build(),
+               type,
+               false);
+     } else if (link instanceof ODataInlineEntitySet) {
+       // return entity set
+       navPropValue = getEntityCollectionProxy(
+               collItemType,
+               type,
+               property.targetContainer(),
+               ((ODataInlineEntitySet) link).getEntitySet(),
+               link.getLink(),
+               false);
+     } else {
+       // navigate
 -      final URI uri = URIUtils.getURI(containerHandler.getFactory().getServiceRoot(), link.getLink().toASCIIString());
++      final URI uri = URIUtils.getURI(getClient().getServiceRoot(), link.getLink().toASCIIString());
++
+       if (AbstractEntityCollection.class.isAssignableFrom(type)) {
+         navPropValue = getEntityCollectionProxy(
+                 collItemType,
+                 type,
+                 property.targetContainer(),
 -                client.getRetrieveRequestFactory().getEntitySetRequest(uri).execute().getBody(),
++                getClient().getRetrieveRequestFactory().getEntitySetRequest(uri).execute().getBody(),
+                 uri,
+                 true);
+       } else if (AbstractEntitySet.class.isAssignableFrom(type)) {
+         navPropValue = getEntitySetProxy(type, uri);
+       } else {
+         final ODataRetrieveResponse<CommonODataEntity> res =
 -                client.getRetrieveRequestFactory().getEntityRequest(uri).execute();
++                getClient().getRetrieveRequestFactory().getEntityRequest(uri).execute();
+ 
+         navPropValue = getEntityProxy(
+                 uri,
+                 res.getBody(),
+                 property.targetContainer(),
 -                client.getURIBuilder(serviceRoot).appendEntitySetSegment(property.targetEntitySet()).build(),
++                getClient().getURIBuilder(serviceRoot).appendEntitySetSegment(property.targetEntitySet()).build(),
+                 type,
+                 res.getETag(),
+                 true);
+       }
+     }
+ 
+     return navPropValue;
+   }
+ 
+   protected abstract Object getPropertyValue(final String name, final Type type);
+ 
+   private Object getPropertyValue(final Property property, final Type type) {
+     return getPropertyValue(property.name(), type);
+   }
+ 
+   public void addAdditionalProperty(final String name, final Object value) {
+     addPropertyChanges(name, value);
+     attach(AttachedEntityStatus.CHANGED);
+   }
+ 
+   public Object getAdditionalProperty(final String name) {
+     return getPropertyValue(name, null);
+   }
+ 
 -  public abstract Collection<String> getAdditionalPropertyNames();
 -
+   private void setNavigationPropertyValue(final NavigationProperty property, final Object value) {
+     // 1) attach source entity
 -    if (!entityContext.isAttached(entityHandler)) {
 -      entityContext.attach(entityHandler, AttachedEntityStatus.CHANGED);
++    if (!getContext().entityContext().isAttached(entityHandler)) {
++      getContext().entityContext().attach(entityHandler, AttachedEntityStatus.CHANGED);
+     }
+ 
+     // 2) attach the target entity handlers
+     for (Object link : AbstractEntityCollection.class.isAssignableFrom(value.getClass())
+             ? (AbstractEntityCollection) value : Collections.singleton(value)) {
+ 
+       final InvocationHandler etih = Proxy.getInvocationHandler(link);
+       if (!(etih instanceof EntityInvocationHandler)) {
+         throw new IllegalArgumentException("Invalid argument type");
+       }
+ 
+       final EntityInvocationHandler linkedHandler = (EntityInvocationHandler) etih;
+       if (!linkedHandler.getTypeRef().isAnnotationPresent(EntityType.class)) {
+         throw new IllegalArgumentException("Invalid argument type " + linkedHandler.getTypeRef().getSimpleName());
+       }
+ 
 -      if (!entityContext.isAttached(linkedHandler)) {
 -        entityContext.attach(linkedHandler, AttachedEntityStatus.LINKED);
++      if (!getContext().entityContext().isAttached(linkedHandler)) {
++        getContext().entityContext().attach(linkedHandler, AttachedEntityStatus.LINKED);
+       }
+     }
+ 
+     // 3) add links
+     addLinkChanges(property, value);
+   }
+ 
+   protected abstract void setPropertyValue(final Property property, final Object value);
+ 
+   protected abstract void addPropertyChanges(final String name, final Object value);
+ 
+   protected abstract void addLinkChanges(final NavigationProperty navProp, final Object value);
+ 
+   public abstract boolean isChanged();
+ }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/1abd8e7e/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ComplexFactoryInvocationHandler.java
----------------------------------------------------------------------
diff --cc ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ComplexFactoryInvocationHandler.java
index c20e476,74ea465..b9aacbf
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ComplexFactoryInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ComplexFactoryInvocationHandler.java
@@@ -28,38 -29,37 +28,38 @@@ class ComplexFactoryInvocationHandler e
  
    private static final long serialVersionUID = 2629912294765040027L;
  
-   private final EntityTypeInvocationHandler entityHandler;
+   private final EntityInvocationHandler entityHandler;
  
-   private final AbstractTypeInvocationHandler invokerHandler;
+   private final AbstractStructuredInvocationHandler invokerHandler;
  
    static ComplexFactoryInvocationHandler getInstance(
 -          final CommonEdmEnabledODataClient<?> client,
            final EntityContainerInvocationHandler containerHandler,
-           final EntityTypeInvocationHandler entityHandler,
-           final AbstractTypeInvocationHandler targetHandler) {
+           final EntityInvocationHandler entityHandler,
+           final AbstractStructuredInvocationHandler targetHandler) {
  
 -    return new ComplexFactoryInvocationHandler(client, containerHandler, entityHandler, targetHandler);
 +    return new ComplexFactoryInvocationHandler(containerHandler, entityHandler, targetHandler);
    }
  
    static ComplexFactoryInvocationHandler getInstance(
-           final EntityTypeInvocationHandler entityHandler,
-           final AbstractTypeInvocationHandler targetHandler) {
+           final EntityInvocationHandler entityHandler,
+           final AbstractStructuredInvocationHandler targetHandler) {
 +
      return new ComplexFactoryInvocationHandler(
 -            entityHandler == null ? null : entityHandler.containerHandler.client,
              targetHandler == null
 -            ? entityHandler == null ? null : entityHandler.containerHandler : targetHandler.containerHandler,
 +            ? entityHandler == null
 +            ? null
 +            : entityHandler.containerHandler
 +            : targetHandler.containerHandler,
              entityHandler,
              targetHandler);
    }
  
    private ComplexFactoryInvocationHandler(
 -          final CommonEdmEnabledODataClient<?> client,
            final EntityContainerInvocationHandler containerHandler,
-           final EntityTypeInvocationHandler entityHandler,
-           final AbstractTypeInvocationHandler targetHandler) {
+           final EntityInvocationHandler entityHandler,
+           final AbstractStructuredInvocationHandler targetHandler) {
  
 -    super(client, containerHandler);
 +    super(containerHandler);
      this.invokerHandler = targetHandler;
      this.entityHandler = entityHandler;
    }
@@@ -78,8 -78,7 +78,8 @@@
        return Proxy.newProxyInstance(
                Thread.currentThread().getContextClassLoader(),
                new Class<?>[] {method.getReturnType()},
-               ComplexTypeInvocationHandler.getInstance(
 -              ComplexInvocationHandler.getInstance(client, property.name(), method.getReturnType(), entityHandler));
++              ComplexInvocationHandler.getInstance(
 +                      getClient(), property.name(), method.getReturnType(), entityHandler));
      } else {
        throw new NoSuchMethodException(method.getName());
      }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/1abd8e7e/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ComplexInvocationHandler.java
----------------------------------------------------------------------
diff --cc ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ComplexInvocationHandler.java
index 0000000,72d42e8..32b82d4
mode 000000,100644..100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ComplexInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ComplexInvocationHandler.java
@@@ -1,0 -1,186 +1,162 @@@
+ /*
+  * 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.lang.annotation.Annotation;
+ import java.lang.reflect.Method;
+ import java.lang.reflect.Proxy;
+ import java.lang.reflect.Type;
+ import java.util.ArrayList;
+ import java.util.Collection;
 -import java.util.HashSet;
 -import java.util.Iterator;
 -import java.util.Set;
+ import org.apache.olingo.client.api.CommonEdmEnabledODataClient;
+ import org.apache.olingo.commons.api.domain.CommonODataProperty;
+ import org.apache.olingo.commons.api.domain.ODataComplexValue;
+ import org.apache.olingo.commons.api.domain.ODataLinked;
+ import org.apache.olingo.commons.api.edm.EdmElement;
+ import org.apache.olingo.commons.api.edm.FullQualifiedName;
+ import org.apache.olingo.commons.core.edm.EdmTypeInfo;
+ import org.apache.olingo.ext.proxy.api.annotations.ComplexType;
+ import org.apache.olingo.ext.proxy.api.annotations.NavigationProperty;
+ import org.apache.olingo.ext.proxy.api.annotations.Property;
+ import org.apache.olingo.ext.proxy.context.AttachedEntityStatus;
+ import org.apache.olingo.ext.proxy.utils.ClassUtils;
+ import org.apache.olingo.ext.proxy.utils.CoreUtils;
+ 
+ public class ComplexInvocationHandler extends AbstractStructuredInvocationHandler {
+ 
+   private static final long serialVersionUID = 2629912294765040037L;
+ 
+   public static ComplexInvocationHandler getInstance(
+           final CommonEdmEnabledODataClient<?> client,
+           final String propertyName,
+           final Class<?> reference,
+           final EntityInvocationHandler handler) {
+ 
+     final Class<?> complexTypeRef;
+     if (Collection.class.isAssignableFrom(reference)) {
+       complexTypeRef = ClassUtils.extractTypeArg(reference);
+     } else {
+       complexTypeRef = reference;
+     }
+ 
+     final ComplexType annotation = complexTypeRef.getAnnotation(ComplexType.class);
+     if (annotation == null) {
+       throw new IllegalArgumentException("Invalid complex type " + complexTypeRef);
+     }
+ 
+     final FullQualifiedName typeName =
+             new FullQualifiedName(ClassUtils.getNamespace(complexTypeRef), annotation.name());
+ 
+     final ODataComplexValue<? extends CommonODataProperty> complex =
+             client.getObjectFactory().newComplexValue(typeName.toString());
+ 
 -    return (ComplexInvocationHandler) ComplexInvocationHandler.getInstance(
 -            client, complex, complexTypeRef, handler);
++    return new ComplexInvocationHandler(client, complex, complexTypeRef, handler);
+   }
+ 
+   public static ComplexInvocationHandler getInstance(
+           final CommonEdmEnabledODataClient<?> client,
+           final ODataComplexValue<?> complex,
+           final Class<?> typeRef,
+           final EntityInvocationHandler handler) {
+ 
+     return new ComplexInvocationHandler(client, complex, typeRef, handler);
+   }
++  
++  private final CommonEdmEnabledODataClient<?> client;
+ 
+   public ComplexInvocationHandler(
+           final CommonEdmEnabledODataClient<?> client,
+           final ODataComplexValue<?> complex,
+           final Class<?> typeRef,
+           final EntityInvocationHandler handler) {
+ 
 -    super(client, typeRef, complex, handler);
++    super(typeRef, complex, handler);
++    this.client = client;
+   }
+ 
+   @SuppressWarnings("unchecked")
+   public ODataComplexValue<CommonODataProperty> getComplex() {
+     return (ODataComplexValue<CommonODataProperty>) this.internal;
+   }
+ 
+   @Override
+   protected Object getPropertyValue(final String name, final Type type) {
+     try {
+       return CoreUtils.getValueFromProperty(client, getComplex().get(name), type, entityHandler);
+     } catch (Exception e) {
+       throw new IllegalArgumentException("Error getting value for property '" + name + "'", e);
+     }
+   }
+ 
+   @Override
 -  public Collection<String> getAdditionalPropertyNames() {
 -    final Set<String> res = new HashSet<String>();
 -    final Set<String> propertyNames = new HashSet<String>();
 -    for (Method method : typeRef.getMethods()) {
 -      final Annotation ann = method.getAnnotation(Property.class);
 -      if (ann != null) {
 -        final String property = ((Property) ann).name();
 -        propertyNames.add(property);
 -      }
 -    }
 -
 -    for (final Iterator<? extends CommonODataProperty> itor = getComplex().iterator(); itor.hasNext();) {
 -      final CommonODataProperty property = itor.next();
 -      if (!propertyNames.contains(property.getName())) {
 -        res.add(property.getName());
 -      }
 -    }
 -
 -    return res;
 -  }
 -
 -  @Override
+   @SuppressWarnings("unchecked")
+   protected void setPropertyValue(final Property property, final Object value) {
+     final FullQualifiedName fqn =
+             new FullQualifiedName(ClassUtils.getNamespace(typeRef), typeRef.getAnnotation(ComplexType.class).name());
+ 
+     final EdmElement edmProperty = client.getCachedEdm().getComplexType(fqn).getProperty(property.name());
+ 
+     final Object toBeAdded;
+ 
+     if (value == null) {
+       toBeAdded = null;
+     } else if (Collection.class.isAssignableFrom(value.getClass())) {
+       toBeAdded = new ArrayList<Object>();
+       for (Object obj : (Collection) value) {
+         ((Collection) toBeAdded).add(obj instanceof Proxy ? Proxy.getInvocationHandler(obj) : obj);
+       }
+     } else if (value instanceof Proxy) {
+       toBeAdded = Proxy.getInvocationHandler(value);
+     } else {
+       toBeAdded = value;
+     }
+ 
+     final EdmTypeInfo type = new EdmTypeInfo.Builder().setEdm(client.getCachedEdm()).setTypeExpression(
+             edmProperty.isCollection() ? "Collection(" + property.type() + ")" : property.type()).build();
+ 
+     client.getBinder().add(getComplex(), CoreUtils.getODataProperty(client, property.name(), type, toBeAdded));
+ 
 -    if (entityHandler != null && !entityContext.isAttached(entityHandler)) {
 -      entityContext.attach(entityHandler, AttachedEntityStatus.CHANGED);
++    if (entityHandler != null && !getContext().entityContext().isAttached(entityHandler)) {
++      getContext().entityContext().attach(entityHandler, AttachedEntityStatus.CHANGED);
+     }
+   }
+ 
+   @Override
+   protected Object getNavigationPropertyValue(final NavigationProperty property, final Method getter) {
+     if (!(internal instanceof ODataLinked)) {
+       throw new UnsupportedOperationException("Internal object is not navigable");
+     }
+ 
 -    return retrieveNavigationProperty(property, getter, containerHandler.getFactory().getServiceRoot());
++    return retrieveNavigationProperty(property, getter, containerHandler.getFactory().getClient().getServiceRoot());
+   }
+ 
+   @Override
+   protected void addPropertyChanges(final String name, final Object value) {
+     // do nothing ....
+   }
+ 
+   @Override
+   protected void addLinkChanges(final NavigationProperty navProp, final Object value) {
+     // do nothing ....
+   }
+ 
+   @Override
+   public boolean isChanged() {
+     return entityHandler == null ? false : entityHandler.isChanged();
+   }
+ }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/1abd8e7e/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ContainerImpl.java
----------------------------------------------------------------------
diff --cc ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ContainerImpl.java
index 2879f5f,90a4d75..0b8b464
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ContainerImpl.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ContainerImpl.java
@@@ -187,9 -186,7 +186,8 @@@ class ContainerImpl implements Containe
  
      LOG.debug("Create '{}'", handler);
  
-     final CommonURIBuilder<?> uriBuilder = factory.getClient().getURIBuilder(factory.getClient().getServiceRoot()).
-             appendEntitySetSegment(handler.getEntitySetName());
-     changeset.addRequest(factory.getClient().getCUDRequestFactory().getEntityCreateRequest(uriBuilder.build(), entity));
 -    changeset.addRequest(client.getCUDRequestFactory().getEntityCreateRequest(handler.getEntitySetURI(), entity));
++    changeset.addRequest(
++            factory.getClient().getCUDRequestFactory().getEntityCreateRequest(handler.getEntitySetURI(), entity));
    }
  
    private void batchUpdateMediaEntity(
@@@ -237,16 -233,18 +235,18 @@@
            final CommonODataEntity changes,
            final ODataChangeset changeset) {
  
-     LOG.debug("Update '{}'", changes.getEditLink());
+     LOG.debug("Update '{}'", handler.getEntityURI());
  
      final ODataEntityUpdateRequest<CommonODataEntity> req =
 -            client.getServiceVersion().compareTo(ODataServiceVersion.V30) <= 0
 -            ? ((org.apache.olingo.client.api.v3.EdmEnabledODataClient) client).getCUDRequestFactory().
 +            factory.getClient().getServiceVersion().compareTo(ODataServiceVersion.V30) <= 0
 +            ? ((org.apache.olingo.client.api.v3.EdmEnabledODataClient) factory.getClient()).getCUDRequestFactory().
-             getEntityUpdateRequest(org.apache.olingo.client.api.communication.request.cud.v3.UpdateType.PATCH, changes)
+             getEntityUpdateRequest(handler.getEntityURI(),
+                     org.apache.olingo.client.api.communication.request.cud.v3.UpdateType.PATCH, changes)
 -            : ((org.apache.olingo.client.api.v4.EdmEnabledODataClient) client).getCUDRequestFactory().
 +            : ((org.apache.olingo.client.api.v4.EdmEnabledODataClient) factory.getClient()).getCUDRequestFactory().
-             getEntityUpdateRequest(org.apache.olingo.client.api.communication.request.cud.v4.UpdateType.PATCH, changes);
+             getEntityUpdateRequest(handler.getEntityURI(),
+                     org.apache.olingo.client.api.communication.request.cud.v4.UpdateType.PATCH, changes);
  
 -    req.setPrefer(new ODataPreferences(client.getServiceVersion()).returnContent());
 +    req.setPrefer(new ODataPreferences(factory.getClient().getServiceVersion()).returnContent());
  
      if (StringUtils.isNotBlank(handler.getETag())) {
        req.setIfMatch(handler.getETag());
@@@ -264,15 -262,15 +264,15 @@@
      LOG.debug("Update '{}'", uri);
  
      final ODataEntityUpdateRequest<CommonODataEntity> req =
 -            client.getServiceVersion().compareTo(ODataServiceVersion.V30) <= 0
 -            ? ((org.apache.olingo.client.api.v3.EdmEnabledODataClient) client).getCUDRequestFactory().
 +            factory.getClient().getServiceVersion().compareTo(ODataServiceVersion.V30) <= 0
 +            ? ((org.apache.olingo.client.api.v3.EdmEnabledODataClient) factory.getClient()).getCUDRequestFactory().
-             getEntityUpdateRequest(
-                     uri, org.apache.olingo.client.api.communication.request.cud.v3.UpdateType.PATCH, changes)
+             getEntityUpdateRequest(uri,
+                     org.apache.olingo.client.api.communication.request.cud.v3.UpdateType.PATCH, changes)
 -            : ((org.apache.olingo.client.api.v4.EdmEnabledODataClient) client).getCUDRequestFactory().
 +            : ((org.apache.olingo.client.api.v4.EdmEnabledODataClient) factory.getClient()).getCUDRequestFactory().
-             getEntityUpdateRequest(
-                     uri, org.apache.olingo.client.api.communication.request.cud.v4.UpdateType.PATCH, changes);
+             getEntityUpdateRequest(uri,
+                     org.apache.olingo.client.api.communication.request.cud.v4.UpdateType.PATCH, changes);
  
 -    req.setPrefer(new ODataPreferences(client.getServiceVersion()).returnContent());
 +    req.setPrefer(new ODataPreferences(factory.getClient().getServiceVersion()).returnContent());
  
      if (StringUtils.isNotBlank(handler.getETag())) {
        req.setIfMatch(handler.getETag());
@@@ -286,10 -284,10 +286,10 @@@
            final CommonODataEntity entity,
            final ODataChangeset changeset) {
  
-     LOG.debug("Delete '{}'", entity.getEditLink());
+     final URI deleteURI = handler.getEntityURI() == null ? entity.getEditLink() : handler.getEntityURI();
+     LOG.debug("Delete '{}'", deleteURI);
  
-     final ODataDeleteRequest req = factory.getClient().getCUDRequestFactory().getDeleteRequest(
-             URIUtils.getURI(factory.getClient().getServiceRoot(), entity.getEditLink().toASCIIString()));
 -    final ODataDeleteRequest req = client.getCUDRequestFactory().getDeleteRequest(deleteURI);
++    final ODataDeleteRequest req = factory.getClient().getCUDRequestFactory().getDeleteRequest(deleteURI);
  
      if (StringUtils.isNotBlank(handler.getETag())) {
        req.setIfMatch(handler.getETag());
@@@ -324,16 -322,17 +324,15 @@@
                ? ODataLinkType.ENTITY_SET_NAVIGATION
                : ODataLinkType.ENTITY_NAVIGATION;
  
-       final Set<EntityTypeInvocationHandler> toBeLinked = new HashSet<EntityTypeInvocationHandler>();
+       final Set<EntityInvocationHandler> toBeLinked = new HashSet<EntityInvocationHandler>();
 -      final String serviceRoot = factory.getServiceRoot();
 +      final String serviceRoot = factory.getClient().getServiceRoot();
  
        for (Object proxy : type == ODataLinkType.ENTITY_SET_NAVIGATION
                ? (Collection) property.getValue() : Collections.singleton(property.getValue())) {
  
-         final EntityTypeInvocationHandler target =
-                 (EntityTypeInvocationHandler) Proxy.getInvocationHandler(proxy);
 -        final EntityInvocationHandler target =
 -                (EntityInvocationHandler) Proxy.getInvocationHandler(proxy);
++        final EntityInvocationHandler target = (EntityInvocationHandler) Proxy.getInvocationHandler(proxy);
  
 -        final AttachedEntityStatus status =
 -                EntityContainerFactory.getContext().entityContext().getStatus(target);
 +        final AttachedEntityStatus status = factory.getContext().entityContext().getStatus(target);
  
          final URI editLink = target.getEntity().getEditLink();
  
@@@ -411,9 -406,8 +409,8 @@@
  
      for (Map.Entry<String, InputStream> streamedChanges : handler.getStreamedPropertyChanges().entrySet()) {
        final URI targetURI = currentStatus == AttachedEntityStatus.NEW
-               ? URI.create("$" + startingPos)
-               : URIUtils.getURI(
+               ? URI.create("$" + startingPos) : URIUtils.getURI(
 -                      factory.getServiceRoot(),
 +                      factory.getClient().getServiceRoot(),
                        CoreUtils.getMediaEditLink(streamedChanges.getKey(), entity).toASCIIString());
  
        batchUpdateMediaResource(handler, targetURI, streamedChanges.getValue(), changeset);
@@@ -470,8 -465,8 +467,8 @@@
          sourceURI = URI.create("$" + sourcePos);
        }
  
-       for (EntityTypeInvocationHandler target : delayedUpdate.getTargets()) {
+       for (EntityInvocationHandler target : delayedUpdate.getTargets()) {
 -        status = EntityContainerFactory.getContext().entityContext().getStatus(target);
 +        status = factory.getContext().entityContext().getStatus(target);
  
          final URI targetURI;
          if (status == AttachedEntityStatus.CHANGED) {

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/1abd8e7e/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityContainerInvocationHandler.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/1abd8e7e/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityInvocationHandler.java
----------------------------------------------------------------------
diff --cc ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityInvocationHandler.java
index 0000000,361c140..c884f45
mode 000000,100644..100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityInvocationHandler.java
@@@ -1,0 -1,385 +1,358 @@@
+ /*
+  * 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.InputStream;
 -import java.lang.annotation.Annotation;
+ import java.lang.reflect.InvocationHandler;
+ import java.lang.reflect.Method;
+ import java.lang.reflect.Proxy;
+ import java.lang.reflect.Type;
+ import java.net.URI;
+ import java.util.Collection;
+ import java.util.Collections;
+ import java.util.HashMap;
 -import java.util.HashSet;
+ import java.util.Map;
 -import java.util.Set;
+ import org.apache.commons.io.IOUtils;
+ import org.apache.commons.lang3.StringUtils;
+ import org.apache.olingo.client.api.communication.request.retrieve.ODataMediaRequest;
+ import org.apache.olingo.client.core.uri.URIUtils;
+ import org.apache.olingo.commons.api.domain.CommonODataEntity;
+ import org.apache.olingo.commons.api.domain.CommonODataProperty;
+ import org.apache.olingo.commons.api.domain.ODataLinked;
+ import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
+ import org.apache.olingo.commons.api.format.ODataMediaFormat;
+ import org.apache.olingo.ext.proxy.api.annotations.EntityType;
+ import org.apache.olingo.ext.proxy.api.annotations.NavigationProperty;
+ import org.apache.olingo.ext.proxy.api.annotations.Property;
+ import org.apache.olingo.ext.proxy.context.AttachedEntityStatus;
+ import org.apache.olingo.ext.proxy.context.EntityUUID;
+ import org.apache.olingo.ext.proxy.utils.CoreUtils;
+ 
+ public class EntityInvocationHandler extends AbstractStructuredInvocationHandler {
+ 
+   private static final long serialVersionUID = 2629912294765040037L;
+ 
+   private final URI entityURI;
+ 
+   protected Map<String, Object> propertyChanges = new HashMap<String, Object>();
+ 
+   protected Map<NavigationProperty, Object> linkChanges = new HashMap<NavigationProperty, Object>();
+ 
+   protected int propertiesTag = 0;
+ 
+   protected int linksTag = 0;
+ 
+   private Map<String, InputStream> streamedPropertyChanges = new HashMap<String, InputStream>();
+ 
+   private InputStream stream;
+ 
+   private EntityUUID uuid;
+ 
+   static EntityInvocationHandler getInstance(
+           final URI entityURI,
+           final CommonODataEntity entity,
+           final EntitySetInvocationHandler<?, ?, ?> entitySet,
+           final Class<?> typeRef) {
+ 
+     return getInstance(
+             entityURI,
+             entity,
+             entitySet.getEntitySetURI(),
+             typeRef,
+             entitySet.containerHandler);
+   }
+ 
+   static EntityInvocationHandler getInstance(
+           final URI entityURI,
+           final CommonODataEntity entity,
+           final URI entitySetURI,
+           final Class<?> typeRef,
+           final EntityContainerInvocationHandler containerHandler) {
+ 
+     return new EntityInvocationHandler(entityURI, entity, entitySetURI, typeRef, containerHandler);
+   }
+ 
+   private EntityInvocationHandler(
+           final URI entityURI,
+           final CommonODataEntity entity,
+           final URI entitySetURI,
+           final Class<?> typeRef,
+           final EntityContainerInvocationHandler containerHandler) {
+ 
 -    super(containerHandler.getClient(), typeRef, (ODataLinked) entity, containerHandler);
++    super(typeRef, (ODataLinked) entity, containerHandler);
+ 
+     this.entityURI = entityURI;
+     this.internal = entity;
+     getEntity().setMediaEntity(typeRef.getAnnotation(EntityType.class).hasStream());
+ 
+     this.uuid = new EntityUUID(
+             containerHandler.getEntityContainerName(),
+             entitySetURI,
+             typeRef,
 -            CoreUtils.getKey(client, typeRef, entity));
++            CoreUtils.getKey(getClient(), this, typeRef, entity));
+   }
+ 
+   public void setEntity(final CommonODataEntity entity) {
+     this.internal = entity;
+     getEntity().setMediaEntity(typeRef.getAnnotation(EntityType.class).hasStream());
+ 
+     this.uuid = new EntityUUID(
+             getUUID().getContainerName(),
+             getUUID().getEntitySetURI(),
+             getUUID().getType(),
 -            CoreUtils.getKey(client, typeRef, entity));
++            CoreUtils.getKey(getClient(), this, typeRef, entity));
+ 
+     this.propertyChanges.clear();
+     this.linkChanges.clear();
+     this.streamedPropertyChanges.clear();
+     this.propertiesTag = 0;
+     this.linksTag = 0;
+   }
+ 
+   public EntityUUID getUUID() {
+     return uuid;
+   }
+ 
+   public String getEntityContainerName() {
+     return uuid.getContainerName();
+   }
+ 
+   public URI getEntitySetURI() {
+     return uuid.getEntitySetURI();
+   }
+ 
+   public final CommonODataEntity getEntity() {
+     return (CommonODataEntity) internal;
+   }
+ 
+   public URI getEntityURI() {
+     return entityURI;
+   }
+ 
+   /**
+    * Gets the current ETag defined into the wrapped entity.
+    *
+    * @return
+    */
+   public String getETag() {
+     return getEntity().getETag();
+   }
+ 
+   /**
+    * Overrides ETag value defined into the wrapped entity.
+    *
+    * @param eTag ETag.
+    */
+   public void setETag(final String eTag) {
+     getEntity().setETag(eTag);
+   }
+ 
+   public Map<String, Object> getPropertyChanges() {
+     return propertyChanges;
+   }
+ 
+   public Map<NavigationProperty, Object> getLinkChanges() {
+     return linkChanges;
+   }
+ 
+   private void updatePropertiesTag(final int checkpoint) {
+     if (checkpoint == propertiesTag) {
+       propertiesTag = propertyChanges.hashCode();
+     }
+   }
+ 
+   private void updateLinksTag(final int checkpoint) {
+     if (checkpoint == linksTag) {
+       linksTag = linkChanges.hashCode();
+     }
+   }
+ 
+   @Override
+   protected Object getPropertyValue(final String name, final Type type) {
+     try {
+       final CommonODataProperty property = getEntity().getProperty(name);
+ 
+       Object res;
+       if (propertyChanges.containsKey(name)) {
+         res = propertyChanges.get(name);
+       } else {
 -        res = CoreUtils.getValueFromProperty(client, property, type, this);
 -
++        res = CoreUtils.getValueFromProperty(getClient(), property, type, this);
+         if (res != null) {
+           addPropertyChanges(name, res);
+         }
+       }
+ 
+       return res;
+     } catch (Exception e) {
+       throw new IllegalArgumentException("Error getting value for property '" + name + "'", e);
+     }
+   }
+ 
+   @Override
 -  public Collection<String> getAdditionalPropertyNames() {
 -    final Set<String> res = new HashSet<String>(propertyChanges.keySet());
 -    final Set<String> propertyNames = new HashSet<String>();
 -    for (Method method : typeRef.getMethods()) {
 -      final Annotation ann = method.getAnnotation(Property.class);
 -      if (ann != null) {
 -        final String property = ((Property) ann).name();
 -        propertyNames.add(property);
 -
 -        // maybe someone could add a normal attribute to the additional set
 -        res.remove(property);
 -      }
 -    }
 -
 -    for (CommonODataProperty property : getEntity().getProperties()) {
 -      if (!propertyNames.contains(property.getName())) {
 -        res.add(property.getName());
 -      }
 -    }
 -
 -    return res;
 -  }
 -
 -  @Override
+   @SuppressWarnings("unchecked")
+   protected void setPropertyValue(final Property property, final Object value) {
+     if (property.type().equalsIgnoreCase(EdmPrimitiveTypeKind.Stream.toString())) {
+       setStreamedProperty(property, (InputStream) value);
+     } else {
+       addPropertyChanges(property.name(), value);
+ 
+       if (value != null) {
 -        final Collection<?> coll;
++        Collection<?> coll;
+         if (Collection.class.isAssignableFrom(value.getClass())) {
+           coll = Collection.class.cast(value);
+         } else {
+           coll = Collections.singleton(value);
+         }
+ 
+         for (Object item : coll) {
+           if (item instanceof Proxy) {
+             final InvocationHandler handler = Proxy.getInvocationHandler(item);
+             if ((handler instanceof ComplexInvocationHandler)
+                     && ((ComplexInvocationHandler) handler).getEntityHandler() == null) {
+               ((ComplexInvocationHandler) handler).setEntityHandler(this);
+             }
+           }
+         }
+       }
+     }
+ 
+     attach(AttachedEntityStatus.CHANGED);
+   }
+ 
+   @Override
+   public boolean isChanged() {
+     return this.linkChanges.hashCode() != this.linksTag
+             || this.propertyChanges.hashCode() != this.propertiesTag
+             || this.stream != null
+             || !this.streamedPropertyChanges.isEmpty();
+   }
+ 
+   public void setStream(final InputStream stream) {
+     if (typeRef.getAnnotation(EntityType.class).hasStream()) {
+       IOUtils.closeQuietly(this.stream);
+       this.stream = stream;
+       attach(AttachedEntityStatus.CHANGED);
+     }
+   }
+ 
+   public InputStream getStreamChanges() {
+     return this.stream;
+   }
+ 
+   public Map<String, InputStream> getStreamedPropertyChanges() {
+     return streamedPropertyChanges;
+   }
+ 
+   public InputStream getStream() {
+     final URI contentSource = getEntity().getMediaContentSource();
+ 
+     if (this.stream == null
+             && typeRef.getAnnotation(EntityType.class).hasStream()
+             && contentSource != null) {
+ 
+       final String contentType =
+               StringUtils.isBlank(getEntity().getMediaContentType()) ? "*/*" : getEntity().getMediaContentType();
+ 
 -      final ODataMediaRequest retrieveReq = client.getRetrieveRequestFactory().getMediaRequest(contentSource);
++      final ODataMediaRequest retrieveReq = getClient().getRetrieveRequestFactory().getMediaRequest(contentSource);
+       retrieveReq.setFormat(ODataMediaFormat.fromFormat(contentType));
+ 
+       this.stream = retrieveReq.execute().getBody();
+     }
+ 
+     return this.stream;
+   }
+ 
+   public Object getStreamedProperty(final Property property) {
+     InputStream res = streamedPropertyChanges.get(property.name());
+ 
+     try {
+       if (res == null) {
+         final URI link = URIUtils.getURI(
 -                containerHandler.getFactory().getServiceRoot(),
++                getClient().getServiceRoot(),
+                 CoreUtils.getMediaEditLink(property.name(), getEntity()).toASCIIString());
+ 
 -        final ODataMediaRequest req = client.getRetrieveRequestFactory().getMediaRequest(link);
++        final ODataMediaRequest req = getClient().getRetrieveRequestFactory().getMediaRequest(link);
+         res = req.execute().getBody();
+ 
+       }
+     } catch (Exception e) {
+       res = null;
+     }
+ 
+     return res;
+ 
+   }
+ 
+   private void setStreamedProperty(final Property property, final InputStream input) {
+     final Object obj = propertyChanges.get(property.name());
+     if (obj instanceof InputStream) {
+       IOUtils.closeQuietly((InputStream) obj);
+     }
+ 
+     streamedPropertyChanges.put(property.name(), input);
+   }
+ 
+   @Override
+   protected Object getNavigationPropertyValue(final NavigationProperty property, final Method getter) {
+     final Object navPropValue;
+ 
+     if (linkChanges.containsKey(property)) {
+       navPropValue = linkChanges.get(property);
+     } else {
 -      navPropValue = retrieveNavigationProperty(property, getter, containerHandler.getFactory().getServiceRoot());
++      navPropValue = retrieveNavigationProperty(
++              property, getter, containerHandler.getFactory().getClient().getServiceRoot());
+     }
+ 
+     if (navPropValue != null) {
+       addLinkChanges(property, navPropValue);
+     }
+ 
+     return navPropValue;
+   }
+ 
+   @Override
+   protected void addPropertyChanges(final String name, final Object value) {
+     final int checkpoint = propertyChanges.hashCode();
+     propertyChanges.put(name, value);
+     updatePropertiesTag(checkpoint);
+   }
+ 
+   @Override
+   protected void addLinkChanges(final NavigationProperty navProp, final Object value) {
+     final int checkpoint = linkChanges.hashCode();
+     linkChanges.put(navProp, value);
+     updateLinksTag(checkpoint);
+   }
+ 
+   @Override
+   public String toString() {
+     return uuid.toString();
+   }
+ 
+   @Override
+   public int hashCode() {
+     return uuid.hashCode();
+   }
+ 
+   @Override
+   public boolean equals(final Object obj) {
+     return obj instanceof EntityInvocationHandler
+             && ((EntityInvocationHandler) obj).getUUID().equals(uuid);
+   }
+ }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/1abd8e7e/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntitySetInvocationHandler.java
----------------------------------------------------------------------
diff --cc ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntitySetInvocationHandler.java
index bcb0fb9,6e70a0e..00861c5
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntitySetInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntitySetInvocationHandler.java
@@@ -84,20 -83,38 +82,38 @@@ class EntitySetInvocationHandler
  
    @SuppressWarnings({"rawtypes", "unchecked"})
    static EntitySetInvocationHandler getInstance(
-           final Class<?> ref, final EntityContainerInvocationHandler containerHandler) {
+           final Class<?> ref, final EntityContainerInvocationHandler containerHandler, final String entitySetName) {
+ 
+     final CommonURIBuilder<?> uriBuilder = containerHandler.getClient().
 -            getURIBuilder(containerHandler.getFactory().getServiceRoot());
++            getURIBuilder(containerHandler.getFactory().getClient().getServiceRoot());
  
-     return new EntitySetInvocationHandler(ref, containerHandler, (ref.getAnnotation(EntitySet.class)).name());
+     final StringBuilder entitySetSegment = new StringBuilder();
+     if (!containerHandler.isDefaultEntityContainer()) {
+       entitySetSegment.append(containerHandler.getEntityContainerName()).append('.');
+     }
+     entitySetSegment.append(entitySetName);
+ 
+     uriBuilder.appendEntitySetSegment(entitySetSegment.toString());
+ 
+     return new EntitySetInvocationHandler(ref, containerHandler, entitySetName, uriBuilder.build());
+   }
+ 
+   @SuppressWarnings({"rawtypes", "unchecked"})
+   static EntitySetInvocationHandler getInstance(
+           final Class<?> ref, final EntityContainerInvocationHandler containerHandler, final URI uri) {
+ 
+     return new EntitySetInvocationHandler(ref, containerHandler, (ref.getAnnotation(EntitySet.class)).name(), uri);
    }
  
    @SuppressWarnings("unchecked")
    protected EntitySetInvocationHandler(
            final Class<?> ref,
            final EntityContainerInvocationHandler containerHandler,
-           final String entitySetName) {
+           final String entitySetName,
+           final URI uri) {
  
 -    super(containerHandler.getClient(), containerHandler);
 +    super(containerHandler);
  
-     this.entitySetName = entitySetName;
      this.isSingleton = AbstractSingleton.class.isAssignableFrom(ref);
  
      final Type[] entitySetParams = ((ParameterizedType) ref.getGenericInterfaces()[0]).getActualTypeArguments();
@@@ -151,12 -155,12 +154,12 @@@
  
    @SuppressWarnings("unchecked")
    private <NE> NE newEntity(final Class<NE> reference) {
 -    final CommonODataEntity entity = client.getObjectFactory().newEntity(
 +    final CommonODataEntity entity = getClient().getObjectFactory().newEntity(
              new FullQualifiedName(containerHandler.getSchemaName(), ClassUtils.getEntityTypeName(reference)));
  
-     final EntityTypeInvocationHandler handler =
-             EntityTypeInvocationHandler.getInstance(entity, entitySetName, reference, containerHandler);
+     final EntityInvocationHandler handler =
+             EntityInvocationHandler.getInstance(null, entity, uri, reference, containerHandler);
 -    EntityContainerFactory.getContext().entityContext().attachNew(handler);
 +    getContext().entityContext().attachNew(handler);
  
      return (NE) Proxy.newProxyInstance(
              Thread.currentThread().getContextClassLoader(),
@@@ -229,10 -233,10 +232,10 @@@
        throw new IllegalArgumentException("Null key");
      }
  
-     final EntityUUID uuid = new EntityUUID(containerHandler.getEntityContainerName(), entitySetName, typeRef, key);
+     final EntityUUID uuid = new EntityUUID(containerHandler.getEntityContainerName(), uri, typeRef, key);
      LOG.debug("Ask for '{}({})'", typeRef.getSimpleName(), key);
  
-     EntityTypeInvocationHandler handler = getContext().entityContext().getEntity(uuid);
 -    EntityInvocationHandler handler = EntityContainerFactory.getContext().entityContext().getEntity(uuid);
++    EntityInvocationHandler handler = getContext().entityContext().getEntity(uuid);
  
      if (handler == null) {
        // not yet attached: search against the service
@@@ -259,12 -264,8 +262,12 @@@
            throw new IllegalArgumentException("Invalid " + typeRef.getSimpleName() + "(" + key + ")");
          }
  
-         handler = EntityTypeInvocationHandler.getInstance(entity, this, typeRef);
+         handler = EntityInvocationHandler.getInstance(uriBuilder.build(), entity, this, typeRef);
          handler.setETag(etag);
 +
 +        if (!key.equals(CoreUtils.getKey(getClient(), handler, typeRef, entity))) {
 +          throw new IllegalArgumentException("Invalid " + typeRef.getSimpleName() + "(" + key + ")");
 +        }
        } catch (Exception e) {
          LOG.info("Entity '" + uuid + "' not found", e);
        }
@@@ -303,9 -304,11 +306,10 @@@
      final List<S> items = new ArrayList<S>(entities.size());
  
      for (CommonODataEntity entity : entities) {
-       final EntityTypeInvocationHandler handler = EntityTypeInvocationHandler.getInstance(entity, this, typeRef);
+       final EntityInvocationHandler handler =
+               EntityInvocationHandler.getInstance(entity.getEditLink(), entity, this, typeRef);
  
-       final EntityTypeInvocationHandler handlerInTheContext = getContext().entityContext().getEntity(handler.getUUID());
 -      final EntityInvocationHandler handlerInTheContext =
 -              EntityContainerFactory.getContext().entityContext().getEntity(handler.getUUID());
++      final EntityInvocationHandler handlerInTheContext = getContext().entityContext().getEntity(handler.getUUID());
  
        items.add((S) Proxy.newProxyInstance(
                Thread.currentThread().getContextClassLoader(),
@@@ -394,11 -398,11 +398,11 @@@
  
    @Override
    public void delete(final KEY key) throws IllegalArgumentException {
 -    final EntityContext entityContext = EntityContainerFactory.getContext().entityContext();
 +    final EntityContext entityContext = getContext().entityContext();
  
-     EntityTypeInvocationHandler entity = entityContext.getEntity(new EntityUUID(
+     EntityInvocationHandler entity = entityContext.getEntity(new EntityUUID(
              containerHandler.getEntityContainerName(),
-             entitySetName,
+             uri,
              typeRef,
              key));
  
@@@ -414,10 -418,10 +418,10 @@@
  
    @Override
    public <S extends T> void delete(final Iterable<S> entities) {
 -    final EntityContext entityContext = EntityContainerFactory.getContext().entityContext();
 +    final EntityContext entityContext = getContext().entityContext();
  
      for (T en : entities) {
-       final EntityTypeInvocationHandler entity = (EntityTypeInvocationHandler) Proxy.getInvocationHandler(en);
+       final EntityInvocationHandler entity = (EntityInvocationHandler) Proxy.getInvocationHandler(en);
        if (entityContext.isAttached(entity)) {
          entityContext.setStatus(entity, AttachedEntityStatus.DELETED);
        } else {
@@@ -426,8 -430,8 +430,8 @@@
      }
    }
  
-   private boolean isDeleted(final EntityTypeInvocationHandler handler) {
+   private boolean isDeleted(final EntityInvocationHandler handler) {
 -    return EntityContainerFactory.getContext().entityContext().getStatus(handler) == AttachedEntityStatus.DELETED;
 +    return getContext().entityContext().getStatus(handler) == AttachedEntityStatus.DELETED;
    }
  
    @Override

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/1abd8e7e/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/OperationInvocationHandler.java
----------------------------------------------------------------------
diff --cc ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/OperationInvocationHandler.java
index e2362eb,69e1f9b..5aaa0e6
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/OperationInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/OperationInvocationHandler.java
@@@ -62,14 -64,18 +62,14 @@@ class OperationInvocationHandler extend
    }
  
    private OperationInvocationHandler(final EntityContainerInvocationHandler containerHandler) {
 -    super(containerHandler.getClient(), containerHandler);
 +    super(containerHandler);
  
      this.target = containerHandler;
 -
 -    this.targetFQN =
 -            new FullQualifiedName(containerHandler.getSchemaName(), containerHandler.getEntityContainerName());
 -
 -    this.serviceRoot = containerHandler.getFactory().getServiceRoot();
 +    this.targetFQN = new FullQualifiedName(containerHandler.getSchemaName(), containerHandler.getEntityContainerName());
    }
  
-   private OperationInvocationHandler(final EntityTypeInvocationHandler entityHandler) {
+   private OperationInvocationHandler(final EntityInvocationHandler entityHandler) {
 -    super(entityHandler.getClient(), entityHandler.containerHandler);
 +    super(entityHandler.containerHandler);
  
      this.target = entityHandler;
      this.targetFQN = entityHandler.getEntity().getTypeName();

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/1abd8e7e/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/SingletonInvocationHandler.java
----------------------------------------------------------------------
diff --cc ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/SingletonInvocationHandler.java
index 664e894,57b1b39..bbae0c8
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/SingletonInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/SingletonInvocationHandler.java
@@@ -41,10 -40,11 +40,11 @@@ public class SingletonInvocationHandler
    private final EntitySetInvocationHandler<?, ?, ?> entitySetHandler;
  
    @SuppressWarnings({"rawtypes", "unchecked"})
-   private SingletonInvocationHandler(final Class<?> ref, final EntityContainerInvocationHandler containerHandler) {
+   private SingletonInvocationHandler(
+           final Class<?> ref, final EntityContainerInvocationHandler containerHandler, final String singletonName) {
+ 
 -    super(containerHandler.getClient(), containerHandler);
 +    super(containerHandler);
-     this.entitySetHandler =
-             new EntitySetInvocationHandler(ref, containerHandler, (ref.getAnnotation(Singleton.class)).name());
+     this.entitySetHandler = EntitySetInvocationHandler.getInstance(ref, containerHandler, singletonName);
    }
  
    @Override

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/1abd8e7e/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/utils/CoreUtils.java
----------------------------------------------------------------------
diff --cc ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/utils/CoreUtils.java
index bd7a537,38dd4cc..822e8ea
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/utils/CoreUtils.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/utils/CoreUtils.java
@@@ -349,10 -349,7 +349,10 @@@ public final class CoreUtils 
    }
  
    public static Object getKey(
 -          final CommonEdmEnabledODataClient<?> client, final Class<?> entityTypeRef, final CommonODataEntity entity) {
 +          final CommonEdmEnabledODataClient<?> client,
-           final EntityTypeInvocationHandler typeHandler,
++          final EntityInvocationHandler typeHandler,
 +          final Class<?> entityTypeRef,
 +          final CommonODataEntity entity) {
  
      Object res = null;
  
@@@ -378,9 -375,8 +378,9 @@@
      return res;
    }
  
 -  public static void populate(
 +  private static void populate(
            final CommonEdmEnabledODataClient<?> client,
-           final EntityTypeInvocationHandler typeHandler,
++          final EntityInvocationHandler typeHandler,
            final Object bean,
            final Class<? extends Annotation> getterAnn,
            final Iterator<? extends CommonODataProperty> propItor) {
@@@ -402,11 -398,10 +402,11 @@@
    }
  
    @SuppressWarnings({"unchecked"})
 -  public static void populate(
 +  private static void populate(
            final CommonEdmEnabledODataClient<?> client,
-           final EntityTypeInvocationHandler typeHandler,
++          final EntityInvocationHandler typeHandler,
            final Object bean,
 -          final Class<?> reference,
 +          final Class<?> typeRef,
            final Class<? extends Annotation> getterAnn,
            final Iterator<? extends CommonODataProperty> propItor) {
  
@@@ -430,10 -425,10 +430,10 @@@
                final Object complex = Proxy.newProxyInstance(
                        Thread.currentThread().getContextClassLoader(),
                        new Class<?>[] {getter.getReturnType()},
-                       ComplexTypeInvocationHandler.getInstance(
+                       ComplexInvocationHandler.getInstance(
 -                              client, property.getName(), getter.getReturnType(), null));
 +                              client, property.getName(), getter.getReturnType(), typeHandler));
  
 -              populate(client, complex, Property.class, property.getValue().asComplex().iterator());
 +              populate(client, typeHandler, complex, Property.class, property.getValue().asComplex().iterator());
                setPropertyValue(bean, getter, complex);
              } else if (property.hasCollectionValue()) {
                final ParameterizedType collType = (ParameterizedType) getter.getGenericReturnType();
@@@ -455,10 -450,10 +455,10 @@@
                    final Object collItem = Proxy.newProxyInstance(
                            Thread.currentThread().getContextClassLoader(),
                            new Class<?>[] {collItemClass},
-                           ComplexTypeInvocationHandler.getInstance(
+                           ComplexInvocationHandler.getInstance(
 -                                  client, property.getName(), collItemClass, null));
 +                                  client, property.getName(), collItemClass, typeHandler));
  
 -                  populate(client, collItem, Property.class, value.asComplex().iterator());
 +                  populate(client, typeHandler, collItem, Property.class, value.asComplex().iterator());
                    collection.add(collItem);
                  }
                }