From ac6e9e725de08d8b74e1e878239f80b64789d85a Mon Sep 17 00:00:00 2001 From: Michael Bolz Date: Thu, 30 Jul 2015 21:33:49 +0200 Subject: [PATCH] [OLINGO-741] Add pre-validation for properties in UriParseTreeVisitor --- .../core/uri/parser/UriParseTreeVisitor.java | 29 ++++++---- .../core/uri/antlr/TestFullResourcePath.java | 56 ++++++++++++++++--- 2 files changed, 68 insertions(+), 17 deletions(-) diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java index 16aa42e44..dcccf7cd8 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java @@ -288,8 +288,21 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor { String odi = ctx.vODI.getText(); - if (checkFirst && ctx.vNS == null) { + boolean searchInContainer = true; + // validate if context type and according property is available + // otherwise search in container for first element + if (checkFirst && ctx.vNS == null && !context.contextTypes.empty()) { + TypeInformation source = context.contextTypes.peek(); + if (source.type instanceof EdmStructuredType) { + EdmStructuredType str = (EdmStructuredType) source.type; + EdmElement property = str.getProperty(odi); + if (property != null) { + searchInContainer = false; + } + } + } + if(searchInContainer) { // check EntitySet EdmEntitySet edmEntitySet = edmEntityContainer.getEntitySet(odi); if (edmEntitySet != null) { @@ -362,8 +375,8 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor { } } - TypeInformation source = null; - UriResource lastResourcePart = context.contextUriInfo.getLastResourcePart(); + final TypeInformation source; + final UriResource lastResourcePart = context.contextUriInfo.getLastResourcePart(); if (lastResourcePart == null) { if (context.contextTypes.empty()) { @@ -427,7 +440,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor { } if (property instanceof EdmProperty) { - if (((EdmProperty) property).isPrimitive() == true) { + if (((EdmProperty) property).isPrimitive()) { // create simple property UriResourcePrimitivePropertyImpl simpleResource = new UriResourcePrimitivePropertyImpl() .setProperty((EdmProperty) property); @@ -485,7 +498,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor { if (lastResourcePart instanceof UriResourceWithKeysImpl) { UriResourceWithKeysImpl lastPartWithKeys = (UriResourceWithKeysImpl) lastResourcePart; - if (lastPartWithKeys.isCollection() == false) { + if (!lastPartWithKeys.isCollection()) { if (lastPartWithKeys.getTypeFilterOnEntry() != null) { throw wrap(new UriParserSemanticException("Entry typefilters are not chainable, used '" + getName(filterEntityType) + "' behind '" @@ -559,7 +572,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor { // e.g. in case of function returning complex data or a list of complex data UriResourceWithKeysImpl lastPartWithKeys = (UriResourceWithKeysImpl) lastResourcePart; - if (lastPartWithKeys.isCollection() == false) { + if (!lastPartWithKeys.isCollection()) { if (lastPartWithKeys.getTypeFilterOnEntry() != null) { throw wrap(new UriParserSemanticException("Entry typefilters are not chainable, used '" + getName(filterComplexType) + "' behind '" @@ -1193,9 +1206,6 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor { public Object visitExpandPath(final ExpandPathContext ctx) { ExpandItemImpl expandItem = new ExpandItemImpl(); - // UriResourceItImpl pathInfoIT = new UriResourceItImpl(); - context.contextUriInfo.getLastResourcePart(); - // save context ExpandItemImpl contextExpandItemPathBU = context.contextExpandItemPath; UriInfoImpl uriInfoResourceBU = context.contextUriInfo; @@ -1203,7 +1213,6 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor { // set tmp context context.contextExpandItemPath = expandItem; context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.resource); - // contextUriInfo.addPathInfo(pathInfoIT); super.visitExpandPath(ctx); diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java index d1ffaab9c..10240abd5 100644 --- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java +++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java @@ -22,6 +22,11 @@ import java.io.UnsupportedEncodingException; import java.util.Arrays; import org.apache.olingo.commons.api.edm.Edm; +import org.apache.olingo.commons.api.edm.EdmEntityContainer; +import org.apache.olingo.commons.api.edm.EdmEntitySet; +import org.apache.olingo.commons.api.edm.EdmEntityType; +import org.apache.olingo.commons.api.edm.EdmNavigationProperty; +import org.apache.olingo.commons.api.edm.FullQualifiedName; import org.apache.olingo.commons.api.http.HttpContentType; import org.apache.olingo.commons.core.Encoder; import org.apache.olingo.commons.core.edm.EdmProviderImpl; @@ -46,6 +51,7 @@ import org.apache.olingo.server.tecsvc.provider.EnumTypeProvider; import org.apache.olingo.server.tecsvc.provider.PropertyProvider; import org.junit.Ignore; import org.junit.Test; +import org.mockito.Mockito; public class TestFullResourcePath { Edm edm = null; @@ -248,8 +254,8 @@ public class TestFullResourcePath { .isFunction("BFCESBaseTwoKeyNavRTESBaseTwoKey"); testUri.run("ESTwoKeyNav/olingo.odata.test1.ETBaseTwoKeyNav" - + "/olingo.odata.test1.BFCESBaseTwoKeyNavRTESBaseTwoKey()" - + "/olingo.odata.test1.ETTwoBaseTwoKeyNav") + + "/olingo.odata.test1.BFCESBaseTwoKeyNavRTESBaseTwoKey()" + + "/olingo.odata.test1.ETTwoBaseTwoKeyNav") .isKind(UriInfoKind.resource).goPath() .first() .isEntitySet("ESTwoKeyNav") @@ -1474,7 +1480,7 @@ public class TestFullResourcePath { .isNavProperty("NavPropertyETKeyNavMany", EntityTypeProvider.nameETKeyNav, true); testUri.run("ESTwoKeyNav(PropertyInt16=1,PropertyString='2')/olingo.odata.test1.ETBaseTwoKeyNav" - + "/NavPropertyETKeyNavMany(3)") + + "/NavPropertyETKeyNavMany(3)") .isKind(UriInfoKind.resource).goPath() .first() .isEntitySet("ESTwoKeyNav") @@ -1766,7 +1772,7 @@ public class TestFullResourcePath { .isTypeFilterOnEntry(EntityTypeProvider.nameETBaseTwoKeyNav); testUri.run("FICRTETTwoKeyNavParam(ParameterInt16=1)(PropertyInt16=2,PropertyString='3')" - + "/olingo.odata.test1.ETBaseTwoKeyNav") + + "/olingo.odata.test1.ETBaseTwoKeyNav") .isKind(UriInfoKind.resource).goPath() .first() .isFunctionImport("FICRTETTwoKeyNavParam") @@ -2072,6 +2078,45 @@ public class TestFullResourcePath { .isCount(); } + /** + * Test for EntitySet and NavigationProperty with same name defined in metadata. + * (related to Olingo issue OLINGO-741) + */ + @Test + public void yetAnotherSmallTest() throws Exception { + TestUriValidator testUri = new TestUriValidator(); + + Edm mockEdm = Mockito.mock(Edm.class); + EdmEntitySet esCategory = Mockito.mock(EdmEntitySet.class); + EdmEntitySet esProduct = Mockito.mock(EdmEntitySet.class); + EdmEntityType typeCategory = Mockito.mock(EdmEntityType.class); + EdmEntityContainer container = Mockito.mock(EdmEntityContainer.class); + EdmNavigationProperty productsNavigation = Mockito.mock(EdmNavigationProperty.class); + EdmEntityType productsType = Mockito.mock(EdmEntityType.class); + + Mockito.when(mockEdm.getEntityContainer(null)).thenReturn(container); + Mockito.when(typeCategory.getName()).thenReturn("Category"); + Mockito.when(typeCategory.getNamespace()).thenReturn("NS"); + Mockito.when(esCategory.getEntityType()).thenReturn(typeCategory); + Mockito.when(productsNavigation.getName()).thenReturn("Products"); + Mockito.when(typeCategory.getProperty("Products")).thenReturn(productsNavigation); + Mockito.when(container.getEntitySet("Category")).thenReturn(esCategory); + Mockito.when(container.getEntitySet("Products")).thenReturn(esProduct); + Mockito.when(productsType.getName()).thenReturn("Products"); + Mockito.when(productsType.getNamespace()).thenReturn("NS"); + Mockito.when(productsNavigation.getType()).thenReturn(productsType); + + // test and verify + testUri.setEdm(mockEdm) + .run("Category", "$expand=Products") + .isKind(UriInfoKind.resource).goPath().goExpand() + .first() + .goPath().first() + .isNavProperty("Products", new FullQualifiedName("NS", "Products"), false) + .isType(new FullQualifiedName("NS", "Products"), false); + Mockito.verifyZeroInteractions(esProduct); + } + @Test public void runExpand() throws Exception { @@ -2362,9 +2407,6 @@ public class TestFullResourcePath { .goExpand().first() .isExpandStartType(EntityTypeProvider.nameETBaseTwoKeyNav) .goPath().first() - // .isType(EntityTypeProvider.nameETTwoKeyNav) - // .isTypeFilterOnCollection(EntityTypeProvider.nameETBaseTwoKeyNav) - // .n() .isNavProperty("NavPropertyETKeyNavMany", EntityTypeProvider.nameETKeyNav, true); testUri.run("ESTwoKeyNav(PropertyInt16=1,PropertyString='Hugo')",