You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by mi...@apache.org on 2014/03/16 10:06:13 UTC
[24/50] [abbrv] git commit: [OLINGO-27] - Implement Server side
paging in OData2 JPA Processor - Enhance the reference scenario to illustrate
server side paging
[OLINGO-27] - Implement Server side paging in OData2 JPA Processor
- Enhance the reference scenario to illustrate server side paging
Signed-off-by: Chandan V A <ch...@sap.com>
Project: http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/commit/4aad349f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/tree/4aad349f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/diff/4aad349f
Branch: refs/heads/Olingo-129_PocJpaDataStore
Commit: 4aad349f8ea260abb7e6f38bab072ccfd9c5300c
Parents: 6b9a4e6
Author: Chandan V A <ch...@sap.com>
Authored: Sun Feb 16 13:05:04 2014 +0530
Committer: Chandan V A <ch...@sap.com>
Committed: Sun Feb 16 13:05:04 2014 +0530
----------------------------------------------------------------------
.../jpa/processor/api/ODataJPAContext.java | 24 +
.../jpa/processor/api/access/JPAPaging.java | 32 ++
.../jpa/processor/api/jpql/JPQLContext.java | 34 +-
.../jpa/processor/core/ODataJPAContextImpl.java | 23 +
.../core/ODataJPAResponseBuilderDefault.java | 28 +-
.../jpa/processor/core/access/data/JPAPage.java | 168 ++++++
.../core/access/data/JPAProcessorImpl.java | 55 +-
.../core/jpql/JPQLJoinSelectContext.java | 4 +
.../processor/core/jpql/JPQLSelectContext.java | 8 +-
.../core/ODataJPAResponseBuilderTest.java | 41 ++
.../core/access/data/JPAPageBuilderTest.java | 541 +++++++++++++++++++
.../core/access/data/JPAProcessorImplTest.java | 187 ++++++-
.../ref/web/JPAReferenceServiceFactory.java | 3 +-
.../jpa-web/src/main/webapp/index.jsp | 15 +-
14 files changed, 1129 insertions(+), 34 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/4aad349f/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/ODataJPAContext.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/ODataJPAContext.java b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/ODataJPAContext.java
index f1e529c..9a57bf3 100644
--- a/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/ODataJPAContext.java
+++ b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/ODataJPAContext.java
@@ -24,6 +24,7 @@ import javax.persistence.EntityManagerFactory;
import org.apache.olingo.odata2.api.edm.provider.EdmProvider;
import org.apache.olingo.odata2.api.processor.ODataContext;
import org.apache.olingo.odata2.api.processor.ODataProcessor;
+import org.apache.olingo.odata2.jpa.processor.api.access.JPAPaging;
import org.apache.olingo.odata2.jpa.processor.api.model.JPAEdmExtension;
/**
@@ -203,4 +204,27 @@ public interface ODataJPAContext {
*/
public boolean getDefaultNaming();
+ /**
+ * The method gets the server side page size to the context
+ * @return the page size
+ */
+ public int getPageSize();
+
+ /**
+ * The method sets the server side page size to the context
+ * @param size
+ */
+ public void setPageSize(int size);
+
+ /**
+ * The method sets the server side paging object
+ * @param an instance of type {@link org.apache.olingo.odata2.jpa.processor.api.access.JPAPaging}
+ */
+ public void setPaging(JPAPaging paging);
+
+ /**
+ * The method returns the server side paging object
+ * @return an instance of type {@link org.apache.olingo.odata2.jpa.processor.api.access.JPAPaging}
+ */
+ public JPAPaging getPaging();
}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/4aad349f/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/access/JPAPaging.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/access/JPAPaging.java b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/access/JPAPaging.java
new file mode 100644
index 0000000..2e3881f
--- /dev/null
+++ b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/access/JPAPaging.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.olingo.odata2.jpa.processor.api.access;
+
+import java.util.List;
+
+public interface JPAPaging {
+ public int getPageSize();
+
+ public List<Object> getPagedEntities();
+
+ public int getNextPage();
+
+ public int getStartPage();
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/4aad349f/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/jpql/JPQLContext.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/jpql/JPQLContext.java b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/jpql/JPQLContext.java
index 0226300..a6230ad 100644
--- a/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/jpql/JPQLContext.java
+++ b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/jpql/JPQLContext.java
@@ -52,6 +52,7 @@ public abstract class JPQLContext implements JPQLContextView {
* The type of JPQL context. Based on the type JPQL statements can be built.
*/
protected JPQLContextType type;
+ protected boolean pagingRequested = false;
/**
* sets JPA Entity Name into the context
@@ -107,6 +108,10 @@ public abstract class JPQLContext implements JPQLContextView {
return type;
}
+ protected void isPagingRequested(final boolean pagingRequested) {
+ this.pagingRequested = pagingRequested;
+ }
+
/**
* the method returns an instance of type
* {@link org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContext.JPQLContextBuilder} based on the
@@ -122,7 +127,28 @@ public abstract class JPQLContext implements JPQLContextView {
*/
public final static JPQLContextBuilder createBuilder(final JPQLContextType contextType, final Object resultsView)
throws ODataJPARuntimeException {
- return JPQLContextBuilder.create(contextType, resultsView);
+ return JPQLContextBuilder.create(contextType, resultsView, false);
+ }
+
+ /**
+ * the method returns an instance of type
+ * {@link org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContext.JPQLContextBuilder} based on the
+ * JPQLContextType. The context builder can be used for
+ * building different JPQL contexts.
+ *
+ * @param contextType
+ * is the JPQLContextType
+ * @param resultsView
+ * is the OData request view
+ * @param withPaging
+ * indicates whether to build the context with paging
+ * @return an instance of type {@link org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContext.JPQLContextBuilder}
+ * @throws ODataJPARuntimeException
+ */
+ public final static JPQLContextBuilder createBuilder(final JPQLContextType contextType, final Object resultsView,
+ final boolean withPaging)
+ throws ODataJPARuntimeException {
+ return JPQLContextBuilder.create(contextType, resultsView, withPaging);
}
/**
@@ -140,6 +166,8 @@ public abstract class JPQLContext implements JPQLContextView {
*/
protected int aliasCounter = 0;
+ protected boolean withPaging = false;
+
protected JPQLContextBuilder() {}
/**
@@ -153,7 +181,8 @@ public abstract class JPQLContext implements JPQLContextView {
* {@link org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContext.JPQLContextBuilder}
* @throws ODataJPARuntimeException
*/
- private static JPQLContextBuilder create(final JPQLContextType contextType, final Object resultsView)
+ private static JPQLContextBuilder create(final JPQLContextType contextType, final Object resultsView,
+ final boolean withPaging)
throws ODataJPARuntimeException {
JPQLContextBuilder contextBuilder =
ODataJPAFactory.createFactory().getJPQLBuilderFactory().getContextBuilder(contextType);
@@ -161,6 +190,7 @@ public abstract class JPQLContext implements JPQLContextView {
throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.ERROR_JPQLCTXBLDR_CREATE, null);
}
contextBuilder.setResultsView(resultsView);
+ contextBuilder.withPaging = withPaging;
return contextBuilder;
}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/4aad349f/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/ODataJPAContextImpl.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/ODataJPAContextImpl.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/ODataJPAContextImpl.java
index fe8c45f..43f1850 100644
--- a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/ODataJPAContextImpl.java
+++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/ODataJPAContextImpl.java
@@ -25,6 +25,7 @@ import org.apache.olingo.odata2.api.edm.provider.EdmProvider;
import org.apache.olingo.odata2.api.processor.ODataContext;
import org.apache.olingo.odata2.api.processor.ODataProcessor;
import org.apache.olingo.odata2.jpa.processor.api.ODataJPAContext;
+import org.apache.olingo.odata2.jpa.processor.api.access.JPAPaging;
import org.apache.olingo.odata2.jpa.processor.api.model.JPAEdmExtension;
public class ODataJPAContextImpl implements ODataJPAContext {
@@ -37,6 +38,8 @@ public class ODataJPAContextImpl implements ODataJPAContext {
private EdmProvider edmProvider;
private String jpaEdmMappingModelName;
private JPAEdmExtension jpaEdmExtension;
+ private int pageSize = 0;
+ private JPAPaging jpaPaging;
private static final ThreadLocal<ODataContext> oDataContextThreadLocal = new ThreadLocal<ODataContext>();
private boolean defaultNaming = true;
@@ -143,4 +146,24 @@ public class ODataJPAContextImpl implements ODataJPAContext {
public boolean getDefaultNaming() {
return defaultNaming;
}
+
+ @Override
+ public int getPageSize() {
+ return pageSize;
+ }
+
+ @Override
+ public void setPageSize(final int size) {
+ pageSize = size;
+ }
+
+ @Override
+ public void setPaging(final JPAPaging paging) {
+ jpaPaging = paging;
+ }
+
+ @Override
+ public JPAPaging getPaging() {
+ return jpaPaging;
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/4aad349f/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 bc01eec..c49d017 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
@@ -48,6 +48,7 @@ import org.apache.olingo.odata2.api.processor.ODataContext;
import org.apache.olingo.odata2.api.processor.ODataResponse;
import org.apache.olingo.odata2.api.uri.ExpandSelectTreeNode;
import org.apache.olingo.odata2.api.uri.NavigationPropertySegment;
+import org.apache.olingo.odata2.api.uri.PathInfo;
import org.apache.olingo.odata2.api.uri.SelectItem;
import org.apache.olingo.odata2.api.uri.UriParser;
import org.apache.olingo.odata2.api.uri.info.DeleteUriInfo;
@@ -470,6 +471,7 @@ public final class ODataJPAResponseBuilderDefault implements ODataJPAResponseBui
final GetEntitySetUriInfo resultsView, final List<Map<String, Object>> edmEntityList)
throws ODataJPARuntimeException {
ODataEntityProviderPropertiesBuilder entityFeedPropertiesBuilder = null;
+ ODataContext context = odataJPAContext.getODataContext();
Integer count = null;
if (resultsView.getInlineCount() != null) {
@@ -483,13 +485,22 @@ public final class ODataJPAResponseBuilderDefault implements ODataJPAResponseBui
}
try {
+ PathInfo pathInfo = context.getPathInfo();
entityFeedPropertiesBuilder =
- EntityProviderWriteProperties.serviceRoot(odataJPAContext.getODataContext().getPathInfo().getServiceRoot());
+ EntityProviderWriteProperties.serviceRoot(pathInfo.getServiceRoot());
+ if (odataJPAContext.getPageSize() > 0 && odataJPAContext.getPaging().getNextPage() > 0) {
+ String nextLink =
+ pathInfo.getServiceRoot().relativize(context.getPathInfo().getRequestUri()).toString();
+ nextLink = percentEncodeNextLink(nextLink);
+ nextLink += (nextLink.contains("?") ? "&" : "?")
+ + "$skiptoken=" + odataJPAContext.getPaging().getNextPage();
+ entityFeedPropertiesBuilder.nextLink(nextLink);
+ }
entityFeedPropertiesBuilder.inlineCount(count);
entityFeedPropertiesBuilder.inlineCountType(resultsView.getInlineCount());
ExpandSelectTreeNode expandSelectTree =
UriParser.createExpandSelectTree(resultsView.getSelect(), resultsView.getExpand());
- entityFeedPropertiesBuilder.callbacks(JPAExpandCallBack.getCallbacks(odataJPAContext.getODataContext()
+ entityFeedPropertiesBuilder.callbacks(JPAExpandCallBack.getCallbacks(context
.getPathInfo().getServiceRoot(), expandSelectTree, resultsView.getExpand()));
entityFeedPropertiesBuilder.expandSelectTree(expandSelectTree);
@@ -500,6 +511,16 @@ public final class ODataJPAResponseBuilderDefault implements ODataJPAResponseBui
return entityFeedPropertiesBuilder.build();
}
+ private static String percentEncodeNextLink(final String link) {
+ if (link == null) {
+ return null;
+ }
+
+ return link.replaceAll("\\$skiptoken=.+?(?:&|$)", "")
+ .replaceAll("\\$skip=.+?(?:&|$)", "")
+ .replaceFirst("(?:\\?|&)$", ""); // Remove potentially trailing "?" or "&" left over from remove actions
+ }
+
/*
* This method handles $inlinecount request. It also modifies the list of results in case of
* $inlinecount and $top/$skip combinations. Specific to Entity Set.
@@ -602,7 +623,8 @@ public final class ODataJPAResponseBuilderDefault implements ODataJPAResponseBui
return navigationPropertyList;
}
- private static List<EdmProperty> getEdmProperties(EdmStructuralType structuralType) throws ODataJPARuntimeException {
+ private static List<EdmProperty> getEdmProperties(final EdmStructuralType structuralType)
+ throws ODataJPARuntimeException {
List<EdmProperty> edmProperties = new ArrayList<EdmProperty>();
try {
for (String propertyName : structuralType.getPropertyNames()) {
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/4aad349f/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
new file mode 100644
index 0000000..3161d8d
--- /dev/null
+++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAPage.java
@@ -0,0 +1,168 @@
+/*******************************************************************************
+ * 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.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.Query;
+
+import org.apache.olingo.odata2.jpa.processor.api.access.JPAPaging;
+
+public class JPAPage implements JPAPaging {
+
+ private int pageSize;
+ private int startPage;
+ private int nextPage;
+ private List<Object> pagedEntries;
+
+ protected JPAPage(final int startPage, final int nextPage, final List<Object> pagedEntities, final int pageSize) {
+ this.pageSize = pageSize;
+ this.startPage = startPage;
+ this.nextPage = nextPage;
+ pagedEntries = pagedEntities;
+ }
+
+ @Override
+ public int getPageSize() {
+ return pageSize;
+ }
+
+ @Override
+ public List<Object> getPagedEntities() {
+ return pagedEntries;
+ }
+
+ @Override
+ public int getNextPage() {
+ return nextPage;
+ }
+
+ @Override
+ public int getStartPage() {
+ return startPage;
+ }
+
+ public static class JPAPageBuilder {
+
+ private int pageSize;
+ private int startPage;
+ private int nextPage;
+ private int top = -1;
+ private int skip;
+ private int skipToken;
+ private Query query;
+
+ public JPAPageBuilder() {}
+
+ public JPAPageBuilder pageSize(final int pageSize) {
+ this.pageSize = pageSize;
+ return this;
+ }
+
+ public JPAPageBuilder query(final Query query) {
+ this.query = query;
+ return this;
+ }
+
+ @SuppressWarnings("unchecked")
+ public JPAPage build() {
+
+ List<Object> entities = new ArrayList<Object>();
+ int size = 0;
+ if (pageSize <= 0) {
+ if (skip > 0) {
+ query.setFirstResult(skip);
+ }
+ if (top > 0) {
+ query.setMaxResults(top);
+ }
+ entities = query.getResultList();
+ } else {
+ if (skip >= pageSize) { // No Records to fetch
+ startPage = skipToken;
+ nextPage = 0;
+ } else {
+ // Max Results
+ size = top + skip;
+ if (size > pageSize) {
+ if (skip == 0) {
+ query.setMaxResults(pageSize);
+ } else {
+ query.setMaxResults(pageSize - skip);
+ }
+ } else {
+ if (top > 0) {
+ query.setMaxResults(top);
+ } else {
+ query.setMaxResults(pageSize);
+ }
+ }
+
+ startPage = skipToken;
+ if (skip > 0) {
+ query.setFirstResult(startPage + skip);
+ } else {
+ query.setFirstResult(startPage);
+ }
+
+ entities = query.getResultList();
+ if (entities.size() == 0) {
+ nextPage = 0;
+ } else {
+ nextPage = startPage + pageSize;
+ }
+ }
+ }
+ return new JPAPage(startPage, nextPage, entities, pageSize);
+ }
+
+ public JPAPageBuilder skip(final int skip) {
+ this.skip = skip;
+ if (skip < 0) {
+ this.skip = 0;
+ } else {
+ this.skip = skip;
+ }
+ return this;
+ }
+
+ public JPAPageBuilder skipToken(final String skipToken) throws NumberFormatException {
+ if (skipToken == null) {
+ this.skipToken = 0;
+ } else {
+ this.skipToken = new Integer(skipToken).intValue();
+ if (this.skipToken < 0) {
+ this.skipToken = 0;
+ }
+ }
+
+ return this;
+ }
+
+ public JPAPageBuilder top(final int top) {
+ if (top < 0) {
+ this.top = 0;
+ } else {
+ this.top = top;
+ }
+ return this;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/4aad349f/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 219f5b7..c018c00 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
@@ -54,6 +54,7 @@ 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.core.ODataEntityParser;
+import org.apache.olingo.odata2.jpa.processor.core.access.data.JPAPage.JPAPageBuilder;
public class JPAProcessorImpl implements JPAProcessor {
@@ -117,13 +118,12 @@ public class JPAProcessorImpl implements JPAProcessor {
}
/* Process Get Entity Set Request (Query) */
- @SuppressWarnings("unchecked")
@Override
- public <T> List<T> process(final GetEntitySetUriInfo uriParserResultView)
+ public List<Object> process(final GetEntitySetUriInfo uriParserResultView)
throws ODataJPAModelException, ODataJPARuntimeException {
if (uriParserResultView.getFunctionImport() != null) {
- return (List<T>) process((GetFunctionImportUriInfo) uriParserResultView);
+ return (List<Object>) process((GetFunctionImportUriInfo) uriParserResultView);
}
JPQLContextType contextType = null;
try {
@@ -139,28 +139,21 @@ public class JPAProcessorImpl implements JPAProcessor {
ODataJPARuntimeException.GENERAL, e);
}
- JPQLContext jpqlContext = JPQLContext.createBuilder(contextType,
- uriParserResultView).build();
+ JPQLContext jpqlContext = null;
+ if (oDataJPAContext.getPageSize() > 0) {
+ jpqlContext = JPQLContext.createBuilder(contextType,
+ uriParserResultView, true).build();
+ } else {
+ jpqlContext = JPQLContext.createBuilder(contextType,
+ uriParserResultView).build();
+ }
JPQLStatement jpqlStatement = JPQLStatement.createBuilder(jpqlContext)
.build();
Query query = null;
try {
query = em.createQuery(jpqlStatement.toString());
- // $top/$skip with $inlinecount case handled in response builder to avoid multiple DB call
- if (uriParserResultView.getSkip() != null && uriParserResultView.getInlineCount() == null) {
- query.setFirstResult(uriParserResultView.getSkip());
- }
-
- if (uriParserResultView.getTop() != null && uriParserResultView.getInlineCount() == null) {
- if (uriParserResultView.getTop() == 0) {
- List<T> resultList = new ArrayList<T>();
- return resultList;
- } else {
- query.setMaxResults(uriParserResultView.getTop());
- }
- }
- return query.getResultList();
+ return handlePaging(query, uriParserResultView);
} catch (Exception e) {
throw ODataJPARuntimeException.throwException(
ODataJPARuntimeException.ERROR_JPQL_QUERY_CREATE, e);
@@ -168,6 +161,28 @@ public class JPAProcessorImpl implements JPAProcessor {
}
}
+ private List<Object> handlePaging(final Query query, final GetEntitySetUriInfo uriParserResultView) {
+
+ JPAPageBuilder pageBuilder = new JPAPageBuilder();
+ pageBuilder.pageSize(oDataJPAContext.getPageSize())
+ .query(query)
+ .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();
+
+ }
+
/* Process Get Entity Request (Read) */
@Override
public <T> Object process(GetEntityUriInfo uriParserResultView)
@@ -439,7 +454,7 @@ public class JPAProcessorImpl implements JPAProcessor {
/* Process Get Entity Set Link Request */
@Override
- public <T> List<T> process(final GetEntitySetLinksUriInfo uriParserResultView)
+ public List<Object> process(final GetEntitySetLinksUriInfo uriParserResultView)
throws ODataJPAModelException, ODataJPARuntimeException {
return this.process((GetEntitySetUriInfo) uriParserResultView);
}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/4aad349f/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectContext.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectContext.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectContext.java
index e69a2d6..e5d9df8 100644
--- a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectContext.java
+++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectContext.java
@@ -62,6 +62,10 @@ public class JPQLJoinSelectContext extends JPQLSelectContext implements JPQLJoin
setType(JPQLContextType.JOIN);
}
+ if (withPaging) {
+ isPagingRequested(withPaging);
+ }
+
setJPAOuterJoinClause(generateJoinClauses());
if (!jpaJoinClauses.isEmpty()) {
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/4aad349f/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectContext.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectContext.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectContext.java
index 61d2801..4668b7d 100644
--- a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectContext.java
+++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectContext.java
@@ -87,6 +87,11 @@ public class JPQLSelectContext extends JPQLContext implements JPQLSelectContextV
} else {
setType(JPQLContextType.SELECT);
}
+
+ if (withPaging) {
+ isPagingRequested(withPaging);
+ }
+
EdmEntityType entityType = entitySetView.getTargetEntitySet().getEntityType();
EdmMapping mapping = entityType.getMapping();
if (mapping != null) {
@@ -135,7 +140,8 @@ public class JPQLSelectContext extends JPQLContext implements JPQLSelectContextV
return ODataExpressionParser.parseToJPAOrderByExpression(entitySetView.getOrderBy(), getJPAEntityAlias());
- } else if (entitySetView.getTop() != null || entitySetView.getSkip() != null) {
+ } else if (entitySetView.getTop() != null || entitySetView.getSkip() != null ||
+ pagingRequested == true) {
return ODataExpressionParser.parseKeyPropertiesToJPAOrderByExpression(entitySetView.getTargetEntitySet()
.getEntityType().getKeyProperties(), getJPAEntityAlias());
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/4aad349f/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/ODataJPAResponseBuilderTest.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/ODataJPAResponseBuilderTest.java b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/ODataJPAResponseBuilderTest.java
index 19d3d01..1345260 100644
--- a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/ODataJPAResponseBuilderTest.java
+++ b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/ODataJPAResponseBuilderTest.java
@@ -59,6 +59,7 @@ import org.apache.olingo.odata2.api.uri.info.GetEntitySetUriInfo;
import org.apache.olingo.odata2.api.uri.info.GetEntityUriInfo;
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.access.JPAPaging;
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.JPAEdmTestModelView;
@@ -246,6 +247,8 @@ public class ODataJPAResponseBuilderTest extends JPAEdmTestModelView {
private ODataJPAContext getODataJPAContext() {
ODataJPAContext objODataJPAContext = EasyMock.createMock(ODataJPAContext.class);
EasyMock.expect(objODataJPAContext.getODataContext()).andStubReturn(getLocalODataContext());
+ EasyMock.expect(objODataJPAContext.getPageSize()).andReturn(10);
+ EasyMock.expect(objODataJPAContext.getPaging()).andReturn(mockJPAPaging()).anyTimes();
EasyMock.replay(objODataJPAContext);
return objODataJPAContext;
}
@@ -261,13 +264,51 @@ public class ODataJPAResponseBuilderTest extends JPAEdmTestModelView {
return objODataContext;
}
+ private JPAPaging mockJPAPaging() {
+ JPAPaging paging = new JPAPaging() {
+
+ @Override
+ public int getStartPage() {
+ return 0;
+ }
+
+ @Override
+ public List<Object> getPagedEntities() {
+ return null;
+ }
+
+ @Override
+ public int getPageSize() {
+ return 10;
+ }
+
+ @Override
+ public int getNextPage() {
+ return 10;
+ }
+ };
+
+ return paging;
+ }
+
private PathInfo getLocalPathInfo() {
PathInfo pathInfo = EasyMock.createMock(PathInfo.class);
EasyMock.expect(pathInfo.getServiceRoot()).andStubReturn(getLocalURI());
+ EasyMock.expect(pathInfo.getRequestUri()).andStubReturn(getRequestURI());
EasyMock.replay(pathInfo);
return pathInfo;
}
+ private URI getRequestURI() {
+ URI uri = null;
+ try {
+ uri = new URI("SalesOrders");
+ } catch (URISyntaxException e) {
+ fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+ }
+ return uri;
+ }
+
private URI getLocalURI() {
URI uri = null;
try {
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/4aad349f/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
new file mode 100644
index 0000000..2013045
--- /dev/null
+++ b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAPageBuilderTest.java
@@ -0,0 +1,541 @@
+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.Calendar;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.persistence.FlushModeType;
+import javax.persistence.LockModeType;
+import javax.persistence.Parameter;
+import javax.persistence.Query;
+import javax.persistence.TemporalType;
+
+import org.apache.olingo.odata2.jpa.processor.core.access.data.JPAPage.JPAPageBuilder;
+import org.junit.Test;
+
+public class JPAPageBuilderTest {
+
+ private static final int PAGE_SIZE = 10;
+
+ @Test
+ public void testBuildDefault() {
+ JPAPageBuilder pageBuilder = new JPAPageBuilder();
+ Query query = mockQuery(false);
+
+ JPAPage page = pageBuilder.query(query)
+ .pageSize(PAGE_SIZE)
+ .skipToken("10")
+ .build();
+
+ assertEquals(20, page.getNextPage());
+ assertEquals(10, page.getStartPage());
+ assertEquals(PAGE_SIZE, page.getPageSize());
+ assertNotNull(page.getPagedEntities());
+ assertEquals(1, page.getPagedEntities().size());
+
+ assertEquals(10, query.getFirstResult());
+ assertEquals(10, query.getMaxResults());
+ }
+
+ @Test
+ public void testBuildDefaultZeroPage() {
+ JPAPageBuilder pageBuilder = new JPAPageBuilder();
+ Query query = mockQuery(false);
+
+ JPAPage page = pageBuilder.query(query)
+ .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());
+
+ assertEquals(0, query.getFirstResult());
+ assertEquals(0, query.getMaxResults());
+ }
+
+ @Test
+ public void testBuildWithNoSkipToken() {
+ JPAPageBuilder pageBuilder = new JPAPageBuilder();
+ Query query = mockQuery(false);
+
+ JPAPage page = pageBuilder.query(query)
+ .pageSize(PAGE_SIZE)
+ .skipToken("0")
+ .build();
+
+ assertEquals(10, page.getNextPage());
+ assertEquals(0, page.getStartPage());
+ assertEquals(PAGE_SIZE, page.getPageSize());
+ assertNotNull(page.getPagedEntities());
+ assertEquals(1, page.getPagedEntities().size());
+
+ assertEquals(0, query.getFirstResult());
+ assertEquals(10, query.getMaxResults());
+ }
+
+ @Test
+ public void testBuildWithNullSkipToken() {
+ JPAPageBuilder pageBuilder = new JPAPageBuilder();
+ Query query = mockQuery(false);
+
+ JPAPage page = pageBuilder.query(query)
+ .pageSize(PAGE_SIZE)
+ .skipToken(null)
+ .build();
+
+ assertEquals(10, page.getNextPage());
+ assertEquals(0, page.getStartPage());
+ assertEquals(PAGE_SIZE, page.getPageSize());
+ assertNotNull(page.getPagedEntities());
+
+ assertEquals(0, query.getFirstResult());
+ assertEquals(10, query.getMaxResults());
+ }
+
+ @Test
+ public void testBuildWithInvalidSkipToken() {
+ JPAPageBuilder pageBuilder = new JPAPageBuilder();
+ Query query = mockQuery(false);
+
+ try {
+ pageBuilder.query(query)
+ .skipToken("AB");
+ } catch (NumberFormatException e) {
+ return;
+ }
+ fail("Exception Expected");
+ }
+
+ @Test
+ public void testBuildWithTop() {
+ JPAPageBuilder pageBuilder = new JPAPageBuilder();
+ Query query = mockQuery(false);
+
+ JPAPage page = pageBuilder.query(query)
+ .pageSize(PAGE_SIZE)
+ .skipToken("10")
+ .top(5)
+ .build();
+
+ assertEquals(20, page.getNextPage());
+ assertEquals(10, page.getStartPage());
+ assertEquals(PAGE_SIZE, page.getPageSize());
+ assertNotNull(page.getPagedEntities());
+
+ assertEquals(10, query.getFirstResult());
+ assertEquals(5, query.getMaxResults());
+ }
+
+ @Test
+ public void testBuildWithTopZeroPage() {
+ JPAPageBuilder pageBuilder = new JPAPageBuilder();
+ Query query = mockQuery(false);
+
+ JPAPage page = pageBuilder.query(query)
+ .pageSize(0)
+ .skipToken("10")
+ .top(5)
+ .build();
+
+ assertEquals(0, page.getNextPage());
+ assertEquals(0, page.getStartPage());
+ assertEquals(0, page.getPageSize());
+ assertNotNull(page.getPagedEntities());
+
+ assertEquals(0, query.getFirstResult());
+ assertEquals(5, query.getMaxResults());
+ }
+
+ @Test
+ public void testBuildWithSkipZeroPage() {
+ JPAPageBuilder pageBuilder = new JPAPageBuilder();
+ Query query = mockQuery(false);
+
+ JPAPage page = pageBuilder.query(query)
+ .pageSize(0)
+ .skipToken("10")
+ .skip(5)
+ .build();
+
+ assertEquals(0, page.getNextPage());
+ assertEquals(0, page.getStartPage());
+ assertEquals(0, page.getPageSize());
+ assertNotNull(page.getPagedEntities());
+
+ assertEquals(5, query.getFirstResult());
+ assertEquals(0, query.getMaxResults());
+ }
+
+ @Test
+ public void testBuildWithTopSkipZeroPage() {
+ JPAPageBuilder pageBuilder = new JPAPageBuilder();
+ Query query = mockQuery(false);
+
+ JPAPage page = pageBuilder.query(query)
+ .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, query.getFirstResult());
+ assertEquals(5, query.getMaxResults());
+ }
+
+ @Test
+ public void testBuildWithTopExceeds() {
+ JPAPageBuilder pageBuilder = new JPAPageBuilder();
+ Query query = mockQuery(false);
+
+ JPAPage page = pageBuilder.query(query)
+ .pageSize(PAGE_SIZE)
+ .skipToken("10")
+ .top(15)
+ .build();
+
+ assertEquals(20, page.getNextPage());
+ assertEquals(10, page.getStartPage());
+ assertEquals(PAGE_SIZE, page.getPageSize());
+ assertNotNull(page.getPagedEntities());
+
+ assertEquals(10, query.getFirstResult());
+ assertEquals(10, query.getMaxResults());
+ }
+
+ @Test
+ public void testBuildWithTopSkipExceeds() {
+ JPAPageBuilder pageBuilder = new JPAPageBuilder();
+ Query query = mockQuery(false);
+
+ JPAPage page = pageBuilder.query(query)
+ .pageSize(PAGE_SIZE)
+ .skipToken("10")
+ .top(5)
+ .skip(10)
+ .build();
+
+ assertEquals(0, page.getNextPage());
+ assertEquals(10, page.getStartPage());
+ assertEquals(PAGE_SIZE, page.getPageSize());
+ assertEquals(0, page.getPagedEntities().size());
+
+ assertEquals(0, query.getFirstResult());
+ assertEquals(0, query.getMaxResults());
+ }
+
+ @Test
+ public void testBuildWithTopSkipMore() {
+ JPAPageBuilder pageBuilder = new JPAPageBuilder();
+ Query query = mockQuery(false);
+
+ JPAPage page = pageBuilder.query(query)
+ .pageSize(PAGE_SIZE)
+ .skipToken("10")
+ .top(5)
+ .skip(9)
+ .build();
+
+ assertEquals(20, page.getNextPage());
+ assertEquals(10, page.getStartPage());
+ assertEquals(PAGE_SIZE, page.getPageSize());
+ assertNotNull(page.getPagedEntities());
+
+ assertEquals(19, query.getFirstResult());
+ assertEquals(1, query.getMaxResults());
+ }
+
+ @Test
+ public void testBuildWithTopMoreSkip() {
+ JPAPageBuilder pageBuilder = new JPAPageBuilder();
+ Query query = mockQuery(false);
+
+ JPAPage page = pageBuilder.query(query)
+ .pageSize(PAGE_SIZE)
+ .skipToken("10")
+ .top(15)
+ .skip(9)
+ .build();
+
+ assertEquals(20, page.getNextPage());
+ assertEquals(10, page.getStartPage());
+ assertEquals(PAGE_SIZE, page.getPageSize());
+ assertNotNull(page.getPagedEntities());
+
+ assertEquals(19, query.getFirstResult());
+ assertEquals(1, query.getMaxResults());
+ }
+
+ @Test
+ public void testBuildWithTopXSkipX() {
+ JPAPageBuilder pageBuilder = new JPAPageBuilder();
+ Query query = mockQuery(false);
+
+ JPAPage page = pageBuilder.query(query)
+ .pageSize(PAGE_SIZE)
+ .skipToken("10")
+ .top(15)
+ .skip(15)
+ .build();
+
+ assertEquals(0, page.getNextPage());
+ assertEquals(10, page.getStartPage());
+ assertEquals(PAGE_SIZE, page.getPageSize());
+ assertNotNull(page.getPagedEntities());
+
+ assertEquals(0, query.getFirstResult());
+ assertEquals(0, query.getMaxResults());
+ }
+
+ @Test
+ public void testBuildWithNegativeTop() {
+ JPAPageBuilder pageBuilder = new JPAPageBuilder();
+ Query query = mockQuery(false);
+
+ JPAPage page = pageBuilder.query(query)
+ .pageSize(PAGE_SIZE)
+ .skipToken("10")
+ .top(-5)
+ .build();
+
+ assertEquals(20, page.getNextPage());
+ assertEquals(10, page.getStartPage());
+ assertEquals(PAGE_SIZE, page.getPageSize());
+ assertNotNull(page.getPagedEntities());
+
+ assertEquals(10, query.getFirstResult());
+ assertEquals(10, query.getMaxResults());
+ }
+
+ @Test
+ public void testBuildWithNegativeTopSkipToken() {
+ JPAPageBuilder pageBuilder = new JPAPageBuilder();
+ Query query = mockQuery(false);
+
+ JPAPage page = pageBuilder.query(query)
+ .pageSize(PAGE_SIZE)
+ .skipToken("-10")
+ .top(-5)
+ .skip(-1)
+ .build();
+
+ assertEquals(10, page.getNextPage());
+ assertEquals(0, page.getStartPage());
+ assertEquals(PAGE_SIZE, page.getPageSize());
+ assertNotNull(page.getPagedEntities());
+
+ assertEquals(0, query.getFirstResult());
+ assertEquals(10, query.getMaxResults());
+ }
+
+ @Test
+ public void testBuildWithNoRecords() {
+ JPAPageBuilder pageBuilder = new JPAPageBuilder();
+ Query query = mockQuery(true);
+
+ JPAPage page = pageBuilder.query(query)
+ .pageSize(PAGE_SIZE)
+ .skipToken("10")
+ .top(1)
+ .skip(1)
+ .build();
+
+ assertEquals(0, page.getNextPage());
+ assertEquals(10, page.getStartPage());
+ assertEquals(PAGE_SIZE, page.getPageSize());
+ assertNotNull(page.getPagedEntities());
+
+ assertEquals(11, query.getFirstResult());
+ assertEquals(1, query.getMaxResults());
+ }
+
+ private Query mockQuery(final boolean setNoRecords) {
+
+ return new Query() {
+
+ private int maxResults;
+ private int firstResult;
+
+ @Override
+ public Query setFirstResult(final int arg0) {
+ firstResult = arg0;
+ return this;
+ }
+
+ @Override
+ public Query setMaxResults(final int arg0) {
+ maxResults = arg0;
+ return this;
+ }
+
+ @Override
+ public int getMaxResults() {
+ return maxResults;
+ }
+
+ @Override
+ public int getFirstResult() {
+ return firstResult;
+ }
+
+ @Override
+ public List<Object> getResultList() {
+ List<Object> list = new ArrayList<Object>();
+ if (maxResults > 0 && setNoRecords == false) {
+ list.add(new Integer(1));
+ }
+ return list;
+ }
+
+ @Override
+ public <T> T unwrap(final Class<T> arg0) {
+ return null;
+ }
+
+ @Override
+ public Query setParameter(final int arg0, final Date arg1, final TemporalType arg2) {
+ return null;
+ }
+
+ @Override
+ public Query setParameter(final int arg0, final Calendar arg1, final TemporalType arg2) {
+ return null;
+ }
+
+ @Override
+ public Query setParameter(final String arg0, final Date arg1, final TemporalType arg2) {
+ return null;
+ }
+
+ @Override
+ public Query setParameter(final String arg0, final Calendar arg1, final TemporalType arg2) {
+ return null;
+ }
+
+ @Override
+ public Query setParameter(final Parameter<Date> arg0, final Date arg1, final TemporalType arg2) {
+ return null;
+ }
+
+ @Override
+ public Query setParameter(final Parameter<Calendar> arg0, final Calendar arg1, final TemporalType arg2) {
+ return null;
+ }
+
+ @Override
+ public Query setParameter(final int arg0, final Object arg1) {
+ return null;
+ }
+
+ @Override
+ public Query setParameter(final String arg0, final Object arg1) {
+ return null;
+ }
+
+ @Override
+ public <T> Query setParameter(final Parameter<T> arg0, final T arg1) {
+ return null;
+ }
+
+ @Override
+ public Query setLockMode(final LockModeType arg0) {
+ return null;
+ }
+
+ @Override
+ public Query setHint(final String arg0, final Object arg1) {
+ return null;
+ }
+
+ @Override
+ public Query setFlushMode(final FlushModeType arg0) {
+ return null;
+ }
+
+ @Override
+ public boolean isBound(final Parameter<?> arg0) {
+ return false;
+ }
+
+ @Override
+ public Object getSingleResult() {
+ return null;
+ }
+
+ @Override
+ public Set<Parameter<?>> getParameters() {
+ return null;
+ }
+
+ @Override
+ public Object getParameterValue(final int arg0) {
+ return null;
+ }
+
+ @Override
+ public Object getParameterValue(final String arg0) {
+ return null;
+ }
+
+ @Override
+ public <T> T getParameterValue(final Parameter<T> arg0) {
+ return null;
+ }
+
+ @Override
+ public <T> Parameter<T> getParameter(final int arg0, final Class<T> arg1) {
+ return null;
+ }
+
+ @Override
+ public <T> Parameter<T> getParameter(final String arg0, final Class<T> arg1) {
+ return null;
+ }
+
+ @Override
+ public Parameter<?> getParameter(final int arg0) {
+ return null;
+ }
+
+ @Override
+ public Parameter<?> getParameter(final String arg0) {
+ return null;
+ }
+
+ @Override
+ public LockModeType getLockMode() {
+ return null;
+ }
+
+ @Override
+ public Map<String, Object> getHints() {
+ return null;
+ }
+
+ @Override
+ public FlushModeType getFlushMode() {
+ return null;
+ }
+
+ @Override
+ public int executeUpdate() {
+ return 0;
+ }
+ };
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/4aad349f/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 bafef01..23fe91c 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
@@ -23,12 +23,20 @@ import static org.junit.Assert.fail;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
+import javax.persistence.FlushModeType;
+import javax.persistence.LockModeType;
+import javax.persistence.Parameter;
import javax.persistence.Query;
+import javax.persistence.TemporalType;
import javax.persistence.metamodel.Metamodel;
import junit.framework.Assert;
@@ -57,6 +65,7 @@ import org.apache.olingo.odata2.api.uri.info.GetEntityCountUriInfo;
import org.apache.olingo.odata2.api.uri.info.GetEntitySetCountUriInfo;
import org.apache.olingo.odata2.api.uri.info.GetEntitySetUriInfo;
import org.apache.olingo.odata2.jpa.processor.api.ODataJPAContext;
+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;
@@ -180,6 +189,7 @@ public class JPAProcessorImplTest {
EasyMock.expect(objUriInfo.getOrderBy()).andStubReturn(getOrderByExpression());
EasyMock.expect(objUriInfo.getTop()).andStubReturn(getTop());
EasyMock.expect(objUriInfo.getSkip()).andStubReturn(getSkip());
+ EasyMock.expect(objUriInfo.getSkipToken()).andReturn("5");
EasyMock.expect(objUriInfo.getInlineCount()).andStubReturn(getInlineCount());
EasyMock.expect(objUriInfo.getFilter()).andStubReturn(getFilter());
// EasyMock.expect(objUriInfo.getFunctionImport()).andStubReturn(getFunctionImport());
@@ -273,6 +283,9 @@ public class JPAProcessorImplTest {
EasyMock.expect(odataJPAContext.getEntityManagerFactory()).andStubReturn(mockEntityManagerFactory());
EasyMock.expect(odataJPAContext.getODataContext()).andStubReturn(getLocalODataContext());
EasyMock.expect(odataJPAContext.getEntityManager()).andStubReturn(getLocalEntityManager());
+ EasyMock.expect(odataJPAContext.getPageSize()).andReturn(10).anyTimes();
+ odataJPAContext.setPaging(EasyMock.isA(JPAPaging.class));
+ EasyMock.expectLastCall();
EasyMock.replay(odataJPAContext);
return odataJPAContext;
}
@@ -311,10 +324,174 @@ public class JPAProcessorImplTest {
}
private Query getQuery() {
- Query query = EasyMock.createMock(Query.class);
- EasyMock.expect(query.getResultList()).andStubReturn(getResultList());
- EasyMock.replay(query);
- return query;
+ return new Query() {
+
+ private int maxResults;
+ private int firstResult;
+
+ @Override
+ public Query setFirstResult(final int arg0) {
+ firstResult = arg0;
+ return this;
+ }
+
+ @Override
+ public Query setMaxResults(final int arg0) {
+ maxResults = arg0;
+ return this;
+ }
+
+ @Override
+ public int getMaxResults() {
+ return maxResults;
+ }
+
+ @Override
+ public int getFirstResult() {
+ return firstResult;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public List<Object> getResultList() {
+ return (List<Object>) getResultListL();
+ }
+
+ @Override
+ public <T> T unwrap(final Class<T> arg0) {
+ return null;
+ }
+
+ @Override
+ public Query setParameter(final int arg0, final Date arg1, final TemporalType arg2) {
+ return null;
+ }
+
+ @Override
+ public Query setParameter(final int arg0, final Calendar arg1, final TemporalType arg2) {
+ return null;
+ }
+
+ @Override
+ public Query setParameter(final String arg0, final Date arg1, final TemporalType arg2) {
+ return null;
+ }
+
+ @Override
+ public Query setParameter(final String arg0, final Calendar arg1, final TemporalType arg2) {
+ return null;
+ }
+
+ @Override
+ public Query setParameter(final Parameter<Date> arg0, final Date arg1, final TemporalType arg2) {
+ return null;
+ }
+
+ @Override
+ public Query setParameter(final Parameter<Calendar> arg0, final Calendar arg1, final TemporalType arg2) {
+ return null;
+ }
+
+ @Override
+ public Query setParameter(final int arg0, final Object arg1) {
+ return null;
+ }
+
+ @Override
+ public Query setParameter(final String arg0, final Object arg1) {
+ return null;
+ }
+
+ @Override
+ public <T> Query setParameter(final Parameter<T> arg0, final T arg1) {
+ return null;
+ }
+
+ @Override
+ public Query setLockMode(final LockModeType arg0) {
+ return null;
+ }
+
+ @Override
+ public Query setHint(final String arg0, final Object arg1) {
+ return null;
+ }
+
+ @Override
+ public Query setFlushMode(final FlushModeType arg0) {
+ return null;
+ }
+
+ @Override
+ public boolean isBound(final Parameter<?> arg0) {
+ return false;
+ }
+
+ @Override
+ public Object getSingleResult() {
+ return null;
+ }
+
+ @Override
+ public Set<Parameter<?>> getParameters() {
+ return null;
+ }
+
+ @Override
+ public Object getParameterValue(final int arg0) {
+ return null;
+ }
+
+ @Override
+ public Object getParameterValue(final String arg0) {
+ return null;
+ }
+
+ @Override
+ public <T> T getParameterValue(final Parameter<T> arg0) {
+ return null;
+ }
+
+ @Override
+ public <T> Parameter<T> getParameter(final int arg0, final Class<T> arg1) {
+ return null;
+ }
+
+ @Override
+ public <T> Parameter<T> getParameter(final String arg0, final Class<T> arg1) {
+ return null;
+ }
+
+ @Override
+ public Parameter<?> getParameter(final int arg0) {
+ return null;
+ }
+
+ @Override
+ public Parameter<?> getParameter(final String arg0) {
+ return null;
+ }
+
+ @Override
+ public LockModeType getLockMode() {
+ return null;
+ }
+
+ @Override
+ public Map<String, Object> getHints() {
+ return null;
+ }
+
+ @Override
+ public FlushModeType getFlushMode() {
+ return null;
+ }
+
+ @Override
+ public int executeUpdate() {
+ return 0;
+ }
+ };
}
private Query getQueryForSelectCount() {
@@ -324,7 +501,7 @@ public class JPAProcessorImplTest {
return query;
}
- private List<?> getResultList() {
+ private List<?> getResultListL() {
List<Object> list = new ArrayList<Object>();
list.add(new Address());
return list;
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/4aad349f/odata2-jpa-processor/jpa-web/src/main/java/org/apache/olingo/odata2/jpa/processor/ref/web/JPAReferenceServiceFactory.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-web/src/main/java/org/apache/olingo/odata2/jpa/processor/ref/web/JPAReferenceServiceFactory.java b/odata2-jpa-processor/jpa-web/src/main/java/org/apache/olingo/odata2/jpa/processor/ref/web/JPAReferenceServiceFactory.java
index 63d9c4a..f21d565 100644
--- a/odata2-jpa-processor/jpa-web/src/main/java/org/apache/olingo/odata2/jpa/processor/ref/web/JPAReferenceServiceFactory.java
+++ b/odata2-jpa-processor/jpa-web/src/main/java/org/apache/olingo/odata2/jpa/processor/ref/web/JPAReferenceServiceFactory.java
@@ -32,6 +32,7 @@ public class JPAReferenceServiceFactory extends ODataJPAServiceFactory {
private static final String MAPPING_MODEL = "SalesOrderProcessingMappingModel.xml";
private static final String CONFIG = "serviceConfig";
private static final String SHOW_DETAIL_ERROR = "showDetailError";
+ private static final int PAGE_SIZE = 5;
@Override
public ODataJPAContext initializeODataJPAContext()
@@ -42,7 +43,7 @@ public class JPAReferenceServiceFactory extends ODataJPAServiceFactory {
oDataJPAContext.setJPAEdmMappingModel(MAPPING_MODEL);
oDataJPAContext
.setJPAEdmExtension((JPAEdmExtension) new SalesOrderProcessingExtension());
-
+ oDataJPAContext.setPageSize(PAGE_SIZE);
setErrorLevel();
return oDataJPAContext;
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/4aad349f/odata2-jpa-processor/jpa-web/src/main/webapp/index.jsp
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-web/src/main/webapp/index.jsp b/odata2-jpa-processor/jpa-web/src/main/webapp/index.jsp
index f897cbb..db37577 100644
--- a/odata2-jpa-processor/jpa-web/src/main/webapp/index.jsp
+++ b/odata2-jpa-processor/jpa-web/src/main/webapp/index.jsp
@@ -290,10 +290,21 @@ th,td {
<li><a
href="SalesOrderProcessing.svc/FindAllSalesOrders?DeliveryStatusCode='01'"
target="_blank">SalesOrderProcessing.svc/FindAllSalesOrders?DeliveryStatusCode='01'</a></li>
- <li><a
- href="SalesOrderProcessing.svc/orderValue?SoId=2L"
+ <li><a href="SalesOrderProcessing.svc/orderValue?SoId=2L"
target="_blank">SalesOrderProcessing.svc/orderValue?SoId=2L</a></li>
</ul>
+ <h3>Paging</h3>
+ <ul>
+ <li><a
+ href="SalesOrderProcessing.svc/SalesOrders?$top=1&$inlinecount=allpages"
+ target="_blank">SalesOrderProcessing.svc/SalesOrders?$top=1&$inlinecount=allpages"</a></li>
+ <li><a
+ href="SalesOrderProcessing.svc/SalesOrders?$top=1&$inlinecount=allpages&$skiptoken=5"
+ target="_blank">SalesOrderProcessing.svc/SalesOrders?$top=1&$inlinecount=allpages&$skiptoken=5</a></li>
+ <li><a
+ href="SalesOrderProcessing.svc/SalesOrders?$top=1&$skip=4&$inlinecount=allpages&$skiptoken=5"
+ target="_blank">SalesOrderProcessing.svc/SalesOrders?$top=1&$skip=4&$inlinecount=allpages&$skiptoken=5</a></li>
+ </ul>
</td>
<td valign="top"> </td>
<td valign="bottom">