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

[6/8] git commit: [OLINGO-366] provides Primitive and Complex collection handling

[OLINGO-366] provides Primitive and Complex collection handling


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

Branch: refs/heads/master
Commit: acc5b5ce58375e1b5f580be6ffdb09057b2a0c39
Parents: 3a06074
Author: fmartelli <fa...@gmail.com>
Authored: Tue Jul 22 13:06:36 2014 +0200
Committer: fmartelli <fa...@gmail.com>
Committed: Tue Jul 22 13:06:36 2014 +0200

----------------------------------------------------------------------
 .../org/apache/olingo/ext/proxy/Service.java    |  45 ++-
 .../olingo/ext/proxy/api/AbstractEntitySet.java |   4 +-
 .../olingo/ext/proxy/api/AbstractSingleton.java |   2 +-
 .../olingo/ext/proxy/api/CollectionQuery.java   |   3 +-
 .../olingo/ext/proxy/api/ComplexCollection.java |  25 ++
 .../olingo/ext/proxy/api/EntityCollection.java  |   2 +-
 .../ext/proxy/api/EntityCollectionQuery.java    |  38 ---
 .../olingo/ext/proxy/api/EntitySetQuery.java    |   2 +-
 .../ext/proxy/api/PrimitiveCollection.java      |  25 ++
 .../org/apache/olingo/ext/proxy/api/Search.java |   2 +-
 .../proxy/api/StruncturedCollectionQuery.java   |  40 +++
 .../AbstractCollectionInvocationHandler.java    | 287 +++++++++++++++++++
 ...stractEntityCollectionInvocationHandler.java | 142 +++------
 .../commons/AbstractInvocationHandler.java      | 102 ++++++-
 .../ComplexCollectionInvocationHandler.java     | 119 ++++++++
 .../proxy/commons/ComplexInvocationHandler.java | 106 ++++++-
 .../EntityCollectionInvocationHandler.java      | 189 +-----------
 .../EntityContainerInvocationHandler.java       |   4 +-
 .../proxy/commons/EntityInvocationHandler.java  | 105 +++++--
 .../commons/EntitySetInvocationHandler.java     |  94 +++---
 .../ext/proxy/commons/EntitySetIterator.java    |   7 +-
 .../commons/OperationInvocationHandler.java     |  34 ++-
 .../PrimitiveCollectionInvocationHandler.java   | 137 +++++++++
 .../olingo/ext/proxy/commons/SearchImpl.java    |   4 +-
 .../commons/SingletonInvocationHandler.java     |  16 +-
 .../olingo/ext/pojogen/AbstractPOJOGenMojo.java |   1 +
 .../olingo/ext/pojogen/AbstractUtility.java     |   8 +-
 .../src/main/resources/complexCollection.vm     | 103 +++++++
 .../src/main/resources/entityCollection.vm      |   2 +-
 .../olingo/fit/proxy/v3/AbstractTestITCase.java |  47 ++-
 .../olingo/fit/proxy/v3/ContextTestITCase.java  |  60 ++--
 .../fit/proxy/v3/EntityRetrieveTestITCase.java  |   3 +-
 .../olingo/fit/proxy/v3/InvokeTestITCase.java   |  28 +-
 .../fit/proxy/v3/MediaEntityTestITCase.java     |   1 +
 .../olingo/fit/proxy/v3/OpenTypeTestITCase.java |   2 +-
 .../astoriadefaultservice/types/Aliases.java    |   4 +-
 .../AllSpatialCollectionTypesCollection.java    |   2 +-
 .../types/AllSpatialCollectionTypes_Simple.java |  24 +-
 ...SpatialCollectionTypes_SimpleCollection.java |   2 +-
 .../types/AllSpatialTypesCollection.java        |   2 +-
 .../types/BackOrderLine2Collection.java         |   2 +-
 .../types/BackOrderLineCollection.java          |   2 +-
 .../types/CarCollection.java                    |   2 +-
 .../types/ComputerCollection.java               |   2 +-
 .../types/ComputerDetail.java                   |   4 +-
 .../types/ComputerDetailCollection.java         |   2 +-
 .../types/ContactDetails.java                   |  12 +-
 .../types/ContractorCollection.java             |   2 +-
 .../astoriadefaultservice/types/Customer.java   |   4 +-
 .../types/CustomerCollection.java               |   2 +-
 .../types/CustomerInfoCollection.java           |   2 +-
 .../types/DiscontinuedProductCollection.java    |   2 +-
 .../types/DriverCollection.java                 |   2 +-
 .../types/EmployeeCollection.java               |   2 +-
 .../types/LastLoginCollection.java              |   2 +-
 .../types/LicenseCollection.java                |   2 +-
 .../types/LoginCollection.java                  |   2 +-
 .../types/MappedEntityType.java                 |  44 +--
 .../types/MappedEntityTypeCollection.java       |   2 +-
 .../types/MessageAttachmentCollection.java      |   2 +-
 .../types/MessageCollection.java                |   2 +-
 .../types/OrderCollection.java                  |   2 +-
 .../types/OrderLineCollection.java              |   2 +-
 .../types/PageViewCollection.java               |   2 +-
 .../types/PersonCollection.java                 |   2 +-
 .../types/PersonMetadataCollection.java         |   2 +-
 .../types/ProductCollection.java                |   2 +-
 .../types/ProductDetailCollection.java          |   2 +-
 .../types/ProductPageViewCollection.java        |   2 +-
 .../types/ProductPhotoCollection.java           |   2 +-
 .../types/ProductReviewCollection.java          |   2 +-
 .../types/RSATokenCollection.java               |   2 +-
 .../types/SpecialEmployeeCollection.java        |   2 +-
 .../types/IndexedRowCollection.java             |   2 +-
 .../opentypesservicev3/types/RowCollection.java |   2 +-
 .../types/RowIndexCollection.java               |   2 +-
 .../types/EdmBinaryCollection.java              |   2 +-
 .../types/EdmBooleanCollection.java             |   2 +-
 .../types/EdmByteCollection.java                |   2 +-
 .../types/EdmDateTimeCollection.java            |   2 +-
 .../types/EdmDateTimeOffsetCollection.java      |   2 +-
 .../types/EdmDecimalCollection.java             |   2 +-
 .../types/EdmDoubleCollection.java              |   2 +-
 .../types/EdmGuidCollection.java                |   2 +-
 .../types/EdmInt16Collection.java               |   2 +-
 .../types/EdmInt32Collection.java               |   2 +-
 .../types/EdmInt64Collection.java               |   2 +-
 .../types/EdmSingleCollection.java              |   2 +-
 .../types/EdmStringCollection.java              |   2 +-
 .../types/EdmTimeCollection.java                |   2 +-
 .../types/FolderCollection.java                 |   2 +-
 .../astoriadefaultservice/DefaultContainer.java |   2 +-
 .../astoriadefaultservice/types/Aliases.java    |   4 +-
 .../AllSpatialCollectionTypesCollection.java    |   2 +-
 .../types/AllSpatialCollectionTypes_Simple.java |  24 +-
 ...SpatialCollectionTypes_SimpleCollection.java |   2 +-
 .../types/AllSpatialTypesCollection.java        |   2 +-
 .../types/BackOrderLine2Collection.java         |   2 +-
 .../types/BackOrderLineCollection.java          |   2 +-
 .../types/CarCollection.java                    |   2 +-
 .../types/ComputerCollection.java               |   2 +-
 .../types/ComputerDetail.java                   |   6 +-
 .../types/ComputerDetailCollection.java         |   2 +-
 .../types/ContactDetails.java                   |  12 +-
 .../types/ContractorCollection.java             |   2 +-
 .../astoriadefaultservice/types/Customer.java   |   4 +-
 .../types/CustomerCollection.java               |   2 +-
 .../types/CustomerInfoCollection.java           |   2 +-
 .../types/DiscontinuedProductCollection.java    |   2 +-
 .../types/DriverCollection.java                 |   2 +-
 .../types/EmployeeCollection.java               |   2 +-
 .../types/LastLoginCollection.java              |   2 +-
 .../types/LicenseCollection.java                |   2 +-
 .../types/LoginCollection.java                  |   2 +-
 .../types/MappedEntityType.java                 |  44 +--
 .../types/MappedEntityTypeCollection.java       |   2 +-
 .../types/MessageAttachmentCollection.java      |   2 +-
 .../types/MessageCollection.java                |   2 +-
 .../types/OrderCollection.java                  |   2 +-
 .../types/OrderLineCollection.java              |   2 +-
 .../types/PageViewCollection.java               |   2 +-
 .../types/PersonCollection.java                 |   2 +-
 .../types/PersonMetadataCollection.java         |   2 +-
 .../types/ProductCollection.java                |   2 +-
 .../types/ProductDetailCollection.java          |   2 +-
 .../types/ProductPageViewCollection.java        |   2 +-
 .../types/ProductPhotoCollection.java           |   2 +-
 .../types/ProductReviewCollection.java          |   2 +-
 .../types/RSATokenCollection.java               |   2 +-
 .../types/SpecialEmployeeCollection.java        |   2 +-
 .../fit/proxy/v4/APIBasicDesignTestITCase.java  |  41 ++-
 .../olingo/fit/proxy/v4/AbstractTestITCase.java |   9 +-
 .../v4/BoundOperationInvokeTestITCase.java      |  16 +-
 .../olingo/fit/proxy/v4/ContextTestITCase.java  |  35 ++-
 .../fit/proxy/v4/DerivedTypeTestITCase.java     |   8 +-
 .../fit/proxy/v4/EntityCreateTestITCase.java    |  58 +++-
 .../fit/proxy/v4/EntityUpdateTestITCase.java    |  10 +-
 .../olingo/fit/proxy/v4/OpenTypeTestITCase.java |   4 +-
 .../v4/OperationImportInvokeTestITCase.java     |  19 +-
 .../types/AdvertisementCollection.java          |   2 +-
 .../odatademo/types/CategoryCollection.java     |   2 +-
 .../odatademo/types/CustomerCollection.java     |   2 +-
 .../odatademo/types/EmployeeCollection.java     |   2 +-
 .../types/FeaturedProductCollection.java        |   2 +-
 .../demo/odatademo/types/PersonCollection.java  |   2 +-
 .../odatademo/types/PersonDetailCollection.java |   2 +-
 .../demo/odatademo/types/ProductCollection.java |   2 +-
 .../types/ProductDetailCollection.java          |   2 +-
 .../odatademo/types/SupplierCollection.java     |   2 +-
 .../types/IndexedRowCollection.java             |   2 +-
 .../opentypesservicev4/types/RowCollection.java |   2 +-
 .../types/RowIndexCollection.java               |   2 +-
 .../odatawcfservice/InMemoryEntities.java       |   8 +-
 .../types/AccountCollection.java                |   2 +-
 .../odatawcfservice/types/AssetCollection.java  |   2 +-
 .../odatawcfservice/types/ClubCollection.java   |   2 +-
 .../types/CompanyCollection.java                |   2 +-
 .../types/CreditCardPICollection.java           |   2 +-
 .../types/CreditRecordCollection.java           |   2 +-
 .../odatawcfservice/types/Customer.java         |   8 +-
 .../types/CustomerCollection.java               |   2 +-
 .../types/DepartmentCollection.java             |   2 +-
 .../odatawcfservice/types/Employee.java         |   8 +-
 .../types/EmployeeCollection.java               |   2 +-
 .../types/GiftCardCollection.java               |   2 +-
 .../types/LabourUnionCollection.java            |   2 +-
 .../services/odatawcfservice/types/Order.java   |   4 +-
 .../odatawcfservice/types/OrderCollection.java  |   2 +-
 .../types/OrderDetailCollection.java            |   2 +-
 .../types/PaymentInstrumentCollection.java      |   2 +-
 .../services/odatawcfservice/types/Person.java  |  10 +-
 .../odatawcfservice/types/PersonCollection.java |   2 +-
 .../services/odatawcfservice/types/Product.java |   4 +-
 .../types/ProductCollection.java                |   2 +-
 .../types/ProductDetailCollection.java          |   2 +-
 .../types/ProductReviewCollection.java          |   2 +-
 .../types/PublicCompanyCollection.java          |   2 +-
 .../types/StatementCollection.java              |   2 +-
 .../types/StoredPICollection.java               |   2 +-
 .../types/SubscriptionCollection.java           |   2 +-
 180 files changed, 1645 insertions(+), 808 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/acc5b5ce/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/Service.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/Service.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/Service.java
index 6c13664..7df1ab2 100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/Service.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/Service.java
@@ -18,6 +18,7 @@
  */
 package org.apache.olingo.ext.proxy;
 
+import java.io.Serializable;
 import org.apache.olingo.client.api.CommonEdmEnabledODataClient;
 import org.apache.olingo.client.core.ODataClientFactory;
 import org.apache.olingo.commons.api.format.ODataFormat;
@@ -35,9 +36,12 @@ import org.apache.olingo.ext.proxy.context.Context;
 import org.apache.olingo.ext.proxy.utils.ClassUtils;
 
 import java.lang.reflect.Proxy;
-import java.util.ArrayList;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
+import org.apache.olingo.ext.proxy.api.ComplexCollection;
+import org.apache.olingo.ext.proxy.api.PrimitiveCollection;
+import org.apache.olingo.ext.proxy.commons.ComplexCollectionInvocationHandler;
+import org.apache.olingo.ext.proxy.commons.PrimitiveCollectionInvocationHandler;
 
 /**
  * Entry point for proxy mode, gives access to entity container instances.
@@ -171,31 +175,48 @@ public final class Service<C extends CommonEdmEnabledODataClient<?>> {
   }
 
   @SuppressWarnings("unchecked")
-  public <NE extends EntityType> NE newEntityInstance(final Class<NE> reference) {
-    final EntityInvocationHandler handler = EntityInvocationHandler.getInstance(reference, this);
+  public <NE extends EntityType> NE newEntityInstance(final Class<NE> ref) {
+    final EntityInvocationHandler handler = EntityInvocationHandler.getInstance(ref, this);
 
     return (NE) Proxy.newProxyInstance(
             Thread.currentThread().getContextClassLoader(),
-            new Class<?>[] {reference},
+            new Class<?>[] {ref},
             handler);
   }
 
   @SuppressWarnings("unchecked")
-  public <T extends EntityType, NEC extends EntityCollection<T>> NEC newEntityCollection(final Class<NEC> reference) {
-    final Class<T> ref = (Class<T>) ClassUtils.extractTypeArg(reference, EntityCollection.class);
-
+  public <T extends EntityType, NEC extends EntityCollection<T>> NEC newEntityCollection(final Class<NEC> ref) {
     return (NEC) Proxy.newProxyInstance(
             Thread.currentThread().getContextClassLoader(),
-            new Class<?>[] {reference},
-            new EntityCollectionInvocationHandler<T>(this, new ArrayList<T>(), ref));
+            new Class<?>[] {ref},
+            new EntityCollectionInvocationHandler<T>(this, ref));
   }
 
   @SuppressWarnings("unchecked")
-  public <NE extends ComplexType> NE newComplex(final Class<NE> reference) {
+  public <NE extends ComplexType> NE newComplexInstance(final Class<NE> ref) {
     return (NE) Proxy.newProxyInstance(
             Thread.currentThread().getContextClassLoader(),
-            new Class<?>[] {reference},
-            ComplexInvocationHandler.getInstance(reference, this));
+            new Class<?>[] {ref},
+            ComplexInvocationHandler.getInstance(ref, this));
+
+  }
 
+  @SuppressWarnings("unchecked")
+  public <T extends ComplexType, NEC extends ComplexCollection<T>> NEC newComplexCollection(final Class<NEC> ref) {
+    final Class<T> itemRef = (Class<T>) ClassUtils.extractTypeArg(ref, ComplexCollection.class);
+
+    return (NEC) Proxy.newProxyInstance(
+            Thread.currentThread().getContextClassLoader(),
+            new Class<?>[] {ref},
+            new ComplexCollectionInvocationHandler<T>(this, itemRef));
+  }
+
+  @SuppressWarnings("unchecked")
+  public <T extends Serializable, NEC extends PrimitiveCollection<T>> NEC newPrimitiveCollection(final Class<T> ref) {
+
+    return (NEC) Proxy.newProxyInstance(
+            Thread.currentThread().getContextClassLoader(),
+            new Class<?>[] {PrimitiveCollection.class},
+            new PrimitiveCollectionInvocationHandler<T>(this, ref));
   }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/acc5b5ce/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/AbstractEntitySet.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/AbstractEntitySet.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/AbstractEntitySet.java
index 1455e87..b472d24 100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/AbstractEntitySet.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/AbstractEntitySet.java
@@ -24,10 +24,10 @@ import java.io.Serializable;
  * Interface for synchronous CRUD operations on an EntitySet.
  */
 public interface AbstractEntitySet<
-        T extends StructuredType, KEY extends Serializable, EC extends EntityCollection<T>>
+        T extends EntityType, KEY extends Serializable, EC extends EntityCollection<T>>
         extends Iterable<T>, Serializable {
 
-  void add(final T entity);
+  boolean add(final T entity);
 
   /**
    * Returns whether an entity with the given id exists.

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/acc5b5ce/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/AbstractSingleton.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/AbstractSingleton.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/AbstractSingleton.java
index cfba4b9..f035292 100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/AbstractSingleton.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/AbstractSingleton.java
@@ -21,6 +21,6 @@ package org.apache.olingo.ext.proxy.api;
 import java.io.Serializable;
 
 public interface AbstractSingleton<
-        T extends Serializable, KEY extends Serializable, EC extends EntityCollection<T>>
+        T extends EntityType, KEY extends Serializable, EC extends EntityCollection<T>>
         extends Serializable {
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/acc5b5ce/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/CollectionQuery.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/CollectionQuery.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/CollectionQuery.java
index 7793d78..3f532ea 100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/CollectionQuery.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/CollectionQuery.java
@@ -18,10 +18,11 @@
  */
 package org.apache.olingo.ext.proxy.api;
 
+import java.util.Collection;
 import org.apache.olingo.client.api.uri.URIFilter;
 
 public interface CollectionQuery<
-        T extends StructuredType, EC extends EntityCollection<T>, CT extends CollectionQuery<T, EC, ?>>
+        T extends StructuredType, EC extends Collection<T>, CT extends CollectionQuery<T, EC, ?>>
         extends CommonQuery<CollectionQuery<T, EC, CT>> {
 
   /**

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/acc5b5ce/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/ComplexCollection.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/ComplexCollection.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/ComplexCollection.java
new file mode 100644
index 0000000..2f381a1
--- /dev/null
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/ComplexCollection.java
@@ -0,0 +1,25 @@
+/*
+ * 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;
+import java.util.Collection;
+
+public interface ComplexCollection<T extends ComplexType> extends Collection<T>, Serializable {
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/acc5b5ce/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/EntityCollection.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/EntityCollection.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/EntityCollection.java
index a0de7bc..449c3e6 100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/EntityCollection.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/EntityCollection.java
@@ -21,5 +21,5 @@ package org.apache.olingo.ext.proxy.api;
 import java.io.Serializable;
 import java.util.Collection;
 
-public interface EntityCollection<T extends Serializable> extends Collection<T>, Serializable {
+public interface EntityCollection<T extends EntityType> extends Collection<T>, Serializable {
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/acc5b5ce/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/EntityCollectionQuery.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/EntityCollectionQuery.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/EntityCollectionQuery.java
deleted file mode 100644
index 534d4f5..0000000
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/EntityCollectionQuery.java
+++ /dev/null
@@ -1,38 +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;
-
-public interface EntityCollectionQuery<
-        T extends StructuredType, EC extends EntityCollection<T>, CT extends EntityCollectionQuery<T, EC, ?>>
-        extends CollectionQuery<T, EC, CT> {
-
-  /**
-   * Explicit paging result handling.
-   *
-   * @return next page.
-   */
-  CT nextPage();
-
-  /**
-   * Checks for next page existence.
-   *
-   * @return <<tt>TRUE</tt> whether a next page exist; <tt>FALSE</tt> otherwise.
-   */
-  boolean hasNextPage();
-}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/acc5b5ce/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/EntitySetQuery.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/EntitySetQuery.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/EntitySetQuery.java
index bbd23b2..e726803 100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/EntitySetQuery.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/EntitySetQuery.java
@@ -19,7 +19,7 @@
 package org.apache.olingo.ext.proxy.api;
 
 public interface EntitySetQuery<
-        T extends StructuredType, EC extends EntityCollection<T>, CT extends EntitySetQuery<T, EC, ?>>
+        T extends EntityType, EC extends EntityCollection<T>, CT extends EntitySetQuery<T, EC, ?>>
         extends CollectionQuery<T, EC, CT> {
 
   /**

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/acc5b5ce/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/PrimitiveCollection.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/PrimitiveCollection.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/PrimitiveCollection.java
new file mode 100644
index 0000000..9ea5cca
--- /dev/null
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/PrimitiveCollection.java
@@ -0,0 +1,25 @@
+/*
+ * 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;
+import java.util.Collection;
+
+public interface PrimitiveCollection<T extends Serializable> extends Collection<T>, Serializable {
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/acc5b5ce/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/Search.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/Search.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/Search.java
index feec716..3d0a56a 100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/Search.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/Search.java
@@ -28,7 +28,7 @@ import java.io.Serializable;
  * @param <T> search result type
  * @param <EC>
  */
-public interface Search<T extends Serializable, EC extends EntityCollection<T>> extends Serializable {
+public interface Search<T extends EntityType, EC extends EntityCollection<T>> extends Serializable {
 
   /**
    * Sets the <tt>$search</tt> expression for this search.

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/acc5b5ce/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/StruncturedCollectionQuery.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/StruncturedCollectionQuery.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/StruncturedCollectionQuery.java
new file mode 100644
index 0000000..bd0db91
--- /dev/null
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/StruncturedCollectionQuery.java
@@ -0,0 +1,40 @@
+/*
+ * 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.util.Collection;
+
+public interface StruncturedCollectionQuery<
+        T extends StructuredType, EC extends Collection<T>, CT extends StruncturedCollectionQuery<T, EC, ?>>
+        extends CollectionQuery<T, EC, CT> {
+
+  /**
+   * Explicit paging result handling.
+   *
+   * @return next page.
+   */
+  CT nextPage();
+
+  /**
+   * Checks for next page existence.
+   *
+   * @return <<tt>TRUE</tt> whether a next page exist; <tt>FALSE</tt> otherwise.
+   */
+  boolean hasNextPage();
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/acc5b5ce/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractCollectionInvocationHandler.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractCollectionInvocationHandler.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractCollectionInvocationHandler.java
new file mode 100644
index 0000000..c8e37b7
--- /dev/null
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractCollectionInvocationHandler.java
@@ -0,0 +1,287 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.ext.proxy.commons;
+
+import java.io.Serializable;
+import org.apache.olingo.client.api.uri.CommonURIBuilder;
+
+import java.lang.reflect.Proxy;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import org.apache.commons.lang3.tuple.Triple;
+import org.apache.olingo.client.api.uri.URIFilter;
+import org.apache.olingo.commons.api.domain.v4.ODataAnnotation;
+import org.apache.olingo.ext.proxy.Service;
+import org.apache.olingo.ext.proxy.api.AbstractTerm;
+import org.apache.olingo.ext.proxy.api.Sort;
+import org.apache.olingo.ext.proxy.api.annotations.Namespace;
+import org.apache.olingo.ext.proxy.api.annotations.Term;
+import org.apache.olingo.ext.proxy.utils.CoreUtils;
+
+public abstract class AbstractCollectionInvocationHandler<T extends Serializable, EC extends Collection<T>>
+        extends AbstractInvocationHandler implements Collection<T> {
+
+  private static final long serialVersionUID = 98078202642671726L;
+
+  protected URI nextPageURI = null;
+
+  protected Collection<T> items;
+
+  protected final URI baseURI;
+
+  protected CommonURIBuilder<?> uri;
+
+  protected final Class<T> itemRef;
+
+  protected final List<ODataAnnotation> annotations = new ArrayList<ODataAnnotation>();
+
+  private final Map<Class<? extends AbstractTerm>, Object> annotationsByTerm =
+          new HashMap<Class<? extends AbstractTerm>, Object>();
+
+  public AbstractCollectionInvocationHandler(
+          final Service<?> service,
+          final Collection<T> items,
+          final Class<T> itemRef,
+          final CommonURIBuilder<?> uri) {
+
+    super(service);
+
+    this.itemRef = itemRef;
+    this.items = items;
+    this.uri = uri;
+    this.baseURI = this.uri == null ? null : this.uri.build();
+  }
+
+  @SuppressWarnings("unchecked")
+  public Collection<T> execute() {
+    if (this.uri != null) {
+      final Triple<List<T>, URI, List<ODataAnnotation>> res = fetchPartial(this.uri.build(), itemRef);
+      this.nextPageURI = res.getMiddle();
+
+      if (items == null) {
+        items = res.getLeft();
+      } else {
+        items.clear();
+        items.addAll(res.getLeft());
+      }
+
+      annotations.clear();
+      annotations.addAll(res.getRight());
+    }
+
+    return this;
+  }
+
+  public abstract <S extends T> Triple<List<S>, URI, List<ODataAnnotation>> fetchPartial(
+          final URI uri, final Class<S> typeRef);
+
+  public void setAnnotations(final List<ODataAnnotation> annotations) {
+    this.annotations.clear();
+    this.annotationsByTerm.clear();
+    this.annotations.addAll(annotations);
+  }
+
+  protected Class<T> getTypeRef() {
+    return this.itemRef;
+  }
+
+  protected URI getURI() {
+    return this.baseURI;
+  }
+
+  public void nextPage() {
+    if (!hasNextPage()) {
+      throw new IllegalStateException("Next page URI not found");
+    }
+    this.uri = getClient().newURIBuilder(nextPageURI.toASCIIString());
+  }
+
+  public boolean hasNextPage() {
+    return this.nextPageURI != null;
+  }
+
+  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(annotation.getValue(), null, service);
+        if (res != null) {
+          annotationsByTerm.put(term, res);
+        }
+      } catch (Exception e) {
+        throw new IllegalArgumentException("Error getting annotation for term '" + term.getName() + "'", e);
+      }
+    }
+
+    return res;
+  }
+
+  @Override
+  public boolean add(final T element) {
+    if (element instanceof Proxy && Proxy.getInvocationHandler(element) instanceof EntityInvocationHandler) {
+      final EntityInvocationHandler handler = EntityInvocationHandler.class.cast(Proxy.getInvocationHandler(element));
+      if (!service.getContext().entityContext().isAttached(handler) && baseURI != null) {
+        handler.updateUUID(baseURI, itemRef, null);
+        service.getContext().entityContext().attachNew(handler);
+      }
+    }
+    return items.add(element);
+  }
+
+  @Override
+  public int size() {
+    return items.size();
+  }
+
+  @Override
+  public boolean isEmpty() {
+    return items.isEmpty();
+  }
+
+  @Override
+  public boolean contains(final Object object) {
+    return items.contains(object);
+  }
+
+  @Override
+  public Iterator<T> iterator() {
+    return items.iterator();
+  }
+
+  @Override
+  public Object[] toArray() {
+    return items.toArray();
+  }
+
+  @Override
+  public <T> T[] toArray(final T[] array) {
+    return items.toArray(array);
+  }
+
+  public Collection<Class<? extends AbstractTerm>> getAnnotationTerms() {
+    return CoreUtils.getAnnotationTerms(annotations);
+  }
+
+  @Override
+  public boolean remove(final Object object) {
+    return items.remove(object);
+  }
+
+  @Override
+  public boolean containsAll(final Collection<?> collection) {
+    return items.containsAll(collection);
+  }
+
+  @Override
+  public boolean addAll(final Collection<? extends T> collection) {
+    return items.addAll(collection);
+  }
+
+  @Override
+  public boolean removeAll(final Collection<?> collection) {
+    return items.removeAll(collection);
+  }
+
+  @Override
+  public boolean retainAll(final Collection<?> collection) {
+    return items.retainAll(collection);
+  }
+
+  @Override
+  public void clear() {
+    items.clear();
+  }
+
+  public void filter(final String filter) {
+    if (this.uri != null) {
+      this.uri.filter(filter);
+    }
+  }
+
+  public void filter(final URIFilter filter) {
+    if (this.uri != null) {
+      this.uri.filter(filter);
+    }
+  }
+
+  public void orderBy(final Sort... sort) {
+    if (this.uri != null) {
+      final StringBuilder builder = new StringBuilder();
+      for (Sort sortClause : sort) {
+        builder.append(sortClause.getKey()).append(' ').append(sortClause.getValue()).append(',');
+      }
+      builder.deleteCharAt(builder.length() - 1);
+
+      this.uri.orderBy(builder.toString());
+    }
+  }
+
+  public void orderBy(final String orderBy) {
+    if (this.uri != null) {
+      this.uri.orderBy(orderBy);
+    }
+  }
+
+  public void top(final int top) throws IllegalArgumentException {
+    if (this.uri != null) {
+      this.uri.top(top);
+    }
+  }
+
+  public void skip(final int skip) throws IllegalArgumentException {
+    if (this.uri != null) {
+      this.uri.skip(skip);
+    }
+  }
+
+  public void expand(final String... expand) {
+    if (this.uri != null) {
+      this.uri.expand(expand);
+    }
+  }
+
+  public void select(final String... select) {
+    if (this.uri != null) {
+      this.uri.select(select);
+    }
+  }
+
+  public void clearQueryOptions() {
+    this.uri = this.baseURI == null ? null : getClient().newURIBuilder(baseURI.toASCIIString());
+    this.nextPageURI = null;
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/acc5b5ce/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractEntityCollectionInvocationHandler.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractEntityCollectionInvocationHandler.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractEntityCollectionInvocationHandler.java
index d63ab73..07b85b8 100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractEntityCollectionInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractEntityCollectionInvocationHandler.java
@@ -23,7 +23,6 @@ import org.apache.commons.lang3.tuple.Triple;
 import org.apache.olingo.client.api.communication.request.retrieve.ODataEntitySetRequest;
 import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse;
 import org.apache.olingo.client.api.uri.CommonURIBuilder;
-import org.apache.olingo.client.api.uri.URIFilter;
 import org.apache.olingo.client.api.v4.ODataClient;
 import org.apache.olingo.commons.api.domain.CommonODataEntity;
 import org.apache.olingo.commons.api.domain.CommonODataEntitySet;
@@ -31,11 +30,7 @@ import org.apache.olingo.commons.api.domain.v4.ODataAnnotation;
 import org.apache.olingo.commons.api.domain.v4.ODataEntitySet;
 import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
 import org.apache.olingo.ext.proxy.api.EntityCollection;
-import org.apache.olingo.ext.proxy.api.AbstractEntitySet;
 import org.apache.olingo.ext.proxy.api.AbstractSingleton;
-import org.apache.olingo.ext.proxy.api.Sort;
-import org.apache.olingo.ext.proxy.api.StructuredType;
-import org.apache.olingo.ext.proxy.utils.ClassUtils;
 
 import java.lang.reflect.Proxy;
 import java.lang.reflect.Type;
@@ -43,100 +38,69 @@ import java.net.URI;
 import java.util.ArrayList;
 import java.util.List;
 import org.apache.olingo.ext.proxy.Service;
+import org.apache.olingo.ext.proxy.api.AbstractEntitySet;
+import org.apache.olingo.ext.proxy.api.EntityType;
+import org.apache.olingo.ext.proxy.utils.ClassUtils;
 
-public abstract class AbstractEntityCollectionInvocationHandler<
-        T extends StructuredType, EC extends EntityCollection<T>>
-        extends AbstractInvocationHandler {
+public abstract class AbstractEntityCollectionInvocationHandler<T extends EntityType, EC extends EntityCollection<T>>
+        extends AbstractCollectionInvocationHandler<T, EC> {
 
   private static final long serialVersionUID = 98078202642671727L;
 
-  protected final Class<T> itemRef;
-
-  protected final Class<EC> collItemRef;
-
-  protected final URI baseURI;
-
   protected URI targetEntitySetURI;
 
-  protected CommonURIBuilder<?> uri;
-
   private boolean isSingleton = false;
 
+  protected final Class<EC> collItemRef;
+
   @SuppressWarnings("unchecked")
   public AbstractEntityCollectionInvocationHandler(
           final Class<?> ref,
           final Service<?> service,
           final CommonURIBuilder<?> uri) {
-    super(service);
 
-    this.uri = uri;
-    this.baseURI = uri.build();
+    super(service,
+            new ArrayList<T>(),
+            (Class<T>) ClassUtils.extractTypeArg(
+            ref, AbstractEntitySet.class, AbstractSingleton.class, EntityCollection.class),
+            uri);
+
     this.targetEntitySetURI = uri.build();
     this.isSingleton = AbstractSingleton.class.isAssignableFrom(ref);
 
-    final Type[] entitySetParams =
-            ClassUtils.extractGenericType(ref, AbstractEntitySet.class, AbstractSingleton.class);
+    final Type[] entitySetParams = ClassUtils.extractGenericType(ref, AbstractEntitySet.class, AbstractSingleton.class);
 
-    this.itemRef = (Class<T>) entitySetParams[0];
-    this.collItemRef = (Class<EC>) entitySetParams[2];
+    if (entitySetParams != null) {
+      this.collItemRef = (Class<EC>) entitySetParams[2];
+    } else {
+      this.collItemRef = null;
+    }
   }
 
   @SuppressWarnings("unchecked")
   public AbstractEntityCollectionInvocationHandler(
-          final Class<?> itemRef,
-          final Class<EC> collItemRef,
+          final Class<? extends EntityCollection<T>> ref,
           final Service<?> service,
           final URI targetEntitySetURI,
           final CommonURIBuilder<?> uri) {
-    super(service);
+    super(service,
+            new ArrayList<T>(),
+            (Class<T>) ClassUtils.extractTypeArg(ref, EntityCollection.class),
+            uri);
 
     this.uri = uri;
-    this.baseURI = uri == null ? null : uri.build();
-    this.itemRef = (Class<T>) itemRef;
-    this.collItemRef = collItemRef;
     this.targetEntitySetURI = targetEntitySetURI;
-  }
-
-  protected Class<T> getTypeRef() {
-    return this.itemRef;
-  }
-
-  protected URI getURI() {
-    return this.baseURI;
+    this.collItemRef = (Class<EC>) ref;
   }
 
   @SuppressWarnings("unchecked")
-  public <S extends T, SEC extends EntityCollection<S>> SEC fetchWholeEntitySet(
-          final CommonURIBuilder<?> uriBuilder, final Class<S> typeRef, final Class<SEC> collTypeRef) {
-
-    final List<S> items = new ArrayList<S>();
-    final List<ODataAnnotation> annotations = new ArrayList<ODataAnnotation>();
-
-    URI nextURI = uriBuilder.build();
-    while (nextURI != null) {
-      final Triple<List<S>, URI, List<ODataAnnotation>> entitySet = fetchPartialEntitySet(nextURI, typeRef);
-      items.addAll(entitySet.getLeft());
-      nextURI = entitySet.getMiddle();
-      annotations.addAll(entitySet.getRight());
-    }
-
-    final EntityCollectionInvocationHandler<S> entityCollectionHandler =
-            new EntityCollectionInvocationHandler<S>(service, items, typeRef, targetEntitySetURI, uriBuilder);
-    entityCollectionHandler.setAnnotations(annotations);
-
-    return (SEC) Proxy.newProxyInstance(
-            Thread.currentThread().getContextClassLoader(),
-            new Class<?>[] {collTypeRef},
-            entityCollectionHandler);
-  }
-
-  @SuppressWarnings("unchecked")
-  public <S extends T> Triple<List<S>, URI, List<ODataAnnotation>> fetchPartialEntitySet(
+  @Override
+  public <S extends T> Triple<List<S>, URI, List<ODataAnnotation>> fetchPartial(
           final URI uri, final Class<S> typeRef) {
 
     final List<CommonODataEntity> entities = new ArrayList<CommonODataEntity>();
     final URI next;
-    final List<ODataAnnotation> annotations = new ArrayList<ODataAnnotation>();
+    final List<ODataAnnotation> anns = new ArrayList<ODataAnnotation>();
 
     if (isSingleton) {
       final ODataRetrieveResponse<org.apache.olingo.commons.api.domain.v4.ODataSingleton> res =
@@ -157,11 +121,11 @@ public abstract class AbstractEntityCollectionInvocationHandler<
       entities.addAll(entitySet.getEntities());
       next = entitySet.getNext();
       if (entitySet instanceof ODataEntitySet) {
-        annotations.addAll(((ODataEntitySet) entitySet).getAnnotations());
+        anns.addAll(((ODataEntitySet) entitySet).getAnnotations());
       }
     }
 
-    final List<S> items = new ArrayList<S>(entities.size());
+    final List<S> res = new ArrayList<S>(entities.size());
 
     for (CommonODataEntity entity : entities) {
       final EntityInvocationHandler handler =
@@ -178,54 +142,12 @@ public abstract class AbstractEntityCollectionInvocationHandler<
 
       final EntityInvocationHandler handlerInTheContext = getContext().entityContext().getEntity(handler.getUUID());
 
-      items.add((S) Proxy.newProxyInstance(
+      res.add((S) Proxy.newProxyInstance(
               Thread.currentThread().getContextClassLoader(),
               new Class<?>[] {typeRef},
               handlerInTheContext == null ? handler : handlerInTheContext));
     }
 
-    return new ImmutableTriple<List<S>, URI, List<ODataAnnotation>>(items, next, annotations);
-  }
-
-  public void filter(final String filter) {
-    this.uri.filter(filter);
-  }
-
-  public void filter(final URIFilter filter) {
-    this.uri.filter(filter);
-  }
-
-  public void orderBy(final Sort... sort) {
-    final StringBuilder builder = new StringBuilder();
-    for (Sort sortClause : sort) {
-      builder.append(sortClause.getKey()).append(' ').append(sortClause.getValue()).append(',');
-    }
-    builder.deleteCharAt(builder.length() - 1);
-
-    this.uri.orderBy(builder.toString());
-  }
-
-  public void orderBy(final String orderBy) {
-    this.uri.orderBy(orderBy);
-  }
-
-  public void top(final int top) throws IllegalArgumentException {
-    this.uri.top(top);
-  }
-
-  public void skip(final int skip) throws IllegalArgumentException {
-    this.uri.skip(skip);
-  }
-
-  public void expand(final String... expand) {
-    this.uri.expand(expand);
-  }
-
-  public void select(final String... select) {
-    this.uri.select(select);
-  }
-
-  public void clearQueryOptions() {
-    this.uri = this.baseURI == null ? null : getClient().newURIBuilder(baseURI.toASCIIString());
+    return new ImmutableTriple<List<S>, URI, List<ODataAnnotation>>(res, next, anns);
   }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/acc5b5ce/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 5d8bc7b..a970123 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
@@ -55,6 +55,10 @@ import java.util.Arrays;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import org.apache.olingo.client.api.uri.CommonURIBuilder;
+import org.apache.olingo.ext.proxy.api.ComplexCollection;
+import org.apache.olingo.ext.proxy.api.ComplexType;
+import org.apache.olingo.ext.proxy.api.PrimitiveCollection;
 
 abstract class AbstractInvocationHandler implements InvocationHandler {
 
@@ -112,7 +116,7 @@ abstract class AbstractInvocationHandler implements InvocationHandler {
     return Proxy.newProxyInstance(
             Thread.currentThread().getContextClassLoader(),
             new Class<?>[] {typeCollectionRef},
-            new EntityCollectionInvocationHandler(service, items, typeRef, targetEntitySetURI,
+            new EntityCollectionInvocationHandler(service, items, typeCollectionRef, targetEntitySetURI,
             uri == null ? null : getClient().newURIBuilder(uri.toASCIIString())));
   }
 
@@ -241,11 +245,101 @@ abstract class AbstractInvocationHandler implements InvocationHandler {
                 false);
       }
     } else {
+      Object res;
+
+      Class<?> ref = ClassUtils.getTypeClass(method.getReturnType());
       final CommonODataProperty property = (CommonODataProperty) result;
-      return property == null || property.hasNullValue()
-              ? null
-              : CoreUtils.getObjectFromODataValue(property.getValue(), method.getGenericReturnType(), service);
+
+      if (property == null || property.hasNullValue()) {
+        res = null;
+      } else if (edmType.isCollection()) {
+        if (edmType.isComplexType()) {
+          final Class<?> itemRef = ClassUtils.extractTypeArg(ref, ComplexCollection.class);
+          final List items = new ArrayList();
+
+          for (ODataValue item : property.getValue().asCollection()) {
+            items.add(getComplex(
+                    property.getName(),
+                    item,
+                    itemRef,
+                    null,
+                    null,
+                    true));
+          }
+
+          res = Proxy.newProxyInstance(
+                  Thread.currentThread().getContextClassLoader(),
+                  new Class<?>[] {ref}, new ComplexCollectionInvocationHandler(
+                  service,
+                  items,
+                  itemRef,
+                  null));
+        } else {
+          final List items = new ArrayList();
+
+          for (ODataValue item : property.getValue().asCollection()) {
+            items.add(item.asPrimitive().toValue());
+          }
+
+          res = Proxy.newProxyInstance(
+                  Thread.currentThread().getContextClassLoader(),
+                  new Class<?>[] {PrimitiveCollection.class}, new PrimitiveCollectionInvocationHandler(
+                  service,
+                  items,
+                  null,
+                  null));
+        }
+      } else {
+        if (edmType.isComplexType()) {
+          res = getComplex(property.getName(), property.getValue().asComplex(), ref, null, null, false);
+        } else {
+          res = CoreUtils.getObjectFromODataValue(property.getValue(), method.getGenericReturnType(), service);
+        }
+      }
+
+      return res;
+    }
+  }
+
+  protected ComplexType getComplex(
+          final String name,
+          final ODataValue value,
+          final Class<?> ref,
+          final EntityInvocationHandler handler,
+          final URI baseURI,
+          final boolean collectionItem) {
+
+    final CommonURIBuilder<?> targetURI;
+    if (collectionItem) {
+      targetURI = null;
+    } else {
+      targetURI = baseURI == null
+              ? null : getClient().newURIBuilder(baseURI.toASCIIString()).appendPropertySegment(name);
+    }
+
+    final ComplexInvocationHandler complexHandler;
+    Class<?> actualRef = ref;
+    if (value == null) {
+      complexHandler = ComplexInvocationHandler.getInstance(
+              actualRef,
+              service,
+              targetURI);
+    } else {
+      actualRef = CoreUtils.getComplexTypeRef(value); // handle derived types
+      complexHandler = ComplexInvocationHandler.getInstance(
+              value.asComplex(),
+              actualRef,
+              service,
+              targetURI);
     }
+
+    complexHandler.setEntityHandler(handler);
+
+    final ComplexType res = ComplexType.class.cast(Proxy.newProxyInstance(
+            Thread.currentThread().getContextClassLoader(),
+            new Class<?>[] {actualRef}, complexHandler));
+
+    return res;
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/acc5b5ce/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ComplexCollectionInvocationHandler.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ComplexCollectionInvocationHandler.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ComplexCollectionInvocationHandler.java
new file mode 100644
index 0000000..0f0cf87
--- /dev/null
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ComplexCollectionInvocationHandler.java
@@ -0,0 +1,119 @@
+/*
+ * 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 org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.tuple.Triple;
+import org.apache.olingo.client.api.uri.CommonURIBuilder;
+import org.apache.olingo.commons.api.domain.v4.ODataAnnotation;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import org.apache.commons.lang3.tuple.ImmutableTriple;
+import org.apache.olingo.client.api.communication.request.retrieve.ODataPropertyRequest;
+import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse;
+import org.apache.olingo.commons.api.domain.ODataValue;
+import org.apache.olingo.commons.api.domain.v3.ODataProperty;
+import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
+import org.apache.olingo.ext.proxy.Service;
+import org.apache.olingo.ext.proxy.api.ComplexCollection;
+import org.apache.olingo.ext.proxy.api.ComplexType;
+
+public class ComplexCollectionInvocationHandler<T extends ComplexType>
+        extends AbstractCollectionInvocationHandler<T, ComplexCollection<T>>
+        implements ComplexCollection<T> {
+
+  private static final long serialVersionUID = 98078202642671756L;
+
+  public ComplexCollectionInvocationHandler(
+          final Service<?> service,
+          final Class<T> itemRef) {
+    this(service, new ArrayList<T>(), itemRef, null);
+  }
+
+  public ComplexCollectionInvocationHandler(
+          final Service<?> service,
+          final Class<T> itemRef,
+          final CommonURIBuilder<?> uri) {
+    this(service, new ArrayList<T>(), itemRef, uri);
+  }
+
+  public ComplexCollectionInvocationHandler(
+          final Service<?> service,
+          final Collection<T> items,
+          final Class<T> itemRef,
+          final CommonURIBuilder<?> uri) {
+
+    super(service, items, itemRef, uri);
+  }
+
+  @Override
+  public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
+    if ("filter".equals(method.getName())
+            || "orderBy".equals(method.getName())
+            || "top".equals(method.getName())
+            || "skip".equals(method.getName())
+            || "expand".equals(method.getName())
+            || "select".equals(method.getName())
+            || "nextPage".equals(method.getName())
+            || "execute".equals(method.getName())) {
+      invokeSelfMethod(method, args);
+      return proxy;
+    } else 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(this));
+    } else {
+      throw new NoSuchMethodException(method.getName());
+    }
+  }
+
+  @SuppressWarnings("unchecked")
+  @Override
+  public <S extends T> Triple<List<S>, URI, List<ODataAnnotation>> fetchPartial(final URI uri, final Class<S> typeRef) {
+    final ODataPropertyRequest<ODataProperty> req = getClient().getRetrieveRequestFactory().getPropertyRequest(uri);
+    if (getClient().getServiceVersion().compareTo(ODataServiceVersion.V30) > 0) {
+      req.setPrefer(getClient().newPreferences().includeAnnotations("*"));
+    }
+
+    final ODataRetrieveResponse<ODataProperty> res = req.execute();
+
+    List<S> resItems = new ArrayList<S>();
+
+    final ODataProperty property = res.getBody();
+    if (property != null && !property.hasNullValue()) {
+      for (ODataValue item : property.getCollectionValue()) {
+        resItems.add((S) getComplex(property.getName(), item, typeRef, null, null, true));
+      }
+    }
+
+    return new ImmutableTriple<List<S>, URI, List<ODataAnnotation>>(
+            resItems, null, Collections.<ODataAnnotation>emptyList());
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/acc5b5ce/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 c2781c7..671e47c 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
@@ -36,14 +36,20 @@ import org.apache.olingo.ext.proxy.utils.CoreUtils;
 
 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.List;
 import java.util.Set;
 import org.apache.olingo.client.api.communication.request.retrieve.ODataPropertyRequest;
 import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse;
 import org.apache.olingo.client.api.uri.CommonURIBuilder;
+import org.apache.olingo.commons.api.domain.ODataValue;
+import org.apache.olingo.ext.proxy.api.ComplexCollection;
+import org.apache.olingo.ext.proxy.api.EdmStreamType;
+import org.apache.olingo.ext.proxy.api.PrimitiveCollection;
 
 public class ComplexInvocationHandler extends AbstractStructuredInvocationHandler {
 
@@ -120,7 +126,7 @@ public class ComplexInvocationHandler extends AbstractStructuredInvocationHandle
 
     super(typeRef, complex, service);
     this.uri = uri;
-    this.baseURI = this.uri.build();
+    this.baseURI = this.uri == null ? null : this.uri.build();
   }
 
   private ComplexInvocationHandler(
@@ -147,12 +153,102 @@ public class ComplexInvocationHandler extends AbstractStructuredInvocationHandle
   }
 
   @Override
+  @SuppressWarnings({"unchecked", "rawtypes"})
   protected Object getPropertyValue(final String name, final Type type) {
     try {
-      final CommonODataProperty property = getComplex().get(name);
-      return property == null || property.hasNullValue()
-              ? null
-              : CoreUtils.getObjectFromODataValue(property.getValue(), type, service);
+      Object res;
+      Class<?> ref = ClassUtils.getTypeClass(type);
+
+      if (ref == EdmStreamType.class) {
+        res = Proxy.newProxyInstance(
+                Thread.currentThread().getContextClassLoader(),
+                new Class<?>[] {EdmStreamType.class}, new EdmStreamTypeHandler(
+                getClient().newURIBuilder(baseURI.toASCIIString()).appendPropertySegment(name),
+                service));
+
+        return res;
+      } else {
+
+        final CommonODataProperty property = getComplex().get(name);
+
+        if (ref != null && ClassUtils.getTypeClass(type).isAnnotationPresent(ComplexType.class)) {
+          res = getComplex(
+                  name,
+                  property == null || property.hasNullValue() ? null : property.getValue(),
+                  ref,
+                  entityHandler,
+                  baseURI,
+                  false);
+        } else if (ref != null && ComplexCollection.class.isAssignableFrom(ref)) {
+
+          final ComplexCollectionInvocationHandler<?> collectionHandler;
+          final Class<?> itemRef = ClassUtils.extractTypeArg(ref, ComplexCollection.class);
+
+          if (property == null || property.hasNullValue()) {
+            collectionHandler = new ComplexCollectionInvocationHandler(
+                    service,
+                    itemRef,
+                    baseURI == null
+                    ? null : getClient().newURIBuilder(baseURI.toASCIIString()).appendPropertySegment(name));
+          } else {
+            List items = new ArrayList();
+
+            for (ODataValue item : property.getValue().asCollection()) {
+              items.add(getComplex(
+                      name,
+                      item,
+                      itemRef,
+                      entityHandler,
+                      baseURI,
+                      true));
+            }
+
+            collectionHandler = new ComplexCollectionInvocationHandler(
+                    service,
+                    items,
+                    itemRef,
+                    baseURI == null
+                    ? null : getClient().newURIBuilder(baseURI.toASCIIString()).appendPropertySegment(name));
+          }
+
+          res = Proxy.newProxyInstance(
+                  Thread.currentThread().getContextClassLoader(),
+                  new Class<?>[] {ref}, collectionHandler);
+
+        } else if (ref != null && PrimitiveCollection.class.isAssignableFrom(ref)) {
+          final PrimitiveCollectionInvocationHandler collectionHandler;
+//          Class<?> itemRef = ref.getMethod("reference").getReturnType();
+
+          if (property == null || property.hasNullValue()) {
+            collectionHandler = new PrimitiveCollectionInvocationHandler(
+                    service,
+                    null,
+                    baseURI == null
+                    ? null : getClient().newURIBuilder(baseURI.toASCIIString()).appendPropertySegment(name));
+          } else {
+            List items = new ArrayList();
+            for (ODataValue item : property.getValue().asCollection()) {
+              items.add(item.asPrimitive().toValue());
+            }
+            collectionHandler = new PrimitiveCollectionInvocationHandler(
+                    service,
+                    items,
+                    null,
+                    baseURI == null
+                    ? null : getClient().newURIBuilder(baseURI.toASCIIString()).appendPropertySegment(name));
+          }
+
+          res = Proxy.newProxyInstance(
+                  Thread.currentThread().getContextClassLoader(),
+                  new Class<?>[] {PrimitiveCollection.class}, collectionHandler);
+        } else {
+          res = property == null || property.hasNullValue()
+                  ? null
+                  : CoreUtils.getObjectFromODataValue(property.getValue(), type, service);
+        }
+
+        return res;
+      }
     } catch (Exception e) {
       throw new IllegalArgumentException("Error getting value for property '" + name + "'", e);
     }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/acc5b5ce/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 7b74b33..168ff3a 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
@@ -19,70 +19,39 @@
 package org.apache.olingo.ext.proxy.commons;
 
 import org.apache.commons.lang3.ArrayUtils;
-import org.apache.commons.lang3.tuple.Triple;
 import org.apache.olingo.client.api.uri.CommonURIBuilder;
-import org.apache.olingo.commons.api.domain.v4.ODataAnnotation;
 import org.apache.olingo.ext.proxy.api.EntityCollection;
-import org.apache.olingo.ext.proxy.api.AbstractTerm;
-import org.apache.olingo.ext.proxy.api.StructuredType;
-import org.apache.olingo.ext.proxy.api.annotations.Namespace;
-import org.apache.olingo.ext.proxy.api.annotations.Term;
-import org.apache.olingo.ext.proxy.utils.CoreUtils;
 
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
 import java.net.URI;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
 import org.apache.olingo.ext.proxy.Service;
+import org.apache.olingo.ext.proxy.api.EntityType;
 
-public class EntityCollectionInvocationHandler<T extends StructuredType>
+public class EntityCollectionInvocationHandler<T extends EntityType>
         extends AbstractEntityCollectionInvocationHandler<T, EntityCollection<T>>
         implements EntityCollection<T> {
 
   private static final long serialVersionUID = 98078202642671726L;
 
-  protected URI nextPageURI = null;
-
-  private Collection<T> items;
-
-  private final List<ODataAnnotation> annotations = new ArrayList<ODataAnnotation>();
-
-  private final Map<Class<? extends AbstractTerm>, Object> annotationsByTerm =
-          new HashMap<Class<? extends AbstractTerm>, Object>();
-
   public EntityCollectionInvocationHandler(
-          final Service<?> service,
-          final Collection<T> items,
-          final Class<T> itemRef) {
-    this(service, items, itemRef, null, null);
+          final Service<?> service, final Class<? extends EntityCollection<T>> collItemRef) {
+    this(service, new ArrayList<T>(), collItemRef, null, null);
   }
 
-  public EntityCollectionInvocationHandler(
+  public <EC extends EntityCollection<T>> EntityCollectionInvocationHandler(
           final Service<?> service,
           final Collection<T> items,
-          final Class<T> itemRef,
+          final Class<? extends EntityCollection<T>> collItemRef,
           final URI targetEntitySetURI,
           final CommonURIBuilder<?> uri) {
 
-    super(itemRef, null, service, targetEntitySetURI, uri);
+    super(collItemRef, service, targetEntitySetURI, uri);
     this.items = items;
   }
 
-  public void setAnnotations(final List<ODataAnnotation> annotations) {
-    this.annotations.clear();
-    this.annotationsByTerm.clear();
-    this.annotations.addAll(annotations);
-  }
-
-  public Class<?> getEntityReference() {
-    return itemRef;
-  }
-
   @Override
   public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
     if ("filter".equals(method.getName())
@@ -108,148 +77,4 @@ public class EntityCollectionInvocationHandler<T extends StructuredType>
       throw new NoSuchMethodException(method.getName());
     }
   }
-
-  public void nextPage() {
-    if (!hasNextPage()) {
-      throw new IllegalStateException("Next page URI not found");
-    }
-    this.uri = getClient().newURIBuilder(nextPageURI.toASCIIString());
-  }
-
-  public boolean hasNextPage() {
-    return this.nextPageURI != null;
-  }
-
-  void setNextPage(final URI next) {
-    this.nextPageURI = next;
-  }
-
-  @SuppressWarnings("unchecked")
-  public EntityCollection<T> execute() {
-    if (this.uri != null) {
-      final Triple<List<T>, URI, List<ODataAnnotation>> entitySet = fetchPartialEntitySet(this.uri.build(), itemRef);
-      this.nextPageURI = entitySet.getMiddle();
-
-      if (items == null) {
-        items = entitySet.getLeft();
-      } else {
-        items.clear();
-        items.addAll(entitySet.getLeft());
-      }
-
-      annotations.clear();
-      annotations.addAll(entitySet.getRight());
-    }
-
-    return this;
-  }
-
-  @Override
-  public int size() {
-    return items.size();
-  }
-
-  @Override
-  public boolean isEmpty() {
-    return items.isEmpty();
-  }
-
-  @Override
-  public boolean contains(final Object object) {
-    return items.contains(object);
-  }
-
-  @Override
-  public Iterator<T> iterator() {
-    return items.iterator();
-  }
-
-  @Override
-  public Object[] toArray() {
-    return items.toArray();
-  }
-
-  @Override
-  public <T> T[] toArray(final T[] array) {
-    return items.toArray(array);
-  }
-
-  @Override
-  public boolean add(final T element) {
-    final EntityInvocationHandler handler = EntityInvocationHandler.class.cast(Proxy.getInvocationHandler(element));
-    if (!service.getContext().entityContext().isAttached(handler) && baseURI != null) {
-      handler.updateUUID(baseURI, itemRef, null);
-      service.getContext().entityContext().attachNew(handler);
-    }
-    return items.add(element);
-  }
-
-  @Override
-  public boolean remove(final Object object) {
-    return items.remove(object);
-  }
-
-  @Override
-  public boolean containsAll(final Collection<?> collection) {
-    return items.containsAll(collection);
-  }
-
-  @Override
-  public boolean addAll(final Collection<? extends T> collection) {
-    return items.addAll(collection);
-  }
-
-  @Override
-  public boolean removeAll(final Collection<?> collection) {
-    return items.removeAll(collection);
-  }
-
-  @Override
-  public boolean retainAll(final Collection<?> collection) {
-    return items.retainAll(collection);
-  }
-
-  @Override
-  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(annotation.getValue(), null, service);
-        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);
-  }
-
-  @Override
-  public void clearQueryOptions() {
-    super.clearQueryOptions();
-    this.nextPageURI = null;
-  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/acc5b5ce/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 3a15f17..340a4a5 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
@@ -96,13 +96,13 @@ public final class EntityContainerInvocationHandler extends AbstractInvocationHa
           return Proxy.newProxyInstance(
                   Thread.currentThread().getContextClassLoader(),
                   new Class<?>[] {returnType},
-                  SingletonInvocationHandler.getInstance(returnType, service, singleton.name()));
+                  SingletonInvocationHandler.getInstance(returnType, service));
         }
       } else {
         return Proxy.newProxyInstance(
                 Thread.currentThread().getContextClassLoader(),
                 new Class<?>[] {returnType},
-                EntitySetInvocationHandler.getInstance(returnType, service, entitySet.name()));
+                EntitySetInvocationHandler.getInstance(returnType, service));
       }
 
       throw new NoSuchMethodException(method.getName());

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/acc5b5ce/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 fdcf6eb..319ed1b 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
@@ -53,16 +53,21 @@ import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
 import java.lang.reflect.Type;
 import java.net.URI;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeSet;
+import org.apache.olingo.commons.api.domain.ODataValue;
+import org.apache.olingo.ext.proxy.api.ComplexCollection;
 import org.apache.olingo.ext.proxy.api.EdmStreamType;
 import org.apache.olingo.ext.proxy.api.EdmStreamValue;
+import org.apache.olingo.ext.proxy.api.PrimitiveCollection;
 import org.apache.olingo.ext.proxy.api.annotations.ComplexType;
 import org.apache.olingo.ext.proxy.utils.ClassUtils;
 
@@ -314,10 +319,12 @@ public class EntityInvocationHandler extends AbstractStructuredInvocationHandler
   }
 
   @Override
+  @SuppressWarnings({"unchecked", "rawtypes"})
   protected Object getPropertyValue(final String name, final Type type) {
     try {
       Object res;
       Class<?> ref = ClassUtils.getTypeClass(type);
+
       if (ref == EdmStreamType.class) {
         if (streamedPropertyCache.containsKey(name)) {
           res = streamedPropertyCache.get(name);
@@ -335,41 +342,87 @@ public class EntityInvocationHandler extends AbstractStructuredInvocationHandler
 
         return res;
       } else {
-        final CommonODataProperty property = getEntity().getProperty(name);
 
         if (propertyChanges.containsKey(name)) {
           res = propertyChanges.get(name);
-        } else if (ref != null && ClassUtils.getTypeClass(type).isAnnotationPresent(ComplexType.class)) {
+        } else {
+          final CommonODataProperty property = getEntity().getProperty(name);
 
-          final ComplexInvocationHandler complexHandler;
-          if (property == null || property.hasNullValue()) {
-            complexHandler = ComplexInvocationHandler.getInstance(
-                    ref,
-                    service,
-                    getClient().newURIBuilder(baseURI.toASCIIString()).appendPropertySegment(name));
-          } else {
-            ref = CoreUtils.getComplexTypeRef(property.getValue()); // handle derived types
-            complexHandler = ComplexInvocationHandler.getInstance(
-                    property.getValue().asComplex(),
+          if (ref != null && ClassUtils.getTypeClass(type).isAnnotationPresent(ComplexType.class)) {
+            res = getComplex(
+                    name,
+                    property == null || property.hasNullValue() ? null : property.getValue(),
                     ref,
-                    service,
-                    getClient().newURIBuilder(baseURI.toASCIIString()).appendPropertySegment(name));
-          }
+                    this,
+                    baseURI,
+                    false);
+            addPropertyChanges(name, res);
+          } else if (ref != null && ComplexCollection.class.isAssignableFrom(ref)) {
+
+            final ComplexCollectionInvocationHandler<?> collectionHandler;
+            final Class<?> itemRef = ClassUtils.extractTypeArg(ref, ComplexCollection.class);
+
+            if (property == null || property.hasNullValue()) {
+              collectionHandler = new ComplexCollectionInvocationHandler(
+                      service,
+                      itemRef,
+                      getClient().newURIBuilder(baseURI.toASCIIString()).appendPropertySegment(name));
+            } else {
+              List items = new ArrayList();
+
+              for (ODataValue item : property.getValue().asCollection()) {
+                items.add(getComplex(
+                        name,
+                        item,
+                        itemRef,
+                        this,
+                        baseURI,
+                        true));
+              }
+
+              collectionHandler = new ComplexCollectionInvocationHandler(
+                      service,
+                      items,
+                      itemRef,
+                      getClient().newURIBuilder(baseURI.toASCIIString()).appendPropertySegment(name));
+            }
 
-          complexHandler.setEntityHandler(this);
+            res = Proxy.newProxyInstance(
+                    Thread.currentThread().getContextClassLoader(),
+                    new Class<?>[] {ref}, collectionHandler);
 
-          res = Proxy.newProxyInstance(
-                  Thread.currentThread().getContextClassLoader(),
-                  new Class<?>[] {ref}, complexHandler);
+            addPropertyChanges(name, res);
+          } else if (ref != null && PrimitiveCollection.class.isAssignableFrom(ref)) {
+            final PrimitiveCollectionInvocationHandler collectionHandler;
+//            Class<?> itemRef = ClassUtils.extractTypeArg(ref, Collection.class);
+            if (property == null || property.hasNullValue()) {
+              collectionHandler = new PrimitiveCollectionInvocationHandler(
+                      service,
+                      null,
+                      getClient().newURIBuilder(baseURI.toASCIIString()).appendPropertySegment(name));
+            } else {
+              List items = new ArrayList();
+              for (ODataValue item : property.getValue().asCollection()) {
+                items.add(item.asPrimitive().toValue());
+              }
+              collectionHandler = new PrimitiveCollectionInvocationHandler(
+                      service,
+                      items,
+                      null,
+                      getClient().newURIBuilder(baseURI.toASCIIString()).appendPropertySegment(name));
+            }
 
-          addPropertyChanges(name, res);
-        } else {
-          res = property == null || property.hasNullValue()
-                  ? null
-                  : CoreUtils.getObjectFromODataValue(property.getValue(), type, service);
+            res = Proxy.newProxyInstance(
+                    Thread.currentThread().getContextClassLoader(),
+                    new Class<?>[] {PrimitiveCollection.class}, collectionHandler);
+          } else {
+            res = property == null || property.hasNullValue()
+                    ? null
+                    : CoreUtils.getObjectFromODataValue(property.getValue(), type, service);
 
-          if (res != null) {
-            addPropertyChanges(name, res);
+            if (res != null) {
+              addPropertyChanges(name, res);
+            }
           }
         }