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:25 UTC

[1/9] [OLINGO-260] Enhancement: non-static context

Repository: olingo-odata4
Updated Branches:
  refs/heads/master 72d894cd3 -> 38214db49


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/e897cf27/fit/src/test/java/org/apache/olingo/fit/proxy/v3/ContextTestITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/proxy/v3/ContextTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/proxy/v3/ContextTestITCase.java
index b1b2e75..a3a78b4 100644
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/v3/ContextTestITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/v3/ContextTestITCase.java
@@ -67,16 +67,16 @@ public class ContextTestITCase extends AbstractTestITCase {
     final EntityTypeInvocationHandler source2 =
             (EntityTypeInvocationHandler) Proxy.getInvocationHandler(customer2);
 
-    assertTrue(entityContext.isAttached(source1));
-    assertTrue(entityContext.isAttached(source2));
+    assertTrue(containerFactory.getContext().entityContext().isAttached(source1));
+    assertTrue(containerFactory.getContext().entityContext().isAttached(source2));
 
-    entityContext.detach(source1);
-    assertFalse(entityContext.isAttached(source1));
-    assertTrue(entityContext.isAttached(source2));
+    containerFactory.getContext().entityContext().detach(source1);
+    assertFalse(containerFactory.getContext().entityContext().isAttached(source1));
+    assertTrue(containerFactory.getContext().entityContext().isAttached(source2));
 
-    entityContext.detach(source2);
-    assertFalse(entityContext.isAttached(source1));
-    assertFalse(entityContext.isAttached(source2));
+    containerFactory.getContext().entityContext().detach(source2);
+    assertFalse(containerFactory.getContext().entityContext().isAttached(source1));
+    assertFalse(containerFactory.getContext().entityContext().isAttached(source2));
   }
 
   @Test
@@ -92,36 +92,36 @@ public class ContextTestITCase extends AbstractTestITCase {
     final EntityTypeInvocationHandler source3 =
             (EntityTypeInvocationHandler) Proxy.getInvocationHandler(customer3);
 
-    assertFalse(entityContext.isAttached(source1));
-    assertFalse(entityContext.isAttached(source2));
-    assertFalse(entityContext.isAttached(source3));
+    assertFalse(containerFactory.getContext().entityContext().isAttached(source1));
+    assertFalse(containerFactory.getContext().entityContext().isAttached(source2));
+    assertFalse(containerFactory.getContext().entityContext().isAttached(source3));
 
-    entityContext.attach(source1);
-    assertTrue(entityContext.isAttached(source1));
-    assertFalse(entityContext.isAttached(source2));
-    assertTrue(entityContext.isAttached(source3));
+    containerFactory.getContext().entityContext().attach(source1);
+    assertTrue(containerFactory.getContext().entityContext().isAttached(source1));
+    assertFalse(containerFactory.getContext().entityContext().isAttached(source2));
+    assertTrue(containerFactory.getContext().entityContext().isAttached(source3));
 
-    entityContext.attach(source2);
-    assertTrue(entityContext.isAttached(source1));
-    assertTrue(entityContext.isAttached(source2));
-    assertTrue(entityContext.isAttached(source3));
+    containerFactory.getContext().entityContext().attach(source2);
+    assertTrue(containerFactory.getContext().entityContext().isAttached(source1));
+    assertTrue(containerFactory.getContext().entityContext().isAttached(source2));
+    assertTrue(containerFactory.getContext().entityContext().isAttached(source3));
 
     try {
-      entityContext.attach(source3);
+      containerFactory.getContext().entityContext().attach(source3);
       fail();
     } catch (IllegalStateException ignore) {
       // ignore
     }
 
-    entityContext.detach(source1);
-    assertFalse(entityContext.isAttached(source1));
-    assertTrue(entityContext.isAttached(source2));
-    assertFalse(entityContext.isAttached(source3));
+    containerFactory.getContext().entityContext().detach(source1);
+    assertFalse(containerFactory.getContext().entityContext().isAttached(source1));
+    assertTrue(containerFactory.getContext().entityContext().isAttached(source2));
+    assertFalse(containerFactory.getContext().entityContext().isAttached(source3));
 
-    entityContext.detach(source2);
-    assertFalse(entityContext.isAttached(source1));
-    assertFalse(entityContext.isAttached(source2));
-    assertFalse(entityContext.isAttached(source3));
+    containerFactory.getContext().entityContext().detach(source2);
+    assertFalse(containerFactory.getContext().entityContext().isAttached(source1));
+    assertFalse(containerFactory.getContext().entityContext().isAttached(source2));
+    assertFalse(containerFactory.getContext().entityContext().isAttached(source3));
   }
 
   @Test
@@ -138,17 +138,17 @@ public class ContextTestITCase extends AbstractTestITCase {
     final EntityTypeInvocationHandler target =
             (EntityTypeInvocationHandler) Proxy.getInvocationHandler(customerInfo);
 
-    assertTrue(entityContext.isAttached(source));
-    assertEquals(AttachedEntityStatus.NEW, entityContext.getStatus(source));
-    assertTrue(entityContext.isAttached(target));
-    assertEquals(AttachedEntityStatus.LINKED, entityContext.getStatus(target));
+    assertTrue(containerFactory.getContext().entityContext().isAttached(source));
+    assertEquals(AttachedEntityStatus.NEW, containerFactory.getContext().entityContext().getStatus(source));
+    assertTrue(containerFactory.getContext().entityContext().isAttached(target));
+    assertEquals(AttachedEntityStatus.LINKED, containerFactory.getContext().entityContext().getStatus(target));
 
     checkUnidirectional("Info", source, "Customer", target, false);
 
-    entityContext.detachAll();
+    containerFactory.getContext().entityContext().detachAll();
 
-    assertFalse(entityContext.isAttached(source));
-    assertFalse(entityContext.isAttached(target));
+    assertFalse(containerFactory.getContext().entityContext().isAttached(source));
+    assertFalse(containerFactory.getContext().entityContext().isAttached(target));
   }
 
   @Test
@@ -165,17 +165,17 @@ public class ContextTestITCase extends AbstractTestITCase {
     final EntityTypeInvocationHandler target =
             (EntityTypeInvocationHandler) Proxy.getInvocationHandler(customerInfo);
 
-    assertTrue(entityContext.isAttached(source));
-    assertEquals(AttachedEntityStatus.CHANGED, entityContext.getStatus(source));
-    assertTrue(entityContext.isAttached(target));
-    assertEquals(AttachedEntityStatus.NEW, entityContext.getStatus(target));
+    assertTrue(containerFactory.getContext().entityContext().isAttached(source));
+    assertEquals(AttachedEntityStatus.CHANGED, containerFactory.getContext().entityContext().getStatus(source));
+    assertTrue(containerFactory.getContext().entityContext().isAttached(target));
+    assertEquals(AttachedEntityStatus.NEW, containerFactory.getContext().entityContext().getStatus(target));
 
     checkUnidirectional("Info", source, "Customer", target, false);
 
-    entityContext.detachAll();
+    containerFactory.getContext().entityContext().detachAll();
 
-    assertFalse(entityContext.isAttached(source));
-    assertFalse(entityContext.isAttached(target));
+    assertFalse(containerFactory.getContext().entityContext().isAttached(source));
+    assertFalse(containerFactory.getContext().entityContext().isAttached(target));
   }
 
   @Test
@@ -192,17 +192,17 @@ public class ContextTestITCase extends AbstractTestITCase {
     final EntityTypeInvocationHandler target =
             (EntityTypeInvocationHandler) Proxy.getInvocationHandler(customerInfo);
 
-    assertTrue(entityContext.isAttached(source));
-    assertEquals(AttachedEntityStatus.CHANGED, entityContext.getStatus(source));
-    assertTrue(entityContext.isAttached(target));
-    assertEquals(AttachedEntityStatus.LINKED, entityContext.getStatus(target));
+    assertTrue(containerFactory.getContext().entityContext().isAttached(source));
+    assertEquals(AttachedEntityStatus.CHANGED, containerFactory.getContext().entityContext().getStatus(source));
+    assertTrue(containerFactory.getContext().entityContext().isAttached(target));
+    assertEquals(AttachedEntityStatus.LINKED, containerFactory.getContext().entityContext().getStatus(target));
 
     checkUnidirectional("Info", source, "Customer", target, false);
 
-    entityContext.detachAll();
+    containerFactory.getContext().entityContext().detachAll();
 
-    assertFalse(entityContext.isAttached(source));
-    assertFalse(entityContext.isAttached(target));
+    assertFalse(containerFactory.getContext().entityContext().isAttached(source));
+    assertFalse(containerFactory.getContext().entityContext().isAttached(target));
   }
 
   @Test
@@ -220,24 +220,25 @@ public class ContextTestITCase extends AbstractTestITCase {
 
     final EntityTypeInvocationHandler source = (EntityTypeInvocationHandler) Proxy.getInvocationHandler(customer);
 
-    assertTrue(entityContext.isAttached(source));
-    assertEquals(AttachedEntityStatus.NEW, entityContext.getStatus(source));
+    assertTrue(containerFactory.getContext().entityContext().isAttached(source));
+    assertEquals(AttachedEntityStatus.NEW, containerFactory.getContext().entityContext().getStatus(source));
     assertEquals(3, ((Collection) (source.getLinkChanges().entrySet().iterator().next().getValue())).size());
 
     for (Order order : toBeLinked) {
       final EntityTypeInvocationHandler target = (EntityTypeInvocationHandler) Proxy.getInvocationHandler(order);
 
-      assertTrue(entityContext.isAttached(target));
-      assertEquals(AttachedEntityStatus.NEW, entityContext.getStatus(target));
+      assertTrue(containerFactory.getContext().entityContext().isAttached(target));
+      assertEquals(AttachedEntityStatus.NEW, containerFactory.getContext().entityContext().getStatus(target));
       checkUnidirectional("Orders", source, "Customer", target, true);
     }
 
-    entityContext.detachAll();
+    containerFactory.getContext().entityContext().detachAll();
 
-    assertFalse(entityContext.isAttached(source));
+    assertFalse(containerFactory.getContext().entityContext().isAttached(source));
 
     for (Order order : toBeLinked) {
-      assertFalse(entityContext.isAttached((EntityTypeInvocationHandler) Proxy.getInvocationHandler(order)));
+      assertFalse(containerFactory.getContext().entityContext().
+              isAttached((EntityTypeInvocationHandler) Proxy.getInvocationHandler(order)));
     }
   }
 
@@ -265,12 +266,12 @@ public class ContextTestITCase extends AbstractTestITCase {
 
     final EntityTypeInvocationHandler source = (EntityTypeInvocationHandler) Proxy.getInvocationHandler(customer);
 
-    assertTrue(entityContext.isAttached(source));
-    assertEquals(AttachedEntityStatus.NEW, entityContext.getStatus(source));
+    assertTrue(containerFactory.getContext().entityContext().isAttached(source));
+    assertEquals(AttachedEntityStatus.NEW, containerFactory.getContext().entityContext().getStatus(source));
 
-    entityContext.detachAll();
+    containerFactory.getContext().entityContext().detachAll();
 
-    assertFalse(entityContext.isAttached(source));
+    assertFalse(containerFactory.getContext().entityContext().isAttached(source));
   }
 
   @Test
@@ -283,7 +284,7 @@ public class ContextTestITCase extends AbstractTestITCase {
     customerInfo = container.getCustomerInfo().get(16);
     assertEquals("some other info ...", customerInfo.getInformation());
 
-    entityContext.detachAll();
+    containerFactory.getContext().entityContext().detachAll();
     customerInfo = container.getCustomerInfo().get(16);
     assertNotEquals("some other info ...", customerInfo.getInformation());
   }
@@ -304,7 +305,7 @@ public class ContextTestITCase extends AbstractTestITCase {
     }
     assertTrue(found);
 
-    entityContext.detachAll();
+    containerFactory.getContext().entityContext().detachAll();
 
     found = false;
     for (CustomerInfo info : container.getCustomerInfo().getAll()) {
@@ -322,7 +323,7 @@ public class ContextTestITCase extends AbstractTestITCase {
 
     final EntityTypeInvocationHandler handler = (EntityTypeInvocationHandler) Proxy.getInvocationHandler(login);
 
-    assertTrue(entityContext.isAttached(handler));
+    assertTrue(containerFactory.getContext().entityContext().isAttached(handler));
 
     try {
       container.flush();
@@ -331,20 +332,20 @@ public class ContextTestITCase extends AbstractTestITCase {
       // ignore
     }
 
-    assertTrue(entityContext.isAttached(handler));
+    assertTrue(containerFactory.getContext().entityContext().isAttached(handler));
 
     login.setCustomerId(-10);
     login.setUsername("customer");
 
     container.flush();
-    assertFalse(entityContext.isAttached(handler));
+    assertFalse(containerFactory.getContext().entityContext().isAttached(handler));
     assertNotNull(container.getLogin().get("customer"));
 
     container.getLogin().delete(login.getUsername());
-    assertTrue(entityContext.isAttached(handler));
+    assertTrue(containerFactory.getContext().entityContext().isAttached(handler));
 
     container.flush();
-    assertFalse(entityContext.isAttached(handler));
+    assertFalse(containerFactory.getContext().entityContext().isAttached(handler));
     assertNull(container.getLogin().get("customer"));
   }
 
@@ -387,18 +388,24 @@ public class ContextTestITCase extends AbstractTestITCase {
     customer.setPrimaryContactInfo(cd);
     customer.setBackupContactInfo(Collections.<ContactDetails>singletonList(bcd));
 
-    assertTrue(entityContext.isAttached((EntityTypeInvocationHandler) Proxy.getInvocationHandler(customerInfo)));
-    assertTrue(entityContext.isAttached((EntityTypeInvocationHandler) Proxy.getInvocationHandler(customer)));
+    assertTrue(containerFactory.getContext().entityContext().
+            isAttached((EntityTypeInvocationHandler) Proxy.getInvocationHandler(customerInfo)));
+    assertTrue(containerFactory.getContext().entityContext().
+            isAttached((EntityTypeInvocationHandler) Proxy.getInvocationHandler(customer)));
     for (Order linked : toBeLinked) {
-      assertTrue(entityContext.isAttached((EntityTypeInvocationHandler) Proxy.getInvocationHandler(linked)));
+      assertTrue(containerFactory.getContext().entityContext().
+              isAttached((EntityTypeInvocationHandler) Proxy.getInvocationHandler(linked)));
     }
 
     container.flush();
 
-    assertFalse(entityContext.isAttached((EntityTypeInvocationHandler) Proxy.getInvocationHandler(customerInfo)));
-    assertFalse(entityContext.isAttached((EntityTypeInvocationHandler) Proxy.getInvocationHandler(customer)));
+    assertFalse(containerFactory.getContext().entityContext().
+            isAttached((EntityTypeInvocationHandler) Proxy.getInvocationHandler(customerInfo)));
+    assertFalse(containerFactory.getContext().entityContext().
+            isAttached((EntityTypeInvocationHandler) Proxy.getInvocationHandler(customer)));
     for (Order linked : toBeLinked) {
-      assertFalse(entityContext.isAttached((EntityTypeInvocationHandler) Proxy.getInvocationHandler(linked)));
+      assertFalse(containerFactory.getContext().entityContext().
+              isAttached((EntityTypeInvocationHandler) Proxy.getInvocationHandler(linked)));
     }
 
     assertEquals("some new info ...", container.getCustomerInfo().get(16).getInformation());
@@ -406,16 +413,20 @@ public class ContextTestITCase extends AbstractTestITCase {
     container.getOrder().delete(toBeLinked);
     container.getCustomer().delete(customer.getCustomerId());
 
-    assertTrue(entityContext.isAttached((EntityTypeInvocationHandler) Proxy.getInvocationHandler(customer)));
+    assertTrue(containerFactory.getContext().entityContext().
+            isAttached((EntityTypeInvocationHandler) Proxy.getInvocationHandler(customer)));
     for (Order linked : toBeLinked) {
-      assertTrue(entityContext.isAttached((EntityTypeInvocationHandler) Proxy.getInvocationHandler(linked)));
+      assertTrue(containerFactory.getContext().entityContext().
+              isAttached((EntityTypeInvocationHandler) Proxy.getInvocationHandler(linked)));
     }
 
     container.flush();
 
-    assertFalse(entityContext.isAttached((EntityTypeInvocationHandler) Proxy.getInvocationHandler(customer)));
+    assertFalse(containerFactory.getContext().entityContext().
+            isAttached((EntityTypeInvocationHandler) Proxy.getInvocationHandler(customer)));
     for (Order linked : toBeLinked) {
-      assertFalse(entityContext.isAttached((EntityTypeInvocationHandler) Proxy.getInvocationHandler(linked)));
+      assertFalse(containerFactory.getContext().entityContext().
+              isAttached((EntityTypeInvocationHandler) Proxy.getInvocationHandler(linked)));
     }
   }
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/e897cf27/fit/src/test/java/org/apache/olingo/fit/proxy/v3/EntityCreateTestITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/proxy/v3/EntityCreateTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/proxy/v3/EntityCreateTestITCase.java
index 2ae58e8..ccfbd2a 100644
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/v3/EntityCreateTestITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/v3/EntityCreateTestITCase.java
@@ -58,7 +58,7 @@ public class EntityCreateTestITCase extends AbstractTestITCase {
     actual = container.getCustomer().get(id);
     assertNull(actual);
 
-    entityContext.detachAll();
+    containerFactory.getContext().detachAll();
     actual = container.getCustomer().get(id);
     assertNotNull(actual);
 
@@ -68,7 +68,7 @@ public class EntityCreateTestITCase extends AbstractTestITCase {
     actual = container.getCustomer().get(id);
     assertNull(actual);
 
-    entityContext.detachAll();
+    containerFactory.getContext().detachAll();
     actual = container.getCustomer().get(id);
     assertNull(actual);
   }
@@ -90,7 +90,7 @@ public class EntityCreateTestITCase extends AbstractTestITCase {
     assertNotNull(actual);
     assertEquals(id, actual.getPersonId());
 
-    entityContext.detachAll();
+    containerFactory.getContext().detachAll();
     actual = container.getPerson().get(id, Employee.class);
     assertNotNull(actual);
 
@@ -100,7 +100,7 @@ public class EntityCreateTestITCase extends AbstractTestITCase {
     actual = container.getPerson().get(id, Employee.class);
     assertNull(actual);
 
-    entityContext.detachAll();
+    containerFactory.getContext().detachAll();
     actual = container.getPerson().get(id, Employee.class);
     assertNull(actual);
   }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/e897cf27/fit/src/test/java/org/apache/olingo/fit/proxy/v3/OpenTypeTestITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/proxy/v3/OpenTypeTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/proxy/v3/OpenTypeTestITCase.java
index 28b768f..1a0a08c 100644
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/v3/OpenTypeTestITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/v3/OpenTypeTestITCase.java
@@ -64,7 +64,7 @@ public class OpenTypeTestITCase extends AbstractTestITCase {
             getAnnotation(EntityType.class).openType());
     assertTrue(otcontainer.getRow().newIndexedRow().getClass().getInterfaces()[0].
             getAnnotation(EntityType.class).openType());
-    entityContext.detachAll();
+    containerFactory.getContext().detachAll();
   }
 
   @Test
@@ -124,7 +124,7 @@ public class OpenTypeTestITCase extends AbstractTestITCase {
     assertTrue(Calendar.class.isAssignableFrom(rowIndex.getAdditionalProperty("aDate").getClass()));
     assertEquals(ContactDetails.class, rowIndex.getAdditionalProperty("aContact").getClass().getInterfaces()[0]);
 
-    entityContext.detachAll();
+    containerFactory.getContext().detachAll();
 
     otcontainer.getRowIndex().delete(id);
     otcontainer.flush();

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/e897cf27/fit/src/test/java/org/apache/olingo/fit/proxy/v3/PropertyTestITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/proxy/v3/PropertyTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/proxy/v3/PropertyTestITCase.java
index 0296bac..e0aec63 100644
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/v3/PropertyTestITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/v3/PropertyTestITCase.java
@@ -18,12 +18,11 @@
  */
 package org.apache.olingo.fit.proxy.v3;
 
-import org.apache.olingo.ext.proxy.EntityContainerFactory;
-import org.apache.olingo.fit.proxy.v3.staticservice.microsoft.test.odata.services.astoriadefaultservice.types.Driver;
-import org.apache.olingo.fit.proxy.v3.staticservice.microsoft.test.odata.services.astoriadefaultservice.types.Order;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.fail;
 
+import org.apache.olingo.fit.proxy.v3.staticservice.microsoft.test.odata.services.astoriadefaultservice.types.Driver;
+import org.apache.olingo.fit.proxy.v3.staticservice.microsoft.test.odata.services.astoriadefaultservice.types.Order;
 import org.junit.Test;
 
 /**
@@ -50,7 +49,7 @@ public class PropertyTestITCase extends AbstractTestITCase {
             fail();
         } catch (IllegalStateException e) {
             // ignore and detach all
-            EntityContainerFactory.getContext().detachAll();
+            containerFactory.getContext().detachAll();
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/e897cf27/fit/src/test/java/org/apache/olingo/fit/proxy/v4/AbstractTestITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/proxy/v4/AbstractTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/proxy/v4/AbstractTestITCase.java
index baa4128..40cd2bb 100644
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/v4/AbstractTestITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/v4/AbstractTestITCase.java
@@ -30,7 +30,6 @@ import java.util.TimeZone;
 import org.apache.olingo.client.api.v4.EdmEnabledODataClient;
 import org.apache.olingo.commons.api.format.ContentType;
 import org.apache.olingo.ext.proxy.EntityContainerFactory;
-import org.apache.olingo.ext.proxy.context.EntityContext;
 import org.apache.olingo.fit.proxy.v4.staticservice.microsoft.test.odata.services.odatawcfservice.InMemoryEntities;
 import org.apache.olingo.fit.proxy.v4.staticservice.microsoft.test.odata.services.odatawcfservice.types.Customer;
 import org.apache.olingo.fit.proxy.v4.staticservice.microsoft.test.odata.services.odatawcfservice.types.Order;
@@ -59,8 +58,6 @@ public abstract class AbstractTestITCase {
 
   protected static String testAuthServiceRootURL;
 
-  protected final EntityContext entityContext = EntityContainerFactory.getContext().entityContext();
-
   protected static EntityContainerFactory<EdmEnabledODataClient> containerFactory;
 
   protected static InMemoryEntities container;
@@ -78,7 +75,7 @@ public abstract class AbstractTestITCase {
     containerFactory.getClient().getConfiguration().setDefaultBatchAcceptFormat(ContentType.APPLICATION_OCTET_STREAM);
     container = containerFactory.getEntityContainer(InMemoryEntities.class);
     assertNotNull(container);
-    EntityContainerFactory.getContext().detachAll();
+    containerFactory.getContext().detachAll();
   }
 
   protected Customer readCustomer(final InMemoryEntities container, int id) {
@@ -113,7 +110,7 @@ public abstract class AbstractTestITCase {
     actual = container.getOrders().get(105);
     assertNull(actual);
 
-    entityContext.detachAll();
+    containerFactory.getContext().detachAll();
     actual = container.getOrders().get(105);
     assertNotNull(actual);
 
@@ -123,7 +120,7 @@ public abstract class AbstractTestITCase {
 
     container.flush();
 
-    entityContext.detachAll();
+    containerFactory.getContext().detachAll();
     actual = container.getOrders().get(105);
     assertNull(actual);
   }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/e897cf27/fit/src/test/java/org/apache/olingo/fit/proxy/v4/EntityCreateTestITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/proxy/v4/EntityCreateTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/proxy/v4/EntityCreateTestITCase.java
index 6d6c899..8c156e2 100644
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/v4/EntityCreateTestITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/v4/EntityCreateTestITCase.java
@@ -74,7 +74,7 @@ public class EntityCreateTestITCase extends AbstractTestITCase {
     assertEquals(id, actual.getPersonID());
     assertEquals(homeAddress.getCity(), actual.getHomeAddress().getCity());
 
-    entityContext.detachAll();
+    containerFactory.getContext().detachAll();
     actual = container.getPeople().get(id, Employee.class);
     assertNotNull(actual);
     assertEquals(id, actual.getPersonID());
@@ -86,7 +86,7 @@ public class EntityCreateTestITCase extends AbstractTestITCase {
     actual = container.getPeople().get(id, Employee.class);;
     assertNull(actual);
 
-    entityContext.detachAll();
+    containerFactory.getContext().detachAll();
     actual = container.getPeople().get(id, Employee.class);
     assertNull(actual);
   }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/e897cf27/fit/src/test/java/org/apache/olingo/fit/proxy/v4/OpenTypeTestITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/proxy/v4/OpenTypeTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/proxy/v4/OpenTypeTestITCase.java
index 11f7d07..9b63483 100644
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/v4/OpenTypeTestITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/v4/OpenTypeTestITCase.java
@@ -65,7 +65,7 @@ public class OpenTypeTestITCase extends AbstractTestITCase {
             getAnnotation(EntityType.class).openType());
     assertTrue(otcontainer.getRow().newIndexedRow().getClass().getInterfaces()[0].
             getAnnotation(EntityType.class).openType());
-    entityContext.detachAll();
+    containerFactory.getContext().detachAll();
   }
 
   @Test
@@ -128,7 +128,7 @@ public class OpenTypeTestITCase extends AbstractTestITCase {
     assertEquals(Color.class, rowIndex.getAdditionalProperty("aColor").getClass());
     assertEquals(Color.Green, rowIndex.getAdditionalProperty("aColor"));
 
-    entityContext.detachAll();
+    containerFactory.getContext().detachAll();
 
     otcontainer.getRowIndex().delete(id);
     otcontainer.flush();

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/e897cf27/fit/src/test/java/org/apache/olingo/fit/proxy/v4/PropertyTestITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/proxy/v4/PropertyTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/proxy/v4/PropertyTestITCase.java
index 7c7fde7..0446809 100644
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/v4/PropertyTestITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/v4/PropertyTestITCase.java
@@ -21,7 +21,6 @@ package org.apache.olingo.fit.proxy.v4;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.fail;
 
-import org.apache.olingo.ext.proxy.EntityContainerFactory;
 import org.apache.olingo.fit.proxy.v4.staticservice.microsoft.test.odata.services.odatawcfservice.types.Customer;
 import org.apache.olingo.fit.proxy.v4.staticservice.microsoft.test.odata.services.odatawcfservice.types.StoredPI;
 import org.junit.Test;
@@ -50,7 +49,7 @@ public class PropertyTestITCase extends AbstractTestITCase {
       fail();
     } catch (IllegalStateException e) {
       // ignore and detach all
-      EntityContainerFactory.getContext().detachAll();
+      containerFactory.getContext().detachAll();
     }
   }
 }


[5/9] git commit: Still 2 IT failing

Posted by il...@apache.org.
Still 2 IT failing


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

Branch: refs/heads/master
Commit: 8a3a1e0358fa6d18fea58cc47c5ad20918fce8d5
Parents: 1abd8e7
Author: Francesco Chicchiriccò <--global>
Authored: Mon May 19 08:19:41 2014 +0200
Committer: Francesco Chicchiriccò <--global>
Committed: Mon May 19 08:19:41 2014 +0200

----------------------------------------------------------------------
 .../apache/olingo/ext/proxy/api/Container.java  |  32 --
 .../ext/proxy/api/PersistenceManager.java       |  32 ++
 .../commons/AbstractInvocationHandler.java      |   2 +-
 .../olingo/ext/proxy/commons/ContainerImpl.java | 551 -------------------
 .../EntityContainerInvocationHandler.java       |   2 +-
 .../proxy/commons/PersistenceManagerImpl.java   | 551 +++++++++++++++++++
 .../src/main/resources/container.vm             |   4 +-
 .../astoriadefaultservice/DefaultContainer.java |   4 +-
 .../opentypesservicev3/DefaultContainer.java    |   4 +-
 .../primitivekeysservice/TestContext.java       |   4 +-
 .../astoriadefaultservice/DefaultContainer.java |   4 +-
 .../opentypesservicev4/DefaultContainer.java    |   4 +-
 .../odatawcfservice/InMemoryEntities.java       |   4 +-
 13 files changed, 599 insertions(+), 599 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8a3a1e03/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/Container.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/Container.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/Container.java
deleted file mode 100644
index b95b341..0000000
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/Container.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.api;
-
-import java.io.Serializable;
-
-/**
- * Interface for container operations.
- */
-public interface Container extends Serializable {
-
-  /**
-   * Flushes all pending changes to the OData service.
-   */
-  void flush();
-}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8a3a1e03/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/PersistenceManager.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/PersistenceManager.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/PersistenceManager.java
new file mode 100644
index 0000000..2d195bd
--- /dev/null
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/PersistenceManager.java
@@ -0,0 +1,32 @@
+/*
+ * 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.api;
+
+import java.io.Serializable;
+
+/**
+ * Interface for container operations.
+ */
+public interface PersistenceManager extends Serializable {
+
+  /**
+   * Flushes all pending changes to the OData service.
+   */
+  void flush();
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8a3a1e03/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 cc7eb36..c45b43b 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
@@ -194,7 +194,7 @@ abstract class AbstractInvocationHandler implements InvocationHandler {
 
     // 2. IMPORTANT: flush any pending change *before* invoke if this operation is side effecting
     if (annotation.type() == OperationType.ACTION) {
-      new ContainerImpl(containerHandler.getFactory()).flush();
+      new PersistenceManagerImpl(containerHandler.getFactory()).flush();
     }
 
     // 3. invoke

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8a3a1e03/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ContainerImpl.java
----------------------------------------------------------------------
diff --git 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
deleted file mode 100644
index 0b8b464..0000000
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ContainerImpl.java
+++ /dev/null
@@ -1,551 +0,0 @@
-/*
- * 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.reflect.Proxy;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.olingo.client.api.communication.header.ODataPreferences;
-import org.apache.olingo.client.api.communication.request.ODataRequest;
-import org.apache.olingo.client.api.communication.request.ODataStreamedRequest;
-import org.apache.olingo.client.api.communication.request.batch.BatchStreamManager;
-import org.apache.olingo.client.api.communication.request.batch.CommonODataBatchRequest;
-import org.apache.olingo.client.api.communication.request.batch.ODataBatchResponseItem;
-import org.apache.olingo.client.api.communication.request.batch.ODataChangeset;
-import org.apache.olingo.client.api.communication.request.cud.ODataDeleteRequest;
-import org.apache.olingo.client.api.communication.request.cud.ODataEntityUpdateRequest;
-import org.apache.olingo.client.api.communication.request.streamed.ODataMediaEntityUpdateRequest;
-import org.apache.olingo.client.api.communication.request.streamed.ODataStreamUpdateRequest;
-import org.apache.olingo.client.api.communication.response.ODataBatchResponse;
-import org.apache.olingo.client.api.communication.response.ODataEntityCreateResponse;
-import org.apache.olingo.client.api.communication.response.ODataEntityUpdateResponse;
-import org.apache.olingo.client.api.communication.response.ODataResponse;
-import org.apache.olingo.client.core.communication.request.batch.ODataChangesetResponseItem;
-import org.apache.olingo.client.core.uri.URIUtils;
-import org.apache.olingo.commons.api.domain.CommonODataEntity;
-import org.apache.olingo.commons.api.domain.ODataLink;
-import org.apache.olingo.commons.api.domain.ODataLinkType;
-import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
-import org.apache.olingo.commons.api.format.ODataMediaFormat;
-import org.apache.olingo.ext.proxy.EntityContainerFactory;
-import org.apache.olingo.ext.proxy.api.Container;
-import org.apache.olingo.ext.proxy.api.annotations.NavigationProperty;
-import org.apache.olingo.ext.proxy.context.AttachedEntity;
-import org.apache.olingo.ext.proxy.context.AttachedEntityStatus;
-import org.apache.olingo.ext.proxy.context.EntityLinkDesc;
-import org.apache.olingo.ext.proxy.utils.CoreUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-class ContainerImpl implements Container {
-
-  private static final long serialVersionUID = -3320312269235907501L;
-
-  /**
-   * Logger.
-   */
-  private static final Logger LOG = LoggerFactory.getLogger(ContainerImpl.class);
-
-  private final EntityContainerFactory<?> factory;
-
-  ContainerImpl(final EntityContainerFactory<?> factory) {
-    this.factory = factory;
-  }
-
-  /**
-   * Transactional changes commit.
-   */
-  @Override
-  public void flush() {
-    final CommonODataBatchRequest request =
-            factory.getClient().getBatchRequestFactory().getBatchRequest(factory.getClient().getServiceRoot());
-    ((ODataRequest) request).setAccept(factory.getClient().getConfiguration().getDefaultBatchAcceptFormat());
-
-    final BatchStreamManager streamManager = (BatchStreamManager) ((ODataStreamedRequest) request).execute();
-
-    final ODataChangeset changeset = streamManager.addChangeset();
-
-    final TransactionItems items = new TransactionItems();
-    final List<EntityLinkDesc> delayedUpdates = new ArrayList<EntityLinkDesc>();
-
-    int pos = 0;
-
-    for (AttachedEntity attachedEntity : factory.getContext().entityContext()) {
-      final AttachedEntityStatus status = attachedEntity.getStatus();
-      if (((status != AttachedEntityStatus.ATTACHED
-              && status != AttachedEntityStatus.LINKED) || attachedEntity.getEntity().isChanged())
-              && !items.contains(attachedEntity.getEntity())) {
-        pos++;
-        pos = processEntityContext(attachedEntity.getEntity(), pos, items, delayedUpdates, changeset);
-      }
-    }
-
-    processDelayedUpdates(delayedUpdates, pos, items, changeset);
-
-    final ODataBatchResponse response = streamManager.getResponse();
-
-    if ((factory.getClient().getServiceVersion().compareTo(ODataServiceVersion.V30) <= 0
-            && response.getStatusCode() != 202)
-            || (factory.getClient().getServiceVersion().compareTo(ODataServiceVersion.V30) > 0
-            && response.getStatusCode() != 200)) {
-
-      throw new IllegalStateException("Operation failed");
-    }
-
-    if (!items.isEmpty()) {
-      final Iterator<ODataBatchResponseItem> iter = response.getBody();
-      if (!iter.hasNext()) {
-        throw new IllegalStateException("Unexpected operation result");
-      }
-
-      final ODataBatchResponseItem item = iter.next();
-      if (!(item instanceof ODataChangesetResponseItem)) {
-        throw new IllegalStateException("Unexpected batch response item " + item.getClass().getSimpleName());
-      }
-
-      final ODataChangesetResponseItem chgres = (ODataChangesetResponseItem) item;
-
-      for (Integer changesetItemId : items.sortedValues()) {
-        LOG.debug("Expected changeset item {}", changesetItemId);
-        final ODataResponse res = chgres.next();
-        if (res.getStatusCode() >= 400) {
-          throw new IllegalStateException("Transaction failed: " + res.getStatusMessage());
-        }
-
-        final EntityInvocationHandler handler = items.get(changesetItemId);
-
-        if (handler != null) {
-          if (res instanceof ODataEntityCreateResponse && res.getStatusCode() == 201) {
-            handler.setEntity(((ODataEntityCreateResponse) res).getBody());
-            LOG.debug("Upgrade created object '{}'", handler);
-          } else if (res instanceof ODataEntityUpdateResponse && res.getStatusCode() == 200) {
-            handler.setEntity(((ODataEntityUpdateResponse) res).getBody());
-            LOG.debug("Upgrade updated object '{}'", handler);
-          }
-        }
-      }
-    }
-
-    factory.getContext().detachAll();
-  }
-
-  private void batch(
-          final EntityInvocationHandler handler,
-          final CommonODataEntity entity,
-          final ODataChangeset changeset) {
-
-    switch (factory.getContext().entityContext().getStatus(handler)) {
-      case NEW:
-        batchCreate(handler, entity, changeset);
-        break;
-
-      case CHANGED:
-        batchUpdate(handler, entity, changeset);
-        break;
-
-      case DELETED:
-        batchDelete(handler, entity, changeset);
-        break;
-
-      default:
-        if (handler.isChanged()) {
-          batchUpdate(handler, entity, changeset);
-        }
-    }
-  }
-
-  private void batchCreate(
-          final EntityInvocationHandler handler,
-          final CommonODataEntity entity,
-          final ODataChangeset changeset) {
-
-    LOG.debug("Create '{}'", handler);
-
-    changeset.addRequest(
-            factory.getClient().getCUDRequestFactory().getEntityCreateRequest(handler.getEntitySetURI(), entity));
-  }
-
-  private void batchUpdateMediaEntity(
-          final EntityInvocationHandler handler,
-          final URI uri,
-          final InputStream input,
-          final ODataChangeset changeset) {
-
-    LOG.debug("Update media entity '{}'", uri);
-
-    final ODataMediaEntityUpdateRequest<?> req =
-            factory.getClient().getStreamedRequestFactory().getMediaEntityUpdateRequest(uri, input);
-
-    req.setContentType(StringUtils.isBlank(handler.getEntity().getMediaContentType())
-            ? ODataMediaFormat.WILDCARD.toString()
-            : ODataMediaFormat.fromFormat(handler.getEntity().getMediaContentType()).toString());
-
-    if (StringUtils.isNotBlank(handler.getETag())) {
-      req.setIfMatch(handler.getETag());
-    }
-
-    changeset.addRequest(req);
-  }
-
-  private void batchUpdateMediaResource(
-          final EntityInvocationHandler handler,
-          final URI uri,
-          final InputStream input,
-          final ODataChangeset changeset) {
-
-    LOG.debug("Update media entity '{}'", uri);
-
-    final ODataStreamUpdateRequest req = factory.getClient().
-            getStreamedRequestFactory().getStreamUpdateRequest(uri, input);
-
-    if (StringUtils.isNotBlank(handler.getETag())) {
-      req.setIfMatch(handler.getETag());
-    }
-
-    changeset.addRequest(req);
-  }
-
-  private void batchUpdate(
-          final EntityInvocationHandler handler,
-          final CommonODataEntity changes,
-          final ODataChangeset changeset) {
-
-    LOG.debug("Update '{}'", handler.getEntityURI());
-
-    final ODataEntityUpdateRequest<CommonODataEntity> req =
-            factory.getClient().getServiceVersion().compareTo(ODataServiceVersion.V30) <= 0
-            ? ((org.apache.olingo.client.api.v3.EdmEnabledODataClient) factory.getClient()).getCUDRequestFactory().
-            getEntityUpdateRequest(handler.getEntityURI(),
-                    org.apache.olingo.client.api.communication.request.cud.v3.UpdateType.PATCH, changes)
-            : ((org.apache.olingo.client.api.v4.EdmEnabledODataClient) factory.getClient()).getCUDRequestFactory().
-            getEntityUpdateRequest(handler.getEntityURI(),
-                    org.apache.olingo.client.api.communication.request.cud.v4.UpdateType.PATCH, changes);
-
-    req.setPrefer(new ODataPreferences(factory.getClient().getServiceVersion()).returnContent());
-
-    if (StringUtils.isNotBlank(handler.getETag())) {
-      req.setIfMatch(handler.getETag());
-    }
-
-    changeset.addRequest(req);
-  }
-
-  private void batchUpdate(
-          final EntityInvocationHandler handler,
-          final URI uri,
-          final CommonODataEntity changes,
-          final ODataChangeset changeset) {
-
-    LOG.debug("Update '{}'", uri);
-
-    final ODataEntityUpdateRequest<CommonODataEntity> req =
-            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)
-            : ((org.apache.olingo.client.api.v4.EdmEnabledODataClient) factory.getClient()).getCUDRequestFactory().
-            getEntityUpdateRequest(uri,
-                    org.apache.olingo.client.api.communication.request.cud.v4.UpdateType.PATCH, changes);
-
-    req.setPrefer(new ODataPreferences(factory.getClient().getServiceVersion()).returnContent());
-
-    if (StringUtils.isNotBlank(handler.getETag())) {
-      req.setIfMatch(handler.getETag());
-    }
-
-    changeset.addRequest(req);
-  }
-
-  private void batchDelete(
-          final EntityInvocationHandler handler,
-          final CommonODataEntity entity,
-          final ODataChangeset changeset) {
-
-    final URI deleteURI = handler.getEntityURI() == null ? entity.getEditLink() : handler.getEntityURI();
-    LOG.debug("Delete '{}'", deleteURI);
-
-    final ODataDeleteRequest req = factory.getClient().getCUDRequestFactory().getDeleteRequest(deleteURI);
-
-    if (StringUtils.isNotBlank(handler.getETag())) {
-      req.setIfMatch(handler.getETag());
-    }
-
-    changeset.addRequest(req);
-  }
-
-  private int processEntityContext(
-          final EntityInvocationHandler handler,
-          int pos,
-          final TransactionItems items,
-          final List<EntityLinkDesc> delayedUpdates,
-          final ODataChangeset changeset) {
-
-    LOG.debug("Process '{}'", handler);
-
-    items.put(handler, null);
-
-    final CommonODataEntity entity = handler.getEntity();
-    entity.getNavigationLinks().clear();
-
-    final AttachedEntityStatus currentStatus = factory.getContext().entityContext().getStatus(handler);
-
-    if (AttachedEntityStatus.DELETED != currentStatus) {
-      entity.getProperties().clear();
-      CoreUtils.addProperties(factory.getClient(), handler.getPropertyChanges(), entity);
-    }
-
-    for (Map.Entry<NavigationProperty, Object> property : handler.getLinkChanges().entrySet()) {
-      final ODataLinkType type = Collection.class.isAssignableFrom(property.getValue().getClass())
-              ? ODataLinkType.ENTITY_SET_NAVIGATION
-              : ODataLinkType.ENTITY_NAVIGATION;
-
-      final Set<EntityInvocationHandler> toBeLinked = new HashSet<EntityInvocationHandler>();
-      final String serviceRoot = factory.getClient().getServiceRoot();
-
-      for (Object proxy : type == ODataLinkType.ENTITY_SET_NAVIGATION
-              ? (Collection) property.getValue() : Collections.singleton(property.getValue())) {
-
-        final EntityInvocationHandler target = (EntityInvocationHandler) Proxy.getInvocationHandler(proxy);
-
-        final AttachedEntityStatus status = factory.getContext().entityContext().getStatus(target);
-
-        final URI editLink = target.getEntity().getEditLink();
-
-        if ((status == AttachedEntityStatus.ATTACHED || status == AttachedEntityStatus.LINKED) && !target.isChanged()) {
-          entity.addLink(buildNavigationLink(
-                  property.getKey().name(),
-                  URIUtils.getURI(serviceRoot, editLink.toASCIIString()), type));
-        } else {
-          if (!items.contains(target)) {
-            pos = processEntityContext(target, pos, items, delayedUpdates, changeset);
-            pos++;
-          }
-
-          final Integer targetPos = items.get(target);
-          if (targetPos == null) {
-            // schedule update for the current object
-            LOG.debug("Schedule '{}' from '{}' to '{}'", type.name(), handler, target);
-            toBeLinked.add(target);
-          } else if (status == AttachedEntityStatus.CHANGED) {
-            entity.addLink(buildNavigationLink(
-                    property.getKey().name(),
-                    URIUtils.getURI(serviceRoot, editLink.toASCIIString()), type));
-          } else {
-            // create the link for the current object
-            LOG.debug("'{}' from '{}' to (${}) '{}'", type.name(), handler, targetPos, target);
-
-            entity.addLink(buildNavigationLink(property.getKey().name(), URI.create("$" + targetPos), type));
-          }
-        }
-      }
-
-      if (!toBeLinked.isEmpty()) {
-        delayedUpdates.add(new EntityLinkDesc(property.getKey().name(), handler, toBeLinked, type));
-      }
-    }
-
-    // insert into the batch
-    LOG.debug("{}: Insert '{}' into the batch", pos, handler);
-    batch(handler, entity, changeset);
-
-    items.put(handler, pos);
-
-    int startingPos = pos;
-
-    if (handler.getEntity().isMediaEntity()) {
-
-      // update media properties
-      if (!handler.getPropertyChanges().isEmpty()) {
-        final URI targetURI = currentStatus == AttachedEntityStatus.NEW
-                ? URI.create("$" + startingPos)
-                : URIUtils.getURI(
-                        factory.getClient().getServiceRoot(),
-                        handler.getEntity().getEditLink().toASCIIString());
-        batchUpdate(handler, targetURI, entity, changeset);
-        pos++;
-        items.put(handler, pos);
-      }
-
-      // update media content
-      if (handler.getStreamChanges() != null) {
-        final URI targetURI = currentStatus == AttachedEntityStatus.NEW
-                ? URI.create("$" + startingPos + "/$value")
-                : URIUtils.getURI(
-                        factory.getClient().getServiceRoot(),
-                        handler.getEntity().getEditLink().toASCIIString() + "/$value");
-
-        batchUpdateMediaEntity(handler, targetURI, handler.getStreamChanges(), changeset);
-
-        // update media info (use null key)
-        pos++;
-        items.put(null, pos);
-      }
-    }
-
-    for (Map.Entry<String, InputStream> streamedChanges : handler.getStreamedPropertyChanges().entrySet()) {
-      final URI targetURI = currentStatus == AttachedEntityStatus.NEW
-              ? URI.create("$" + startingPos) : URIUtils.getURI(
-                      factory.getClient().getServiceRoot(),
-                      CoreUtils.getMediaEditLink(streamedChanges.getKey(), entity).toASCIIString());
-
-      batchUpdateMediaResource(handler, targetURI, streamedChanges.getValue(), changeset);
-
-      // update media info (use null key)
-      pos++;
-      items.put(handler, pos);
-    }
-
-    return pos;
-  }
-
-  private ODataLink buildNavigationLink(final String name, final URI uri, final ODataLinkType type) {
-    ODataLink result;
-
-    switch (type) {
-      case ENTITY_NAVIGATION:
-        result = factory.getClient().getObjectFactory().newEntityNavigationLink(name, uri);
-        break;
-
-      case ENTITY_SET_NAVIGATION:
-        result = factory.getClient().getObjectFactory().newEntitySetNavigationLink(name, uri);
-        break;
-
-      default:
-        throw new IllegalArgumentException("Invalid link type " + type.name());
-    }
-
-    return result;
-  }
-
-  private void processDelayedUpdates(
-          final List<EntityLinkDesc> delayedUpdates,
-          int pos,
-          final TransactionItems items,
-          final ODataChangeset changeset) {
-
-    for (EntityLinkDesc delayedUpdate : delayedUpdates) {
-      pos++;
-      items.put(delayedUpdate.getSource(), pos);
-
-      final CommonODataEntity changes =
-              factory.getClient().getObjectFactory().newEntity(delayedUpdate.getSource().getEntity().getTypeName());
-
-      AttachedEntityStatus status = factory.getContext().entityContext().getStatus(delayedUpdate.getSource());
-
-      final URI sourceURI;
-      if (status == AttachedEntityStatus.CHANGED) {
-        sourceURI = URIUtils.getURI(
-                factory.getClient().getServiceRoot(),
-                delayedUpdate.getSource().getEntity().getEditLink().toASCIIString());
-      } else {
-        int sourcePos = items.get(delayedUpdate.getSource());
-        sourceURI = URI.create("$" + sourcePos);
-      }
-
-      for (EntityInvocationHandler target : delayedUpdate.getTargets()) {
-        status = factory.getContext().entityContext().getStatus(target);
-
-        final URI targetURI;
-        if (status == AttachedEntityStatus.CHANGED) {
-          targetURI = URIUtils.getURI(
-                  factory.getClient().getServiceRoot(), target.getEntity().getEditLink().toASCIIString());
-        } else {
-          int targetPos = items.get(target);
-          targetURI = URI.create("$" + targetPos);
-        }
-
-        changes.addLink(delayedUpdate.getType() == ODataLinkType.ENTITY_NAVIGATION
-                ? factory.getClient().getObjectFactory().
-                newEntityNavigationLink(delayedUpdate.getSourceName(), targetURI)
-                : factory.getClient().getObjectFactory().
-                newEntitySetNavigationLink(delayedUpdate.getSourceName(), targetURI));
-
-        LOG.debug("'{}' from {} to {}", delayedUpdate.getType().name(), sourceURI, targetURI);
-      }
-
-      batchUpdate(delayedUpdate.getSource(), sourceURI, changes, changeset);
-    }
-  }
-
-  private class TransactionItems {
-
-    private final List<EntityInvocationHandler> keys = new ArrayList<EntityInvocationHandler>();
-
-    private final List<Integer> values = new ArrayList<Integer>();
-
-    public EntityInvocationHandler get(final Integer value) {
-      if (value != null && values.contains(value)) {
-        return keys.get(values.indexOf(value));
-      } else {
-        return null;
-      }
-    }
-
-    public Integer get(final EntityInvocationHandler key) {
-      if (key != null && keys.contains(key)) {
-        return values.get(keys.indexOf(key));
-      } else {
-        return null;
-      }
-    }
-
-    public void remove(final EntityInvocationHandler key) {
-      if (keys.contains(key)) {
-        values.remove(keys.indexOf(key));
-        keys.remove(key);
-      }
-    }
-
-    public void put(final EntityInvocationHandler key, final Integer value) {
-      // replace just in case of null current value; otherwise add the new entry
-      if (key != null && keys.contains(key) && values.get(keys.indexOf(key)) == null) {
-        remove(key);
-      }
-      keys.add(key);
-      values.add(value);
-    }
-
-    public List<Integer> sortedValues() {
-      final List<Integer> sortedValues = new ArrayList<Integer>(values);
-      Collections.<Integer>sort(sortedValues);
-      return sortedValues;
-    }
-
-    public boolean contains(final EntityInvocationHandler key) {
-      return keys.contains(key);
-    }
-
-    public int size() {
-      return keys.size();
-    }
-
-    public boolean isEmpty() {
-      return keys.isEmpty();
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8a3a1e03/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityContainerInvocationHandler.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityContainerInvocationHandler.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityContainerInvocationHandler.java
index 16b9bbf..3bbeae3 100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityContainerInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityContainerInvocationHandler.java
@@ -84,7 +84,7 @@ public final class EntityContainerInvocationHandler extends AbstractInvocationHa
     if (isSelfMethod(method, args)) {
       return invokeSelfMethod(method, args);
     } else if ("flush".equals(method.getName()) && ArrayUtils.isEmpty(args)) {
-      new ContainerImpl(factory).flush();
+      new PersistenceManagerImpl(factory).flush();
       return ClassUtils.returnVoid();
     } else if ("operations".equals(method.getName()) && ArrayUtils.isEmpty(args)) {
       final Class<?> returnType = method.getReturnType();

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8a3a1e03/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/PersistenceManagerImpl.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/PersistenceManagerImpl.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/PersistenceManagerImpl.java
new file mode 100644
index 0000000..9c39c95
--- /dev/null
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/PersistenceManagerImpl.java
@@ -0,0 +1,551 @@
+/*
+ * 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.reflect.Proxy;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.olingo.client.api.communication.header.ODataPreferences;
+import org.apache.olingo.client.api.communication.request.ODataRequest;
+import org.apache.olingo.client.api.communication.request.ODataStreamedRequest;
+import org.apache.olingo.client.api.communication.request.batch.BatchStreamManager;
+import org.apache.olingo.client.api.communication.request.batch.CommonODataBatchRequest;
+import org.apache.olingo.client.api.communication.request.batch.ODataBatchResponseItem;
+import org.apache.olingo.client.api.communication.request.batch.ODataChangeset;
+import org.apache.olingo.client.api.communication.request.cud.ODataDeleteRequest;
+import org.apache.olingo.client.api.communication.request.cud.ODataEntityUpdateRequest;
+import org.apache.olingo.client.api.communication.request.streamed.ODataMediaEntityUpdateRequest;
+import org.apache.olingo.client.api.communication.request.streamed.ODataStreamUpdateRequest;
+import org.apache.olingo.client.api.communication.response.ODataBatchResponse;
+import org.apache.olingo.client.api.communication.response.ODataEntityCreateResponse;
+import org.apache.olingo.client.api.communication.response.ODataEntityUpdateResponse;
+import org.apache.olingo.client.api.communication.response.ODataResponse;
+import org.apache.olingo.client.core.communication.request.batch.ODataChangesetResponseItem;
+import org.apache.olingo.client.core.uri.URIUtils;
+import org.apache.olingo.commons.api.domain.CommonODataEntity;
+import org.apache.olingo.commons.api.domain.ODataLink;
+import org.apache.olingo.commons.api.domain.ODataLinkType;
+import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
+import org.apache.olingo.commons.api.format.ODataMediaFormat;
+import org.apache.olingo.ext.proxy.EntityContainerFactory;
+import org.apache.olingo.ext.proxy.api.PersistenceManager;
+import org.apache.olingo.ext.proxy.api.annotations.NavigationProperty;
+import org.apache.olingo.ext.proxy.context.AttachedEntity;
+import org.apache.olingo.ext.proxy.context.AttachedEntityStatus;
+import org.apache.olingo.ext.proxy.context.EntityLinkDesc;
+import org.apache.olingo.ext.proxy.utils.CoreUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class PersistenceManagerImpl implements PersistenceManager {
+
+  private static final long serialVersionUID = -3320312269235907501L;
+
+  /**
+   * Logger.
+   */
+  private static final Logger LOG = LoggerFactory.getLogger(PersistenceManagerImpl.class);
+
+  private final EntityContainerFactory<?> factory;
+
+  PersistenceManagerImpl(final EntityContainerFactory<?> factory) {
+    this.factory = factory;
+  }
+
+  /**
+   * Transactional changes commit.
+   */
+  @Override
+  public void flush() {
+    final CommonODataBatchRequest request =
+            factory.getClient().getBatchRequestFactory().getBatchRequest(factory.getClient().getServiceRoot());
+    ((ODataRequest) request).setAccept(factory.getClient().getConfiguration().getDefaultBatchAcceptFormat());
+
+    final BatchStreamManager streamManager = (BatchStreamManager) ((ODataStreamedRequest) request).execute();
+
+    final ODataChangeset changeset = streamManager.addChangeset();
+
+    final TransactionItems items = new TransactionItems();
+    final List<EntityLinkDesc> delayedUpdates = new ArrayList<EntityLinkDesc>();
+
+    int pos = 0;
+
+    for (AttachedEntity attachedEntity : factory.getContext().entityContext()) {
+      final AttachedEntityStatus status = attachedEntity.getStatus();
+      if (((status != AttachedEntityStatus.ATTACHED
+              && status != AttachedEntityStatus.LINKED) || attachedEntity.getEntity().isChanged())
+              && !items.contains(attachedEntity.getEntity())) {
+        pos++;
+        pos = processEntityContext(attachedEntity.getEntity(), pos, items, delayedUpdates, changeset);
+      }
+    }
+
+    processDelayedUpdates(delayedUpdates, pos, items, changeset);
+
+    final ODataBatchResponse response = streamManager.getResponse();
+
+    if ((factory.getClient().getServiceVersion().compareTo(ODataServiceVersion.V30) <= 0
+            && response.getStatusCode() != 202)
+            || (factory.getClient().getServiceVersion().compareTo(ODataServiceVersion.V30) > 0
+            && response.getStatusCode() != 200)) {
+
+      throw new IllegalStateException("Operation failed");
+    }
+
+    if (!items.isEmpty()) {
+      final Iterator<ODataBatchResponseItem> iter = response.getBody();
+      if (!iter.hasNext()) {
+        throw new IllegalStateException("Unexpected operation result");
+      }
+
+      final ODataBatchResponseItem item = iter.next();
+      if (!(item instanceof ODataChangesetResponseItem)) {
+        throw new IllegalStateException("Unexpected batch response item " + item.getClass().getSimpleName());
+      }
+
+      final ODataChangesetResponseItem chgres = (ODataChangesetResponseItem) item;
+
+      for (Integer changesetItemId : items.sortedValues()) {
+        LOG.debug("Expected changeset item {}", changesetItemId);
+        final ODataResponse res = chgres.next();
+        if (res.getStatusCode() >= 400) {
+          throw new IllegalStateException("Transaction failed: " + res.getStatusMessage());
+        }
+
+        final EntityInvocationHandler handler = items.get(changesetItemId);
+
+        if (handler != null) {
+          if (res instanceof ODataEntityCreateResponse && res.getStatusCode() == 201) {
+            handler.setEntity(((ODataEntityCreateResponse) res).getBody());
+            LOG.debug("Upgrade created object '{}'", handler);
+          } else if (res instanceof ODataEntityUpdateResponse && res.getStatusCode() == 200) {
+            handler.setEntity(((ODataEntityUpdateResponse) res).getBody());
+            LOG.debug("Upgrade updated object '{}'", handler);
+          }
+        }
+      }
+    }
+
+    factory.getContext().detachAll();
+  }
+
+  private void batch(
+          final EntityInvocationHandler handler,
+          final CommonODataEntity entity,
+          final ODataChangeset changeset) {
+
+    switch (factory.getContext().entityContext().getStatus(handler)) {
+      case NEW:
+        batchCreate(handler, entity, changeset);
+        break;
+
+      case CHANGED:
+        batchUpdate(handler, entity, changeset);
+        break;
+
+      case DELETED:
+        batchDelete(handler, entity, changeset);
+        break;
+
+      default:
+        if (handler.isChanged()) {
+          batchUpdate(handler, entity, changeset);
+        }
+    }
+  }
+
+  private void batchCreate(
+          final EntityInvocationHandler handler,
+          final CommonODataEntity entity,
+          final ODataChangeset changeset) {
+
+    LOG.debug("Create '{}'", handler);
+
+    changeset.addRequest(
+            factory.getClient().getCUDRequestFactory().getEntityCreateRequest(handler.getEntitySetURI(), entity));
+  }
+
+  private void batchUpdateMediaEntity(
+          final EntityInvocationHandler handler,
+          final URI uri,
+          final InputStream input,
+          final ODataChangeset changeset) {
+
+    LOG.debug("Update media entity '{}'", uri);
+
+    final ODataMediaEntityUpdateRequest<?> req =
+            factory.getClient().getStreamedRequestFactory().getMediaEntityUpdateRequest(uri, input);
+
+    req.setContentType(StringUtils.isBlank(handler.getEntity().getMediaContentType())
+            ? ODataMediaFormat.WILDCARD.toString()
+            : ODataMediaFormat.fromFormat(handler.getEntity().getMediaContentType()).toString());
+
+    if (StringUtils.isNotBlank(handler.getETag())) {
+      req.setIfMatch(handler.getETag());
+    }
+
+    changeset.addRequest(req);
+  }
+
+  private void batchUpdateMediaResource(
+          final EntityInvocationHandler handler,
+          final URI uri,
+          final InputStream input,
+          final ODataChangeset changeset) {
+
+    LOG.debug("Update media entity '{}'", uri);
+
+    final ODataStreamUpdateRequest req = factory.getClient().
+            getStreamedRequestFactory().getStreamUpdateRequest(uri, input);
+
+    if (StringUtils.isNotBlank(handler.getETag())) {
+      req.setIfMatch(handler.getETag());
+    }
+
+    changeset.addRequest(req);
+  }
+
+  private void batchUpdate(
+          final EntityInvocationHandler handler,
+          final CommonODataEntity changes,
+          final ODataChangeset changeset) {
+
+    LOG.debug("Update '{}'", handler.getEntityURI());
+
+    final ODataEntityUpdateRequest<CommonODataEntity> req =
+            factory.getClient().getServiceVersion().compareTo(ODataServiceVersion.V30) <= 0
+            ? ((org.apache.olingo.client.api.v3.EdmEnabledODataClient) factory.getClient()).getCUDRequestFactory().
+            getEntityUpdateRequest(handler.getEntityURI(),
+                    org.apache.olingo.client.api.communication.request.cud.v3.UpdateType.PATCH, changes)
+            : ((org.apache.olingo.client.api.v4.EdmEnabledODataClient) factory.getClient()).getCUDRequestFactory().
+            getEntityUpdateRequest(handler.getEntityURI(),
+                    org.apache.olingo.client.api.communication.request.cud.v4.UpdateType.PATCH, changes);
+
+    req.setPrefer(new ODataPreferences(factory.getClient().getServiceVersion()).returnContent());
+
+    if (StringUtils.isNotBlank(handler.getETag())) {
+      req.setIfMatch(handler.getETag());
+    }
+
+    changeset.addRequest(req);
+  }
+
+  private void batchUpdate(
+          final EntityInvocationHandler handler,
+          final URI uri,
+          final CommonODataEntity changes,
+          final ODataChangeset changeset) {
+
+    LOG.debug("Update '{}'", uri);
+
+    final ODataEntityUpdateRequest<CommonODataEntity> req =
+            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)
+            : ((org.apache.olingo.client.api.v4.EdmEnabledODataClient) factory.getClient()).getCUDRequestFactory().
+            getEntityUpdateRequest(uri,
+                    org.apache.olingo.client.api.communication.request.cud.v4.UpdateType.PATCH, changes);
+
+    req.setPrefer(new ODataPreferences(factory.getClient().getServiceVersion()).returnContent());
+
+    if (StringUtils.isNotBlank(handler.getETag())) {
+      req.setIfMatch(handler.getETag());
+    }
+
+    changeset.addRequest(req);
+  }
+
+  private void batchDelete(
+          final EntityInvocationHandler handler,
+          final CommonODataEntity entity,
+          final ODataChangeset changeset) {
+
+    final URI deleteURI = handler.getEntityURI() == null ? entity.getEditLink() : handler.getEntityURI();
+    LOG.debug("Delete '{}'", deleteURI);
+
+    final ODataDeleteRequest req = factory.getClient().getCUDRequestFactory().getDeleteRequest(deleteURI);
+
+    if (StringUtils.isNotBlank(handler.getETag())) {
+      req.setIfMatch(handler.getETag());
+    }
+
+    changeset.addRequest(req);
+  }
+
+  private int processEntityContext(
+          final EntityInvocationHandler handler,
+          int pos,
+          final TransactionItems items,
+          final List<EntityLinkDesc> delayedUpdates,
+          final ODataChangeset changeset) {
+
+    LOG.debug("Process '{}'", handler);
+
+    items.put(handler, null);
+
+    final CommonODataEntity entity = handler.getEntity();
+    entity.getNavigationLinks().clear();
+
+    final AttachedEntityStatus currentStatus = factory.getContext().entityContext().getStatus(handler);
+
+    if (AttachedEntityStatus.DELETED != currentStatus) {
+      entity.getProperties().clear();
+      CoreUtils.addProperties(factory.getClient(), handler.getPropertyChanges(), entity);
+    }
+
+    for (Map.Entry<NavigationProperty, Object> property : handler.getLinkChanges().entrySet()) {
+      final ODataLinkType type = Collection.class.isAssignableFrom(property.getValue().getClass())
+              ? ODataLinkType.ENTITY_SET_NAVIGATION
+              : ODataLinkType.ENTITY_NAVIGATION;
+
+      final Set<EntityInvocationHandler> toBeLinked = new HashSet<EntityInvocationHandler>();
+      final String serviceRoot = factory.getClient().getServiceRoot();
+
+      for (Object proxy : type == ODataLinkType.ENTITY_SET_NAVIGATION
+              ? (Collection) property.getValue() : Collections.singleton(property.getValue())) {
+
+        final EntityInvocationHandler target = (EntityInvocationHandler) Proxy.getInvocationHandler(proxy);
+
+        final AttachedEntityStatus status = factory.getContext().entityContext().getStatus(target);
+
+        final URI editLink = target.getEntity().getEditLink();
+
+        if ((status == AttachedEntityStatus.ATTACHED || status == AttachedEntityStatus.LINKED) && !target.isChanged()) {
+          entity.addLink(buildNavigationLink(
+                  property.getKey().name(),
+                  URIUtils.getURI(serviceRoot, editLink.toASCIIString()), type));
+        } else {
+          if (!items.contains(target)) {
+            pos = processEntityContext(target, pos, items, delayedUpdates, changeset);
+            pos++;
+          }
+
+          final Integer targetPos = items.get(target);
+          if (targetPos == null) {
+            // schedule update for the current object
+            LOG.debug("Schedule '{}' from '{}' to '{}'", type.name(), handler, target);
+            toBeLinked.add(target);
+          } else if (status == AttachedEntityStatus.CHANGED) {
+            entity.addLink(buildNavigationLink(
+                    property.getKey().name(),
+                    URIUtils.getURI(serviceRoot, editLink.toASCIIString()), type));
+          } else {
+            // create the link for the current object
+            LOG.debug("'{}' from '{}' to (${}) '{}'", type.name(), handler, targetPos, target);
+
+            entity.addLink(buildNavigationLink(property.getKey().name(), URI.create("$" + targetPos), type));
+          }
+        }
+      }
+
+      if (!toBeLinked.isEmpty()) {
+        delayedUpdates.add(new EntityLinkDesc(property.getKey().name(), handler, toBeLinked, type));
+      }
+    }
+
+    // insert into the batch
+    LOG.debug("{}: Insert '{}' into the batch", pos, handler);
+    batch(handler, entity, changeset);
+
+    items.put(handler, pos);
+
+    int startingPos = pos;
+
+    if (handler.getEntity().isMediaEntity()) {
+
+      // update media properties
+      if (!handler.getPropertyChanges().isEmpty()) {
+        final URI targetURI = currentStatus == AttachedEntityStatus.NEW
+                ? URI.create("$" + startingPos)
+                : URIUtils.getURI(
+                        factory.getClient().getServiceRoot(),
+                        handler.getEntity().getEditLink().toASCIIString());
+        batchUpdate(handler, targetURI, entity, changeset);
+        pos++;
+        items.put(handler, pos);
+      }
+
+      // update media content
+      if (handler.getStreamChanges() != null) {
+        final URI targetURI = currentStatus == AttachedEntityStatus.NEW
+                ? URI.create("$" + startingPos + "/$value")
+                : URIUtils.getURI(
+                        factory.getClient().getServiceRoot(),
+                        handler.getEntity().getEditLink().toASCIIString() + "/$value");
+
+        batchUpdateMediaEntity(handler, targetURI, handler.getStreamChanges(), changeset);
+
+        // update media info (use null key)
+        pos++;
+        items.put(null, pos);
+      }
+    }
+
+    for (Map.Entry<String, InputStream> streamedChanges : handler.getStreamedPropertyChanges().entrySet()) {
+      final URI targetURI = currentStatus == AttachedEntityStatus.NEW
+              ? URI.create("$" + startingPos) : URIUtils.getURI(
+                      factory.getClient().getServiceRoot(),
+                      CoreUtils.getMediaEditLink(streamedChanges.getKey(), entity).toASCIIString());
+
+      batchUpdateMediaResource(handler, targetURI, streamedChanges.getValue(), changeset);
+
+      // update media info (use null key)
+      pos++;
+      items.put(handler, pos);
+    }
+
+    return pos;
+  }
+
+  private ODataLink buildNavigationLink(final String name, final URI uri, final ODataLinkType type) {
+    ODataLink result;
+
+    switch (type) {
+      case ENTITY_NAVIGATION:
+        result = factory.getClient().getObjectFactory().newEntityNavigationLink(name, uri);
+        break;
+
+      case ENTITY_SET_NAVIGATION:
+        result = factory.getClient().getObjectFactory().newEntitySetNavigationLink(name, uri);
+        break;
+
+      default:
+        throw new IllegalArgumentException("Invalid link type " + type.name());
+    }
+
+    return result;
+  }
+
+  private void processDelayedUpdates(
+          final List<EntityLinkDesc> delayedUpdates,
+          int pos,
+          final TransactionItems items,
+          final ODataChangeset changeset) {
+
+    for (EntityLinkDesc delayedUpdate : delayedUpdates) {
+      pos++;
+      items.put(delayedUpdate.getSource(), pos);
+
+      final CommonODataEntity changes =
+              factory.getClient().getObjectFactory().newEntity(delayedUpdate.getSource().getEntity().getTypeName());
+
+      AttachedEntityStatus status = factory.getContext().entityContext().getStatus(delayedUpdate.getSource());
+
+      final URI sourceURI;
+      if (status == AttachedEntityStatus.CHANGED) {
+        sourceURI = URIUtils.getURI(
+                factory.getClient().getServiceRoot(),
+                delayedUpdate.getSource().getEntity().getEditLink().toASCIIString());
+      } else {
+        int sourcePos = items.get(delayedUpdate.getSource());
+        sourceURI = URI.create("$" + sourcePos);
+      }
+
+      for (EntityInvocationHandler target : delayedUpdate.getTargets()) {
+        status = factory.getContext().entityContext().getStatus(target);
+
+        final URI targetURI;
+        if (status == AttachedEntityStatus.CHANGED) {
+          targetURI = URIUtils.getURI(
+                  factory.getClient().getServiceRoot(), target.getEntity().getEditLink().toASCIIString());
+        } else {
+          int targetPos = items.get(target);
+          targetURI = URI.create("$" + targetPos);
+        }
+
+        changes.addLink(delayedUpdate.getType() == ODataLinkType.ENTITY_NAVIGATION
+                ? factory.getClient().getObjectFactory().
+                newEntityNavigationLink(delayedUpdate.getSourceName(), targetURI)
+                : factory.getClient().getObjectFactory().
+                newEntitySetNavigationLink(delayedUpdate.getSourceName(), targetURI));
+
+        LOG.debug("'{}' from {} to {}", delayedUpdate.getType().name(), sourceURI, targetURI);
+      }
+
+      batchUpdate(delayedUpdate.getSource(), sourceURI, changes, changeset);
+    }
+  }
+
+  private class TransactionItems {
+
+    private final List<EntityInvocationHandler> keys = new ArrayList<EntityInvocationHandler>();
+
+    private final List<Integer> values = new ArrayList<Integer>();
+
+    public EntityInvocationHandler get(final Integer value) {
+      if (value != null && values.contains(value)) {
+        return keys.get(values.indexOf(value));
+      } else {
+        return null;
+      }
+    }
+
+    public Integer get(final EntityInvocationHandler key) {
+      if (key != null && keys.contains(key)) {
+        return values.get(keys.indexOf(key));
+      } else {
+        return null;
+      }
+    }
+
+    public void remove(final EntityInvocationHandler key) {
+      if (keys.contains(key)) {
+        values.remove(keys.indexOf(key));
+        keys.remove(key);
+      }
+    }
+
+    public void put(final EntityInvocationHandler key, final Integer value) {
+      // replace just in case of null current value; otherwise add the new entry
+      if (key != null && keys.contains(key) && values.get(keys.indexOf(key)) == null) {
+        remove(key);
+      }
+      keys.add(key);
+      values.add(value);
+    }
+
+    public List<Integer> sortedValues() {
+      final List<Integer> sortedValues = new ArrayList<Integer>(values);
+      Collections.<Integer>sort(sortedValues);
+      return sortedValues;
+    }
+
+    public boolean contains(final EntityInvocationHandler key) {
+      return keys.contains(key);
+    }
+
+    public int size() {
+      return keys.size();
+    }
+
+    public boolean isEmpty() {
+      return keys.isEmpty();
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8a3a1e03/ext/pojogen-maven-plugin/src/main/resources/container.vm
----------------------------------------------------------------------
diff --git a/ext/pojogen-maven-plugin/src/main/resources/container.vm b/ext/pojogen-maven-plugin/src/main/resources/container.vm
index 362018d..d31024b 100644
--- a/ext/pojogen-maven-plugin/src/main/resources/container.vm
+++ b/ext/pojogen-maven-plugin/src/main/resources/container.vm
@@ -25,7 +25,7 @@ import org.apache.olingo.ext.proxy.api.annotations.EntityContainer;
 import org.apache.olingo.ext.proxy.api.annotations.Operation;
 import org.apache.olingo.ext.proxy.api.annotations.Parameter;
 import org.apache.olingo.ext.proxy.api.annotations.Property;
-import org.apache.olingo.ext.proxy.api.Container;
+import org.apache.olingo.ext.proxy.api.PersistenceManager;
 import org.apache.olingo.ext.proxy.api.OperationType;
 #foreach($ns in $namespaces)
 import ${basePackage}.${ns}.*;
@@ -52,7 +52,7 @@ import javax.xml.datatype.Duration;
 @EntityContainer(name = "$container.Name",
   namespace = "$namespace",
   isDefaultEntityContainer = $container.Default)
-public interface $utility.capitalize($container.Name) extends Container {
+public interface $utility.capitalize($container.Name) extends PersistenceManager {
 
 #foreach($entitySet in $container.EntitySets)
     $utility.capitalize($entitySet.Name) get$utility.capitalize($entitySet.Name)();

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8a3a1e03/fit/src/test/java/org/apache/olingo/fit/proxy/v3/actionoverloading/microsoft/test/odata/services/astoriadefaultservice/DefaultContainer.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/proxy/v3/actionoverloading/microsoft/test/odata/services/astoriadefaultservice/DefaultContainer.java b/fit/src/test/java/org/apache/olingo/fit/proxy/v3/actionoverloading/microsoft/test/odata/services/astoriadefaultservice/DefaultContainer.java
index a89563e..784a96f 100644
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/v3/actionoverloading/microsoft/test/odata/services/astoriadefaultservice/DefaultContainer.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/v3/actionoverloading/microsoft/test/odata/services/astoriadefaultservice/DefaultContainer.java
@@ -25,7 +25,7 @@ import org.apache.olingo.ext.proxy.api.annotations.EntityContainer;
 import org.apache.olingo.ext.proxy.api.annotations.Operation;
 import org.apache.olingo.ext.proxy.api.annotations.Parameter;
 import org.apache.olingo.ext.proxy.api.annotations.Property;
-import org.apache.olingo.ext.proxy.api.Container;
+import org.apache.olingo.ext.proxy.api.PersistenceManager;
 import org.apache.olingo.ext.proxy.api.OperationType;
 import org.apache.olingo.fit.proxy.v3.actionoverloading.microsoft.test.odata.services.astoriadefaultservice.*;
 import org.apache.olingo.fit.proxy.v3.actionoverloading.microsoft.test.odata.services.astoriadefaultservice.types.*;
@@ -50,7 +50,7 @@ import javax.xml.datatype.Duration;
 @EntityContainer(name = "DefaultContainer",
   namespace = "Microsoft.Test.OData.Services.AstoriaDefaultService",
   isDefaultEntityContainer = true)
-public interface DefaultContainer extends Container {
+public interface DefaultContainer extends PersistenceManager {
 
     Customer getCustomer();
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8a3a1e03/fit/src/test/java/org/apache/olingo/fit/proxy/v3/opentype/microsoft/test/odata/services/opentypesservicev3/DefaultContainer.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/proxy/v3/opentype/microsoft/test/odata/services/opentypesservicev3/DefaultContainer.java b/fit/src/test/java/org/apache/olingo/fit/proxy/v3/opentype/microsoft/test/odata/services/opentypesservicev3/DefaultContainer.java
index 513c854..95186f1 100644
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/v3/opentype/microsoft/test/odata/services/opentypesservicev3/DefaultContainer.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/v3/opentype/microsoft/test/odata/services/opentypesservicev3/DefaultContainer.java
@@ -25,7 +25,7 @@ import org.apache.olingo.ext.proxy.api.annotations.EntityContainer;
 import org.apache.olingo.ext.proxy.api.annotations.Operation;
 import org.apache.olingo.ext.proxy.api.annotations.Parameter;
 import org.apache.olingo.ext.proxy.api.annotations.Property;
-import org.apache.olingo.ext.proxy.api.Container;
+import org.apache.olingo.ext.proxy.api.PersistenceManager;
 import org.apache.olingo.ext.proxy.api.OperationType;
 import org.apache.olingo.fit.proxy.v3.opentype.microsoft.test.odata.services.opentypesservicev3.*;
 import org.apache.olingo.fit.proxy.v3.opentype.microsoft.test.odata.services.opentypesservicev3.types.*;
@@ -50,7 +50,7 @@ import javax.xml.datatype.Duration;
 @EntityContainer(name = "DefaultContainer",
   namespace = "Microsoft.Test.OData.Services.OpenTypesServiceV3",
   isDefaultEntityContainer = true)
-public interface DefaultContainer extends Container {
+public interface DefaultContainer extends PersistenceManager {
 
     Row getRow();
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8a3a1e03/fit/src/test/java/org/apache/olingo/fit/proxy/v3/primitivekeys/microsoft/test/odata/services/primitivekeysservice/TestContext.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/proxy/v3/primitivekeys/microsoft/test/odata/services/primitivekeysservice/TestContext.java b/fit/src/test/java/org/apache/olingo/fit/proxy/v3/primitivekeys/microsoft/test/odata/services/primitivekeysservice/TestContext.java
index 5e9ef59..aa4f588 100644
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/v3/primitivekeys/microsoft/test/odata/services/primitivekeysservice/TestContext.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/v3/primitivekeys/microsoft/test/odata/services/primitivekeysservice/TestContext.java
@@ -25,7 +25,7 @@ import org.apache.olingo.ext.proxy.api.annotations.EntityContainer;
 import org.apache.olingo.ext.proxy.api.annotations.Operation;
 import org.apache.olingo.ext.proxy.api.annotations.Parameter;
 import org.apache.olingo.ext.proxy.api.annotations.Property;
-import org.apache.olingo.ext.proxy.api.Container;
+import org.apache.olingo.ext.proxy.api.PersistenceManager;
 import org.apache.olingo.ext.proxy.api.OperationType;
 import org.apache.olingo.fit.proxy.v3.primitivekeys.microsoft.test.odata.services.primitivekeysservice.*;
 import org.apache.olingo.fit.proxy.v3.primitivekeys.microsoft.test.odata.services.primitivekeysservice.types.*;
@@ -50,7 +50,7 @@ import javax.xml.datatype.Duration;
 @EntityContainer(name = "TestContext",
   namespace = "Microsoft.Test.OData.Services.PrimitiveKeysService",
   isDefaultEntityContainer = true)
-public interface TestContext extends Container {
+public interface TestContext extends PersistenceManager {
 
     EdmTimeSet getEdmTimeSet();
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8a3a1e03/fit/src/test/java/org/apache/olingo/fit/proxy/v3/staticservice/microsoft/test/odata/services/astoriadefaultservice/DefaultContainer.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/proxy/v3/staticservice/microsoft/test/odata/services/astoriadefaultservice/DefaultContainer.java b/fit/src/test/java/org/apache/olingo/fit/proxy/v3/staticservice/microsoft/test/odata/services/astoriadefaultservice/DefaultContainer.java
index 77b6759..894fd90 100644
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/v3/staticservice/microsoft/test/odata/services/astoriadefaultservice/DefaultContainer.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/v3/staticservice/microsoft/test/odata/services/astoriadefaultservice/DefaultContainer.java
@@ -25,7 +25,7 @@ import org.apache.olingo.ext.proxy.api.annotations.EntityContainer;
 import org.apache.olingo.ext.proxy.api.annotations.Operation;
 import org.apache.olingo.ext.proxy.api.annotations.Parameter;
 import org.apache.olingo.ext.proxy.api.annotations.Property;
-import org.apache.olingo.ext.proxy.api.Container;
+import org.apache.olingo.ext.proxy.api.PersistenceManager;
 import org.apache.olingo.ext.proxy.api.OperationType;
 import org.apache.olingo.fit.proxy.v3.staticservice.microsoft.test.odata.services.astoriadefaultservice.*;
 import org.apache.olingo.fit.proxy.v3.staticservice.microsoft.test.odata.services.astoriadefaultservice.types.*;
@@ -50,7 +50,7 @@ import javax.xml.datatype.Duration;
 @EntityContainer(name = "DefaultContainer",
   namespace = "Microsoft.Test.OData.Services.AstoriaDefaultService",
   isDefaultEntityContainer = true)
-public interface DefaultContainer extends Container {
+public interface DefaultContainer extends PersistenceManager {
 
     Customer getCustomer();
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8a3a1e03/fit/src/test/java/org/apache/olingo/fit/proxy/v4/opentype/microsoft/test/odata/services/opentypesservicev4/DefaultContainer.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/proxy/v4/opentype/microsoft/test/odata/services/opentypesservicev4/DefaultContainer.java b/fit/src/test/java/org/apache/olingo/fit/proxy/v4/opentype/microsoft/test/odata/services/opentypesservicev4/DefaultContainer.java
index 18df189..11d485e 100644
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/v4/opentype/microsoft/test/odata/services/opentypesservicev4/DefaultContainer.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/v4/opentype/microsoft/test/odata/services/opentypesservicev4/DefaultContainer.java
@@ -25,7 +25,7 @@ import org.apache.olingo.ext.proxy.api.annotations.EntityContainer;
 import org.apache.olingo.ext.proxy.api.annotations.Operation;
 import org.apache.olingo.ext.proxy.api.annotations.Parameter;
 import org.apache.olingo.ext.proxy.api.annotations.Property;
-import org.apache.olingo.ext.proxy.api.Container;
+import org.apache.olingo.ext.proxy.api.PersistenceManager;
 import org.apache.olingo.ext.proxy.api.OperationType;
 import org.apache.olingo.fit.proxy.v4.opentype.microsoft.test.odata.services.opentypesservicev4.*;
 import org.apache.olingo.fit.proxy.v4.opentype.microsoft.test.odata.services.opentypesservicev4.types.*;
@@ -50,7 +50,7 @@ import javax.xml.datatype.Duration;
 @EntityContainer(name = "DefaultContainer",
   namespace = "Microsoft.Test.OData.Services.OpenTypesServiceV4",
   isDefaultEntityContainer = true)
-public interface DefaultContainer extends Container {
+public interface DefaultContainer extends PersistenceManager {
 
     Row getRow();
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8a3a1e03/fit/src/test/java/org/apache/olingo/fit/proxy/v4/staticservice/microsoft/test/odata/services/odatawcfservice/InMemoryEntities.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/proxy/v4/staticservice/microsoft/test/odata/services/odatawcfservice/InMemoryEntities.java b/fit/src/test/java/org/apache/olingo/fit/proxy/v4/staticservice/microsoft/test/odata/services/odatawcfservice/InMemoryEntities.java
index e2256f1..5ce328d 100644
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/v4/staticservice/microsoft/test/odata/services/odatawcfservice/InMemoryEntities.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/v4/staticservice/microsoft/test/odata/services/odatawcfservice/InMemoryEntities.java
@@ -24,7 +24,7 @@ import org.apache.olingo.ext.proxy.api.annotations.EntityContainer;
 import org.apache.olingo.ext.proxy.api.annotations.Operation;
 import org.apache.olingo.ext.proxy.api.annotations.Parameter;
 import org.apache.olingo.ext.proxy.api.annotations.Property;
-import org.apache.olingo.ext.proxy.api.Container;
+import org.apache.olingo.ext.proxy.api.PersistenceManager;
 import org.apache.olingo.ext.proxy.api.OperationType;
 import org.apache.olingo.fit.proxy.v4.staticservice.microsoft.test.odata.services.odatawcfservice.*;
 import org.apache.olingo.fit.proxy.v4.staticservice.microsoft.test.odata.services.odatawcfservice.types.*;
@@ -49,7 +49,7 @@ import javax.xml.datatype.Duration;
 @EntityContainer(name = "InMemoryEntities",
   namespace = "Microsoft.Test.OData.Services.ODataWCFService",
   isDefaultEntityContainer = true)
-public interface InMemoryEntities extends Container {
+public interface InMemoryEntities extends PersistenceManager {
 
     Accounts getAccounts();
     StoredPIs getStoredPIs();


[8/9] git commit: Merge from masterù

Posted by il...@apache.org.
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/7a09dd24
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/7a09dd24
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/7a09dd24

Branch: refs/heads/master
Commit: 7a09dd248ff61291d1520afafeb59fa1f834b5a7
Parents: 8a3a1e0 72d894c
Author: Francesco Chicchiriccò <--global>
Authored: Thu May 22 12:51:01 2014 +0200
Committer: Francesco Chicchiriccò <--global>
Committed: Thu May 22 12:51:01 2014 +0200

----------------------------------------------------------------------
 ext/client-proxy-android/pom.xml                |   96 +
 ext/client-proxy/pom.xml                        |    2 +-
 .../ext/proxy/EntityContainerFactory.java       |   16 +-
 .../olingo/ext/proxy/api/AbstractOpenType.java  |    2 +
 .../olingo/ext/proxy/api/AbstractTerm.java      |   24 +
 .../olingo/ext/proxy/api/Annotatable.java       |   34 +
 .../AnnotationsForNavigationProperty.java       |   34 +
 .../api/annotations/AnnotationsForProperty.java |   34 +
 .../olingo/ext/proxy/api/annotations/Term.java  |   40 +
 .../commons/AbstractInvocationHandler.java      |   58 +-
 .../AbstractStructuredInvocationHandler.java    |  106 +-
 .../commons/AnnotatableInvocationHandler.java   |  178 +
 .../commons/AnnotatationsInvocationHandler.java |   87 +
 .../ComplexFactoryInvocationHandler.java        |    5 +-
 .../proxy/commons/ComplexInvocationHandler.java |  113 +-
 .../EntityCollectionInvocationHandler.java      |   53 +
 .../proxy/commons/EntityInvocationHandler.java  |  187 +-
 .../commons/EntitySetInvocationHandler.java     |   60 +-
 .../ext/proxy/commons/EntitySetIterator.java    |   16 +-
 .../olingo/ext/proxy/commons/FilterImpl.java    |    2 +-
 .../commons/OperationInvocationHandler.java     |    7 +-
 .../proxy/commons/PersistenceManagerImpl.java   |  123 +-
 .../olingo/ext/proxy/commons/SearchImpl.java    |    2 +-
 .../olingo/ext/proxy/context/EntityContext.java |    7 +-
 .../olingo/ext/proxy/context/EntityUUID.java    |    4 +-
 .../olingo/ext/proxy/utils/CoreUtils.java       |  197 +-
 .../olingo/ext/pojogen/AbstractPOJOGenMojo.java |   15 +-
 .../src/main/resources/complexType.vm           |    4 +
 .../src/main/resources/entityCollection.vm      |    5 +
 .../src/main/resources/entityType.vm            |   33 +-
 .../src/main/resources/services.vm              |   21 -
 .../src/main/resources/term.vm                  |   34 +
 .../src/main/resources/v40/complexType.vm       |   28 +-
 ext/pom.xml                                     |    1 +
 fit/pom.xml                                     |    1 +
 fit/src/it/demoV4/pom.xml                       |   93 +
 fit/src/it/demoV4/verify.groovy                 |   20 +
 .../org/apache/olingo/fit/AbstractServices.java |   13 +-
 .../apache/olingo/fit/V3ActionOverloading.java  |    2 +-
 .../java/org/apache/olingo/fit/V3OpenType.java  |    2 +-
 .../org/apache/olingo/fit/V3PrimitiveKeys.java  |    2 +-
 .../java/org/apache/olingo/fit/V3Services.java  |   16 +-
 .../main/java/org/apache/olingo/fit/V4Demo.java |   31 +-
 .../java/org/apache/olingo/fit/V4OpenType.java  |    2 +-
 .../java/org/apache/olingo/fit/V4Services.java  |   65 +-
 .../org/apache/olingo/fit/V4Vocabularies.java   |    4 +-
 .../org/apache/olingo/fit/utils/DataBinder.java |   94 +-
 .../org/apache/olingo/fit/utils/FSManager.java  |   74 +-
 .../apache/olingo/fit/utils/XMLUtilities.java   |    2 +-
 .../resources/V40/Accounts/102/entity.full.json |   34 +
 .../main/resources/V40/Accounts/102/entity.xml  |   55 +
 .../V40/Accounts/102/links/MyGiftCard.full.json |   15 +
 .../V40/Accounts/102/links/MyGiftCard.xml       |   41 +
 .../MyPaymentInstruments(102901).full.json      |   16 +
 .../102/links/MyPaymentInstruments(102901).xml  |   40 +
 .../MyPaymentInstruments(102902).full.json      |   16 +
 .../102/links/MyPaymentInstruments(102902).xml  |   40 +
 .../102/links/MyPaymentInstruments.full.json    |   62 +
 .../Accounts/102/links/MyPaymentInstruments.xml |   95 +
 .../main/resources/V40/Boss/entity.full.json    |    2 +
 fit/src/main/resources/V40/Boss/entity.xml      |    5 +-
 fit/src/main/resources/V40/openTypeMetadata.xml |    4 +
 .../olingo/fit/proxy/v3/AbstractTestITCase.java |    3 -
 .../proxy/v3/AuthEntityRetrieveTestITCase.java  |   48 -
 .../fit/proxy/v3/EntityCreateTestITCase.java    |    2 +-
 .../fit/proxy/v3/MediaEntityTestITCase.java     |  107 +
 .../olingo/fit/proxy/v3/OpenTypeTestITCase.java |    9 +-
 .../olingo/fit/proxy/v4/AbstractTestITCase.java |    5 +-
 .../proxy/v4/AuthEntityCreateTestITCase.java    |   52 +
 .../proxy/v4/AuthEntityRetrieveTestITCase.java  |    4 +-
 .../fit/proxy/v4/EntityCreateTestITCase.java    |  107 +-
 .../fit/proxy/v4/MediaEntityTestITCase.java     |  106 +
 .../olingo/fit/proxy/v4/OpenTypeTestITCase.java |   20 +-
 .../fit/proxy/v4/SingletonTestITCase.java       |   32 +
 .../proxy/v4/demo/odatademo/Advertisements.java |   52 +
 .../fit/proxy/v4/demo/odatademo/Categories.java |   52 +
 .../proxy/v4/demo/odatademo/DemoService.java    |   85 +
 .../proxy/v4/demo/odatademo/PersonDetails.java  |   52 +
 .../fit/proxy/v4/demo/odatademo/Persons.java    |   56 +
 .../proxy/v4/demo/odatademo/ProductDetails.java |   52 +
 .../fit/proxy/v4/demo/odatademo/Products.java   |   54 +
 .../fit/proxy/v4/demo/odatademo/Suppliers.java  |   52 +
 .../proxy/v4/demo/odatademo/package-info.java   |   21 +
 .../proxy/v4/demo/odatademo/types/Address.java  |  140 +
 .../v4/demo/odatademo/types/Advertisement.java  |  150 +
 .../types/AdvertisementCollection.java          |   47 +
 .../proxy/v4/demo/odatademo/types/Category.java |  124 +
 .../odatademo/types/CategoryCollection.java     |   47 +
 .../proxy/v4/demo/odatademo/types/Customer.java |  148 +
 .../odatademo/types/CustomerCollection.java     |   47 +
 .../proxy/v4/demo/odatademo/types/Employee.java |  194 +
 .../odatademo/types/EmployeeCollection.java     |   47 +
 .../demo/odatademo/types/FeaturedProduct.java   |  276 +
 .../types/FeaturedProductCollection.java        |   47 +
 .../proxy/v4/demo/odatademo/types/Person.java   |  124 +
 .../demo/odatademo/types/PersonCollection.java  |   47 +
 .../v4/demo/odatademo/types/PersonDetail.java   |  224 +
 .../odatademo/types/PersonDetailCollection.java |   47 +
 .../proxy/v4/demo/odatademo/types/Product.java  |  271 +
 .../demo/odatademo/types/ProductCollection.java |   47 +
 .../v4/demo/odatademo/types/ProductDetail.java  |  124 +
 .../types/ProductDetailCollection.java          |   47 +
 .../proxy/v4/demo/odatademo/types/Supplier.java |  201 +
 .../odatademo/types/SupplierCollection.java     |   47 +
 .../v4/demo/odatademo/types/package-info.java   |   21 +
 .../opentypesservicev4/DefaultContainer.java    |    6 +-
 .../odata/services/opentypesservicev4/Row.java  |    1 -
 .../services/opentypesservicev4/RowIndex.java   |    1 -
 .../opentypesservicev4/types/AccountInfo.java   |   90 +
 .../types/ContactDetails.java                   |   25 +-
 .../opentypesservicev4/types/IndexedRow.java    |    5 +-
 .../types/IndexedRowCollection.java             |    5 +
 .../services/opentypesservicev4/types/Row.java  |    5 +-
 .../opentypesservicev4/types/RowCollection.java |    5 +
 .../opentypesservicev4/types/RowIndex.java      |   13 +-
 .../types/RowIndexCollection.java               |    5 +
 .../services/odatawcfservice/types/Account.java |   40 +-
 .../types/AccountCollection.java                |    5 +
 .../odatawcfservice/types/AccountInfo.java      |   21 +-
 .../services/odatawcfservice/types/Address.java |   23 +
 .../services/odatawcfservice/types/Asset.java   |   24 +-
 .../odatawcfservice/types/AssetCollection.java  |    5 +
 .../services/odatawcfservice/types/Club.java    |   20 +-
 .../odatawcfservice/types/ClubCollection.java   |    5 +
 .../services/odatawcfservice/types/Company.java |   48 +-
 .../odatawcfservice/types/CompanyAddress.java   |   30 +-
 .../types/CompanyCollection.java                |    5 +
 .../odatawcfservice/types/CreditCardPI.java     |   61 +-
 .../types/CreditCardPICollection.java           |    5 +
 .../odatawcfservice/types/CreditRecord.java     |   28 +-
 .../types/CreditRecordCollection.java           |    5 +
 .../odatawcfservice/types/Customer.java         |   69 +-
 .../types/CustomerCollection.java               |    5 +
 .../odatawcfservice/types/Department.java       |   28 +-
 .../types/DepartmentCollection.java             |    5 +
 .../odatawcfservice/types/Employee.java         |   61 +-
 .../types/EmployeeCollection.java               |    5 +
 .../odatawcfservice/types/GiftCard.java         |   32 +-
 .../types/GiftCardCollection.java               |    5 +
 .../odatawcfservice/types/HomeAddress.java      |   30 +-
 .../services/odatawcfservice/types/IsBoss.java  |   31 +
 .../odatawcfservice/types/LabourUnion.java      |   20 +-
 .../types/LabourUnionCollection.java            |    5 +
 .../services/odatawcfservice/types/Order.java   |   40 +-
 .../odatawcfservice/types/OrderCollection.java  |    5 +
 .../odatawcfservice/types/OrderDetail.java      |   40 +-
 .../types/OrderDetailCollection.java            |    5 +
 .../types/PaymentInstrument.java                |   36 +-
 .../types/PaymentInstrumentCollection.java      |    5 +
 .../services/odatawcfservice/types/Person.java  |   48 +-
 .../odatawcfservice/types/PersonCollection.java |    5 +
 .../services/odatawcfservice/types/Product.java |   52 +-
 .../types/ProductCollection.java                |    5 +
 .../odatawcfservice/types/ProductDetail.java    |   36 +-
 .../types/ProductDetailCollection.java          |    5 +
 .../odatawcfservice/types/ProductReview.java    |   36 +-
 .../types/ProductReviewCollection.java          |    5 +
 .../odatawcfservice/types/PublicCompany.java    |   65 +-
 .../types/PublicCompanyCollection.java          |    5 +
 .../odatawcfservice/types/Statement.java        |   28 +-
 .../types/StatementCollection.java              |    5 +
 .../odatawcfservice/types/StoredPI.java         |   28 +-
 .../types/StoredPICollection.java               |    5 +
 .../odatawcfservice/types/Subscription.java     |   32 +-
 .../types/SubscriptionCollection.java           |    5 +
 .../olingo/fit/v3/AbstractTestITCase.java       |    4 +-
 .../fit/v3/ActionOverloadingTestITCase.java     |  155 +-
 .../apache/olingo/fit/v3/AsyncTestITCase.java   |   15 +-
 .../apache/olingo/fit/v3/BatchTestITCase.java   |   68 +-
 .../apache/olingo/fit/v3/CountTestITCase.java   |    4 +-
 .../olingo/fit/v3/EntityCreateTestITCase.java   |   16 +-
 .../olingo/fit/v3/EntityRetrieveTestITCase.java |   14 +-
 .../olingo/fit/v3/EntitySetTestITCase.java      |    8 +-
 .../olingo/fit/v3/EntityUpdateTestITCase.java   |   26 +-
 .../apache/olingo/fit/v3/ErrorTestITCase.java   |   20 +-
 .../olingo/fit/v3/FilterFactoryTestITCase.java  |    2 +-
 .../apache/olingo/fit/v3/FilterTestITCase.java  |    2 +-
 .../apache/olingo/fit/v3/InvokeTestITCase.java  |  120 +-
 .../olingo/fit/v3/KeyAsSegmentTestITCase.java   |    6 +-
 .../apache/olingo/fit/v3/LinkTestITCase.java    |    8 +-
 .../olingo/fit/v3/MediaEntityTestITCase.java    |   44 +-
 .../olingo/fit/v3/OpenTypeTestITCase.java       |    6 +-
 .../olingo/fit/v3/PrimitiveKeysTestITCase.java  |    2 +-
 .../fit/v3/PropertyRetrieveTestITCase.java      |    8 +-
 .../olingo/fit/v3/PropertyTestITCase.java       |   23 +-
 .../olingo/fit/v3/PropertyValueTestITCase.java  |   52 +-
 .../olingo/fit/v3/QueryOptionsTestITCase.java   |   12 +-
 .../olingo/fit/v4/AbstractTestITCase.java       |    4 +-
 .../apache/olingo/fit/v4/AsyncTestITCase.java   |    6 +-
 .../apache/olingo/fit/v4/BatchTestITCase.java   |  124 +-
 .../fit/v4/BoundOperationInvokeTestITCase.java  |  258 +-
 .../apache/olingo/fit/v4/DeltaTestITCase.java   |    2 +-
 .../olingo/fit/v4/DerivedTypeTestITCase.java    |    8 +-
 .../olingo/fit/v4/EntityCreateTestITCase.java   |    6 +-
 .../olingo/fit/v4/EntityRetrieveTestITCase.java |   20 +-
 .../olingo/fit/v4/EntitySetTestITCase.java      |   19 +-
 .../olingo/fit/v4/EntityUpdateTestITCase.java   |    8 +-
 .../olingo/fit/v4/ErrorResponseTestITCase.java  |    2 +-
 .../olingo/fit/v4/FilterFactoryTestITCase.java  |    2 +-
 .../olingo/fit/v4/KeyAsSegmentTestITCase.java   |    4 +-
 .../olingo/fit/v4/MediaEntityTestITCase.java    |   21 +-
 .../olingo/fit/v4/OpenTypeTestITCase.java       |    6 +-
 .../fit/v4/OperationImportInvokeTestITCase.java |  187 +-
 .../olingo/fit/v4/PropertyTestITCase.java       |   42 +-
 .../olingo/fit/v4/PropertyValueTestITCase.java  |   67 +-
 .../olingo/fit/v4/QueryOptionsTestITCase.java   |   22 +-
 .../olingo/fit/v4/SingletonTestITCase.java      |    6 +-
 .../org.apache.olingo.ext.proxy.complex         |    1 +
 .../META-INF/org.apache.olingo.ext.proxy.term   |    1 +
 .../client/api/CommonEdmEnabledODataClient.java |    7 +
 .../olingo/client/api/CommonODataClient.java    |    7 +-
 .../api/communication/header/ODataHeaders.java  |   31 +
 .../request/ODataPayloadManager.java            |   57 +
 .../request/ODataStreamManager.java             |   57 -
 .../request/ODataStreamedRequest.java           |    6 +-
 .../request/batch/BatchManager.java             |   43 +
 .../request/batch/BatchStreamManager.java       |   42 -
 .../request/batch/ODataRetrieve.java            |   37 -
 .../request/batch/ODataSingleRequest.java       |   37 +
 .../request/batch/v3/BatchStreamManager.java    |   26 -
 .../request/batch/v3/ODataBatchRequest.java     |    3 +-
 .../request/batch/v4/BatchStreamManager.java    |   34 -
 .../request/batch/v4/ODataBatchRequest.java     |    3 +-
 .../request/cud/CommonCUDRequestFactory.java    |   41 +
 .../invoke/EdmEnabledInvokeRequestFactory.java  |  129 +
 .../request/invoke/InvokeRequestFactory.java    |   68 +-
 .../retrieve/CommonRetrieveRequestFactory.java  |   17 +
 .../MediaEntityCreateStreamManager.java         |    4 +-
 .../MediaEntityUpdateStreamManager.java         |    4 +-
 .../streamed/ODataStreamedEntityRequest.java    |    4 +-
 .../streamed/StreamUpdateStreamManager.java     |    4 +-
 .../streamed/StreamedRequestFactory.java        |   67 -
 .../request/v4/AsyncBatchRequestWrapper.java    |   15 +-
 .../client/api/v3/EdmEnabledODataClient.java    |    8 +
 .../olingo/client/api/v3/ODataClient.java       |    2 +-
 .../client/api/v4/EdmEnabledODataClient.java    |    7 +
 .../olingo/client/api/v4/ODataClient.java       |    2 +-
 .../olingo/client/core/AbstractODataClient.java |    1 -
 .../communication/header/ODataHeadersImpl.java  |   49 +-
 .../request/AbstractODataRequest.java           |    5 +-
 .../request/AbstractODataStreamManager.java     |    4 +-
 .../request/batch/AbstractBatchManager.java     |  143 +
 .../batch/AbstractBatchStreamManager.java       |  138 -
 .../batch/AbstractODataBatchRequest.java        |    6 +-
 .../batch/AbstractODataBatchRequestItem.java    |    2 +-
 .../request/batch/ODataChangesetImpl.java       |    2 +-
 .../request/batch/ODataRetrieveImpl.java        |   81 -
 .../batch/ODataRetrieveResponseItem.java        |   87 -
 .../request/batch/ODataSingleRequestImpl.java   |   82 +
 .../request/batch/ODataSingleResponseItem.java  |   87 +
 .../batch/v3/BatchRequestFactoryImpl.java       |    2 +-
 .../request/batch/v3/ODataBatchRequestImpl.java |   36 +-
 .../batch/v4/BatchRequestFactoryImpl.java       |    2 +-
 .../request/batch/v4/ODataBatchRequestImpl.java |   37 +-
 .../batch/v4/ODataOutsideUpdateImpl.java        |   84 -
 .../v4/ODataOutsideUpdateResponseItem.java      |   80 -
 .../request/cud/AbstractCUDRequestFactory.java  |   49 +-
 .../cud/ODataPropertyUpdateRequestImpl.java     |    8 +-
 .../AbstractEdmEnabledInvokeRequestFactory.java |  172 +
 .../invoke/AbstractInvokeRequestFactory.java    |   55 +-
 .../v3/EdmEnabledInvokeRequestFactoryImpl.java  |   53 +
 .../invoke/v3/InvokeRequestFactoryImpl.java     |   36 +-
 .../v4/EdmEnabledInvokeRequestFactoryImpl.java  |   53 +
 .../invoke/v4/InvokeRequestFactoryImpl.java     |   36 +-
 .../invoke/v4/ODataInvokeRequestImpl.java       |    1 -
 .../AbstractRetrieveRequestFactory.java         |   17 +-
 .../request/retrieve/ODataValueRequestImpl.java |    2 +-
 .../v3/ODataLinkCollectionRequestImpl.java      |    2 +-
 .../retrieve/v3/RetrieveRequestFactoryImpl.java |    2 +-
 .../retrieve/v4/RetrieveRequestFactoryImpl.java |    2 +-
 .../retrieve/v4/XMLMetadataRequestImpl.java     |    2 +-
 .../AbstractODataStreamedEntityRequest.java     |    4 +-
 .../streamed/AbstractODataStreamedRequest.java  |   20 +-
 .../ODataMediaEntityCreateRequestImpl.java      |   10 +-
 .../ODataMediaEntityUpdateRequestImpl.java      |   10 +-
 .../streamed/ODataStreamUpdateRequestImpl.java  |   10 +-
 .../streamed/StreamedRequestFactoryImpl.java    |   77 -
 .../v4/AsyncBatchRequestWrapperImpl.java        |   21 +-
 .../client/core/op/AbstractODataBinder.java     |   56 +-
 .../client/core/op/impl/v3/ODataBinderImpl.java |   14 +-
 .../client/core/op/impl/v4/ODataBinderImpl.java |   32 +-
 .../apache/olingo/client/core/uri/URIUtils.java |   80 +-
 .../core/v3/EdmEnabledODataClientImpl.java      |   20 +
 .../olingo/client/core/v3/ODataClientImpl.java  |   15 +-
 .../core/v4/EdmEnabledODataClientImpl.java      |   19 +
 .../olingo/client/core/v4/ODataClientImpl.java  |   15 +-
 .../client/core/uri/v3/URIBuilderTest.java      |   26 +-
 .../client/core/uri/v4/URIBuilderTest.java      |   26 +-
 .../olingo/client/core/v4/EntityTest.java       |    2 +-
 .../apache/olingo/commons/api/Constants.java    |    2 +
 .../commons/api/domain/v4/ODataAnnotatable.java |   26 +
 .../api/domain/v4/ODataAnnotatatable.java       |   26 -
 .../commons/api/domain/v4/ODataDeltaLink.java   |    2 +-
 .../commons/api/domain/v4/ODataEntity.java      |    2 +-
 .../commons/api/domain/v4/ODataEntitySet.java   |    2 +-
 .../olingo/commons/api/domain/v4/ODataLink.java |    2 +-
 .../api/domain/v4/ODataLinkedComplexValue.java  |    2 +-
 .../commons/api/domain/v4/ODataProperty.java    |    2 +-
 .../olingo/commons/api/http/HttpMethod.java     |   33 +
 .../core/data/AbstractJsonSerializer.java       |   15 +
 .../commons/core/data/AtomDeserializer.java     |    1 +
 lib/pom.xml                                     |    1 +
 .../org/apache/olingo/server/api/OData.java     |   55 +
 .../apache/olingo/server/api/ODataHandler.java  |   28 -
 .../olingo/server/api/ODataHttpHandler.java     |   28 +
 .../apache/olingo/server/api/ODataServer.java   |   52 -
 .../server/api/edm/provider/EntitySet.java      |    2 +-
 lib/server-core/pom.xml                         |   32 +-
 .../org/apache/olingo/server/core/Decoder.java  |   90 +
 .../apache/olingo/server/core/ODataHandler.java |   78 +
 .../olingo/server/core/ODataHandlerImpl.java    |   81 -
 .../server/core/ODataHttpHandlerImpl.java       |  202 +
 .../apache/olingo/server/core/ODataImpl.java    |   61 +
 .../apache/olingo/server/core/ODataRequest.java |  103 +
 .../olingo/server/core/ODataResponse.java       |   56 +
 .../olingo/server/core/ODataServerImpl.java     |   56 -
 .../core/edm/provider/EdmComplexTypeImpl.java   |    2 +-
 .../edm/provider/EdmEntityContainerImpl.java    |    8 +-
 .../core/edm/provider/EdmEntitySetImpl.java     |    5 +-
 .../core/edm/provider/EdmEntityTypeImpl.java    |    4 +-
 .../core/edm/provider/EdmEnumTypeImpl.java      |    2 +-
 .../server/core/edm/provider/EdmMemberImpl.java |   17 +-
 .../edm/provider/EdmNavigationPropertyImpl.java |    6 +-
 .../core/edm/provider/EdmOperationImpl.java     |    2 +-
 .../edm/provider/EdmOperationImportImpl.java    |    3 +-
 .../core/edm/provider/EdmParameterImpl.java     |    5 +-
 .../core/edm/provider/EdmPropertyImpl.java      |    7 +-
 .../core/edm/provider/EdmProviderImpl.java      |   18 +-
 .../provider/EdmReferentialConstraintImpl.java  |   17 +-
 .../core/edm/provider/EdmReturnTypeImpl.java    |    2 +-
 .../server/core/edm/provider/EdmSchemaImpl.java |    6 +-
 .../edm/provider/EdmServiceMetadataImpl.java    |    2 +-
 .../core/edm/provider/EdmSingletonImpl.java     |    5 +-
 .../provider/EdmStructuredTypeHelperImpl.java   |    4 +-
 .../edm/provider/EdmTypeDefinitionImpl.java     |    9 +-
 .../core/serializer/ODataXmlSerializerImpl.java |    1 +
 .../json/ServiceDocumentJsonSerializer.java     |   13 +-
 .../xml/MetadataDocumentXmlSerializer.java      |    1 -
 .../server/core/uri/parser/UriContext.java      |    8 +-
 .../server/core/ODataHttpHandlerImplTest.java   |  175 +
 lib/server-tecsvc/pom.xml                       |   61 +-
 .../olingo/server/tecsvc/TechnicalServlet.java  |   29 +-
 .../tecsvc/provider/ContainerProvider.java      |   80 +-
 .../server/tecsvc/provider/EdmTechProvider.java |    2 +-
 .../server/tecsvc/provider/SchemaProvider.java  |   76 +-
 lib/server-tecsvc/src/main/version/version.html |   43 +
 .../src/main/webapp/META-INF/MANIFEST.MF        |   13 +
 .../src/main/webapp/WEB-INF/web.xml             |    2 +-
 .../src/main/webapp/css/olingo.css              |   89 +
 .../src/main/webapp/img/OlingoOrangeTM.png      |  Bin 0 -> 113360 bytes
 lib/server-tecsvc/src/main/webapp/index.html    |   32 -
 lib/server-tecsvc/src/main/webapp/index.jsp     |   71 +
 .../serializer/json/ServiceDocumentTest.java    |  133 -
 .../serializer/xml/MetadataDocumentTest.java    |  254 -
 .../olingo/server/core/uri/RawUriTest.java      |  151 -
 .../olingo/server/core/uri/UriInfoImplTest.java |  201 -
 .../server/core/uri/UriResourceImplTest.java    |  508 --
 .../core/uri/antlr/TestFullResourcePath.java    | 5110 ------------------
 .../olingo/server/core/uri/antlr/TestLexer.java |  248 -
 .../core/uri/antlr/TestUriParserImpl.java       | 1144 ----
 .../core/uri/queryoption/QueryOptionTest.java   |  303 --
 .../queryoption/expression/ExpressionTest.java  |  239 -
 .../core/uri/testutil/EdmTechTestProvider.java  |  100 -
 .../core/uri/testutil/ExpandValidator.java      |  230 -
 .../core/uri/testutil/FilterTreeToText.java     |  154 -
 .../core/uri/testutil/FilterValidator.java      |  534 --
 .../core/uri/testutil/ParseTreeToText.java      |   82 -
 .../core/uri/testutil/ParserValidator.java      |  162 -
 .../core/uri/testutil/ParserWithLogging.java    |   56 -
 .../core/uri/testutil/ResourceValidator.java    |  599 --
 .../core/uri/testutil/TestErrorLogger.java      |  105 -
 .../core/uri/testutil/TestUriValidator.java     |  258 -
 .../server/core/uri/testutil/TestValidator.java |   23 -
 .../core/uri/testutil/TokenValidator.java       |  194 -
 .../core/uri/testutil/UriLexerWithTrace.java    |   85 -
 .../core/uri/validator/UriValidatorTest.java    |  378 --
 lib/server-test/pom.xml                         |   71 +
 .../olingo/server/core/ODataHandlerTest.java    |   86 +
 .../serializer/json/ServiceDocumentTest.java    |  133 +
 .../serializer/xml/MetadataDocumentTest.java    |  253 +
 .../olingo/server/core/uri/RawUriTest.java      |  151 +
 .../olingo/server/core/uri/UriInfoImplTest.java |  201 +
 .../server/core/uri/UriResourceImplTest.java    |  508 ++
 .../core/uri/antlr/TestFullResourcePath.java    | 5110 ++++++++++++++++++
 .../olingo/server/core/uri/antlr/TestLexer.java |  248 +
 .../core/uri/antlr/TestUriParserImpl.java       | 1144 ++++
 .../core/uri/queryoption/QueryOptionTest.java   |  303 ++
 .../queryoption/expression/ExpressionTest.java  |  239 +
 .../core/uri/testutil/EdmTechTestProvider.java  |  100 +
 .../core/uri/testutil/ExpandValidator.java      |  230 +
 .../core/uri/testutil/FilterTreeToText.java     |  154 +
 .../core/uri/testutil/FilterValidator.java      |  534 ++
 .../core/uri/testutil/ParseTreeToText.java      |   82 +
 .../core/uri/testutil/ParserValidator.java      |  162 +
 .../core/uri/testutil/ParserWithLogging.java    |   56 +
 .../core/uri/testutil/ResourceValidator.java    |  599 ++
 .../core/uri/testutil/TestErrorLogger.java      |  105 +
 .../core/uri/testutil/TestUriValidator.java     |  258 +
 .../server/core/uri/testutil/TestValidator.java |   23 +
 .../core/uri/testutil/TokenValidator.java       |  194 +
 .../core/uri/testutil/UriLexerWithTrace.java    |   85 +
 .../core/uri/validator/UriValidatorTest.java    |  378 ++
 .../src/test/resources/simplelogger.properties  |   20 +
 pom.xml                                         |   45 +-
 404 files changed, 21671 insertions(+), 14170 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a09dd24/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/EntityContainerFactory.java
----------------------------------------------------------------------
diff --cc ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/EntityContainerFactory.java
index 83eb855,9de2d4f..cfa3562
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/EntityContainerFactory.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/EntityContainerFactory.java
@@@ -39,38 -44,48 +39,36 @@@ public final class EntityContainerFacto
  
    private static final Map<Class<?>, Object> ENTITY_CONTAINERS = new ConcurrentHashMap<Class<?>, Object>();
  
 -  private final CommonEdmEnabledODataClient<?> client;
 -
 -  private final String serviceRoot;
 -
 -  public static Context getContext() {
 -    synchronized (MONITOR) {
 -      if (context == null) {
 -        context = new Context();
 -      }
 -    }
 -
 -    return context;
 -  }
 -
    @SuppressWarnings("unchecked")
--  private static <C extends CommonEdmEnabledODataClient<?>> EntityContainerFactory<C> getInstance(
--          final C client, final String serviceRoot) {
--
--    if (!FACTORY_PER_SERVICEROOT.containsKey(serviceRoot)) {
++  private static <C extends CommonEdmEnabledODataClient<?>> EntityContainerFactory<C> getInstance(final C client) {
++    if (!FACTORY_PER_SERVICEROOT.containsKey(client.getServiceRoot())) {
+       client.getConfiguration().setDefaultPubFormat(ODataPubFormat.JSON_FULL_METADATA);
 -      final EntityContainerFactory<C> instance = new EntityContainerFactory<C>(client, serviceRoot);
 -      FACTORY_PER_SERVICEROOT.put(serviceRoot, instance);
 +      final EntityContainerFactory<C> instance = new EntityContainerFactory<C>(client);
-       FACTORY_PER_SERVICEROOT.put(serviceRoot, instance);
++      FACTORY_PER_SERVICEROOT.put(client.getServiceRoot(), instance);
      }
-     client.getConfiguration().setDefaultPubFormat(ODataPubFormat.JSON_FULL_METADATA);
  
--    return (EntityContainerFactory<C>) FACTORY_PER_SERVICEROOT.get(serviceRoot);
++    return (EntityContainerFactory<C>) FACTORY_PER_SERVICEROOT.get(client.getServiceRoot());
    }
  
    public static EntityContainerFactory<org.apache.olingo.client.api.v3.EdmEnabledODataClient> getV3(
            final String serviceRoot) {
  
--    return getInstance(ODataClientFactory.getEdmEnabledV3(serviceRoot), serviceRoot);
++    return getInstance(ODataClientFactory.getEdmEnabledV3(serviceRoot));
    }
  
    public static EntityContainerFactory<org.apache.olingo.client.api.v4.EdmEnabledODataClient> getV4(
            final String serviceRoot) {
  
--    return getInstance(ODataClientFactory.getEdmEnabledV4(serviceRoot), serviceRoot);
++    return getInstance(ODataClientFactory.getEdmEnabledV4(serviceRoot));
    }
  
 -  private EntityContainerFactory(final CommonEdmEnabledODataClient<?> client, final String serviceRoot) {
 +  private final CommonEdmEnabledODataClient<?> client;
 +
 +  private final Context context;
 +
 +  private EntityContainerFactory(final CommonEdmEnabledODataClient<?> client) {
      this.client = client;
 -    this.serviceRoot = serviceRoot;
 +    this.context = new Context();
    }
  
    @SuppressWarnings("unchecked")

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a09dd24/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 c45b43b,09b443b..2293c39
--- 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
@@@ -46,7 -51,6 +51,8 @@@ import org.apache.olingo.ext.proxy.Enti
  import org.apache.olingo.ext.proxy.api.OperationType;
  import org.apache.olingo.ext.proxy.api.annotations.Operation;
  import org.apache.olingo.ext.proxy.api.annotations.Parameter;
++import org.apache.olingo.ext.proxy.context.AttachedEntityStatus;
 +import org.apache.olingo.ext.proxy.context.Context;
  import org.apache.olingo.ext.proxy.utils.ClassUtils;
  import org.apache.olingo.ext.proxy.utils.CoreUtils;
  
@@@ -67,11 -70,7 +73,11 @@@ abstract class AbstractInvocationHandle
    }
  
    protected CommonEdmEnabledODataClient<?> getClient() {
-     return factory == null ? containerHandler.getClient() : factory.getClient();
 -    return client;
++    return factory == null ? containerHandler.getFactory().getClient() : factory.getClient();
 +  }
 +
 +  protected Context getContext() {
-     return factory == null ? containerHandler.getContext() : factory.getContext();
++    return factory == null ? containerHandler.getFactory().getContext() : factory.getContext();
    }
  
    protected boolean isSelfMethod(final Method method, final Object[] args) {
@@@ -105,7 -104,7 +111,7 @@@
  
      for (CommonODataEntity entityFromSet : entitySet.getEntities()) {
        items.add(getEntityProxy(
--              entityFromSet.getEditLink(), entityFromSet, entityContainerName, null, typeRef, checkInTheContext));
++              entityFromSet.getEditLink(), entityFromSet, entityContainerName, null, typeRef, null, checkInTheContext));
      }
  
      return Proxy.newProxyInstance(
@@@ -130,17 -129,17 +136,6 @@@
            final String entityContainerName,
            final URI entitySetURI,
            final Class<?> type,
--          final boolean checkInTheContext) {
--
--    return getEntityProxy(entityURI, entity, entityContainerName, entitySetURI, type, null, checkInTheContext);
--  }
--
--  protected Object getEntityProxy(
--          final URI entityURI,
--          final CommonODataEntity entity,
--          final String entityContainerName,
--          final URI entitySetURI,
--          final Class<?> type,
            final String eTag,
            final boolean checkInTheContext) {
  
@@@ -152,8 -151,8 +147,10 @@@
        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());
++    } else {
++      handler.attach(AttachedEntityStatus.ATTACHED, false);
      }
  
      return Proxy.newProxyInstance(
@@@ -198,8 -216,12 +214,12 @@@
      }
  
      // 3. invoke
 -    final ODataInvokeResult result = client.getInvokeRequestFactory().getInvokeRequest(
 +    final ODataInvokeResult result = getClient().getInvokeRequestFactory().getInvokeRequest(
-             target, edmOperation, parameterValues).execute().getBody();
+             edmOperation instanceof EdmFunction ? HttpMethod.GET : HttpMethod.POST,
+             target,
+             getResultReference(edmOperation.getReturnType()),
+             parameterValues).
+             execute().getBody();
  
      // 4. process invoke result
      if (StringUtils.isBlank(annotation.returnType())) {
@@@ -227,11 -249,13 +247,15 @@@
                  null,
                  null,
                  method.getReturnType(),
++                null,
                  false);
        }
      } else {
-       return CoreUtils.getValueFromProperty(
-               getClient(), (CommonODataProperty) result, method.getGenericReturnType(), null);
+       final CommonODataProperty property = (CommonODataProperty) result;
+       return property == null || property.hasNullValue()
+               ? null
 -              : CoreUtils.getObjectFromODataValue(client, property.getValue(), method.getGenericReturnType(), null);
++              : CoreUtils.getObjectFromODataValue(
++                      getClient(), property.getValue(), method.getGenericReturnType(), null);
      }
    }
  

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a09dd24/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 8a1155a,5f04408..9438d63
--- 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
@@@ -24,8 -24,13 +24,12 @@@ import java.lang.reflect.ParameterizedT
  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.Map;
  import org.apache.commons.lang3.ArrayUtils;
 -import org.apache.olingo.client.api.CommonEdmEnabledODataClient;
+ import org.apache.olingo.client.api.communication.request.retrieve.ODataEntityRequest;
  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;
@@@ -33,6 -38,8 +37,7 @@@ import org.apache.olingo.commons.api.do
  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.commons.api.edm.constants.ODataServiceVersion;
 -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;
@@@ -58,15 -68,22 +63,21 @@@ public abstract class AbstractStructure
  
    protected Object internal;
  
+   private final Map<String, AnnotatableInvocationHandler> propAnnotatableHandlers =
+           new HashMap<String, AnnotatableInvocationHandler>();
+ 
+   private final Map<String, AnnotatableInvocationHandler> navPropAnnotatableHandlers =
+           new HashMap<String, AnnotatableInvocationHandler>();
+ 
    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);
+     this.entityHandler = null;
    }
  
    protected AbstractStructuredInvocationHandler(
@@@ -74,18 -92,28 +85,28 @@@
            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;
+     // prevent memory leak
+     this.entityHandler = entityHandler == this ? null : entityHandler;
+   }
+ 
+   public Object getInternal() {
+     return internal;
    }
  
    public EntityInvocationHandler getEntityHandler() {
-     return entityHandler;
+     return entityHandler == null
+             ? this instanceof EntityInvocationHandler
+             ? EntityInvocationHandler.class.cast(this)
+             : null
+             : entityHandler;
    }
  
 -  public void setEntityHandler(EntityInvocationHandler entityHandler) {
 -    // prevent memory leak
 +  public void setEntityHandler(final EntityInvocationHandler entityHandler) {
-     this.entityHandler = entityHandler;
++    // prevents memory leak
+     this.entityHandler = entityHandler == this ? null : entityHandler;
    }
  
    public Class<?> getTypeRef() {
@@@ -163,8 -198,8 +191,8 @@@
    }
  
    protected void attach() {
-     if (entityHandler != null && !getContext().entityContext().isAttached(entityHandler)) {
-       getContext().entityContext().attach(entityHandler, AttachedEntityStatus.ATTACHED);
 -    if (getEntityHandler() != null && !entityContext.isAttached(getEntityHandler())) {
 -      entityContext.attach(getEntityHandler(), AttachedEntityStatus.ATTACHED);
++    if (entityHandler != null && !getContext().entityContext().isAttached(getEntityHandler())) {
++      getContext().entityContext().attach(getEntityHandler(), AttachedEntityStatus.ATTACHED);
      }
    }
  
@@@ -173,12 -208,12 +201,12 @@@
    }
  
    protected void attach(final AttachedEntityStatus status, final boolean override) {
-     if (getContext().entityContext().isAttached(entityHandler)) {
 -    if (entityContext.isAttached(getEntityHandler())) {
++    if (getContext().entityContext().isAttached(getEntityHandler())) {
        if (override) {
-         getContext().entityContext().setStatus(entityHandler, status);
 -        entityContext.setStatus(getEntityHandler(), status);
++        getContext().entityContext().setStatus(getEntityHandler(), status);
        }
      } else {
-       getContext().entityContext().attach(entityHandler, status);
 -      entityContext.attach(getEntityHandler(), status);
++      getContext().entityContext().attach(getEntityHandler(), status);
      }
    }
  
@@@ -206,8 -241,8 +234,9 @@@
                null,
                ((ODataInlineEntity) link).getEntity(),
                property.targetContainer(),
-               getClient().getURIBuilder(serviceRoot).appendEntitySetSegment(property.targetEntitySet()).build(),
 -              client.newURIBuilder(serviceRoot).appendEntitySetSegment(property.targetEntitySet()).build(),
++              getClient().newURIBuilder().appendEntitySetSegment(property.targetEntitySet()).build(),
                type,
++              null,
                false);
      } else if (link instanceof ODataInlineEntitySet) {
        // return entity set
@@@ -233,14 -267,18 +262,18 @@@
        } else if (AbstractEntitySet.class.isAssignableFrom(type)) {
          navPropValue = getEntitySetProxy(type, uri);
        } else {
-         final ODataRetrieveResponse<CommonODataEntity> res =
-                 getClient().getRetrieveRequestFactory().getEntityRequest(uri).execute();
 -        final ODataEntityRequest<CommonODataEntity> req = client.getRetrieveRequestFactory().getEntityRequest(uri);
 -        if (client.getServiceVersion().compareTo(ODataServiceVersion.V30) > 0) {
 -          req.setPrefer(client.newPreferences().includeAnnotations("*"));
++        final ODataEntityRequest<CommonODataEntity> req = getClient().getRetrieveRequestFactory().getEntityRequest(uri);
++        if (getClient().getServiceVersion().compareTo(ODataServiceVersion.V30) > 0) {
++          req.setPrefer(getClient().newPreferences().includeAnnotations("*"));
+         }
+ 
+         final ODataRetrieveResponse<CommonODataEntity> res = req.execute();
  
          navPropValue = getEntityProxy(
                  uri,
                  res.getBody(),
                  property.targetContainer(),
-                 getClient().getURIBuilder(serviceRoot).appendEntitySetSegment(property.targetEntitySet()).build(),
 -                client.newURIBuilder(serviceRoot).appendEntitySetSegment(property.targetEntitySet()).build(),
++                getClient().newURIBuilder(serviceRoot).appendEntitySetSegment(property.targetEntitySet()).build(),
                  type,
                  res.getETag(),
                  true);
@@@ -265,10 -292,12 +287,12 @@@
      return getPropertyValue(name, null);
    }
  
+   public abstract Collection<String> getAdditionalPropertyNames();
+ 
    private void setNavigationPropertyValue(final NavigationProperty property, final Object value) {
      // 1) attach source entity
-     if (!getContext().entityContext().isAttached(entityHandler)) {
-       getContext().entityContext().attach(entityHandler, AttachedEntityStatus.CHANGED);
 -    if (!entityContext.isAttached(getEntityHandler())) {
 -      entityContext.attach(getEntityHandler(), AttachedEntityStatus.CHANGED);
++    if (!getContext().entityContext().isAttached(getEntityHandler())) {
++      getContext().entityContext().attach(getEntityHandler(), AttachedEntityStatus.CHANGED);
      }
  
      // 2) attach the target entity handlers

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a09dd24/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AnnotatableInvocationHandler.java
----------------------------------------------------------------------
diff --cc ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AnnotatableInvocationHandler.java
index 0000000,c0a4e53..890603a
mode 000000,100644..100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AnnotatableInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AnnotatableInvocationHandler.java
@@@ -1,0 -1,180 +1,178 @@@
+ /*
+  * 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.Proxy;
+ import java.util.Collection;
+ import java.util.Collections;
+ import java.util.HashMap;
+ import java.util.List;
+ import java.util.Map;
 -import org.apache.olingo.client.api.CommonEdmEnabledODataClient;
+ import org.apache.olingo.commons.api.domain.v4.ODataAnnotation;
+ import org.apache.olingo.commons.api.domain.v4.ODataEntity;
+ import org.apache.olingo.commons.api.domain.v4.ODataLinkedComplexValue;
+ import org.apache.olingo.ext.proxy.api.AbstractTerm;
+ import org.apache.olingo.ext.proxy.api.Annotatable;
+ import org.apache.olingo.ext.proxy.api.annotations.Namespace;
+ import org.apache.olingo.ext.proxy.api.annotations.Term;
+ import org.apache.olingo.ext.proxy.context.AttachedEntityStatus;
+ import org.apache.olingo.ext.proxy.utils.CoreUtils;
+ 
+ public class AnnotatableInvocationHandler extends AbstractInvocationHandler implements Annotatable {
+ 
+   private static final long serialVersionUID = 3111228269617223332L;
+ 
+   private final String propName;
+ 
+   private final String navPropName;
+ 
+   private final EntityInvocationHandler entityHandler;
+ 
+   private final AbstractStructuredInvocationHandler targetHandler;
+ 
+   private final Map<Class<? extends AbstractTerm>, Object> annotations =
+           new HashMap<Class<? extends AbstractTerm>, Object>();
+ 
+   public AnnotatableInvocationHandler(
 -          final CommonEdmEnabledODataClient<?> client,
+           final EntityContainerInvocationHandler containerHandler,
+           final String propName,
+           final String navPropName,
+           final EntityInvocationHandler entityHandler,
+           final AbstractStructuredInvocationHandler targetHandler) {
+ 
 -    super(client, containerHandler);
++    super(containerHandler);
+ 
+     this.propName = propName;
+     this.navPropName = navPropName;
+     this.entityHandler = entityHandler;
+     this.targetHandler = targetHandler;
+   }
+ 
+   @Override
+   public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
+     return invokeSelfMethod(method, args);
+   }
+ 
+   public Map<Class<? extends AbstractTerm>, Object> getAnnotations() {
+     return annotations;
+   }
+ 
+   private List<ODataAnnotation> internalAnnotations() {
+     List<ODataAnnotation> result = Collections.<ODataAnnotation>emptyList();
+ 
+     if (entityHandler.getEntity() instanceof ODataEntity) {
+       if (targetHandler.getInternal() instanceof ODataEntity) {
+         result = propName == null
+                 ? ((org.apache.olingo.commons.api.domain.v4.ODataLink) ((ODataEntity) targetHandler.getInternal()).
+                 getNavigationLink(navPropName)).getAnnotations()
+                 : ((ODataEntity) targetHandler.getInternal()).getProperty(propName).getAnnotations();
+       } else if (targetHandler.getInternal() instanceof ODataLinkedComplexValue) {
+         result = propName == null
+                 ? ((org.apache.olingo.commons.api.domain.v4.ODataLink) ((ODataLinkedComplexValue) targetHandler.
+                 getInternal()).getNavigationLink(navPropName)).getAnnotations()
+                 : ((ODataLinkedComplexValue) targetHandler.getInternal()).get(propName).getAnnotations();
+       }
+     }
+ 
+     return result;
+   }
+ 
+   @Override
+   public void addAnnotation(final Class<? extends AbstractTerm> term, final Object value) {
+     this.annotations.put(term, value);
+ 
+     if (value != null) {
+       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(entityHandler);
+           }
+         }
+       }
+     }
+ 
+     entityHandler.attach(AttachedEntityStatus.CHANGED);
+     if (navPropName == null) {
+       targetHandler.putPropAnnotatableHandler(propName, this);
+     } else {
+       targetHandler.putNavPropAnnotatableHandler(navPropName, this);
+     }
+   }
+ 
+   @Override
+   public void removeAnnotation(final Class<? extends AbstractTerm> term) {
+     this.annotations.remove(term);
+ 
+     entityHandler.attach(AttachedEntityStatus.CHANGED);
+     if (navPropName == null) {
+       targetHandler.putPropAnnotatableHandler(propName, this);
+     } else {
+       targetHandler.putNavPropAnnotatableHandler(navPropName, this);
+     }
+   }
+ 
+   @Override
+   public Object getAnnotation(final Class<? extends AbstractTerm> term) {
+     Object res = null;
+ 
+     if (annotations.containsKey(term)) {
+       res = annotations.get(term);
+     } else if (entityHandler.getEntity() instanceof ODataEntity) {
+       try {
+         final Term termAnn = term.getAnnotation(Term.class);
+         final Namespace namespaceAnn = term.getAnnotation(Namespace.class);
+         ODataAnnotation annotation = null;
+         for (ODataAnnotation _annotation : internalAnnotations()) {
+           if ((namespaceAnn.value() + "." + termAnn.name()).equals(_annotation.getTerm())) {
+             annotation = _annotation;
+           }
+         }
+         res = annotation == null || annotation.hasNullValue()
+                 ? null
+                 : CoreUtils.getObjectFromODataValue(
 -                        client, annotation.getValue(), null, targetHandler.getEntityHandler());
++                        getClient(), annotation.getValue(), null, targetHandler.getEntityHandler());
+         if (res != null) {
+           annotations.put(term, res);
+         }
+       } catch (Exception e) {
+         throw new IllegalArgumentException("Error getting annotation for term '" + term.getName() + "'", e);
+       }
+     }
+ 
+     return res;
+   }
+ 
+   @Override
+   public Collection<Class<? extends AbstractTerm>> getAnnotationTerms() {
+     return entityHandler.getEntity() instanceof ODataEntity
+             ? CoreUtils.getAnnotationTerms(internalAnnotations())
+             : Collections.<Class<? extends AbstractTerm>>emptyList();
+   }
+ }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a09dd24/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AnnotatationsInvocationHandler.java
----------------------------------------------------------------------
diff --cc ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AnnotatationsInvocationHandler.java
index 0000000,d9ef3ea..e009f6a
mode 000000,100644..100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AnnotatationsInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AnnotatationsInvocationHandler.java
@@@ -1,0 -1,91 +1,87 @@@
+ /*
+  * 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.Method;
+ import java.lang.reflect.Proxy;
 -import org.apache.olingo.client.api.CommonEdmEnabledODataClient;
+ import org.apache.olingo.ext.proxy.api.annotations.AnnotationsForNavigationProperty;
+ import org.apache.olingo.ext.proxy.api.annotations.AnnotationsForProperty;
+ import org.apache.olingo.ext.proxy.utils.ClassUtils;
+ 
+ public class AnnotatationsInvocationHandler extends AbstractInvocationHandler {
+ 
+   private static final long serialVersionUID = -1993362719908718985L;
+ 
+   private final EntityInvocationHandler entityHandler;
+ 
+   private final AbstractStructuredInvocationHandler targetHandler;
+ 
+   static AnnotatationsInvocationHandler getInstance(
+           final EntityInvocationHandler entityHandler,
+           final AbstractStructuredInvocationHandler targetHandler) {
+ 
+     return new AnnotatationsInvocationHandler(
 -            entityHandler == null ? null : entityHandler.containerHandler.client,
+             targetHandler == null
+             ? entityHandler == null ? null : entityHandler.containerHandler : targetHandler.containerHandler,
+             entityHandler,
+             targetHandler);
+   }
+ 
+   private AnnotatationsInvocationHandler(
 -          final CommonEdmEnabledODataClient<?> client,
+           final EntityContainerInvocationHandler containerHandler,
+           final EntityInvocationHandler entityHandler,
+           final AbstractStructuredInvocationHandler targetHandler) {
+ 
 -    super(client, containerHandler);
++    super(containerHandler);
+     this.targetHandler = targetHandler;
+     this.entityHandler = entityHandler;
+   }
+ 
+   @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 (method.getName().startsWith("get") && method.getName().endsWith("Annotations")) {
+       final Method getter = proxy.getClass().getInterfaces()[0].getMethod(method.getName());
+ 
+       String propName = null;
+       String navPropName = null;
+ 
+       final AnnotationsForProperty annForProp = ClassUtils.getAnnotation(AnnotationsForProperty.class, getter);
+       if (annForProp == null) {
+         final AnnotationsForNavigationProperty annForNavProp =
+                 ClassUtils.getAnnotation(AnnotationsForNavigationProperty.class, getter);
+         if (annForNavProp == null) {
+           throw new UnsupportedOperationException("Unsupported method " + method.getName());
+         }
+ 
+         navPropName = annForNavProp.name();
+       } else {
+         propName = annForProp.name();
+       }
+ 
+       return Proxy.newProxyInstance(
+               Thread.currentThread().getContextClassLoader(),
+               new Class<?>[] {method.getReturnType()},
 -              new AnnotatableInvocationHandler(
 -                      client, containerHandler, propName, navPropName, entityHandler, targetHandler));
++              new AnnotatableInvocationHandler(containerHandler, propName, navPropName, entityHandler, targetHandler));
+     } else {
+       throw new NoSuchMethodException(method.getName());
+     }
+   }
+ }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a09dd24/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 b9aacbf,2429a02..f17f760
--- 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
@@@ -78,8 -79,7 +78,11 @@@ class ComplexFactoryInvocationHandler e
        return Proxy.newProxyInstance(
                Thread.currentThread().getContextClassLoader(),
                new Class<?>[] {method.getReturnType()},
-               ComplexInvocationHandler.getInstance(
 -              ComplexInvocationHandler.getInstance(client, property.name(), method.getReturnType(), entityHandler));
++              entityHandler == null
++              ? ComplexInvocationHandler.getInstance(
++                      getClient(), property.name(), method.getReturnType(), containerHandler)
++              : 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/7a09dd24/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 32b82d4,a207e68..ad25203
--- 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
@@@ -18,11 -18,15 +18,16 @@@
   */
  package org.apache.olingo.ext.proxy.commons;
  
+ import java.lang.annotation.Annotation;
  import java.lang.reflect.Method;
  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.commons.lang3.tuple.ImmutablePair;
++import org.apache.commons.lang3.tuple.Pair;
  import org.apache.olingo.client.api.CommonEdmEnabledODataClient;
  import org.apache.olingo.commons.api.domain.CommonODataProperty;
  import org.apache.olingo.commons.api.domain.ODataComplexValue;
@@@ -41,11 -45,11 +46,9 @@@ public class ComplexInvocationHandler e
  
    private static final long serialVersionUID = 2629912294765040037L;
  
--  public static ComplexInvocationHandler getInstance(
++  private static Pair<ODataComplexValue<? extends CommonODataProperty>, Class<?>> init(
            final CommonEdmEnabledODataClient<?> client,
--          final String propertyName,
--          final Class<?> reference,
--          final EntityInvocationHandler handler) {
++          final Class<?> reference) {
  
      final Class<?> complexTypeRef;
      if (Collection.class.isAssignableFrom(reference)) {
@@@ -65,7 -69,8 +68,27 @@@
      final ODataComplexValue<? extends CommonODataProperty> complex =
              client.getObjectFactory().newComplexValue(typeName.toString());
  
-     return new ComplexInvocationHandler(client, complex, complexTypeRef, handler);
 -    return (ComplexInvocationHandler) ComplexInvocationHandler.getInstance(
 -            client, complex, complexTypeRef, handler);
++    return new ImmutablePair<ODataComplexValue<? extends CommonODataProperty>, Class<?>>(complex, complexTypeRef);
++  }
++
++  public static ComplexInvocationHandler getInstance(
++          final CommonEdmEnabledODataClient<?> client,
++          final String propertyName,
++          final Class<?> reference,
++          final EntityInvocationHandler handler) {
++
++    final Pair<ODataComplexValue<? extends CommonODataProperty>, Class<?>> init = init(client, reference);
++    return new ComplexInvocationHandler(client, init.getLeft(), init.getRight(), handler);
++  }
++
++  public static ComplexInvocationHandler getInstance(
++          final CommonEdmEnabledODataClient<?> client,
++          final String propertyName,
++          final Class<?> reference,
++          final EntityContainerInvocationHandler containerHandler) {
++
++    final Pair<ODataComplexValue<? extends CommonODataProperty>, Class<?>> init = init(client, reference);
++    return new ComplexInvocationHandler(client, init.getLeft(), init.getRight(), containerHandler);
    }
  
    public static ComplexInvocationHandler getInstance(
@@@ -76,19 -81,16 +99,29 @@@
  
      return new ComplexInvocationHandler(client, complex, typeRef, handler);
    }
-   
+ 
 -  public ComplexInvocationHandler(
 +  private final CommonEdmEnabledODataClient<?> client;
 +
-   public ComplexInvocationHandler(
++  private 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;
 +  }
 +
++  private ComplexInvocationHandler(
++          final CommonEdmEnabledODataClient<?> client,
++          final ODataComplexValue<?> complex,
++          final Class<?> typeRef,
++          final EntityContainerInvocationHandler containerHandler) {
++
++    super(typeRef, complex, containerHandler);
++    this.client = client;
+   }
+ 
    @SuppressWarnings("unchecked")
    public ODataComplexValue<CommonODataProperty> getComplex() {
      return (ODataComplexValue<CommonODataProperty>) this.internal;
@@@ -111,6 -137,15 +168,13 @@@
  
      final EdmElement edmProperty = client.getCachedEdm().getComplexType(fqn).getProperty(property.name());
  
+     final EdmTypeInfo type = new EdmTypeInfo.Builder().setEdm(client.getCachedEdm()).setTypeExpression(
+             edmProperty.isCollection() ? "Collection(" + property.type() + ")" : property.type()).build();
+ 
+     setPropertyValue(property.name(), type, value);
+   }
+ 
 -  @SuppressWarnings("unchecked")
+   private void setPropertyValue(final String name, final EdmTypeInfo type, final Object value) {
 -
      final Object toBeAdded;
  
      if (value == null) {
@@@ -118,21 -153,18 +182,16 @@@
      } 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);
 -        Collection.class.cast(toBeAdded).add(obj instanceof Proxy ? Proxy.getInvocationHandler(obj) : obj);
++        Collection.class.cast(toBeAdded).add(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));
+     client.getBinder().add(getComplex(), CoreUtils.getODataProperty(client, name, type, toBeAdded));
  
-     if (entityHandler != null && !getContext().entityContext().isAttached(entityHandler)) {
-       getContext().entityContext().attach(entityHandler, AttachedEntityStatus.CHANGED);
 -    if (getEntityHandler() != null && !entityContext.isAttached(getEntityHandler())) {
 -      entityContext.attach(getEntityHandler(), AttachedEntityStatus.CHANGED);
++    if (getEntityHandler() != null && !getContext().entityContext().isAttached(getEntityHandler())) {
++      getContext().entityContext().attach(getEntityHandler(), AttachedEntityStatus.CHANGED);
      }
    }
  
@@@ -146,8 -178,18 +205,18 @@@
    }
  
    @Override
-   protected void addPropertyChanges(final String name, final Object value) {
-     // do nothing ....
+   public void addAdditionalProperty(final String name, final Object value) {
+     setPropertyValue(name, null, value);
+     attach(AttachedEntityStatus.CHANGED);
+   }
+ 
+   @Override
+   public void removeAdditionalProperty(final String name) {
+     final CommonODataProperty property = getComplex().get(name);
 -    if(property !=null && !property.hasNullValue()){
++    if (property != null && !property.hasNullValue()) {
+       setPropertyValue(name, null, null);
+       attach(AttachedEntityStatus.CHANGED);
+     }
    }
  
    @Override

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a09dd24/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityCollectionInvocationHandler.java
----------------------------------------------------------------------
diff --cc ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityCollectionInvocationHandler.java
index ba3e449,49f61bf..1d1d136
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityCollectionInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityCollectionInvocationHandler.java
@@@ -142,4 -162,37 +162,37 @@@ public class EntityCollectionInvocation
    public void clear() {
      items.clear();
    }
+ 
+   public Object getAnnotation(final Class<? extends AbstractTerm> term) {
+     Object res = null;
+ 
+     if (annotationsByTerm.containsKey(term)) {
+       res = annotationsByTerm.get(term);
+     } else {
+       try {
+         final Term termAnn = term.getAnnotation(Term.class);
+         final Namespace namespaceAnn = term.getAnnotation(Namespace.class);
+         ODataAnnotation annotation = null;
+         for (ODataAnnotation _annotation : annotations) {
+           if ((namespaceAnn.value() + "." + termAnn.name()).equals(_annotation.getTerm())) {
+             annotation = _annotation;
+           }
+         }
+         res = annotation == null || annotation.hasNullValue()
+                 ? null
 -                : CoreUtils.getObjectFromODataValue(client, annotation.getValue(), null, null);
++                : CoreUtils.getObjectFromODataValue(getClient(), annotation.getValue(), null, null);
+         if (res != null) {
+           annotationsByTerm.put(term, res);
+         }
+       } catch (Exception e) {
+         throw new IllegalArgumentException("Error getting annotation for term '" + term.getName() + "'", e);
+       }
+     }
+ 
+     return res;
+   }
+ 
+   public Collection<Class<? extends AbstractTerm>> getAnnotationTerms() {
+     return CoreUtils.getAnnotationTerms(annotations);
+   }
  }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a09dd24/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 c884f45,2d9065a..793a34b
--- 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
@@@ -116,13 -129,14 +129,14 @@@ public class EntityInvocationHandler ex
              getUUID().getContainerName(),
              getUUID().getEntitySetURI(),
              getUUID().getType(),
 -            CoreUtils.getKey(client, typeRef, entity));
 +            CoreUtils.getKey(getClient(), this, typeRef, entity));
  
+     this.streamedPropertyChanges.clear();
      this.propertyChanges.clear();
      this.linkChanges.clear();
-     this.streamedPropertyChanges.clear();
      this.propertiesTag = 0;
      this.linksTag = 0;
+     this.annotations.clear();
    }
  
    public EntityUUID getUUID() {
@@@ -186,19 -210,26 +210,26 @@@
    @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);
+       if (!(type instanceof ParameterizedType) && (Class<?>) type == InputStream.class) {
+         return getStreamedProperty(name);
        } else {
-         res = CoreUtils.getValueFromProperty(getClient(), property, type, this);
-         if (res != null) {
-           addPropertyChanges(name, res);
+         final CommonODataProperty property = getEntity().getProperty(name);
+ 
+         Object res;
+         if (propertyChanges.containsKey(name)) {
+           res = propertyChanges.get(name);
+         } else {
+           res = property == null || property.hasNullValue()
+                   ? null
 -                  : CoreUtils.getObjectFromODataValue(client, property.getValue(), type, this);
++                  : CoreUtils.getObjectFromODataValue(getClient(), property.getValue(), type, this);
+ 
+           if (res != null) {
+             cacheProperty(name, res);
+           }
          }
-       }
  
-       return res;
+         return res;
+       }
      } catch (Exception e) {
        throw new IllegalArgumentException("Error getting value for property '" + name + "'", e);
      }
@@@ -269,7 -323,7 +323,8 @@@
        final String contentType =
                StringUtils.isBlank(getEntity().getMediaContentType()) ? "*/*" : getEntity().getMediaContentType();
  
-       final ODataMediaRequest retrieveReq = getClient().getRetrieveRequestFactory().getMediaRequest(contentSource);
 -      final ODataMediaRequest retrieveReq = client.getRetrieveRequestFactory().getMediaEntityRequest(contentSource);
++      final ODataMediaRequest retrieveReq = getClient().getRetrieveRequestFactory().
++              getMediaEntityRequest(contentSource);
        retrieveReq.setFormat(ODataMediaFormat.fromFormat(contentType));
  
        this.stream = retrieveReq.execute().getBody();
@@@ -284,19 -338,19 +339,17 @@@
      try {
        if (res == null) {
          final URI link = URIUtils.getURI(
 -                containerHandler.getFactory().getServiceRoot(),
 +                getClient().getServiceRoot(),
-                 CoreUtils.getMediaEditLink(property.name(), getEntity()).toASCIIString());
+                 CoreUtils.getMediaEditLink(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) {
@@@ -315,8 -369,7 +368,8 @@@
      if (linkChanges.containsKey(property)) {
        navPropValue = linkChanges.get(property);
      } else {
 -      navPropValue = retrieveNavigationProperty(property, getter, containerHandler.getFactory().getServiceRoot());
 +      navPropValue = retrieveNavigationProperty(
-               property, getter, containerHandler.getFactory().getClient().getServiceRoot());
++              property, getter, containerHandler.getFactory().getClient().getServiceRoot());      
      }
  
      if (navPropValue != null) {
@@@ -341,6 -403,75 +403,75 @@@
    }
  
    @Override
+   public void addAnnotation(final Class<? extends AbstractTerm> term, final Object value) {
+     this.annotations.put(term, value);
+ 
+     if (value != null) {
+       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 void removeAnnotation(final Class<? extends AbstractTerm> term) {
+     this.annotations.remove(term);
+     attach(AttachedEntityStatus.CHANGED);
+   }
+ 
+   @Override
+   public Object getAnnotation(final Class<? extends AbstractTerm> term) {
+     Object res = null;
+ 
+     if (annotations.containsKey(term)) {
+       res = annotations.get(term);
+     } else if (getEntity() instanceof ODataEntity) {
+       try {
+         final Term termAnn = term.getAnnotation(Term.class);
+         final Namespace namespaceAnn = term.getAnnotation(Namespace.class);
+         ODataAnnotation annotation = null;
+         for (ODataAnnotation _annotation : ((ODataEntity) getEntity()).getAnnotations()) {
+           if ((namespaceAnn.value() + "." + termAnn.name()).equals(_annotation.getTerm())) {
+             annotation = _annotation;
+           }
+         }
+         res = annotation == null || annotation.hasNullValue()
+                 ? null
 -                : CoreUtils.getObjectFromODataValue(client, annotation.getValue(), null, this);
++                : CoreUtils.getObjectFromODataValue(getClient(), annotation.getValue(), null, this);
+         if (res != null) {
+           annotations.put(term, res);
+         }
+       } catch (Exception e) {
+         throw new IllegalArgumentException("Error getting annotation for term '" + term.getName() + "'", e);
+       }
+     }
+ 
+     return res;
+   }
+ 
+   @Override
+   public Collection<Class<? extends AbstractTerm>> getAnnotationTerms() {
+     return getEntity() instanceof ODataEntity
+             ? CoreUtils.getAnnotationTerms(((ODataEntity) getEntity()).getAnnotations())
+             : Collections.<Class<? extends AbstractTerm>>emptyList();
+   }
+ 
+   @Override
    public String toString() {
      return uuid.toString();
    }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a09dd24/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 00861c5,7aa8c22..ba85827
--- 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
@@@ -177,8 -182,8 +181,8 @@@ class EntitySetInvocationHandler
  
    @Override
    public Long count() {
 -    final ODataValueRequest req = client.getRetrieveRequestFactory().
 -            getValueRequest(client.newURIBuilder(this.uri.toASCIIString()).count().build());
 +    final ODataValueRequest req = getClient().getRetrieveRequestFactory().
-             getValueRequest(getClient().getURIBuilder(this.uri.toASCIIString()).count().build());
++            getValueRequest(getClient().newURIBuilder(this.uri.toASCIIString()).count().build());
      req.setFormat(ODataValueFormat.TEXT);
      return Long.valueOf(req.execute().getBody().asPrimitive().toString());
    }
@@@ -241,7 -246,7 +245,7 @@@
        // not yet attached: search against the service
        try {
          LOG.debug("Search for '{}({})' into the service", typeRef.getSimpleName(), key);
-         final CommonURIBuilder<?> uriBuilder = getClient().getURIBuilder(this.uri.toASCIIString());
 -        final CommonURIBuilder<?> uriBuilder = client.newURIBuilder(this.uri.toASCIIString());
++        final CommonURIBuilder<?> uriBuilder = getClient().newURIBuilder(this.uri.toASCIIString());
  
          if (key.getClass().getAnnotation(CompoundKey.class) == null) {
            LOG.debug("Append key segment '{}'", key);
@@@ -253,8 -258,13 +257,13 @@@
  
          LOG.debug("GET {}", uriBuilder.toString());
  
-         final ODataRetrieveResponse<CommonODataEntity> res =
-                 getClient().getRetrieveRequestFactory().getEntityRequest(uriBuilder.build()).execute();
+         final ODataEntityRequest<CommonODataEntity> req =
 -                client.getRetrieveRequestFactory().getEntityRequest(uriBuilder.build());
 -        if (client.getServiceVersion().compareTo(ODataServiceVersion.V30) > 0) {
 -          req.setPrefer(client.newPreferences().includeAnnotations("*"));
++                getClient().getRetrieveRequestFactory().getEntityRequest(uriBuilder.build());
++        if (getClient().getServiceVersion().compareTo(ODataServiceVersion.V30) > 0) {
++          req.setPrefer(getClient().newPreferences().includeAnnotations("*"));
+         }
+ 
+         final ODataRetrieveResponse<CommonODataEntity> res = req.execute();
  
          final String etag = res.getETag();
          final CommonODataEntity entity = res.getBody();
@@@ -295,8 -305,13 +307,13 @@@
        entities.add(res.getBody());
        next = null;
      } else {
-       final ODataRetrieveResponse<CommonODataEntitySet> res =
-               getClient().getRetrieveRequestFactory().getEntitySetRequest(uri).execute();
+       final ODataEntitySetRequest<CommonODataEntitySet> req =
 -              client.getRetrieveRequestFactory().getEntitySetRequest(uri);
 -      if (client.getServiceVersion().compareTo(ODataServiceVersion.V30) > 0) {
 -        req.setPrefer(client.newPreferences().includeAnnotations("*"));
++              getClient().getRetrieveRequestFactory().getEntitySetRequest(uri);
++      if (getClient().getServiceVersion().compareTo(ODataServiceVersion.V30) > 0) {
++        req.setPrefer(getClient().newPreferences().includeAnnotations("*"));
+       }
+ 
+       final ODataRetrieveResponse<CommonODataEntitySet> res = req.execute();
  
        final CommonODataEntitySet entitySet = res.getBody();
        entities.addAll(entitySet.getEntities());
@@@ -350,7 -375,7 +376,7 @@@
      final Class<S> ref = (Class<S>) ClassUtils.extractTypeArg(collTypeRef);
      final Class<S> oref = (Class<S>) ClassUtils.extractTypeArg(this.collTypeRef);
  
-     final CommonURIBuilder<?> uriBuilder = getClient().getURIBuilder(this.uri.toASCIIString());
 -    final CommonURIBuilder<?> uriBuilder = client.newURIBuilder(this.uri.toASCIIString());
++    final CommonURIBuilder<?> uriBuilder = getClient().newURIBuilder(this.uri.toASCIIString());
  
      final URI entitySetURI;
      if (oref.equals(ref)) {
@@@ -436,6 -462,6 +462,6 @@@
  
    @Override
    public EntitySetIterator<T, KEY, EC> iterator() {
-     return new EntitySetIterator<T, KEY, EC>(getClient().getURIBuilder(this.uri.toASCIIString()).build(), this);
 -    return new EntitySetIterator<T, KEY, EC>(client.newURIBuilder(this.uri.toASCIIString()).build(), this);
++    return new EntitySetIterator<T, KEY, EC>(getClient().newURIBuilder(this.uri.toASCIIString()).build(), this);
    }
  }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a09dd24/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 5aaa0e6,d28a319..d7c46f6
--- 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
@@@ -146,8 -153,8 +145,8 @@@ final class OperationInvocationHandler 
        edmOperation = container.getActionImport(operation.name()).getUnboundAction();
      }
  
-     final CommonURIBuilder<?> uriBuilder = getClient().getURIBuilder(getClient().getServiceRoot()).
-             appendOperationCallSegment(URIUtils.operationImportURISegment(container, edmOperation.getName()));
 -    final CommonURIBuilder<?> uriBuilder = getClient().newURIBuilder(this.serviceRoot).
++    final CommonURIBuilder<?> uriBuilder = getClient().newURIBuilder().
+             appendOperationCallSegment(edmOperation.getName());
  
      return new AbstractMap.SimpleEntry<URI, EdmOperation>(uriBuilder.build(), edmOperation);
    }


[2/9] git commit: [OLINGO-260] Enhancement: non-static context

Posted by il...@apache.org.
[OLINGO-260] Enhancement: non-static context


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

Branch: refs/heads/master
Commit: e897cf27f5b582124dc11fef4d9355b245ca3eea
Parents: 96c4551
Author: Francesco Chicchiriccò <--global>
Authored: Fri May 16 14:25:35 2014 +0200
Committer: Francesco Chicchiriccò <--global>
Committed: Fri May 16 14:25:35 2014 +0200

----------------------------------------------------------------------
 .../ext/proxy/EntityContainerFactory.java       |  39 ++---
 .../commons/AbstractInvocationHandler.java      |  36 ++--
 .../commons/AbstractTypeInvocationHandler.java  |  41 ++---
 .../ComplexFactoryInvocationHandler.java        |  17 +-
 .../commons/ComplexTypeInvocationHandler.java   |  40 +----
 .../olingo/ext/proxy/commons/ContainerImpl.java | 103 ++++++------
 .../EntityCollectionInvocationHandler.java      |   2 +-
 .../EntityContainerInvocationHandler.java       |  19 +--
 .../commons/EntitySetInvocationHandler.java     |  56 +++----
 .../commons/EntityTypeInvocationHandler.java    |  44 +----
 .../commons/OperationInvocationHandler.java     |  30 ++--
 .../commons/SingletonInvocationHandler.java     |   2 +-
 .../olingo/ext/proxy/utils/CoreUtils.java       |  31 ++--
 .../olingo/fit/proxy/v3/AbstractTestITCase.java |   5 +-
 .../proxy/v3/ActionOverloadingTestITCase.java   |   8 +-
 .../olingo/fit/proxy/v3/ContextTestITCase.java  | 165 ++++++++++---------
 .../fit/proxy/v3/EntityCreateTestITCase.java    |   8 +-
 .../olingo/fit/proxy/v3/OpenTypeTestITCase.java |   4 +-
 .../olingo/fit/proxy/v3/PropertyTestITCase.java |   7 +-
 .../olingo/fit/proxy/v4/AbstractTestITCase.java |   9 +-
 .../fit/proxy/v4/EntityCreateTestITCase.java    |   4 +-
 .../olingo/fit/proxy/v4/OpenTypeTestITCase.java |   4 +-
 .../olingo/fit/proxy/v4/PropertyTestITCase.java |   3 +-
 23 files changed, 302 insertions(+), 375 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/e897cf27/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/EntityContainerFactory.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/EntityContainerFactory.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/EntityContainerFactory.java
index c378a7a..83eb855 100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/EntityContainerFactory.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/EntityContainerFactory.java
@@ -21,7 +21,6 @@ package org.apache.olingo.ext.proxy;
 import java.lang.reflect.Proxy;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
-import org.apache.commons.lang3.StringUtils;
 import org.apache.olingo.client.api.CommonEdmEnabledODataClient;
 import org.apache.olingo.client.core.ODataClientFactory;
 import org.apache.olingo.commons.api.format.ODataPubFormat;
@@ -35,35 +34,17 @@ import org.apache.olingo.ext.proxy.context.Context;
  */
 public final class EntityContainerFactory<C extends CommonEdmEnabledODataClient<?>> {
 
-  private static final Object MONITOR = new Object();
-
-  private static Context context = null;
-
   private static final Map<String, EntityContainerFactory<?>> FACTORY_PER_SERVICEROOT =
           new ConcurrentHashMap<String, EntityContainerFactory<?>>();
 
   private static final Map<Class<?>, Object> ENTITY_CONTAINERS = new ConcurrentHashMap<Class<?>, Object>();
 
-  private final CommonEdmEnabledODataClient<?> client;
-
-  private final String serviceRoot;
-
-  public static Context getContext() {
-    synchronized (MONITOR) {
-      if (context == null) {
-        context = new Context();
-      }
-    }
-
-    return context;
-  }
-
   @SuppressWarnings("unchecked")
   private static <C extends CommonEdmEnabledODataClient<?>> EntityContainerFactory<C> getInstance(
           final C client, final String serviceRoot) {
 
     if (!FACTORY_PER_SERVICEROOT.containsKey(serviceRoot)) {
-      final EntityContainerFactory<C> instance = new EntityContainerFactory<C>(client, serviceRoot);
+      final EntityContainerFactory<C> instance = new EntityContainerFactory<C>(client);
       FACTORY_PER_SERVICEROOT.put(serviceRoot, instance);
     }
     client.getConfiguration().setDefaultPubFormat(ODataPubFormat.JSON_FULL_METADATA);
@@ -83,9 +64,13 @@ public final class EntityContainerFactory<C extends CommonEdmEnabledODataClient<
     return getInstance(ODataClientFactory.getEdmEnabledV4(serviceRoot), serviceRoot);
   }
 
-  private EntityContainerFactory(final CommonEdmEnabledODataClient<?> client, final String serviceRoot) {
+  private final CommonEdmEnabledODataClient<?> client;
+
+  private final Context context;
+
+  private EntityContainerFactory(final CommonEdmEnabledODataClient<?> client) {
     this.client = client;
-    this.serviceRoot = serviceRoot;
+    this.context = new Context();
   }
 
   @SuppressWarnings("unchecked")
@@ -93,8 +78,8 @@ public final class EntityContainerFactory<C extends CommonEdmEnabledODataClient<
     return (C) client;
   }
 
-  public String getServiceRoot() {
-    return serviceRoot;
+  public Context getContext() {
+    return context;
   }
 
   /**
@@ -107,15 +92,11 @@ public final class EntityContainerFactory<C extends CommonEdmEnabledODataClient<
    * @throws IllegalArgumentException if the passed reference is not an interface annotated as EntityContainer
    */
   public <T> T getEntityContainer(final Class<T> reference) throws IllegalStateException, IllegalArgumentException {
-    if (StringUtils.isBlank(serviceRoot)) {
-      throw new IllegalStateException("serviceRoot was not set");
-    }
-
     if (!ENTITY_CONTAINERS.containsKey(reference)) {
       final Object entityContainer = Proxy.newProxyInstance(
               Thread.currentThread().getContextClassLoader(),
               new Class<?>[] {reference},
-              EntityContainerInvocationHandler.getInstance(client, reference, this));
+              EntityContainerInvocationHandler.getInstance(reference, this));
       ENTITY_CONTAINERS.put(reference, entityContainer);
     }
     return reference.cast(ENTITY_CONTAINERS.get(reference));

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/e897cf27/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 5181b48..e16c96e 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
@@ -46,6 +46,7 @@ import org.apache.olingo.ext.proxy.EntityContainerFactory;
 import org.apache.olingo.ext.proxy.api.OperationType;
 import org.apache.olingo.ext.proxy.api.annotations.Operation;
 import org.apache.olingo.ext.proxy.api.annotations.Parameter;
+import org.apache.olingo.ext.proxy.context.Context;
 import org.apache.olingo.ext.proxy.utils.ClassUtils;
 import org.apache.olingo.ext.proxy.utils.CoreUtils;
 
@@ -53,19 +54,24 @@ abstract class AbstractInvocationHandler implements InvocationHandler {
 
   private static final long serialVersionUID = 358520026931462958L;
 
-  protected final CommonEdmEnabledODataClient<?> client;
+  protected EntityContainerFactory<?> factory;
 
   protected EntityContainerInvocationHandler containerHandler;
 
-  protected AbstractInvocationHandler(
-          final CommonEdmEnabledODataClient<?> client, final EntityContainerInvocationHandler containerHandler) {
+  protected AbstractInvocationHandler(final EntityContainerFactory<?> factory) {
+    this.factory = factory;
+  }
 
-    this.client = client;
+  protected AbstractInvocationHandler(final EntityContainerInvocationHandler containerHandler) {
     this.containerHandler = containerHandler;
   }
 
   protected CommonEdmEnabledODataClient<?> getClient() {
-    return client;
+    return factory == null ? containerHandler.getClient() : factory.getClient();
+  }
+
+  protected Context getContext() {
+    return factory == null ? containerHandler.getContext() : factory.getContext();
   }
 
   protected boolean isSelfMethod(final Method method, final Object[] args) {
@@ -98,8 +104,7 @@ abstract class AbstractInvocationHandler implements InvocationHandler {
     final List<Object> items = new ArrayList<Object>();
 
     for (CommonODataEntity entityFromSet : entitySet.getEntities()) {
-      items.add(getEntityProxy(
-              entityFromSet, entityContainerName, null, typeRef, checkInTheContext));
+      items.add(getEntityProxy(entityFromSet, entityContainerName, null, typeRef, checkInTheContext));
     }
 
     return Proxy.newProxyInstance(
@@ -135,8 +140,8 @@ abstract class AbstractInvocationHandler implements InvocationHandler {
       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(
@@ -165,11 +170,11 @@ abstract class AbstractInvocationHandler implements InvocationHandler {
         }
 
         final EdmTypeInfo type = new EdmTypeInfo.Builder().
-                setEdm(client.getCachedEdm()).setTypeExpression(parameter.getKey().type()).build();
+                setEdm(getClient().getCachedEdm()).setTypeExpression(parameter.getKey().type()).build();
 
         final ODataValue paramValue = parameter.getValue() == null
                 ? null
-                : CoreUtils.getODataValue(client, type, parameter.getValue());
+                : CoreUtils.getODataValue(getClient(), type, parameter.getValue());
 
         parameterValues.put(parameter.getKey().name(), paramValue);
       }
@@ -177,11 +182,11 @@ abstract class AbstractInvocationHandler implements InvocationHandler {
 
     // 2. IMPORTANT: flush any pending change *before* invoke if this operation is side effecting
     if (annotation.type() == OperationType.ACTION) {
-      new ContainerImpl(client, containerHandler.getFactory()).flush();
+      new ContainerImpl(containerHandler.getFactory()).flush();
     }
 
     // 3. invoke
-    final ODataInvokeResult result = client.getInvokeRequestFactory().getInvokeRequest(
+    final ODataInvokeResult result = getClient().getInvokeRequestFactory().getInvokeRequest(
             target, edmOperation, parameterValues).execute().getBody();
 
     // 4. process invoke result
@@ -190,7 +195,7 @@ abstract class AbstractInvocationHandler implements InvocationHandler {
     }
 
     final EdmTypeInfo edmType = new EdmTypeInfo.Builder().
-            setEdm(client.getCachedEdm()).setTypeExpression(annotation.returnType()).build();
+            setEdm(getClient().getCachedEdm()).setTypeExpression(annotation.returnType()).build();
 
     if (edmType.isEntityType()) {
       if (edmType.isCollection()) {
@@ -212,7 +217,8 @@ abstract class AbstractInvocationHandler implements InvocationHandler {
                 false);
       }
     } else {
-      return CoreUtils.getValueFromProperty(client, (CommonODataProperty) result, method.getGenericReturnType(), null);
+      return CoreUtils.getValueFromProperty(
+              getClient(), (CommonODataProperty) result, method.getGenericReturnType(), null);
     }
   }
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/e897cf27/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractTypeInvocationHandler.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractTypeInvocationHandler.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractTypeInvocationHandler.java
index 169ddfe..0923fbe 100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractTypeInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractTypeInvocationHandler.java
@@ -24,10 +24,8 @@ 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;
@@ -35,13 +33,11 @@ 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.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;
@@ -57,31 +53,27 @@ public abstract class AbstractTypeInvocationHandler extends AbstractInvocationHa
 
   protected final Class<?> typeRef;
 
-  protected final EntityContext entityContext = EntityContainerFactory.getContext().entityContext();
-
   protected EntityTypeInvocationHandler entityHandler;
 
   protected Object internal;
 
   protected AbstractTypeInvocationHandler(
-          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 = EntityTypeInvocationHandler.class.cast(this);
   }
 
   protected AbstractTypeInvocationHandler(
-          final CommonEdmEnabledODataClient<?> client,
           final Class<?> typeRef,
           final Object internal,
           final EntityTypeInvocationHandler entityHandler) {
 
-    super(client, entityHandler == null ? null : entityHandler.containerHandler);
+    super(entityHandler == null ? null : entityHandler.containerHandler);
     this.internal = internal;
     this.typeRef = typeRef;
     this.entityHandler = entityHandler;
@@ -91,7 +83,7 @@ public abstract class AbstractTypeInvocationHandler extends AbstractInvocationHa
     return entityHandler;
   }
 
-  public void setEntityHandler(EntityTypeInvocationHandler entityHandler) {
+  public void setEntityHandler(final EntityTypeInvocationHandler entityHandler) {
     this.entityHandler = entityHandler;
   }
 
@@ -170,8 +162,8 @@ public abstract class AbstractTypeInvocationHandler extends AbstractInvocationHa
   }
 
   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);
     }
   }
 
@@ -180,12 +172,12 @@ public abstract class AbstractTypeInvocationHandler extends AbstractInvocationHa
   }
 
   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);
     }
   }
 
@@ -224,20 +216,19 @@ public abstract class AbstractTypeInvocationHandler extends AbstractInvocationHa
               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 = getEntityCollection(
                 collItemType,
                 type,
                 property.targetContainer(),
-                client.getRetrieveRequestFactory().getEntitySetRequest(uri).execute().getBody(),
+                getClient().getRetrieveRequestFactory().getEntitySetRequest(uri).execute().getBody(),
                 uri,
                 true);
       } else {
         final ODataRetrieveResponse<CommonODataEntity> res =
-                client.getRetrieveRequestFactory().getEntityRequest(uri).execute();
+                getClient().getRetrieveRequestFactory().getEntityRequest(uri).execute();
 
         navPropValue = getEntityProxy(
                 res.getBody(),
@@ -267,12 +258,10 @@ public abstract class AbstractTypeInvocationHandler extends AbstractInvocationHa
     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
@@ -289,8 +278,8 @@ public abstract class AbstractTypeInvocationHandler extends AbstractInvocationHa
         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);
       }
     }
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/e897cf27/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ComplexFactoryInvocationHandler.java
----------------------------------------------------------------------
diff --git 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
index 2f833c6..c20e476 100644
--- 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
@@ -20,7 +20,6 @@ package org.apache.olingo.ext.proxy.commons;
 
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
-import org.apache.olingo.client.api.CommonEdmEnabledODataClient;
 import org.apache.olingo.ext.proxy.api.OperationExecutor;
 import org.apache.olingo.ext.proxy.api.annotations.Property;
 import org.apache.olingo.ext.proxy.utils.ClassUtils;
@@ -34,32 +33,33 @@ class ComplexFactoryInvocationHandler extends AbstractInvocationHandler implemen
   private final AbstractTypeInvocationHandler invokerHandler;
 
   static ComplexFactoryInvocationHandler getInstance(
-          final CommonEdmEnabledODataClient<?> client,
           final EntityContainerInvocationHandler containerHandler,
           final EntityTypeInvocationHandler entityHandler,
           final AbstractTypeInvocationHandler targetHandler) {
 
-    return new ComplexFactoryInvocationHandler(client, containerHandler, entityHandler, targetHandler);
+    return new ComplexFactoryInvocationHandler(containerHandler, entityHandler, targetHandler);
   }
 
   static ComplexFactoryInvocationHandler getInstance(
           final EntityTypeInvocationHandler entityHandler,
           final AbstractTypeInvocationHandler 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) {
 
-    super(client, containerHandler);
+    super(containerHandler);
     this.invokerHandler = targetHandler;
     this.entityHandler = entityHandler;
   }
@@ -78,7 +78,8 @@ class ComplexFactoryInvocationHandler extends AbstractInvocationHandler implemen
       return Proxy.newProxyInstance(
               Thread.currentThread().getContextClassLoader(),
               new Class<?>[] {method.getReturnType()},
-              ComplexTypeInvocationHandler.getInstance(client, property.name(), method.getReturnType(), entityHandler));
+              ComplexTypeInvocationHandler.getInstance(
+                      getClient(), property.name(), method.getReturnType(), entityHandler));
     } else {
       throw new NoSuchMethodException(method.getName());
     }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/e897cf27/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ComplexTypeInvocationHandler.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ComplexTypeInvocationHandler.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ComplexTypeInvocationHandler.java
index 2175e8c..2b5dcdd 100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ComplexTypeInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ComplexTypeInvocationHandler.java
@@ -18,15 +18,11 @@
  */
 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;
@@ -69,8 +65,7 @@ public class ComplexTypeInvocationHandler extends AbstractTypeInvocationHandler
     final ODataComplexValue<? extends CommonODataProperty> complex =
             client.getObjectFactory().newComplexValue(typeName.toString());
 
-    return (ComplexTypeInvocationHandler) ComplexTypeInvocationHandler.getInstance(
-            client, complex, complexTypeRef, handler);
+    return new ComplexTypeInvocationHandler(client, complex, complexTypeRef, handler);
   }
 
   public static ComplexTypeInvocationHandler getInstance(
@@ -82,13 +77,16 @@ public class ComplexTypeInvocationHandler extends AbstractTypeInvocationHandler
     return new ComplexTypeInvocationHandler(client, complex, typeRef, handler);
   }
 
-  public ComplexTypeInvocationHandler(
+  private final CommonEdmEnabledODataClient<?> client;
+
+  private ComplexTypeInvocationHandler(
           final CommonEdmEnabledODataClient<?> client,
           final ODataComplexValue<?> complex,
           final Class<?> typeRef,
           final EntityTypeInvocationHandler handler) {
 
-    super(client, typeRef, complex, handler);
+    super(typeRef, complex, handler);
+    this.client = client;
   }
 
   @SuppressWarnings("unchecked")
@@ -106,28 +104,6 @@ public class ComplexTypeInvocationHandler extends AbstractTypeInvocationHandler
   }
 
   @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 =
@@ -155,8 +131,8 @@ public class ComplexTypeInvocationHandler extends AbstractTypeInvocationHandler
 
     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);
     }
   }
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/e897cf27/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ContainerImpl.java
----------------------------------------------------------------------
diff --git 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
index ab824ec..2879f5f 100644
--- 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
@@ -30,7 +30,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.olingo.client.api.CommonEdmEnabledODataClient;
 import org.apache.olingo.client.api.communication.header.ODataPreferences;
 import org.apache.olingo.client.api.communication.request.ODataRequest;
 import org.apache.olingo.client.api.communication.request.ODataStreamedRequest;
@@ -73,12 +72,9 @@ class ContainerImpl implements Container {
    */
   private static final Logger LOG = LoggerFactory.getLogger(ContainerImpl.class);
 
-  private final CommonEdmEnabledODataClient<?> client;
+  private final EntityContainerFactory<?> factory;
 
-  private final EntityContainerFactory factory;
-
-  ContainerImpl(final CommonEdmEnabledODataClient<?> client, final EntityContainerFactory factory) {
-    this.client = client;
+  ContainerImpl(final EntityContainerFactory<?> factory) {
     this.factory = factory;
   }
 
@@ -87,8 +83,9 @@ class ContainerImpl implements Container {
    */
   @Override
   public void flush() {
-    final CommonODataBatchRequest request = client.getBatchRequestFactory().getBatchRequest(client.getServiceRoot());
-    ((ODataRequest)request).setAccept(client.getConfiguration().getDefaultBatchAcceptFormat());
+    final CommonODataBatchRequest request =
+            factory.getClient().getBatchRequestFactory().getBatchRequest(factory.getClient().getServiceRoot());
+    ((ODataRequest) request).setAccept(factory.getClient().getConfiguration().getDefaultBatchAcceptFormat());
 
     final BatchStreamManager streamManager = (BatchStreamManager) ((ODataStreamedRequest) request).execute();
 
@@ -99,7 +96,7 @@ class ContainerImpl implements Container {
 
     int pos = 0;
 
-    for (AttachedEntity attachedEntity : EntityContainerFactory.getContext().entityContext()) {
+    for (AttachedEntity attachedEntity : factory.getContext().entityContext()) {
       final AttachedEntityStatus status = attachedEntity.getStatus();
       if (((status != AttachedEntityStatus.ATTACHED
               && status != AttachedEntityStatus.LINKED) || attachedEntity.getEntity().isChanged())
@@ -113,8 +110,11 @@ class ContainerImpl implements Container {
 
     final ODataBatchResponse response = streamManager.getResponse();
 
-    if ((client.getServiceVersion().compareTo(ODataServiceVersion.V30) <= 0 && response.getStatusCode() != 202)
-            || (client.getServiceVersion().compareTo(ODataServiceVersion.V30) > 0 && response.getStatusCode() != 200)) {
+    if ((factory.getClient().getServiceVersion().compareTo(ODataServiceVersion.V30) <= 0
+            && response.getStatusCode() != 202)
+            || (factory.getClient().getServiceVersion().compareTo(ODataServiceVersion.V30) > 0
+            && response.getStatusCode() != 200)) {
+
       throw new IllegalStateException("Operation failed");
     }
 
@@ -152,7 +152,7 @@ class ContainerImpl implements Container {
       }
     }
 
-    EntityContainerFactory.getContext().detachAll();
+    factory.getContext().detachAll();
   }
 
   private void batch(
@@ -160,7 +160,7 @@ class ContainerImpl implements Container {
           final CommonODataEntity entity,
           final ODataChangeset changeset) {
 
-    switch (EntityContainerFactory.getContext().entityContext().getStatus(handler)) {
+    switch (factory.getContext().entityContext().getStatus(handler)) {
       case NEW:
         batchCreate(handler, entity, changeset);
         break;
@@ -187,9 +187,9 @@ class ContainerImpl implements Container {
 
     LOG.debug("Create '{}'", handler);
 
-    final CommonURIBuilder<?> uriBuilder = client.getURIBuilder(factory.getServiceRoot()).
+    final CommonURIBuilder<?> uriBuilder = factory.getClient().getURIBuilder(factory.getClient().getServiceRoot()).
             appendEntitySetSegment(handler.getEntitySetName());
-    changeset.addRequest(client.getCUDRequestFactory().getEntityCreateRequest(uriBuilder.build(), entity));
+    changeset.addRequest(factory.getClient().getCUDRequestFactory().getEntityCreateRequest(uriBuilder.build(), entity));
   }
 
   private void batchUpdateMediaEntity(
@@ -201,7 +201,7 @@ class ContainerImpl implements Container {
     LOG.debug("Update media entity '{}'", uri);
 
     final ODataMediaEntityUpdateRequest<?> req =
-            client.getStreamedRequestFactory().getMediaEntityUpdateRequest(uri, input);
+            factory.getClient().getStreamedRequestFactory().getMediaEntityUpdateRequest(uri, input);
 
     req.setContentType(StringUtils.isBlank(handler.getEntity().getMediaContentType())
             ? ODataMediaFormat.WILDCARD.toString()
@@ -222,7 +222,8 @@ class ContainerImpl implements Container {
 
     LOG.debug("Update media entity '{}'", uri);
 
-    final ODataStreamUpdateRequest req = client.getStreamedRequestFactory().getStreamUpdateRequest(uri, input);
+    final ODataStreamUpdateRequest req = factory.getClient().
+            getStreamedRequestFactory().getStreamUpdateRequest(uri, input);
 
     if (StringUtils.isNotBlank(handler.getETag())) {
       req.setIfMatch(handler.getETag());
@@ -239,13 +240,13 @@ class ContainerImpl implements Container {
     LOG.debug("Update '{}'", changes.getEditLink());
 
     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)
-            : ((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);
 
-    req.setPrefer(new ODataPreferences(client.getServiceVersion()).returnContent());
+    req.setPrefer(new ODataPreferences(factory.getClient().getServiceVersion()).returnContent());
 
     if (StringUtils.isNotBlank(handler.getETag())) {
       req.setIfMatch(handler.getETag());
@@ -263,15 +264,15 @@ class ContainerImpl implements Container {
     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)
-            : ((org.apache.olingo.client.api.v4.EdmEnabledODataClient) client).getCUDRequestFactory().
+                    uri, org.apache.olingo.client.api.communication.request.cud.v3.UpdateType.PATCH, changes)
+            : ((org.apache.olingo.client.api.v4.EdmEnabledODataClient) factory.getClient()).getCUDRequestFactory().
             getEntityUpdateRequest(
-            uri, org.apache.olingo.client.api.communication.request.cud.v4.UpdateType.PATCH, changes);
+                    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());
@@ -287,8 +288,8 @@ class ContainerImpl implements Container {
 
     LOG.debug("Delete '{}'", entity.getEditLink());
 
-    final ODataDeleteRequest req = client.getCUDRequestFactory().getDeleteRequest(URIUtils.getURI(
-            factory.getServiceRoot(), entity.getEditLink().toASCIIString()));
+    final ODataDeleteRequest req = factory.getClient().getCUDRequestFactory().getDeleteRequest(
+            URIUtils.getURI(factory.getClient().getServiceRoot(), entity.getEditLink().toASCIIString()));
 
     if (StringUtils.isNotBlank(handler.getETag())) {
       req.setIfMatch(handler.getETag());
@@ -311,11 +312,11 @@ class ContainerImpl implements Container {
     final CommonODataEntity entity = handler.getEntity();
     entity.getNavigationLinks().clear();
 
-    final AttachedEntityStatus currentStatus = EntityContainerFactory.getContext().entityContext().getStatus(handler);
+    final AttachedEntityStatus currentStatus = factory.getContext().entityContext().getStatus(handler);
 
     if (AttachedEntityStatus.DELETED != currentStatus) {
       entity.getProperties().clear();
-      CoreUtils.addProperties(client, handler.getPropertyChanges(), entity);
+      CoreUtils.addProperties(factory.getClient(), handler.getPropertyChanges(), entity);
     }
 
     for (Map.Entry<NavigationProperty, Object> property : handler.getLinkChanges().entrySet()) {
@@ -324,7 +325,7 @@ class ContainerImpl implements Container {
               : ODataLinkType.ENTITY_NAVIGATION;
 
       final Set<EntityTypeInvocationHandler> toBeLinked = new HashSet<EntityTypeInvocationHandler>();
-      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())) {
@@ -332,8 +333,7 @@ class ContainerImpl implements Container {
         final EntityTypeInvocationHandler target =
                 (EntityTypeInvocationHandler) 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();
 
@@ -385,7 +385,9 @@ class ContainerImpl implements Container {
       if (!handler.getPropertyChanges().isEmpty()) {
         final URI targetURI = currentStatus == AttachedEntityStatus.NEW
                 ? URI.create("$" + startingPos)
-                : URIUtils.getURI(factory.getServiceRoot(), handler.getEntity().getEditLink().toASCIIString());
+                : URIUtils.getURI(
+                        factory.getClient().getServiceRoot(),
+                        handler.getEntity().getEditLink().toASCIIString());
         batchUpdate(handler, targetURI, entity, changeset);
         pos++;
         items.put(handler, pos);
@@ -396,7 +398,8 @@ class ContainerImpl implements Container {
         final URI targetURI = currentStatus == AttachedEntityStatus.NEW
                 ? URI.create("$" + startingPos + "/$value")
                 : URIUtils.getURI(
-                factory.getServiceRoot(), handler.getEntity().getEditLink().toASCIIString() + "/$value");
+                        factory.getClient().getServiceRoot(),
+                        handler.getEntity().getEditLink().toASCIIString() + "/$value");
 
         batchUpdateMediaEntity(handler, targetURI, handler.getStreamChanges(), changeset);
 
@@ -408,9 +411,10 @@ class ContainerImpl implements Container {
 
     for (Map.Entry<String, InputStream> streamedChanges : handler.getStreamedPropertyChanges().entrySet()) {
       final URI targetURI = currentStatus == AttachedEntityStatus.NEW
-              ? URI.create("$" + startingPos) : URIUtils.getURI(
-              factory.getServiceRoot(),
-              CoreUtils.getMediaEditLink(streamedChanges.getKey(), entity).toASCIIString());
+              ? URI.create("$" + startingPos)
+              : URIUtils.getURI(
+                      factory.getClient().getServiceRoot(),
+                      CoreUtils.getMediaEditLink(streamedChanges.getKey(), entity).toASCIIString());
 
       batchUpdateMediaResource(handler, targetURI, streamedChanges.getValue(), changeset);
 
@@ -427,11 +431,11 @@ class ContainerImpl implements Container {
 
     switch (type) {
       case ENTITY_NAVIGATION:
-        result = client.getObjectFactory().newEntityNavigationLink(name, uri);
+        result = factory.getClient().getObjectFactory().newEntityNavigationLink(name, uri);
         break;
 
       case ENTITY_SET_NAVIGATION:
-        result = client.getObjectFactory().newEntitySetNavigationLink(name, uri);
+        result = factory.getClient().getObjectFactory().newEntitySetNavigationLink(name, uri);
         break;
 
       default:
@@ -452,15 +456,14 @@ class ContainerImpl implements Container {
       items.put(delayedUpdate.getSource(), pos);
 
       final CommonODataEntity changes =
-              client.getObjectFactory().newEntity(delayedUpdate.getSource().getEntity().getTypeName());
+              factory.getClient().getObjectFactory().newEntity(delayedUpdate.getSource().getEntity().getTypeName());
 
-      AttachedEntityStatus status =
-              EntityContainerFactory.getContext().entityContext().getStatus(delayedUpdate.getSource());
+      AttachedEntityStatus status = factory.getContext().entityContext().getStatus(delayedUpdate.getSource());
 
       final URI sourceURI;
       if (status == AttachedEntityStatus.CHANGED) {
         sourceURI = URIUtils.getURI(
-                factory.getServiceRoot(),
+                factory.getClient().getServiceRoot(),
                 delayedUpdate.getSource().getEntity().getEditLink().toASCIIString());
       } else {
         int sourcePos = items.get(delayedUpdate.getSource());
@@ -468,20 +471,22 @@ class ContainerImpl implements Container {
       }
 
       for (EntityTypeInvocationHandler target : delayedUpdate.getTargets()) {
-        status = EntityContainerFactory.getContext().entityContext().getStatus(target);
+        status = factory.getContext().entityContext().getStatus(target);
 
         final URI targetURI;
         if (status == AttachedEntityStatus.CHANGED) {
           targetURI = URIUtils.getURI(
-                  factory.getServiceRoot(), target.getEntity().getEditLink().toASCIIString());
+                  factory.getClient().getServiceRoot(), target.getEntity().getEditLink().toASCIIString());
         } else {
           int targetPos = items.get(target);
           targetURI = URI.create("$" + targetPos);
         }
 
         changes.addLink(delayedUpdate.getType() == ODataLinkType.ENTITY_NAVIGATION
-                ? client.getObjectFactory().newEntityNavigationLink(delayedUpdate.getSourceName(), targetURI)
-                : client.getObjectFactory().newEntitySetNavigationLink(delayedUpdate.getSourceName(), targetURI));
+                ? factory.getClient().getObjectFactory().
+                newEntityNavigationLink(delayedUpdate.getSourceName(), targetURI)
+                : factory.getClient().getObjectFactory().
+                newEntitySetNavigationLink(delayedUpdate.getSourceName(), targetURI));
 
         LOG.debug("'{}' from {} to {}", delayedUpdate.getType().name(), sourceURI, targetURI);
       }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/e897cf27/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityCollectionInvocationHandler.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityCollectionInvocationHandler.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityCollectionInvocationHandler.java
index 06d03a2..ba3e449 100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityCollectionInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityCollectionInvocationHandler.java
@@ -47,7 +47,7 @@ public class EntityCollectionInvocationHandler<T extends Serializable>
   public EntityCollectionInvocationHandler(final EntityContainerInvocationHandler containerHandler,
           final Collection<T> items, final Class<?> itemRef, final URI uri) {
 
-    super(containerHandler.getClient(), containerHandler);
+    super(containerHandler);
 
     this.items = items;
     this.itemRef = itemRef;

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/e897cf27/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityContainerInvocationHandler.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityContainerInvocationHandler.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityContainerInvocationHandler.java
index 299a842..0289835 100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityContainerInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityContainerInvocationHandler.java
@@ -22,7 +22,6 @@ import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
 import org.apache.commons.lang3.ArrayUtils;
-import org.apache.olingo.client.api.CommonEdmEnabledODataClient;
 import org.apache.olingo.ext.proxy.EntityContainerFactory;
 import org.apache.olingo.ext.proxy.api.annotations.EntityContainer;
 import org.apache.olingo.ext.proxy.api.annotations.EntitySet;
@@ -33,7 +32,7 @@ public final class EntityContainerInvocationHandler extends AbstractInvocationHa
 
   private static final long serialVersionUID = 7379006755693410764L;
 
-  private final EntityContainerFactory factory;
+  private final EntityContainerFactory<?> factory;
 
   protected final String namespace;
 
@@ -42,17 +41,15 @@ public final class EntityContainerInvocationHandler extends AbstractInvocationHa
   private final boolean defaultEC;
 
   public static EntityContainerInvocationHandler getInstance(
-          final CommonEdmEnabledODataClient<?> client, final Class<?> ref, final EntityContainerFactory factory) {
+          final Class<?> ref, final EntityContainerFactory<?> factory) {
 
-    final EntityContainerInvocationHandler instance = new EntityContainerInvocationHandler(client, ref, factory);
+    final EntityContainerInvocationHandler instance = new EntityContainerInvocationHandler(ref, factory);
     instance.containerHandler = instance;
     return instance;
   }
 
-  private EntityContainerInvocationHandler(
-          final CommonEdmEnabledODataClient<?> client, final Class<?> ref, final EntityContainerFactory factory) {
-
-    super(client, null);
+  private EntityContainerInvocationHandler(final Class<?> ref, final EntityContainerFactory<?> factory) {
+    super(factory);
 
     final Annotation annotation = ref.getAnnotation(EntityContainer.class);
     if (!(annotation instanceof EntityContainer)) {
@@ -66,7 +63,7 @@ public final class EntityContainerInvocationHandler extends AbstractInvocationHa
     this.namespace = ((EntityContainer) annotation).namespace();
   }
 
-  protected EntityContainerFactory getFactory() {
+  protected EntityContainerFactory<?> getFactory() {
     return factory;
   }
 
@@ -87,7 +84,7 @@ public final class EntityContainerInvocationHandler extends AbstractInvocationHa
     if (isSelfMethod(method, args)) {
       return invokeSelfMethod(method, args);
     } else if ("flush".equals(method.getName()) && ArrayUtils.isEmpty(args)) {
-      new ContainerImpl(client, factory).flush();
+      new ContainerImpl(factory).flush();
       return ClassUtils.returnVoid();
     } else if ("operations".equals(method.getName()) && ArrayUtils.isEmpty(args)) {
       final Class<?> returnType = method.getReturnType();
@@ -102,7 +99,7 @@ public final class EntityContainerInvocationHandler extends AbstractInvocationHa
       return Proxy.newProxyInstance(
               Thread.currentThread().getContextClassLoader(),
               new Class<?>[] {returnType},
-              ComplexFactoryInvocationHandler.getInstance(getClient(), this, null, null));
+              ComplexFactoryInvocationHandler.getInstance(this, null, null));
     } else {
       final Class<?> returnType = method.getReturnType();
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/e897cf27/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntitySetInvocationHandler.java
----------------------------------------------------------------------
diff --git 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
index 18c2ce2..bcb0fb9 100644
--- 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
@@ -44,7 +44,6 @@ import org.apache.olingo.commons.api.domain.CommonODataEntitySet;
 import org.apache.olingo.commons.api.edm.FullQualifiedName;
 import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
 import org.apache.olingo.commons.api.format.ODataValueFormat;
-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.AbstractSingleton;
@@ -96,7 +95,7 @@ class EntitySetInvocationHandler<
           final EntityContainerInvocationHandler containerHandler,
           final String entitySetName) {
 
-    super(containerHandler.getClient(), containerHandler);
+    super(containerHandler);
 
     this.entitySetName = entitySetName;
     this.isSingleton = AbstractSingleton.class.isAssignableFrom(ref);
@@ -106,7 +105,7 @@ class EntitySetInvocationHandler<
     this.typeRef = (Class<T>) entitySetParams[0];
     this.collTypeRef = (Class<EC>) entitySetParams[2];
 
-    final CommonURIBuilder<?> uriBuilder = client.getURIBuilder(containerHandler.getFactory().getServiceRoot());
+    final CommonURIBuilder<?> uriBuilder = getClient().getURIBuilder(getClient().getServiceRoot());
 
     final StringBuilder entitySetSegment = new StringBuilder();
     if (!containerHandler.isDefaultEntityContainer()) {
@@ -152,12 +151,12 @@ class EntitySetInvocationHandler<
 
   @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);
-    EntityContainerFactory.getContext().entityContext().attachNew(handler);
+    getContext().entityContext().attachNew(handler);
 
     return (NE) Proxy.newProxyInstance(
             Thread.currentThread().getContextClassLoader(),
@@ -175,8 +174,8 @@ class EntitySetInvocationHandler<
 
   @Override
   public Long count() {
-    final ODataValueRequest req = client.getRetrieveRequestFactory().
-            getValueRequest(client.getURIBuilder(this.uri.toASCIIString()).count().build());
+    final ODataValueRequest req = getClient().getRetrieveRequestFactory().
+            getValueRequest(getClient().getURIBuilder(this.uri.toASCIIString()).count().build());
     req.setFormat(ODataValueFormat.TEXT);
     return Long.valueOf(req.execute().getBody().asPrimitive().toString());
   }
@@ -233,13 +232,13 @@ class EntitySetInvocationHandler<
     final EntityUUID uuid = new EntityUUID(containerHandler.getEntityContainerName(), entitySetName, typeRef, key);
     LOG.debug("Ask for '{}({})'", typeRef.getSimpleName(), key);
 
-    EntityTypeInvocationHandler handler = EntityContainerFactory.getContext().entityContext().getEntity(uuid);
+    EntityTypeInvocationHandler handler = getContext().entityContext().getEntity(uuid);
 
     if (handler == null) {
       // not yet attached: search against the service
       try {
         LOG.debug("Search for '{}({})' into the service", typeRef.getSimpleName(), key);
-        final CommonURIBuilder<?> uriBuilder = client.getURIBuilder(this.uri.toASCIIString());
+        final CommonURIBuilder<?> uriBuilder = getClient().getURIBuilder(this.uri.toASCIIString());
 
         if (key.getClass().getAnnotation(CompoundKey.class) == null) {
           LOG.debug("Append key segment '{}'", key);
@@ -252,17 +251,20 @@ class EntitySetInvocationHandler<
         LOG.debug("GET {}", uriBuilder.toString());
 
         final ODataRetrieveResponse<CommonODataEntity> res =
-                client.getRetrieveRequestFactory().getEntityRequest(uriBuilder.build()).execute();
+                getClient().getRetrieveRequestFactory().getEntityRequest(uriBuilder.build()).execute();
 
         final String etag = res.getETag();
         final CommonODataEntity entity = res.getBody();
-
-        if (entity == null || !key.equals(CoreUtils.getKey(client, typeRef, entity))) {
+        if (entity == null) {
           throw new IllegalArgumentException("Invalid " + typeRef.getSimpleName() + "(" + key + ")");
         }
 
         handler = EntityTypeInvocationHandler.getInstance(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);
       }
@@ -285,13 +287,13 @@ class EntitySetInvocationHandler<
 
     if (isSingleton) {
       final ODataRetrieveResponse<org.apache.olingo.commons.api.domain.v4.Singleton> res =
-              ((ODataClient) client).getRetrieveRequestFactory().getSingletonRequest(uri).execute();
+              ((ODataClient) getClient()).getRetrieveRequestFactory().getSingletonRequest(uri).execute();
 
       entities.add(res.getBody());
       next = null;
     } else {
       final ODataRetrieveResponse<CommonODataEntitySet> res =
-              client.getRetrieveRequestFactory().getEntitySetRequest(uri).execute();
+              getClient().getRetrieveRequestFactory().getEntitySetRequest(uri).execute();
 
       final CommonODataEntitySet entitySet = res.getBody();
       entities.addAll(entitySet.getEntities());
@@ -303,8 +305,7 @@ class EntitySetInvocationHandler<
     for (CommonODataEntity entity : entities) {
       final EntityTypeInvocationHandler handler = EntityTypeInvocationHandler.getInstance(entity, this, typeRef);
 
-      final EntityTypeInvocationHandler handlerInTheContext =
-              EntityContainerFactory.getContext().entityContext().getEntity(handler.getUUID());
+      final EntityTypeInvocationHandler handlerInTheContext = getContext().entityContext().getEntity(handler.getUUID());
 
       items.add((S) Proxy.newProxyInstance(
               Thread.currentThread().getContextClassLoader(),
@@ -345,7 +346,7 @@ class EntitySetInvocationHandler<
     final Class<S> ref = (Class<S>) ClassUtils.extractTypeArg(collTypeRef);
     final Class<S> oref = (Class<S>) ClassUtils.extractTypeArg(this.collTypeRef);
 
-    final CommonURIBuilder<?> uriBuilder = client.getURIBuilder(this.uri.toASCIIString());
+    final CommonURIBuilder<?> uriBuilder = getClient().getURIBuilder(this.uri.toASCIIString());
 
     final URI entitySetURI;
     if (oref.equals(ref)) {
@@ -360,7 +361,7 @@ class EntitySetInvocationHandler<
 
   @Override
   public Filter<T, EC> createFilter() {
-    return new FilterImpl<T, EC>(this.client, this.collTypeRef, this.uri, this);
+    return new FilterImpl<T, EC>(getClient(), this.collTypeRef, this.uri, this);
   }
 
   @Override
@@ -368,16 +369,15 @@ class EntitySetInvocationHandler<
   public <S extends T, SEC extends AbstractEntityCollection<S>> Filter<S, SEC> createFilter(
           final Class<SEC> reference) {
 
-    return new FilterImpl<S, SEC>(
-            this.client, reference, this.uri, (EntitySetInvocationHandler<S, ?, SEC>) this);
+    return new FilterImpl<S, SEC>(getClient(), reference, this.uri, (EntitySetInvocationHandler<S, ?, SEC>) this);
   }
 
   @Override
   public Search<T, EC> createSearch() {
-    if (client.getServiceVersion().compareTo(ODataServiceVersion.V30) <= 0) {
+    if (getClient().getServiceVersion().compareTo(ODataServiceVersion.V30) <= 0) {
       throw new UnsupportedInV3Exception();
     }
-    return new SearchImpl<T, EC>((EdmEnabledODataClient) this.client, this.collTypeRef, this.uri, this);
+    return new SearchImpl<T, EC>((EdmEnabledODataClient) getClient(), this.collTypeRef, this.uri, this);
   }
 
   @Override
@@ -385,16 +385,16 @@ class EntitySetInvocationHandler<
   public <S extends T, SEC extends AbstractEntityCollection<S>> Search<S, SEC> createSearch(
           final Class<SEC> reference) {
 
-    if (client.getServiceVersion().compareTo(ODataServiceVersion.V30) <= 0) {
+    if (getClient().getServiceVersion().compareTo(ODataServiceVersion.V30) <= 0) {
       throw new UnsupportedInV3Exception();
     }
     return new SearchImpl<S, SEC>(
-            (EdmEnabledODataClient) this.client, reference, this.uri, (EntitySetInvocationHandler<S, ?, SEC>) this);
+            (EdmEnabledODataClient) getClient(), reference, this.uri, (EntitySetInvocationHandler<S, ?, SEC>) this);
   }
 
   @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(
             containerHandler.getEntityContainerName(),
@@ -414,7 +414,7 @@ class EntitySetInvocationHandler<
 
   @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);
@@ -427,11 +427,11 @@ class EntitySetInvocationHandler<
   }
 
   private boolean isDeleted(final EntityTypeInvocationHandler handler) {
-    return EntityContainerFactory.getContext().entityContext().getStatus(handler) == AttachedEntityStatus.DELETED;
+    return getContext().entityContext().getStatus(handler) == AttachedEntityStatus.DELETED;
   }
 
   @Override
   public EntitySetIterator<T, KEY, EC> iterator() {
-    return new EntitySetIterator<T, KEY, EC>(client.getURIBuilder(this.uri.toASCIIString()).build(), this);
+    return new EntitySetIterator<T, KEY, EC>(getClient().getURIBuilder(this.uri.toASCIIString()).build(), this);
   }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/e897cf27/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityTypeInvocationHandler.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityTypeInvocationHandler.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityTypeInvocationHandler.java
index 57b73d0..5b2c30d 100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityTypeInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityTypeInvocationHandler.java
@@ -19,7 +19,6 @@
 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;
@@ -28,9 +27,7 @@ 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;
@@ -92,7 +89,7 @@ public class EntityTypeInvocationHandler extends AbstractTypeInvocationHandler {
           final Class<?> typeRef,
           final EntityContainerInvocationHandler containerHandler) {
 
-    super(containerHandler.getClient(), typeRef, (ODataLinked) entity, containerHandler);
+    super(typeRef, (ODataLinked) entity, containerHandler);
 
     this.internal = entity;
     getEntity().setMediaEntity(typeRef.getAnnotation(EntityType.class).hasStream());
@@ -101,7 +98,7 @@ public class EntityTypeInvocationHandler extends AbstractTypeInvocationHandler {
             containerHandler.getEntityContainerName(),
             entitySetName,
             typeRef,
-            CoreUtils.getKey(client, typeRef, entity));
+            CoreUtils.getKey(getClient(), this, typeRef, entity));
   }
 
   public void setEntity(final CommonODataEntity entity) {
@@ -112,7 +109,7 @@ public class EntityTypeInvocationHandler extends AbstractTypeInvocationHandler {
             getUUID().getContainerName(),
             getUUID().getEntitySetName(),
             getUUID().getType(),
-            CoreUtils.getKey(client, typeRef, entity));
+            CoreUtils.getKey(getClient(), this, typeRef, entity));
 
     this.propertyChanges.clear();
     this.linkChanges.clear();
@@ -184,8 +181,7 @@ public class EntityTypeInvocationHandler extends AbstractTypeInvocationHandler {
       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);
         }
@@ -198,30 +194,6 @@ public class EntityTypeInvocationHandler extends AbstractTypeInvocationHandler {
   }
 
   @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())) {
@@ -230,7 +202,7 @@ public class EntityTypeInvocationHandler extends AbstractTypeInvocationHandler {
       addPropertyChanges(property.name(), value);
 
       if (value != null) {
-        final Collection<?> coll;
+        Collection<?> coll;
         if (Collection.class.isAssignableFrom(value.getClass())) {
           coll = Collection.class.cast(value);
         } else {
@@ -287,7 +259,7 @@ public class EntityTypeInvocationHandler extends AbstractTypeInvocationHandler {
       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();
@@ -303,10 +275,10 @@ public class EntityTypeInvocationHandler extends AbstractTypeInvocationHandler {
     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();
 
       }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/e897cf27/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/OperationInvocationHandler.java
----------------------------------------------------------------------
diff --git 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
index cdc0bfb..e2362eb 100644
--- 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
@@ -49,8 +49,6 @@ class OperationInvocationHandler extends AbstractInvocationHandler implements Op
 
   private final FullQualifiedName targetFQN;
 
-  private final String serviceRoot;
-
   static OperationInvocationHandler getInstance(final EntityContainerInvocationHandler containerHandler) {
     return new OperationInvocationHandler(containerHandler);
   }
@@ -64,26 +62,21 @@ class OperationInvocationHandler extends AbstractInvocationHandler implements Op
   }
 
   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) {
-    super(entityHandler.getClient(), entityHandler.containerHandler);
+    super(entityHandler.containerHandler);
 
     this.target = entityHandler;
     this.targetFQN = entityHandler.getEntity().getTypeName();
-    this.serviceRoot = containerHandler.getFactory().getServiceRoot();
   }
 
   private OperationInvocationHandler(final EntityCollectionInvocationHandler<?> collectionHandler) {
-    super(collectionHandler.getClient(), collectionHandler.containerHandler);
+    super(collectionHandler.containerHandler);
 
     this.target = collectionHandler;
 
@@ -91,7 +84,6 @@ class OperationInvocationHandler extends AbstractInvocationHandler implements Op
     final String typeNamespace = ClassUtils.getNamespace(collectionHandler.getEntityReference());
 
     this.targetFQN = new FullQualifiedName(typeNamespace, typeName);
-    this.serviceRoot = containerHandler.getFactory().getServiceRoot();
   }
 
   @Override
@@ -145,7 +137,7 @@ class OperationInvocationHandler extends AbstractInvocationHandler implements Op
 
   private Map.Entry<URI, EdmOperation> getUnboundOperation(
           final Operation operation, final List<String> parameterNames) {
-    final EdmEntityContainer container = client.getCachedEdm().getEntityContainer(targetFQN);
+    final EdmEntityContainer container = getClient().getCachedEdm().getEntityContainer(targetFQN);
     final EdmOperation edmOperation;
 
     if (operation.type() == OperationType.FUNCTION) {
@@ -154,7 +146,7 @@ class OperationInvocationHandler extends AbstractInvocationHandler implements Op
       edmOperation = container.getActionImport(operation.name()).getUnboundAction();
     }
 
-    final CommonURIBuilder<?> uriBuilder = getClient().getURIBuilder(this.serviceRoot).
+    final CommonURIBuilder<?> uriBuilder = getClient().getURIBuilder(getClient().getServiceRoot()).
             appendOperationCallSegment(URIUtils.operationImportURISegment(container, edmOperation.getName()));
 
     return new AbstractMap.SimpleEntry<URI, EdmOperation>(uriBuilder.build(), edmOperation);
@@ -176,13 +168,13 @@ class OperationInvocationHandler extends AbstractInvocationHandler implements Op
             ? new FullQualifiedName(targetFQN.getNamespace(), boundOp.getTitle())
             : new FullQualifiedName(boundOp.getTitle());
 
-    EdmEntityType entityType = client.getCachedEdm().getEntityType(entity.getTypeName());
+    EdmEntityType entityType = getClient().getCachedEdm().getEntityType(entity.getTypeName());
     EdmOperation edmOperation = null;
     while (edmOperation == null && entityType != null) {
       edmOperation = operation.type() == OperationType.FUNCTION
-              ? client.getCachedEdm().getBoundFunction(
+              ? getClient().getCachedEdm().getBoundFunction(
                       operationFQN, entityType.getFullQualifiedName(), false, parameterNames)
-              : client.getCachedEdm().getBoundAction(
+              : getClient().getCachedEdm().getBoundAction(
                       operationFQN, entityType.getFullQualifiedName(), false);
       if (entityType.getBaseType() != null) {
         entityType = entityType.getBaseType();
@@ -202,10 +194,10 @@ class OperationInvocationHandler extends AbstractInvocationHandler implements Op
 
     EdmOperation edmOperation;
     if (operation.type() == OperationType.FUNCTION) {
-      edmOperation = client.getCachedEdm().getBoundFunction(
+      edmOperation = getClient().getCachedEdm().getBoundFunction(
               new FullQualifiedName(targetFQN.getNamespace(), operation.name()), targetFQN, true, parameterNames);
     } else {
-      edmOperation = client.getCachedEdm().getBoundAction(
+      edmOperation = getClient().getCachedEdm().getBoundAction(
               new FullQualifiedName(targetFQN.getNamespace(), operation.name()), targetFQN, true);
     }
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/e897cf27/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/SingletonInvocationHandler.java
----------------------------------------------------------------------
diff --git 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
index 4ec75eb..664e894 100644
--- 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
@@ -42,7 +42,7 @@ public class SingletonInvocationHandler<
 
   @SuppressWarnings({"rawtypes", "unchecked"})
   private SingletonInvocationHandler(final Class<?> ref, final EntityContainerInvocationHandler containerHandler) {
-    super(containerHandler.getClient(), containerHandler);
+    super(containerHandler);
     this.entitySetHandler =
             new EntitySetInvocationHandler(ref, containerHandler, (ref.getAnnotation(Singleton.class)).name());
   }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/e897cf27/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/utils/CoreUtils.java
----------------------------------------------------------------------
diff --git 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
index cda964e..bd7a537 100644
--- 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,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 Class<?> entityTypeRef,
+          final CommonODataEntity entity) {
 
     Object res = null;
 
@@ -364,7 +367,7 @@ public final class CoreUtils {
       } else {
         try {
           res = keyRef.newInstance();
-          populate(client, res, CompoundKeyElement.class, entity.getProperties().iterator());
+          populate(client, typeHandler, res, CompoundKeyElement.class, entity.getProperties().iterator());
         } catch (Exception e) {
           LOG.error("Error population compound key {}", keyRef.getSimpleName(), e);
           throw new IllegalArgumentException("Cannot populate compound key");
@@ -375,8 +378,9 @@ public final class CoreUtils {
     return res;
   }
 
-  public static void populate(
+  private static void populate(
           final CommonEdmEnabledODataClient<?> client,
+          final EntityTypeInvocationHandler typeHandler,
           final Object bean,
           final Class<? extends Annotation> getterAnn,
           final Iterator<? extends CommonODataProperty> propItor) {
@@ -393,15 +397,16 @@ public final class CoreUtils {
       } else {
         typeRef = bean.getClass();
       }
-      populate(client, bean, typeRef, getterAnn, propItor);
+      populate(client, typeHandler, bean, typeRef, getterAnn, propItor);
     }
   }
 
   @SuppressWarnings({"unchecked"})
-  public static void populate(
+  private static void populate(
           final CommonEdmEnabledODataClient<?> client,
+          final EntityTypeInvocationHandler typeHandler,
           final Object bean,
-          final Class<?> reference,
+          final Class<?> typeRef,
           final Class<? extends Annotation> getterAnn,
           final Iterator<? extends CommonODataProperty> propItor) {
 
@@ -409,7 +414,7 @@ public final class CoreUtils {
       while (propItor.hasNext()) {
         final CommonODataProperty property = propItor.next();
 
-        final Method getter = ClassUtils.findGetterByAnnotatedName(reference, getterAnn, property.getName());
+        final Method getter = ClassUtils.findGetterByAnnotatedName(typeRef, getterAnn, property.getName());
 
         if (getter == null) {
           LOG.warn("Could not find any property annotated as {} in {}",
@@ -420,15 +425,15 @@ public final class CoreUtils {
               setPropertyValue(bean, getter, null);
             } else if (property.hasPrimitiveValue()) {
               setPropertyValue(bean, getter, primitiveValueToObject(
-                      property.getPrimitiveValue(), getPropertyClass(reference, property.getName())));
+                      property.getPrimitiveValue(), getPropertyClass(typeRef, property.getName())));
             } else if (property.hasComplexValue()) {
               final Object complex = Proxy.newProxyInstance(
                       Thread.currentThread().getContextClassLoader(),
                       new Class<?>[] {getter.getReturnType()},
                       ComplexTypeInvocationHandler.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();
@@ -445,15 +450,15 @@ public final class CoreUtils {
                 final ODataValue value = collPropItor.next();
                 if (value.isPrimitive()) {
                   collection.add(primitiveValueToObject(
-                          value.asPrimitive(), getPropertyClass(reference, property.getName())));
+                          value.asPrimitive(), getPropertyClass(typeRef, property.getName())));
                 } else if (value.isComplex()) {
                   final Object collItem = Proxy.newProxyInstance(
                           Thread.currentThread().getContextClassLoader(),
                           new Class<?>[] {collItemClass},
                           ComplexTypeInvocationHandler.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);
                 }
               }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/e897cf27/fit/src/test/java/org/apache/olingo/fit/proxy/v3/AbstractTestITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/proxy/v3/AbstractTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/proxy/v3/AbstractTestITCase.java
index de9cdc3..17bb65b 100644
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/v3/AbstractTestITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/v3/AbstractTestITCase.java
@@ -29,7 +29,6 @@ import java.util.Collections;
 import org.apache.olingo.client.api.v3.EdmEnabledODataClient;
 import org.apache.olingo.commons.api.format.ContentType;
 import org.apache.olingo.ext.proxy.EntityContainerFactory;
-import org.apache.olingo.ext.proxy.context.EntityContext;
 import org.apache.olingo.fit.proxy.v3.staticservice.microsoft.test.odata.services.astoriadefaultservice.
         DefaultContainer;
 import org.apache.olingo.fit.proxy.v3.staticservice.microsoft.test.odata.services.astoriadefaultservice.types.
@@ -65,8 +64,6 @@ public abstract class AbstractTestITCase {
 
   protected static String testAuthServiceRootURL;
 
-  protected final EntityContext entityContext = EntityContainerFactory.getContext().entityContext();
-
   protected static EntityContainerFactory<EdmEnabledODataClient> containerFactory;
 
   protected static DefaultContainer container;
@@ -85,7 +82,7 @@ public abstract class AbstractTestITCase {
     containerFactory.getClient().getConfiguration().setDefaultBatchAcceptFormat(ContentType.APPLICATION_OCTET_STREAM);
     container = containerFactory.getEntityContainer(DefaultContainer.class);
     assertNotNull(container);
-    EntityContainerFactory.getContext().detachAll();
+    containerFactory.getContext().detachAll();
   }
 
   protected Customer getSampleCustomerProfile(

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/e897cf27/fit/src/test/java/org/apache/olingo/fit/proxy/v3/ActionOverloadingTestITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/proxy/v3/ActionOverloadingTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/proxy/v3/ActionOverloadingTestITCase.java
index c0e65c9..5c8019b 100644
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/v3/ActionOverloadingTestITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/v3/ActionOverloadingTestITCase.java
@@ -58,12 +58,12 @@ public class ActionOverloadingTestITCase extends AbstractTestITCase {
     int res = aocontainer.operations().retrieveProduct();
     assertEquals(-10, res);
 
-    EntityContainerFactory.getContext().detachAll();
+    containerFactory.getContext().detachAll();
 
     res = aocontainer.getProduct().get(-10).operations().retrieveProduct();
     assertEquals(-10, res);
 
-    EntityContainerFactory.getContext().detachAll();
+    containerFactory.getContext().detachAll();
 
     final OrderLineKey key = new OrderLineKey();
     key.setOrderId(-10);
@@ -89,7 +89,7 @@ public class ActionOverloadingTestITCase extends AbstractTestITCase {
     ecoll.operations().increaseSalaries(5);
 
     // the invoke above changed the local entities, re-read
-    EntityContainerFactory.getContext().detachAll();        
+    containerFactory.getContext().detachAll();        
     ecoll = aocontainer.getPerson().getAll(EmployeeCollection.class);
     empl = ecoll.iterator().next();
     
@@ -107,7 +107,7 @@ public class ActionOverloadingTestITCase extends AbstractTestITCase {
     secoll.operations().increaseSalaries(5);
 
     // the invoke above changed the local entities, re-read
-    EntityContainerFactory.getContext().detachAll();        
+    containerFactory.getContext().detachAll();        
     secoll = aocontainer.getPerson().getAll(SpecialEmployeeCollection.class);
     sempl = secoll.toArray(new SpecialEmployee[secoll.size()])[1];
     


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

Posted by il...@apache.org.
[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);
                  }
                }


[6/9] git commit: Cleaning up EntityContainerFactory#getServiceRoot

Posted by il...@apache.org.
Cleaning up EntityContainerFactory#getServiceRoot


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

Branch: refs/heads/master
Commit: 3c0b8ad2658cf84f002e3b10c9b93d6ea1ccc9c5
Parents: 72d894c
Author: Francesco Chicchiriccò <--global>
Authored: Thu May 22 08:55:43 2014 +0200
Committer: Francesco Chicchiriccò <--global>
Committed: Thu May 22 08:55:43 2014 +0200

----------------------------------------------------------------------
 .../ext/proxy/EntityContainerFactory.java       | 30 ++++++--------------
 .../AbstractStructuredInvocationHandler.java    | 10 +++----
 .../proxy/commons/ComplexInvocationHandler.java |  4 +--
 .../olingo/ext/proxy/commons/ContainerImpl.java | 16 +++++------
 .../proxy/commons/EntityInvocationHandler.java  |  5 ++--
 .../commons/OperationInvocationHandler.java     |  9 ++----
 6 files changed, 25 insertions(+), 49 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/3c0b8ad2/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/EntityContainerFactory.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/EntityContainerFactory.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/EntityContainerFactory.java
index 9de2d4f..b0d2ff9 100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/EntityContainerFactory.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/EntityContainerFactory.java
@@ -21,7 +21,6 @@ package org.apache.olingo.ext.proxy;
 import java.lang.reflect.Proxy;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
-import org.apache.commons.lang3.StringUtils;
 import org.apache.olingo.client.api.CommonEdmEnabledODataClient;
 import org.apache.olingo.client.core.ODataClientFactory;
 import org.apache.olingo.commons.api.format.ODataPubFormat;
@@ -46,8 +45,6 @@ public final class EntityContainerFactory<C extends CommonEdmEnabledODataClient<
 
   private final CommonEdmEnabledODataClient<?> client;
 
-  private final String serviceRoot;
-
   public static Context getContext() {
     synchronized (MONITOR) {
       if (context == null) {
@@ -59,33 +56,31 @@ public final class EntityContainerFactory<C extends CommonEdmEnabledODataClient<
   }
 
   @SuppressWarnings("unchecked")
-  private static <C extends CommonEdmEnabledODataClient<?>> EntityContainerFactory<C> getInstance(
-          final C client, final String serviceRoot) {
+  private static <C extends CommonEdmEnabledODataClient<?>> EntityContainerFactory<C> getInstance(final C client) {
 
-    if (!FACTORY_PER_SERVICEROOT.containsKey(serviceRoot)) {
+    if (!FACTORY_PER_SERVICEROOT.containsKey(client.getServiceRoot())) {
       client.getConfiguration().setDefaultPubFormat(ODataPubFormat.JSON_FULL_METADATA);
-      final EntityContainerFactory<C> instance = new EntityContainerFactory<C>(client, serviceRoot);
-      FACTORY_PER_SERVICEROOT.put(serviceRoot, instance);
+      final EntityContainerFactory<C> instance = new EntityContainerFactory<C>(client);
+      FACTORY_PER_SERVICEROOT.put(client.getServiceRoot(), instance);
     }
 
-    return (EntityContainerFactory<C>) FACTORY_PER_SERVICEROOT.get(serviceRoot);
+    return (EntityContainerFactory<C>) FACTORY_PER_SERVICEROOT.get(client.getServiceRoot());
   }
 
   public static EntityContainerFactory<org.apache.olingo.client.api.v3.EdmEnabledODataClient> getV3(
           final String serviceRoot) {
 
-    return getInstance(ODataClientFactory.getEdmEnabledV3(serviceRoot), serviceRoot);
+    return getInstance(ODataClientFactory.getEdmEnabledV3(serviceRoot));
   }
 
   public static EntityContainerFactory<org.apache.olingo.client.api.v4.EdmEnabledODataClient> getV4(
           final String serviceRoot) {
 
-    return getInstance(ODataClientFactory.getEdmEnabledV4(serviceRoot), serviceRoot);
+    return getInstance(ODataClientFactory.getEdmEnabledV4(serviceRoot));
   }
 
-  private EntityContainerFactory(final CommonEdmEnabledODataClient<?> client, final String serviceRoot) {
+  private EntityContainerFactory(final CommonEdmEnabledODataClient<?> client) {
     this.client = client;
-    this.serviceRoot = serviceRoot;
   }
 
   @SuppressWarnings("unchecked")
@@ -93,24 +88,15 @@ public final class EntityContainerFactory<C extends CommonEdmEnabledODataClient<
     return (C) client;
   }
 
-  public String getServiceRoot() {
-    return serviceRoot;
-  }
-
   /**
    * Return an initialized concrete implementation of the passed EntityContainer interface.
    *
    * @param <T> interface annotated as EntityContainer
    * @param reference class object of the EntityContainer annotated interface
    * @return an initialized concrete implementation of the passed reference
-   * @throws IllegalStateException if <tt>serviceRoot</tt> was not set
    * @throws IllegalArgumentException if the passed reference is not an interface annotated as EntityContainer
    */
   public <T> T getEntityContainer(final Class<T> reference) throws IllegalStateException, IllegalArgumentException {
-    if (StringUtils.isBlank(serviceRoot)) {
-      throw new IllegalStateException("serviceRoot was not set");
-    }
-
     if (!ENTITY_CONTAINERS.containsKey(reference)) {
       final Object entityContainer = Proxy.newProxyInstance(
               Thread.currentThread().getContextClassLoader(),

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/3c0b8ad2/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 5f04408..f208e83 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
@@ -219,9 +219,7 @@ public abstract class AbstractStructuredInvocationHandler extends AbstractInvoca
 
   protected abstract Object getNavigationPropertyValue(final NavigationProperty property, final Method getter);
 
-  protected Object retrieveNavigationProperty(
-          final NavigationProperty property, final Method getter, final String serviceRoot) {
-
+  protected Object retrieveNavigationProperty(final NavigationProperty property, final Method getter) {
     final Class<?> type = getter.getReturnType();
     final Class<?> collItemType;
     if (AbstractEntityCollection.class.isAssignableFrom(type)) {
@@ -241,7 +239,7 @@ public abstract class AbstractStructuredInvocationHandler extends AbstractInvoca
               null,
               ((ODataInlineEntity) link).getEntity(),
               property.targetContainer(),
-              client.newURIBuilder(serviceRoot).appendEntitySetSegment(property.targetEntitySet()).build(),
+              client.newURIBuilder().appendEntitySetSegment(property.targetEntitySet()).build(),
               type,
               false);
     } else if (link instanceof ODataInlineEntitySet) {
@@ -255,7 +253,7 @@ public abstract class AbstractStructuredInvocationHandler extends AbstractInvoca
               false);
     } else {
       // navigate
-      final URI uri = URIUtils.getURI(containerHandler.getFactory().getServiceRoot(), link.getLink().toASCIIString());
+      final URI uri = URIUtils.getURI(client.getServiceRoot(), link.getLink().toASCIIString());
       if (AbstractEntityCollection.class.isAssignableFrom(type)) {
         navPropValue = getEntityCollectionProxy(
                 collItemType,
@@ -278,7 +276,7 @@ public abstract class AbstractStructuredInvocationHandler extends AbstractInvoca
                 uri,
                 res.getBody(),
                 property.targetContainer(),
-                client.newURIBuilder(serviceRoot).appendEntitySetSegment(property.targetEntitySet()).build(),
+                client.newURIBuilder().appendEntitySetSegment(property.targetEntitySet()).build(),
                 type,
                 res.getETag(),
                 true);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/3c0b8ad2/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ComplexInvocationHandler.java
----------------------------------------------------------------------
diff --git 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
index a207e68..2a7e946 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
@@ -174,7 +174,7 @@ public class ComplexInvocationHandler extends AbstractStructuredInvocationHandle
       throw new UnsupportedOperationException("Internal object is not navigable");
     }
 
-    return retrieveNavigationProperty(property, getter, containerHandler.getFactory().getServiceRoot());
+    return retrieveNavigationProperty(property, getter);
   }
 
   @Override
@@ -186,7 +186,7 @@ public class ComplexInvocationHandler extends AbstractStructuredInvocationHandle
   @Override
   public void removeAdditionalProperty(final String name) {
     final CommonODataProperty property = getComplex().get(name);
-    if(property !=null && !property.hasNullValue()){
+    if (property != null && !property.hasNullValue()) {
       setPropertyValue(name, null, null);
       attach(AttachedEntityStatus.CHANGED);
     }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/3c0b8ad2/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ContainerImpl.java
----------------------------------------------------------------------
diff --git 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
index 1a6e6d9..f7abf9b 100644
--- 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
@@ -336,7 +336,6 @@ class ContainerImpl implements Container {
               : ODataLinkType.ENTITY_NAVIGATION;
 
       final Set<EntityInvocationHandler> toBeLinked = new HashSet<EntityInvocationHandler>();
-      final String serviceRoot = factory.getServiceRoot();
 
       for (Object proxy : type == ODataLinkType.ENTITY_SET_NAVIGATION
               ? (Collection) property.getValue() : Collections.singleton(property.getValue())) {
@@ -352,7 +351,7 @@ class ContainerImpl implements Container {
         if ((status == AttachedEntityStatus.ATTACHED || status == AttachedEntityStatus.LINKED) && !target.isChanged()) {
           entity.addLink(buildNavigationLink(
                   property.getKey().name(),
-                  URIUtils.getURI(serviceRoot, editLink.toASCIIString()), type));
+                  URIUtils.getURI(client.getServiceRoot(), editLink.toASCIIString()), type));
         } else {
           if (!items.contains(target)) {
             pos = processEntityContext(target, pos, items, delayedUpdates, changeset);
@@ -367,7 +366,7 @@ class ContainerImpl implements Container {
           } else if (status == AttachedEntityStatus.CHANGED) {
             entity.addLink(buildNavigationLink(
                     property.getKey().name(),
-                    URIUtils.getURI(serviceRoot, editLink.toASCIIString()), type));
+                    URIUtils.getURI(client.getServiceRoot(), editLink.toASCIIString()), type));
           } else {
             // create the link for the current object
             LOG.debug("'{}' from '{}' to (${}) '{}'", type.name(), handler, targetPos, target);
@@ -406,7 +405,7 @@ class ContainerImpl implements Container {
         if (!handler.getPropertyChanges().isEmpty()) {
           final URI targetURI = currentStatus == AttachedEntityStatus.NEW
                   ? URI.create("$" + startingPos)
-                  : URIUtils.getURI(factory.getServiceRoot(), handler.getEntity().getEditLink().toASCIIString());
+                  : URIUtils.getURI(client.getServiceRoot(), handler.getEntity().getEditLink().toASCIIString());
           batchUpdate(handler, targetURI, entity, changeset);
           pos++;
           items.put(handler, pos);
@@ -417,7 +416,7 @@ class ContainerImpl implements Container {
           final URI targetURI = currentStatus == AttachedEntityStatus.NEW
                   ? URI.create("$" + startingPos + "/$value")
                   : URIUtils.getURI(
-                          factory.getServiceRoot(), handler.getEntity().getEditLink().toASCIIString() + "/$value");
+                          client.getServiceRoot(), handler.getEntity().getEditLink().toASCIIString() + "/$value");
 
           batchUpdateMediaEntity(handler, targetURI, handler.getStreamChanges(), changeset);
 
@@ -430,7 +429,7 @@ class ContainerImpl implements Container {
       for (Map.Entry<String, InputStream> streamedChanges : handler.getStreamedPropertyChanges().entrySet()) {
         final URI targetURI = currentStatus == AttachedEntityStatus.NEW
                 ? URI.create("$" + startingPos) : URIUtils.getURI(
-                        factory.getServiceRoot(),
+                        client.getServiceRoot(),
                         CoreUtils.getMediaEditLink(streamedChanges.getKey(), entity).toASCIIString());
 
         batchUpdateMediaResource(handler, targetURI, streamedChanges.getValue(), changeset);
@@ -482,7 +481,7 @@ class ContainerImpl implements Container {
       final URI sourceURI;
       if (status == AttachedEntityStatus.CHANGED) {
         sourceURI = URIUtils.getURI(
-                factory.getServiceRoot(),
+                client.getServiceRoot(),
                 delayedUpdate.getSource().getEntity().getEditLink().toASCIIString());
       } else {
         int sourcePos = items.get(delayedUpdate.getSource());
@@ -494,8 +493,7 @@ class ContainerImpl implements Container {
 
         final URI targetURI;
         if (status == AttachedEntityStatus.CHANGED) {
-          targetURI = URIUtils.getURI(
-                  factory.getServiceRoot(), target.getEntity().getEditLink().toASCIIString());
+          targetURI = URIUtils.getURI(client.getServiceRoot(), target.getEntity().getEditLink().toASCIIString());
         } else {
           int targetPos = items.get(target);
           targetURI = URI.create("$" + targetPos);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/3c0b8ad2/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityInvocationHandler.java
----------------------------------------------------------------------
diff --git 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
index 2d9065a..4c2fa36 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
@@ -338,8 +338,7 @@ public class EntityInvocationHandler extends AbstractStructuredInvocationHandler
     try {
       if (res == null) {
         final URI link = URIUtils.getURI(
-                containerHandler.getFactory().getServiceRoot(),
-                CoreUtils.getMediaEditLink(name, getEntity()).toASCIIString());
+                client.getServiceRoot(), CoreUtils.getMediaEditLink(name, getEntity()).toASCIIString());
 
         final ODataMediaRequest req = client.getRetrieveRequestFactory().getMediaRequest(link);
         res = req.execute().getBody();
@@ -369,7 +368,7 @@ public class EntityInvocationHandler extends AbstractStructuredInvocationHandler
     if (linkChanges.containsKey(property)) {
       navPropValue = linkChanges.get(property);
     } else {
-      navPropValue = retrieveNavigationProperty(property, getter, containerHandler.getFactory().getServiceRoot());
+      navPropValue = retrieveNavigationProperty(property, getter);
     }
 
     if (navPropValue != null) {

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/3c0b8ad2/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/OperationInvocationHandler.java
----------------------------------------------------------------------
diff --git 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
index d28a319..1a3e1be 100644
--- 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
@@ -48,8 +48,6 @@ final class OperationInvocationHandler extends AbstractInvocationHandler impleme
 
   private final FullQualifiedName targetFQN;
 
-  private final String serviceRoot;
-
   static OperationInvocationHandler getInstance(final EntityContainerInvocationHandler containerHandler) {
     return new OperationInvocationHandler(containerHandler);
   }
@@ -69,8 +67,6 @@ final class OperationInvocationHandler extends AbstractInvocationHandler impleme
 
     this.targetFQN =
             new FullQualifiedName(containerHandler.getSchemaName(), containerHandler.getEntityContainerName());
-
-    this.serviceRoot = containerHandler.getFactory().getServiceRoot();
   }
 
   private OperationInvocationHandler(final EntityInvocationHandler entityHandler) {
@@ -78,7 +74,6 @@ final class OperationInvocationHandler extends AbstractInvocationHandler impleme
 
     this.target = entityHandler;
     this.targetFQN = entityHandler.getEntity().getTypeName();
-    this.serviceRoot = containerHandler.getFactory().getServiceRoot();
   }
 
   private OperationInvocationHandler(final EntityCollectionInvocationHandler<?> collectionHandler) {
@@ -90,7 +85,6 @@ final class OperationInvocationHandler extends AbstractInvocationHandler impleme
     final String typeNamespace = ClassUtils.getNamespace(collectionHandler.getEntityReference());
 
     this.targetFQN = new FullQualifiedName(typeNamespace, typeName);
-    this.serviceRoot = containerHandler.getFactory().getServiceRoot();
   }
 
   @Override
@@ -144,6 +138,7 @@ final class OperationInvocationHandler extends AbstractInvocationHandler impleme
 
   private Map.Entry<URI, EdmOperation> getUnboundOperation(
           final Operation operation, final List<String> parameterNames) {
+
     final EdmEntityContainer container = client.getCachedEdm().getEntityContainer(targetFQN);
     final EdmOperation edmOperation;
 
@@ -153,7 +148,7 @@ final class OperationInvocationHandler extends AbstractInvocationHandler impleme
       edmOperation = container.getActionImport(operation.name()).getUnboundAction();
     }
 
-    final CommonURIBuilder<?> uriBuilder = getClient().newURIBuilder(this.serviceRoot).
+    final CommonURIBuilder<?> uriBuilder = getClient().newURIBuilder().
             appendOperationCallSegment(edmOperation.getName());
 
     return new AbstractMap.SimpleEntry<URI, EdmOperation>(uriBuilder.build(), edmOperation);


[7/9] Merge from masterù

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a09dd24/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/PersistenceManagerImpl.java
----------------------------------------------------------------------
diff --cc ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/PersistenceManagerImpl.java
index 9c39c95,0000000..e7ffc57
mode 100644,000000..100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/PersistenceManagerImpl.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/PersistenceManagerImpl.java
@@@ -1,551 -1,0 +1,568 @@@
 +/*
 + * 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.reflect.Proxy;
 +import java.net.URI;
 +import java.util.ArrayList;
 +import java.util.Collection;
 +import java.util.Collections;
 +import java.util.HashSet;
 +import java.util.Iterator;
 +import java.util.List;
 +import java.util.Map;
 +import java.util.Set;
 +import org.apache.commons.lang3.StringUtils;
 +import org.apache.olingo.client.api.communication.header.ODataPreferences;
 +import org.apache.olingo.client.api.communication.request.ODataRequest;
 +import org.apache.olingo.client.api.communication.request.ODataStreamedRequest;
- import org.apache.olingo.client.api.communication.request.batch.BatchStreamManager;
++import org.apache.olingo.client.api.communication.request.batch.BatchManager;
 +import org.apache.olingo.client.api.communication.request.batch.CommonODataBatchRequest;
 +import org.apache.olingo.client.api.communication.request.batch.ODataBatchResponseItem;
 +import org.apache.olingo.client.api.communication.request.batch.ODataChangeset;
 +import org.apache.olingo.client.api.communication.request.cud.ODataDeleteRequest;
 +import org.apache.olingo.client.api.communication.request.cud.ODataEntityUpdateRequest;
 +import org.apache.olingo.client.api.communication.request.streamed.ODataMediaEntityUpdateRequest;
 +import org.apache.olingo.client.api.communication.request.streamed.ODataStreamUpdateRequest;
 +import org.apache.olingo.client.api.communication.response.ODataBatchResponse;
 +import org.apache.olingo.client.api.communication.response.ODataEntityCreateResponse;
 +import org.apache.olingo.client.api.communication.response.ODataEntityUpdateResponse;
 +import org.apache.olingo.client.api.communication.response.ODataResponse;
 +import org.apache.olingo.client.core.communication.request.batch.ODataChangesetResponseItem;
 +import org.apache.olingo.client.core.uri.URIUtils;
 +import org.apache.olingo.commons.api.domain.CommonODataEntity;
 +import org.apache.olingo.commons.api.domain.ODataLink;
 +import org.apache.olingo.commons.api.domain.ODataLinkType;
++import org.apache.olingo.commons.api.domain.v4.ODataEntity;
 +import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
 +import org.apache.olingo.commons.api.format.ODataMediaFormat;
 +import org.apache.olingo.ext.proxy.EntityContainerFactory;
 +import org.apache.olingo.ext.proxy.api.PersistenceManager;
 +import org.apache.olingo.ext.proxy.api.annotations.NavigationProperty;
 +import org.apache.olingo.ext.proxy.context.AttachedEntity;
 +import org.apache.olingo.ext.proxy.context.AttachedEntityStatus;
 +import org.apache.olingo.ext.proxy.context.EntityLinkDesc;
 +import org.apache.olingo.ext.proxy.utils.CoreUtils;
 +import org.slf4j.Logger;
 +import org.slf4j.LoggerFactory;
 +
 +class PersistenceManagerImpl implements PersistenceManager {
 +
 +  private static final long serialVersionUID = -3320312269235907501L;
 +
 +  /**
 +   * Logger.
 +   */
 +  private static final Logger LOG = LoggerFactory.getLogger(PersistenceManagerImpl.class);
 +
 +  private final EntityContainerFactory<?> factory;
 +
 +  PersistenceManagerImpl(final EntityContainerFactory<?> factory) {
 +    this.factory = factory;
 +  }
 +
 +  /**
 +   * Transactional changes commit.
 +   */
 +  @Override
 +  public void flush() {
 +    final CommonODataBatchRequest request =
 +            factory.getClient().getBatchRequestFactory().getBatchRequest(factory.getClient().getServiceRoot());
 +    ((ODataRequest) request).setAccept(factory.getClient().getConfiguration().getDefaultBatchAcceptFormat());
 +
-     final BatchStreamManager streamManager = (BatchStreamManager) ((ODataStreamedRequest) request).execute();
++    final BatchManager streamManager = (BatchManager) ((ODataStreamedRequest) request).payloadManager();
 +
 +    final ODataChangeset changeset = streamManager.addChangeset();
 +
 +    final TransactionItems items = new TransactionItems();
 +    final List<EntityLinkDesc> delayedUpdates = new ArrayList<EntityLinkDesc>();
 +
 +    int pos = 0;
 +
 +    for (AttachedEntity attachedEntity : factory.getContext().entityContext()) {
 +      final AttachedEntityStatus status = attachedEntity.getStatus();
 +      if (((status != AttachedEntityStatus.ATTACHED
 +              && status != AttachedEntityStatus.LINKED) || attachedEntity.getEntity().isChanged())
 +              && !items.contains(attachedEntity.getEntity())) {
 +        pos++;
 +        pos = processEntityContext(attachedEntity.getEntity(), pos, items, delayedUpdates, changeset);
 +      }
 +    }
 +
 +    processDelayedUpdates(delayedUpdates, pos, items, changeset);
 +
 +    final ODataBatchResponse response = streamManager.getResponse();
 +
-     if ((factory.getClient().getServiceVersion().compareTo(ODataServiceVersion.V30) <= 0
-             && response.getStatusCode() != 202)
-             || (factory.getClient().getServiceVersion().compareTo(ODataServiceVersion.V30) > 0
-             && response.getStatusCode() != 200)) {
- 
++    // This should be 202 for service version <= 3.0 and 200 for service version >= 4.0 but it seems that
++    // many service implementations are not fully compliant with this respect.
++    if (response.getStatusCode() != 202 && response.getStatusCode() != 200) {
 +      throw new IllegalStateException("Operation failed");
 +    }
 +
 +    if (!items.isEmpty()) {
 +      final Iterator<ODataBatchResponseItem> iter = response.getBody();
 +      if (!iter.hasNext()) {
 +        throw new IllegalStateException("Unexpected operation result");
 +      }
 +
 +      final ODataBatchResponseItem item = iter.next();
 +      if (!(item instanceof ODataChangesetResponseItem)) {
 +        throw new IllegalStateException("Unexpected batch response item " + item.getClass().getSimpleName());
 +      }
 +
 +      final ODataChangesetResponseItem chgres = (ODataChangesetResponseItem) item;
 +
 +      for (Integer changesetItemId : items.sortedValues()) {
 +        LOG.debug("Expected changeset item {}", changesetItemId);
 +        final ODataResponse res = chgres.next();
 +        if (res.getStatusCode() >= 400) {
 +          throw new IllegalStateException("Transaction failed: " + res.getStatusMessage());
 +        }
 +
 +        final EntityInvocationHandler handler = items.get(changesetItemId);
 +
 +        if (handler != null) {
 +          if (res instanceof ODataEntityCreateResponse && res.getStatusCode() == 201) {
 +            handler.setEntity(((ODataEntityCreateResponse) res).getBody());
 +            LOG.debug("Upgrade created object '{}'", handler);
 +          } else if (res instanceof ODataEntityUpdateResponse && res.getStatusCode() == 200) {
 +            handler.setEntity(((ODataEntityUpdateResponse) res).getBody());
 +            LOG.debug("Upgrade updated object '{}'", handler);
 +          }
 +        }
 +      }
 +    }
 +
 +    factory.getContext().detachAll();
 +  }
 +
-   private void batch(
++  private AttachedEntityStatus batch(
 +          final EntityInvocationHandler handler,
 +          final CommonODataEntity entity,
 +          final ODataChangeset changeset) {
 +
 +    switch (factory.getContext().entityContext().getStatus(handler)) {
 +      case NEW:
 +        batchCreate(handler, entity, changeset);
-         break;
++        return AttachedEntityStatus.NEW;
 +
 +      case CHANGED:
 +        batchUpdate(handler, entity, changeset);
-         break;
++        return AttachedEntityStatus.CHANGED;
 +
 +      case DELETED:
 +        batchDelete(handler, entity, changeset);
-         break;
++        return AttachedEntityStatus.DELETED;
 +
 +      default:
 +        if (handler.isChanged()) {
 +          batchUpdate(handler, entity, changeset);
 +        }
++        return AttachedEntityStatus.CHANGED;
 +    }
 +  }
 +
 +  private void batchCreate(
 +          final EntityInvocationHandler handler,
 +          final CommonODataEntity entity,
 +          final ODataChangeset changeset) {
 +
 +    LOG.debug("Create '{}'", handler);
 +
-     changeset.addRequest(
-             factory.getClient().getCUDRequestFactory().getEntityCreateRequest(handler.getEntitySetURI(), entity));
++    changeset.addRequest(factory.getClient().getCUDRequestFactory().
++            getEntityCreateRequest(handler.getEntitySetURI(), entity));
 +  }
 +
 +  private void batchUpdateMediaEntity(
 +          final EntityInvocationHandler handler,
 +          final URI uri,
 +          final InputStream input,
 +          final ODataChangeset changeset) {
 +
 +    LOG.debug("Update media entity '{}'", uri);
 +
 +    final ODataMediaEntityUpdateRequest<?> req =
-             factory.getClient().getStreamedRequestFactory().getMediaEntityUpdateRequest(uri, input);
++            factory.getClient().getCUDRequestFactory().getMediaEntityUpdateRequest(uri, input);
 +
 +    req.setContentType(StringUtils.isBlank(handler.getEntity().getMediaContentType())
 +            ? ODataMediaFormat.WILDCARD.toString()
 +            : ODataMediaFormat.fromFormat(handler.getEntity().getMediaContentType()).toString());
 +
 +    if (StringUtils.isNotBlank(handler.getETag())) {
 +      req.setIfMatch(handler.getETag());
 +    }
 +
 +    changeset.addRequest(req);
 +  }
 +
 +  private void batchUpdateMediaResource(
 +          final EntityInvocationHandler handler,
 +          final URI uri,
 +          final InputStream input,
 +          final ODataChangeset changeset) {
 +
 +    LOG.debug("Update media entity '{}'", uri);
 +
-     final ODataStreamUpdateRequest req = factory.getClient().
-             getStreamedRequestFactory().getStreamUpdateRequest(uri, input);
++    final ODataStreamUpdateRequest req = factory.getClient().getCUDRequestFactory().getStreamUpdateRequest(uri, input);
 +
 +    if (StringUtils.isNotBlank(handler.getETag())) {
 +      req.setIfMatch(handler.getETag());
 +    }
 +
 +    changeset.addRequest(req);
 +  }
 +
 +  private void batchUpdate(
 +          final EntityInvocationHandler handler,
 +          final CommonODataEntity changes,
 +          final ODataChangeset changeset) {
 +
 +    LOG.debug("Update '{}'", handler.getEntityURI());
 +
 +    final ODataEntityUpdateRequest<CommonODataEntity> req =
 +            factory.getClient().getServiceVersion().compareTo(ODataServiceVersion.V30) <= 0
 +            ? ((org.apache.olingo.client.api.v3.EdmEnabledODataClient) factory.getClient()).getCUDRequestFactory().
 +            getEntityUpdateRequest(handler.getEntityURI(),
 +                    org.apache.olingo.client.api.communication.request.cud.v3.UpdateType.PATCH, changes)
 +            : ((org.apache.olingo.client.api.v4.EdmEnabledODataClient) factory.getClient()).getCUDRequestFactory().
 +            getEntityUpdateRequest(handler.getEntityURI(),
 +                    org.apache.olingo.client.api.communication.request.cud.v4.UpdateType.PATCH, changes);
 +
 +    req.setPrefer(new ODataPreferences(factory.getClient().getServiceVersion()).returnContent());
 +
 +    if (StringUtils.isNotBlank(handler.getETag())) {
 +      req.setIfMatch(handler.getETag());
 +    }
 +
 +    changeset.addRequest(req);
 +  }
 +
 +  private void batchUpdate(
 +          final EntityInvocationHandler handler,
 +          final URI uri,
 +          final CommonODataEntity changes,
 +          final ODataChangeset changeset) {
 +
 +    LOG.debug("Update '{}'", uri);
 +
 +    final ODataEntityUpdateRequest<CommonODataEntity> req =
 +            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)
 +            : ((org.apache.olingo.client.api.v4.EdmEnabledODataClient) factory.getClient()).getCUDRequestFactory().
 +            getEntityUpdateRequest(uri,
 +                    org.apache.olingo.client.api.communication.request.cud.v4.UpdateType.PATCH, changes);
 +
 +    req.setPrefer(new ODataPreferences(factory.getClient().getServiceVersion()).returnContent());
 +
 +    if (StringUtils.isNotBlank(handler.getETag())) {
 +      req.setIfMatch(handler.getETag());
 +    }
 +
 +    changeset.addRequest(req);
 +  }
 +
 +  private void batchDelete(
 +          final EntityInvocationHandler handler,
 +          final CommonODataEntity entity,
 +          final ODataChangeset changeset) {
 +
 +    final URI deleteURI = handler.getEntityURI() == null ? entity.getEditLink() : handler.getEntityURI();
 +    LOG.debug("Delete '{}'", deleteURI);
 +
 +    final ODataDeleteRequest req = factory.getClient().getCUDRequestFactory().getDeleteRequest(deleteURI);
 +
 +    if (StringUtils.isNotBlank(handler.getETag())) {
 +      req.setIfMatch(handler.getETag());
 +    }
 +
 +    changeset.addRequest(req);
 +  }
 +
 +  private int processEntityContext(
 +          final EntityInvocationHandler handler,
 +          int pos,
 +          final TransactionItems items,
 +          final List<EntityLinkDesc> delayedUpdates,
 +          final ODataChangeset changeset) {
 +
 +    LOG.debug("Process '{}'", handler);
 +
 +    items.put(handler, null);
 +
 +    final CommonODataEntity entity = handler.getEntity();
 +    entity.getNavigationLinks().clear();
 +
 +    final AttachedEntityStatus currentStatus = factory.getContext().entityContext().getStatus(handler);
 +
 +    if (AttachedEntityStatus.DELETED != currentStatus) {
 +      entity.getProperties().clear();
 +      CoreUtils.addProperties(factory.getClient(), handler.getPropertyChanges(), entity);
++
++      if (entity instanceof ODataEntity) {
++        ((ODataEntity) entity).getAnnotations().clear();
++        CoreUtils.addAnnotations(factory.getClient(), handler.getAnnotations(), (ODataEntity) entity);
++
++        for (Map.Entry<String, AnnotatableInvocationHandler> entry : handler.getPropAnnotatableHandlers().entrySet()) {
++          CoreUtils.addAnnotations(factory.getClient(),
++                  entry.getValue().getAnnotations(), ((ODataEntity) entity).getProperty(entry.getKey()));
++        }
++      }
 +    }
 +
 +    for (Map.Entry<NavigationProperty, Object> property : handler.getLinkChanges().entrySet()) {
 +      final ODataLinkType type = Collection.class.isAssignableFrom(property.getValue().getClass())
 +              ? ODataLinkType.ENTITY_SET_NAVIGATION
 +              : ODataLinkType.ENTITY_NAVIGATION;
 +
 +      final Set<EntityInvocationHandler> toBeLinked = new HashSet<EntityInvocationHandler>();
-       final String serviceRoot = factory.getClient().getServiceRoot();
- 
 +      for (Object proxy : type == ODataLinkType.ENTITY_SET_NAVIGATION
 +              ? (Collection) property.getValue() : Collections.singleton(property.getValue())) {
 +
 +        final EntityInvocationHandler target = (EntityInvocationHandler) Proxy.getInvocationHandler(proxy);
 +
 +        final AttachedEntityStatus status = factory.getContext().entityContext().getStatus(target);
 +
 +        final URI editLink = target.getEntity().getEditLink();
 +
 +        if ((status == AttachedEntityStatus.ATTACHED || status == AttachedEntityStatus.LINKED) && !target.isChanged()) {
 +          entity.addLink(buildNavigationLink(
 +                  property.getKey().name(),
-                   URIUtils.getURI(serviceRoot, editLink.toASCIIString()), type));
++                  URIUtils.getURI(factory.getClient().getServiceRoot(), editLink.toASCIIString()), type));
 +        } else {
 +          if (!items.contains(target)) {
 +            pos = processEntityContext(target, pos, items, delayedUpdates, changeset);
 +            pos++;
 +          }
 +
 +          final Integer targetPos = items.get(target);
 +          if (targetPos == null) {
 +            // schedule update for the current object
 +            LOG.debug("Schedule '{}' from '{}' to '{}'", type.name(), handler, target);
 +            toBeLinked.add(target);
 +          } else if (status == AttachedEntityStatus.CHANGED) {
 +            entity.addLink(buildNavigationLink(
 +                    property.getKey().name(),
-                     URIUtils.getURI(serviceRoot, editLink.toASCIIString()), type));
++                    URIUtils.getURI(factory.getClient().getServiceRoot(), editLink.toASCIIString()), type));
 +          } else {
 +            // create the link for the current object
 +            LOG.debug("'{}' from '{}' to (${}) '{}'", type.name(), handler, targetPos, target);
 +
 +            entity.addLink(buildNavigationLink(property.getKey().name(), URI.create("$" + targetPos), type));
 +          }
 +        }
 +      }
 +
 +      if (!toBeLinked.isEmpty()) {
 +        delayedUpdates.add(new EntityLinkDesc(property.getKey().name(), handler, toBeLinked, type));
 +      }
 +    }
 +
++    if (entity instanceof ODataEntity) {
++      for (Map.Entry<String, AnnotatableInvocationHandler> entry
++              : handler.getNavPropAnnotatableHandlers().entrySet()) {
++
++        CoreUtils.addAnnotations(factory.getClient(),
++                entry.getValue().getAnnotations(),
++                (org.apache.olingo.commons.api.domain.v4.ODataLink) entity.getNavigationLink(entry.getKey()));
++      }
++    }
++
 +    // insert into the batch
 +    LOG.debug("{}: Insert '{}' into the batch", pos, handler);
-     batch(handler, entity, changeset);
++    final AttachedEntityStatus processedStatus = batch(handler, entity, changeset);
 +
 +    items.put(handler, pos);
 +
-     int startingPos = pos;
++    if (processedStatus != AttachedEntityStatus.DELETED) {
++      int startingPos = pos;
++
++      if (handler.getEntity().isMediaEntity() && handler.isChanged()) {
++        // update media properties
++        if (!handler.getPropertyChanges().isEmpty()) {
++          final URI targetURI = currentStatus == AttachedEntityStatus.NEW
++                  ? URI.create("$" + startingPos)
++                  : URIUtils.getURI(
++                          factory.getClient().getServiceRoot(), handler.getEntity().getEditLink().toASCIIString());
++          batchUpdate(handler, targetURI, entity, changeset);
++          pos++;
++          items.put(handler, pos);
++        }
++
++        // update media content
++        if (handler.getStreamChanges() != null) {
++          final URI targetURI = currentStatus == AttachedEntityStatus.NEW
++                  ? URI.create("$" + startingPos + "/$value")
++                  : URIUtils.getURI(
++                          factory.getClient().getServiceRoot(),
++                          handler.getEntity().getEditLink().toASCIIString() + "/$value");
 +
-     if (handler.getEntity().isMediaEntity()) {
++          batchUpdateMediaEntity(handler, targetURI, handler.getStreamChanges(), changeset);
 +
-       // update media properties
-       if (!handler.getPropertyChanges().isEmpty()) {
-         final URI targetURI = currentStatus == AttachedEntityStatus.NEW
-                 ? URI.create("$" + startingPos)
-                 : URIUtils.getURI(
-                         factory.getClient().getServiceRoot(),
-                         handler.getEntity().getEditLink().toASCIIString());
-         batchUpdate(handler, targetURI, entity, changeset);
-         pos++;
-         items.put(handler, pos);
++          // update media info (use null key)
++          pos++;
++          items.put(null, pos);
++        }
 +      }
 +
-       // update media content
-       if (handler.getStreamChanges() != null) {
++      for (Map.Entry<String, InputStream> streamedChanges : handler.getStreamedPropertyChanges().entrySet()) {
 +        final URI targetURI = currentStatus == AttachedEntityStatus.NEW
-                 ? URI.create("$" + startingPos + "/$value")
-                 : URIUtils.getURI(
++                ? URI.create("$" + startingPos) : URIUtils.getURI(
 +                        factory.getClient().getServiceRoot(),
-                         handler.getEntity().getEditLink().toASCIIString() + "/$value");
++                        CoreUtils.getMediaEditLink(streamedChanges.getKey(), entity).toASCIIString());
 +
-         batchUpdateMediaEntity(handler, targetURI, handler.getStreamChanges(), changeset);
++        batchUpdateMediaResource(handler, targetURI, streamedChanges.getValue(), changeset);
 +
 +        // update media info (use null key)
 +        pos++;
-         items.put(null, pos);
++        items.put(handler, pos);
 +      }
 +    }
 +
-     for (Map.Entry<String, InputStream> streamedChanges : handler.getStreamedPropertyChanges().entrySet()) {
-       final URI targetURI = currentStatus == AttachedEntityStatus.NEW
-               ? URI.create("$" + startingPos) : URIUtils.getURI(
-                       factory.getClient().getServiceRoot(),
-                       CoreUtils.getMediaEditLink(streamedChanges.getKey(), entity).toASCIIString());
- 
-       batchUpdateMediaResource(handler, targetURI, streamedChanges.getValue(), changeset);
- 
-       // update media info (use null key)
-       pos++;
-       items.put(handler, pos);
-     }
- 
 +    return pos;
 +  }
 +
 +  private ODataLink buildNavigationLink(final String name, final URI uri, final ODataLinkType type) {
 +    ODataLink result;
 +
 +    switch (type) {
 +      case ENTITY_NAVIGATION:
 +        result = factory.getClient().getObjectFactory().newEntityNavigationLink(name, uri);
 +        break;
 +
 +      case ENTITY_SET_NAVIGATION:
 +        result = factory.getClient().getObjectFactory().newEntitySetNavigationLink(name, uri);
 +        break;
 +
 +      default:
 +        throw new IllegalArgumentException("Invalid link type " + type.name());
 +    }
 +
 +    return result;
 +  }
 +
 +  private void processDelayedUpdates(
 +          final List<EntityLinkDesc> delayedUpdates,
 +          int pos,
 +          final TransactionItems items,
 +          final ODataChangeset changeset) {
 +
 +    for (EntityLinkDesc delayedUpdate : delayedUpdates) {
 +      pos++;
 +      items.put(delayedUpdate.getSource(), pos);
 +
 +      final CommonODataEntity changes =
 +              factory.getClient().getObjectFactory().newEntity(delayedUpdate.getSource().getEntity().getTypeName());
 +
 +      AttachedEntityStatus status = factory.getContext().entityContext().getStatus(delayedUpdate.getSource());
 +
 +      final URI sourceURI;
 +      if (status == AttachedEntityStatus.CHANGED) {
 +        sourceURI = URIUtils.getURI(
 +                factory.getClient().getServiceRoot(),
 +                delayedUpdate.getSource().getEntity().getEditLink().toASCIIString());
 +      } else {
 +        int sourcePos = items.get(delayedUpdate.getSource());
 +        sourceURI = URI.create("$" + sourcePos);
 +      }
 +
 +      for (EntityInvocationHandler target : delayedUpdate.getTargets()) {
 +        status = factory.getContext().entityContext().getStatus(target);
 +
 +        final URI targetURI;
 +        if (status == AttachedEntityStatus.CHANGED) {
 +          targetURI = URIUtils.getURI(
 +                  factory.getClient().getServiceRoot(), target.getEntity().getEditLink().toASCIIString());
 +        } else {
 +          int targetPos = items.get(target);
 +          targetURI = URI.create("$" + targetPos);
 +        }
 +
 +        changes.addLink(delayedUpdate.getType() == ODataLinkType.ENTITY_NAVIGATION
 +                ? factory.getClient().getObjectFactory().
 +                newEntityNavigationLink(delayedUpdate.getSourceName(), targetURI)
 +                : factory.getClient().getObjectFactory().
 +                newEntitySetNavigationLink(delayedUpdate.getSourceName(), targetURI));
 +
 +        LOG.debug("'{}' from {} to {}", delayedUpdate.getType().name(), sourceURI, targetURI);
 +      }
 +
 +      batchUpdate(delayedUpdate.getSource(), sourceURI, changes, changeset);
 +    }
 +  }
 +
 +  private class TransactionItems {
 +
 +    private final List<EntityInvocationHandler> keys = new ArrayList<EntityInvocationHandler>();
 +
 +    private final List<Integer> values = new ArrayList<Integer>();
 +
 +    public EntityInvocationHandler get(final Integer value) {
 +      if (value != null && values.contains(value)) {
 +        return keys.get(values.indexOf(value));
 +      } else {
 +        return null;
 +      }
 +    }
 +
 +    public Integer get(final EntityInvocationHandler key) {
 +      if (key != null && keys.contains(key)) {
 +        return values.get(keys.indexOf(key));
 +      } else {
 +        return null;
 +      }
 +    }
 +
 +    public void remove(final EntityInvocationHandler key) {
 +      if (keys.contains(key)) {
 +        values.remove(keys.indexOf(key));
 +        keys.remove(key);
 +      }
 +    }
 +
 +    public void put(final EntityInvocationHandler key, final Integer value) {
 +      // replace just in case of null current value; otherwise add the new entry
 +      if (key != null && keys.contains(key) && values.get(keys.indexOf(key)) == null) {
 +        remove(key);
 +      }
 +      keys.add(key);
 +      values.add(value);
 +    }
 +
 +    public List<Integer> sortedValues() {
 +      final List<Integer> sortedValues = new ArrayList<Integer>(values);
 +      Collections.<Integer>sort(sortedValues);
 +      return sortedValues;
 +    }
 +
 +    public boolean contains(final EntityInvocationHandler key) {
 +      return keys.contains(key);
 +    }
 +
 +    public int size() {
 +      return keys.size();
 +    }
 +
 +    public boolean isEmpty() {
 +      return keys.isEmpty();
 +    }
 +  }
 +}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a09dd24/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/context/EntityContext.java
----------------------------------------------------------------------
diff --cc ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/context/EntityContext.java
index 2b42cd1,560b185..ae6937d
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/context/EntityContext.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/context/EntityContext.java
@@@ -101,9 -101,9 +101,7 @@@ public class EntityContext implements I
     * @param entity entity to be detached.
     */
    public void detach(final EntityInvocationHandler entity) {
--    if (searchableEntities.containsKey(entity.getUUID())) {
--      searchableEntities.remove(entity.getUUID());
--    }
++    searchableEntities.remove(entity.getUUID());
      allAttachedEntities.remove(entity);
    }
  

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a09dd24/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/context/EntityUUID.java
----------------------------------------------------------------------
diff --cc ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/context/EntityUUID.java
index edfc227,edfc227..168696a
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/context/EntityUUID.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/context/EntityUUID.java
@@@ -92,7 -92,7 +92,9 @@@ public class EntityUUID implements Seri
  
    @Override
    public int hashCode() {
--    return HashCodeBuilder.reflectionHashCode(this, "tempKey");
++    return key == null
++            ? HashCodeBuilder.reflectionHashCode(this)
++            : HashCodeBuilder.reflectionHashCode(this, "tempKey");
    }
  
    @Override

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a09dd24/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 822e8ea,b32e80e..5e44e74
--- 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
@@@ -43,9 -43,11 +43,10 @@@ import org.apache.olingo.commons.api.do
  import org.apache.olingo.commons.api.domain.ODataLink;
  import org.apache.olingo.commons.api.domain.ODataPrimitiveValue;
  import org.apache.olingo.commons.api.domain.ODataValue;
+ import org.apache.olingo.commons.api.domain.v4.ODataAnnotatable;
+ import org.apache.olingo.commons.api.domain.v4.ODataAnnotation;
 -import org.apache.olingo.commons.api.domain.v4.ODataEntity;
  import org.apache.olingo.commons.api.domain.v4.ODataEnumValue;
  import org.apache.olingo.commons.api.domain.v4.ODataObjectFactory;
- import org.apache.olingo.commons.api.domain.v4.ODataProperty;
  import org.apache.olingo.commons.api.edm.EdmElement;
  import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
  import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
@@@ -106,12 -112,12 +111,7 @@@ public final class CoreUtils 
          }
        }
      } else if (type.isComplexType()) {
--      Object objHandler;
--      if (obj instanceof Proxy) {
--        objHandler = Proxy.getInvocationHandler(obj);
--      } else {
--        objHandler = obj;
--      }
++      final Object objHandler = Proxy.getInvocationHandler(obj);
        if (objHandler instanceof ComplexInvocationHandler) {
          value = ((ComplexInvocationHandler) objHandler).getComplex();
  
@@@ -121,7 -127,7 +121,7 @@@
            if (propAnn != null) {
              try {
                value.asComplex().add(getODataComplexProperty(
--                      client, type.getFullQualifiedName(), propAnn.name(), method.invoke(objHandler)));
++                      client, type.getFullQualifiedName(), propAnn.name(), method.invoke(obj)));
              } catch (Exception ignore) {
                // ignore value
                LOG.warn("Error attaching complex {} for field '{}.{}'",

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a09dd24/fit/pom.xml
----------------------------------------------------------------------
diff --cc fit/pom.xml
index 41f990a,41f990a..93f4a45
--- a/fit/pom.xml
+++ b/fit/pom.xml
@@@ -182,6 -182,6 +182,7 @@@
                <cargo.tomcat.ajp.port>${cargo.tomcat.ajp.port}</cargo.tomcat.ajp.port>
                <cargo.rmi.port>${cargo.rmi.port}</cargo.rmi.port>
  
++              <!--<cargo.jvmargs>-Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n-->
                <cargo.jvmargs>-noverify -XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC -XX:MaxPermSize=256m</cargo.jvmargs>
              </properties>
              <files>

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a09dd24/fit/src/main/java/org/apache/olingo/fit/V3Services.java
----------------------------------------------------------------------
diff --cc fit/src/main/java/org/apache/olingo/fit/V3Services.java
index 410fcad,0a0eb09..a036fd2
--- a/fit/src/main/java/org/apache/olingo/fit/V3Services.java
+++ b/fit/src/main/java/org/apache/olingo/fit/V3Services.java
@@@ -156,7 -156,7 +156,7 @@@ public class V3Services extends Abstrac
                addChangesetItemIntro(chbos, lastContebtID, cboundary);
  
                res = bodyPartRequest(new MimeBodyPart(part.getInputStream()), references);
-               if (res.getStatus() >= 400) {
 -              if (res==null || res.getStatus() >= 400) {
++              if (res == null || res.getStatus() >= 400) {
                  throw new Exception("Failure processing changeset");
                }
  
@@@ -222,10 -222,10 +222,10 @@@
            @QueryParam("$filter") @DefaultValue(StringUtils.EMPTY) String filter,
            @QueryParam("$orderby") @DefaultValue(StringUtils.EMPTY) String orderby,
            @QueryParam("$skiptoken") @DefaultValue(StringUtils.EMPTY) String skiptoken) {
--    
++
      return super.getEntitySet(uriInfo, accept, "Car", top, skip, format, count, filter, orderby, skiptoken);
--  }  
--  
++  }
++
    @GET
    @Path("/Login({entityId})")
    public Response getLogin(
@@@ -258,6 -258,6 +258,14 @@@
      return super.postNewEntity(uriInfo, accept, contentType, prefer, "Login", entity);
    }
  
++  @DELETE
++  @Path("/Login({entityId})")
++  public Response removeLogin(
++          @PathParam("entityId") String entityId) {
++
++    return super.removeEntity("Login", StringUtils.remove(entityId, "'"));
++  }
++
    /**
     * Retrieve links sample.
     *

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a09dd24/fit/src/main/java/org/apache/olingo/fit/utils/FSManager.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a09dd24/fit/src/test/java/org/apache/olingo/fit/proxy/v3/AbstractTestITCase.java
----------------------------------------------------------------------
diff --cc fit/src/test/java/org/apache/olingo/fit/proxy/v3/AbstractTestITCase.java
index 17bb65b,0bf0eb5..f2de82a
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/v3/AbstractTestITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/v3/AbstractTestITCase.java
@@@ -62,8 -63,8 +62,6 @@@ public abstract class AbstractTestITCas
  
    protected static String testLargeModelServiceRootURL;
  
-   protected static String testAuthServiceRootURL;
- 
 -  protected final EntityContext entityContext = EntityContainerFactory.getContext().entityContext();
 -
    protected static EntityContainerFactory<EdmEnabledODataClient> containerFactory;
  
    protected static DefaultContainer container;

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a09dd24/fit/src/test/java/org/apache/olingo/fit/proxy/v3/EntityCreateTestITCase.java
----------------------------------------------------------------------
diff --cc fit/src/test/java/org/apache/olingo/fit/proxy/v3/EntityCreateTestITCase.java
index ccfbd2a,2ae58e8..75e583d
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/v3/EntityCreateTestITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/v3/EntityCreateTestITCase.java
@@@ -116,7 -116,7 +116,7 @@@ public class EntityCreateTestITCase ext
  
      Customer actual = readCustomer(container, id);
      checkSampleCustomerProfile(actual, id, sampleName);
--    assertEquals(Integer.valueOf(16), actual.getInfo().getCustomerInfoId());
++    assertEquals(16, actual.getInfo().getCustomerInfoId(), 0);
  
      container.getCustomer().delete(actual.getCustomerId());
      container.flush();

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a09dd24/fit/src/test/java/org/apache/olingo/fit/proxy/v3/MediaEntityTestITCase.java
----------------------------------------------------------------------
diff --cc fit/src/test/java/org/apache/olingo/fit/proxy/v3/MediaEntityTestITCase.java
index 0000000,366b5c3..c20b056
mode 000000,100644..100644
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/v3/MediaEntityTestITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/v3/MediaEntityTestITCase.java
@@@ -1,0 -1,108 +1,107 @@@
+ /*
+  * 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.fit.proxy.v3;
+ 
+ import static org.junit.Assert.assertNull;
+ import static org.junit.Assert.assertNotNull;
+ import static org.junit.Assert.assertEquals;
+ import static org.junit.Assert.assertTrue;
+ 
+ import java.io.ByteArrayInputStream;
+ import java.io.IOException;
+ import java.io.InputStream;
+ import org.apache.commons.io.IOUtils;
 -import org.apache.olingo.ext.proxy.EntityContainerFactory;
+ import org.apache.olingo.fit.proxy.v3.staticservice.microsoft.test.odata.services.astoriadefaultservice.types.Car;
+ import org.junit.Test;
+ 
+ /**
+  * This is the unit test class to check media entity retrieve operations.
+  */
+ public class MediaEntityTestITCase extends AbstractTestITCase {
+ 
+   @Test
+   public void read() throws IOException {
+     final InputStream is = container.getCar().get(12).getStream();
+     assertNotNull(is);
+     IOUtils.closeQuietly(is);
+   }
+ 
+   @Test
+   public void updateReadStreamedProperty() throws IOException {
+     final String TO_BE_UPDATED = "buffered stream sample (" + System.currentTimeMillis() + ")";
+     final InputStream input = new ByteArrayInputStream(TO_BE_UPDATED.getBytes());
+ 
+     Car car = container.getCar().get(12);
+     car.setPhoto(input);
+ 
+     container.flush();
+ 
+     car = container.getCar().get(12);
+     final InputStream is = car.getPhoto();
+     assertEquals(TO_BE_UPDATED, IOUtils.toString(is));
+     IOUtils.closeQuietly(is);
+   }
+ 
+   @Test
+   public void update() throws IOException {
+     final Car car = container.getCar().get(14);
+     assertNotNull(car);
+ 
+     final String TO_BE_UPDATED = "buffered stream sample (" + System.currentTimeMillis() + ")";
+     InputStream input = IOUtils.toInputStream(TO_BE_UPDATED);
+ 
+     car.setStream(input);
+ 
+     container.flush();
+ 
+     input = container.getCar().get(14).getStream();
+     assertEquals(TO_BE_UPDATED, IOUtils.toString(input));
+     IOUtils.closeQuietly(input);
+   }
+ 
+   @Test
+   public void create() throws IOException {
+     Car car = container.getCar().newCar();
+ 
+     final String TO_BE_UPDATED = "buffered stream sample (" + System.currentTimeMillis() + ")";
+     InputStream input = IOUtils.toInputStream(TO_BE_UPDATED);
+ 
+     final String DESC = "DESC - " + System.currentTimeMillis();
+     car.setStream(input);
+     car.setDescription(DESC);
+ 
+     container.flush();
+ 
+     int key = car.getVIN();
+     assertTrue(key > 0);
+ 
 -    EntityContainerFactory.getContext().detachAll();
++    containerFactory.getContext().detachAll();
+ 
+     car = container.getCar().get(key);
+     assertEquals(DESC, car.getDescription());
+     input = car.getStream();
+     assertEquals(TO_BE_UPDATED, IOUtils.toString(input));
+     IOUtils.closeQuietly(input);
+ 
+     container.getCar().delete(key);
+     container.flush();
+ 
+     assertNull(container.getCar().get(key));
+   }
+ }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a09dd24/fit/src/test/java/org/apache/olingo/fit/proxy/v3/OpenTypeTestITCase.java
----------------------------------------------------------------------
diff --cc fit/src/test/java/org/apache/olingo/fit/proxy/v3/OpenTypeTestITCase.java
index 1a0a08c,28b768f..3ee02ba
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/v3/OpenTypeTestITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/v3/OpenTypeTestITCase.java
@@@ -44,12 -44,12 +44,13 @@@ import org.junit.Test
   */
  public class OpenTypeTestITCase extends AbstractTestITCase {
  
++  private static EntityContainerFactory<EdmEnabledODataClient> otcontainerFactory;
++
    private static DefaultContainer otcontainer;
  
    @BeforeClass
    public static void initContainer() {
--    final EntityContainerFactory<EdmEnabledODataClient> otcontainerFactory = 
--            EntityContainerFactory.getV3(testOpenTypeServiceRootURL);
++    otcontainerFactory = EntityContainerFactory.getV3(testOpenTypeServiceRootURL);
      otcontainerFactory.getClient().getConfiguration().
              setDefaultBatchAcceptFormat(ContentType.APPLICATION_OCTET_STREAM);
      otcontainer = otcontainerFactory.getEntityContainer(DefaultContainer.class);
@@@ -64,7 -64,7 +65,7 @@@
              getAnnotation(EntityType.class).openType());
      assertTrue(otcontainer.getRow().newIndexedRow().getClass().getInterfaces()[0].
              getAnnotation(EntityType.class).openType());
-     containerFactory.getContext().detachAll();
 -    entityContext.detachAll();
++    otcontainerFactory.getContext().detachAll();
    }
  
    @Test
@@@ -124,7 -124,7 +125,7 @@@
      assertTrue(Calendar.class.isAssignableFrom(rowIndex.getAdditionalProperty("aDate").getClass()));
      assertEquals(ContactDetails.class, rowIndex.getAdditionalProperty("aContact").getClass().getInterfaces()[0]);
  
-     containerFactory.getContext().detachAll();
 -    entityContext.detachAll();
++    otcontainerFactory.getContext().detachAll();
  
      otcontainer.getRowIndex().delete(id);
      otcontainer.flush();

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a09dd24/fit/src/test/java/org/apache/olingo/fit/proxy/v4/AbstractTestITCase.java
----------------------------------------------------------------------
diff --cc fit/src/test/java/org/apache/olingo/fit/proxy/v4/AbstractTestITCase.java
index 40cd2bb,4efc7d0..c46d59d
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/v4/AbstractTestITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/v4/AbstractTestITCase.java
@@@ -105,7 -111,7 +108,7 @@@ public abstract class AbstractTestITCas
      assertEquals(orderDate.getTimeInMillis(), actual.getOrderDate().getTimeInMillis());
      assertEquals(BigDecimal.TEN, actual.getShelfLife());
      assertEquals(2, actual.getOrderShelfLifes().size());
--
++    
      container.getOrders().delete(105);
      actual = container.getOrders().get(105);
      assertNull(actual);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a09dd24/fit/src/test/java/org/apache/olingo/fit/proxy/v4/AuthEntityCreateTestITCase.java
----------------------------------------------------------------------
diff --cc fit/src/test/java/org/apache/olingo/fit/proxy/v4/AuthEntityCreateTestITCase.java
index 0000000,d837075..678e714
mode 000000,100644..100644
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/v4/AuthEntityCreateTestITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/v4/AuthEntityCreateTestITCase.java
@@@ -1,0 -1,50 +1,52 @@@
+ /*
+  * 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.fit.proxy.v4;
+ 
 -import static org.junit.Assert.assertNotNull;
 -
 -import org.junit.AfterClass;
 -import org.junit.BeforeClass;
 -
+ import org.apache.olingo.client.core.http.BasicAuthHttpClientFactory;
+ import org.apache.olingo.commons.api.format.ContentType;
+ import org.apache.olingo.ext.proxy.EntityContainerFactory;
 -import static org.apache.olingo.fit.proxy.v4.AbstractTestITCase.containerFactory;
++
++import org.apache.olingo.client.api.v4.EdmEnabledODataClient;
+ import org.apache.olingo.fit.proxy.v4.staticservice.microsoft.test.odata.services.odatawcfservice.InMemoryEntities;
+ 
+ public class AuthEntityCreateTestITCase extends EntityCreateTestITCase {
+ 
 -  @BeforeClass
 -  public static void setupContaner() {
 -    containerFactory = EntityContainerFactory.getV4(testAuthServiceRootURL);
 -    containerFactory.getClient().getConfiguration().setDefaultBatchAcceptFormat(ContentType.APPLICATION_OCTET_STREAM);
 -    containerFactory.getClient().getConfiguration().
 -            setHttpClientFactory(new BasicAuthHttpClientFactory("odatajclient", "odatajclient"));
 -    container = containerFactory.getEntityContainer(InMemoryEntities.class);
 -    assertNotNull(container);
++  private EntityContainerFactory<EdmEnabledODataClient> ecf;
++
++  private InMemoryEntities ime;
++
++  @Override
++  public EntityContainerFactory<EdmEnabledODataClient> getContainerFactory() {
++    if (ecf == null) {
++      ecf = EntityContainerFactory.getV4(testAuthServiceRootURL);
++      ecf.getClient().getConfiguration().setDefaultBatchAcceptFormat(ContentType.APPLICATION_OCTET_STREAM);
++      ecf.getClient().getConfiguration().
++              setHttpClientFactory(new BasicAuthHttpClientFactory("odatajclient", "odatajclient"));
++    }
++    return ecf;
+   }
+ 
 -  @AfterClass
 -  public static void disableBasicAuth() {
 -    containerFactory = EntityContainerFactory.getV4(testStaticServiceRootURL);
 -    container = containerFactory.getEntityContainer(InMemoryEntities.class);
 -    assertNotNull(container);
++  @Override
++  protected InMemoryEntities getContainer() {
++    if (ime == null) {
++      ime = getContainerFactory().getEntityContainer(InMemoryEntities.class);
++    }
++    return ime;
+   }
+ }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a09dd24/fit/src/test/java/org/apache/olingo/fit/proxy/v4/EntityCreateTestITCase.java
----------------------------------------------------------------------
diff --cc fit/src/test/java/org/apache/olingo/fit/proxy/v4/EntityCreateTestITCase.java
index 5eaae9a,88c4743..faea864
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/v4/EntityCreateTestITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/v4/EntityCreateTestITCase.java
@@@ -29,6 -29,8 +29,9 @@@ import java.util.Calendar
  import java.util.Collections;
  import java.util.TimeZone;
  import org.apache.commons.lang3.RandomUtils;
 -import static org.apache.olingo.fit.proxy.v4.AbstractTestITCase.container;
 -
++import org.apache.olingo.client.api.v4.EdmEnabledODataClient;
++import org.apache.olingo.ext.proxy.EntityContainerFactory;
++import org.apache.olingo.fit.proxy.v4.staticservice.microsoft.test.odata.services.odatawcfservice.InMemoryEntities;
  import org.apache.olingo.fit.proxy.v4.staticservice.microsoft.test.odata.services.odatawcfservice.types.AccessLevel;
  import org.apache.olingo.fit.proxy.v4.staticservice.microsoft.test.odata.services.odatawcfservice.types.Address;
  import org.apache.olingo.fit.proxy.v4.staticservice.microsoft.test.odata.services.odatawcfservice.types.Color;
@@@ -53,16 -55,16 +56,24 @@@ import org.junit.Test
   */
  public class EntityCreateTestITCase extends AbstractTestITCase {
  
++  public EntityContainerFactory<EdmEnabledODataClient> getContainerFactory() {
++    return containerFactory;
++  }
++
++  protected InMemoryEntities getContainer() {
++    return container;
++  }
++
    @Test
    public void createAndDelete() {
--    createAndDeleteOrder(container);
++    createAndDeleteOrder(getContainer());
    }
  
    @Test
    public void createEmployee() {
      final Integer id = 101;
  
--    final Employee employee = container.getPeople().newEmployee();
++    final Employee employee = getContainer().getPeople().newEmployee();
      employee.setPersonID(id);
      employee.setFirstName("Fabio");
      employee.setLastName("Martelli");
@@@ -78,27 -80,27 +89,27 @@@
      employee.setHomeAddress(homeAddress);
      employee.setNumbers(Arrays.asList(new String[] {"3204725072", "08569930"}));
  
--    container.flush();
++    getContainer().flush();
  
--    Employee actual = container.getPeople().get(id, Employee.class);
++    Employee actual = getContainer().getPeople().get(id, Employee.class);
      assertNotNull(actual);
      assertEquals(id, actual.getPersonID());
      assertEquals(homeAddress.getCity(), actual.getHomeAddress().getCity());
  
-     containerFactory.getContext().detachAll();
-     actual = container.getPeople().get(id, Employee.class);
 -    entityContext.detachAll();
 -    actual = container.getPeople().get(id, Employee.class);
++    getContainerFactory().getContext().detachAll();
++    actual = getContainer().getPeople().get(id, Employee.class);
      assertNotNull(actual);
      assertEquals(id, actual.getPersonID());
      assertEquals(homeAddress.getCity(), actual.getHomeAddress().getCity());
  
--    container.getPeople().delete(actual.getPersonID());
--    container.flush();
++    getContainer().getPeople().delete(actual.getPersonID());
++    getContainer().flush();
  
-     actual = container.getPeople().get(id, Employee.class);;
 -    actual = container.getPeople().get(id, Employee.class);
++    actual = getContainer().getPeople().get(id, Employee.class);
      assertNull(actual);
  
-     containerFactory.getContext().detachAll();
-     actual = container.getPeople().get(id, Employee.class);
 -    entityContext.detachAll();
 -    actual = container.getPeople().get(id, Employee.class);
++    getContainerFactory().getContext().detachAll();
++    actual = getContainer().getPeople().get(id, Employee.class);
      assertNull(actual);
    }
  
@@@ -106,7 -108,7 +117,7 @@@
    public void createWithNavigation() {
      final Integer id = 101;
  
--    final Customer customer = container.getCustomers().newCustomer();
++    final Customer customer = getContainer().getCustomers().newCustomer();
      customer.setPersonID(id);
      customer.setPersonID(id);
      customer.setFirstName("Fabio");
@@@ -120,21 -122,21 +131,21 @@@
      customer.setHomeAddress(homeAddress);
      customer.setNumbers(Arrays.asList(new String[] {"3204725072", "08569930"}));
  
--    final OrderCollection orders = container.getOrders().newOrderCollection();
--    orders.add(container.getOrders().get(8));
++    final OrderCollection orders = getContainer().getOrders().newOrderCollection();
++    orders.add(getContainer().getOrders().get(8));
      customer.setOrders(orders);
  
--    container.flush();
++    getContainer().flush();
  
      Customer actual = readCustomer(container, id);
      assertEquals(homeAddress.getCity(), actual.getHomeAddress().getCity());
      assertEquals(1, actual.getOrders().size());
      assertEquals(8, actual.getOrders().iterator().next().getOrderID(), 0);
 -    
 -    container.getCustomers().delete(actual.getPersonID());
 -    container.flush();
  
-     container.getCustomers().delete(actual.getPersonID());
-     container.flush();
 -    actual = container.getCustomers().get(id);
++    getContainer().getCustomers().delete(actual.getPersonID());
++    getContainer().flush();
 +
-     actual = container.getCustomers().get(id);
++    actual = getContainer().getCustomers().get(id);
      assertNull(actual);
    }
  
@@@ -145,7 -147,7 +156,7 @@@
      // -------------------------------
      // Create a new order
      // -------------------------------
--    Order order = container.getOrders().newOrder();
++    Order order = getContainer().getOrders().newOrder();
      order.setOrderID(id);
  
      final Calendar orderDate = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
@@@ -160,7 -162,7 +171,7 @@@
      // -------------------------------
      // Create a new customer
      // -------------------------------
--    final Customer customer = container.getCustomers().newCustomer();
++    final Customer customer = getContainer().getCustomers().newCustomer();
      customer.setPersonID(id);
      customer.setPersonID(id);
      customer.setFirstName("Fabio");
@@@ -174,7 -176,7 +185,7 @@@
      customer.setHomeAddress(homeAddress);
      customer.setNumbers(Arrays.asList(new String[] {"3204725072", "08569930"}));
  
--    final OrderCollection orders = container.getOrders().newOrderCollection();
++    final OrderCollection orders = getContainer().getOrders().newOrderCollection();
      orders.add(order);
      customer.setOrders(orders);
      // -------------------------------
@@@ -185,7 -187,7 +196,7 @@@
      order.setCustomerForOrder(customer);
      // -------------------------------
  
--    container.flush();
++    getContainer().flush();
  
      assertEquals(id, order.getOrderID());
      assertEquals(id, customer.getPersonID());
@@@ -195,56 -197,56 +206,56 @@@
      assertEquals(1, actual.getOrders().size());
      assertEquals(id, actual.getOrders().iterator().next().getOrderID());
  
--    order = container.getOrders().get(id);
++    order = getContainer().getOrders().get(id);
      assertNotNull(order);
      assertEquals(id, order.getCustomerForOrder().getPersonID());
  
--    container.getOrders().delete(actual.getOrders());
--    container.flush();
++    getContainer().getOrders().delete(actual.getOrders());
++    getContainer().flush();
  
--    order = container.getOrders().get(id);
++    order = getContainer().getOrders().get(id);
      assertNull(order);
  
      actual = readCustomer(container, id);
      assertTrue(actual.getOrders().isEmpty());
  
--    container.getCustomers().delete(actual.getPersonID());
--    container.flush();
++    getContainer().getCustomers().delete(actual.getPersonID());
++    getContainer().flush();
  
--    actual = container.getCustomers().get(id);
++    actual = getContainer().getCustomers().get(id);
      assertNull(actual);
    }
  
    @Test
    public void multiKey() {
--    OrderDetail details = container.getOrderDetails().newOrderDetail();
++    OrderDetail details = getContainer().getOrderDetails().newOrderDetail();
      details.setOrderID(8);
      details.setProductID(1);
      details.setQuantity(100);
      details.setUnitPrice(5f);
  
--    container.flush();
++    getContainer().flush();
  
      OrderDetailKey key = new OrderDetailKey();
      key.setOrderID(8);
      key.setProductID(1);
  
--    details = container.getOrderDetails().get(key);
++    details = getContainer().getOrderDetails().get(key);
      assertNotNull(details);
      assertEquals(Integer.valueOf(100), details.getQuantity());
      assertEquals(8, details.getOrderID(), 0);
      assertEquals(1, details.getProductID(), 0);
      assertEquals(5f, details.getUnitPrice(), 0);
  
--    container.getOrderDetails().delete(key);
--    container.flush();
++    getContainer().getOrderDetails().delete(key);
++    getContainer().flush();
  
--    assertNull(container.getOrderDetails().get(key));
++    assertNull(getContainer().getOrderDetails().get(key));
    }
  
    @Test
    public void deepInsert() {
--    Product product = container.getProducts().newProduct();
++    Product product = getContainer().getProducts().newProduct();
      product.setProductID(12);
      product.setName("Latte");
      product.setQuantityPerUnit("100g Bag");
@@@ -255,30 -257,30 +266,30 @@@
      product.setSkinColor(Color.Blue);
      product.setCoverColors(Arrays.asList(new Color[] {Color.Red, Color.Green}));
  
--    final ProductDetail detail = container.getProductDetails().newProductDetail();
++    final ProductDetail detail = getContainer().getProductDetails().newProductDetail();
      detail.setProductID(product.getProductID());
      detail.setProductDetailID(12);
      detail.setProductName("LatteHQ");
      detail.setDescription("High-Quality Milk");
  
--    final ProductDetailCollection detailCollection = container.getProductDetails().newProductDetailCollection();
++    final ProductDetailCollection detailCollection = getContainer().getProductDetails().newProductDetailCollection();
      detailCollection.add(detail);
  
      product.setDetails(detailCollection);
  
--    container.flush();
++    getContainer().flush();
  
--    product = container.getProducts().get(12);
++    product = getContainer().getProducts().get(12);
      assertEquals("Latte", product.getName());
      assertEquals(12, product.getDetails().iterator().next().getProductDetailID(), 0);
    }
  
    @Test
    public void contained() {
--    PaymentInstrumentCollection instruments = container.getAccounts().get(101).getMyPaymentInstruments().getAll();
++    PaymentInstrumentCollection instruments = getContainer().getAccounts().get(101).getMyPaymentInstruments().getAll();
      final int sizeBefore = instruments.size();
  
--    final PaymentInstrument instrument = container.getAccounts().get(101).
++    final PaymentInstrument instrument = getContainer().getAccounts().get(101).
              getMyPaymentInstruments().newPaymentInstrument();
  
      final int id = RandomUtils.nextInt(101999, 105000);
@@@ -286,17 -288,17 +297,17 @@@
      instrument.setFriendlyName("New one");
      instrument.setCreatedDate(Calendar.getInstance());
  
--    container.flush();
++    getContainer().flush();
  
--    instruments = container.getAccounts().get(101).getMyPaymentInstruments().getAll();
++    instruments = getContainer().getAccounts().get(101).getMyPaymentInstruments().getAll();
      final int sizeAfter = instruments.size();
      assertEquals(sizeBefore + 1, sizeAfter);
  
--    container.getAccounts().get(101).getMyPaymentInstruments().delete(id);
++    getContainer().getAccounts().get(101).getMyPaymentInstruments().delete(id);
  
--    container.flush();
++    getContainer().flush();
  
--    instruments = container.getAccounts().get(101).getMyPaymentInstruments().getAll();
++    instruments = getContainer().getAccounts().get(101).getMyPaymentInstruments().getAll();
      final int sizeEnd = instruments.size();
      assertEquals(sizeBefore, sizeEnd);
    }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a09dd24/fit/src/test/java/org/apache/olingo/fit/proxy/v4/MediaEntityTestITCase.java
----------------------------------------------------------------------
diff --cc fit/src/test/java/org/apache/olingo/fit/proxy/v4/MediaEntityTestITCase.java
index 0000000,ad78bdd..60074b0
mode 000000,100644..100644
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/v4/MediaEntityTestITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/v4/MediaEntityTestITCase.java
@@@ -1,0 -1,106 +1,106 @@@
+ /*
+  * 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.fit.proxy.v4;
+ 
+ import static org.junit.Assert.assertNull;
+ import static org.junit.Assert.assertNotNull;
+ import static org.junit.Assert.assertEquals;
+ import static org.junit.Assert.assertTrue;
+ 
+ import java.io.IOException;
+ import java.io.InputStream;
+ import java.util.Calendar;
+ import java.util.UUID;
+ import org.apache.commons.io.IOUtils;
+ import org.apache.commons.lang3.RandomStringUtils;
+ import org.apache.olingo.client.api.v4.EdmEnabledODataClient;
+ import org.apache.olingo.commons.api.format.ContentType;
+ import org.apache.olingo.ext.proxy.EntityContainerFactory;
+ import org.apache.olingo.fit.proxy.v4.demo.odatademo.DemoService;
+ import org.apache.olingo.fit.proxy.v4.demo.odatademo.types.Advertisement;
+ import org.junit.BeforeClass;
+ import org.junit.Test;
+ 
+ /**
+  * This is the unit test class to check media entity retrieve operations.
+  */
+ public class MediaEntityTestITCase extends AbstractTestITCase {
+ 
+   private static DemoService dcontainer;
+ 
+   @BeforeClass
+   public static void initContainer() {
+     final EntityContainerFactory<EdmEnabledODataClient> otcontainerFactory =
+             EntityContainerFactory.getV4(testDemoServiceRootURL);
+     otcontainerFactory.getClient().getConfiguration().setDefaultBatchAcceptFormat(ContentType.APPLICATION_OCTET_STREAM);
+     dcontainer = otcontainerFactory.getEntityContainer(DemoService.class);
+     assertNotNull(dcontainer);
+   }
+ 
+   @Test
+   public void read() throws IOException {
+     final UUID uuid = UUID.fromString("f89dee73-af9f-4cd4-b330-db93c25ff3c7");
+ 
+     final Advertisement adv = dcontainer.getAdvertisements().get(uuid);
+     assertTrue(adv.getAirDate() instanceof Calendar);
+ 
+     final InputStream is = adv.getStream();
+     assertNotNull(is);
+     IOUtils.closeQuietly(is);
+   }
+ 
+   @Test
+   public void update() throws IOException {
+     final UUID uuid = UUID.fromString("f89dee73-af9f-4cd4-b330-db93c25ff3c7");
+ 
+     final Advertisement adv = dcontainer.getAdvertisements().get(uuid);
+     assertNotNull(adv);
+ 
+     final String random = RandomStringUtils.random(124, "abcdefghijklmnopqrstuvwxyz");
+ 
+     adv.setStream(IOUtils.toInputStream(random));
+ 
+     dcontainer.flush();
+ 
+     assertEquals(random, IOUtils.toString(dcontainer.getAdvertisements().get(uuid).getStream()));
+   }
+ 
+   @Test
+   public void create() throws IOException {
+     final String random = RandomStringUtils.random(124, "abcdefghijklmnopqrstuvwxyz");
+ 
+     final Advertisement adv = dcontainer.getAdvertisements().newAdvertisement();
+     adv.setStream(IOUtils.toInputStream(random));
+     adv.setAirDate(Calendar.getInstance());
+ 
+     dcontainer.flush();
+ 
+     final UUID uuid = adv.getID();
 -    entityContext.detachAll();
++    containerFactory.getContext().detachAll();
+     
+     assertEquals(random, IOUtils.toString(dcontainer.getAdvertisements().get(uuid).getStream()));
+ 
 -    entityContext.detachAll();
++    containerFactory.getContext().detachAll();
+ 
+     dcontainer.getAdvertisements().delete(uuid);
+     dcontainer.flush();
+ 
+     assertNull(dcontainer.getAdvertisements().get(uuid));
+   }
+ }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a09dd24/fit/src/test/java/org/apache/olingo/fit/proxy/v4/OpenTypeTestITCase.java
----------------------------------------------------------------------
diff --cc fit/src/test/java/org/apache/olingo/fit/proxy/v4/OpenTypeTestITCase.java
index 9b63483,e337521..035b7a3
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/v4/OpenTypeTestITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/v4/OpenTypeTestITCase.java
@@@ -45,12 -46,12 +46,13 @@@ import org.junit.Test
   */
  public class OpenTypeTestITCase extends AbstractTestITCase {
  
++  private static EntityContainerFactory<EdmEnabledODataClient> otcontainerFactory;
++
    private static DefaultContainer otcontainer;
  
    @BeforeClass
    public static void initContainer() {
--    final EntityContainerFactory<EdmEnabledODataClient> otcontainerFactory =
--            EntityContainerFactory.getV4(testOpenTypeServiceRootURL);
++    otcontainerFactory = EntityContainerFactory.getV4(testOpenTypeServiceRootURL);
      otcontainerFactory.getClient().getConfiguration().
              setDefaultBatchAcceptFormat(ContentType.APPLICATION_OCTET_STREAM);
      otcontainer = otcontainerFactory.getEntityContainer(DefaultContainer.class);
@@@ -65,7 -66,7 +67,7 @@@
              getAnnotation(EntityType.class).openType());
      assertTrue(otcontainer.getRow().newIndexedRow().getClass().getInterfaces()[0].
              getAnnotation(EntityType.class).openType());
-     containerFactory.getContext().detachAll();
 -    entityContext.detachAll();
++    otcontainerFactory.getContext().detachAll();
    }
  
    @Test
@@@ -127,8 -134,12 +135,12 @@@
      assertEquals(ContactDetails.class, rowIndex.getAdditionalProperty("aContact").getClass().getInterfaces()[0]);
      assertEquals(Color.class, rowIndex.getAdditionalProperty("aColor").getClass());
      assertEquals(Color.Green, rowIndex.getAdditionalProperty("aColor"));
+     assertEquals("Fabio", AccountInfo.class.cast(rowIndex.getAdditionalProperty("info")).getFirstName());
+     assertEquals("Martelli", AccountInfo.class.cast(rowIndex.getAdditionalProperty("info")).getLastName());
+     assertEquals("fabio.martelli@tirasa.net", AccountInfo.class.cast(rowIndex.getAdditionalProperty("info")).
+             getAdditionalProperty("email"));
  
-     containerFactory.getContext().detachAll();
 -    entityContext.detachAll();
++    otcontainerFactory.getContext().detachAll();
  
      otcontainer.getRowIndex().delete(id);
      otcontainer.flush();

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a09dd24/fit/src/test/java/org/apache/olingo/fit/proxy/v4/demo/odatademo/DemoService.java
----------------------------------------------------------------------
diff --cc fit/src/test/java/org/apache/olingo/fit/proxy/v4/demo/odatademo/DemoService.java
index 0000000,88c555d..627a08f
mode 000000,100644..100644
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/v4/demo/odatademo/DemoService.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/v4/demo/odatademo/DemoService.java
@@@ -1,0 -1,85 +1,85 @@@
+ /* 
+  * 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.fit.proxy.v4.demo.odatademo;
+ 
+ import org.apache.olingo.client.api.http.HttpMethod;
+ import org.apache.olingo.ext.proxy.api.annotations.Namespace;
+ import org.apache.olingo.ext.proxy.api.annotations.EntityContainer;
+ import org.apache.olingo.ext.proxy.api.annotations.Operation;
+ import org.apache.olingo.ext.proxy.api.annotations.Parameter;
+ import org.apache.olingo.ext.proxy.api.annotations.Property;
 -import org.apache.olingo.ext.proxy.api.Container;
++import org.apache.olingo.ext.proxy.api.PersistenceManager;
+ import org.apache.olingo.ext.proxy.api.OperationType;
+ import org.apache.olingo.fit.proxy.v4.demo.odatademo.*;
+ import org.apache.olingo.fit.proxy.v4.demo.odatademo.types.*;
+ 
+ import org.apache.olingo.commons.api.edm.geo.Geospatial;
+ import org.apache.olingo.commons.api.edm.geo.GeospatialCollection;
+ import org.apache.olingo.commons.api.edm.geo.LineString;
+ import org.apache.olingo.commons.api.edm.geo.MultiLineString;
+ import org.apache.olingo.commons.api.edm.geo.MultiPoint;
+ import org.apache.olingo.commons.api.edm.geo.MultiPolygon;
+ import org.apache.olingo.commons.api.edm.geo.Point;
+ import org.apache.olingo.commons.api.edm.geo.Polygon;
+ import java.math.BigDecimal;
+ import java.net.URI;
+ import java.util.UUID;
+ import java.io.Serializable;
+ import java.util.Collection;
+ import java.util.Calendar;
+ import javax.xml.datatype.Duration;
+ 
+ @Namespace("ODataDemo")
+ @EntityContainer(name = "DemoService",
+   namespace = "ODataDemo",
+   isDefaultEntityContainer = true)
 -public interface DemoService extends Container {
++public interface DemoService extends PersistenceManager {
+ 
+     Products getProducts();
+     Advertisements getAdvertisements();
+     Persons getPersons();
+     Categories getCategories();
+     PersonDetails getPersonDetails();
+     Suppliers getSuppliers();
+     ProductDetails getProductDetails();
+ 
+ 
+ 
+   Operations operations();
+ 
+   public interface Operations {
+   
+         @Operation(name = "IncreaseSalaries",
+                     type = OperationType.ACTION)
+   void increaseSalaries(
+         @Parameter(name = "percentage", type = "Edm.Int32", nullable = false) Integer percentage
+     );
+   
+       }
+ 
+       ComplexFactory complexFactory();
+ 
+     interface ComplexFactory {
+           @Property(name = "Address",
+                 type = "ODataDemo.Address")
+       org.apache.olingo.fit.proxy.v4.demo.odatademo.types.Address newAddress();
+ 
+         }
+   }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7a09dd24/fit/src/test/java/org/apache/olingo/fit/proxy/v4/opentype/microsoft/test/odata/services/opentypesservicev4/DefaultContainer.java
----------------------------------------------------------------------
diff --cc fit/src/test/java/org/apache/olingo/fit/proxy/v4/opentype/microsoft/test/odata/services/opentypesservicev4/DefaultContainer.java
index 11d485e,f146c6b..574d5b4
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/v4/opentype/microsoft/test/odata/services/opentypesservicev4/DefaultContainer.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/v4/opentype/microsoft/test/odata/services/opentypesservicev4/DefaultContainer.java
@@@ -50,10 -50,9 +50,9 @@@ import javax.xml.datatype.Duration
  @EntityContainer(name = "DefaultContainer",
    namespace = "Microsoft.Test.OData.Services.OpenTypesServiceV4",
    isDefaultEntityContainer = true)
 -public interface DefaultContainer extends Container {
 +public interface DefaultContainer extends PersistenceManager {
  
      Row getRow();
- 
      RowIndex getRowIndex();
  
  


[3/9] [OLINGO-260] Merge from master

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/1abd8e7e/fit/src/test/java/org/apache/olingo/fit/proxy/v3/ContextTestITCase.java
----------------------------------------------------------------------
diff --cc fit/src/test/java/org/apache/olingo/fit/proxy/v3/ContextTestITCase.java
index a3a78b4,df6ef13..8db857a
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/v3/ContextTestITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/v3/ContextTestITCase.java
@@@ -62,21 -62,21 +62,21 @@@ public class ContextTestITCase extends 
      final Customer customer1 = container.getCustomer().newCustomer();
      final Customer customer2 = container.getCustomer().newCustomer();
  
-     final EntityTypeInvocationHandler source1 =
-             (EntityTypeInvocationHandler) Proxy.getInvocationHandler(customer1);
-     final EntityTypeInvocationHandler source2 =
-             (EntityTypeInvocationHandler) Proxy.getInvocationHandler(customer2);
+     final EntityInvocationHandler source1 =
+             (EntityInvocationHandler) Proxy.getInvocationHandler(customer1);
+     final EntityInvocationHandler source2 =
+             (EntityInvocationHandler) Proxy.getInvocationHandler(customer2);
  
 -    assertTrue(entityContext.isAttached(source1));
 -    assertTrue(entityContext.isAttached(source2));
 +    assertTrue(containerFactory.getContext().entityContext().isAttached(source1));
 +    assertTrue(containerFactory.getContext().entityContext().isAttached(source2));
  
 -    entityContext.detach(source1);
 -    assertFalse(entityContext.isAttached(source1));
 -    assertTrue(entityContext.isAttached(source2));
 +    containerFactory.getContext().entityContext().detach(source1);
 +    assertFalse(containerFactory.getContext().entityContext().isAttached(source1));
 +    assertTrue(containerFactory.getContext().entityContext().isAttached(source2));
  
 -    entityContext.detach(source2);
 -    assertFalse(entityContext.isAttached(source1));
 -    assertFalse(entityContext.isAttached(source2));
 +    containerFactory.getContext().entityContext().detach(source2);
 +    assertFalse(containerFactory.getContext().entityContext().isAttached(source1));
 +    assertFalse(containerFactory.getContext().entityContext().isAttached(source2));
    }
  
    @Test
@@@ -85,29 -85,29 +85,29 @@@
      final Customer customer2 = container.getCustomer().get(-9);
      final Customer customer3 = container.getCustomer().get(-10);
  
-     final EntityTypeInvocationHandler source1 =
-             (EntityTypeInvocationHandler) Proxy.getInvocationHandler(customer1);
-     final EntityTypeInvocationHandler source2 =
-             (EntityTypeInvocationHandler) Proxy.getInvocationHandler(customer2);
-     final EntityTypeInvocationHandler source3 =
-             (EntityTypeInvocationHandler) Proxy.getInvocationHandler(customer3);
+     final EntityInvocationHandler source1 =
+             (EntityInvocationHandler) Proxy.getInvocationHandler(customer1);
+     final EntityInvocationHandler source2 =
+             (EntityInvocationHandler) Proxy.getInvocationHandler(customer2);
+     final EntityInvocationHandler source3 =
+             (EntityInvocationHandler) Proxy.getInvocationHandler(customer3);
  
 -    assertFalse(entityContext.isAttached(source1));
 -    assertFalse(entityContext.isAttached(source2));
 -    assertFalse(entityContext.isAttached(source3));
 +    assertFalse(containerFactory.getContext().entityContext().isAttached(source1));
 +    assertFalse(containerFactory.getContext().entityContext().isAttached(source2));
 +    assertFalse(containerFactory.getContext().entityContext().isAttached(source3));
  
 -    entityContext.attach(source1);
 -    assertTrue(entityContext.isAttached(source1));
 -    assertFalse(entityContext.isAttached(source2));
 -    assertTrue(entityContext.isAttached(source3));
 +    containerFactory.getContext().entityContext().attach(source1);
 +    assertTrue(containerFactory.getContext().entityContext().isAttached(source1));
 +    assertFalse(containerFactory.getContext().entityContext().isAttached(source2));
 +    assertTrue(containerFactory.getContext().entityContext().isAttached(source3));
  
 -    entityContext.attach(source2);
 -    assertTrue(entityContext.isAttached(source1));
 -    assertTrue(entityContext.isAttached(source2));
 -    assertTrue(entityContext.isAttached(source3));
 +    containerFactory.getContext().entityContext().attach(source2);
 +    assertTrue(containerFactory.getContext().entityContext().isAttached(source1));
 +    assertTrue(containerFactory.getContext().entityContext().isAttached(source2));
 +    assertTrue(containerFactory.getContext().entityContext().isAttached(source3));
  
      try {
 -      entityContext.attach(source3);
 +      containerFactory.getContext().entityContext().attach(source3);
        fail();
      } catch (IllegalStateException ignore) {
        // ignore
@@@ -133,15 -133,15 +133,15 @@@
  
      assertNotNull(customer.getInfo());
  
-     final EntityTypeInvocationHandler source =
-             (EntityTypeInvocationHandler) Proxy.getInvocationHandler(customer);
-     final EntityTypeInvocationHandler target =
-             (EntityTypeInvocationHandler) Proxy.getInvocationHandler(customerInfo);
+     final EntityInvocationHandler source =
+             (EntityInvocationHandler) Proxy.getInvocationHandler(customer);
+     final EntityInvocationHandler target =
+             (EntityInvocationHandler) Proxy.getInvocationHandler(customerInfo);
  
 -    assertTrue(entityContext.isAttached(source));
 -    assertEquals(AttachedEntityStatus.NEW, entityContext.getStatus(source));
 -    assertTrue(entityContext.isAttached(target));
 -    assertEquals(AttachedEntityStatus.LINKED, entityContext.getStatus(target));
 +    assertTrue(containerFactory.getContext().entityContext().isAttached(source));
 +    assertEquals(AttachedEntityStatus.NEW, containerFactory.getContext().entityContext().getStatus(source));
 +    assertTrue(containerFactory.getContext().entityContext().isAttached(target));
 +    assertEquals(AttachedEntityStatus.LINKED, containerFactory.getContext().entityContext().getStatus(target));
  
      checkUnidirectional("Info", source, "Customer", target, false);
  
@@@ -160,15 -160,15 +160,15 @@@
  
      assertNotNull(customer.getInfo());
  
-     final EntityTypeInvocationHandler source =
-             (EntityTypeInvocationHandler) Proxy.getInvocationHandler(customer);
-     final EntityTypeInvocationHandler target =
-             (EntityTypeInvocationHandler) Proxy.getInvocationHandler(customerInfo);
+     final EntityInvocationHandler source =
+             (EntityInvocationHandler) Proxy.getInvocationHandler(customer);
+     final EntityInvocationHandler target =
+             (EntityInvocationHandler) Proxy.getInvocationHandler(customerInfo);
  
 -    assertTrue(entityContext.isAttached(source));
 -    assertEquals(AttachedEntityStatus.CHANGED, entityContext.getStatus(source));
 -    assertTrue(entityContext.isAttached(target));
 -    assertEquals(AttachedEntityStatus.NEW, entityContext.getStatus(target));
 +    assertTrue(containerFactory.getContext().entityContext().isAttached(source));
 +    assertEquals(AttachedEntityStatus.CHANGED, containerFactory.getContext().entityContext().getStatus(source));
 +    assertTrue(containerFactory.getContext().entityContext().isAttached(target));
 +    assertEquals(AttachedEntityStatus.NEW, containerFactory.getContext().entityContext().getStatus(target));
  
      checkUnidirectional("Info", source, "Customer", target, false);
  
@@@ -187,15 -187,15 +187,15 @@@
  
      assertNotNull(customer.getInfo());
  
-     final EntityTypeInvocationHandler source =
-             (EntityTypeInvocationHandler) Proxy.getInvocationHandler(customer);
-     final EntityTypeInvocationHandler target =
-             (EntityTypeInvocationHandler) Proxy.getInvocationHandler(customerInfo);
+     final EntityInvocationHandler source =
+             (EntityInvocationHandler) Proxy.getInvocationHandler(customer);
+     final EntityInvocationHandler target =
+             (EntityInvocationHandler) Proxy.getInvocationHandler(customerInfo);
  
 -    assertTrue(entityContext.isAttached(source));
 -    assertEquals(AttachedEntityStatus.CHANGED, entityContext.getStatus(source));
 -    assertTrue(entityContext.isAttached(target));
 -    assertEquals(AttachedEntityStatus.LINKED, entityContext.getStatus(target));
 +    assertTrue(containerFactory.getContext().entityContext().isAttached(source));
 +    assertEquals(AttachedEntityStatus.CHANGED, containerFactory.getContext().entityContext().getStatus(source));
 +    assertTrue(containerFactory.getContext().entityContext().isAttached(target));
 +    assertEquals(AttachedEntityStatus.LINKED, containerFactory.getContext().entityContext().getStatus(target));
  
      checkUnidirectional("Info", source, "Customer", target, false);
  
@@@ -218,27 -218,26 +218,27 @@@
      assertNotNull(customer.getOrders());
      assertEquals(3, customer.getOrders().size());
  
-     final EntityTypeInvocationHandler source = (EntityTypeInvocationHandler) Proxy.getInvocationHandler(customer);
+     final EntityInvocationHandler source = (EntityInvocationHandler) Proxy.getInvocationHandler(customer);
  
 -    assertTrue(entityContext.isAttached(source));
 -    assertEquals(AttachedEntityStatus.NEW, entityContext.getStatus(source));
 +    assertTrue(containerFactory.getContext().entityContext().isAttached(source));
 +    assertEquals(AttachedEntityStatus.NEW, containerFactory.getContext().entityContext().getStatus(source));
      assertEquals(3, ((Collection) (source.getLinkChanges().entrySet().iterator().next().getValue())).size());
  
      for (Order order : toBeLinked) {
-       final EntityTypeInvocationHandler target = (EntityTypeInvocationHandler) Proxy.getInvocationHandler(order);
+       final EntityInvocationHandler target = (EntityInvocationHandler) Proxy.getInvocationHandler(order);
  
 -      assertTrue(entityContext.isAttached(target));
 -      assertEquals(AttachedEntityStatus.NEW, entityContext.getStatus(target));
 +      assertTrue(containerFactory.getContext().entityContext().isAttached(target));
 +      assertEquals(AttachedEntityStatus.NEW, containerFactory.getContext().entityContext().getStatus(target));
        checkUnidirectional("Orders", source, "Customer", target, true);
      }
  
 -    entityContext.detachAll();
 +    containerFactory.getContext().entityContext().detachAll();
  
 -    assertFalse(entityContext.isAttached(source));
 +    assertFalse(containerFactory.getContext().entityContext().isAttached(source));
  
      for (Order order : toBeLinked) {
 -      assertFalse(entityContext.isAttached((EntityInvocationHandler) Proxy.getInvocationHandler(order)));
 +      assertFalse(containerFactory.getContext().entityContext().
-               isAttached((EntityTypeInvocationHandler) Proxy.getInvocationHandler(order)));
++              isAttached((EntityInvocationHandler) Proxy.getInvocationHandler(order)));
      }
    }
  
@@@ -264,14 -263,14 +264,14 @@@
      assertEquals(2, customer.getBackupContactInfo().iterator().next().getAlternativeNames().size());
      assertTrue(customer.getBackupContactInfo().iterator().next().getAlternativeNames().contains("alternative4"));
  
-     final EntityTypeInvocationHandler source = (EntityTypeInvocationHandler) Proxy.getInvocationHandler(customer);
+     final EntityInvocationHandler source = (EntityInvocationHandler) Proxy.getInvocationHandler(customer);
  
 -    assertTrue(entityContext.isAttached(source));
 -    assertEquals(AttachedEntityStatus.NEW, entityContext.getStatus(source));
 +    assertTrue(containerFactory.getContext().entityContext().isAttached(source));
 +    assertEquals(AttachedEntityStatus.NEW, containerFactory.getContext().entityContext().getStatus(source));
  
 -    entityContext.detachAll();
 +    containerFactory.getContext().entityContext().detachAll();
  
 -    assertFalse(entityContext.isAttached(source));
 +    assertFalse(containerFactory.getContext().entityContext().isAttached(source));
    }
  
    @Test
@@@ -321,9 -320,9 +321,9 @@@
    public void checkContextInCaseOfErrors() {
      final Login login = container.getLogin().newLogin();
  
-     final EntityTypeInvocationHandler handler = (EntityTypeInvocationHandler) Proxy.getInvocationHandler(login);
+     final EntityInvocationHandler handler = (EntityInvocationHandler) Proxy.getInvocationHandler(login);
  
 -    assertTrue(entityContext.isAttached(handler));
 +    assertTrue(containerFactory.getContext().entityContext().isAttached(handler));
  
      try {
        container.flush();
@@@ -388,24 -387,18 +388,24 @@@
      customer.setPrimaryContactInfo(cd);
      customer.setBackupContactInfo(Collections.<ContactDetails>singletonList(bcd));
  
 -    assertTrue(entityContext.isAttached((EntityInvocationHandler) Proxy.getInvocationHandler(customerInfo)));
 -    assertTrue(entityContext.isAttached((EntityInvocationHandler) Proxy.getInvocationHandler(customer)));
 +    assertTrue(containerFactory.getContext().entityContext().
-             isAttached((EntityTypeInvocationHandler) Proxy.getInvocationHandler(customerInfo)));
++            isAttached((EntityInvocationHandler) Proxy.getInvocationHandler(customerInfo)));
 +    assertTrue(containerFactory.getContext().entityContext().
-             isAttached((EntityTypeInvocationHandler) Proxy.getInvocationHandler(customer)));
++            isAttached((EntityInvocationHandler) Proxy.getInvocationHandler(customer)));
      for (Order linked : toBeLinked) {
 -      assertTrue(entityContext.isAttached((EntityInvocationHandler) Proxy.getInvocationHandler(linked)));
 +      assertTrue(containerFactory.getContext().entityContext().
-               isAttached((EntityTypeInvocationHandler) Proxy.getInvocationHandler(linked)));
++              isAttached((EntityInvocationHandler) Proxy.getInvocationHandler(linked)));
      }
  
      container.flush();
  
 -    assertFalse(entityContext.isAttached((EntityInvocationHandler) Proxy.getInvocationHandler(customerInfo)));
 -    assertFalse(entityContext.isAttached((EntityInvocationHandler) Proxy.getInvocationHandler(customer)));
 +    assertFalse(containerFactory.getContext().entityContext().
-             isAttached((EntityTypeInvocationHandler) Proxy.getInvocationHandler(customerInfo)));
++            isAttached((EntityInvocationHandler) Proxy.getInvocationHandler(customerInfo)));
 +    assertFalse(containerFactory.getContext().entityContext().
-             isAttached((EntityTypeInvocationHandler) Proxy.getInvocationHandler(customer)));
++            isAttached((EntityInvocationHandler) Proxy.getInvocationHandler(customer)));
      for (Order linked : toBeLinked) {
 -      assertFalse(entityContext.isAttached((EntityInvocationHandler) Proxy.getInvocationHandler(linked)));
 +      assertFalse(containerFactory.getContext().entityContext().
-               isAttached((EntityTypeInvocationHandler) Proxy.getInvocationHandler(linked)));
++              isAttached((EntityInvocationHandler) Proxy.getInvocationHandler(linked)));
      }
  
      assertEquals("some new info ...", container.getCustomerInfo().get(16).getInformation());
@@@ -413,20 -406,16 +413,20 @@@
      container.getOrder().delete(toBeLinked);
      container.getCustomer().delete(customer.getCustomerId());
  
 -    assertTrue(entityContext.isAttached((EntityInvocationHandler) Proxy.getInvocationHandler(customer)));
 +    assertTrue(containerFactory.getContext().entityContext().
-             isAttached((EntityTypeInvocationHandler) Proxy.getInvocationHandler(customer)));
++            isAttached((EntityInvocationHandler) Proxy.getInvocationHandler(customer)));
      for (Order linked : toBeLinked) {
 -      assertTrue(entityContext.isAttached((EntityInvocationHandler) Proxy.getInvocationHandler(linked)));
 +      assertTrue(containerFactory.getContext().entityContext().
-               isAttached((EntityTypeInvocationHandler) Proxy.getInvocationHandler(linked)));
++              isAttached((EntityInvocationHandler) Proxy.getInvocationHandler(linked)));
      }
  
      container.flush();
  
 -    assertFalse(entityContext.isAttached((EntityInvocationHandler) Proxy.getInvocationHandler(customer)));
 +    assertFalse(containerFactory.getContext().entityContext().
-             isAttached((EntityTypeInvocationHandler) Proxy.getInvocationHandler(customer)));
++            isAttached((EntityInvocationHandler) Proxy.getInvocationHandler(customer)));
      for (Order linked : toBeLinked) {
 -      assertFalse(entityContext.isAttached((EntityInvocationHandler) Proxy.getInvocationHandler(linked)));
 +      assertFalse(containerFactory.getContext().entityContext().
-               isAttached((EntityTypeInvocationHandler) Proxy.getInvocationHandler(linked)));
++              isAttached((EntityInvocationHandler) Proxy.getInvocationHandler(linked)));
      }
    }
  

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/1abd8e7e/fit/src/test/java/org/apache/olingo/fit/proxy/v4/EntityCreateTestITCase.java
----------------------------------------------------------------------


[9/9] git commit: Client proxy enhancement: non-static persistence context

Posted by il...@apache.org.
Client proxy enhancement: non-static persistence context


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

Branch: refs/heads/master
Commit: 38214db490a90bbaa32aec3b0db035fc44b92ac2
Parents: 3c0b8ad 7a09dd2
Author: Francesco Chicchiriccò <--global>
Authored: Thu May 22 13:22:14 2014 +0200
Committer: Francesco Chicchiriccò <--global>
Committed: Thu May 22 13:22:14 2014 +0200

----------------------------------------------------------------------
 .../ext/proxy/EntityContainerFactory.java       |  28 +-
 .../apache/olingo/ext/proxy/api/Container.java  |  32 --
 .../ext/proxy/api/PersistenceManager.java       |  32 ++
 .../commons/AbstractInvocationHandler.java      |  50 +-
 .../AbstractStructuredInvocationHandler.java    |  49 +-
 .../commons/AnnotatableInvocationHandler.java   |   6 +-
 .../commons/AnnotatationsInvocationHandler.java |   8 +-
 .../ComplexFactoryInvocationHandler.java        |  21 +-
 .../proxy/commons/ComplexInvocationHandler.java |  59 +-
 .../olingo/ext/proxy/commons/ContainerImpl.java | 569 -------------------
 .../EntityCollectionInvocationHandler.java      |   4 +-
 .../EntityContainerInvocationHandler.java       |  19 +-
 .../proxy/commons/EntityInvocationHandler.java  |  20 +-
 .../commons/EntitySetInvocationHandler.java     |  62 +-
 .../commons/OperationInvocationHandler.java     |  22 +-
 .../proxy/commons/PersistenceManagerImpl.java   | 568 ++++++++++++++++++
 .../commons/SingletonInvocationHandler.java     |   2 +-
 .../olingo/ext/proxy/context/EntityContext.java |   4 +-
 .../olingo/ext/proxy/context/EntityUUID.java    |   4 +-
 .../olingo/ext/proxy/utils/CoreUtils.java       |  41 +-
 .../src/main/resources/container.vm             |   4 +-
 fit/pom.xml                                     |   1 +
 .../java/org/apache/olingo/fit/V3Services.java  |  16 +-
 .../org/apache/olingo/fit/utils/FSManager.java  |   6 +-
 .../olingo/fit/proxy/v3/AbstractTestITCase.java |   5 +-
 .../proxy/v3/ActionOverloadingTestITCase.java   |   8 +-
 .../olingo/fit/proxy/v3/ContextTestITCase.java  | 165 +++---
 .../fit/proxy/v3/EntityCreateTestITCase.java    |  10 +-
 .../fit/proxy/v3/MediaEntityTestITCase.java     |   3 +-
 .../olingo/fit/proxy/v3/OpenTypeTestITCase.java |   9 +-
 .../olingo/fit/proxy/v3/PropertyTestITCase.java |   7 +-
 .../astoriadefaultservice/DefaultContainer.java |   4 +-
 .../opentypesservicev3/DefaultContainer.java    |   4 +-
 .../primitivekeysservice/TestContext.java       |   4 +-
 .../astoriadefaultservice/DefaultContainer.java |   4 +-
 .../olingo/fit/proxy/v4/AbstractTestITCase.java |  11 +-
 .../proxy/v4/AuthEntityCreateTestITCase.java    |  40 +-
 .../fit/proxy/v4/EntityCreateTestITCase.java    | 109 ++--
 .../fit/proxy/v4/MediaEntityTestITCase.java     |   4 +-
 .../olingo/fit/proxy/v4/OpenTypeTestITCase.java |   9 +-
 .../olingo/fit/proxy/v4/PropertyTestITCase.java |   3 +-
 .../proxy/v4/demo/odatademo/DemoService.java    |   4 +-
 .../opentypesservicev4/DefaultContainer.java    |   4 +-
 .../odatawcfservice/InMemoryEntities.java       |   4 +-
 44 files changed, 1033 insertions(+), 1005 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/38214db4/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/EntityContainerFactory.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/38214db4/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 f208e83,9438d63..9b54380
--- 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
@@@ -276,7 -273,7 +271,7 @@@ public abstract class AbstractStructure
                  uri,
                  res.getBody(),
                  property.targetContainer(),
-                 client.newURIBuilder().appendEntitySetSegment(property.targetEntitySet()).build(),
 -                getClient().newURIBuilder(serviceRoot).appendEntitySetSegment(property.targetEntitySet()).build(),
++                getClient().newURIBuilder().appendEntitySetSegment(property.targetEntitySet()).build(),
                  type,
                  res.getETag(),
                  true);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/38214db4/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ComplexInvocationHandler.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/38214db4/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityInvocationHandler.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/38214db4/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 1a3e1be,d7c46f6..f446a96
--- 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
@@@ -138,8 -136,7 +136,8 @@@ final class OperationInvocationHandler 
  
    private Map.Entry<URI, EdmOperation> getUnboundOperation(
            final Operation operation, final List<String> parameterNames) {
 +
-     final EdmEntityContainer container = client.getCachedEdm().getEntityContainer(targetFQN);
+     final EdmEntityContainer container = getClient().getCachedEdm().getEntityContainer(targetFQN);
      final EdmOperation edmOperation;
  
      if (operation.type() == OperationType.FUNCTION) {