[OLINGO-231] Merge with 2.0.0 version

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

Branch: refs/heads/OLINGO-231_PocForAndroid
Commit: 46d83c8e6f68a9390928acfd559cb79199e6fbbb
Parents: cb1ba46
Author: mibo <[email protected]>
Authored: Wed Jul 20 21:05:52 2016 +0200
Committer: mibo <[email protected]>
Committed: Wed Jul 20 21:05:52 2016 +0200

----------------------------------------------------------------------
 .../annotation-processor-api/pom.xml            |   2 +-
 .../annotation-processor-core/pom.xml           |   2 +-
 .../processor/core/ListsProcessor.java          |  11 +-
 .../core/datasource/BeanPropertyAccess.java     |   8 +-
 .../core/datasource/BeanPropertyAccessTest.java |   2 +-
 .../processor/core/util/ClassHelperTest.java    |   2 +-
 .../annotation-processor-ref/pom.xml            |   2 +-
 .../annotation-processor-web/pom.xml            |   2 +-
 odata2-annotation-processor/pom.xml             |   2 +-
 odata2-dist/janos/pom.xml                       |   2 +-
 odata2-dist/javadoc/pom.xml                     |   2 +-
 odata2-dist/jpa/pom.xml                         |   2 +-
 odata2-dist/lib/pom.xml                         |   2 +-
 odata2-dist/pom.xml                             |   2 +-
 odata2-dist/ref/pom.xml                         |   2 +-
 odata2-jpa-processor/jpa-api/pom.xml            |   2 +-
 .../jpa/processor/api/ODataJPAProcessor.java    |   8 +
 .../processor/api/ODataJPATombstoneContext.java |  90 +++++
 .../api/ODataJPATombstoneEntityListener.java    |  60 ++++
 .../api/exception/ODataJPAErrorCallback.java    |   2 +-
 .../api/model/JPAEdmAssociationEndView.java     |   4 +-
 .../processor/api/model/JPAEdmExtension.java    |   9 +
 .../jpa/processor/api/model/JPAEdmMapping.java  |  16 +
 .../processor/api/model/JPAEdmPropertyView.java |   8 +
 odata2-jpa-processor/jpa-core/pom.xml           |   2 +-
 .../core/ODataJPAProcessorDefault.java          |  45 ++-
 .../core/ODataJPAResponseBuilderDefault.java    |  27 +-
 .../processor/core/access/data/JPAEntity.java   |   5 +
 .../core/access/data/JPAEntityParser.java       |  10 +
 .../core/access/data/JPAExpandCallBack.java     | 221 ------------
 .../jpa/processor/core/access/data/JPAPage.java |  81 ++++-
 .../core/access/data/JPAProcessorImpl.java      |  96 ++++-
 .../core/access/model/EdmTypeConvertor.java     |  69 ----
 .../access/model/JPAEdmMappingModelService.java |  14 +-
 .../core/access/model/JPAEdmNameBuilder.java    |  10 +-
 .../core/access/model/JPATypeConvertor.java     |   6 +-
 .../core/callback/JPAExpandCallBack.java        | 222 ++++++++++++
 .../core/callback/JPATombstoneCallBack.java     |  60 ++++
 .../processor/core/model/JPAEdmAssociation.java |  13 +-
 .../core/model/JPAEdmAssociationEnd.java        |  33 +-
 .../processor/core/model/JPAEdmEntityType.java  |  18 +
 .../processor/core/model/JPAEdmMappingImpl.java |  13 +
 .../processor/core/model/JPAEdmProperty.java    |  62 +++-
 .../model/JPAEdmReferentialConstraintRole.java  |  80 +----
 .../core/ODataJPAResponseBuilderTest.java       |   2 +-
 .../JPAEntityParserForStaticMethodTest.java     | 330 +++++++++++++++++
 .../JPAEntityParserTestForStaticMethods.java    | 330 -----------------
 .../core/access/data/JPAExpandCallBackTest.java |   1 +
 .../access/data/JPAPageBuilderDeltaTest.java    | 357 +++++++++++++++++++
 .../core/access/data/JPAPageBuilderTest.java    |  19 +-
 .../core/access/data/JPAProcessorImplTest.java  |  12 +-
 .../access/model/JPAEdmNameBuilderTest.java     |   4 +-
 .../core/model/JPAEdmAssociationTest.java       |  23 +-
 .../core/model/JPAEdmEntityContainerTest.java   |   5 +
 .../core/model/JPAEdmEntitySetTest.java         |   5 +
 .../core/model/JPAEdmEntityTypeTest.java        |   5 +
 .../JPAEdmReferentialConstraintRoleTest.java    |  13 +
 .../model/JPAEdmReferentialConstraintTest.java  |  14 +
 .../core/model/JPAEdmTestModelView.java         |  10 +-
 odata2-jpa-processor/jpa-ref/pom.xml            |   9 +-
 .../ref/converter/BlobToByteConverter.java      |   6 +
 .../SalesOrderItemTombstoneListener.java        |  93 +++++
 .../listeners/SalesOrderTombstoneListener.java  |  57 +++
 .../jpa/processor/ref/model/Category.java       |  12 +
 .../jpa/processor/ref/model/Customer.java       |  12 +
 .../jpa/processor/ref/model/Material.java       |   9 +-
 .../processor/ref/model/SalesOrderHeader.java   |  25 +-
 .../jpa/processor/ref/model/SalesOrderItem.java |   4 +-
 odata2-jpa-processor/jpa-web/pom.xml            |   2 +-
 .../SalesOrderProcessingExtension.java          |   6 +
 .../ref/web/JPAReferenceServiceFactory.java     |   1 +
 .../resources/SQL_Insert_Category.properties    |   8 +-
 .../resources/SQL_Insert_Customer.properties    |  10 +-
 .../resources/SQL_Insert_Material.properties    |  22 +-
 .../SQL_Insert_SalesOrderHeader.properties      |  22 +-
 odata2-jpa-processor/pom.xml                    |   2 +-
 odata2-lib/odata-annotation/pom.xml             |   2 +-
 odata2-lib/odata-api/pom.xml                    |   2 +-
 .../olingo/odata2/api/edm/EdmMapping.java       |   9 -
 .../olingo/odata2/api/edm/provider/Mapping.java |  18 -
 .../api/ep/EntityProviderWriteProperties.java   |  48 ++-
 .../odata2/api/processor/ODataResponse.java     |  14 +
 odata2-lib/odata-core/pom.xml                   |   2 +-
 .../olingo/odata2/core/ODataRequestImpl.java    |  41 ++-
 .../olingo/odata2/core/batch/AcceptParser.java  |   7 +-
 .../odata2/core/batch/BatchRequestParser.java   |  34 +-
 .../odata2/core/batch/BatchRequestWriter.java   |   2 +-
 .../odata2/core/batch/BatchResponseParser.java  |  16 +-
 .../olingo/odata2/core/edm/EdmBinary.java       |  17 +-
 .../edm/provider/EdmAssociationImplProv.java    |  11 +-
 .../edm/provider/EdmFunctionImportImplProv.java |  11 +-
 .../odata2/core/ep/BasicEntityProvider.java     |   6 +-
 .../core/ep/consumer/JsonEntryConsumer.java     |   1 -
 .../core/ep/consumer/JsonPropertyConsumer.java  |  12 +
 .../core/ep/consumer/XmlEntityConsumer.java     |   2 +-
 .../core/ep/consumer/XmlEntryConsumer.java      |  20 +-
 .../core/ep/consumer/XmlFeedConsumer.java       |   2 +-
 .../core/ep/consumer/XmlMetadataConsumer.java   |   5 +-
 .../ep/producer/AtomEntryEntityProducer.java    |  95 +++--
 .../ep/producer/JsonEntryEntityProducer.java    |  79 ++--
 .../ep/producer/XmlPropertyEntityProducer.java  |   4 +-
 .../core/rest/ODataExceptionMapperImpl.java     |  13 +-
 .../odata2/core/servlet/ODataServlet.java       |  23 +-
 .../olingo/odata2/core/servlet/RestUtil.java    |   1 +
 .../src/main/resources/i18n_en.properties       |   2 +-
 .../olingo/odata2/core/ODataRequestTest.java    |  77 ++++
 .../olingo/odata2/core/ODataResponseTest.java   |  17 +
 .../odata2/core/batch/BatchRequestTest.java     |  26 +-
 .../core/batch/BatchRequestWriterTest.java      |  20 +-
 .../odata2/core/batch/BatchResponseTest.java    |  17 +-
 .../odata2/core/edm/EdmSimpleTypeTest.java      |  12 +-
 .../provider/EdmAssociationImplProvTest.java    |  12 +-
 .../provider/EdmFunctionImportImplProvTest.java |   6 +-
 .../core/edm/provider/EdmMappingTest.java       |   5 +-
 .../edm/provider/EdmPropertyImplProvTest.java   |   3 +-
 .../odata2/core/ep/AbstractProviderTest.java    |   1 +
 .../ep/ODataEntityProviderPropertiesTest.java   |  22 +-
 .../core/ep/consumer/JsonEntryConsumerTest.java |  97 +++++
 .../consumer/JsonEntryDeepInsertEntryTest.java  |   2 +
 .../core/ep/consumer/JsonFeedConsumerTest.java  |   2 +
 .../ep/consumer/JsonPropertyConsumerTest.java   |  12 +
 .../core/ep/consumer/XmlEntityConsumerTest.java |  84 ++++-
 .../core/ep/consumer/XmlFeedConsumerTest.java   |  27 ++
 .../ep/consumer/XmlMetadataConsumerTest.java    |  81 ++++-
 .../core/ep/producer/AtomEntryProducerTest.java | 350 ++++++++++++++++--
 .../core/ep/producer/AtomFeedProducerTest.java  |  16 +-
 .../producer/JsonEntryEntityProducerTest.java   | 252 ++++++++++---
 .../ep/producer/JsonFeedEntityProducerTest.java |  33 ++
 .../core/rest/ODataExceptionMapperImplTest.java |   4 +-
 .../odata2/core/servlet/ODataServletTest.java   | 114 ++++++
 .../src/test/resources/EmployeeContentOnly.xml  |  37 ++
 .../EmployeeContentOnlyWithAdditionalLink.xml   |  38 ++
 .../test/resources/JsonEmployeeContentOnly.json |  25 ++
 ...onEmployeeContentOnlyWithAdditionalLink.json |  30 ++
 .../odata-core/src/test/resources/JsonRoom.json |  24 ++
 .../src/test/resources/JsonRoomContentOnly.json |   8 +
 .../JsonRoomContentOnlyWithAdditionalLink.json  |  13 +
 .../src/test/resources/RoomContentOnly.xml      |  28 ++
 .../RoomContentOnlyWithAdditionalLink.xml       |  29 ++
 .../src/test/resources/feed_rooms_small.xml     |  69 ++++
 odata2-lib/odata-fit/pom.xml                    |   2 +-
 .../olingo/odata2/fit/basic/BasicHttpTest.java  |   4 +-
 .../olingo/odata2/fit/basic/UrlRewriteTest.java |   2 +-
 odata2-lib/odata-ref/pom.xml                    |   2 +-
 .../odata2/ref/edm/ScenarioEdmProvider.java     |  15 +-
 .../ref/processor/BeanPropertyAccess.java       |   8 +-
 .../odata2/ref/processor/ListsProcessor.java    |  11 +-
 odata2-lib/odata-testutil/pom.xml               |   2 +-
 .../odata2/testutil/helper/StringHelper.java    |  32 +-
 .../olingo/odata2/testutil/mock/EdmMock.java    |   6 +-
 .../odata2/testutil/mock/EdmTestProvider.java   |   8 +-
 odata2-lib/odata-web/pom.xml                    |   2 +-
 odata2-lib/pom.xml                              |   2 +-
 odata2-sample/cars-annotation-archetype/pom.xml |   4 +-
 .../main/resources/archetype-resources/pom.xml  |   2 +-
 odata2-sample/cars-jpa-archetype/pom.xml        |   2 +-
 .../main/resources/archetype-resources/pom.xml  |   2 +-
 odata2-sample/cars-service-archetype/pom.xml    |   4 +-
 .../main/resources/archetype-resources/pom.xml  |   2 +-
 odata2-sample/pom.xml                           |   4 +-
 pom.xml                                         |   2 +-
 161 files changed, 3677 insertions(+), 1294 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/46d83c8e/odata2-annotation-processor/annotation-processor-api/pom.xml
----------------------------------------------------------------------
diff --git a/odata2-annotation-processor/annotation-processor-api/pom.xml 
b/odata2-annotation-processor/annotation-processor-api/pom.xml
index b0c3bdb..1b39e30 100644
--- a/odata2-annotation-processor/annotation-processor-api/pom.xml
+++ b/odata2-annotation-processor/annotation-processor-api/pom.xml
@@ -25,7 +25,7 @@
   <parent>
     <groupId>org.apache.olingo</groupId>
     <artifactId>olingo-odata2-annotation-processor</artifactId>
-    <version>1.3.0-SNAPSHOT</version>
+    <version>2.0.0</version>
     <relativePath>..</relativePath>
   </parent>
 

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/46d83c8e/odata2-annotation-processor/annotation-processor-core/pom.xml
----------------------------------------------------------------------
diff --git a/odata2-annotation-processor/annotation-processor-core/pom.xml 
b/odata2-annotation-processor/annotation-processor-core/pom.xml
index c91fba4..d367282 100644
--- a/odata2-annotation-processor/annotation-processor-core/pom.xml
+++ b/odata2-annotation-processor/annotation-processor-core/pom.xml
@@ -20,7 +20,7 @@
   <parent>
     <groupId>org.apache.olingo</groupId>
     <artifactId>olingo-odata2-annotation-processor</artifactId>
-    <version>1.3.0-SNAPSHOT</version>
+    <version>2.0.0</version>
     <relativePath>..</relativePath>
   </parent>
 

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/46d83c8e/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/ListsProcessor.java
----------------------------------------------------------------------
diff --git 
a/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/ListsProcessor.java
 
b/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/ListsProcessor.java
index 2c18668..a03136b 100644
--- 
a/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/ListsProcessor.java
+++ 
b/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/ListsProcessor.java
@@ -567,7 +567,7 @@ public class ListsProcessor extends DataSourceProcessor {
     final List<EdmProperty> propertyPath = uriInfo.getPropertyPath();
     final EdmProperty property = propertyPath.get(propertyPath.size() - 1);
     final Object value = property.isSimple() ?
-        property.getMapping() == null || property.getMapping().getMimeType() 
== null ?
+        property.getMapping() == null || 
property.getMapping().getMediaResourceMimeTypeKey() == null ?
             getPropertyValue(data, propertyPath) : getSimpleTypeValueMap(data, 
propertyPath) :
         getStructuralTypeValueMap(getPropertyValue(data, propertyPath), 
(EdmStructuralType) property.getType());
 
@@ -604,7 +604,7 @@ public class ListsProcessor extends DataSourceProcessor {
 
     final List<EdmProperty> propertyPath = uriInfo.getPropertyPath();
     final EdmProperty property = propertyPath.get(propertyPath.size() - 1);
-    final Object value = property.getMapping() == null || 
property.getMapping().getMimeType() == null ?
+    final Object value = property.getMapping() == null || 
property.getMapping().getMediaResourceMimeTypeKey() == null ?
         getPropertyValue(data, propertyPath) : getSimpleTypeValueMap(data, 
propertyPath);
 
     return 
ODataResponse.fromResponse(EntityProvider.writePropertyValue(property, 
value)).eTag(
@@ -1506,13 +1506,10 @@ public class ListsProcessor extends DataSourceProcessor 
{
 
   private void handleMimeType(final Object data, final EdmMapping mapping, 
final Map<String, Object> valueMap)
       throws ODataException {
-    final String mimeTypeName = mapping.getMimeType();
+    final String mimeTypeName = mapping.getMediaResourceMimeTypeKey();
     if (mimeTypeName != null) {
       Object value = valueAccess.getMappingValue(data, mapping);
       valueMap.put(mimeTypeName, value);
-      if (mapping.getMediaResourceMimeTypeKey() != null) {
-        valueMap.put(mapping.getMediaResourceMimeTypeKey(), value);
-      }
     }
   }
 
@@ -1543,7 +1540,7 @@ public class ListsProcessor extends DataSourceProcessor {
       final Object value = valueAccess.getPropertyValue(data, property);
 
       if (property.isSimple()) {
-        if (property.getMapping() == null || 
property.getMapping().getMimeType() == null) {
+        if (property.getMapping() == null || 
property.getMapping().getMediaResourceMimeTypeKey() == null) {
           valueMap.put(propertyName, value);
         } else {
           // TODO: enable MIME type mapping outside the current subtree

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/46d83c8e/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/BeanPropertyAccess.java
----------------------------------------------------------------------
diff --git 
a/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/BeanPropertyAccess.java
 
b/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/BeanPropertyAccess.java
index 290b99f..cd88b81 100644
--- 
a/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/BeanPropertyAccess.java
+++ 
b/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/BeanPropertyAccess.java
@@ -55,16 +55,16 @@ public class BeanPropertyAccess implements ValueAccess {
 
   @Override
   public <T> Object getMappingValue(final T data, final EdmMapping mapping) 
throws ODataException {
-    if (mapping != null && mapping.getMimeType() != null) {
-      return getValue(data, mapping.getMimeType());
+    if (mapping != null && mapping.getMediaResourceMimeTypeKey() != null) {
+      return getValue(data, mapping.getMediaResourceMimeTypeKey());
     }
     return null;
   }
 
   @Override
   public <T, V> void setMappingValue(final T data, final EdmMapping mapping, 
final V value) throws ODataException {
-    if (mapping != null && mapping.getMimeType() != null) {
-      setValue(data, getSetterMethodName(mapping.getMimeType()), value);
+    if (mapping != null && mapping.getMediaResourceMimeTypeKey() != null) {
+      setValue(data, 
getSetterMethodName(mapping.getMediaResourceMimeTypeKey()), value);
     }
   }
 

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/46d83c8e/odata2-annotation-processor/annotation-processor-core/src/test/java/org/apache/olingo/odata2/annotation/processor/core/datasource/BeanPropertyAccessTest.java
----------------------------------------------------------------------
diff --git 
a/odata2-annotation-processor/annotation-processor-core/src/test/java/org/apache/olingo/odata2/annotation/processor/core/datasource/BeanPropertyAccessTest.java
 
b/odata2-annotation-processor/annotation-processor-core/src/test/java/org/apache/olingo/odata2/annotation/processor/core/datasource/BeanPropertyAccessTest.java
index 9d25e0a..76e0cb4 100644
--- 
a/odata2-annotation-processor/annotation-processor-core/src/test/java/org/apache/olingo/odata2/annotation/processor/core/datasource/BeanPropertyAccessTest.java
+++ 
b/odata2-annotation-processor/annotation-processor-core/src/test/java/org/apache/olingo/odata2/annotation/processor/core/datasource/BeanPropertyAccessTest.java
@@ -234,7 +234,7 @@ public class BeanPropertyAccessTest {
 
   private EdmMapping mockMapping(final String mimeTypeKey) throws EdmException 
{
     EdmMapping mapping = Mockito.mock(EdmMapping.class);
-    Mockito.when(mapping.getMimeType()).thenReturn(mimeTypeKey);
+    
Mockito.when(mapping.getMediaResourceMimeTypeKey()).thenReturn(mimeTypeKey);
     return mapping;
   }
 

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/46d83c8e/odata2-annotation-processor/annotation-processor-core/src/test/java/org/apache/olingo/odata2/annotation/processor/core/util/ClassHelperTest.java
----------------------------------------------------------------------
diff --git 
a/odata2-annotation-processor/annotation-processor-core/src/test/java/org/apache/olingo/odata2/annotation/processor/core/util/ClassHelperTest.java
 
b/odata2-annotation-processor/annotation-processor-core/src/test/java/org/apache/olingo/odata2/annotation/processor/core/util/ClassHelperTest.java
index 4da0960..bcd955a 100644
--- 
a/odata2-annotation-processor/annotation-processor-core/src/test/java/org/apache/olingo/odata2/annotation/processor/core/util/ClassHelperTest.java
+++ 
b/odata2-annotation-processor/annotation-processor-core/src/test/java/org/apache/olingo/odata2/annotation/processor/core/util/ClassHelperTest.java
@@ -64,7 +64,7 @@ public class ClassHelperTest {
   @Test(expected = ClassFormatError.class)
   public void loadFromSpaceDir() throws Exception {
     URL currentPath = 
Thread.currentThread().getContextClassLoader().getResource(".");
-    File folder = new File(currentPath.getFile(), "space space/package");
+    File folder = new File(currentPath.toURI().getSchemeSpecificPart(), "space 
space/package");
     folder.mkdirs();
     File classFile = new File(folder, "Invalid.class");
     classFile.createNewFile();

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/46d83c8e/odata2-annotation-processor/annotation-processor-ref/pom.xml
----------------------------------------------------------------------
diff --git a/odata2-annotation-processor/annotation-processor-ref/pom.xml 
b/odata2-annotation-processor/annotation-processor-ref/pom.xml
index c014d2e..8e05f59 100644
--- a/odata2-annotation-processor/annotation-processor-ref/pom.xml
+++ b/odata2-annotation-processor/annotation-processor-ref/pom.xml
@@ -20,7 +20,7 @@
   <parent>
     <groupId>org.apache.olingo</groupId>
     <artifactId>olingo-odata2-annotation-processor</artifactId>
-    <version>1.3.0-SNAPSHOT</version>
+    <version>2.0.0</version>
     <relativePath>..</relativePath>
   </parent>
 

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/46d83c8e/odata2-annotation-processor/annotation-processor-web/pom.xml
----------------------------------------------------------------------
diff --git a/odata2-annotation-processor/annotation-processor-web/pom.xml 
b/odata2-annotation-processor/annotation-processor-web/pom.xml
index 64e5742..17d85bc 100644
--- a/odata2-annotation-processor/annotation-processor-web/pom.xml
+++ b/odata2-annotation-processor/annotation-processor-web/pom.xml
@@ -20,7 +20,7 @@
   <parent>
     <groupId>org.apache.olingo</groupId>
     <artifactId>olingo-odata2-annotation-processor</artifactId>
-    <version>1.3.0-SNAPSHOT</version>
+    <version>2.0.0</version>
     <relativePath>..</relativePath>
   </parent>
 

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/46d83c8e/odata2-annotation-processor/pom.xml
----------------------------------------------------------------------
diff --git a/odata2-annotation-processor/pom.xml 
b/odata2-annotation-processor/pom.xml
index 4df2244..a3f3bfd 100644
--- a/odata2-annotation-processor/pom.xml
+++ b/odata2-annotation-processor/pom.xml
@@ -18,7 +18,7 @@
     <parent>
         <groupId>org.apache.olingo</groupId>
         <artifactId>olingo-odata2-parent</artifactId>
-        <version>1.3.0-SNAPSHOT</version>
+        <version>2.0.0</version>
         <relativePath>..</relativePath>
     </parent>
 

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/46d83c8e/odata2-dist/janos/pom.xml
----------------------------------------------------------------------
diff --git a/odata2-dist/janos/pom.xml b/odata2-dist/janos/pom.xml
index 441358a..220ac80 100644
--- a/odata2-dist/janos/pom.xml
+++ b/odata2-dist/janos/pom.xml
@@ -17,7 +17,7 @@
     <parent>
         <groupId>org.apache.olingo</groupId>
         <artifactId>olingo-odata2-dist</artifactId>
-        <version>1.3.0-SNAPSHOT</version>
+        <version>2.0.0</version>
         <relativePath>..</relativePath>
     </parent>
 

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/46d83c8e/odata2-dist/javadoc/pom.xml
----------------------------------------------------------------------
diff --git a/odata2-dist/javadoc/pom.xml b/odata2-dist/javadoc/pom.xml
index 081d3f2..eb9487d 100644
--- a/odata2-dist/javadoc/pom.xml
+++ b/odata2-dist/javadoc/pom.xml
@@ -17,7 +17,7 @@
     <parent>
         <groupId>org.apache.olingo</groupId>
         <artifactId>olingo-odata2-dist</artifactId>
-        <version>1.3.0-SNAPSHOT</version>
+        <version>2.0.0</version>
         <relativePath>..</relativePath>
     </parent>
 

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/46d83c8e/odata2-dist/jpa/pom.xml
----------------------------------------------------------------------
diff --git a/odata2-dist/jpa/pom.xml b/odata2-dist/jpa/pom.xml
index ea4b142..7a40638 100644
--- a/odata2-dist/jpa/pom.xml
+++ b/odata2-dist/jpa/pom.xml
@@ -17,7 +17,7 @@
     <parent>
         <groupId>org.apache.olingo</groupId>
         <artifactId>olingo-odata2-dist</artifactId>
-        <version>1.3.0-SNAPSHOT</version>
+        <version>2.0.0</version>
         <relativePath>..</relativePath>
     </parent>
 

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/46d83c8e/odata2-dist/lib/pom.xml
----------------------------------------------------------------------
diff --git a/odata2-dist/lib/pom.xml b/odata2-dist/lib/pom.xml
index 937f1ed..60b3bea 100644
--- a/odata2-dist/lib/pom.xml
+++ b/odata2-dist/lib/pom.xml
@@ -17,7 +17,7 @@
     <parent>
         <groupId>org.apache.olingo</groupId>
         <artifactId>olingo-odata2-dist</artifactId>
-        <version>1.3.0-SNAPSHOT</version>
+        <version>2.0.0</version>
         <relativePath>..</relativePath>
     </parent>
 

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/46d83c8e/odata2-dist/pom.xml
----------------------------------------------------------------------
diff --git a/odata2-dist/pom.xml b/odata2-dist/pom.xml
index 4c69edf..dcf28d1 100644
--- a/odata2-dist/pom.xml
+++ b/odata2-dist/pom.xml
@@ -17,7 +17,7 @@
     <parent>
         <groupId>org.apache.olingo</groupId>
         <artifactId>olingo-odata2-parent</artifactId>
-        <version>1.3.0-SNAPSHOT</version>
+        <version>2.0.0</version>
         <relativePath>..</relativePath>
     </parent>
 

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/46d83c8e/odata2-dist/ref/pom.xml
----------------------------------------------------------------------
diff --git a/odata2-dist/ref/pom.xml b/odata2-dist/ref/pom.xml
index 674c4b1..2c3de83 100644
--- a/odata2-dist/ref/pom.xml
+++ b/odata2-dist/ref/pom.xml
@@ -17,7 +17,7 @@
     <parent>
         <groupId>org.apache.olingo</groupId>
         <artifactId>olingo-odata2-dist</artifactId>
-        <version>1.3.0-SNAPSHOT</version>
+        <version>2.0.0</version>
         <relativePath>..</relativePath>
     </parent>
 

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/46d83c8e/odata2-jpa-processor/jpa-api/pom.xml
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-api/pom.xml 
b/odata2-jpa-processor/jpa-api/pom.xml
index 69b80d6..7903559 100644
--- a/odata2-jpa-processor/jpa-api/pom.xml
+++ b/odata2-jpa-processor/jpa-api/pom.xml
@@ -24,7 +24,7 @@
        <parent>
                <groupId>org.apache.olingo</groupId>
                <artifactId>olingo-odata2-jpa-processor</artifactId>
-               <version>1.3.0-SNAPSHOT</version>
+               <version>2.0.0</version>
                <relativePath>../</relativePath>
        </parent>
 

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/46d83c8e/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/ODataJPAProcessor.java
----------------------------------------------------------------------
diff --git 
a/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/ODataJPAProcessor.java
 
b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/ODataJPAProcessor.java
index 127c79a..3a1b179 100644
--- 
a/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/ODataJPAProcessor.java
+++ 
b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/ODataJPAProcessor.java
@@ -74,4 +74,12 @@ public abstract class ODataJPAProcessor extends 
ODataSingleProcessor {
         
ODataJPAFactory.createFactory().getODataJPAAccessFactory().getODataJPAResponseBuilder(this.oDataJPAContext);
   }
 
+  /**
+   * The method closes ThreadContext. It is mandatory to call this method to
+   * avoid memory leaks.
+   */
+  public void close() {
+    ODataJPATombstoneContext.cleanup();
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/46d83c8e/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/ODataJPATombstoneContext.java
----------------------------------------------------------------------
diff --git 
a/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/ODataJPATombstoneContext.java
 
b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/ODataJPATombstoneContext.java
new file mode 100644
index 0000000..7229d14
--- /dev/null
+++ 
b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/ODataJPATombstoneContext.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * 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.odata2.jpa.processor.api;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * This class provides a thread safe container for accessing Tombstone objects
+ * 
+ */
+public final class ODataJPATombstoneContext {
+
+  private static final ThreadLocal<String> deltaToken = new 
ThreadLocal<String>();
+  private static final ThreadLocal<Long> deltaTokenUTCTimeStamp = new 
ThreadLocal<Long>();
+  private static final ThreadLocal<HashMap<String, List<Object>>> deltas =
+      new ThreadLocal<HashMap<String, List<Object>>>();
+
+  public static String getDeltaToken() {
+    return deltaToken.get();
+  }
+
+  public static void setDeltaToken(final String token) {
+    deltaToken.set(token);
+  }
+
+  public static void addToDeltaResult(final Object entity, final String 
entityName) {
+    HashMap<String, List<Object>> entityDeltaMap = deltas.get();
+    if (entityDeltaMap == null) {
+      deltas.set(new HashMap<String, List<Object>>());
+    }
+    entityDeltaMap = deltas.get();
+    if (entityDeltaMap.get(entityName) == null) {
+      entityDeltaMap.put(entityName, new ArrayList<Object>());
+    }
+    entityDeltaMap.get(entityName).add(entity);
+  }
+
+  public static List<Object> getDeltaResult(final String entityName) {
+    HashMap<String, List<Object>> entityDeltaMap = deltas.get();
+    if (entityDeltaMap != null) {
+      return entityDeltaMap.get(entityName);
+    } else {
+      return null;
+    }
+  }
+
+  public static void cleanup() {
+    deltas.remove();
+    deltaToken.remove();
+    deltaTokenUTCTimeStamp.remove();
+  }
+
+  public static Long getDeltaTokenUTCTimeStamp() {
+    Long timestamp = deltaTokenUTCTimeStamp.get();
+
+    if (timestamp != null) {
+      return timestamp;
+    } else if (deltaToken.get() != null) {
+      try {
+        timestamp = new Long(Long.parseLong(deltaToken.get()));
+      } catch (NumberFormatException e) {
+        return null;
+      }
+      deltaTokenUTCTimeStamp.set(timestamp);
+    } else {
+      deltaTokenUTCTimeStamp.set(new Long(0L));
+    }
+
+    return deltaTokenUTCTimeStamp.get();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/46d83c8e/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/ODataJPATombstoneEntityListener.java
----------------------------------------------------------------------
diff --git 
a/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/ODataJPATombstoneEntityListener.java
 
b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/ODataJPATombstoneEntityListener.java
new file mode 100644
index 0000000..148fa38
--- /dev/null
+++ 
b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/ODataJPATombstoneEntityListener.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * 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.odata2.jpa.processor.api;
+
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetUriInfo;
+
+/**
+ * Extend this class and implement a JPA Entity Listener as specified in JSR 
317 Java Persistence 2.0.
+ * The class provides abstract methods that shall be implemented by JPA 
application to handle OData Tombstone features.
+ * The implemented JPA Entity Listener classes will be called back from OData 
JPA Processor Library.
+ */
+public abstract class ODataJPATombstoneEntityListener {
+
+  public ODataJPATombstoneEntityListener() {}
+
+  protected final void addToDelta(final Object entity, final String 
entityName) {
+    ODataJPATombstoneContext.addToDeltaResult(entity, entityName);
+  }
+
+  /**
+   * Implement this method to create a {@link javax.persistence.Query} object. 
The Query object can be created from
+   * OData requests. The query instance thus created can be used for handling 
delta JPA entities. The delta token passed
+   * from OData request can
+   * be accessed from {@link 
com.sap.core.odata.processor.api.jpa.ODataJPATombstoneContext}.
+   * @param resultsView is a reference to OData request
+   * @param em is a reference to {@link javax.persistence.EntityManager}
+   * @return an instance of type {@link javax.persistence.Query}
+   */
+  public abstract Query getQuery(GetEntitySetUriInfo resultsView, 
EntityManager em);
+
+  /**
+   * Implement this method to create a delta token.
+   * @param deltas is list of delta JPA Entities
+   * @param query is an instance of type {@link javax.persistence.Query} that 
was used for handling delta entites
+   * @return a delta token of type String
+   */
+  public abstract String generateDeltaToken(List<Object> deltas, Query query);
+
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/46d83c8e/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/exception/ODataJPAErrorCallback.java
----------------------------------------------------------------------
diff --git 
a/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/exception/ODataJPAErrorCallback.java
 
b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/exception/ODataJPAErrorCallback.java
index 6d7e737..4482f61 100644
--- 
a/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/exception/ODataJPAErrorCallback.java
+++ 
b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/exception/ODataJPAErrorCallback.java
@@ -32,7 +32,7 @@ public class ODataJPAErrorCallback implements 
ODataErrorCallback {
     final String SEPARATOR = " : ";
 
     Throwable t = context.getException();
-    if (t instanceof ODataJPAException) {
+    if (t instanceof ODataJPAException && t.getCause() != null) {
       StringBuilder errorBuilder = new StringBuilder();
       errorBuilder.append(t.getCause().getClass().toString());
       errorBuilder.append(SEPARATOR);

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/46d83c8e/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/model/JPAEdmAssociationEndView.java
----------------------------------------------------------------------
diff --git 
a/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/model/JPAEdmAssociationEndView.java
 
b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/model/JPAEdmAssociationEndView.java
index 2d1262e..44ef3b2 100644
--- 
a/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/model/JPAEdmAssociationEndView.java
+++ 
b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/model/JPAEdmAssociationEndView.java
@@ -80,9 +80,9 @@ public interface JPAEdmAssociationEndView extends 
JPAEdmBaseView {
    */
   boolean compare(AssociationEnd end1, AssociationEnd end2);
 
-  String getJoinColumnName();
+  String[] getJoinColumnNames();
 
-  String getJoinColumnReferenceColumnName();
+  String[] getJoinColumnReferenceColumnNames();
 
   String getMappedByName();
 

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/46d83c8e/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/model/JPAEdmExtension.java
----------------------------------------------------------------------
diff --git 
a/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/model/JPAEdmExtension.java
 
b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/model/JPAEdmExtension.java
index 18f43a0..c8c0f8f 100644
--- 
a/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/model/JPAEdmExtension.java
+++ 
b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/model/JPAEdmExtension.java
@@ -18,6 +18,8 @@
  
******************************************************************************/
 package org.apache.olingo.odata2.jpa.processor.api.model;
 
+import java.io.InputStream;
+
 /**
  * The interface provides methods to extend JPA EDM containers.
  * 
@@ -47,4 +49,11 @@ public interface JPAEdmExtension {
    */
   public void extendJPAEdmSchema(JPAEdmSchemaView view);
 
+  /**
+   * Implement this method to provide a stream of Mapping model.
+   * @return
+   * a stream of mapping model XML as per JPAEDMMappingModel.xsd
+   */
+  public InputStream getJPAEdmMappingModelStream();
+
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/46d83c8e/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/model/JPAEdmMapping.java
----------------------------------------------------------------------
diff --git 
a/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/model/JPAEdmMapping.java
 
b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/model/JPAEdmMapping.java
index 4b77b6d..44f0f29 100644
--- 
a/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/model/JPAEdmMapping.java
+++ 
b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/model/JPAEdmMapping.java
@@ -18,6 +18,8 @@
  
******************************************************************************/
 package org.apache.olingo.odata2.jpa.processor.api.model;
 
+import 
org.apache.olingo.odata2.jpa.processor.api.ODataJPATombstoneEntityListener;
+
 /**
  * The interface acts a container for storing Java persistence column name. The
  * JPA EDM mapping instance can be associated with any EDM simple, EDM complex
@@ -60,4 +62,18 @@ public interface JPAEdmMapping {
    */
   public Class<?> getJPAType();
 
+  /**
+   * The method sets a stateless JPA EntityListner type. The entity listener 
type
+   * should inherit from {@link 
com.sap.core.odata.processor.api.jpa.ODataJPATombstoneEntityListener}.
+   * @param entityListner
+   * is an instance of type Class<?>
+   */
+  public void setODataJPATombstoneEntityListener(Class<? extends 
ODataJPATombstoneEntityListener> entityListener);
+
+  /**
+   * The method returns a stateless JPA EntityListener type.
+   * @return JPA EntityListener type
+   */
+  public Class<? extends ODataJPATombstoneEntityListener> 
getODataJPATombstoneEntityListener();
+
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/46d83c8e/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/model/JPAEdmPropertyView.java
----------------------------------------------------------------------
diff --git 
a/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/model/JPAEdmPropertyView.java
 
b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/model/JPAEdmPropertyView.java
index ce06f68..3ce66d6 100644
--- 
a/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/model/JPAEdmPropertyView.java
+++ 
b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/model/JPAEdmPropertyView.java
@@ -110,4 +110,12 @@ public interface JPAEdmPropertyView extends JPAEdmBaseView 
{
    * @return an instance of type {@link 
org.apache.olingo.odata2.jpa.processor.api.model.JPAEdmComplexTypeView}
    */
   JPAEdmComplexTypeView getJPAEdmComplexTypeView();
+
+  /**
+   * The method returns a list of JPA Join Column Annotations for the given 
JPA Attribute
+   * @return
+   * a list of Array of Strings. First element in the Array represents the 
join column name and the second element in
+   * the array represents the referencedColumn name
+   */
+  List<String[]> getJPAJoinColumns();
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/46d83c8e/odata2-jpa-processor/jpa-core/pom.xml
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/pom.xml 
b/odata2-jpa-processor/jpa-core/pom.xml
index 08f3be0..fc7cff1 100644
--- a/odata2-jpa-processor/jpa-core/pom.xml
+++ b/odata2-jpa-processor/jpa-core/pom.xml
@@ -24,7 +24,7 @@
        <parent>
                <groupId>org.apache.olingo</groupId>
                <artifactId>olingo-odata2-jpa-processor</artifactId>
-               <version>1.3.0-SNAPSHOT</version>
+               <version>2.0.0</version>
                <relativePath>../</relativePath>
        </parent>
 

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/46d83c8e/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/ODataJPAProcessorDefault.java
----------------------------------------------------------------------
diff --git 
a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/ODataJPAProcessorDefault.java
 
b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/ODataJPAProcessorDefault.java
index 2ecabd1..6512b79 100644
--- 
a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/ODataJPAProcessorDefault.java
+++ 
b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/ODataJPAProcessorDefault.java
@@ -19,10 +19,19 @@
 package org.apache.olingo.odata2.jpa.processor.core;
 
 import java.io.InputStream;
+import java.util.ArrayList;
 import java.util.List;
 
+import org.apache.olingo.odata2.api.batch.BatchHandler;
+import org.apache.olingo.odata2.api.batch.BatchRequestPart;
+import org.apache.olingo.odata2.api.batch.BatchResponsePart;
+import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
+import org.apache.olingo.odata2.api.ep.EntityProvider;
+import org.apache.olingo.odata2.api.ep.EntityProviderBatchProperties;
 import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.processor.ODataRequest;
 import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.api.uri.PathInfo;
 import org.apache.olingo.odata2.api.uri.info.DeleteUriInfo;
 import org.apache.olingo.odata2.api.uri.info.GetEntityCountUriInfo;
 import org.apache.olingo.odata2.api.uri.info.GetEntityLinkUriInfo;
@@ -55,6 +64,8 @@ public class ODataJPAProcessorDefault extends 
ODataJPAProcessor {
     ODataResponse oDataResponse =
         responseBuilder.build(uriParserResultView, jpaEntities, contentType);
 
+    close();
+
     return oDataResponse;
   }
 
@@ -199,4 +210,36 @@ public class ODataJPAProcessorDefault extends 
ODataJPAProcessor {
     return ODataResponse.newBuilder().build();
 
   }
-}
+
+  @Override
+  public ODataResponse executeBatch(final BatchHandler handler, final String 
contentType, final InputStream content)
+      throws ODataException {
+    ODataResponse batchResponse;
+    List<BatchResponsePart> batchResponseParts = new 
ArrayList<BatchResponsePart>();
+    PathInfo pathInfo = getContext().getPathInfo();
+    EntityProviderBatchProperties batchProperties = 
EntityProviderBatchProperties.init().pathInfo(pathInfo).build();
+    List<BatchRequestPart> batchParts = 
EntityProvider.parseBatchRequest(contentType, content, batchProperties);
+    for (BatchRequestPart batchPart : batchParts) {
+      batchResponseParts.add(handler.handleBatchPart(batchPart));
+    }
+    batchResponse = EntityProvider.writeBatchResponse(batchResponseParts);
+    return batchResponse;
+  }
+
+  @Override
+  public BatchResponsePart executeChangeSet(final BatchHandler handler, final 
List<ODataRequest> requests)
+      throws ODataException {
+    List<ODataResponse> responses = new ArrayList<ODataResponse>();
+    for (ODataRequest request : requests) {
+      ODataResponse response = handler.handleRequest(request);
+      if (response.getStatus().getStatusCode() >= 
HttpStatusCodes.BAD_REQUEST.getStatusCode()) {
+        // Rollback
+        List<ODataResponse> errorResponses = new ArrayList<ODataResponse>(1);
+        errorResponses.add(response);
+        return 
BatchResponsePart.responses(errorResponses).changeSet(false).build();
+      }
+      responses.add(response);
+    }
+    return BatchResponsePart.responses(responses).changeSet(true).build();
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/46d83c8e/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/ODataJPAResponseBuilderDefault.java
----------------------------------------------------------------------
diff --git 
a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/ODataJPAResponseBuilderDefault.java
 
b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/ODataJPAResponseBuilderDefault.java
index 4277d76..e5ed19b 100644
--- 
a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/ODataJPAResponseBuilderDefault.java
+++ 
b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/ODataJPAResponseBuilderDefault.java
@@ -18,11 +18,13 @@
  
******************************************************************************/
 package org.apache.olingo.odata2.jpa.processor.core;
 
+import java.net.URI;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.olingo.odata2.api.ODataCallback;
 import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
 import org.apache.olingo.odata2.api.commons.InlineCount;
 import org.apache.olingo.odata2.api.edm.EdmEntitySet;
@@ -41,6 +43,7 @@ import org.apache.olingo.odata2.api.ep.EntityProvider;
 import org.apache.olingo.odata2.api.ep.EntityProviderException;
 import org.apache.olingo.odata2.api.ep.EntityProviderWriteProperties;
 import 
org.apache.olingo.odata2.api.ep.EntityProviderWriteProperties.ODataEntityProviderPropertiesBuilder;
+import org.apache.olingo.odata2.api.ep.callback.TombstoneCallback;
 import org.apache.olingo.odata2.api.exception.ODataException;
 import org.apache.olingo.odata2.api.exception.ODataHttpException;
 import org.apache.olingo.odata2.api.exception.ODataNotFoundException;
@@ -61,10 +64,12 @@ import org.apache.olingo.odata2.api.uri.info.PostUriInfo;
 import org.apache.olingo.odata2.api.uri.info.PutMergePatchUriInfo;
 import org.apache.olingo.odata2.jpa.processor.api.ODataJPAContext;
 import org.apache.olingo.odata2.jpa.processor.api.ODataJPAResponseBuilder;
+import org.apache.olingo.odata2.jpa.processor.api.ODataJPATombstoneContext;
 import org.apache.olingo.odata2.jpa.processor.api.access.JPAPaging;
 import 
org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPARuntimeException;
 import org.apache.olingo.odata2.jpa.processor.core.access.data.JPAEntityParser;
-import 
org.apache.olingo.odata2.jpa.processor.core.access.data.JPAExpandCallBack;
+import org.apache.olingo.odata2.jpa.processor.core.callback.JPAExpandCallBack;
+import 
org.apache.olingo.odata2.jpa.processor.core.callback.JPATombstoneCallBack;
 
 public final class ODataJPAResponseBuilderDefault implements 
ODataJPAResponseBuilder {
 
@@ -487,12 +492,14 @@ public final class ODataJPAResponseBuilderDefault 
implements ODataJPAResponseBui
 
     try {
       PathInfo pathInfo = context.getPathInfo();
+      URI serviceRoot = pathInfo.getServiceRoot();
+
       entityFeedPropertiesBuilder =
           EntityProviderWriteProperties.serviceRoot(pathInfo.getServiceRoot());
       JPAPaging paging = odataJPAContext.getPaging();
       if (odataJPAContext.getPageSize() > 0 && paging != null && 
paging.getNextPage() > 0) {
         String nextLink =
-            
pathInfo.getServiceRoot().relativize(context.getPathInfo().getRequestUri()).toString();
+            serviceRoot.relativize(pathInfo.getRequestUri()).toString();
         nextLink = percentEncodeNextLink(nextLink);
         nextLink += (nextLink.contains("?") ? "&" : "?")
             + "$skiptoken=" + odataJPAContext.getPaging().getNextPage();
@@ -502,8 +509,20 @@ public final class ODataJPAResponseBuilderDefault 
implements ODataJPAResponseBui
       
entityFeedPropertiesBuilder.inlineCountType(resultsView.getInlineCount());
       ExpandSelectTreeNode expandSelectTree =
           UriParser.createExpandSelectTree(resultsView.getSelect(), 
resultsView.getExpand());
-      
entityFeedPropertiesBuilder.callbacks(JPAExpandCallBack.getCallbacks(context
-          .getPathInfo().getServiceRoot(), expandSelectTree, 
resultsView.getExpand()));
+
+      Map<String, ODataCallback> expandCallBack =
+          JPAExpandCallBack.getCallbacks(serviceRoot, expandSelectTree, 
resultsView.getExpand());
+
+      Map<String, ODataCallback> callBackMap = new HashMap<String, 
ODataCallback>();
+      callBackMap.putAll(expandCallBack);
+
+      String deltaToken = ODataJPATombstoneContext.getDeltaToken();
+      if (deltaToken != null) {
+        callBackMap.put(TombstoneCallback.CALLBACK_KEY_TOMBSTONE, new 
JPATombstoneCallBack(serviceRoot.toString(),
+            resultsView, deltaToken));
+      }
+
+      entityFeedPropertiesBuilder.callbacks(callBackMap);
       entityFeedPropertiesBuilder.expandSelectTree(expandSelectTree);
 
     } catch (ODataException e) {

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/46d83c8e/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAEntity.java
----------------------------------------------------------------------
diff --git 
a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAEntity.java
 
b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAEntity.java
index ec05d6b..3c42288 100644
--- 
a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAEntity.java
+++ 
b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAEntity.java
@@ -23,7 +23,9 @@ import java.lang.reflect.Method;
 import java.sql.Blob;
 import java.sql.Clob;
 import java.sql.SQLException;
+import java.sql.Timestamp;
 import java.util.ArrayList;
+import java.util.Calendar;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -349,6 +351,9 @@ public class JPAEntity {
         } else {
           method.invoke(entity, onJPAWriteContent.getJPAClob(((String) 
entityPropertyValue).toCharArray()));
         }
+      } else if (parameterType.equals(Timestamp.class)) {
+        Timestamp ts = new Timestamp(((Calendar) 
entityPropertyValue).getTimeInMillis());
+        method.invoke(entity, ts);
       } else {
         method.invoke(entity, entityPropertyValue);
       }

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/46d83c8e/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAEntityParser.java
----------------------------------------------------------------------
diff --git 
a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAEntityParser.java
 
b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAEntityParser.java
index 1314ed2..9543bfe 100644
--- 
a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAEntityParser.java
+++ 
b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAEntityParser.java
@@ -260,6 +260,11 @@ public final class JPAEntityParser {
 
   public static String getString(final Clob clob) throws 
ODataJPARuntimeException {
     try {
+
+      if (clob == null) {
+        return null;
+      }
+
       Reader stringReader = clob.getCharacterStream();
       StringWriter buffer = null;
       long clobSize = clob.length();
@@ -307,8 +312,13 @@ public final class JPAEntityParser {
 
   public static byte[] getBytes(final Blob blob) throws 
ODataJPARuntimeException {
     try {
+
+      if (blob == null) {
+        return null;
+      }
       InputStream is = null;
       ByteArrayOutputStream buffer = null;
+
       long blobSize = blob.length();
       long remainingBlobSize = blobSize;
       int len = 0;

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/46d83c8e/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAExpandCallBack.java
----------------------------------------------------------------------
diff --git 
a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAExpandCallBack.java
 
b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAExpandCallBack.java
deleted file mode 100644
index 1ea8914..0000000
--- 
a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAExpandCallBack.java
+++ /dev/null
@@ -1,221 +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.odata2.jpa.processor.core.access.data;
-
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-
-import org.apache.olingo.odata2.api.ODataCallback;
-import org.apache.olingo.odata2.api.edm.EdmEntitySet;
-import org.apache.olingo.odata2.api.edm.EdmEntityType;
-import org.apache.olingo.odata2.api.edm.EdmException;
-import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
-import org.apache.olingo.odata2.api.edm.EdmProperty;
-import org.apache.olingo.odata2.api.ep.EntityProviderWriteProperties;
-import 
org.apache.olingo.odata2.api.ep.EntityProviderWriteProperties.ODataEntityProviderPropertiesBuilder;
-import org.apache.olingo.odata2.api.ep.callback.OnWriteEntryContent;
-import org.apache.olingo.odata2.api.ep.callback.OnWriteFeedContent;
-import org.apache.olingo.odata2.api.ep.callback.WriteCallbackContext;
-import org.apache.olingo.odata2.api.ep.callback.WriteEntryCallbackContext;
-import org.apache.olingo.odata2.api.ep.callback.WriteEntryCallbackResult;
-import org.apache.olingo.odata2.api.ep.callback.WriteFeedCallbackContext;
-import org.apache.olingo.odata2.api.ep.callback.WriteFeedCallbackResult;
-import org.apache.olingo.odata2.api.exception.ODataApplicationException;
-import org.apache.olingo.odata2.api.uri.ExpandSelectTreeNode;
-import org.apache.olingo.odata2.api.uri.NavigationPropertySegment;
-import 
org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPARuntimeException;
-
-public class JPAExpandCallBack implements OnWriteFeedContent, 
OnWriteEntryContent, ODataCallback {
-
-  private URI baseUri;
-  private List<ArrayList<NavigationPropertySegment>> expandList;
-  private EdmEntitySet nextEntitySet = null;
-  private HashMap<String, List<EdmProperty>> edmPropertyMap = new 
HashMap<String, List<EdmProperty>>();
-
-  private JPAExpandCallBack(final URI baseUri, final 
List<ArrayList<NavigationPropertySegment>> expandList) {
-    super();
-    this.baseUri = baseUri;
-    this.expandList = expandList;
-  }
-
-  @Override
-  public WriteEntryCallbackResult retrieveEntryResult(final 
WriteEntryCallbackContext context)
-      throws ODataApplicationException {
-    WriteEntryCallbackResult result = new WriteEntryCallbackResult();
-    Map<String, Object> entry = context.getEntryData();
-    Map<String, Object> edmPropertyValueMap = null;
-    List<EdmNavigationProperty> currentNavPropertyList = null;
-    Map<String, ExpandSelectTreeNode> navigationLinks = null;
-    JPAEntityParser jpaResultParser = new JPAEntityParser();
-    EdmNavigationProperty currentNavigationProperty = 
context.getNavigationProperty();
-    try {
-      Object inlinedEntry = entry.get(currentNavigationProperty.getName());
-      if (nextEntitySet == null) {
-        nextEntitySet = 
context.getSourceEntitySet().getRelatedEntitySet(currentNavigationProperty);
-      }
-      edmPropertyValueMap = 
jpaResultParser.parse2EdmPropertyValueMap(inlinedEntry, 
nextEntitySet.getEntityType());
-      result.setEntryData(edmPropertyValueMap);
-      navigationLinks = context.getCurrentExpandSelectTreeNode().getLinks();
-      if (navigationLinks.size() > 0) {
-        currentNavPropertyList = new ArrayList<EdmNavigationProperty>();
-        EdmNavigationProperty nextNavProperty =
-            
getNextNavigationProperty(context.getSourceEntitySet().getEntityType(), 
context.getNavigationProperty());
-        if (nextNavProperty != null) {
-          currentNavPropertyList.add(nextNavProperty);
-        }
-        HashMap<String, Object> navigationMap =
-            jpaResultParser.parse2EdmNavigationValueMap(inlinedEntry, 
currentNavPropertyList);
-        edmPropertyValueMap.putAll(navigationMap);
-        result.setEntryData(edmPropertyValueMap);
-      }
-      result.setInlineProperties(getInlineEntityProviderProperties(context));
-    } catch (EdmException e) {
-      throw new ODataApplicationException(e.getMessage(), Locale.getDefault(), 
e);
-    } catch (ODataJPARuntimeException e) {
-      throw new ODataApplicationException(e.getMessage(), Locale.getDefault(), 
e);
-    }
-
-    return result;
-  }
-
-  private List<EdmProperty> getEdmProperties(final EdmEntitySet entitySet, 
final ExpandSelectTreeNode expandTreeNode)
-      throws ODataApplicationException {
-
-    try {
-      String name = entitySet.getName();
-      if (edmPropertyMap.containsKey(name)) {
-        return edmPropertyMap.get(name);
-      }
-      List<EdmProperty> edmProperties = new ArrayList<EdmProperty>();
-      edmProperties.addAll(expandTreeNode.getProperties());
-      boolean hit = false;
-      for (EdmProperty keyProperty : 
entitySet.getEntityType().getKeyProperties()) {
-        hit = false;
-        for (EdmProperty property : edmProperties) {
-          if (property.getName().equals(keyProperty.getName())) {
-            hit = true;
-            break;
-          }
-        }
-        if (hit == false) {
-          edmProperties.add(keyProperty);
-        }
-      }
-      edmPropertyMap.put(name, edmProperties);
-      return edmProperties;
-    } catch (EdmException e) {
-      throw new ODataApplicationException(e.getMessage(), Locale.getDefault(), 
e);
-    }
-  }
-
-  @Override
-  public WriteFeedCallbackResult retrieveFeedResult(final 
WriteFeedCallbackContext context)
-      throws ODataApplicationException {
-    WriteFeedCallbackResult result = new WriteFeedCallbackResult();
-    HashMap<String, Object> inlinedEntry = (HashMap<String, Object>) 
context.getEntryData();
-    List<Map<String, Object>> edmEntityList = new ArrayList<Map<String, 
Object>>();
-    JPAEntityParser jpaResultParser = new JPAEntityParser();
-    List<EdmNavigationProperty> currentNavPropertyList = null;
-    EdmNavigationProperty currentNavigationProperty = 
context.getNavigationProperty();
-    ExpandSelectTreeNode currentExpandTreeNode = 
context.getCurrentExpandSelectTreeNode();
-
-    try {
-      @SuppressWarnings({ "unchecked" })
-      Collection<Object> listOfItems = (Collection<Object>) 
inlinedEntry.get(context.getNavigationProperty().getName());
-      if (nextEntitySet == null) {
-        nextEntitySet = 
context.getSourceEntitySet().getRelatedEntitySet(currentNavigationProperty);
-      }
-      if (currentExpandTreeNode.getProperties().size() > 0) {
-        edmEntityList =
-            jpaResultParser.parse2EdmEntityList(listOfItems, 
getEdmProperties(nextEntitySet,
-                currentExpandTreeNode));
-      } else {
-        edmEntityList = jpaResultParser.parse2EdmEntityList(listOfItems, 
nextEntitySet.getEntityType());
-      }
-      result.setFeedData(edmEntityList);
-
-      if (currentExpandTreeNode.getLinks().size() > 0) {
-        currentNavPropertyList = new ArrayList<EdmNavigationProperty>();
-        EdmNavigationProperty nextNavProperty =
-            
getNextNavigationProperty(context.getSourceEntitySet().getEntityType(), 
context.getNavigationProperty());
-        if (nextNavProperty != null) {
-          currentNavPropertyList.add(nextNavProperty);
-        }
-        int count = 0;
-        for (Object object : listOfItems) {
-          HashMap<String, Object> navigationMap =
-              jpaResultParser.parse2EdmNavigationValueMap(object, 
currentNavPropertyList);
-          edmEntityList.get(count).putAll(navigationMap);
-          count++;
-        }
-        result.setFeedData(edmEntityList);
-      }
-      result.setInlineProperties(getInlineEntityProviderProperties(context));
-    } catch (EdmException e) {
-      throw new ODataApplicationException(e.getMessage(), Locale.getDefault(), 
e);
-    } catch (ODataJPARuntimeException e) {
-      throw new ODataApplicationException(e.getMessage(), Locale.getDefault(), 
e);
-    }
-    return result;
-  }
-
-  private EdmNavigationProperty getNextNavigationProperty(final EdmEntityType 
sourceEntityType,
-      final EdmNavigationProperty navigationProperty) throws EdmException {
-    for (ArrayList<NavigationPropertySegment> navPropSegments : expandList) {
-      int size = navPropSegments.size();
-      for (int i = 0; i < size; i++) {
-        EdmNavigationProperty navProperty = 
navPropSegments.get(i).getNavigationProperty();
-        if 
(navProperty.getFromRole().equalsIgnoreCase(sourceEntityType.getName())
-            && navProperty.getName().equals(navigationProperty.getName())) {
-          if (i < size - 1) {
-            return navPropSegments.get(i + 1).getNavigationProperty();
-          }
-        }
-      }
-    }
-    return null;
-  }
-
-  public static <T> Map<String, ODataCallback> getCallbacks(final URI baseUri,
-      final ExpandSelectTreeNode expandSelectTreeNode, final 
List<ArrayList<NavigationPropertySegment>> expandList)
-      throws EdmException {
-    Map<String, ODataCallback> callbacks = new HashMap<String, 
ODataCallback>();
-
-    for (String navigationPropertyName : 
expandSelectTreeNode.getLinks().keySet()) {
-      callbacks.put(navigationPropertyName, new JPAExpandCallBack(baseUri, 
expandList));
-    }
-
-    return callbacks;
-
-  }
-
-  private EntityProviderWriteProperties 
getInlineEntityProviderProperties(final WriteCallbackContext context)
-      throws EdmException {
-    ODataEntityProviderPropertiesBuilder propertiesBuilder = 
EntityProviderWriteProperties.serviceRoot(baseUri);
-    propertiesBuilder.callbacks(getCallbacks(baseUri, 
context.getCurrentExpandSelectTreeNode(), expandList));
-    
propertiesBuilder.expandSelectTree(context.getCurrentExpandSelectTreeNode());
-    return propertiesBuilder.build();
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/46d83c8e/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAPage.java
----------------------------------------------------------------------
diff --git 
a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAPage.java
 
b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAPage.java
index 3161d8d..7aff111 100644
--- 
a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAPage.java
+++ 
b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAPage.java
@@ -68,6 +68,13 @@ public class JPAPage implements JPAPaging {
     private int skip;
     private int skipToken;
     private Query query;
+    private List<Object> entities;
+    private List<Object> pagedEntities;
+
+    private static class TopSkip {
+      public int top;
+      public int skip;
+    }
 
     public JPAPageBuilder() {}
 
@@ -81,19 +88,47 @@ public class JPAPage implements JPAPaging {
       return this;
     }
 
-    @SuppressWarnings("unchecked")
     public JPAPage build() {
+      if (entities != null) {
+        return buildFromEntities();
+      } else {
+        return buildFromQuery();
+      }
+    }
 
-      List<Object> entities = new ArrayList<Object>();
+    private JPAPage buildFromEntities() {
+      TopSkip topSkip = formulateTopSkip();
+      pagedEntities = new ArrayList<Object>();
+      if (topSkip.skip <= 0) {
+        topSkip.skip = 1;
+      }
+      for (int i = topSkip.skip - 1, j = 0; (j < topSkip.top && i < 
entities.size()); j++) {
+        pagedEntities.add(entities.get(i++));
+      }
+      formulateNextPage();
+      return new JPAPage(startPage, nextPage, pagedEntities, pageSize);
+    }
+
+    @SuppressWarnings("unchecked")
+    private JPAPage buildFromQuery() {
+      TopSkip topSkip = formulateTopSkip();
+      query.setFirstResult(topSkip.skip);
+      query.setMaxResults(topSkip.top);
+      pagedEntities = query.getResultList();
+      formulateNextPage();
+      return new JPAPage(startPage, nextPage, pagedEntities, pageSize);
+    }
+
+    private TopSkip formulateTopSkip() {
+      TopSkip topSkip = new TopSkip();
       int size = 0;
       if (pageSize <= 0) {
         if (skip > 0) {
-          query.setFirstResult(skip);
+          topSkip.skip = skip;
         }
         if (top > 0) {
-          query.setMaxResults(top);
+          topSkip.top = top;
         }
-        entities = query.getResultList();
       } else {
         if (skip >= pageSize) { // No Records to fetch
           startPage = skipToken;
@@ -103,34 +138,37 @@ public class JPAPage implements JPAPaging {
           size = top + skip;
           if (size > pageSize) {
             if (skip == 0) {
-              query.setMaxResults(pageSize);
+              topSkip.top = pageSize;
             } else {
-              query.setMaxResults(pageSize - skip);
+              topSkip.top = pageSize - skip;
             }
           } else {
             if (top > 0) {
-              query.setMaxResults(top);
+              topSkip.top = top;
             } else {
-              query.setMaxResults(pageSize);
+              topSkip.top = pageSize;
             }
           }
 
           startPage = skipToken;
           if (skip > 0) {
-            query.setFirstResult(startPage + skip);
-          } else {
-            query.setFirstResult(startPage);
-          }
-
-          entities = query.getResultList();
-          if (entities.size() == 0) {
-            nextPage = 0;
+            topSkip.skip = startPage + skip;
           } else {
-            nextPage = startPage + pageSize;
+            topSkip.skip = startPage;
           }
         }
       }
-      return new JPAPage(startPage, nextPage, entities, pageSize);
+      return topSkip;
+    }
+
+    private void formulateNextPage() {
+      if (pagedEntities.size() == 0) {
+        nextPage = 0;
+      } else if (pagedEntities.size() < pageSize) {
+        nextPage = 0;
+      } else {
+        nextPage = startPage + pageSize;
+      }
     }
 
     public JPAPageBuilder skip(final int skip) {
@@ -164,5 +202,10 @@ public class JPAPage implements JPAPaging {
       }
       return this;
     }
+
+    public JPAPageBuilder entities(final List<Object> result) {
+      entities = result;
+      return this;
+    }
   }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/46d83c8e/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAProcessorImpl.java
----------------------------------------------------------------------
diff --git 
a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAProcessorImpl.java
 
b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAProcessorImpl.java
index c018c00..fdef108 100644
--- 
a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAProcessorImpl.java
+++ 
b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAProcessorImpl.java
@@ -31,6 +31,7 @@ import javax.persistence.Query;
 import org.apache.olingo.odata2.api.edm.EdmEntitySet;
 import org.apache.olingo.odata2.api.edm.EdmEntityType;
 import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
 import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
 import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
 import org.apache.olingo.odata2.api.uri.UriInfo;
@@ -45,6 +46,8 @@ import 
org.apache.olingo.odata2.api.uri.info.GetFunctionImportUriInfo;
 import org.apache.olingo.odata2.api.uri.info.PostUriInfo;
 import org.apache.olingo.odata2.api.uri.info.PutMergePatchUriInfo;
 import org.apache.olingo.odata2.jpa.processor.api.ODataJPAContext;
+import org.apache.olingo.odata2.jpa.processor.api.ODataJPATombstoneContext;
+import 
org.apache.olingo.odata2.jpa.processor.api.ODataJPATombstoneEntityListener;
 import org.apache.olingo.odata2.jpa.processor.api.access.JPAFunction;
 import org.apache.olingo.odata2.jpa.processor.api.access.JPAMethodContext;
 import org.apache.olingo.odata2.jpa.processor.api.access.JPAProcessor;
@@ -53,6 +56,7 @@ import 
org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPARuntimeExcep
 import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContext;
 import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContextType;
 import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLStatement;
+import org.apache.olingo.odata2.jpa.processor.api.model.JPAEdmMapping;
 import org.apache.olingo.odata2.jpa.processor.core.ODataEntityParser;
 import 
org.apache.olingo.odata2.jpa.processor.core.access.data.JPAPage.JPAPageBuilder;
 
@@ -134,26 +138,57 @@ public class JPAProcessorImpl implements JPAProcessor {
         contextType = JPQLContextType.SELECT;
       }
 
-    } catch (EdmException e) {
-      ODataJPARuntimeException.throwException(
-          ODataJPARuntimeException.GENERAL, e);
-    }
+      JPQLContext jpqlContext = null;
 
-    JPQLContext jpqlContext = null;
-    if (oDataJPAContext.getPageSize() > 0) {
-      jpqlContext = JPQLContext.createBuilder(contextType,
-          uriParserResultView, true).build();
-    } else {
-      jpqlContext = JPQLContext.createBuilder(contextType,
-          uriParserResultView).build();
-    }
+      if (oDataJPAContext.getPageSize() > 0) {
+        jpqlContext = JPQLContext.createBuilder(contextType,
+            uriParserResultView, true).build();
+      } else {
+        jpqlContext = JPQLContext.createBuilder(contextType,
+            uriParserResultView).build();
+      }
+
+      JPQLStatement jpqlStatement = JPQLStatement.createBuilder(jpqlContext)
+          .build();
+      Map<String, String> customQueryOptions = 
uriParserResultView.getCustomQueryOptions();
+      String deltaToken = null;
+      if (customQueryOptions != null) {
+        deltaToken = 
uriParserResultView.getCustomQueryOptions().get("!deltatoken");
+      }
+      if (deltaToken != null) {
+        ODataJPATombstoneContext.setDeltaToken(deltaToken);
+      }
+
+      Query query = null;
+      List<Object> result = null;
+
+      JPAEdmMapping mapping = (JPAEdmMapping) 
uriParserResultView.getTargetEntitySet().getEntityType().getMapping();
+      ODataJPATombstoneEntityListener listener = null;
+      if (mapping.getODataJPATombstoneEntityListener() != null) {
+        listener = (ODataJPATombstoneEntityListener) 
mapping.getODataJPATombstoneEntityListener().newInstance();
+        query = listener.getQuery(uriParserResultView, em);
+      }
+      if (query == null) {
+        query = em.createQuery(jpqlStatement.toString());
+        if (listener != null) {
+          query.getResultList();
+          List<Object> deltaResult =
+              (List<Object>) 
ODataJPATombstoneContext.getDeltaResult(((EdmMapping) 
mapping).getInternalName());
+          result = handlePaging(deltaResult, uriParserResultView);
+        } else {
+          result = handlePaging(query, uriParserResultView);
+        }
+      } else {
+        result = handlePaging(query, uriParserResultView);
+      }
+
+      // Set New Token
+      if (listener != null) {
+        
ODataJPATombstoneContext.setDeltaToken(listener.generateDeltaToken((List<Object>)
 result, query));
+      }
+
+      return result == null ? new ArrayList<Object>() : result;
 
-    JPQLStatement jpqlStatement = JPQLStatement.createBuilder(jpqlContext)
-        .build();
-    Query query = null;
-    try {
-      query = em.createQuery(jpqlStatement.toString());
-      return handlePaging(query, uriParserResultView);
     } catch (Exception e) {
       throw ODataJPARuntimeException.throwException(
           ODataJPARuntimeException.ERROR_JPQL_QUERY_CREATE, e);
@@ -161,6 +196,30 @@ public class JPAProcessorImpl implements JPAProcessor {
     }
   }
 
+  private List<Object> handlePaging(final List<Object> result, final 
GetEntitySetUriInfo uriParserResultView) {
+    if (result == null) {
+      return null;
+    }
+    JPAPageBuilder pageBuilder = new JPAPageBuilder();
+    pageBuilder.pageSize(oDataJPAContext.getPageSize())
+        .entities(result)
+        .skipToken(uriParserResultView.getSkipToken());
+
+    // $top/$skip with $inlinecount case handled in response builder to avoid 
multiple DB call
+    if (uriParserResultView.getSkip() != null && 
uriParserResultView.getInlineCount() == null) {
+      pageBuilder.skip(uriParserResultView.getSkip().intValue());
+    }
+
+    if (uriParserResultView.getTop() != null && 
uriParserResultView.getInlineCount() == null) {
+      pageBuilder.top(uriParserResultView.getTop().intValue());
+    }
+
+    JPAPage page = pageBuilder.build();
+    oDataJPAContext.setPaging(page);
+
+    return page.getPagedEntities();
+  }
+
   private List<Object> handlePaging(final Query query, final 
GetEntitySetUriInfo uriParserResultView) {
 
     JPAPageBuilder pageBuilder = new JPAPageBuilder();
@@ -179,6 +238,7 @@ public class JPAProcessorImpl implements JPAProcessor {
 
     JPAPage page = pageBuilder.build();
     oDataJPAContext.setPaging(page);
+
     return page.getPagedEntities();
 
   }

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/46d83c8e/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/model/EdmTypeConvertor.java
----------------------------------------------------------------------
diff --git 
a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/model/EdmTypeConvertor.java
 
b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/model/EdmTypeConvertor.java
deleted file mode 100644
index 771aae6..0000000
--- 
a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/model/EdmTypeConvertor.java
+++ /dev/null
@@ -1,69 +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.odata2.jpa.processor.core.access.model;
-
-import java.math.BigDecimal;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.UUID;
-
-import org.apache.olingo.odata2.api.edm.EdmSimpleType;
-import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
-import org.apache.olingo.odata2.api.edm.EdmType;
-import 
org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPAModelException;
-import 
org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPARuntimeException;
-
-public class EdmTypeConvertor {
-
-  public static Class<?> convertToJavaType(final EdmType edmType) throws 
ODataJPAModelException,
-      ODataJPARuntimeException {
-    if (edmType instanceof EdmSimpleType) {
-      EdmSimpleType edmSimpleType = (EdmSimpleType) edmType;
-      if (edmSimpleType == 
EdmSimpleTypeKind.String.getEdmSimpleTypeInstance()) {
-        return String.class;
-      } else if (edmSimpleType == 
EdmSimpleTypeKind.Int64.getEdmSimpleTypeInstance()) {
-        return Long.TYPE;
-      } else if (edmSimpleType == 
EdmSimpleTypeKind.Int16.getEdmSimpleTypeInstance()) {
-        return Short.TYPE;
-      } else if (edmSimpleType == 
EdmSimpleTypeKind.Int32.getEdmSimpleTypeInstance()) {
-        return Integer.TYPE;
-      } else if (edmSimpleType == 
EdmSimpleTypeKind.Double.getEdmSimpleTypeInstance()) {
-        return Double.TYPE;
-      } else if (edmSimpleType == 
EdmSimpleTypeKind.Single.getEdmSimpleTypeInstance()) {
-        return Float.TYPE;
-      } else if (edmSimpleType == 
EdmSimpleTypeKind.Decimal.getEdmSimpleTypeInstance()) {
-        return BigDecimal.class;
-      } else if (edmSimpleType == 
EdmSimpleTypeKind.Binary.getEdmSimpleTypeInstance()) {
-        return byte[].class;
-      } else if (edmSimpleType == 
EdmSimpleTypeKind.Byte.getEdmSimpleTypeInstance()) {
-        return Byte.TYPE;
-      } else if (edmSimpleType == 
EdmSimpleTypeKind.Boolean.getEdmSimpleTypeInstance()) {
-        return Boolean.TYPE;
-      } else if (edmSimpleType == 
EdmSimpleTypeKind.DateTime.getEdmSimpleTypeInstance()) {
-        return Date.class;
-      } else if (edmSimpleType == 
EdmSimpleTypeKind.DateTimeOffset.getEdmSimpleTypeInstance()) {
-        return Calendar.class;
-      } else if (edmSimpleType == 
EdmSimpleTypeKind.Guid.getEdmSimpleTypeInstance()) {
-        return UUID.class;
-      }
-    }
-    throw 
ODataJPAModelException.throwException(ODataJPAModelException.TYPE_NOT_SUPPORTED
-        .addContent(edmType.toString()), null);
-  }
-}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/46d83c8e/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/model/JPAEdmMappingModelService.java
----------------------------------------------------------------------
diff --git 
a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/model/JPAEdmMappingModelService.java
 
b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/model/JPAEdmMappingModelService.java
index dd453ac..8bec453 100644
--- 
a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/model/JPAEdmMappingModelService.java
+++ 
b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/model/JPAEdmMappingModelService.java
@@ -27,6 +27,7 @@ import javax.xml.bind.Unmarshaller;
 import org.apache.olingo.odata2.jpa.processor.api.ODataJPAContext;
 import 
org.apache.olingo.odata2.jpa.processor.api.access.JPAEdmMappingModelAccess;
 import 
org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.jpa.processor.api.model.JPAEdmExtension;
 import 
org.apache.olingo.odata2.jpa.processor.api.model.mapping.JPAAttributeMapType.JPAAttribute;
 import 
org.apache.olingo.odata2.jpa.processor.api.model.mapping.JPAEdmMappingModel;
 import 
org.apache.olingo.odata2.jpa.processor.api.model.mapping.JPAEmbeddableTypeMapType;
@@ -38,13 +39,20 @@ public class JPAEdmMappingModelService implements 
JPAEdmMappingModelAccess {
 
   boolean mappingModelExists = true;
   private JPAEdmMappingModel mappingModel;
+  private InputStream mappingModelStream = null;
   private String mappingModelName;
 
   public JPAEdmMappingModelService(final ODataJPAContext ctx) {
+    JPAEdmExtension ext = null;
     mappingModelName = ctx.getJPAEdmMappingModel();
     if (mappingModelName == null) {
-      mappingModelExists = false;
+      ext = ctx.getJPAEdmExtension();
+      if (ext != null) {
+        mappingModelStream = ext.getJPAEdmMappingModelStream();
+      }
     }
+
+    mappingModelExists = mappingModelName != null || mappingModelStream != 
null ? true : false;
   }
 
   @Override
@@ -194,8 +202,10 @@ public class JPAEdmMappingModelService implements 
JPAEdmMappingModelAccess {
   }
 
   protected InputStream loadMappingModelInputStream() {
+    if (mappingModelStream != null) {
+      return mappingModelStream;
+    }
     InputStream is = 
JPAEdmMappingModelService.class.getClassLoader().getResourceAsStream("../../" + 
mappingModelName);
-
     return is;
 
   }

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/46d83c8e/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/model/JPAEdmNameBuilder.java
----------------------------------------------------------------------
diff --git 
a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/model/JPAEdmNameBuilder.java
 
b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/model/JPAEdmNameBuilder.java
index 1f0e152..75878e6 100644
--- 
a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/model/JPAEdmNameBuilder.java
+++ 
b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/model/JPAEdmNameBuilder.java
@@ -22,7 +22,6 @@ import java.lang.reflect.AnnotatedElement;
 import java.lang.reflect.Field;
 
 import javax.persistence.Column;
-import javax.persistence.JoinColumn;
 import javax.persistence.metamodel.Attribute;
 import javax.persistence.metamodel.ManagedType;
 import javax.persistence.metamodel.PluralAttribute;
@@ -129,6 +128,7 @@ public class JPAEdmNameBuilder {
     Attribute<?, ?> jpaAttribute = view.getJPAAttribute();
     String jpaAttributeName = jpaAttribute.getName();
     String propertyName = null;
+    String[] joinColumnNames = null;
 
     JPAEdmMappingModelAccess mappingModelAccess = 
view.getJPAEdmMappingModelAccess();
     if (mappingModelAccess != null && 
mappingModelAccess.isMappingModelExists()) {
@@ -147,7 +147,8 @@ public class JPAEdmNameBuilder {
     } else if (propertyName == null) {
       propertyName = jpaAttributeName;
       if (isForeignKey == true) {
-        propertyName = FK_PREFIX + UNDERSCORE + propertyName;
+        joinColumnNames = 
view.getJPAJoinColumns().get(view.getJPAJoinColumns().size() - 1);
+        propertyName = FK_PREFIX + UNDERSCORE + joinColumnNames[0];
       }
     }
 
@@ -162,9 +163,8 @@ public class JPAEdmNameBuilder {
       if (column != null) {
         mapping.setJPAColumnName(column.name());
       } else {
-        JoinColumn joinColumn = 
annotatedElement.getAnnotation(JoinColumn.class);
-        if (joinColumn != null) {
-          mapping.setJPAColumnName(joinColumn.name());
+        if (joinColumnNames != null) {
+          mapping.setJPAColumnName(joinColumnNames[0]);
           jpaAttributeName += "." + view.getJPAReferencedAttribute().getName();
         }
       }

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/46d83c8e/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/model/JPATypeConvertor.java
----------------------------------------------------------------------
diff --git 
a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/model/JPATypeConvertor.java
 
b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/model/JPATypeConvertor.java
index 685ee83..8ea1ce3 100644
--- 
a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/model/JPATypeConvertor.java
+++ 
b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/model/JPATypeConvertor.java
@@ -22,8 +22,9 @@ import java.lang.reflect.AnnotatedElement;
 import java.math.BigDecimal;
 import java.sql.Blob;
 import java.sql.Clob;
+import java.sql.Date;
+import java.sql.Timestamp;
 import java.util.Calendar;
-import java.util.Date;
 import java.util.UUID;
 
 import javax.persistence.Lob;
@@ -81,7 +82,8 @@ public class JPATypeConvertor {
       return EdmSimpleTypeKind.Byte;
     } else if (jpaType.equals(Boolean.class) || jpaType.equals(boolean.class)) 
{
       return EdmSimpleTypeKind.Boolean;
-    } else if ((jpaType.equals(Date.class)) || 
(jpaType.equals(Calendar.class))) {
+    } else if ((jpaType.equals(Date.class)) || 
(jpaType.equals(Calendar.class)) ||
+        jpaType.equals(Timestamp.class)) {
       try {
         if ((currentAttribute != null)
             && (determineTemporalType(currentAttribute)

Reply via email to