From 71ea12382c452cbafc7a12273480d43428476456 Mon Sep 17 00:00:00 2001 From: Sven Kobler Date: Mon, 10 Feb 2014 09:40:18 +0100 Subject: [PATCH] [OLINGO-63] Uri Parser: add evalation of referential contrains --- .../api/edm/EdmNavigationProperty.java | 2 + .../odata4/producer/api/uri/UriParameter.java | 2 + .../producer/core/uri/antlr/UriLexer.g4 | 2 +- .../producer/core/uri/antlr/UriParser.g4 | 4 +- .../producer/core/uri/UriParameterImpl.java | 12 +- .../core/uri/UriParseTreeVisitor.java | 181 +++++++++++++--- .../core/uri/UriResourceFunctionImpl.java | 13 +- .../core/testutil/EdmTechProvider.java | 13 +- .../core/testutil/FilterValidator.java | 3 +- .../core/testutil/UriResourceValidator.java | 16 +- .../core/uri/UriParameterImplTest.java | 6 +- .../core/uri/antlr/TestFullResourcePath.java | 200 ++++++++++-------- .../producer/core/uri/antlr/TestLexer.java | 2 +- .../producer/core/uri/antlr/TestParser.java | 23 -- .../core/uri/antlr/TestUriParserImpl.java | 68 ++++++ 15 files changed, 381 insertions(+), 166 deletions(-) diff --git a/odata4-lib/odata4-commons-api/src/main/java/org/apache/olingo/odata4/commons/api/edm/EdmNavigationProperty.java b/odata4-lib/odata4-commons-api/src/main/java/org/apache/olingo/odata4/commons/api/edm/EdmNavigationProperty.java index aa317e419..7d4cbbd4d 100644 --- a/odata4-lib/odata4-commons-api/src/main/java/org/apache/olingo/odata4/commons/api/edm/EdmNavigationProperty.java +++ b/odata4-lib/odata4-commons-api/src/main/java/org/apache/olingo/odata4/commons/api/edm/EdmNavigationProperty.java @@ -18,6 +18,8 @@ ******************************************************************************/ package org.apache.olingo.odata4.commons.api.edm; +import java.util.List; + /** * A CSDL NavigationProperty element *

EdmNavigationProperty allows navigation from one entity type to another via a relationship. diff --git a/odata4-lib/odata4-producer-api/src/main/java/org/apache/olingo/odata4/producer/api/uri/UriParameter.java b/odata4-lib/odata4-producer-api/src/main/java/org/apache/olingo/odata4/producer/api/uri/UriParameter.java index 7a47585c6..12a212b7d 100644 --- a/odata4-lib/odata4-producer-api/src/main/java/org/apache/olingo/odata4/producer/api/uri/UriParameter.java +++ b/odata4-lib/odata4-producer-api/src/main/java/org/apache/olingo/odata4/producer/api/uri/UriParameter.java @@ -29,5 +29,7 @@ public interface UriParameter { public Expression getExression(); public String getName(); + + public String getRefencedProperty(); } diff --git a/odata4-lib/odata4-producer-core/src/main/antlr4/org/apache/olingo/odata4/producer/core/uri/antlr/UriLexer.g4 b/odata4-lib/odata4-producer-core/src/main/antlr4/org/apache/olingo/odata4/producer/core/uri/antlr/UriLexer.g4 index 26d435034..33e729659 100644 --- a/odata4-lib/odata4-producer-core/src/main/antlr4/org/apache/olingo/odata4/producer/core/uri/antlr/UriLexer.g4 +++ b/odata4-lib/odata4-producer-core/src/main/antlr4/org/apache/olingo/odata4/producer/core/uri/antlr/UriLexer.g4 @@ -77,7 +77,7 @@ END_OBJECT : WS* ( '}' / '%7D' ) WS*; BEGIN_ARRAY : WS* ( '[' / '%5B' ) WS*; END_ARRAY : WS* ( ']' / '%5D' ) WS*; -NAME_SEPARATOR : WS* COLON WS*; + //alpha stuff fragment ALPHA : 'a'..'z' | 'A'..'Z'; diff --git a/odata4-lib/odata4-producer-core/src/main/antlr4/org/apache/olingo/odata4/producer/core/uri/antlr/UriParser.g4 b/odata4-lib/odata4-producer-core/src/main/antlr4/org/apache/olingo/odata4/producer/core/uri/antlr/UriParser.g4 index 4838ae00f..c0f0fe866 100644 --- a/odata4-lib/odata4-producer-core/src/main/antlr4/org/apache/olingo/odata4/producer/core/uri/antlr/UriParser.g4 +++ b/odata4-lib/odata4-producer-core/src/main/antlr4/org/apache/olingo/odata4/producer/core/uri/antlr/UriParser.g4 @@ -284,7 +284,7 @@ rootExpr : ROOT vPs=pathSegments; memberExpr : vIt=IT ( SLASH (vANY=anyExpr | vALL=allExpr))? | vIts=ITSLASH? vPs=pathSegments ( SLASH (vANY=anyExpr | vALL=allExpr))?; -anyExpr : ANY_LAMDA OPEN WSP? ( vLV=odataIdentifier WSP? COLON WSP? vLE=commonExpr WSP? )? CLOSE; +anyExpr : ANY_LAMDA OPEN WSP? ( vLV=odataIdentifier WSP? COLON WSP? vLE=commonExpr WSP? )? CLOSE; allExpr : ALL_LAMDA OPEN WSP? vLV=odataIdentifier WSP? COLON WSP? vLE=commonExpr WSP? CLOSE; methodCallExpr : indexOfMethodCallExpr @@ -380,7 +380,7 @@ json_value : jsonPrimitiv json_object : BEGIN_OBJECT STRING_IN_JSON - NAME_SEPARATOR + WSP? COLON WSP? json_value END_OBJECT; diff --git a/odata4-lib/odata4-producer-core/src/main/java/org/apache/olingo/odata4/producer/core/uri/UriParameterImpl.java b/odata4-lib/odata4-producer-core/src/main/java/org/apache/olingo/odata4/producer/core/uri/UriParameterImpl.java index 54950bcbc..c72b78a1b 100644 --- a/odata4-lib/odata4-producer-core/src/main/java/org/apache/olingo/odata4/producer/core/uri/UriParameterImpl.java +++ b/odata4-lib/odata4-producer-core/src/main/java/org/apache/olingo/odata4/producer/core/uri/UriParameterImpl.java @@ -28,6 +28,7 @@ public class UriParameterImpl implements UriParameter { private String text; private String alias; private Expression expression; + private String referencedProperty; @Override public String getName() { @@ -61,7 +62,6 @@ public class UriParameterImpl implements UriParameter { @Override public Expression getExression() { - return expression; } @@ -69,4 +69,14 @@ public class UriParameterImpl implements UriParameter { this.expression = expression; return this; } + + @Override + public String getRefencedProperty() { + return this.referencedProperty; + } + + public UriParameterImpl setRefencedProperty(String referencedProperty) { + this.referencedProperty = referencedProperty; + return this; + } } diff --git a/odata4-lib/odata4-producer-core/src/main/java/org/apache/olingo/odata4/producer/core/uri/UriParseTreeVisitor.java b/odata4-lib/odata4-producer-core/src/main/java/org/apache/olingo/odata4/producer/core/uri/UriParseTreeVisitor.java index 4256be66f..1e6c794cd 100644 --- a/odata4-lib/odata4-producer-core/src/main/java/org/apache/olingo/odata4/producer/core/uri/UriParseTreeVisitor.java +++ b/odata4-lib/odata4-producer-core/src/main/java/org/apache/olingo/odata4/producer/core/uri/UriParseTreeVisitor.java @@ -257,6 +257,8 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor { */ private UriInfoImpl contextUriInfo; + private boolean contextReadingFunctionParameters = false; + // --- class --- public void init() { @@ -278,10 +280,10 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor { } private FullQualifiedName getFullName(final NamespaceContext vNS, final String odi) { - String namespace = vNS.getText(); - namespace = namespace.substring(0, namespace.length() - 1); + String namespace = vNS.getText(); + namespace = namespace.substring(0, namespace.length() - 1); - return new FullQualifiedName(namespace, odi); + return new FullQualifiedName(namespace, odi); } private LambdaVariables getLambdaVar(final String odi) { @@ -353,11 +355,24 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor { if (edmFunctionImport != null) { // read the URI parameters + this.contextReadingFunctionParameters = true; List parameters = (List) ctx.vlNVO.get(0).accept(this); + this.contextReadingFunctionParameters = false; ctx.vlNVO.remove(0); // parameters are consumed UriResourceFunctionImpl uriResource = new UriResourceFunctionImpl(); uriResource.setFunctionImport(edmFunctionImport, parameters); + /* get function from function import */ + List names = new ArrayList(); + for (UriParameterImpl item : parameters) { + names.add(item.getName()); + } + EdmFunction function = edmFunctionImport.getFunction(names); + if (function == null) { + throw wrap(new UriParserSemanticException("Function via function import not found")); + } + uriResource.setFunction(edmFunctionImport.getFunction(names)); + contextUriInfo.addResourcePart(uriResource); return null; } @@ -565,8 +580,9 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor { throw wrap(new UriParserSemanticException("Expected function parameters")); } + this.contextReadingFunctionParameters = true; List parameters = (List) ctx.vlNVO.get(0).accept(this); - + this.contextReadingFunctionParameters = false; // get names of function parameters List names = new ArrayList(); for (UriParameterImpl item : parameters) { @@ -624,7 +640,6 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor { public Object visitAllExpr(final AllExprContext ctx) { UriResourceLambdaAllImpl all = new UriResourceLambdaAllImpl(); - // TODO UriResourcePart obj = contextUriInfo.getLastResourcePart(); if (!(obj instanceof UriResourceImplTyped)) { throw wrap(new UriParserSemanticException("any only allowed on typed path segments")); @@ -1451,51 +1466,147 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor { @Override public Object visitNameValueOptList(final NameValueOptListContext ctx) { - - // is key predicate if (ctx.vVO != null) { + + // is single key predicate without a name String valueText = ctx.vVO.vV.getText(); ExpressionImpl expression = (ExpressionImpl) ctx.vVO.vV.accept(this); - if (!(contextUriInfo.getLastResourcePart() instanceof UriResourceImplTyped)) { + // get type of last resource part + UriResourcePart last = contextUriInfo.getLastResourcePart(); + if (!(last instanceof UriResourceImplTyped)) { throw wrap(new UriParserSyntaxException("Paramterslist on untyped resource path segement not allowed")); } + EdmEntityType lastType = (EdmEntityType) ((UriResourceImplTyped) last).getType(); - EdmEntityType entityType = - (EdmEntityType) ((UriResourceImplTyped) contextUriInfo.getLastResourcePart()).getType(); + // get list of keys for lastType + List lastKeyPredicates = lastType.getKeyPredicateNames(); - List keyPredicates = entityType.getKeyPredicateNames(); - if (keyPredicates.size() == 1) { - String keyName = keyPredicates.get(0); + // if there is exactly one key defined in the EDM, then this key the the key written in the URI, + // so fill the keylist with this key and return + if (lastKeyPredicates.size() == 1) { + String keyName = lastKeyPredicates.get(0); List list = new ArrayList(); list.add(new UriParameterImpl().setName(keyName).setText(valueText).setExpression(expression)); return list; } - // If there is only a single key in the URI but there are more than one keys defined in the EDM, then reduce - // The keylist with the keys defined as referential constrained. - // TODO add support vor using refential constrains - /* - * if (contextUriInfo.getLastResourcePart() instanceof UriResourceNavigationPropertyImpl) { - * UriResourceNavigationPropertyImpl nav = - * (UriResourceNavigationPropertyImpl) contextUriInfo.getLastResourcePart(); - * nav.getNavigationProperty(); - * } - */ + // There are more keys defined in the EDM, but only one is written in the URI. This is allowed only if + // referential constrains are defined on this navigation property which can be used to will up all required + // key. - throw wrap(new UriParserSyntaxException( - "for using a value only keyPredicate there must be exact ONE defined keyProperty")); + // for using referential constrains the last resource part must be a navigation property + if (!(contextUriInfo.getLastResourcePart() instanceof UriResourceNavigationPropertyImpl)) { + throw wrap(new UriParserSyntaxException("Not enougth keyproperties defined")); + } + UriResourceNavigationPropertyImpl lastNav = (UriResourceNavigationPropertyImpl) last; - } else { + // get the partner of the navigation property + EdmNavigationProperty partner = lastNav.getProperty().getPartner(); + if (partner == null) { + throw wrap(new UriParserSyntaxException("Not enougth keyproperties defined")); + } + + // create the keylist List list = new ArrayList(); - if (ctx.vNVL != null) { - for (ParseTree c : ctx.vNVL.vlNVP) { - list.add((UriParameterImpl) c.accept(this)); + + // find the key not filled by referential constrains and collect the other keys filled by + // referential constrains + String missedKey = null; + for (String item : lastKeyPredicates) { + String property = partner.getReferencingPropertyName(item); + if (property != null) { + list.add(new UriParameterImpl().setName(item).setRefencedProperty(property)); + } else { + if (missedKey == null) { + missedKey = item; + } else { + // two of more keys are missing + throw wrap(new UriParserSyntaxException("Not enougth referntial contrains defined")); + } } } - return list; + // the missing key is the one which is defined in the URI + list.add(new UriParameterImpl().setName(missedKey).setText(valueText).setExpression(expression)); + + return list; + } else if (ctx.vNVL != null) { + + List list = new ArrayList(); + + for (ParseTree c : ctx.vNVL.vlNVP) { + list.add((UriParameterImpl) c.accept(this)); + } + + if (contextReadingFunctionParameters){ + return list; } + + UriResourcePart last = contextUriInfo.getLastResourcePart(); + // if the last resource part is a function + /*if (last instanceof UriResourceFunctionImpl) { + UriResourceFunctionImpl function = (UriResourceFunctionImpl) last; + if (!function.isParameterListFilled()) { + return list; + } + }*/ + + // get type of last resource part + if (!(last instanceof UriResourceImplTyped)) { + throw wrap(new UriParserSyntaxException("Parameterslist on untyped resource path segement not allowed")); + } + EdmEntityType lastType = (EdmEntityType) ((UriResourceImplTyped) last).getType(); + + // get list of keys for lastType + List lastKeyPredicates = lastType.getKeyPredicateNames(); + + // check if all key are filled from the URI + if (list.size() == lastKeyPredicates.size()) { + return list; + } + + // if not, check if the missing key predicates can be satisfied with help of the defined referential constrains + + // for using referential constrains the last resource part must be a navigation property + if (!(contextUriInfo.getLastResourcePart() instanceof UriResourceNavigationPropertyImpl)) { + throw wrap(new UriParserSyntaxException("Not enougth keyproperties defined")); + } + UriResourceNavigationPropertyImpl lastNav = (UriResourceNavigationPropertyImpl) last; + + // get the partner of the navigation property + EdmNavigationProperty partner = lastNav.getProperty().getPartner(); + if (partner == null) { + throw wrap(new UriParserSyntaxException("Not enougth keyproperties defined")); + } + + // fill missing keys from referential constrains + for (String key : lastKeyPredicates) { + boolean found = false; + for (UriParameterImpl item : list) { + if (item.getName().equals(key)) { + found = true; + break; + } + } + + if (!found) { + String property = partner.getReferencingPropertyName(key); + if (property != null) { + // store the key name as referenced property + list.add(0, new UriParameterImpl().setName(key).setRefencedProperty(property)); + } + } + } + + // check again if all keyPredicate are filled from the URI + if (list.size() == lastKeyPredicates.size()) { + return list; + } + + throw wrap(new UriParserSyntaxException("Not enougth keyproperties defined")); + } + return new ArrayList(); } @Override @@ -1752,13 +1863,13 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor { if (property.isPrimitive()) { UriResourcePrimitivePropertyImpl simple = new UriResourcePrimitivePropertyImpl(); simple.setProperty(property); - + UriInfoImpl resourcePath = (UriInfoImpl) contextSelectItem.getResourceInfo(); resourcePath.addResourcePart(simple); } else { UriResourceComplexPropertyImpl complex = new UriResourceComplexPropertyImpl(); complex.setProperty(property); - + UriInfoImpl resourcePath = (UriInfoImpl) contextSelectItem.getResourceInfo(); resourcePath.addResourcePart(complex); } @@ -1780,7 +1891,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor { EdmComplexType ct = edm.getComplexType(fullName); if (ct != null) { if (((EdmStructuralType) prevType).compatibleTo(ct)) { - UriResourcePart lastSegment = ((UriInfoImpl)contextSelectItem.getResourceInfo()).getLastResourcePart(); + UriResourcePart lastSegment = ((UriInfoImpl) contextSelectItem.getResourceInfo()).getLastResourcePart(); if (lastSegment instanceof UriResourceImplKeyPred) { UriResourceImplKeyPred lastKeyPred = (UriResourceImplKeyPred) lastSegment; lastKeyPred.setCollectionTypeFilter(ct); @@ -1814,7 +1925,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor { if (action != null) { UriResourceActionImpl uriAction = new UriResourceActionImpl(); uriAction.setAction(action); - + UriInfoImpl resourcePath = (UriInfoImpl) contextSelectItem.getResourceInfo(); resourcePath.addResourcePart(uriAction); } @@ -1826,7 +1937,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor { if (function != null) { UriResourceFunctionImpl uriFunction = new UriResourceFunctionImpl(); uriFunction.setFunction(function); - + UriInfoImpl resourcePath = (UriInfoImpl) contextSelectItem.getResourceInfo(); resourcePath.addResourcePart(uriFunction); } diff --git a/odata4-lib/odata4-producer-core/src/main/java/org/apache/olingo/odata4/producer/core/uri/UriResourceFunctionImpl.java b/odata4-lib/odata4-producer-core/src/main/java/org/apache/olingo/odata4/producer/core/uri/UriResourceFunctionImpl.java index 605bb1e03..e2b632783 100644 --- a/odata4-lib/odata4-producer-core/src/main/java/org/apache/olingo/odata4/producer/core/uri/UriResourceFunctionImpl.java +++ b/odata4-lib/odata4-producer-core/src/main/java/org/apache/olingo/odata4/producer/core/uri/UriResourceFunctionImpl.java @@ -36,6 +36,7 @@ public class UriResourceFunctionImpl extends UriResourceImplKeyPred implements U protected List parameters; protected EdmFunction function; protected EdmFunctionImport functionImport; + private boolean isParameterListFilled = false; public UriResourceFunctionImpl() { super(UriResourceKind.function); @@ -51,6 +52,7 @@ public class UriResourceFunctionImpl extends UriResourceImplKeyPred implements U } public UriResourceFunctionImpl setParameters(final List parameters) { + isParameterListFilled = true; this.parameters = parameters; return this; } @@ -73,14 +75,7 @@ public class UriResourceFunctionImpl extends UriResourceImplKeyPred implements U public UriResourceFunctionImpl setFunctionImport(final EdmFunctionImport edmFI, final List parameters) { functionImport = edmFI; - this.parameters = parameters; - List names = new ArrayList(); - for (UriParameterImpl item : parameters) { - names.add(item.getName()); - } - - setFunction(edmFI.getFunction(names)); setParameters(parameters); return this; @@ -109,4 +104,8 @@ public class UriResourceFunctionImpl extends UriResourceImplKeyPred implements U return ""; } + public boolean isParameterListFilled() { + return isParameterListFilled; + } + } diff --git a/odata4-lib/odata4-producer-core/src/test/java/org/apache/olingo/odata4/producer/core/testutil/EdmTechProvider.java b/odata4-lib/odata4-producer-core/src/test/java/org/apache/olingo/odata4/producer/core/testutil/EdmTechProvider.java index 817d6aa4a..a33717195 100644 --- a/odata4-lib/odata4-producer-core/src/test/java/org/apache/olingo/odata4/producer/core/testutil/EdmTechProvider.java +++ b/odata4-lib/odata4-producer-core/src/test/java/org/apache/olingo/odata4/producer/core/testutil/EdmTechProvider.java @@ -1188,7 +1188,7 @@ public class EdmTechProvider extends EdmProvider { .setCollection(true) )); - } else if (entityTypeName.equals(nameETCompMixPrimCollComp)) { + } else if (entityTypeName.equals(nameETFourKeyAlias)) { return new EntityType() .setName("ETFourKeyAlias") .setKey(Arrays.asList( @@ -1480,6 +1480,17 @@ public class EdmTechProvider extends EdmProvider { .setReturnType( new ReturnType().setType(nameCTTwoPrim)) ); + } else if (functionName.equals(nameUFCRTCollCTTwoPrimParam)) { + return Arrays.asList( + new Function() + .setName("UFCRTCollCTTwoPrimParam") + .setParameters(Arrays.asList( + new Parameter().setName("ParameterString").setType(nameString), + new Parameter().setName("ParameterInt16").setType(nameInt16))) + .setComposable(true) + .setReturnType( + new ReturnType().setType(nameCTTwoPrim).setCollection(true)) + ); } else if (functionName.equals(nameUFCRTCTTwoPrim)) { return Arrays.asList( diff --git a/odata4-lib/odata4-producer-core/src/test/java/org/apache/olingo/odata4/producer/core/testutil/FilterValidator.java b/odata4-lib/odata4-producer-core/src/test/java/org/apache/olingo/odata4/producer/core/testutil/FilterValidator.java index 642559bcf..e4919e7e4 100644 --- a/odata4-lib/odata4-producer-core/src/test/java/org/apache/olingo/odata4/producer/core/testutil/FilterValidator.java +++ b/odata4-lib/odata4-producer-core/src/test/java/org/apache/olingo/odata4/producer/core/testutil/FilterValidator.java @@ -82,6 +82,7 @@ public class FilterValidator implements Validator { if (filter.getExpression() == null) { fail("FilterValidator: no filter found"); } + setExpression(filter.getExpression()); return this; } @@ -363,7 +364,7 @@ public class FilterValidator implements Validator { return this; } - public FilterValidator isMemberExpression() { + public FilterValidator isMember() { if (!(curExpression instanceof MemberImpl)) { fail("Current expression not a member"); } diff --git a/odata4-lib/odata4-producer-core/src/test/java/org/apache/olingo/odata4/producer/core/testutil/UriResourceValidator.java b/odata4-lib/odata4-producer-core/src/test/java/org/apache/olingo/odata4/producer/core/testutil/UriResourceValidator.java index 1993394eb..30cb6a73a 100644 --- a/odata4-lib/odata4-producer-core/src/test/java/org/apache/olingo/odata4/producer/core/testutil/UriResourceValidator.java +++ b/odata4-lib/odata4-producer-core/src/test/java/org/apache/olingo/odata4/producer/core/testutil/UriResourceValidator.java @@ -202,7 +202,8 @@ public class UriResourceValidator implements Validator { public UriResourceValidator isTypeFilter(final FullQualifiedName expectedType) { if (uriPathInfo.getKind() != UriResourceKind.complexProperty && - uriPathInfo.getKind() != UriResourceKind.singleton) { + uriPathInfo.getKind() != UriResourceKind.singleton && + uriPathInfo.getKind() != UriResourceKind.startingTypeFilter) { fail("invalid resource kind: " + uriPathInfo.getKind().toString()); } @@ -330,6 +331,19 @@ public class UriResourceValidator implements Validator { return this; } + + public UriResourceValidator isKeyPredicateRef(final int index, final String name, final String refencedProperty) { + if (!(uriPathInfo instanceof UriResourceImplKeyPred)) { + fail("invalid resource kind: " + uriPathInfo.getKind().toString()); + } + + UriResourceImplKeyPred info = (UriResourceImplKeyPred) uriPathInfo; + List keyPredicates = info.getKeyPredicates(); + assertEquals(name, keyPredicates.get(index).getName()); + assertEquals(refencedProperty, keyPredicates.get(index).getRefencedProperty()); + return this; + + } public UriResourceValidator isKeyPredicate(final int index, final String name, final String text) { if (!(uriPathInfo instanceof UriResourceImplKeyPred)) { fail("invalid resource kind: " + uriPathInfo.getKind().toString()); diff --git a/odata4-lib/odata4-producer-core/src/test/java/org/apache/olingo/odata4/producer/core/uri/UriParameterImplTest.java b/odata4-lib/odata4-producer-core/src/test/java/org/apache/olingo/odata4/producer/core/uri/UriParameterImplTest.java index b960f1ec7..53b3fc272 100644 --- a/odata4-lib/odata4-producer-core/src/test/java/org/apache/olingo/odata4/producer/core/uri/UriParameterImplTest.java +++ b/odata4-lib/odata4-producer-core/src/test/java/org/apache/olingo/odata4/producer/core/uri/UriParameterImplTest.java @@ -210,9 +210,7 @@ public class UriParameterImplTest { impl = new UriResourceFunctionImpl(); EdmFunctionImport functionImport = edm.getEntityContainer(null).getFunctionImport("FINRTInt16"); impl.setFunctionImport(functionImport, new ArrayList()); - assertEquals(functionImport, impl.getFunctionImport()); - assertEquals(functionImport.getFunction(new ArrayList()), impl.getFunction()); assertEquals("FINRTInt16", impl.toString()); // function collection @@ -221,8 +219,10 @@ public class UriParameterImplTest { assertNotNull(function); UriParameterImpl parameter = new UriParameterImpl().setName("ParameterInt16"); impl.setFunctionImport(functionImport, Arrays.asList(parameter)); - assertEquals("FICRTESTwoKeyNavParam", impl.toString()); + + + impl.setFunction(functionImport.getFunction(Arrays.asList("ParameterInt16"))); assertEquals(true, impl.isCollection()); impl.setKeyPredicates(new ArrayList()); assertEquals(false, impl.isCollection()); diff --git a/odata4-lib/odata4-producer-core/src/test/java/org/apache/olingo/odata4/producer/core/uri/antlr/TestFullResourcePath.java b/odata4-lib/odata4-producer-core/src/test/java/org/apache/olingo/odata4/producer/core/uri/antlr/TestFullResourcePath.java index 1af58fa1b..3621a697e 100644 --- a/odata4-lib/odata4-producer-core/src/test/java/org/apache/olingo/odata4/producer/core/uri/antlr/TestFullResourcePath.java +++ b/odata4-lib/odata4-producer-core/src/test/java/org/apache/olingo/odata4/producer/core/uri/antlr/TestFullResourcePath.java @@ -53,18 +53,14 @@ public class TestFullResourcePath { @Test public void test() { - /* - * testUri.run("ESTwoKeyNav?" - * + "$expand=com.sap.odata.test1.ETBaseTwoKeyNav/NavPropertyETKeyNavMany") - * .isKind(UriInfoKind.resource).goPath().first() - * .goExpand().first() - * .goPath().first() - * .isUriPathInfoKind(UriResourceKind.it) - * .isType(EdmTechProvider.nameETTwoKeyNav) - * .isTypeFilterOnCollection(EdmTechProvider.nameETBaseTwoKeyNav) - * .n() - * .isNavProperty("NavPropertyETKeyNavMany"); - */ + testUri.run("ESTwoKeyNav/com.sap.odata.test1.BFCESTwoKeyNavRTESTwoKeyNav(ParameterString='ABC')").goPath() + .at(0) + .isUriPathInfoKind(UriResourceKind.entitySet) + .isType(EdmTechProvider.nameETTwoKeyNav) + .isCollection(true) + .at(1) + .isUriPathInfoKind(UriResourceKind.function) + .isType(EdmTechProvider.nameETTwoKeyNav); } @Test @@ -100,8 +96,6 @@ public class TestFullResourcePath { .isType(EdmTechProvider.nameETTwoKeyNav); } - - //DONE @Test @@ -1530,13 +1524,28 @@ public class TestFullResourcePath { .isKeyPredicate(1, "PropertyString", "'5'") .n() .isNavProperty("NavPropertyETKeyNavMany", EdmTechProvider.nameETKeyNav, true); - } @Test public void runEsNamePpNpRc() { - // testUri.run("ESKeyNav(1)/NavPropertyETTwoKeyNavMany('2')"); - // testUri.run("ESKeyNav(PropertyInt16=1)/NavPropertyETTwoKeyNavMany(PropertyString='2')"); + // checks for using referential constrains to fill missing keys + testUri.run("ESKeyNav(1)/NavPropertyETTwoKeyNavMany('2')").goPath() + .first() + .isEntitySet("ESKeyNav") + .isKeyPredicate(0, "PropertyInt16", "1") + .n() + .isNavProperty("NavPropertyETTwoKeyNavMany", EdmTechProvider.nameETTwoKeyNav, false) + .isKeyPredicateRef(0, "PropertyInt16", "PropertyInt16") + .isKeyPredicate(1, "PropertyString", "'2'"); + + testUri.run("ESKeyNav(PropertyInt16=1)/NavPropertyETTwoKeyNavMany(PropertyString='2')").goPath() + .first() + .isEntitySet("ESKeyNav") + .isKeyPredicate(0, "PropertyInt16", "1") + .n() + .isNavProperty("NavPropertyETTwoKeyNavMany", EdmTechProvider.nameETTwoKeyNav, false) + .isKeyPredicateRef(0, "PropertyInt16", "PropertyInt16") + .isKeyPredicate(1, "PropertyString", "'2'"); } @@ -2499,7 +2508,6 @@ public class TestFullResourcePath { .isFormatText("Test_all_valid_signsSpecified_for_format_signs%26-._~$@%27/Aa123%26-._~$@%27"); } - @Test public void runCount() { // count @@ -2755,72 +2763,82 @@ public class TestFullResourcePath { } @Test - public void TestFilter() throws UriParserException { - /* - * testFilter.runOnETTwoKeyNav("PropertyString") - * .is("<$it/PropertyString>") - * .isType(EdmTechProvider.nameString); - * - * testFilter.runOnETTwoKeyNav("PropertyComplex/PropertyInt16") - * .is("<$it/PropertyComplex/PropertyInt16>") - * .isType(EdmTechProvider.nameInt16); - * - * testFilter.runOnETTwoKeyNav("PropertyComplex/PropertyComplex/PropertyDate") - * .is("<$it/PropertyComplex/PropertyComplex/PropertyDate>") - * .isType(EdmTechProvider.nameDate); - * - * testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne") - * .is("<$it/NavPropertyETTwoKeyNavOne>") - * .isType(EdmTechProvider.nameETTwoKeyNav); - * - * testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne/PropertyString") - * .is("<$it/NavPropertyETTwoKeyNavOne/PropertyString>") - * .isType(EdmTechProvider.nameString); - * - * testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne/PropertyComplex") - * .is("<$it/NavPropertyETTwoKeyNavOne/PropertyComplex>") - * .isType(EdmTechProvider.nameCTPrimComp); - * - * testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne/PropertyComplex/PropertyComplex") - * .is("<$it/NavPropertyETTwoKeyNavOne/PropertyComplex/PropertyComplex>") - * .isType(EdmTechProvider.nameCTAllPrim); - * - * testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne/PropertyComplex/PropertyInt16") - * .is("<$it/NavPropertyETTwoKeyNavOne/PropertyComplex/PropertyInt16>") - * .isType(EdmTechProvider.nameInt16); - * - * testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne/PropertyComplex/PropertyInt16 eq 1") - * .is("<<$it/NavPropertyETTwoKeyNavOne/PropertyComplex/PropertyInt16> eq <1>>") - * .root().left() - * .isType(EdmTechProvider.nameInt16) - * .root().right() - * .isLiteral("1"); - * - * // testFilter - * // .runOnETTwoKeyNav( - * // "NavPropertyETKeyNavMany(1)/NavPropertyETTwoKeyNavMany(PropertyString='2')/PropertyString eq 'SomeString'"); - * testFilter.runOnETTwoKeyNav("com.sap.odata.test1.ETBaseTwoKeyNav/PropertyDate eq 2013-11-12") - * .is("<<$it/com.sap.odata.test1.ETBaseTwoKeyNav/PropertyDate> eq <2013-11-12>>") - * .root().left() - * .isType(EdmTechProvider.nameDate) - * .root().right() - * .isLiteral("2013-11-12"); - * - * testFilter.runOnCTTwoPrim("com.sap.odata.test1.CTBase/AdditionalPropString eq 'SomeString'") - * .is("<<$it/com.sap.odata.test1.CTBase/AdditionalPropString> eq <'SomeString'>>") - * .root().left() - * .isType(EdmTechProvider.nameString) - * .root().right() - * .isLiteral("'SomeString'"); - * - * testFilter - * .runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne/com.sap.odata.test1.ETBaseTwoKeyNav/PropertyDate eq 2013-11-12") - * .is("<<$it/NavPropertyETTwoKeyNavOne/com.sap.odata.test1.ETBaseTwoKeyNav/PropertyDate> eq <2013-11-12>>") - * .root().left() - * .isType(EdmTechProvider.nameDate) - * .root().right() - * .isLiteral("2013-11-12"); - */ + public void testFilter() throws UriParserException { + + testFilter.runOnETTwoKeyNav("PropertyString") + .is("") + .isType(EdmTechProvider.nameString); + + testFilter.runOnETTwoKeyNav("PropertyComplex/PropertyInt16") + .is("") + .isType(EdmTechProvider.nameInt16); + + testFilter.runOnETTwoKeyNav("PropertyComplex/PropertyComplex/PropertyDate") + .is("") + .isType(EdmTechProvider.nameDate); + + testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne") + .is("") + .isType(EdmTechProvider.nameETTwoKeyNav); + + testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne/PropertyString") + .is("") + .isType(EdmTechProvider.nameString); + + testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne/PropertyComplex") + .is("") + .isType(EdmTechProvider.nameCTPrimComp); + + testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne/PropertyComplex/PropertyComplex") + .is("") + .isType(EdmTechProvider.nameCTAllPrim); + + testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne/PropertyComplex/PropertyInt16") + .is("") + .isType(EdmTechProvider.nameInt16); + + testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne/PropertyComplex/PropertyInt16 eq 1") + .is("< eq <1>>") + .root().left() + .isType(EdmTechProvider.nameInt16) + .root().right() + .isLiteral("1"); + + // testFilter + // .runOnETTwoKeyNav( + // "NavPropertyETKeyNavMany(1)/NavPropertyETTwoKeyNavMany(PropertyString='2')/PropertyString eq 'SomeString'"); + testFilter.runOnETTwoKeyNav("com.sap.odata.test1.ETBaseTwoKeyNav/PropertyDate eq 2013-11-12") + .is("< eq <2013-11-12>>") + .root().left() + .isType(EdmTechProvider.nameDate) + .isMember().goPath() + .first().isUriPathInfoKind(UriResourceKind.startingTypeFilter) + .isType(EdmTechTestProvider.nameETTwoKeyNav).isTypeFilterOnEntry(EdmTechTestProvider.nameETBaseTwoKeyNav) + .n().isPrimitiveProperty("PropertyDate", EdmTechTestProvider.nameDate, false) + .goUpFilterValidator() + .root().right() + .isLiteral("2013-11-12"); + + testFilter.runOnCTTwoPrim("com.sap.odata.test1.CTBase/AdditionalPropString eq 'SomeString'") + .is("< eq <'SomeString'>>") + .root().left() + .isType(EdmTechProvider.nameString) + .isMember().goPath() + .first().isUriPathInfoKind(UriResourceKind.startingTypeFilter) + .isType(EdmTechTestProvider.nameCTTwoPrim).isTypeFilterOnEntry(EdmTechTestProvider.nameCTBase) + .n().isPrimitiveProperty("AdditionalPropString", EdmTechTestProvider.nameString, false) + .goUpFilterValidator() + .root().right() + .isLiteral("'SomeString'"); + + testFilter + .runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne/com.sap.odata.test1.ETBaseTwoKeyNav/PropertyDate eq 2013-11-12") + .is("< eq <2013-11-12>>") + .root().left() + .isType(EdmTechProvider.nameDate) + .root().right() + .isLiteral("2013-11-12"); + testFilter .runOnETTwoKeyNav("PropertyComplexTwoPrim/com.sap.odata.test1.CTTwoBase/AdditionalPropString eq 'SomeString'") .is("< eq <'SomeString'>>") @@ -3208,7 +3226,7 @@ public class TestFullResourcePath { } @Test - public void TestFilterProperties() throws UriParserException { + public void testFilterProperties() throws UriParserException { // testFilter.runOnETAllPrim("XPropertyByte mod 0"); // testFilter.runOnETAllPrim("com.sap.odata.test1.UFCRTETTwoKeyNavParamCTTwoPrim(ParameterCTTwoPrim=@ParamAlias)"); @@ -3257,7 +3275,7 @@ public class TestFullResourcePath { } @Test - public void TestFilterPMethods() throws ExceptionVisitExpression, ODataApplicationException, UriParserException { + public void testFilterPMethods() throws ExceptionVisitExpression, ODataApplicationException, UriParserException { testFilter.runOnETKeyNav("indexof(PropertyString,'47') eq 5") .is("<,<'47'>)> eq <5>>") @@ -4169,7 +4187,7 @@ public class TestFullResourcePath { } @Test - public void TestHas() throws ExceptionVisitExpression, ODataApplicationException, UriParserException { + public void testHas() throws ExceptionVisitExpression, ODataApplicationException, UriParserException { /* * testFilter.runOnETTwoKeyNav("PropertyEnumString has com.sap.odata.test1.ENString'String1'") * .is("< has >>") @@ -4360,7 +4378,7 @@ public class TestFullResourcePath { testFilter.runOnETAllPrim("PropertyByte eq 255") .is("< eq <255>>") .isBinary(SupportedBinaryOperators.EQ) - .root().left().goPath().isPrimitiveProperty("PropertyByte", + .root().left().goPath().isPrimitiveProperty("PropertyByte", EdmTechProvider.nameByte, false).goUpFilterValidator() .root().right().isLiteral("255"); @@ -4395,7 +4413,8 @@ public class TestFullResourcePath { testFilter.runOnETAllPrim("PropertyDateTimeOffset eq 2013-09-25T12:34:56.123456789012-10:24") .is("< eq <2013-09-25T12:34:56.123456789012-10:24>>") .isBinary(SupportedBinaryOperators.EQ) - .root().left().goPath().isPrimitiveProperty("PropertyDateTimeOffset", EdmTechProvider.nameDateTimeOffset, false) + .root().left().goPath() + .isPrimitiveProperty("PropertyDateTimeOffset", EdmTechProvider.nameDateTimeOffset, false) .goUpFilterValidator() .root().right().isLiteral("2013-09-25T12:34:56.123456789012-10:24"); @@ -4462,7 +4481,7 @@ public class TestFullResourcePath { } @Test - public void TestOrderby() throws UriParserException { + public void testOrderby() throws UriParserException { /* * testFilter.runOrderByOnETTwoKeyNav("com.sap.odata.test1.UFCRTETAllPrimTwoParam(" * + "ParameterString=@ParamStringAlias,ParameterInt16=@ParamInt16Alias)/PropertyString eq 'SomeString'") @@ -4784,6 +4803,7 @@ public class TestFullResourcePath { .isSortOrder(0, true) .goOrder(0).left().goPath().isComplex("PropertyEnumString").goUpFilterValidator() .goOrder(0).right().isEnum(EdmTechProvider.nameENString, Arrays.asList("String1")); + // XPropertyInt16 1 // XPropertyInt16, PropertyInt32 PropertyDuration // XPropertyInt16 PropertyInt32, PropertyDuration desc diff --git a/odata4-lib/odata4-producer-core/src/test/java/org/apache/olingo/odata4/producer/core/uri/antlr/TestLexer.java b/odata4-lib/odata4-producer-core/src/test/java/org/apache/olingo/odata4/producer/core/uri/antlr/TestLexer.java index 498945d95..720f5d689 100644 --- a/odata4-lib/odata4-producer-core/src/test/java/org/apache/olingo/odata4/producer/core/uri/antlr/TestLexer.java +++ b/odata4-lib/odata4-producer-core/src/test/java/org/apache/olingo/odata4/producer/core/uri/antlr/TestLexer.java @@ -46,7 +46,7 @@ public class TestLexer { //@Test public void test() { - //test.log(1).run("$metadata?$format=atom#asdfaf"); + //test.log(1).run("ESTwoKeyNav?$filter=CollPropertyComplex/all( l :true)"); } // ;------------------------------------------------------------------------------ diff --git a/odata4-lib/odata4-producer-core/src/test/java/org/apache/olingo/odata4/producer/core/uri/antlr/TestParser.java b/odata4-lib/odata4-producer-core/src/test/java/org/apache/olingo/odata4/producer/core/uri/antlr/TestParser.java index e8046485e..536bc4e02 100644 --- a/odata4-lib/odata4-producer-core/src/test/java/org/apache/olingo/odata4/producer/core/uri/antlr/TestParser.java +++ b/odata4-lib/odata4-producer-core/src/test/java/org/apache/olingo/odata4/producer/core/uri/antlr/TestParser.java @@ -1365,28 +1365,5 @@ public class TestParser { + "searchExpr(searchWord(abc)))))))))) )"); } - // ;------------------------------------------------------------------------------ - // ; 2. Query Options - // ;------------------------------------------------------------------------------ - - // ;------------------------------------------------------------------------------ - // ; 4. Expressions - // ;------------------------------------------------------------------------------ - - // ;------------------------------------------------------------------------------ - // ; 5. JSON format for function parameters - // ;------------------------------------------------------------------------------ - - // ;------------------------------------------------------------------------------ - // ; 6. Names and identifiers - // ;------------------------------------------------------------------------------ - - // ;------------------------------------------------------------------------------ - // ; 7. Literal Data Values - // ;------------------------------------------------------------------------------ - - // ;------------------------------------------------------------------------------ - // ; 0. misc - // ;------------------------------------------------------------------------------ } diff --git a/odata4-lib/odata4-producer-core/src/test/java/org/apache/olingo/odata4/producer/core/uri/antlr/TestUriParserImpl.java b/odata4-lib/odata4-producer-core/src/test/java/org/apache/olingo/odata4/producer/core/uri/antlr/TestUriParserImpl.java index 6a3176e44..f093e9a40 100644 --- a/odata4-lib/odata4-producer-core/src/test/java/org/apache/olingo/odata4/producer/core/uri/antlr/TestUriParserImpl.java +++ b/odata4-lib/odata4-producer-core/src/test/java/org/apache/olingo/odata4/producer/core/uri/antlr/TestUriParserImpl.java @@ -994,4 +994,72 @@ public class TestUriParserImpl { testUri.run("ESAllPrim(1)/PropertyString/$value"); } + @Test + public void testMemberStartingWithCast() { + // on EntityType entry + // TODO inform OTTO + testUri.run("ESTwoKeyNav(ParameterInt16=1,PropertyString='ABC')?" + + "$filter=com.sap.odata.test1.ETBaseTwoKeyNav/PropertyDate") + .goFilter().root().isMember().goPath() + .at(0) + .isUriPathInfoKind(UriResourceKind.startingTypeFilter) + .isType(EdmTechTestProvider.nameETTwoKeyNav, false) + .isTypeFilterOnEntry(EdmTechTestProvider.nameETBaseTwoKeyNav) + .at(1).isType(EdmTechTestProvider.nameDate); + + // on EntityType collection + testUri.run("ESTwoKeyNav?$filter=com.sap.odata.test1.ETBaseTwoKeyNav/PropertyDate") + .goFilter().root().isMember().goPath() + .at(0) + .isUriPathInfoKind(UriResourceKind.startingTypeFilter) + .isType(EdmTechTestProvider.nameETTwoKeyNav, true) + .isTypeFilterOnCollection(EdmTechTestProvider.nameETBaseTwoKeyNav) + .at(1).isType(EdmTechTestProvider.nameDate); + + testUri.run("FICRTCTTwoPrimParam(ParameterInt16=1,ParameterString='2')?" + + "$filter=com.sap.odata.test1.CTBase/AdditionalPropString") + .goFilter().root().isMember().goPath() + .at(0) + .isUriPathInfoKind(UriResourceKind.startingTypeFilter) + .isType(EdmTechTestProvider.nameCTTwoPrim, false) + .isTypeFilterOnEntry(EdmTechTestProvider.nameCTBase) + .at(1).isType(EdmTechTestProvider.nameString); + +// on Complex collection + testUri.run("FICRTCollCTTwoPrimParam(ParameterInt16=1,ParameterString='2')?" + + "$filter=com.sap.odata.test1.CTBase/AdditionalPropString") + .goFilter().root().isMember().goPath() + .at(0) + .isUriPathInfoKind(UriResourceKind.startingTypeFilter) + .isType(EdmTechTestProvider.nameCTTwoPrim, true) + .isTypeFilterOnCollection(EdmTechTestProvider.nameCTBase) + .at(1).isType(EdmTechTestProvider.nameString); + + } + + @Test + public void testComplexTypeCastFollowingAsCollection() { + // TODO inform OTTO + testUri.run("FICRTCollCTTwoPrimParam(ParameterInt16=1,ParameterString='2')/com.sap.odata.test1.CTBase"); + + } + + @Test + public void testLambda() { + testUri.run("ESTwoKeyNav?$filter=CollPropertyComplex/all( l : true )") + .goFilter().is(">>"); + + testUri.run("ESTwoKeyNav?$filter=CollPropertyComplex/any( l : true )") + .goFilter().is(">>"); + testUri.run("ESTwoKeyNav?$filter=CollPropertyComplex/any( )") + .goFilter().is(">"); + + testUri.run("ESTwoKeyNav?$filter=all( l : true )") + .goFilter().is("<>>"); + testUri.run("ESTwoKeyNav?$filter=any( l : true )") + .goFilter().is("<>>"); + testUri.run("ESTwoKeyNav?$filter=any( )") + .goFilter().is("<>"); + } + }