You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by ch...@apache.org on 2014/05/18 17:02:31 UTC

[1/2] [OLINGO-224] Support for Delta Token and Refactor unit test

Repository: olingo-odata2
Updated Branches:
  refs/heads/master a95331e5a -> df063fd01


http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/df063fd0/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAEntityParserTestForStaticMethods.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAEntityParserTestForStaticMethods.java b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAEntityParserTestForStaticMethods.java
deleted file mode 100644
index efb388d..0000000
--- a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAEntityParserTestForStaticMethods.java
+++ /dev/null
@@ -1,330 +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 static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.io.ByteArrayOutputStream;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.lang.reflect.Method;
-import java.net.URL;
-import java.sql.Blob;
-import java.sql.Clob;
-import java.sql.SQLException;
-
-import javax.sql.rowset.serial.SerialBlob;
-import javax.sql.rowset.serial.SerialClob;
-import javax.sql.rowset.serial.SerialException;
-
-import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPARuntimeException;
-import org.apache.olingo.odata2.jpa.processor.core.common.ODataJPATestConstants;
-import org.junit.Test;
-
-public class JPAEntityParserTestForStaticMethods {
-
-  @Test
-  public void testToStringDefault() {
-
-    Character[] input = new Character[] { 'A', 'B' };
-    assertEquals("AB", JPAEntityParser.toString(input));
-
-  }
-
-  @Test
-  public void testToStringNull() {
-    Character[] input = null;
-    assertNull(JPAEntityParser.toString(input));
-  }
-
-  @Test
-  public void testToStringPartialNull() {
-    Character[] input = new Character[] { 'A', null };
-    assertEquals("A", JPAEntityParser.toString(input));
-  }
-
-  @Test
-  public void testToCharacterArrayDefault() {
-    String input = new String("AB");
-    Character[] ch = JPAEntityParser.toCharacterArray(input);
-
-    assertEquals(2, ch.length);
-    assertTrue(ch[0].equals('A'));
-    assertTrue(ch[1].equals('B'));
-  }
-
-  @Test
-  public void testToCharacterArrayNull() {
-    String input = null;
-    Character[] ch = JPAEntityParser.toCharacterArray(input);
-
-    assertNull(ch);
-  }
-
-  @Test
-  public void testGetPropertyCharacter() {
-    try {
-      Method method = JPAEntityParserTestForStaticMethods.class.getMethod("getCharacter", (Class<?>[]) null);
-      String output = (String) JPAEntityParser.getPropertyValue(method, this);
-      assertEquals("A", output);
-
-    } catch (NoSuchMethodException e) {
-      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
-    } catch (SecurityException e) {
-      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
-    } catch (ODataJPARuntimeException e) {
-      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
-    }
-  }
-
-  @Test
-  public void testGetPropertyCharacterNull() {
-    try {
-      Method method = JPAEntityParserTestForStaticMethods.class.getMethod("getCharacterNull", (Class<?>[]) null);
-      String output = (String) JPAEntityParser.getPropertyValue(method, this);
-      assertNull(output);
-
-    } catch (NoSuchMethodException e) {
-      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
-    } catch (SecurityException e) {
-      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
-    } catch (ODataJPARuntimeException e) {
-      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
-    }
-  }
-
-  @Test
-  public void testGetPropertyCharacterArray() {
-    try {
-      Method method = JPAEntityParserTestForStaticMethods.class.getMethod("getCharacterArray", (Class<?>[]) null);
-      String output = (String) JPAEntityParser.getPropertyValue(method, this);
-      assertEquals("AB", output);
-
-    } catch (NoSuchMethodException e) {
-      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
-    } catch (SecurityException e) {
-      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
-    } catch (ODataJPARuntimeException e) {
-      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
-    }
-  }
-
-  @Test
-  public void testGetPropertyCharacterArrayNull() {
-    try {
-      Method method = JPAEntityParserTestForStaticMethods.class.getMethod("getCharacterArrayNull", (Class<?>[]) null);
-      String output = (String) JPAEntityParser.getPropertyValue(method, this);
-      assertNull(output);
-
-    } catch (NoSuchMethodException e) {
-      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
-    } catch (SecurityException e) {
-      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
-    } catch (ODataJPARuntimeException e) {
-      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
-    }
-  }
-
-  @Test
-  public void testGetPropertyChar() {
-    try {
-      Method method = JPAEntityParserTestForStaticMethods.class.getMethod("getChar", (Class<?>[]) null);
-      String output = (String) JPAEntityParser.getPropertyValue(method, this);
-      assertEquals("A", output);
-
-    } catch (NoSuchMethodException e) {
-      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
-    } catch (SecurityException e) {
-      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
-    } catch (ODataJPARuntimeException e) {
-      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
-    }
-  }
-
-  @Test
-  public void testGetPropertyCharNull() {
-    try {
-      Method method = JPAEntityParserTestForStaticMethods.class.getMethod("getCharNull", (Class<?>[]) null);
-      String output = (String) JPAEntityParser.getPropertyValue(method, this);
-      assertNull(output);
-
-    } catch (NoSuchMethodException e) {
-      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
-    } catch (SecurityException e) {
-      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
-    } catch (ODataJPARuntimeException e) {
-      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
-    }
-  }
-
-  @Test
-  public void testGetPropertyCharArray() {
-    try {
-      Method method = JPAEntityParserTestForStaticMethods.class.getMethod("getCharArray", (Class<?>[]) null);
-      String output = (String) JPAEntityParser.getPropertyValue(method, this);
-      assertEquals("AB", output);
-
-    } catch (NoSuchMethodException e) {
-      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
-    } catch (SecurityException e) {
-      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
-    } catch (ODataJPARuntimeException e) {
-      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
-    }
-  }
-
-  @Test
-  public void testGetPropertyCharArrayNull() {
-    try {
-      Method method = JPAEntityParserTestForStaticMethods.class.getMethod("getCharArrayNull", (Class<?>[]) null);
-      String output = (String) JPAEntityParser.getPropertyValue(method, this);
-      assertNull(output);
-
-    } catch (NoSuchMethodException e) {
-      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
-    } catch (SecurityException e) {
-      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
-    } catch (ODataJPARuntimeException e) {
-      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
-    }
-  }
-
-  @Test
-  public void testGetPropertyCharArrayValueNull() {
-    try {
-      Method method = JPAEntityParserTestForStaticMethods.class.getMethod("getCharArrayValueNull", (Class<?>[]) null);
-      String output = (String) JPAEntityParser.getPropertyValue(method, this);
-      assertEquals("A\u0000", output);
-
-    } catch (NoSuchMethodException e) {
-      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
-    } catch (SecurityException e) {
-      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
-    } catch (ODataJPARuntimeException e) {
-      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
-    }
-  }
-
-  @Test
-  public void testGetString() {
-    char[] expectedChar = new char[] { 'a', 'b', 'c' };
-    try {
-      Clob clob = new SerialClob(expectedChar);
-      String actualString = JPAEntityParser.getString(clob);
-
-      assertEquals(new String(expectedChar), actualString);
-
-    } catch (SerialException e) {
-      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
-    } catch (SQLException e) {
-      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
-    } catch (ODataJPARuntimeException e) {
-      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
-    }
-  }
-
-  @Test
-  public void testGetBytes() {
-    final String fileName = "SalesOrderProcessingMappingModels.xml";
-
-    try {
-      FileInputStream fis = getFileStream(fileName);
-
-      ByteArrayOutputStream baos = new ByteArrayOutputStream();
-      int content = fis.read();
-      while (content != -1) {
-        baos.write(content);
-        content = fis.read();
-      }
-      Blob blob = new SerialBlob(baos.toByteArray());
-      byte[] actualBytes = (byte[]) JPAEntityParser.getBytes(blob);
-      byte[] expectedBytes = baos.toByteArray();
-
-      assertEquals(expectedBytes.length, actualBytes.length);
-      int size = actualBytes.length;
-      int index = 0;
-      while (index < size) {
-        assertEquals(expectedBytes[index], actualBytes[index]);
-        index++;
-      }
-
-    } catch (FileNotFoundException e) {
-      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
-    } catch (SerialException e) {
-      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
-    } catch (SQLException e) {
-      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
-    } catch (IOException e) {
-      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
-    } catch (ODataJPARuntimeException e) {
-      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
-    }
-  }
-
-  private FileInputStream getFileStream(final String name) throws SerialException, FileNotFoundException {
-    final String fileName = "SalesOrderProcessingMappingModels.xml";
-    FileInputStream fis;
-
-    URL fileURL = JPAEntityParserTestForStaticMethods.class.getClassLoader().getResource(fileName);
-    fis = new FileInputStream(fileURL.getPath());
-
-    return fis;
-
-  }
-
-  public Character getCharacter() {
-    return new Character('A');
-  }
-
-  public Character getCharacterNull() {
-    return null;
-  }
-
-  public Character[] getCharacterArray() {
-    return new Character[] { 'A', 'B' };
-  }
-
-  public Character[] getCharacterArrayNull() {
-    return null;
-  }
-
-  public char getChar() {
-    return 'A';
-  }
-
-  public char getCharNull() {
-    return '\u0000';
-  }
-
-  public char[] getCharArray() {
-    return new char[] { 'A', 'B' };
-  }
-
-  public char[] getCharArrayNull() {
-    return null;
-  }
-
-  public char[] getCharArrayValueNull() {
-    return new char[] { 'A', '\u0000' };
-  }
-}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/df063fd0/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAExpandCallBackTest.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAExpandCallBackTest.java b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAExpandCallBackTest.java
index 634df6e..5b0147c 100644
--- a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAExpandCallBackTest.java
+++ b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAExpandCallBackTest.java
@@ -41,6 +41,7 @@ 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.core.callback.JPAExpandCallBack;
 import org.apache.olingo.odata2.jpa.processor.core.common.ODataJPATestConstants;
 import org.apache.olingo.odata2.jpa.processor.core.mock.data.EdmMockUtil;
 import org.junit.Test;

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/df063fd0/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAPageBuilderDeltaTest.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAPageBuilderDeltaTest.java b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAPageBuilderDeltaTest.java
new file mode 100644
index 0000000..3408ae8
--- /dev/null
+++ b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAPageBuilderDeltaTest.java
@@ -0,0 +1,339 @@
+package org.apache.olingo.odata2.jpa.processor.core.access.data;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.olingo.odata2.jpa.processor.core.access.data.JPAPage.JPAPageBuilder;
+import org.junit.Test;
+
+public class JPAPageBuilderDeltaTest {
+
+  private static final int PAGE_SIZE = 10;
+
+  @Test
+  public void testBuildDefaultDelta() {
+    JPAPageBuilder pageBuilder = new JPAPageBuilder();
+
+    JPAPage page = pageBuilder.entities(mockEntities())
+        .pageSize(PAGE_SIZE)
+        .skipToken("10")
+        .build();
+
+    assertEquals(20, page.getNextPage());
+    assertEquals(10, page.getStartPage());
+    assertEquals(PAGE_SIZE, page.getPageSize());
+    assertNotNull(page.getPagedEntities());
+    assertEquals(10, page.getPagedEntities().size());
+
+    List<Object> pagedEntities = page.getPagedEntities();
+
+    assertEquals("9", pagedEntities.get(0));
+    assertEquals("18", pagedEntities.get(9));
+  }
+
+  @Test
+  public void testBuildWithNoSkipTokenDelta() {
+    JPAPageBuilder pageBuilder = new JPAPageBuilder();
+
+    JPAPage page = pageBuilder.entities(mockEntities())
+        .pageSize(PAGE_SIZE)
+        .skipToken("0")
+        .build();
+
+    assertEquals(10, page.getNextPage());
+    assertEquals(0, page.getStartPage());
+    assertEquals(PAGE_SIZE, page.getPageSize());
+    assertNotNull(page.getPagedEntities());
+
+    List<Object> pagedEntities = page.getPagedEntities();
+    assertEquals(10, pagedEntities.size());
+    assertEquals("0", pagedEntities.get(0));
+    assertEquals("9", pagedEntities.get(9));
+  }
+
+  @Test
+  public void testBuildDefaultZeroPageDelta() {
+    JPAPageBuilder pageBuilder = new JPAPageBuilder();
+
+    JPAPage page = pageBuilder.entities(mockEntities())
+        .pageSize(0)
+        .skipToken("10")
+        .build();
+
+    assertEquals(0, page.getNextPage());
+    assertEquals(0, page.getStartPage());
+    assertEquals(0, page.getPageSize());
+    assertNotNull(page.getPagedEntities());
+    assertEquals(0, page.getPagedEntities().size());
+
+  }
+
+  @Test
+  public void testBuildWithNullSkipToken() {
+    JPAPageBuilder pageBuilder = new JPAPageBuilder();
+
+    JPAPage page = pageBuilder.entities(mockEntities())
+        .pageSize(PAGE_SIZE)
+        .skipToken(null)
+        .build();
+
+    assertEquals(10, page.getNextPage());
+    assertEquals(0, page.getStartPage());
+    assertEquals(PAGE_SIZE, page.getPageSize());
+
+    List<Object> pagedEntities = page.getPagedEntities();
+    assertNotNull(pagedEntities);
+    assertEquals("0", pagedEntities.get(0));
+    assertEquals("9", pagedEntities.get(9));
+  }
+
+  @Test
+  public void testBuildWithInvalidSkipToken() {
+    JPAPageBuilder pageBuilder = new JPAPageBuilder();
+    try {
+      pageBuilder.entities(mockEntities())
+          .skipToken("AB");
+    } catch (NumberFormatException e) {
+      return;
+    }
+    fail("Exception Expected");
+  }
+
+  @Test
+  public void testBuildWithTop() {
+    JPAPageBuilder pageBuilder = new JPAPageBuilder();
+
+    JPAPage page = pageBuilder.entities(mockEntities())
+        .pageSize(PAGE_SIZE)
+        .skipToken("20")
+        .top(5)
+        .build();
+
+    assertEquals(0, page.getNextPage());
+    assertEquals(20, page.getStartPage());
+    assertEquals(PAGE_SIZE, page.getPageSize());
+
+    List<Object> pagedEntities = page.getPagedEntities();
+    assertNotNull(pagedEntities);
+    assertEquals(5, pagedEntities.size());
+    assertEquals("19", pagedEntities.get(0));
+    assertEquals("23", pagedEntities.get(4));
+  }
+
+  @Test
+  public void testBuildWithTopZeroPage() {
+    JPAPageBuilder pageBuilder = new JPAPageBuilder();
+    JPAPage page = pageBuilder.entities(mockEntities())
+        .pageSize(0)
+        .skipToken("10")
+        .top(5)
+        .build();
+
+    assertEquals(0, page.getNextPage());
+    assertEquals(0, page.getStartPage());
+    assertEquals(0, page.getPageSize());
+    assertNotNull(page.getPagedEntities());
+    assertEquals(5, page.getPagedEntities().size());
+  }
+
+  @Test
+  public void testBuildWithSkipZeroPage() {
+    JPAPageBuilder pageBuilder = new JPAPageBuilder();
+    JPAPage page = pageBuilder.entities(mockEntities())
+        .pageSize(0)
+        .skipToken("10")
+        .skip(5)
+        .build();
+
+    assertEquals(0, page.getNextPage());
+    assertEquals(0, page.getStartPage());
+    assertEquals(0, page.getPageSize());
+    assertNotNull(page.getPagedEntities());
+
+    assertEquals(0, page.getPagedEntities().size());
+  }
+
+  @Test
+  public void testBuildWithTopSkipZeroPage() {
+    JPAPageBuilder pageBuilder = new JPAPageBuilder();
+    JPAPage page = pageBuilder.entities(mockEntities())
+        .pageSize(0)
+        .skipToken("10")
+        .skip(5)
+        .top(5)
+        .build();
+
+    assertEquals(0, page.getNextPage());
+    assertEquals(0, page.getStartPage());
+    assertEquals(0, page.getPageSize());
+    assertNotNull(page.getPagedEntities());
+    assertEquals(5, page.getPagedEntities().size());
+  }
+
+  @Test
+  public void testBuildWithTopExceeds() {
+    JPAPageBuilder pageBuilder = new JPAPageBuilder();
+    JPAPage page = pageBuilder.entities(mockEntities())
+        .pageSize(PAGE_SIZE)
+        .skipToken("10")
+        .top(15)
+        .build();
+
+    assertEquals(20, page.getNextPage());
+    assertEquals(10, page.getStartPage());
+    assertEquals(PAGE_SIZE, page.getPageSize());
+    List<Object> pagedEntities = page.getPagedEntities();
+    assertNotNull(pagedEntities);
+    assertEquals(10, pagedEntities.size());
+    assertEquals("9", pagedEntities.get(0));
+    assertEquals("18", pagedEntities.get(9));
+  }
+
+  @Test
+  public void testBuildWithTopSkipExceeds() {
+    JPAPageBuilder pageBuilder = new JPAPageBuilder();
+    JPAPage page = pageBuilder.entities(mockEntities())
+        .pageSize(PAGE_SIZE)
+        .skipToken("10")
+        .top(5)
+        .skip(10)
+        .build();
+
+    assertEquals(0, page.getNextPage());
+    assertEquals(10, page.getStartPage());
+    assertEquals(PAGE_SIZE, page.getPageSize());
+    List<Object> pagedEntities = page.getPagedEntities();
+    assertEquals(0, pagedEntities.size());
+
+  }
+
+  @Test
+  public void testBuildWithTopSkipMore() {
+    JPAPageBuilder pageBuilder = new JPAPageBuilder();
+    JPAPage page = pageBuilder.entities(mockEntities())
+        .pageSize(PAGE_SIZE)
+        .skipToken("10")
+        .top(5)
+        .skip(9)
+        .build();
+
+    assertEquals(0, page.getNextPage());
+    assertEquals(10, page.getStartPage());
+    assertEquals(PAGE_SIZE, page.getPageSize());
+    List<Object> pagedEntities = page.getPagedEntities();
+    assertNotNull(pagedEntities);
+
+    assertEquals("18", pagedEntities.get(0));
+    assertEquals(1, pagedEntities.size());
+  }
+
+  @Test
+  public void testBuildWithTopMoreSkip() {
+    JPAPageBuilder pageBuilder = new JPAPageBuilder();
+    JPAPage page = pageBuilder.entities(mockEntities())
+        .pageSize(PAGE_SIZE)
+        .skipToken("10")
+        .top(15)
+        .skip(9)
+        .build();
+
+    assertEquals(0, page.getNextPage());
+    assertEquals(10, page.getStartPage());
+    assertEquals(PAGE_SIZE, page.getPageSize());
+    List<Object> pagedEntities = page.getPagedEntities();
+    assertNotNull(pagedEntities);
+
+    assertEquals("18", pagedEntities.get(0));
+    assertEquals(1, pagedEntities.size());
+  }
+
+  @Test
+  public void testBuildWithTopXSkipX() {
+    JPAPageBuilder pageBuilder = new JPAPageBuilder();
+    JPAPage page = pageBuilder.entities(mockEntities())
+        .pageSize(PAGE_SIZE)
+        .skipToken("10")
+        .top(15)
+        .skip(15)
+        .build();
+
+    assertEquals(0, page.getNextPage());
+    assertEquals(10, page.getStartPage());
+    assertEquals(PAGE_SIZE, page.getPageSize());
+    List<Object> pagedEntities = page.getPagedEntities();
+    assertNotNull(pagedEntities);
+
+    assertEquals(0, pagedEntities.size());
+  }
+
+  @Test
+  public void testBuildWithNegativeTop() {
+    JPAPageBuilder pageBuilder = new JPAPageBuilder();
+    JPAPage page = pageBuilder.entities(mockEntities())
+        .pageSize(PAGE_SIZE)
+        .skipToken("10")
+        .top(-5)
+        .build();
+
+    assertEquals(20, page.getNextPage());
+    assertEquals(10, page.getStartPage());
+    assertEquals(PAGE_SIZE, page.getPageSize());
+    List<Object> pagedEntities = page.getPagedEntities();
+    assertNotNull(pagedEntities);
+
+    assertEquals("9", pagedEntities.get(0));
+    assertEquals(10, pagedEntities.size());
+  }
+
+  @Test
+  public void testBuildWithNegativeTopSkipToken() {
+    JPAPageBuilder pageBuilder = new JPAPageBuilder();
+    JPAPage page = pageBuilder.entities(mockEntities())
+        .pageSize(PAGE_SIZE)
+        .skipToken("-10")
+        .top(-5)
+        .skip(-1)
+        .build();
+
+    assertEquals(10, page.getNextPage());
+    assertEquals(0, page.getStartPage());
+    assertEquals(PAGE_SIZE, page.getPageSize());
+    List<Object> pagedEntities = page.getPagedEntities();
+    assertNotNull(pagedEntities);
+
+    assertEquals(10, pagedEntities.size());
+
+  }
+
+  @Test
+  public void testBuildWithNoRecords() {
+    JPAPageBuilder pageBuilder = new JPAPageBuilder();
+    JPAPage page = pageBuilder.entities(mockEntities())
+        .pageSize(PAGE_SIZE)
+        .skipToken("10")
+        .top(1)
+        .skip(1)
+        .build();
+
+    assertEquals(0, page.getNextPage());
+    assertEquals(10, page.getStartPage());
+    assertEquals(PAGE_SIZE, page.getPageSize());
+    List<Object> pagedEntities = page.getPagedEntities();
+    assertNotNull(pagedEntities);
+
+    assertEquals(1, pagedEntities.size());
+    assertEquals("10", pagedEntities.get(0));
+  }
+
+  private List<Object> mockEntities() {
+    List<Object> entities = new ArrayList<Object>();
+    for (int i = 0; i < 30; i++) {
+      entities.add(String.valueOf(i));
+    }
+    return entities;
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/df063fd0/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAPageBuilderTest.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAPageBuilderTest.java b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAPageBuilderTest.java
index d775be3..b9e6894 100644
--- a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAPageBuilderTest.java
+++ b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAPageBuilderTest.java
@@ -52,7 +52,7 @@ public class JPAPageBuilderTest {
         .skipToken("10")
         .build();
 
-    assertEquals(20, page.getNextPage());
+    assertEquals(0, page.getNextPage());
     assertEquals(10, page.getStartPage());
     assertEquals(PAGE_SIZE, page.getPageSize());
     assertNotNull(page.getPagedEntities());
@@ -62,6 +62,8 @@ public class JPAPageBuilderTest {
     assertEquals(10, query.getMaxResults());
   }
 
+
+
   @Test
   public void testBuildDefaultZeroPage() {
     JPAPageBuilder pageBuilder = new JPAPageBuilder();
@@ -82,7 +84,7 @@ public class JPAPageBuilderTest {
     assertEquals(0, query.getMaxResults());
   }
 
-  @Test
+   @Test
   public void testBuildWithNoSkipToken() {
     JPAPageBuilder pageBuilder = new JPAPageBuilder();
     Query query = mockQuery(false);
@@ -92,7 +94,7 @@ public class JPAPageBuilderTest {
         .skipToken("0")
         .build();
 
-    assertEquals(10, page.getNextPage());
+    assertEquals(0, page.getNextPage());
     assertEquals(0, page.getStartPage());
     assertEquals(PAGE_SIZE, page.getPageSize());
     assertNotNull(page.getPagedEntities());
@@ -112,7 +114,7 @@ public class JPAPageBuilderTest {
         .skipToken(null)
         .build();
 
-    assertEquals(10, page.getNextPage());
+    assertEquals(0, page.getNextPage());
     assertEquals(0, page.getStartPage());
     assertEquals(PAGE_SIZE, page.getPageSize());
     assertNotNull(page.getPagedEntities());
@@ -146,7 +148,7 @@ public class JPAPageBuilderTest {
         .top(5)
         .build();
 
-    assertEquals(20, page.getNextPage());
+    assertEquals(0, page.getNextPage());
     assertEquals(10, page.getStartPage());
     assertEquals(PAGE_SIZE, page.getPageSize());
     assertNotNull(page.getPagedEntities());
@@ -227,7 +229,7 @@ public class JPAPageBuilderTest {
         .top(15)
         .build();
 
-    assertEquals(20, page.getNextPage());
+    assertEquals(0, page.getNextPage());
     assertEquals(10, page.getStartPage());
     assertEquals(PAGE_SIZE, page.getPageSize());
     assertNotNull(page.getPagedEntities());
@@ -269,7 +271,7 @@ public class JPAPageBuilderTest {
         .skip(9)
         .build();
 
-    assertEquals(20, page.getNextPage());
+    assertEquals(0, page.getNextPage());
     assertEquals(10, page.getStartPage());
     assertEquals(PAGE_SIZE, page.getPageSize());
     assertNotNull(page.getPagedEntities());
@@ -290,7 +292,7 @@ public class JPAPageBuilderTest {
         .skip(9)
         .build();
 
-    assertEquals(20, page.getNextPage());
+    assertEquals(0, page.getNextPage());
     assertEquals(10, page.getStartPage());
     assertEquals(PAGE_SIZE, page.getPageSize());
     assertNotNull(page.getPagedEntities());
@@ -331,7 +333,7 @@ public class JPAPageBuilderTest {
         .top(-5)
         .build();
 
-    assertEquals(20, page.getNextPage());
+    assertEquals(0, page.getNextPage());
     assertEquals(10, page.getStartPage());
     assertEquals(PAGE_SIZE, page.getPageSize());
     assertNotNull(page.getPagedEntities());
@@ -352,7 +354,7 @@ public class JPAPageBuilderTest {
         .skip(-1)
         .build();
 
-    assertEquals(10, page.getNextPage());
+    assertEquals(0, page.getNextPage());
     assertEquals(0, page.getStartPage());
     assertEquals(PAGE_SIZE, page.getPageSize());
     assertNotNull(page.getPagedEntities());
@@ -556,4 +558,6 @@ public class JPAPageBuilderTest {
       }
     };
   }
+
+
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/df063fd0/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAProcessorImplTest.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAProcessorImplTest.java b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAProcessorImplTest.java
index 23fe91c..e74dc52 100644
--- a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAProcessorImplTest.java
+++ b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAProcessorImplTest.java
@@ -53,6 +53,7 @@ import org.apache.olingo.odata2.api.edm.EdmProperty;
 import org.apache.olingo.odata2.api.edm.EdmType;
 import org.apache.olingo.odata2.api.edm.EdmTypeKind;
 import org.apache.olingo.odata2.api.edm.EdmTyped;
+import org.apache.olingo.odata2.api.edm.provider.Mapping;
 import org.apache.olingo.odata2.api.exception.ODataException;
 import org.apache.olingo.odata2.api.processor.ODataContext;
 import org.apache.olingo.odata2.api.uri.KeyPredicate;
@@ -69,6 +70,7 @@ import org.apache.olingo.odata2.jpa.processor.api.access.JPAPaging;
 import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPAModelException;
 import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPARuntimeException;
 import org.apache.olingo.odata2.jpa.processor.core.common.ODataJPATestConstants;
+import org.apache.olingo.odata2.jpa.processor.core.model.JPAEdmMappingImpl;
 import org.easymock.EasyMock;
 import org.junit.Before;
 import org.junit.Test;
@@ -192,8 +194,8 @@ public class JPAProcessorImplTest {
     EasyMock.expect(objUriInfo.getSkipToken()).andReturn("5");
     EasyMock.expect(objUriInfo.getInlineCount()).andStubReturn(getInlineCount());
     EasyMock.expect(objUriInfo.getFilter()).andStubReturn(getFilter());
-    // EasyMock.expect(objUriInfo.getFunctionImport()).andStubReturn(getFunctionImport());
     EasyMock.expect(objUriInfo.getFunctionImport()).andStubReturn(null);
+    EasyMock.expect(objUriInfo.getCustomQueryOptions()).andStubReturn(null);
     EasyMock.replay(objUriInfo);
     return objUriInfo;
   }
@@ -576,13 +578,13 @@ public class JPAProcessorImplTest {
   }
 
   private EdmMapping getEdmMappingMockedObj(final String propertyName) {
-    EdmMapping mockedEdmMapping = EasyMock.createMock(EdmMapping.class);
+    EdmMapping mockedEdmMapping = new JPAEdmMappingImpl();
     if (propertyName.equalsIgnoreCase(SALES_ORDER)) {
-      EasyMock.expect(mockedEdmMapping.getInternalName()).andStubReturn(SALES_ORDER_HEADERS);
+      ((Mapping) mockedEdmMapping).setInternalName(SALES_ORDER_HEADERS);
     } else {
-      EasyMock.expect(mockedEdmMapping.getInternalName()).andStubReturn(propertyName);
+      ((Mapping) mockedEdmMapping).setInternalName(propertyName);
     }
-    EasyMock.replay(mockedEdmMapping);
+
     return mockedEdmMapping;
   }
 

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/df063fd0/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/model/JPAEdmNameBuilderTest.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/model/JPAEdmNameBuilderTest.java b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/model/JPAEdmNameBuilderTest.java
index aebea64..2c3c194 100644
--- a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/model/JPAEdmNameBuilderTest.java
+++ b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/model/JPAEdmNameBuilderTest.java
@@ -49,7 +49,7 @@ public class JPAEdmNameBuilderTest {
     EasyMock.expect(propertyView.getEdmSimpleProperty()).andStubReturn(simpleProperty);
     EasyMock.replay(propertyView);
 
-    JPAEdmNameBuilder.build(propertyView, false, false,false);
+    JPAEdmNameBuilder.build(propertyView, false, false, false);
     assertEquals("Id", simpleProperty.getName());
   }
 
@@ -69,7 +69,7 @@ public class JPAEdmNameBuilderTest {
     EasyMock.expect(propertyView.getEdmSimpleProperty()).andStubReturn(simpleProperty);
     EasyMock.replay(propertyView);
 
-    JPAEdmNameBuilder.build(propertyView, false, true,false);
+    JPAEdmNameBuilder.build(propertyView, false, true, false);
     assertEquals("id", simpleProperty.getName());
   }
 

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/df063fd0/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/model/JPAEdmEntityContainerTest.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/model/JPAEdmEntityContainerTest.java b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/model/JPAEdmEntityContainerTest.java
index f94fa6f..340cdde 100644
--- a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/model/JPAEdmEntityContainerTest.java
+++ b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/model/JPAEdmEntityContainerTest.java
@@ -179,6 +179,11 @@ public class JPAEdmEntityContainerTest extends JPAEdmTestModelView {
       public String getName() {
         return "SalesOrderHeader";
       }
+
+      @Override
+      public Class<String> getJavaType() {
+        return (Class<String>) java.lang.String.class;
+      }
     }
   }
 

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/df063fd0/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/model/JPAEdmEntitySetTest.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/model/JPAEdmEntitySetTest.java b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/model/JPAEdmEntitySetTest.java
index 6994dd9..6374206 100644
--- a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/model/JPAEdmEntitySetTest.java
+++ b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/model/JPAEdmEntitySetTest.java
@@ -219,6 +219,11 @@ public class JPAEdmEntitySetTest extends JPAEdmTestModelView {
       public String getName() {
         return "SalesOrderHeader";
       }
+
+      @Override
+      public Class<String> getJavaType() {
+        return (Class<String>) java.lang.String.class;
+      }
     }
   }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/df063fd0/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/model/JPAEdmEntityTypeTest.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/model/JPAEdmEntityTypeTest.java b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/model/JPAEdmEntityTypeTest.java
index 8c79ece..15b8076 100644
--- a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/model/JPAEdmEntityTypeTest.java
+++ b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/model/JPAEdmEntityTypeTest.java
@@ -144,6 +144,11 @@ public class JPAEdmEntityTypeTest extends JPAEdmTestModelView {
       public String getName() {
         return "SalesOrderHeader";
       }
+
+      @Override
+      public Class<String> getJavaType() {
+        return (Class<String>) java.lang.String.class;
+      }
     }
   }
 

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/df063fd0/odata2-jpa-processor/jpa-ref/pom.xml
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-ref/pom.xml b/odata2-jpa-processor/jpa-ref/pom.xml
index 26d3b41..1a8e8aa 100644
--- a/odata2-jpa-processor/jpa-ref/pom.xml
+++ b/odata2-jpa-processor/jpa-ref/pom.xml
@@ -90,6 +90,13 @@
 			<version>${project.version}</version>
 		</dependency>
 
+		<!-- OData API Support -->
+		<dependency>
+			<groupId>org.apache.olingo</groupId>
+			<artifactId>olingo-odata2-jpa-processor-api</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+
 		<!-- JUnits -->
 		<dependency>
 			<groupId>junit</groupId>


[2/2] git commit: [OLINGO-224] Support for Delta Token and Refactor unit test

Posted by ch...@apache.org.
[OLINGO-224] Support for Delta Token and Refactor unit test


Signed-off-by: Chandan V A <ch...@sap.com>

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

Branch: refs/heads/master
Commit: df063fd01715ca06dae4535c38aa6aa7bf98421f
Parents: a95331e
Author: Chandan V A <ch...@sap.com>
Authored: Sun May 18 20:32:08 2014 +0530
Committer: Chandan V A <ch...@sap.com>
Committed: Sun May 18 20:32:08 2014 +0530

----------------------------------------------------------------------
 .../jpa/processor/api/ODataJPAProcessor.java    |   8 +
 .../processor/api/ODataJPATombstoneContext.java |  90 +++++
 .../api/ODataJPATombstoneEntityListener.java    |  58 ++++
 .../jpa/processor/api/model/JPAEdmMapping.java  |  16 +
 .../core/ODataJPAProcessorDefault.java          |   2 +
 .../core/ODataJPAResponseBuilderDefault.java    |  27 +-
 .../core/access/data/JPAExpandCallBack.java     | 221 ------------
 .../jpa/processor/core/access/data/JPAPage.java |  81 +++--
 .../core/access/data/JPAProcessorImpl.java      |  96 +++++-
 .../core/callback/JPAExpandCallBack.java        | 222 ++++++++++++
 .../core/callback/JPATombstoneCallBack.java     |  60 ++++
 .../processor/core/model/JPAEdmEntityType.java  |  18 +
 .../processor/core/model/JPAEdmMappingImpl.java |  13 +
 .../JPAEntityParserForStaticMethodTest.java     | 330 ++++++++++++++++++
 .../JPAEntityParserTestForStaticMethods.java    | 330 ------------------
 .../core/access/data/JPAExpandCallBackTest.java |   1 +
 .../access/data/JPAPageBuilderDeltaTest.java    | 339 +++++++++++++++++++
 .../core/access/data/JPAPageBuilderTest.java    |  24 +-
 .../core/access/data/JPAProcessorImplTest.java  |  12 +-
 .../access/model/JPAEdmNameBuilderTest.java     |   4 +-
 .../core/model/JPAEdmEntityContainerTest.java   |   5 +
 .../core/model/JPAEdmEntitySetTest.java         |   5 +
 .../core/model/JPAEdmEntityTypeTest.java        |   5 +
 odata2-jpa-processor/jpa-ref/pom.xml            |   7 +
 24 files changed, 1365 insertions(+), 609 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/df063fd0/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/df063fd0/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..cb946a0
--- /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/df063fd0/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..f120ab9
--- /dev/null
+++ b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/ODataJPATombstoneEntityListener.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * 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/df063fd0/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/df063fd0/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..b685db3 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
@@ -55,6 +55,8 @@ public class ODataJPAProcessorDefault extends ODataJPAProcessor {
     ODataResponse oDataResponse =
         responseBuilder.build(uriParserResultView, jpaEntities, contentType);
 
+    close();
+
     return oDataResponse;
   }
 

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/df063fd0/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/df063fd0/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/df063fd0/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..281d7ce 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(List<Object> result) {
+      this.entities = result;
+      return this;
+    }
   }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/df063fd0/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..a7bcf35 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(List<Object> result, 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/df063fd0/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/callback/JPAExpandCallBack.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/callback/JPAExpandCallBack.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/callback/JPAExpandCallBack.java
new file mode 100644
index 0000000..19bcf77
--- /dev/null
+++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/callback/JPAExpandCallBack.java
@@ -0,0 +1,222 @@
+/*******************************************************************************
+ * 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.callback;
+
+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;
+import org.apache.olingo.odata2.jpa.processor.core.access.data.JPAEntityParser;
+
+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/df063fd0/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/callback/JPATombstoneCallBack.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/callback/JPATombstoneCallBack.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/callback/JPATombstoneCallBack.java
new file mode 100644
index 0000000..6ae9b2b
--- /dev/null
+++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/callback/JPATombstoneCallBack.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.core.callback;
+
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.ep.callback.TombstoneCallback;
+import org.apache.olingo.odata2.api.ep.callback.TombstoneCallbackResult;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetUriInfo;
+
+public class JPATombstoneCallBack implements TombstoneCallback {
+
+  private static final String DELTA_TOKEN_STRING = "?!deltatoken=";
+  private String baseUri;
+  private String deltaTokenValue;
+  private GetEntitySetUriInfo resultsView;
+
+  public JPATombstoneCallBack(final String baseUri, final GetEntitySetUriInfo resultsView,
+      final String deltaTokenValue) {
+    this.baseUri = baseUri;
+    this.deltaTokenValue = deltaTokenValue;
+    this.resultsView = resultsView;
+  }
+
+  @Override
+  public TombstoneCallbackResult getTombstoneCallbackResult() {
+    TombstoneCallbackResult jpaTombstoneCallBackResult = new TombstoneCallbackResult();
+
+    jpaTombstoneCallBackResult.setDeltaLink(buildToken());
+    return jpaTombstoneCallBackResult;
+  }
+
+  private String buildToken() {
+    StringBuilder tokenBuilder = new StringBuilder();
+    tokenBuilder.append(baseUri);
+    try {
+      tokenBuilder.append(resultsView.getTargetEntitySet().getName());
+    } catch (EdmException e) {
+      // Nothing
+    }
+    tokenBuilder.append(DELTA_TOKEN_STRING);
+    tokenBuilder.append(deltaTokenValue);
+    return tokenBuilder.toString();
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/df063fd0/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/model/JPAEdmEntityType.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/model/JPAEdmEntityType.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/model/JPAEdmEntityType.java
index a127c1e..eea7254 100644
--- a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/model/JPAEdmEntityType.java
+++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/model/JPAEdmEntityType.java
@@ -25,13 +25,17 @@ import java.util.List;
 import java.util.ListIterator;
 import java.util.Set;
 
+import javax.persistence.EntityListeners;
+
 import org.apache.olingo.odata2.api.edm.provider.EntityType;
+import org.apache.olingo.odata2.jpa.processor.api.ODataJPATombstoneEntityListener;
 import org.apache.olingo.odata2.jpa.processor.api.access.JPAEdmBuilder;
 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.exception.ODataJPARuntimeException;
 import org.apache.olingo.odata2.jpa.processor.api.model.JPAEdmEntityTypeView;
 import org.apache.olingo.odata2.jpa.processor.api.model.JPAEdmKeyView;
+import org.apache.olingo.odata2.jpa.processor.api.model.JPAEdmMapping;
 import org.apache.olingo.odata2.jpa.processor.api.model.JPAEdmNavigationPropertyView;
 import org.apache.olingo.odata2.jpa.processor.api.model.JPAEdmPropertyView;
 import org.apache.olingo.odata2.jpa.processor.api.model.JPAEdmSchemaView;
@@ -83,6 +87,7 @@ public class JPAEdmEntityType extends JPAEdmBaseViewImpl implements JPAEdmEntity
 
   private class JPAEdmEntityTypeBuilder implements JPAEdmBuilder {
 
+    @SuppressWarnings("unchecked")
     @Override
     public void build() throws ODataJPAModelException, ODataJPARuntimeException {
 
@@ -105,7 +110,20 @@ public class JPAEdmEntityType extends JPAEdmBaseViewImpl implements JPAEdmEntity
         }
 
         JPAEdmNameBuilder.build(JPAEdmEntityType.this);
+        JPAEdmMapping jpaEdmMapping = (JPAEdmMapping) currentEdmEntityType.getMapping();
+        EntityListeners entityListners = currentJPAEntityType.getJavaType().getAnnotation(EntityListeners.class);
+        if (entityListners != null) {
+          for (Class<? extends ODataJPATombstoneEntityListener> entityListner : entityListners.value())
+          {
+            try {
+              jpaEdmMapping.setODataJPATombstoneEntityListener(entityListner);
+              break;
+            } catch (ClassCastException e) {
+              continue;
+            }
 
+          }
+        }
         JPAEdmPropertyView propertyView = new JPAEdmProperty(schemaView);
         propertyView.getBuilder().build();
 

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/df063fd0/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/model/JPAEdmMappingImpl.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/model/JPAEdmMappingImpl.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/model/JPAEdmMappingImpl.java
index fc9f3fd..5944191 100644
--- a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/model/JPAEdmMappingImpl.java
+++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/model/JPAEdmMappingImpl.java
@@ -19,12 +19,14 @@
 package org.apache.olingo.odata2.jpa.processor.core.model;
 
 import org.apache.olingo.odata2.api.edm.provider.Mapping;
+import org.apache.olingo.odata2.jpa.processor.api.ODataJPATombstoneEntityListener;
 import org.apache.olingo.odata2.jpa.processor.api.model.JPAEdmMapping;
 
 public class JPAEdmMappingImpl extends Mapping implements JPAEdmMapping {
 
   private String columnName = null;
   private Class<?> type = null;
+  private Class<? extends ODataJPATombstoneEntityListener> entityListener = null;
 
   @Override
   public void setJPAColumnName(final String name) {
@@ -47,4 +49,15 @@ public class JPAEdmMappingImpl extends Mapping implements JPAEdmMapping {
   public Class<?> getJPAType() {
     return type;
   }
+
+  @Override
+  public void setODataJPATombstoneEntityListener(
+      final Class<? extends ODataJPATombstoneEntityListener> entityListener) {
+    this.entityListener = entityListener;
+  }
+
+  @Override
+  public Class<? extends ODataJPATombstoneEntityListener> getODataJPATombstoneEntityListener() {
+    return entityListener;
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/df063fd0/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAEntityParserForStaticMethodTest.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAEntityParserForStaticMethodTest.java b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAEntityParserForStaticMethodTest.java
new file mode 100644
index 0000000..7d09a18
--- /dev/null
+++ b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAEntityParserForStaticMethodTest.java
@@ -0,0 +1,330 @@
+/*******************************************************************************
+ * 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.SQLException;
+
+import javax.sql.rowset.serial.SerialBlob;
+import javax.sql.rowset.serial.SerialClob;
+import javax.sql.rowset.serial.SerialException;
+
+import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.jpa.processor.core.common.ODataJPATestConstants;
+import org.junit.Test;
+
+public class JPAEntityParserForStaticMethodTest {
+
+  @Test
+  public void testToStringDefault() {
+
+    Character[] input = new Character[] { 'A', 'B' };
+    assertEquals("AB", JPAEntityParser.toString(input));
+
+  }
+
+  @Test
+  public void testToStringNull() {
+    Character[] input = null;
+    assertNull(JPAEntityParser.toString(input));
+  }
+
+  @Test
+  public void testToStringPartialNull() {
+    Character[] input = new Character[] { 'A', null };
+    assertEquals("A", JPAEntityParser.toString(input));
+  }
+
+  @Test
+  public void testToCharacterArrayDefault() {
+    String input = new String("AB");
+    Character[] ch = JPAEntityParser.toCharacterArray(input);
+
+    assertEquals(2, ch.length);
+    assertTrue(ch[0].equals('A'));
+    assertTrue(ch[1].equals('B'));
+  }
+
+  @Test
+  public void testToCharacterArrayNull() {
+    String input = null;
+    Character[] ch = JPAEntityParser.toCharacterArray(input);
+
+    assertNull(ch);
+  }
+
+  @Test
+  public void testGetPropertyCharacter() {
+    try {
+      Method method = JPAEntityParserForStaticMethodTest.class.getMethod("getCharacter", (Class<?>[]) null);
+      String output = (String) JPAEntityParser.getPropertyValue(method, this);
+      assertEquals("A", output);
+
+    } catch (NoSuchMethodException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (SecurityException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testGetPropertyCharacterNull() {
+    try {
+      Method method = JPAEntityParserForStaticMethodTest.class.getMethod("getCharacterNull", (Class<?>[]) null);
+      String output = (String) JPAEntityParser.getPropertyValue(method, this);
+      assertNull(output);
+
+    } catch (NoSuchMethodException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (SecurityException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testGetPropertyCharacterArray() {
+    try {
+      Method method = JPAEntityParserForStaticMethodTest.class.getMethod("getCharacterArray", (Class<?>[]) null);
+      String output = (String) JPAEntityParser.getPropertyValue(method, this);
+      assertEquals("AB", output);
+
+    } catch (NoSuchMethodException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (SecurityException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testGetPropertyCharacterArrayNull() {
+    try {
+      Method method = JPAEntityParserForStaticMethodTest.class.getMethod("getCharacterArrayNull", (Class<?>[]) null);
+      String output = (String) JPAEntityParser.getPropertyValue(method, this);
+      assertNull(output);
+
+    } catch (NoSuchMethodException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (SecurityException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testGetPropertyChar() {
+    try {
+      Method method = JPAEntityParserForStaticMethodTest.class.getMethod("getChar", (Class<?>[]) null);
+      String output = (String) JPAEntityParser.getPropertyValue(method, this);
+      assertEquals("A", output);
+
+    } catch (NoSuchMethodException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (SecurityException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testGetPropertyCharNull() {
+    try {
+      Method method = JPAEntityParserForStaticMethodTest.class.getMethod("getCharNull", (Class<?>[]) null);
+      String output = (String) JPAEntityParser.getPropertyValue(method, this);
+      assertNull(output);
+
+    } catch (NoSuchMethodException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (SecurityException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testGetPropertyCharArray() {
+    try {
+      Method method = JPAEntityParserForStaticMethodTest.class.getMethod("getCharArray", (Class<?>[]) null);
+      String output = (String) JPAEntityParser.getPropertyValue(method, this);
+      assertEquals("AB", output);
+
+    } catch (NoSuchMethodException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (SecurityException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testGetPropertyCharArrayNull() {
+    try {
+      Method method = JPAEntityParserForStaticMethodTest.class.getMethod("getCharArrayNull", (Class<?>[]) null);
+      String output = (String) JPAEntityParser.getPropertyValue(method, this);
+      assertNull(output);
+
+    } catch (NoSuchMethodException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (SecurityException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testGetPropertyCharArrayValueNull() {
+    try {
+      Method method = JPAEntityParserForStaticMethodTest.class.getMethod("getCharArrayValueNull", (Class<?>[]) null);
+      String output = (String) JPAEntityParser.getPropertyValue(method, this);
+      assertEquals("A\u0000", output);
+
+    } catch (NoSuchMethodException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (SecurityException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testGetString() {
+    char[] expectedChar = new char[] { 'a', 'b', 'c' };
+    try {
+      Clob clob = new SerialClob(expectedChar);
+      String actualString = JPAEntityParser.getString(clob);
+
+      assertEquals(new String(expectedChar), actualString);
+
+    } catch (SerialException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (SQLException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testGetBytes() {
+    final String fileName = "SalesOrderProcessingMappingModels.xml";
+
+    try {
+      FileInputStream fis = getFileStream(fileName);
+
+      ByteArrayOutputStream baos = new ByteArrayOutputStream();
+      int content = fis.read();
+      while (content != -1) {
+        baos.write(content);
+        content = fis.read();
+      }
+      Blob blob = new SerialBlob(baos.toByteArray());
+      byte[] actualBytes = (byte[]) JPAEntityParser.getBytes(blob);
+      byte[] expectedBytes = baos.toByteArray();
+
+      assertEquals(expectedBytes.length, actualBytes.length);
+      int size = actualBytes.length;
+      int index = 0;
+      while (index < size) {
+        assertEquals(expectedBytes[index], actualBytes[index]);
+        index++;
+      }
+
+    } catch (FileNotFoundException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (SerialException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (SQLException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (IOException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  private FileInputStream getFileStream(final String name) throws SerialException, FileNotFoundException {
+    final String fileName = "SalesOrderProcessingMappingModels.xml";
+    FileInputStream fis;
+
+    URL fileURL = JPAEntityParserForStaticMethodTest.class.getClassLoader().getResource(fileName);
+    fis = new FileInputStream(fileURL.getPath());
+
+    return fis;
+
+  }
+
+  public Character getCharacter() {
+    return new Character('A');
+  }
+
+  public Character getCharacterNull() {
+    return null;
+  }
+
+  public Character[] getCharacterArray() {
+    return new Character[] { 'A', 'B' };
+  }
+
+  public Character[] getCharacterArrayNull() {
+    return null;
+  }
+
+  public char getChar() {
+    return 'A';
+  }
+
+  public char getCharNull() {
+    return '\u0000';
+  }
+
+  public char[] getCharArray() {
+    return new char[] { 'A', 'B' };
+  }
+
+  public char[] getCharArrayNull() {
+    return null;
+  }
+
+  public char[] getCharArrayValueNull() {
+    return new char[] { 'A', '\u0000' };
+  }
+}