diff --git a/jpa-archetype/odata-jpa-archetype-spring/pom.xml b/jpa-archetype/odata-jpa-archetype-spring/pom.xml index 9186c479c..ba2fbd81e 100644 --- a/jpa-archetype/odata-jpa-archetype-spring/pom.xml +++ b/jpa-archetype/odata-jpa-archetype-spring/pom.xml @@ -17,7 +17,7 @@ org.apache.maven.archetype archetype-packaging - 3.2.1 + 3.3.0 @@ -25,7 +25,7 @@ org.apache.maven.plugins maven-archetype-plugin - 3.2.1 + 3.3.0 true diff --git a/jpa/odata-jpa-metadata/src/test/java/com/sap/olingo/jpa/metadata/core/edm/mapper/impl/IntermediateDescriptionPropertyTest.java b/jpa/odata-jpa-metadata/src/test/java/com/sap/olingo/jpa/metadata/core/edm/mapper/impl/IntermediateDescriptionPropertyTest.java index 1c61c63f9..4ef2affd5 100644 --- a/jpa/odata-jpa-metadata/src/test/java/com/sap/olingo/jpa/metadata/core/edm/mapper/impl/IntermediateDescriptionPropertyTest.java +++ b/jpa/odata-jpa-metadata/src/test/java/com/sap/olingo/jpa/metadata/core/edm/mapper/impl/IntermediateDescriptionPropertyTest.java @@ -262,7 +262,6 @@ void checkAnnotations() throws ODataJPAModelException { @Test void checkPostProcessorCalled() throws ODataJPAModelException { - // PostProcessorSpy spy = new PostProcessorSpy(); IntermediateModelElement.setPostProcessor(processor); final Attribute jpaAttribute = helper.getDeclaredAttribute(helper.getEmbeddableType("PostalAddressData"), "countryName"); @@ -285,8 +284,7 @@ void checkPostProcessorAnnotationAdded() throws ODataJPAModelException { @Test void checkEmptyAssociationThrowsException() throws ODataJPAModelException { - final IntermediateDescriptionProperty cut = new IntermediateDescriptionProperty(nameBuilder, createAttributeMock( - false, false, 0), et, helper.schema); + cut = new IntermediateDescriptionProperty(nameBuilder, createAttributeMock(false, false, 0), et, helper.schema); final ODataJPAModelException act = assertThrows(ODataJPAModelException.class, () -> cut.lazyBuildEdmItem()); assertEquals(ODataJPAModelException.MessageKeys.DESCRIPTION_ANNOTATION_MISSING.getKey(), act.getId()); } @@ -294,8 +292,7 @@ void checkEmptyAssociationThrowsException() throws ODataJPAModelException { @Test void checkUnknownAttributeAtTargetThrowsException() throws ODataJPAModelException { - final IntermediateDescriptionProperty cut = new IntermediateDescriptionProperty(nameBuilder, createAttributeMock( - true, false, 0), et, helper.schema); + cut = new IntermediateDescriptionProperty(nameBuilder, createAttributeMock(true, false, 0), et, helper.schema); final ODataJPAModelException act = assertThrows(ODataJPAModelException.class, () -> cut.lazyBuildEdmItem()); assertEquals(ODataJPAModelException.MessageKeys.INVALID_DESCRIPTION_PROPERTY.getKey(), act.getId()); } @@ -303,8 +300,7 @@ void checkUnknownAttributeAtTargetThrowsException() throws ODataJPAModelExceptio @Test void checkNoLocationAtTargetThrowsException() throws ODataJPAModelException { - final IntermediateDescriptionProperty cut = new IntermediateDescriptionProperty(nameBuilder, createAttributeMock( - true, true, 0), et, helper.schema); + cut = new IntermediateDescriptionProperty(nameBuilder, createAttributeMock(true, true, 0), et, helper.schema); final ODataJPAModelException act = assertThrows(ODataJPAModelException.class, () -> cut.lazyBuildEdmItem()); assertEquals(ODataJPAModelException.MessageKeys.DESCRIPTION_LOCALE_FIELD_MISSING.getKey(), act.getId()); } @@ -312,8 +308,7 @@ void checkNoLocationAtTargetThrowsException() throws ODataJPAModelException { @Test void checkLocationAndLanguageAtTargetThrowsException() throws ODataJPAModelException { - final IntermediateDescriptionProperty cut = new IntermediateDescriptionProperty(nameBuilder, createAttributeMock( - true, true, 2), et, helper.schema); + cut = new IntermediateDescriptionProperty(nameBuilder, createAttributeMock(true, true, 2), et, helper.schema); final ODataJPAModelException act = assertThrows(ODataJPAModelException.class, () -> cut.lazyBuildEdmItem()); assertEquals(ODataJPAModelException.MessageKeys.DESCRIPTION_LOCALE_FIELD_MISSING.getKey(), act.getId()); } @@ -393,17 +388,24 @@ void checkPathHasJoinTableNull() throws ODataJPAModelException { assertNull(act.getJoinTable()); } - private class PostProcessorSetName implements JPAEdmMetadataPostProcessor { + @Test + void checkPathGetForeignKeyColumns() throws ODataJPAModelException { + createDefaultCut(); + final var act = cut.getPath().getForeignKeyColumns(); + assertNotNull(act); + assertTrue(act.isEmpty()); + } + + private static class PostProcessorSetName implements JPAEdmMetadataPostProcessor { @Override public void processProperty(final IntermediatePropertyAccess property, final String jpaManagedTypeClassName) { - if (jpaManagedTypeClassName.equals(ADDR_CANONICAL_NAME)) { - if (property.getInternalName().equals("countryName")) { - final CsdlAnnotation annotation = new CsdlAnnotation(); - annotation.setTerm("Immutable"); - annotation.setExpression(new CsdlConstantExpression(ConstantExpressionType.Bool, "true")); - property.addAnnotations(Collections.singletonList(annotation)); - } + if (jpaManagedTypeClassName.equals(ADDR_CANONICAL_NAME) + && property.getInternalName().equals("countryName")) { + final CsdlAnnotation annotation = new CsdlAnnotation(); + annotation.setTerm("Immutable"); + annotation.setExpression(new CsdlConstantExpression(ConstantExpressionType.Bool, "true")); + property.addAnnotations(Collections.singletonList(annotation)); } } @@ -430,7 +432,7 @@ private void createDefaultCut() throws ODataJPAModelException { } private Attribute createAttributeMock(final boolean association, final boolean associationName, - final int langFields) { + final int languageFields) { final Attribute attribute = mock(Attribute.class); final ManagedType managedType = mock(ManagedType.class); final Member member = mock(AnnotatedMember.class); @@ -461,9 +463,9 @@ public Class answer(final InvocationOnMock invocation) throws T when(((AnnotatedElement) member).getAnnotation(EdmDescriptionAssociation.class)).thenReturn(a); if (associationName) when(a.descriptionAttribute()).thenReturn("name"); - if (langFields > 0) + if (languageFields > 0) when(a.languageAttribute()).thenReturn("language"); - if (langFields > 1) + if (languageFields > 1) when(a.localeAttribute()).thenReturn("location"); } return attribute; diff --git a/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/api/JPAODataPage.java b/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/api/JPAODataPage.java index ee0955b5f..c6dc937cd 100644 --- a/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/api/JPAODataPage.java +++ b/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/api/JPAODataPage.java @@ -5,8 +5,20 @@ import org.apache.olingo.server.api.uri.UriInfoResource; +/** + * A page in case a the amount of returned data shall be restricted by the server. + * + * @param uriInfo UriInfoResource of the original request + * @param skip Skip value to be used + * @param top Top value to be used + * @param skipToken The skip token to be used in the next link for non expand requests. + * @param expandInformation Provides for pages of restricted expand requests the path and key information needed to build the + * next + * request. + * + */ public record JPAODataPage(UriInfoResource uriInfo, int skip, int top, Object skipToken, - List expandInfo) { + List expandInformation) { public JPAODataPage(final UriInfoResource uriInfo, final int skip, final int top, final Object skipToken) { this(uriInfo, skip, top, skipToken, Collections.emptyList()); diff --git a/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/api/JPAODataPageExpandInfo.java b/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/api/JPAODataPageExpandInfo.java index 3a1cc1a8e..b5dbf48da 100644 --- a/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/api/JPAODataPageExpandInfo.java +++ b/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/api/JPAODataPageExpandInfo.java @@ -1,5 +1,14 @@ package com.sap.olingo.jpa.processor.core.api; +/** + * + * @param navigationPropertyPath Concatenated path information leading to the next expand + * @param keyPath Concatenated key information to be used to convert the expand + * + * @author Oliver Grande + * @since 2.2.0 + * + */ public record JPAODataPageExpandInfo(String navigationPropertyPath, String keyPath) { } diff --git a/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/api/JPAODataPagingProvider.java b/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/api/JPAODataPagingProvider.java index 235a66968..eeb76f38e 100644 --- a/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/api/JPAODataPagingProvider.java +++ b/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/api/JPAODataPagingProvider.java @@ -83,7 +83,7 @@ default JPAODataPage getFirstPage(final UriInfo uriInfo, @Nullable final Integer * @param uriInfo * @param preferredPageSize Value of the odata.maxpagesize preference header * @param countQuery A query that can be used to determine the maximum number of results that can be - * expected. Only if the number of expected results is bigger then the page size a next link + * expected. Only if the number of expected results is bigger then the page size a page should be generated. * @param em An instance of the entity manager * @return An optional of the page that shall be read. In case the optional is empty, all records are read from the * database. @@ -98,11 +98,12 @@ default Optional getFirstPage(final JPARequestParameterMap request /** * Requires module {@code odata-jpa-processor-cb} * @param requestParameter The parameter from the request context - * @param pathInformation - * @param uriInfo - * @param association + * @param pathInformation Fragmented string representation of the URI, to be able to rebuild the uri info. + * @param uriInfo Java representation of the request URI + * @param association Metadata of the * @param preferredPageSize - * @param count + * @param count A query that can be used to determine the maximum number of results that can be + * expected per parent. Only if the number of expected results is bigger then the page size a page should be generated. * @param em An instance of the entity manager * @return */ diff --git a/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/api/JPAODataRequestContextAccess.java b/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/api/JPAODataRequestContextAccess.java index 1b8dbfc8f..c8f9239a8 100644 --- a/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/api/JPAODataRequestContextAccess.java +++ b/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/api/JPAODataRequestContextAccess.java @@ -73,4 +73,6 @@ public Optional getQueryEnhancement(@Nonnull final JP public JPAODataEtagHelper getEtagHelper(); public Optional getPagingProvider(); + + public JPAODataPathInformation getPathInformation(); } diff --git a/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/processor/JPANavigationRequestProcessor.java b/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/processor/JPANavigationRequestProcessor.java index cda140471..ef211509d 100644 --- a/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/processor/JPANavigationRequestProcessor.java +++ b/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/processor/JPANavigationRequestProcessor.java @@ -82,7 +82,6 @@ public > void retrieveData(final ODataRequest request, f final ContentType responseFormat) throws ODataException { try (var measurement = debugger.newMeasurement(this, "retrieveData")) { - checkRequestSupported(); // Create a JPQL Query and execute it JPAJoinQuery query = null; diff --git a/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/processor/JPAODataInternalRequestContext.java b/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/processor/JPAODataInternalRequestContext.java index a955e7989..7b8f49388 100644 --- a/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/processor/JPAODataInternalRequestContext.java +++ b/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/processor/JPAODataInternalRequestContext.java @@ -36,6 +36,7 @@ import com.sap.olingo.jpa.processor.core.api.JPAODataEtagHelper; import com.sap.olingo.jpa.processor.core.api.JPAODataGroupProvider; import com.sap.olingo.jpa.processor.core.api.JPAODataPagingProvider; +import com.sap.olingo.jpa.processor.core.api.JPAODataPathInformation; import com.sap.olingo.jpa.processor.core.api.JPAODataQueryDirectives; import com.sap.olingo.jpa.processor.core.api.JPAODataRequestContext; import com.sap.olingo.jpa.processor.core.api.JPAODataRequestContextAccess; @@ -71,6 +72,7 @@ public final class JPAODataInternalRequestContext implements JPAODataRequestCont private JPAODataQueryDirectives queryDirectives; private JPAODataEtagHelper etagHelper; private Optional pagingProvider; + private JPAODataPathInformation pathInformation; public JPAODataInternalRequestContext(@Nonnull final JPAODataRequestContext requestContext, @Nonnull final JPAODataSessionContextAccess sessionContext, final OData odata) { @@ -89,7 +91,7 @@ public JPAODataInternalRequestContext(@Nonnull final JPAODataRequestContext requ */ public JPAODataInternalRequestContext(final UriInfoResource uriInfo, final JPAODataRequestContextAccess context) throws ODataJPAProcessorException { - this(uriInfo, null, context, context.getHeader()); + this(uriInfo, null, context, context.getHeader(), null); } /** @@ -100,11 +102,12 @@ public JPAODataInternalRequestContext(final UriInfoResource uriInfo, final JPAOD */ public JPAODataInternalRequestContext(final UriInfoResource uriInfo, final JPAODataRequestContextAccess context, final Map> header) throws ODataJPAProcessorException { - this(uriInfo, null, context, header); + this(uriInfo, null, context, header, null); } JPAODataInternalRequestContext(final UriInfoResource uriInfo, @Nullable final JPASerializer serializer, - final JPAODataRequestContextAccess context, final Map> header) + final JPAODataRequestContextAccess context, final Map> header, + final JPAODataPathInformation pathInformation) throws ODataJPAProcessorException { copyContextValues(context); @@ -115,6 +118,7 @@ public JPAODataInternalRequestContext(final UriInfoResource uriInfo, final JPAOD this.header = new JPAHttpHeaderHashMap(header); this.customParameter = new JPARequestParameterHashMap(context.getRequestParameter()); this.hookFactory = new JPAHookFactory(em, this.header, customParameter); + this.pathInformation = pathInformation != null ? pathInformation : this.pathInformation; } @Override @@ -248,6 +252,11 @@ public Optional getPagingProvider() { return pagingProvider; } + @Override + public JPAODataPathInformation getPathInformation() { + return pathInformation; + } + private void copyContextValues(final JPAODataRequestContextAccess context) throws ODataJPAProcessorException { this.em = context.getEntityManager(); @@ -264,6 +273,7 @@ private void copyContextValues(final JPAODataRequestContextAccess context) this.queryDirectives = context.getQueryDirectives(); this.etagHelper = context.getEtagHelper(); this.pagingProvider = context.getPagingProvider(); + this.pathInformation = context.getPathInformation(); } private void copyRequestContext(@Nonnull final JPAODataRequestContext requestContext, diff --git a/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/processor/JPAProcessorFactory.java b/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/processor/JPAProcessorFactory.java index 2d8934548..96b8a9cb4 100644 --- a/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/processor/JPAProcessorFactory.java +++ b/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/processor/JPAProcessorFactory.java @@ -55,7 +55,7 @@ public JPACUDRequestProcessor createCUDRequestProcessor(final UriInfo uriInfo, f final JPAODataRequestContextAccess requestContext = new JPAODataInternalRequestContext(uriInfo, serializerFactory .createCUDSerializer(responseFormat, uriInfo, Optional.ofNullable(header.get(HttpHeader.ODATA_MAX_VERSION))), - context, header); + context, header, null); return new JPACUDRequestProcessor(odata, serviceMetadata, requestContext, new JPAConversionHelper()); } @@ -73,7 +73,7 @@ public JPAActionRequestProcessor createActionProcessor(final UriInfo uriInfo, fi final JPAODataRequestContextAccess requestContext = new JPAODataInternalRequestContext(uriInfo, responseFormat != null ? serializerFactory.createSerializer(responseFormat, uriInfo, Optional.ofNullable(header - .get(HttpHeader.ODATA_MAX_VERSION))) : null, context, header); + .get(HttpHeader.ODATA_MAX_VERSION))) : null, context, header, null); return new JPAActionRequestProcessor(odata, requestContext); @@ -88,7 +88,7 @@ public JPARequestProcessor createProcessor(final UriInfo uriInfo, final ContentT final JPAODataRequestContextAccess requestContext = new JPAODataInternalRequestContext(newUriInfo, serializerFactory .createSerializer(responseFormat, newUriInfo, Optional.ofNullable(header.get( - HttpHeader.ODATA_MAX_VERSION))), context, header); + HttpHeader.ODATA_MAX_VERSION))), context, header, pathInformation); return switch (newUriInfo.getLastResourcePart().getKind()) { case count -> new JPACountRequestProcessor(odata, requestContext); diff --git a/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/query/JPAExpandItemInfoFactory.java b/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/query/JPAExpandItemInfoFactory.java index 3d477f33f..c0adb14c6 100644 --- a/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/query/JPAExpandItemInfoFactory.java +++ b/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/query/JPAExpandItemInfoFactory.java @@ -72,7 +72,8 @@ public List buildExpandItemInfo(final JPAServiceDocument sd, final Optional page; if (provider.isPresent()) page = provider.get().getFirstPageExpand(requestContext.getRequestParameter(), - null, requestContext.getUriInfo(), item.getKey().getTopOption(), item.getKey().getSkipOption(), + requestContext.getPathInformation(), requestContext.getUriInfo(), item.getKey().getTopOption(), item + .getKey().getSkipOption(), item.getValue().getLeaf(), count, requestContext.getEntityManager()); else page = Optional.empty(); diff --git a/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/uri/JPAUriInfoFactory.java b/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/uri/JPAUriInfoFactory.java index 91e403433..8bb9ec174 100644 --- a/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/uri/JPAUriInfoFactory.java +++ b/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/uri/JPAUriInfoFactory.java @@ -36,23 +36,23 @@ public JPAUriInfoFactory(@Nonnull final JPAODataPage page) { } public JPAUriInfoResource build() { - if (page.expandInfo().isEmpty()) + if (page.expandInformation().isEmpty()) // Standard pagination not resolving the $levels, as JPA Processor supports ODatas max option, // so depth is not known up-front and a late resolution has to be done anyhow. This also prevent the early // resolution of * return new JPAUriInfoBuilder(page.uriInfo()) - // .withResolvedStars() .withTop(page.top()) .withSkip(page.skip()) .withSkipToken(page.skipToken()) .build(); else return new JPAUriInfoBuilder(page.uriInfo()) - .withResolvedStars(page.expandInfo()) - .withExpandInfo(page.expandInfo()) + .withResolvedStars(page.expandInformation()) + .withExpandInfo(page.expandInformation()) .withExpandOrderBy() .withTop(page.top()) .withSkip(page.skip()) + .withSkipToken(page.skipToken()) .build(); } diff --git a/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/api/example/JPAExamplePagingProviderTest.java b/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/api/example/JPAExamplePagingProviderTest.java index 550062cc8..1c8a68a25 100644 --- a/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/api/example/JPAExamplePagingProviderTest.java +++ b/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/api/example/JPAExamplePagingProviderTest.java @@ -3,6 +3,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -10,6 +11,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import org.apache.olingo.commons.api.edm.EdmEntitySet; import org.apache.olingo.commons.api.edm.EdmProperty; @@ -46,24 +48,24 @@ void setup() throws ODataApplicationException { void testReturnDefaultTopSkipPageSize2() throws ODataApplicationException { final UriInfo info = buildUriInfo(); final JPAExamplePagingProvider cut = createOrganizationCut(2); - final JPAODataPage act = cut.getFirstPage(info, null, countQuery, null); + final Optional act = cut.getFirstPage(null, null, info, null, countQuery, null); - assertEquals(0, act.skip()); - assertEquals(2, act.top()); - assertNotNull(toODataString((String) act.skipToken())); - assertEquals(info, act.uriInfo()); + assertEquals(0, act.get().skip()); + assertEquals(2, act.get().top()); + assertNotNull(toODataString((String) act.get().skipToken())); + assertEquals(info, act.get().uriInfo()); } @Test void testReturnDefaultTopSkipPageSize5() throws ODataApplicationException { final UriInfo info = buildUriInfo(); final JPAExamplePagingProvider cut = createOrganizationCut(5); - final JPAODataPage act = cut.getFirstPage(info, null, countQuery, null); + final Optional act = cut.getFirstPage(null, null, info, null, countQuery, null); - assertEquals(0, act.skip()); - assertEquals(5, act.top()); - assertNotNull(toODataString((String) act.skipToken())); - assertEquals(info, act.uriInfo()); + assertEquals(0, act.get().skip()); + assertEquals(5, act.get().top()); + assertNotNull(toODataString((String) act.get().skipToken())); + assertEquals(info, act.get().uriInfo()); } @Test @@ -71,107 +73,107 @@ void testReturnDefaultTopSkipPageSizeOther() throws ODataApplicationException { final UriInfo info = buildUriInfo("AdministrativeDivisions", "AdministrativeDivision"); final JPAExamplePagingProvider cut = createOrganizationCut(5); when(countQuery.countResults()).thenReturn(12L); - final JPAODataPage act = cut.getFirstPage(info, null, countQuery, null); + final Optional act = cut.getFirstPage(null, null, info, null, countQuery, null); - assertEquals(0, act.skip()); - assertEquals(10, act.top()); - assertNotNull(toODataString((String) act.skipToken())); - assertEquals(info, act.uriInfo()); + assertEquals(0, act.get().skip()); + assertEquals(10, act.get().top()); + assertNotNull(toODataString((String) act.get().skipToken())); + assertEquals(info, act.get().uriInfo()); } @Test void testReturnDefaultTopSkipPageSize5NextPage() throws ODataApplicationException { final UriInfo info = buildUriInfo(); final JPAExamplePagingProvider cut = createOrganizationCut(5); - JPAODataPage act = cut.getFirstPage(info, null, countQuery, null); - act = cut.getNextPage(toODataString((String) act.skipToken())); + Optional act = cut.getFirstPage(null, null, info, null, countQuery, null); + act = cut.getNextPage(toODataString((String) act.get().skipToken()), null, null, null, null); - assertEquals(5, act.skip()); - assertEquals(5, act.top()); - assertEquals(info, act.uriInfo()); + assertEquals(5, act.get().skip()); + assertEquals(5, act.get().top()); + assertEquals(info, act.get().uriInfo()); } @Test void testReturnNullIfEntitySetIsUnknown() throws ODataApplicationException { final UriInfo info = buildUriInfo(); final JPAExamplePagingProvider cut = createPersonCut(5); - final JPAODataPage act = cut.getFirstPage(info, null, countQuery, null); + final Optional act = cut.getFirstPage(null, null, info, null, countQuery, null); - assertNull(act); + assertTrue(act.isEmpty()); } @Test void testReturnNullIfEntitySetIsUnknownButMaxPageSizeHeader() throws ODataApplicationException { final UriInfo info = buildUriInfo(); final JPAExamplePagingProvider cut = createPersonCut(5); - final JPAODataPage act = cut.getFirstPage(info, 3, countQuery, null); + final Optional act = cut.getFirstPage(null, null, info, 3, countQuery, null); - assertNull(act); + assertTrue(act.isEmpty()); } @Test void testReturnGetFirstPageRespectMaxPageSizeHeader() throws ODataApplicationException { final UriInfo info = buildUriInfo(); final JPAExamplePagingProvider cut = createOrganizationCut(5); - final JPAODataPage act = cut.getFirstPage(info, 3, countQuery, null); + final Optional act = cut.getFirstPage(null, null, info, 3, countQuery, null); - assertEquals(0, act.skip()); - assertEquals(3, act.top()); - assertNotNull(toODataString((String) act.skipToken())); - assertEquals(info, act.uriInfo()); + assertEquals(0, act.get().skip()); + assertEquals(3, act.get().top()); + assertNotNull(toODataString((String) act.get().skipToken())); + assertEquals(info, act.get().uriInfo()); } @Test void testReturnGetNextPageRespectMaxPageSizeHeader() throws ODataApplicationException { final UriInfo info = buildUriInfo(); final JPAExamplePagingProvider cut = createOrganizationCut(5); - JPAODataPage act = cut.getFirstPage(info, 3, countQuery, null); - act = cut.getNextPage(toODataString((String) act.skipToken())); + Optional act = cut.getFirstPage(null, null, info, 3, countQuery, null); + act = cut.getNextPage(toODataString((String) act.get().skipToken()), null, null, null, null); - assertEquals(3, act.skip()); - assertEquals(3, act.top()); - assertNotNull(toODataString((String) act.skipToken())); - assertEquals(info, act.uriInfo()); + assertEquals(3, act.get().skip()); + assertEquals(3, act.get().top()); + assertNotNull(toODataString((String) act.get().skipToken())); + assertEquals(info, act.get().uriInfo()); } @Test void testReturnSkipTokenNullAtLastPage() throws ODataApplicationException { final UriInfo info = buildUriInfo(); final JPAExamplePagingProvider cut = createOrganizationCut(5); - JPAODataPage act = cut.getFirstPage(info, null, countQuery, null); - act = cut.getNextPage(toODataString((String) act.skipToken())); + Optional act = cut.getFirstPage(null, null, info, null, countQuery, null); + act = cut.getNextPage(toODataString((String) act.get().skipToken()), null, null, null, null); - assertNull(act.skipToken()); + assertNull(act.get().skipToken()); } @Test void testReturnSkipTokenNullOnlyOnePage() throws ODataApplicationException { final UriInfo info = buildUriInfo("AdministrativeDivisions", "AdministrativeDivision"); final JPAExamplePagingProvider cut = createOrganizationCut(5); - final JPAODataPage act = cut.getFirstPage(info, null, countQuery, null); + final Optional act = cut.getFirstPage(null, null, info, null, countQuery, null); - assertNull(act.skipToken()); + assertNull(act.get().skipToken()); } @Test void testReturnSkipTokenIfNotLastPage() throws ODataApplicationException { final UriInfo info = buildUriInfo(); final JPAExamplePagingProvider cut = createOrganizationCut(2); - JPAODataPage act = cut.getFirstPage(info, null, countQuery, null); - act = cut.getNextPage(toODataString((String) act.skipToken())); + Optional act = cut.getFirstPage(null, null, info, null, countQuery, null); + act = cut.getNextPage(toODataString((String) act.get().skipToken()), null, null, null, null); - assertNotNull(toODataString((String) act.skipToken())); + assertNotNull(toODataString((String) act.get().skipToken())); } @Test void testReturnThirdPage() throws ODataApplicationException { final UriInfo info = buildUriInfo(); final JPAExamplePagingProvider cut = createOrganizationCut(2); - JPAODataPage act = cut.getFirstPage(info, null, countQuery, null); - act = cut.getNextPage(toODataString((String) act.skipToken())); - act = cut.getNextPage(toODataString((String) act.skipToken())); + Optional act = cut.getFirstPage(null, null, info, null, countQuery, null); + act = cut.getNextPage(toODataString((String) act.get().skipToken()), null, null, null, null); + act = cut.getNextPage(toODataString((String) act.get().skipToken()), null, null, null, null); - assertNotNull(toODataString((String) act.skipToken())); + assertNotNull(toODataString((String) act.get().skipToken())); } @Test @@ -179,10 +181,10 @@ void testRespectTopSkipOfUriFirstPageLowerMaxSize() throws ODataApplicationExcep final UriInfo info = buildUriInfo(); addTopSkipToUri(info); final JPAExamplePagingProvider cut = createOrganizationCut(10); - final JPAODataPage act = cut.getFirstPage(info, null, countQuery, null); + final Optional act = cut.getFirstPage(null, null, info, null, countQuery, null); - assertEquals(2, act.skip()); - assertEquals(7, act.top()); + assertEquals(2, act.get().skip()); + assertEquals(7, act.get().top()); } @Test @@ -190,10 +192,10 @@ void testRespectTopSkipOfUriFirstPage() throws ODataApplicationException { final UriInfo info = buildUriInfo(); addTopSkipToUri(info); final JPAExamplePagingProvider cut = createOrganizationCut(5); - final JPAODataPage act = cut.getFirstPage(info, null, countQuery, null); + final Optional act = cut.getFirstPage(null, null, info, null, countQuery, null); - assertEquals(2, act.skip()); - assertEquals(5, act.top()); + assertEquals(2, act.get().skip()); + assertEquals(5, act.get().top()); } @Test @@ -201,11 +203,11 @@ void testRespectTopSkipOfUriNextPage() throws ODataApplicationException { final UriInfo info = buildUriInfo(); addTopSkipToUri(info); final JPAExamplePagingProvider cut = createOrganizationCut(5); - JPAODataPage act = cut.getFirstPage(info, null, countQuery, null); - act = cut.getNextPage(toODataString((String) act.skipToken())); + Optional act = cut.getFirstPage(null, null, info, null, countQuery, null); + act = cut.getNextPage(toODataString((String) act.get().skipToken()), null, null, null, null); - assertEquals(7, act.skip()); - assertEquals(2, act.top()); + assertEquals(7, act.get().skip()); + assertEquals(2, act.get().top()); } @Test @@ -213,10 +215,10 @@ void testNoSkipTokenIfRealNoReturnedLowerPage() throws ODataApplicationException final UriInfo info = buildUriInfo(); addTopSkipToUri(info, 8, 10); final JPAExamplePagingProvider cut = createOrganizationCut(5); - final JPAODataPage act = cut.getFirstPage(info, null, countQuery, null); + final Optional act = cut.getFirstPage(null, null, info, null, countQuery, null); - assertNull(act.skipToken()); - assertEquals(8, act.skip()); + assertNull(act.get().skipToken()); + assertEquals(8, act.get().skip()); } @Test @@ -226,13 +228,13 @@ void testBufferFull() throws ODataApplicationException { sizes.put("Organizations", 2); final JPAExamplePagingProvider cut = new JPAExamplePagingProvider(sizes, 2); - final JPAODataPage first = cut.getFirstPage(info, null, countQuery, null); - assertNotNull(cut.getNextPage((String) first.skipToken())); - final JPAODataPage second = cut.getNextPage((String) first.skipToken()); - assertNotNull(cut.getNextPage((String) second.skipToken())); - final JPAODataPage third = cut.getNextPage((String) second.skipToken()); - assertNotNull(cut.getNextPage((String) third.skipToken())); - assertNull(cut.getNextPage((String) first.skipToken())); + final Optional first = cut.getFirstPage(null, null, info, null, countQuery, null); + assertNotNull(cut.getNextPage((String) first.get().skipToken(), null, null, null, null)); + final Optional second = cut.getNextPage((String) first.get().skipToken(), null, null, null, null); + assertTrue(cut.getNextPage((String) second.get().skipToken(), null, null, null, null).isPresent()); + final Optional third = cut.getNextPage((String) second.get().skipToken(), null, null, null, null); + assertTrue(cut.getNextPage((String) third.get().skipToken(), null, null, null, null).isPresent()); + assertTrue(cut.getNextPage((String) first.get().skipToken(), null, null, null, null).isEmpty()); } @Test @@ -242,13 +244,13 @@ void testBufferNotFull() throws ODataApplicationException { sizes.put("Organizations", 2); final JPAExamplePagingProvider cut = new JPAExamplePagingProvider(sizes, 10); - final JPAODataPage first = cut.getFirstPage(info, null, countQuery, null); - assertNotNull(cut.getNextPage((String) first.skipToken())); - final JPAODataPage second = cut.getNextPage((String) first.skipToken()); - assertNotNull(cut.getNextPage((String) second.skipToken())); - final JPAODataPage third = cut.getNextPage((String) second.skipToken()); - assertNotNull(cut.getNextPage((String) third.skipToken())); - assertNotNull(cut.getNextPage((String) first.skipToken())); + final Optional first = cut.getFirstPage(null, null, info, null, countQuery, null); + assertNotNull(cut.getNextPage((String) first.get().skipToken(), null, null, null, null)); + final Optional second = cut.getNextPage((String) first.get().skipToken(), null, null, null, null); + assertTrue(cut.getNextPage((String) second.get().skipToken(), null, null, null, null).isPresent()); + final Optional third = cut.getNextPage((String) second.get().skipToken(), null, null, null, null); + assertTrue(cut.getNextPage((String) third.get().skipToken(), null, null, null, null).isPresent()); + assertTrue(cut.getNextPage((String) first.get().skipToken(), null, null, null, null).isPresent()); } private UriInfo buildUriInfo() { diff --git a/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/modify/JPACreateResultTest.java b/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/modify/JPACreateResultTest.java index 4e985f688..2f81cc750 100644 --- a/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/modify/JPACreateResultTest.java +++ b/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/modify/JPACreateResultTest.java @@ -1,5 +1,6 @@ package com.sap.olingo.jpa.processor.core.modify; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -282,6 +283,12 @@ void testHasCountReturns() throws ODataJPAModelException, ODataApplicationExcept assertFalse(cut.hasCount()); } + @Test + void testConvertNoException() throws ODataJPAModelException, ODataApplicationException { + createCutProvidesEmptyMap(); + assertDoesNotThrow(() -> cut.convert(converter)); + } + private void assertDoesNotContain(final List result, final String prefix) { for (final Tuple t : result) { for (final TupleElement e : t.getElements()) diff --git a/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/processor/JPAODataInternalRequestContextTest.java b/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/processor/JPAODataInternalRequestContextTest.java index 0feb0345c..6f0179e0d 100644 --- a/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/processor/JPAODataInternalRequestContextTest.java +++ b/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/processor/JPAODataInternalRequestContextTest.java @@ -44,6 +44,7 @@ import com.sap.olingo.jpa.processor.core.api.JPAODataEtagHelper; import com.sap.olingo.jpa.processor.core.api.JPAODataGroupProvider; import com.sap.olingo.jpa.processor.core.api.JPAODataPagingProvider; +import com.sap.olingo.jpa.processor.core.api.JPAODataPathInformation; import com.sap.olingo.jpa.processor.core.api.JPAODataQueryDirectives; import com.sap.olingo.jpa.processor.core.api.JPAODataRequestContext; import com.sap.olingo.jpa.processor.core.api.JPAODataRequestContextAccess; @@ -83,6 +84,7 @@ class JPAODataInternalRequestContextTest { private JPAODataPagingProvider pagingProvider; private OData odata; private ETagHelper olingoEtagHelper; + private JPAODataPathInformation pathInformation; @BeforeEach void setup() throws ODataException { @@ -110,6 +112,7 @@ void setup() throws ODataException { queryDirectives = new JPAODataQueryDirectives.JPAODataQueryDirectivesImpl(0); pagingProvider = mock(JPAODataPagingProvider.class); etagHelper = mock(JPAODataEtagHelper.class); + pathInformation = new JPAODataPathInformation("", "", "", ""); when(odata.createETagHelper()).thenReturn(olingoEtagHelper); @@ -123,6 +126,7 @@ void setup() throws ODataException { when(contextAccess.getQueryDirectives()).thenReturn(queryDirectives); when(contextAccess.getEtagHelper()).thenReturn(etagHelper); when(contextAccess.getPagingProvider()).thenReturn(Optional.of(pagingProvider)); + when(contextAccess.getPathInformation()).thenReturn(pathInformation); when(requestContext.getClaimsProvider()).thenReturn(claims); when(requestContext.getCUDRequestHandler()).thenReturn(cudHandler); @@ -144,7 +148,7 @@ void setup() throws ODataException { @Test void testCreateFromContextUriAccessWithDebugger() throws ODataJPAProcessorException { - cut = new JPAODataInternalRequestContext(uriInfoResource, serializer, contextAccess, header); + cut = new JPAODataInternalRequestContext(uriInfoResource, serializer, contextAccess, header, pathInformation); assertEquals(transactionFactory, cut.getTransactionFactory()); assertEquals(serializer, cut.getSerializer()); @@ -160,6 +164,7 @@ void testCreateFromContextUriAccessWithDebugger() throws ODataJPAProcessorExcept assertEquals(queryDirectives, cut.getQueryDirectives()); assertEquals(etagHelper, cut.getEtagHelper()); assertEquals(pagingProvider, cut.getPagingProvider().get()); + assertEquals(pathInformation, cut.getPathInformation()); } @Test @@ -182,6 +187,7 @@ void testCreateFromContextUriContextAccess() throws ODataJPAProcessorException { assertEquals(queryDirectives, cut.getQueryDirectives()); assertEquals(etagHelper, cut.getEtagHelper()); assertEquals(pagingProvider, cut.getPagingProvider().get()); + assertEquals(pathInformation, cut.getPathInformation()); } @Test @@ -225,13 +231,13 @@ void testCreateFromRequestContextWithDebugSupport() { @Test void testCreateFromContextAccessWithDebugSupport() throws ODataJPAProcessorException { cut = new JPAODataInternalRequestContext(requestContext, sessionContext, odata); - cut = new JPAODataInternalRequestContext(uriInfo, serializer, cut, header); + cut = new JPAODataInternalRequestContext(uriInfo, serializer, cut, header, pathInformation); assertTrue(cut.getDebugSupport().isUserAuthorized()); } @Test void testGetLocaleLocaleNotEmpty() throws ODataJPAProcessorException { - cut = new JPAODataInternalRequestContext(uriInfo, serializer, contextAccess, header); + cut = new JPAODataInternalRequestContext(uriInfo, serializer, contextAccess, header, pathInformation); locales.add(Locale.JAPAN); locales.add(Locale.CANADA_FRENCH); @@ -240,7 +246,7 @@ void testGetLocaleLocaleNotEmpty() throws ODataJPAProcessorException { @Test void testGetLocaleLocaleEmpty() throws ODataJPAProcessorException { - cut = new JPAODataInternalRequestContext(uriInfo, serializer, contextAccess, header); + cut = new JPAODataInternalRequestContext(uriInfo, serializer, contextAccess, header, pathInformation); assertEquals(Locale.ENGLISH, cut.getLocale()); } @@ -248,7 +254,7 @@ void testGetLocaleLocaleEmpty() throws ODataJPAProcessorException { @Test void testGetLocaleLocaleNull() throws ODataJPAProcessorException { when(contextAccess.getProvidedLocale()).thenReturn(null); - cut = new JPAODataInternalRequestContext(uriInfo, serializer, contextAccess, header); + cut = new JPAODataInternalRequestContext(uriInfo, serializer, contextAccess, header, pathInformation); assertEquals(Locale.ENGLISH, cut.getLocale()); } @@ -256,7 +262,7 @@ void testGetLocaleLocaleNull() throws ODataJPAProcessorException { @Test void testGetTransactionFactoryIfNull() throws ODataJPAProcessorException { when(contextAccess.getTransactionFactory()).thenReturn(null); - cut = new JPAODataInternalRequestContext(uriInfo, serializer, contextAccess, header); + cut = new JPAODataInternalRequestContext(uriInfo, serializer, contextAccess, header, pathInformation); assertTrue(cut.getTransactionFactory() instanceof JPAODataDefaultTransactionFactory); } @@ -264,7 +270,7 @@ void testGetTransactionFactoryIfNull() throws ODataJPAProcessorException { @Test void testGetDebuggerReturnsDefaultIfNullAndFalse() throws ODataJPAProcessorException { when(contextAccess.getDebugger()).thenReturn(null); - cut = new JPAODataInternalRequestContext(uriInfo, serializer, contextAccess, header); + cut = new JPAODataInternalRequestContext(uriInfo, serializer, contextAccess, header, pathInformation); assertTrue(cut.getDebugger() instanceof JPAEmptyDebugger); } @@ -272,7 +278,7 @@ void testGetDebuggerReturnsDefaultIfNullAndFalse() throws ODataJPAProcessorExcep @SuppressWarnings({ "unchecked", "rawtypes" }) @Test void testGetQueryEnhancement() throws ODataJPAModelException, ODataJPAProcessorException { - cut = new JPAODataInternalRequestContext(uriInfo, serializer, contextAccess, header); + cut = new JPAODataInternalRequestContext(uriInfo, serializer, contextAccess, header, pathInformation); final JPAEntityType et = mock(JPAEntityType.class); final JPAQueryExtension extension = mock(JPAQueryExtension.class); when(et.getQueryExtension()).thenReturn(Optional.of(extension)); @@ -291,7 +297,7 @@ public Constructor answer(final InvocationO @Test void testGetCalculator() throws ODataJPAModelException, ODataJPAProcessorException, NoSuchMethodException, SecurityException { - cut = new JPAODataInternalRequestContext(uriInfo, serializer, contextAccess, header); + cut = new JPAODataInternalRequestContext(uriInfo, serializer, contextAccess, header, pathInformation); final JPAAttribute attribute = mock(JPAAttribute.class); final Constructor constructor = DummyPropertyCalculator.class.getConstructor(EntityManager.class); @@ -303,7 +309,7 @@ void testGetCalculator() throws ODataJPAModelException, ODataJPAProcessorExcepti @Test void testSetUriInfoThrowsExceptionPageExists() throws ODataJPAProcessorException { - cut = new JPAODataInternalRequestContext(uriInfo, serializer, contextAccess, header); + cut = new JPAODataInternalRequestContext(uriInfo, serializer, contextAccess, header, pathInformation); assertThrows(ODataJPAIllegalAccessException.class, () -> cut.setUriInfo(uriInfo)); } @@ -311,7 +317,7 @@ void testSetUriInfoThrowsExceptionPageExists() throws ODataJPAProcessorException @Test void testSetEntityManager() throws ODataJPAProcessorException { final EntityManager entityManager = mock(EntityManager.class); - cut = new JPAODataInternalRequestContext(uriInfo, serializer, contextAccess, header); + cut = new JPAODataInternalRequestContext(uriInfo, serializer, contextAccess, header, pathInformation); cut.setEntityManager(entityManager); assertEquals(entityManager, cut.getEntityManager()); @@ -320,7 +326,7 @@ void testSetEntityManager() throws ODataJPAProcessorException { @Test void testSetSerializer() throws ODataJPAProcessorException { final JPASerializer jpaSerializer = mock(JPASerializer.class); - cut = new JPAODataInternalRequestContext(uriInfo, serializer, contextAccess, header); + cut = new JPAODataInternalRequestContext(uriInfo, serializer, contextAccess, header, pathInformation); cut.setJPASerializer(jpaSerializer); assertEquals(jpaSerializer, cut.getSerializer()); diff --git a/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/processor/TestJPAODataRequestContextImpl.java b/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/processor/TestJPAODataRequestContextImpl.java index 99092e6e4..945be335a 100644 --- a/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/processor/TestJPAODataRequestContextImpl.java +++ b/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/processor/TestJPAODataRequestContextImpl.java @@ -34,6 +34,7 @@ import com.sap.olingo.jpa.processor.core.api.JPAODataClaimsProvider; import com.sap.olingo.jpa.processor.core.api.JPAODataGroupProvider; import com.sap.olingo.jpa.processor.core.api.JPAODataGroupsProvider; +import com.sap.olingo.jpa.processor.core.api.JPAODataPathInformation; import com.sap.olingo.jpa.processor.core.api.JPAODataRequestContext; import com.sap.olingo.jpa.processor.core.api.JPAODataSessionContextAccess; import com.sap.olingo.jpa.processor.core.errormodel.DummyPropertyCalculator; @@ -50,12 +51,14 @@ class TestJPAODataRequestContextImpl { private JPAODataRequestContext requestContext; private JPAEdmProvider edmProvider; private OData odata; + private JPAODataPathInformation pathInformation; @BeforeEach void setup() throws ODataException { edmProvider = mock(JPAEdmProvider.class); sessionContext = mock(JPAODataSessionContextAccess.class); requestContext = mock(JPAODataRequestContext.class); + pathInformation = new JPAODataPathInformation("", "", "", ""); odata = mock(OData.class); when(sessionContext.getEdmProvider()).thenReturn(edmProvider); cut = new JPAODataInternalRequestContext(requestContext, sessionContext, odata); @@ -118,7 +121,8 @@ void testCopyConstructorCopiesExternalAndAddsUriInfoSerializer() throws ODataJPA final UriInfo uriInfo = mock(UriInfo.class); final JPASerializer serializer = mock(JPASerializer.class); final Map> header = Collections.emptyMap(); - final JPAODataInternalRequestContext act = new JPAODataInternalRequestContext(uriInfo, serializer, cut, header); + final JPAODataInternalRequestContext act = new JPAODataInternalRequestContext(uriInfo, serializer, cut, header, + pathInformation); assertEquals(uriInfo, act.getUriInfo()); assertEquals(serializer, act.getSerializer()); @@ -131,7 +135,8 @@ void testCopyConstructorCopiesExternalAndAddsUriInfoSerializerNull() throws ODat fillContextForCopyConstructor(); final UriInfo uriInfo = mock(UriInfo.class); final Map> header = Collections.emptyMap(); - final JPAODataInternalRequestContext act = new JPAODataInternalRequestContext(uriInfo, null, cut, header); + final JPAODataInternalRequestContext act = new JPAODataInternalRequestContext(uriInfo, null, cut, header, + pathInformation); assertEquals(uriInfo, act.getUriInfo()); assertEquals(null, act.getSerializer()); @@ -151,9 +156,9 @@ void testGetCalculatorReturnsInstanceNoParameter() throws ODataJPAModelException NoSuchMethodException, SecurityException { final JPAAttribute attribute = mock(JPAAttribute.class); - final Constructor c = FullNameCalculator.class.getConstructor(); + final Constructor constructor = FullNameCalculator.class.getConstructor(); when(attribute.isTransient()).thenReturn(true); - when(attribute.getCalculatorConstructor()).thenReturn((Constructor>) c); + when(attribute.getCalculatorConstructor()).thenReturn((Constructor>) constructor); assertTrue(cut.getCalculator(attribute).isPresent()); } @@ -164,9 +169,9 @@ void testGetCalculatorReturnsInstanceFromCache() throws ODataJPAModelException, NoSuchMethodException, SecurityException { final JPAAttribute attribute = mock(JPAAttribute.class); - final Constructor c = FullNameCalculator.class.getConstructor(); + final Constructor constructor = FullNameCalculator.class.getConstructor(); when(attribute.isTransient()).thenReturn(true); - when(attribute.getCalculatorConstructor()).thenReturn((Constructor>) c); + when(attribute.getCalculatorConstructor()).thenReturn((Constructor>) constructor); final Optional> act = cut.getCalculator(attribute); assertEquals(act.get(), cut.getCalculator(attribute).get()); } @@ -177,12 +182,12 @@ void testGetCalculatorReturnsInstanceEntityManager() throws ODataJPAModelExcepti NoSuchMethodException, SecurityException { final JPAAttribute attribute = mock(JPAAttribute.class); - final Constructor c = DummyPropertyCalculator.class.getConstructor(EntityManager.class); + final Constructor constructor = DummyPropertyCalculator.class.getConstructor(EntityManager.class); cut = new JPAODataInternalRequestContext(JPAODataRequestContext .with().setEntityManager(mock(EntityManager.class)).build(), sessionContext, odata); when(attribute.isTransient()).thenReturn(true); - when(attribute.getCalculatorConstructor()).thenReturn((Constructor>) c); + when(attribute.getCalculatorConstructor()).thenReturn((Constructor>) constructor); final Optional> act = cut.getCalculator(attribute); assertTrue(act.isPresent()); @@ -195,9 +200,10 @@ void testGetCalculatorReturnsInstanceHeader() throws ODataJPAModelException, ODa NoSuchMethodException, SecurityException { final JPAAttribute attribute = mock(JPAAttribute.class); - final Constructor c = HeaderParamTransientPropertyConverter.class.getConstructor(JPAHttpHeaderMap.class); + final Constructor constructor = HeaderParamTransientPropertyConverter.class.getConstructor( + JPAHttpHeaderMap.class); when(attribute.isTransient()).thenReturn(true); - when(attribute.getCalculatorConstructor()).thenReturn((Constructor>) c); + when(attribute.getCalculatorConstructor()).thenReturn((Constructor>) constructor); final Optional> act = cut.getCalculator(attribute); assertTrue(act.isPresent()); assertNotNull(((HeaderParamTransientPropertyConverter) act.get()).getHeader()); @@ -209,12 +215,12 @@ void testGetCalculatorReturnsInstanceTwoParameter() throws ODataJPAModelExceptio NoSuchMethodException, SecurityException { final JPAAttribute attribute = mock(JPAAttribute.class); - final Constructor c = TwoParameterTransientPropertyConverter.class.getConstructor(EntityManager.class, + final Constructor constructor = TwoParameterTransientPropertyConverter.class.getConstructor(EntityManager.class, JPAHttpHeaderMap.class); cut = new JPAODataInternalRequestContext(JPAODataRequestContext .with().setEntityManager(mock(EntityManager.class)).build(), sessionContext, odata); when(attribute.isTransient()).thenReturn(true); - when(attribute.getCalculatorConstructor()).thenReturn((Constructor>) c); + when(attribute.getCalculatorConstructor()).thenReturn((Constructor>) constructor); final Optional> act = cut.getCalculator(attribute); assertTrue(act.isPresent()); diff --git a/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/query/JPANavigationNullQueryTest.java b/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/query/JPANavigationNullQueryTest.java index 4492f173f..301312c0c 100644 --- a/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/query/JPANavigationNullQueryTest.java +++ b/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/query/JPANavigationNullQueryTest.java @@ -1,6 +1,7 @@ package com.sap.olingo.jpa.processor.core.query; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doReturn; @@ -149,4 +150,11 @@ void testJoinQueryAggregateWithClaim() throws ODataApplicationException, ODataJP verify(cb).equal(idPath, idPath); verify(cb).equal(userNamePath, "Willi"); } + + @Test + void testCreateWhereEnhancementReturnsNull() throws ODataApplicationException { + cut = new JPANavigationNullQuery(odata, helper.sd, jpaEntityType, em, parent, from, association, Optional.of( + claimsProvider), Collections.emptyList()); + assertNull(cut.createWhereEnhancement(jpaEntityType, from)); + } } diff --git a/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/uri/JPAExpandItemTest.java b/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/uri/JPAExpandItemTest.java new file mode 100644 index 000000000..bf1d1a1fc --- /dev/null +++ b/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/uri/JPAExpandItemTest.java @@ -0,0 +1,80 @@ +package com.sap.olingo.jpa.processor.core.uri; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.DynamicTest.dynamicTest; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.Arrays; +import java.util.Collection; + +import org.apache.olingo.commons.api.edm.EdmType; +import org.apache.olingo.server.api.uri.queryoption.ApplyOption; +import org.apache.olingo.server.api.uri.queryoption.CountOption; +import org.apache.olingo.server.api.uri.queryoption.ExpandItem; +import org.apache.olingo.server.api.uri.queryoption.LevelsExpandOption; +import org.apache.olingo.server.api.uri.queryoption.SkipOption; +import org.apache.olingo.server.api.uri.queryoption.TopOption; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DynamicTest; +import org.junit.jupiter.api.TestFactory; + +class JPAExpandItemTest { + private JPAExpandItem cut; + private LevelsExpandOption levels; + private ExpandItem item; + private EdmType typeFilter; + private ApplyOption apply; + private TopOption top; + private SkipOption skip; + private CountOption count; + + @BeforeEach + void setup() { + levels = mock(LevelsExpandOption.class); + item = mock(ExpandItem.class); + typeFilter = mock(EdmType.class); + apply = mock(ApplyOption.class); + top = mock(TopOption.class); + skip = mock(SkipOption.class); + count = mock(CountOption.class); + + when(item.hasCountPath()).thenReturn(true); + when(item.isRef()).thenReturn(true); + when(item.getStartTypeFilter()).thenReturn(typeFilter); + when(item.getApplyOption()).thenReturn(apply); + when(item.getTopOption()).thenReturn(top); + when(item.getSkipOption()).thenReturn(skip); + when(item.getCountOption()).thenReturn(count); + } + + @TestFactory + Collection dynamicTestsNoItemProvided() { + cut = new JPAExpandItem(levels); + return Arrays.asList( + dynamicTest("isRef returns false", () -> assertFalse(cut.isRef())), + dynamicTest("hasCountPath returns false", () -> assertFalse(cut.hasCountPath())), + dynamicTest("getStartTypeFilter returns null", () -> assertNull(cut.getStartTypeFilter())), + dynamicTest("getApplyOption returns null", () -> assertNull(cut.getApplyOption())), + dynamicTest("getTopOption returns null", () -> assertNull(cut.getTopOption())), + dynamicTest("getSkipOption returns null", () -> assertNull(cut.getSkipOption())), + dynamicTest("getCountOption returns null", () -> assertNull(cut.getCountOption()))); + } + + @TestFactory + Collection dynamicTestsItemProvided() { + cut = new JPAExpandItem(item, levels); + return Arrays.asList( + dynamicTest("isRef returns original value", () -> assertTrue(cut.isRef())), + dynamicTest("hasCountPath returns original value", () -> assertTrue(cut.hasCountPath())), + dynamicTest("getStartTypeFilter returns original value", () -> assertEquals(typeFilter, cut + .getStartTypeFilter())), + dynamicTest("getApplyOption returns original value", () -> assertEquals(apply, cut.getApplyOption())), + dynamicTest("getTopOption returns original value", () -> assertEquals(top, cut.getTopOption())), + dynamicTest("getSkipOption returns original value", () -> assertEquals(skip, cut.getSkipOption())), + dynamicTest("getCountOption returns original value", () -> assertEquals(count, cut.getCountOption()))); + } +} diff --git a/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/uri/JPAUriInfoFactoryTest.java b/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/uri/JPAUriInfoFactoryTest.java index 42a10c785..3bcee2873 100644 --- a/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/uri/JPAUriInfoFactoryTest.java +++ b/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/uri/JPAUriInfoFactoryTest.java @@ -130,6 +130,9 @@ void testFactoryConvertsOneExpand() { final var act = cut.build(); assertFirstPagedResourceParts(act); + assertEquals(20, act.getSkipOption().getValue()); + assertEquals(10, act.getTopOption().getValue()); + assertEquals("New", act.getSkipTokenOption().getValue()); } @Test diff --git a/jpa/pom.xml b/jpa/pom.xml index 01d6d0a19..d836d70d0 100644 --- a/jpa/pom.xml +++ b/jpa/pom.xml @@ -18,7 +18,7 @@ 2.16.0 1.7.1 4.3.0 - 3.8.3 + 3.8.4 10.18.0 6.1.0 4.0.1 @@ -29,8 +29,8 @@ 6.4.0.Final 4.0.0 10.16.1.1 - 5.11.0 - 1.10.3 + 5.11.1 + 1.11.1 5.13.0 0.8.12 4.1.113.Final