http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/72fcaa1a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java ---------------------------------------------------------------------- diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java new file mode 100644 index 0000000..c267754 --- /dev/null +++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java @@ -0,0 +1,2389 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.olingo.server.core.uri.parser; + +import java.util.Arrays; +import java.util.Collections; + +import org.apache.olingo.commons.api.edm.Edm; +import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind; +import org.apache.olingo.commons.api.edmx.EdmxReference; +import org.apache.olingo.server.api.OData; +import org.apache.olingo.server.api.uri.UriResourceKind; +import org.apache.olingo.server.api.uri.queryoption.expression.BinaryOperatorKind; +import org.apache.olingo.server.api.uri.queryoption.expression.MethodKind; +import org.apache.olingo.server.core.uri.parser.UriParserSemanticException.MessageKeys; +import org.apache.olingo.server.core.uri.testutil.FilterValidator; +import org.apache.olingo.server.core.uri.validator.UriValidationException; +import org.apache.olingo.server.tecsvc.provider.ComplexTypeProvider; +import org.apache.olingo.server.tecsvc.provider.EdmTechProvider; +import org.apache.olingo.server.tecsvc.provider.EntityTypeProvider; +import org.apache.olingo.server.tecsvc.provider.EnumTypeProvider; +import org.apache.olingo.server.tecsvc.provider.PropertyProvider; +import org.apache.olingo.server.tecsvc.provider.TypeDefinitionProvider; +import org.junit.Test; + +/** Tests of the parts of the URI parser that parse the sytem query options $filter and $orderby. */ +public class ExpressionParserTest { + + private static final OData oData = OData.newInstance(); + private static final Edm edm = oData.createServiceMetadata( + new EdmTechProvider(), Collections.<EdmxReference> emptyList()).getEdm(); + + private final FilterValidator testFilter = new FilterValidator().setEdm(edm); + + @Test + public void filter() throws Exception { + testFilter.runOnETAllPrim("PropertyBoolean") + .is("<PropertyBoolean>") + .isType(PropertyProvider.nameBoolean); + + testFilter.runOnETTwoKeyNav("PropertyComp/PropertyInt16 gt 0") + .is("<<PropertyComp/PropertyInt16> gt <0>>") + .left().isType(PropertyProvider.nameInt16); + + testFilter.runOnETTwoKeyNav("PropertyComp/PropertyComp/PropertyDate ne null") + .is("<<PropertyComp/PropertyComp/PropertyDate> ne <null>>") + .left().isType(PropertyProvider.nameDate); + + testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne eq null") + .is("<<NavPropertyETTwoKeyNavOne> eq <null>>") + .left().isType(EntityTypeProvider.nameETTwoKeyNav); + + testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne/PropertyString eq ''") + .is("<<NavPropertyETTwoKeyNavOne/PropertyString> eq <''>>") + .left().isType(PropertyProvider.nameString); + + testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne/PropertyComp eq null") + .is("<<NavPropertyETTwoKeyNavOne/PropertyComp> eq <null>>") + .left().isType(ComplexTypeProvider.nameCTPrimComp); + + testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne/PropertyComp/PropertyComp eq null") + .is("<<NavPropertyETTwoKeyNavOne/PropertyComp/PropertyComp> eq <null>>") + .left().isType(ComplexTypeProvider.nameCTAllPrim); + + testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne/PropertyComp/PropertyInt16 eq 1") + .is("<<NavPropertyETTwoKeyNavOne/PropertyComp/PropertyInt16> eq <1>>") + .left().isType(PropertyProvider.nameInt16) + .root().right().isLiteral("1"); + + testFilter.runOnETTwoKeyNav("NavPropertyETKeyNavMany(1)/NavPropertyETTwoKeyNavMany(PropertyString='2')/" + + "PropertyString eq 'SomeString'") + .is("<<NavPropertyETKeyNavMany/NavPropertyETTwoKeyNavMany/PropertyString> eq <'SomeString'>>") + .left() + .isType(PropertyProvider.nameString) + .isMember().goPath() + .first() + .isNavProperty("NavPropertyETKeyNavMany", EntityTypeProvider.nameETKeyNav, false) + .isKeyPredicate(0, "PropertyInt16", "1") + .n() + .isNavProperty("NavPropertyETTwoKeyNavMany", EntityTypeProvider.nameETTwoKeyNav, false) + .isKeyPredicateRef(0, "PropertyInt16", "PropertyInt16") + .isKeyPredicate(1, "PropertyString", "'2'") + .n() + .isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false) + .goUpFilterValidator() + .root().right(); + + testFilter.runOnETTwoKeyNav("olingo.odata.test1.ETBaseTwoKeyNav/PropertyDate eq 2013-11-12") + .is("<<PropertyDate> eq <2013-11-12>>") + .left() + .isType(PropertyProvider.nameDate) + .isMember().isMemberStartType(EntityTypeProvider.nameETBaseTwoKeyNav).goPath() + .first().isPrimitiveProperty("PropertyDate", PropertyProvider.nameDate, false) + .goUpFilterValidator() + .root().right() + .isLiteral("2013-11-12"); + + testFilter.runOnCTTwoPrim("olingo.odata.test1.CTBase/AdditionalPropString eq 'SomeString'") + .is("<<AdditionalPropString> eq <'SomeString'>>") + .left() + .isType(PropertyProvider.nameString) + .isMember().isMemberStartType(ComplexTypeProvider.nameCTBase).goPath() + .first().isPrimitiveProperty("AdditionalPropString", PropertyProvider.nameString, false) + .goUpFilterValidator() + .root().right() + .isLiteral("'SomeString'"); + + testFilter + .runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne/olingo.odata.test1.ETBaseTwoKeyNav/PropertyDate eq 2013-11-12") + .is("<<NavPropertyETTwoKeyNavOne/olingo.odata.test1.ETBaseTwoKeyNav/PropertyDate> eq <2013-11-12>>") + .left() + .isType(PropertyProvider.nameDate) + .root().right() + .isLiteral("2013-11-12"); + + testFilter + .runOnETTwoKeyNav("PropertyCompTwoPrim/olingo.odata.test1.CTTwoBase/AdditionalPropString eq 'SomeString'") + .is("<<PropertyCompTwoPrim/olingo.odata.test1.CTTwoBase/AdditionalPropString> eq <'SomeString'>>") + .left() + .isType(PropertyProvider.nameString) + .root().right() + .isLiteral("'SomeString'"); + + testFilter.runOnETTwoKeyNavEx("invalid").isExSemantic(MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE); + testFilter.runOnETTwoKeyNavEx("PropertyComp").isExSemantic(MessageKeys.TYPES_NOT_COMPATIBLE); + testFilter.runOnETTwoKeyNavEx("PropertyComp/invalid").isExSemantic(MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE); + testFilter.runOnETTwoKeyNavEx("CollPropertyComp/") + .isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX); + testFilter.runOnETTwoKeyNavEx("concat('a','b')/invalid").isExSemantic(MessageKeys.TYPES_NOT_COMPATIBLE); + testFilter.runOnETTwoKeyNavEx("PropertyComp/concat('a','b')") + .isExSemantic(MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE); + testFilter.runOnETTwoKeyNavEx("PropertyComp/PropertyInt16 eq '1'") + .isExSemantic(MessageKeys.TYPES_NOT_COMPATIBLE); + testFilter.runOnETTwoKeyNavEx("PropertyComp/PropertyComp/PropertyDate eq 1") + .isExSemantic(MessageKeys.TYPES_NOT_COMPATIBLE); + testFilter.runOnETTwoKeyNavEx("PropertyComp/PropertyComp/PropertyString eq 1") + .isExSemantic(MessageKeys.TYPES_NOT_COMPATIBLE); + testFilter.runOnETTwoKeyNavEx("PropertyComp/PropertyInt64 eq 1") + .isExSemantic(MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE); + testFilter.runOnETTwoKeyNavEx("NavPropertyETKeyNavMany/PropertyInt16 gt 42") + .isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX); + testFilter.runOnETTwoKeyNavEx("NavPropertyETKeyNavMany/NavPropertyETTwoKeyNavOne eq null") + .isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX); + testFilter.runOnETTwoKeyNavEx("NavPropertyETKeyNavMany ne null").isExSemantic(MessageKeys.COLLECTION_NOT_ALLOWED); + testFilter.runOnETTwoKeyNavEx("CollPropertyString eq 'SomeString'") + .isExSemantic(MessageKeys.COLLECTION_NOT_ALLOWED); + testFilter.runOnETTwoKeyNavEx("NavPropertyETKeyNavMany").isExSemantic(MessageKeys.COLLECTION_NOT_ALLOWED); + testFilter.runOnETTwoKeyNavEx("olingo.odata.test1.ETBaseTwoKeyNav/PropertyDate") + .isExSemantic(MessageKeys.TYPES_NOT_COMPATIBLE); + testFilter.runUriEx("FICRTCTTwoPrimTwoParam(ParameterInt16=1,ParameterString='2')", + "$filter=olingo.odata.test1.CTBase/AdditionalPropString") + .isExSemantic(MessageKeys.TYPES_NOT_COMPATIBLE); + } + + @Test + public void filterUnaryOperators() throws Exception { + testFilter.runOnETAllPrim("not PropertyBoolean").is("<not <PropertyBoolean>>"); + testFilter.runOnETAllPrim("-PropertyInt16 eq PropertyInt16").is("<<- <PropertyInt16>> eq <PropertyInt16>>"); + } + + @Test + public void filterBinaryOperators() throws Exception { + testFilter.runOnETAllPrim("PropertySByte eq PropertySByte") + .is("<<PropertySByte> eq <PropertySByte>>") + .isBinary(BinaryOperatorKind.EQ) + .left().isType(PropertyProvider.nameSByte) + .root().right().isType(PropertyProvider.nameSByte); + + testFilter.runOnETAllPrim("PropertySByte ne PropertySByte") + .is("<<PropertySByte> ne <PropertySByte>>") + .isBinary(BinaryOperatorKind.NE) + .left().isType(PropertyProvider.nameSByte) + .root().right().isType(PropertyProvider.nameSByte); + + testFilter.runOnETAllPrim("PropertySByte add PropertySByte gt 0") + .is("<<<PropertySByte> add <PropertySByte>> gt <0>>") + .left().left().isType(PropertyProvider.nameSByte) + .root().left().right().isType(PropertyProvider.nameSByte); + + testFilter.runOnETAllPrim("PropertyByte add PropertyByte gt 0") + .is("<<<PropertyByte> add <PropertyByte>> gt <0>>") + .left().left().isType(PropertyProvider.nameByte) + .root().left().right().isType(PropertyProvider.nameByte); + testFilter.runOnETAllPrim("PropertyInt16 add PropertyInt16 gt 0") + .is("<<<PropertyInt16> add <PropertyInt16>> gt <0>>") + .left().left().isType(PropertyProvider.nameInt16) + .root().left().right().isType(PropertyProvider.nameInt16); + testFilter.runOnETAllPrim("PropertyInt32 add PropertyInt32 gt 0") + .is("<<<PropertyInt32> add <PropertyInt32>> gt <0>>") + .left().left().isType(PropertyProvider.nameInt32) + .root().left().right().isType(PropertyProvider.nameInt32); + testFilter.runOnETAllPrim("PropertyInt64 add PropertyInt64 gt 0") + .is("<<<PropertyInt64> add <PropertyInt64>> gt <0>>") + .left().left().isType(PropertyProvider.nameInt64) + .root().left().right().isType(PropertyProvider.nameInt64); + testFilter.runOnETAllPrim("PropertySingle add PropertySingle gt 0") + .is("<<<PropertySingle> add <PropertySingle>> gt <0>>") + .left().left().isType(PropertyProvider.nameSingle) + .root().left().right().isType(PropertyProvider.nameSingle); + testFilter.runOnETAllPrim("PropertyDouble add PropertyDouble gt 0") + .is("<<<PropertyDouble> add <PropertyDouble>> gt <0>>") + .left().left().isType(PropertyProvider.nameDouble) + .root().left().right().isType(PropertyProvider.nameDouble); + testFilter.runOnETAllPrim("PropertyDecimal add PropertyDecimal gt 0") + .is("<<<PropertyDecimal> add <PropertyDecimal>> gt <0>>") + .left().left().isType(PropertyProvider.nameDecimal) + .root().left().right().isType(PropertyProvider.nameDecimal); + testFilter.runOnETAllPrim("PropertySByte add PropertyDecimal gt 0") + .is("<<<PropertySByte> add <PropertyDecimal>> gt <0>>") + .left().left().isType(PropertyProvider.nameSByte) + .root().left().right().isType(PropertyProvider.nameDecimal); + testFilter.runOnETAllPrim("PropertySByte add PropertyInt32 gt 0") + .is("<<<PropertySByte> add <PropertyInt32>> gt <0>>") + .left().left().isType(PropertyProvider.nameSByte) + .root().left().right().isType(PropertyProvider.nameInt32); + testFilter.runOnETAllPrim("PropertySByte add PropertyInt64 gt 0") + .is("<<<PropertySByte> add <PropertyInt64>> gt <0>>") + .left().left().isType(PropertyProvider.nameSByte) + .root().left().right().isType(PropertyProvider.nameInt64); + testFilter.runOnETAllPrim("PropertyDateTimeOffset add PropertyDuration ne null") + .is("<<<PropertyDateTimeOffset> add <PropertyDuration>> ne <null>>") + .left().left().isType(PropertyProvider.nameDateTimeOffset) + .root().left().right().isType(PropertyProvider.nameDuration); + testFilter.runOnETAllPrim("PropertyDuration add PropertyDuration ne null") + .is("<<<PropertyDuration> add <PropertyDuration>> ne <null>>") + .left().left().isType(PropertyProvider.nameDuration) + .root().left().right().isType(PropertyProvider.nameDuration); + testFilter.runOnETAllPrim("PropertyDate add PropertyDuration ne null") + .is("<<<PropertyDate> add <PropertyDuration>> ne <null>>") + .left().left().isType(PropertyProvider.nameDate) + .root().left().right().isType(PropertyProvider.nameDuration); + testFilter.runOnETAllPrim("PropertySByte sub PropertySByte gt 0") + .is("<<<PropertySByte> sub <PropertySByte>> gt <0>>") + .left().left().isType(PropertyProvider.nameSByte) + .root().left().right().isType(PropertyProvider.nameSByte); + testFilter.runOnETAllPrim("PropertyByte sub PropertyByte gt 0") + .is("<<<PropertyByte> sub <PropertyByte>> gt <0>>") + .left().left().isType(PropertyProvider.nameByte) + .root().left().right().isType(PropertyProvider.nameByte); + testFilter.runOnETAllPrim("PropertyInt16 sub PropertyInt16 gt 0") + .is("<<<PropertyInt16> sub <PropertyInt16>> gt <0>>") + .left().left().isType(PropertyProvider.nameInt16) + .root().left().right().isType(PropertyProvider.nameInt16); + testFilter.runOnETAllPrim("PropertyInt32 sub PropertyInt32 gt 0") + .is("<<<PropertyInt32> sub <PropertyInt32>> gt <0>>") + .left().left().isType(PropertyProvider.nameInt32) + .root().left().right().isType(PropertyProvider.nameInt32); + testFilter.runOnETAllPrim("PropertyInt64 sub PropertyInt64 gt 0") + .is("<<<PropertyInt64> sub <PropertyInt64>> gt <0>>") + .left().left().isType(PropertyProvider.nameInt64) + .root().left().right().isType(PropertyProvider.nameInt64); + testFilter.runOnETAllPrim("PropertySingle sub PropertySingle gt 0") + .is("<<<PropertySingle> sub <PropertySingle>> gt <0>>") + .left().left().isType(PropertyProvider.nameSingle) + .root().left().right().isType(PropertyProvider.nameSingle); + testFilter.runOnETAllPrim("PropertyDouble sub PropertyDouble gt 0") + .is("<<<PropertyDouble> sub <PropertyDouble>> gt <0>>") + .left().left().isType(PropertyProvider.nameDouble) + .root().left().right().isType(PropertyProvider.nameDouble); + testFilter.runOnETAllPrim("PropertyDecimal sub PropertyDecimal gt 0") + .is("<<<PropertyDecimal> sub <PropertyDecimal>> gt <0>>") + .left().left().isType(PropertyProvider.nameDecimal) + .root().left().right().isType(PropertyProvider.nameDecimal); + testFilter.runOnETAllPrim("PropertyDecimal sub PropertyInt32 gt 0") + .is("<<<PropertyDecimal> sub <PropertyInt32>> gt <0>>") + .left().left().isType(PropertyProvider.nameDecimal) + .root().left().right().isType(PropertyProvider.nameInt32); + testFilter.runOnETAllPrim("PropertyDecimal sub PropertyInt64 gt 0") + .is("<<<PropertyDecimal> sub <PropertyInt64>> gt <0>>") + .left().left().isType(PropertyProvider.nameDecimal) + .root().left().right().isType(PropertyProvider.nameInt64); + testFilter.runOnETAllPrim("PropertyDecimal sub PropertyByte gt 0") + .is("<<<PropertyDecimal> sub <PropertyByte>> gt <0>>") + .left().left().isType(PropertyProvider.nameDecimal) + .root().left().right().isType(PropertyProvider.nameByte); + testFilter.runOnETAllPrim("PropertyDateTimeOffset sub PropertyDuration ne null") + .is("<<<PropertyDateTimeOffset> sub <PropertyDuration>> ne <null>>") + .left().left().isType(PropertyProvider.nameDateTimeOffset) + .root().left().right().isType(PropertyProvider.nameDuration); + testFilter.runOnETAllPrim("PropertyDuration sub PropertyDuration ne null") + .is("<<<PropertyDuration> sub <PropertyDuration>> ne <null>>") + .left().left().isType(PropertyProvider.nameDuration) + .root().left().right().isType(PropertyProvider.nameDuration); + testFilter.runOnETAllPrim("PropertyDateTimeOffset sub PropertyDateTimeOffset ne null") + .is("<<<PropertyDateTimeOffset> sub <PropertyDateTimeOffset>> ne <null>>") + .left().left().isType(PropertyProvider.nameDateTimeOffset) + .root().left().right().isType(PropertyProvider.nameDateTimeOffset); + testFilter.runOnETAllPrim("PropertyDate sub PropertyDuration ne null") + .is("<<<PropertyDate> sub <PropertyDuration>> ne <null>>") + .left().left().isType(PropertyProvider.nameDate) + .root().left().right().isType(PropertyProvider.nameDuration); + testFilter.runOnETAllPrim("PropertyDate sub PropertyDate ne null") + .is("<<<PropertyDate> sub <PropertyDate>> ne <null>>") + .left().left().isType(PropertyProvider.nameDate) + .root().left().right().isType(PropertyProvider.nameDate); + testFilter.runOnETAllPrim("PropertySByte mul PropertySByte gt 0") + .is("<<<PropertySByte> mul <PropertySByte>> gt <0>>") + .left().left().isType(PropertyProvider.nameSByte) + .root().left().right().isType(PropertyProvider.nameSByte); + testFilter.runOnETAllPrim("PropertyByte mul PropertyByte gt 0") + .is("<<<PropertyByte> mul <PropertyByte>> gt <0>>") + .left().left().isType(PropertyProvider.nameByte) + .root().left().right().isType(PropertyProvider.nameByte); + testFilter.runOnETAllPrim("PropertyInt16 mul PropertyInt16 gt 0") + .is("<<<PropertyInt16> mul <PropertyInt16>> gt <0>>") + .left().left().isType(PropertyProvider.nameInt16) + .root().left().right().isType(PropertyProvider.nameInt16); + testFilter.runOnETAllPrim("PropertyInt32 mul PropertyInt32 gt 0") + .is("<<<PropertyInt32> mul <PropertyInt32>> gt <0>>") + .left().left().isType(PropertyProvider.nameInt32) + .root().left().right().isType(PropertyProvider.nameInt32); + testFilter.runOnETAllPrim("PropertyInt64 mul PropertyInt64 gt 0") + .is("<<<PropertyInt64> mul <PropertyInt64>> gt <0>>") + .left().left().isType(PropertyProvider.nameInt64) + .root().left().right().isType(PropertyProvider.nameInt64); + testFilter.runOnETAllPrim("PropertySingle mul PropertySingle gt 0") + .is("<<<PropertySingle> mul <PropertySingle>> gt <0>>") + .left().left().isType(PropertyProvider.nameSingle) + .root().left().right().isType(PropertyProvider.nameSingle); + testFilter.runOnETAllPrim("PropertyDouble mul PropertyDouble gt 0") + .is("<<<PropertyDouble> mul <PropertyDouble>> gt <0>>") + .left().left().isType(PropertyProvider.nameDouble) + .root().left().right().isType(PropertyProvider.nameDouble); + testFilter.runOnETAllPrim("PropertyDecimal mul PropertyDecimal gt 0") + .is("<<<PropertyDecimal> mul <PropertyDecimal>> gt <0>>") + .left().left().isType(PropertyProvider.nameDecimal) + .root().left().right().isType(PropertyProvider.nameDecimal); + testFilter.runOnETAllPrim("PropertyInt64 mul PropertyInt32 gt 0") + .is("<<<PropertyInt64> mul <PropertyInt32>> gt <0>>") + .left().left().isType(PropertyProvider.nameInt64) + .root().left().right().isType(PropertyProvider.nameInt32); + testFilter.runOnETAllPrim("PropertyInt64 mul PropertySByte gt 0") + .is("<<<PropertyInt64> mul <PropertySByte>> gt <0>>") + .left().left().isType(PropertyProvider.nameInt64) + .root().left().right().isType(PropertyProvider.nameSByte); + testFilter.runOnETAllPrim("PropertyInt64 mul PropertyDecimal gt 0") + .is("<<<PropertyInt64> mul <PropertyDecimal>> gt <0>>") + .left().left().isType(PropertyProvider.nameInt64) + .root().left().right().isType(PropertyProvider.nameDecimal); + testFilter.runOnETAllPrim("PropertySByte div PropertySByte gt 0") + .is("<<<PropertySByte> div <PropertySByte>> gt <0>>") + .left().left().isType(PropertyProvider.nameSByte) + .root().left().right().isType(PropertyProvider.nameSByte); + testFilter.runOnETAllPrim("PropertyByte div PropertyByte gt 0") + .is("<<<PropertyByte> div <PropertyByte>> gt <0>>") + .left().left().isType(PropertyProvider.nameByte) + .root().left().right().isType(PropertyProvider.nameByte); + testFilter.runOnETAllPrim("PropertyInt16 div PropertyInt16 gt 0") + .is("<<<PropertyInt16> div <PropertyInt16>> gt <0>>") + .left().left().isType(PropertyProvider.nameInt16) + .root().left().right().isType(PropertyProvider.nameInt16); + testFilter.runOnETAllPrim("PropertyInt32 div PropertyInt32 gt 0") + .is("<<<PropertyInt32> div <PropertyInt32>> gt <0>>") + .left().left().isType(PropertyProvider.nameInt32) + .root().left().right().isType(PropertyProvider.nameInt32); + testFilter.runOnETAllPrim("PropertyInt64 div PropertyInt64 gt 0") + .is("<<<PropertyInt64> div <PropertyInt64>> gt <0>>") + .left().left().isType(PropertyProvider.nameInt64) + .root().left().right().isType(PropertyProvider.nameInt64); + testFilter.runOnETAllPrim("PropertySingle div PropertySingle gt 0") + .is("<<<PropertySingle> div <PropertySingle>> gt <0>>") + .left().left().isType(PropertyProvider.nameSingle) + .root().left().right().isType(PropertyProvider.nameSingle); + testFilter.runOnETAllPrim("PropertyDouble div PropertyDouble gt 0") + .is("<<<PropertyDouble> div <PropertyDouble>> gt <0>>") + .left().left().isType(PropertyProvider.nameDouble) + .root().left().right().isType(PropertyProvider.nameDouble); + testFilter.runOnETAllPrim("PropertyDecimal div PropertyDecimal gt 0") + .is("<<<PropertyDecimal> div <PropertyDecimal>> gt <0>>") + .left().left().isType(PropertyProvider.nameDecimal) + .root().left().right().isType(PropertyProvider.nameDecimal); + testFilter.runOnETAllPrim("PropertyByte div PropertyInt32 gt 0") + .is("<<<PropertyByte> div <PropertyInt32>> gt <0>>") + .left().left().isType(PropertyProvider.nameByte) + .root().left().right().isType(PropertyProvider.nameInt32); + testFilter.runOnETAllPrim("PropertyByte div PropertyDecimal gt 0") + .is("<<<PropertyByte> div <PropertyDecimal>> gt <0>>") + .left().left().isType(PropertyProvider.nameByte) + .root().left().right().isType(PropertyProvider.nameDecimal); + testFilter.runOnETAllPrim("PropertyByte div PropertySByte gt 0") + .is("<<<PropertyByte> div <PropertySByte>> gt <0>>") + .left().left().isType(PropertyProvider.nameByte) + .root().left().right().isType(PropertyProvider.nameSByte); + + testFilter.runOnETAllPrim("PropertyByte div 0 gt 0") + .is("<<<PropertyByte> div <0>> gt <0>>"); + + testFilter.runOnETAllPrim("0 div 0 gt 0") + .is("<<<0> div <0>> gt <0>>"); + + testFilter.runOnETAllPrim("PropertySByte mod PropertySByte gt 0") + .is("<<<PropertySByte> mod <PropertySByte>> gt <0>>") + .left().left().isType(PropertyProvider.nameSByte) + .root().left().right().isType(PropertyProvider.nameSByte); + testFilter.runOnETAllPrim("PropertyByte mod PropertyByte gt 0") + .is("<<<PropertyByte> mod <PropertyByte>> gt <0>>") + .left().left().isType(PropertyProvider.nameByte) + .root().left().right().isType(PropertyProvider.nameByte); + testFilter.runOnETAllPrim("PropertyInt16 mod PropertyInt16 gt 0") + .is("<<<PropertyInt16> mod <PropertyInt16>> gt <0>>") + .left().left().isType(PropertyProvider.nameInt16) + .root().left().right().isType(PropertyProvider.nameInt16); + testFilter.runOnETAllPrim("PropertyInt32 mod PropertyInt32 gt 0") + .is("<<<PropertyInt32> mod <PropertyInt32>> gt <0>>") + .left().left().isType(PropertyProvider.nameInt32) + .root().left().right().isType(PropertyProvider.nameInt32); + testFilter.runOnETAllPrim("PropertyInt64 mod PropertyInt64 gt 0") + .is("<<<PropertyInt64> mod <PropertyInt64>> gt <0>>") + .left().left().isType(PropertyProvider.nameInt64) + .root().left().right().isType(PropertyProvider.nameInt64); + testFilter.runOnETAllPrim("PropertySingle mod PropertySingle gt 0") + .is("<<<PropertySingle> mod <PropertySingle>> gt <0>>") + .left().left().isType(PropertyProvider.nameSingle) + .root().left().right().isType(PropertyProvider.nameSingle); + testFilter.runOnETAllPrim("PropertyDouble mod PropertyDouble gt 0") + .is("<<<PropertyDouble> mod <PropertyDouble>> gt <0>>") + .left().left().isType(PropertyProvider.nameDouble) + .root().left().right().isType(PropertyProvider.nameDouble); + testFilter.runOnETAllPrim("PropertyDecimal mod PropertyDecimal gt 0") + .is("<<<PropertyDecimal> mod <PropertyDecimal>> gt <0>>") + .left().left().isType(PropertyProvider.nameDecimal) + .root().left().right().isType(PropertyProvider.nameDecimal); + + testFilter.runOnETAllPrim("PropertyDecimal ge PropertyDecimal") + .is("<<PropertyDecimal> ge <PropertyDecimal>>") + .isBinary(BinaryOperatorKind.GE) + .left().isType(PropertyProvider.nameDecimal) + .root().right().isType(PropertyProvider.nameDecimal); + testFilter.runOnETAllPrim("PropertyDecimal lt PropertyDecimal") + .is("<<PropertyDecimal> lt <PropertyDecimal>>") + .isBinary(BinaryOperatorKind.LT) + .left().isType(PropertyProvider.nameDecimal) + .root().right().isType(PropertyProvider.nameDecimal); + testFilter.runOnETAllPrim("PropertyDecimal le PropertyDecimal") + .is("<<PropertyDecimal> le <PropertyDecimal>>") + .isBinary(BinaryOperatorKind.LE) + .left().isType(PropertyProvider.nameDecimal) + .root().right().isType(PropertyProvider.nameDecimal); + + // Numeric promotion: Double is considered the widest type. + testFilter.runOnETAllPrim("PropertyDecimal ne NaN") + .right().isLiteral("NaN").isType(PropertyProvider.nameDouble); + testFilter.runOnETAllPrim("PropertyDecimal gt -INF") + .right().isLiteral("-INF").isType(PropertyProvider.nameDouble); + testFilter.runOnETAllPrim("PropertyDecimal lt INF") + .right().isLiteral("INF").isType(PropertyProvider.nameDouble); + + testFilter.runOnETAllPrim("PropertyInt16 gt null") + .left().isType(PropertyProvider.nameInt16); + + testFilter.runOnETKeyNavEx("binary'Yw==' gt null").isExSemantic(MessageKeys.TYPES_NOT_COMPATIBLE); + testFilter.runOnETKeyNavEx("NavPropertyETKeyNavOne gt null").isExSemantic(MessageKeys.TYPES_NOT_COMPATIBLE); + testFilter.runOnETKeyNavEx("NavPropertyETKeyNavMany gt null").isExSemantic(MessageKeys.COLLECTION_NOT_ALLOWED); + } + + @Test + public void filterProperties() throws Exception { + testFilter.runOnETAllPrim("PropertyBoolean eq true") + .is("<<PropertyBoolean> eq <true>>") + .isBinary(BinaryOperatorKind.EQ) + .root().left().goPath().isPrimitiveProperty("PropertyBoolean", PropertyProvider.nameBoolean, false) + .goUpFilterValidator() + .root().right().isLiteral("true"); + + testFilter.runOnETAllPrim("PropertyDecimal eq 1.25") + .is("<<PropertyDecimal> eq <1.25>>") + .isBinary(BinaryOperatorKind.EQ) + .root().left().goPath().isPrimitiveProperty("PropertyDecimal", PropertyProvider.nameDecimal, false) + .goUpFilterValidator() + .root().right().isLiteral("1.25"); + + testFilter.runOnETAllPrim("PropertyDouble eq 1.5") + .is("<<PropertyDouble> eq <1.5>>") + .isBinary(BinaryOperatorKind.EQ) + .root().left().goPath().isPrimitiveProperty("PropertyDouble", PropertyProvider.nameDouble, false) + .goUpFilterValidator() + .root().right().isLiteral("1.5"); + + testFilter.runOnETAllPrim("PropertySingle eq 1.5") + .is("<<PropertySingle> eq <1.5>>") + .isBinary(BinaryOperatorKind.EQ) + .root().left().goPath().isPrimitiveProperty("PropertySingle", PropertyProvider.nameSingle, false) + .goUpFilterValidator() + .root().right().isLiteral("1.5"); + + testFilter.runOnETAllPrim("PropertySByte eq -128") + .is("<<PropertySByte> eq <-128>>") + .isBinary(BinaryOperatorKind.EQ) + .root().left().goPath().isPrimitiveProperty("PropertySByte", PropertyProvider.nameSByte, false) + .goUpFilterValidator() + .root().right().isLiteral("-128"); + + testFilter.runOnETAllPrim("PropertyByte eq 255") + .is("<<PropertyByte> eq <255>>") + .isBinary(BinaryOperatorKind.EQ) + .root().left().goPath().isPrimitiveProperty("PropertyByte", PropertyProvider.nameByte, false) + .goUpFilterValidator() + .root().right().isLiteral("255"); + + testFilter.runOnETAllPrim("PropertyInt16 eq 32767") + .is("<<PropertyInt16> eq <32767>>") + .isBinary(BinaryOperatorKind.EQ) + .root().left().goPath().isPrimitiveProperty("PropertyInt16", PropertyProvider.nameInt16, false) + .goUpFilterValidator() + .root().right().isLiteral("32767"); + + testFilter.runOnETAllPrim("PropertyInt32 eq 2147483647") + .is("<<PropertyInt32> eq <2147483647>>") + .isBinary(BinaryOperatorKind.EQ) + .root().left().goPath().isPrimitiveProperty("PropertyInt32", PropertyProvider.nameInt32, false) + .goUpFilterValidator() + .root().right().isLiteral("2147483647"); + + testFilter.runOnETAllPrim("PropertyInt64 eq 9223372036854775807") + .is("<<PropertyInt64> eq <9223372036854775807>>") + .isBinary(BinaryOperatorKind.EQ) + .root().left().goPath().isPrimitiveProperty("PropertyInt64", PropertyProvider.nameInt64, false) + .goUpFilterValidator() + .root().right().isLiteral("9223372036854775807"); + + testFilter.runOnETAllPrim("PropertyDate eq 2013-09-25") + .is("<<PropertyDate> eq <2013-09-25>>") + .isBinary(BinaryOperatorKind.EQ) + .root().left().goPath().isPrimitiveProperty("PropertyDate", PropertyProvider.nameDate, false) + .goUpFilterValidator() + .root().right().isLiteral("2013-09-25"); + + testFilter.runOnETAllPrim("PropertyDateTimeOffset eq 2013-09-25T12:34:56.123456789012-10:24") + .is("<<PropertyDateTimeOffset> eq <2013-09-25T12:34:56.123456789012-10:24>>") + .isBinary(BinaryOperatorKind.EQ) + .root().left().goPath() + .isPrimitiveProperty("PropertyDateTimeOffset", PropertyProvider.nameDateTimeOffset, false) + .goUpFilterValidator() + .root().right().isLiteral("2013-09-25T12:34:56.123456789012-10:24"); + + testFilter.runOnETAllPrim("PropertyDuration eq duration'P10DT5H34M21.123456789012S'") + .is("<<PropertyDuration> eq <duration'P10DT5H34M21.123456789012S'>>") + .isBinary(BinaryOperatorKind.EQ) + .root().left().goPath().isPrimitiveProperty("PropertyDuration", PropertyProvider.nameDuration, false) + .goUpFilterValidator() + .root().right().isLiteral("duration'P10DT5H34M21.123456789012S'"); + + testFilter.runOnETAllPrim("PropertyGuid eq 005056A5-09B1-1ED3-89BD-FB81372CCB33") + .is("<<PropertyGuid> eq <005056A5-09B1-1ED3-89BD-FB81372CCB33>>") + .isBinary(BinaryOperatorKind.EQ) + .root().left().goPath().isPrimitiveProperty("PropertyGuid", PropertyProvider.nameGuid, false) + .goUpFilterValidator() + .root().right().isLiteral("005056A5-09B1-1ED3-89BD-FB81372CCB33"); + + testFilter.runOnETAllPrim("PropertyString eq 'somestring'") + .is("<<PropertyString> eq <'somestring'>>") + .isBinary(BinaryOperatorKind.EQ) + .root().left().goPath().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false) + .goUpFilterValidator() + .root().right().isLiteral("'somestring'"); + + testFilter.runOnETAllPrim("PropertyTimeOfDay eq 12:34:55.12345678901") + .is("<<PropertyTimeOfDay> eq <12:34:55.12345678901>>") + .isBinary(BinaryOperatorKind.EQ) + .root().left().goPath().isPrimitiveProperty("PropertyTimeOfDay", PropertyProvider.nameTimeOfDay, false) + .goUpFilterValidator() + .root().right().isLiteral("12:34:55.12345678901"); + + testFilter.runOnETMixEnumDefCollComp("PropertyEnumString eq olingo.odata.test1.ENString'String1'") + .is("<<PropertyEnumString> eq <olingo.odata.test1.ENString<String1>>>") + .isBinary(BinaryOperatorKind.EQ) + .root().left().goPath().isPrimitiveProperty("PropertyEnumString", EnumTypeProvider.nameENString, false) + .goUpFilterValidator() + .root().right().isEnum(EnumTypeProvider.nameENString, Arrays.asList("String1")); + + testFilter.runOnETMixEnumDefCollComp("PropertyEnumString eq olingo.odata.test1.ENString'String2'") + .is("<<PropertyEnumString> eq <olingo.odata.test1.ENString<String2>>>") + .isBinary(BinaryOperatorKind.EQ) + .root().left().goPath().isPrimitiveProperty("PropertyEnumString", EnumTypeProvider.nameENString, false) + .goUpFilterValidator() + .root().right().isEnum(EnumTypeProvider.nameENString, Arrays.asList("String2")); + + testFilter.runOnETMixEnumDefCollComp( + "PropertyCompMixedEnumDef/PropertyEnumString eq olingo.odata.test1.ENString'String3'") + .is("<<PropertyCompMixedEnumDef/PropertyEnumString> eq <olingo.odata.test1.ENString<String3>>>") + .isBinary(BinaryOperatorKind.EQ) + .root().left().goPath() + .first().isComplexProperty("PropertyCompMixedEnumDef", ComplexTypeProvider.nameCTMixEnumDef, false) + .n().isPrimitiveProperty("PropertyEnumString", EnumTypeProvider.nameENString, false) + .goUpFilterValidator() + .root().right().isEnum(EnumTypeProvider.nameENString, Arrays.asList("String3")); + + testFilter + .runOnETMixEnumDefCollComp( + "PropertyCompMixedEnumDef/PropertyEnumString eq " + + "PropertyCompMixedEnumDef/PropertyEnumString") + .is("<<PropertyCompMixedEnumDef/PropertyEnumString> eq " + + "<PropertyCompMixedEnumDef/PropertyEnumString>>") + .isBinary(BinaryOperatorKind.EQ) + .root().left().goPath() + .first().isComplexProperty("PropertyCompMixedEnumDef", ComplexTypeProvider.nameCTMixEnumDef, false) + .n().isPrimitiveProperty("PropertyEnumString", EnumTypeProvider.nameENString, false) + .goUpFilterValidator() + .root().right().goPath() + .first().isComplexProperty("PropertyCompMixedEnumDef", ComplexTypeProvider.nameCTMixEnumDef, false) + .n().isPrimitiveProperty("PropertyEnumString", EnumTypeProvider.nameENString, false); + + testFilter.runOnETAllPrim("PropertyByte mod 0 gt 0") + .is("<<<PropertyByte> mod <0>> gt <0>>"); + + testFilter.runOnETKeyNavEx("CollPropertyComp/PropertyInt16 le 0") + .isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX); + } + + @Test + public void filterFunctions() throws Exception { + testFilter.runOnETAllPrim( + "olingo.odata.test1.UFCRTETTwoKeyNavParamCTTwoPrim(ParameterCTTwoPrim=@ParamAlias) eq null" + + "&@ParamAlias={}") + .is("<<UFCRTETTwoKeyNavParamCTTwoPrim> eq <null>>") + .left().goPath() + .first() + .isFunction("UFCRTETTwoKeyNavParamCTTwoPrim") + .isParameterAlias(0, "ParameterCTTwoPrim", "@ParamAlias"); + + testFilter.runOnETTwoKeyNav("PropertyComp/olingo.odata.test1.BFCCTPrimCompRTETTwoKeyNavParam" + + "(ParameterString=PropertyComp/PropertyComp/PropertyString)/PropertyString eq 'SomeString'") + .is("<<PropertyComp/BFCCTPrimCompRTETTwoKeyNavParam/PropertyString> eq <'SomeString'>>") + .root().left().goPath() + .first().isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false) + .n().isFunction("BFCCTPrimCompRTETTwoKeyNavParam") + .goParameter(0).isMember() + .goPath() + .first().isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false) + .n().isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTAllPrim, false) + .n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false) + .goUpFilterValidator().goUpToResourceValidator() + .n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false); + + testFilter.runOnETTwoKeyNav("PropertyComp/olingo.odata.test1.BFCCTPrimCompRTESTwoKeyNav()" + + "(PropertyInt16=1,PropertyString='2')/PropertyString eq 'SomeString'") + .is("<<PropertyComp/BFCCTPrimCompRTESTwoKeyNav/PropertyString> eq <'SomeString'>>") + .root().left().goPath() + .first().isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false) + .n().isFunction("BFCCTPrimCompRTESTwoKeyNav") + .isKeyPredicate(0, "PropertyInt16", "1") + .isKeyPredicate(1, "PropertyString", "'2'") + .n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false); + + testFilter.runOnETTwoKeyNav("PropertyComp/olingo.odata.test1.BFCCTPrimCompRTETTwoKeyNavParam" + + "(ParameterString='1')/PropertyString eq 'SomeString'") + .is("<<PropertyComp/BFCCTPrimCompRTETTwoKeyNavParam/PropertyString> eq <'SomeString'>>") + .root().left().goPath() + .first() + .isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false) + .n() + .isFunction("BFCCTPrimCompRTETTwoKeyNavParam") + .isParameter(0, "ParameterString", "'1'") + .n() + .isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false); + + testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavMany/olingo.odata.test1.BFCESTwoKeyNavRTString()" + + " eq 'SomeString'") + .is("<<NavPropertyETTwoKeyNavMany/BFCESTwoKeyNavRTString> eq <'SomeString'>>") + .root().left().goPath() + .first() + .isNavProperty("NavPropertyETTwoKeyNavMany", EntityTypeProvider.nameETTwoKeyNav, true) + .n().isFunction("BFCESTwoKeyNavRTString"); + + testFilter.runOnETKeyNav("$it/olingo.odata.test1.BFCETKeyNavRTETKeyNav()/PropertyString eq 'SomeString'") + .is("<<$it/BFCETKeyNavRTETKeyNav/PropertyString> eq <'SomeString'>>") + .root().left().goPath() + .first().isIt() + .n().isFunction("BFCETKeyNavRTETKeyNav") + .n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false); + + testFilter.runOnETTwoKeyNav("olingo.odata.test1.BFCESTwoKeyNavRTCTTwoPrim()/PropertyString eq 'SomeString'") + .is("<<BFCESTwoKeyNavRTCTTwoPrim/PropertyString> eq <'SomeString'>>") + .root().left().goPath() + .first().isFunction("BFCESTwoKeyNavRTCTTwoPrim") + .n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false); + + testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne/olingo.odata.test1.BFCETTwoKeyNavRTETTwoKeyNav()" + + "/PropertyComp/PropertyComp/PropertyString eq 'Walldorf'") + .is("<<NavPropertyETTwoKeyNavOne/BFCETTwoKeyNavRTETTwoKeyNav/PropertyComp/PropertyComp/PropertyString> " + + "eq <'Walldorf'>>") + .root().left().goPath() + .first().isNavProperty("NavPropertyETTwoKeyNavOne", EntityTypeProvider.nameETTwoKeyNav, false) + .n().isFunction("BFCETTwoKeyNavRTETTwoKeyNav") + .n().isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false) + .n().isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTAllPrim, false) + .n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false); + + testFilter.runOnETTwoKeyNav("PropertyComp/olingo.odata.test1.BFCCTPrimCompRTESTwoKeyNav()" + + "/olingo.odata.test1.ETBaseTwoKeyNav(PropertyInt16=2,PropertyString='3')/PropertyString eq 'SomeString'") + .is("<<PropertyComp/BFCCTPrimCompRTESTwoKeyNav/olingo.odata.test1.ETBaseTwoKeyNav/PropertyString> " + + "eq <'SomeString'>>") + .root().left().goPath() + .first().isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false) + .n().isFunction("BFCCTPrimCompRTESTwoKeyNav") + .isTypeFilterOnEntry(EntityTypeProvider.nameETBaseTwoKeyNav) + .isKeyPredicate(0, "PropertyInt16", "2") + .isKeyPredicate(1, "PropertyString", "'3'") + .n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false); + + testFilter.runOnETTwoKeyNavSingle("$it/olingo.odata.test1.BFCETTwoKeyNavRTCTTwoPrim()/olingo.odata.test1.CTBase" + + "/PropertyString eq 'SomeString'") + .is("<<$it/BFCETTwoKeyNavRTCTTwoPrim/olingo.odata.test1.CTBase/PropertyString> eq <'SomeString'>>") + .root().left().goPath() + .first() + .isIt() + .n() + .isFunction("BFCETTwoKeyNavRTCTTwoPrim") + .isTypeFilterOnEntry(ComplexTypeProvider.nameCTBase) + .n() + .isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false); + + testFilter.runOnETTwoKeyNav("olingo.odata.test1.UFCRTETTwoKeyNavParam(ParameterInt16=1)/PropertyInt16 eq 2") + .is("<<UFCRTETTwoKeyNavParam/PropertyInt16> eq <2>>") + .root().left().goPath() + .first() + .isFunction("UFCRTETTwoKeyNavParam") + .isParameter(0, "ParameterInt16", "1") + .n() + .isPrimitiveProperty("PropertyInt16", PropertyProvider.nameInt16, false); + + testFilter.runOnETTwoKeyNav("olingo.odata.test1.UFCRTETTwoKeyNavParam(ParameterInt16=@Param1Alias)" + + "/PropertyInt16 eq 2" + + "&@Param1Alias=1") + .root().left().goPath() + .first() + .isFunction("UFCRTETTwoKeyNavParam") + .isParameterAlias(0, "ParameterInt16", "@Param1Alias") + .n() + .isPrimitiveProperty("PropertyInt16", PropertyProvider.nameInt16, false); + + testFilter.runOnETTwoKeyNav("olingo.odata.test1.UFCRTETTwoKeyNavParam(ParameterInt16=1)" + + "/PropertyComp/PropertyComp/PropertyString eq 'SomeString'") + .root().left().goPath() + .first() + .isFunction("UFCRTETTwoKeyNavParam") + .isParameter(0, "ParameterInt16", "1") + .n() + .isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false) + .n() + .isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTAllPrim, false) + .n() + .isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false); + + testFilter.runOnETTwoKeyNav("olingo.odata.test1.UFCRTETTwoKeyNavParam(ParameterInt16=PropertyInt16)" + + "/PropertyComp/PropertyComp/PropertyString eq 'SomeString'") + .root().left().goPath() + .first() + .isFunction("UFCRTETTwoKeyNavParam") + .goParameter(0) + .isMember().goPath().first().isPrimitiveProperty("PropertyInt16", PropertyProvider.nameInt16, false) + .goUpFilterValidator().goUpToResourceValidator() + .n().isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false) + .n().isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTAllPrim, false) + .n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false); + + testFilter.runOnETTwoKeyNavEx("olingo.odata.test1.UFCRTETTwoKeyNavParam(ParameterInt16=@alias)") + .isExValidation(UriValidationException.MessageKeys.MISSING_ALIAS); + } + + @Test + public void methods() throws Exception { + testFilter.runOnETKeyNav("indexof(PropertyString,'47') eq 5") + .is("<<indexof(<PropertyString>,<'47'>)> eq <5>>") + .left() + .isMethod(MethodKind.INDEXOF, 2) + .isParameterText(0, "<PropertyString>") + .isParameterText(1, "<'47'>"); + + testFilter.runOnETKeyNav("tolower(PropertyString) eq 'foo'") + .is("<<tolower(<PropertyString>)> eq <'foo'>>") + .left() + .isMethod(MethodKind.TOLOWER, 1) + .isParameterText(0, "<PropertyString>"); + + testFilter.runOnETKeyNav("toupper(PropertyString) eq 'FOO'") + .is("<<toupper(<PropertyString>)> eq <'FOO'>>") + .left() + .isMethod(MethodKind.TOUPPER, 1) + .isParameterText(0, "<PropertyString>"); + + testFilter.runOnETKeyNav("trim(PropertyString) eq 'fooba'") + .is("<<trim(<PropertyString>)> eq <'fooba'>>") + .left() + .isMethod(MethodKind.TRIM, 1) + .isParameterText(0, "<PropertyString>"); + + testFilter.runOnETKeyNav("substring(PropertyString,4) eq 'foo'") + .is("<<substring(<PropertyString>,<4>)> eq <'foo'>>") + .left() + .isMethod(MethodKind.SUBSTRING, 2) + .isParameterText(0, "<PropertyString>") + .isParameterText(1, "<4>"); + + testFilter.runOnETKeyNav("substring(PropertyString,4) eq 'foo'") + .is("<<substring(<PropertyString>,<4>)> eq <'foo'>>") + .left() + .isMethod(MethodKind.SUBSTRING, 2) + .isParameterText(0, "<PropertyString>") + .isParameterText(1, "<4>"); + + testFilter.runOnETKeyNav("substring(PropertyString,2,4) eq 'foo'") + .is("<<substring(<PropertyString>,<2>,<4>)> eq <'foo'>>") + .left() + .isMethod(MethodKind.SUBSTRING, 3) + .isParameterText(0, "<PropertyString>") + .isParameterText(1, "<2>") + .isParameterText(2, "<4>"); + + testFilter.runOnETKeyNav("concat(PropertyString,PropertyCompTwoPrim/PropertyString) eq 'foo'") + .is("<<concat(<PropertyString>,<PropertyCompTwoPrim/PropertyString>)> eq <'foo'>>") + .left() + .isMethod(MethodKind.CONCAT, 2) + .isParameterText(0, "<PropertyString>") + .isParameterText(1, "<PropertyCompTwoPrim/PropertyString>"); + + testFilter.runOnETKeyNav("concat(PropertyString,'bar') eq 'foobar'") + .is("<<concat(<PropertyString>,<'bar'>)> eq <'foobar'>>") + .left() + .isMethod(MethodKind.CONCAT, 2) + .isParameterText(0, "<PropertyString>") + .isParameterText(1, "<'bar'>"); + + testFilter.runOnETKeyNav("concat(PropertyString,'bar') eq 'foobar'") + .is("<<concat(<PropertyString>,<'bar'>)> eq <'foobar'>>") + .left() + .isMethod(MethodKind.CONCAT, 2) + .isParameterText(0, "<PropertyString>") + .isParameterText(1, "<'bar'>"); + + testFilter.runOnETKeyNav("length(PropertyString) eq 32") + .is("<<length(<PropertyString>)> eq <32>>") + .left() + .isMethod(MethodKind.LENGTH, 1) + .isParameterText(0, "<PropertyString>"); + + testFilter.runOnETAllPrim("year(PropertyDate) eq 2013") + .is("<<year(<PropertyDate>)> eq <2013>>") + .left() + .isMethod(MethodKind.YEAR, 1) + .isParameterText(0, "<PropertyDate>"); + + testFilter.runOnETAllPrim("year(2013-09-25) eq 2013") + .is("<<year(<2013-09-25>)> eq <2013>>") + .left() + .isMethod(MethodKind.YEAR, 1) + .isParameterText(0, "<2013-09-25>"); + + testFilter.runOnETAllPrim("year(PropertyDateTimeOffset) eq 2013") + .is("<<year(<PropertyDateTimeOffset>)> eq <2013>>") + .left() + .isMethod(MethodKind.YEAR, 1) + .isParameterText(0, "<PropertyDateTimeOffset>"); + + testFilter.runOnETAllPrim("year(2013-09-25T12:34:56.123456789012-10:24) eq 2013") + .is("<<year(<2013-09-25T12:34:56.123456789012-10:24>)> eq <2013>>") + .left() + .isMethod(MethodKind.YEAR, 1) + .isParameterText(0, "<2013-09-25T12:34:56.123456789012-10:24>"); + + testFilter.runOnETAllPrim("month(PropertyDate) eq 9") + .is("<<month(<PropertyDate>)> eq <9>>") + .left() + .isMethod(MethodKind.MONTH, 1) + .isParameterText(0, "<PropertyDate>"); + + testFilter.runOnETAllPrim("month(2013-09-25) eq 9") + .is("<<month(<2013-09-25>)> eq <9>>") + .left() + .isMethod(MethodKind.MONTH, 1) + .isParameterText(0, "<2013-09-25>"); + + testFilter.runOnETAllPrim("month(PropertyDateTimeOffset) eq 9") + .is("<<month(<PropertyDateTimeOffset>)> eq <9>>") + .left() + .isMethod(MethodKind.MONTH, 1) + .isParameterText(0, "<PropertyDateTimeOffset>"); + + testFilter.runOnETAllPrim("month(2013-09-25T12:34:56.123456789012-10:24) eq 9") + .is("<<month(<2013-09-25T12:34:56.123456789012-10:24>)> eq <9>>") + .left() + .isMethod(MethodKind.MONTH, 1) + .isParameterText(0, "<2013-09-25T12:34:56.123456789012-10:24>"); + + testFilter.runOnETAllPrim("day(PropertyDate) eq 25") + .is("<<day(<PropertyDate>)> eq <25>>") + .left() + .isMethod(MethodKind.DAY, 1) + .isParameterText(0, "<PropertyDate>"); + + testFilter.runOnETAllPrim("day(2013-09-25) eq 25") + .is("<<day(<2013-09-25>)> eq <25>>") + .left() + .isMethod(MethodKind.DAY, 1) + .isParameterText(0, "<2013-09-25>"); + + testFilter.runOnETAllPrim("day(PropertyDateTimeOffset) eq 25") + .is("<<day(<PropertyDateTimeOffset>)> eq <25>>") + .left() + .isMethod(MethodKind.DAY, 1) + .isParameterText(0, "<PropertyDateTimeOffset>"); + + testFilter.runOnETAllPrim("day(2013-09-25T12:34:56.123456789012-10:24) eq 25") + .is("<<day(<2013-09-25T12:34:56.123456789012-10:24>)> eq <25>>") + .left() + .isMethod(MethodKind.DAY, 1) + .isParameterText(0, "<2013-09-25T12:34:56.123456789012-10:24>"); + + testFilter.runOnETAllPrim("hour(PropertyDateTimeOffset) eq 2") + .is("<<hour(<PropertyDateTimeOffset>)> eq <2>>") + .left() + .isMethod(MethodKind.HOUR, 1) + .isParameterText(0, "<PropertyDateTimeOffset>"); + + testFilter.runOnETAllPrim("hour(PropertyDateTimeOffset) eq 2") + .is("<<hour(<PropertyDateTimeOffset>)> eq <2>>") + .left() + .isMethod(MethodKind.HOUR, 1) + .isParameterText(0, "<PropertyDateTimeOffset>"); + + testFilter.runOnETAllPrim("hour(2013-09-25T12:34:56.123456789012-10:24) eq 2") + .is("<<hour(<2013-09-25T12:34:56.123456789012-10:24>)> eq <2>>") + .left() + .isMethod(MethodKind.HOUR, 1) + .isParameterText(0, "<2013-09-25T12:34:56.123456789012-10:24>"); + + testFilter.runOnETAllPrim("hour(PropertyTimeOfDay) eq 2") + .is("<<hour(<PropertyTimeOfDay>)> eq <2>>") + .left() + .isMethod(MethodKind.HOUR, 1) + .isParameterText(0, "<PropertyTimeOfDay>"); + + testFilter.runOnETAllPrim("hour(12:34:55.123456789012) eq 12") + .is("<<hour(<12:34:55.123456789012>)> eq <12>>") + .left() + .isMethod(MethodKind.HOUR, 1) + .isParameterText(0, "<12:34:55.123456789012>"); + + testFilter.runOnETAllPrim("minute(PropertyDateTimeOffset) eq 34") + .is("<<minute(<PropertyDateTimeOffset>)> eq <34>>") + .left() + .isMethod(MethodKind.MINUTE, 1) + .isParameterText(0, "<PropertyDateTimeOffset>"); + + testFilter.runOnETAllPrim("minute(2013-09-25T12:34:56.123456789012-10:24) eq 34") + .is("<<minute(<2013-09-25T12:34:56.123456789012-10:24>)> eq <34>>") + .left() + .isMethod(MethodKind.MINUTE, 1) + .isParameterText(0, "<2013-09-25T12:34:56.123456789012-10:24>"); + + testFilter.runOnETAllPrim("minute(PropertyTimeOfDay) eq 34") + .is("<<minute(<PropertyTimeOfDay>)> eq <34>>") + .left() + .isMethod(MethodKind.MINUTE, 1) + .isParameterText(0, "<PropertyTimeOfDay>"); + + testFilter.runOnETAllPrim("minute(12:34:55.123456789012) eq 34") + .is("<<minute(<12:34:55.123456789012>)> eq <34>>") + .left() + .isMethod(MethodKind.MINUTE, 1) + .isParameterText(0, "<12:34:55.123456789012>"); + + testFilter.runOnETAllPrim("second(PropertyDateTimeOffset) eq 56") + .is("<<second(<PropertyDateTimeOffset>)> eq <56>>") + .left() + .isMethod(MethodKind.SECOND, 1) + .isParameterText(0, "<PropertyDateTimeOffset>"); + + testFilter.runOnETAllPrim("second(2013-09-25T12:34:56.123456789012-10:24) eq 56") + .is("<<second(<2013-09-25T12:34:56.123456789012-10:24>)> eq <56>>") + .left() + .isMethod(MethodKind.SECOND, 1) + .isParameterText(0, "<2013-09-25T12:34:56.123456789012-10:24>"); + + testFilter.runOnETAllPrim("second(PropertyTimeOfDay) eq 56") + .is("<<second(<PropertyTimeOfDay>)> eq <56>>") + .left() + .isMethod(MethodKind.SECOND, 1) + .isParameterText(0, "<PropertyTimeOfDay>"); + + testFilter.runOnETAllPrim("second(12:34:55.123456789012) eq 56") + .is("<<second(<12:34:55.123456789012>)> eq <56>>") + .left() + .isMethod(MethodKind.SECOND, 1) + .isParameterText(0, "<12:34:55.123456789012>"); + + testFilter.runOnETAllPrim("fractionalseconds(PropertyDateTimeOffset) eq 123456789012") + .is("<<fractionalseconds(<PropertyDateTimeOffset>)> eq <123456789012>>") + .left() + .isMethod(MethodKind.FRACTIONALSECONDS, 1) + .isParameterText(0, "<PropertyDateTimeOffset>"); + + testFilter.runOnETAllPrim("fractionalseconds(2013-09-25T12:34:56.123456789012-10:24) eq 123456789012") + .is("<<fractionalseconds(<2013-09-25T12:34:56.123456789012-10:24>)> eq <123456789012>>") + .left() + .isMethod(MethodKind.FRACTIONALSECONDS, 1) + .isParameterText(0, "<2013-09-25T12:34:56.123456789012-10:24>"); + + testFilter.runOnETAllPrim("fractionalseconds(PropertyTimeOfDay) eq 123456789012") + .is("<<fractionalseconds(<PropertyTimeOfDay>)> eq <123456789012>>") + .left() + .isMethod(MethodKind.FRACTIONALSECONDS, 1) + .isParameterText(0, "<PropertyTimeOfDay>"); + + testFilter.runOnETAllPrim("fractionalseconds(12:34:55.123456789012) eq 123456789012") + .is("<<fractionalseconds(<12:34:55.123456789012>)> eq <123456789012>>") + .left() + .isMethod(MethodKind.FRACTIONALSECONDS, 1) + .isParameterText(0, "<12:34:55.123456789012>"); + + testFilter.runOnETAllPrim("totalseconds(PropertyDuration) eq 4711") + .is("<<totalseconds(<PropertyDuration>)> eq <4711>>") + .left() + .isMethod(MethodKind.TOTALSECONDS, 1) + .isParameterText(0, "<PropertyDuration>"); + + testFilter.runOnETAllPrim("totalseconds(duration'P10DT5H34M21.123456789012S') eq 4711") + .is("<<totalseconds(<duration'P10DT5H34M21.123456789012S'>)> eq <4711>>") + .left() + .isMethod(MethodKind.TOTALSECONDS, 1) + .isParameterText(0, "<duration'P10DT5H34M21.123456789012S'>"); + + testFilter.runOnETAllPrim("date(PropertyDateTimeOffset) eq 2013-09-25") + .is("<<date(<PropertyDateTimeOffset>)> eq <2013-09-25>>") + .left() + .isMethod(MethodKind.DATE, 1) + .isParameterText(0, "<PropertyDateTimeOffset>"); + + testFilter.runOnETAllPrim("date(2013-09-25T12:34:56.123456789012-10:24) eq 2013-09-25") + .is("<<date(<2013-09-25T12:34:56.123456789012-10:24>)> eq <2013-09-25>>") + .left() + .isMethod(MethodKind.DATE, 1) + .isParameterText(0, "<2013-09-25T12:34:56.123456789012-10:24>"); + + testFilter.runOnETAllPrim("time(PropertyDateTimeOffset) eq 12:34:55.123456789012") + .is("<<time(<PropertyDateTimeOffset>)> eq <12:34:55.123456789012>>") + .left() + .isMethod(MethodKind.TIME, 1) + .isParameterText(0, "<PropertyDateTimeOffset>"); + + testFilter.runOnETAllPrim("time(2013-09-25T12:34:56.123456789012-10:24) eq 12:34:55.123456789012") + .is("<<time(<2013-09-25T12:34:56.123456789012-10:24>)> eq <12:34:55.123456789012>>") + .left() + .isMethod(MethodKind.TIME, 1) + .isParameterText(0, "<2013-09-25T12:34:56.123456789012-10:24>"); + + testFilter.runOnETAllPrim("round(PropertyDouble) eq 17") + .is("<<round(<PropertyDouble>)> eq <17>>") + .left() + .isMethod(MethodKind.ROUND, 1) + .isParameterText(0, "<PropertyDouble>"); + + testFilter.runOnETAllPrim("round(17.45e1) eq 17") + .is("<<round(<17.45e1>)> eq <17>>") + .left() + .isMethod(MethodKind.ROUND, 1) + .isParameterText(0, "<17.45e1>"); + + testFilter.runOnETAllPrim("round(PropertyDecimal) eq 17") + .is("<<round(<PropertyDecimal>)> eq <17>>") + .left() + .isMethod(MethodKind.ROUND, 1) + .isParameterText(0, "<PropertyDecimal>"); + + testFilter.runOnETAllPrim("round(17.45) eq 17") + .is("<<round(<17.45>)> eq <17>>") + .left() + .isMethod(MethodKind.ROUND, 1) + .isParameterText(0, "<17.45>"); + + testFilter.runOnETAllPrim("floor(PropertyDouble) eq 17") + .is("<<floor(<PropertyDouble>)> eq <17>>") + .left() + .isMethod(MethodKind.FLOOR, 1) + .isParameterText(0, "<PropertyDouble>"); + + testFilter.runOnETAllPrim("floor(17.45e1) eq 17") + .is("<<floor(<17.45e1>)> eq <17>>") + .left() + .isMethod(MethodKind.FLOOR, 1) + .isParameterText(0, "<17.45e1>"); + + testFilter.runOnETAllPrim("floor(PropertyDecimal) eq 17") + .is("<<floor(<PropertyDecimal>)> eq <17>>") + .left() + .isMethod(MethodKind.FLOOR, 1) + .isParameterText(0, "<PropertyDecimal>"); + + testFilter.runOnETAllPrim("floor(17.45) eq 17") + .is("<<floor(<17.45>)> eq <17>>") + .left() + .isMethod(MethodKind.FLOOR, 1) + .isParameterText(0, "<17.45>"); + + testFilter.runOnETAllPrim("ceiling(PropertyDouble) eq 18") + .is("<<ceiling(<PropertyDouble>)> eq <18>>") + .left() + .isMethod(MethodKind.CEILING, 1) + .isParameterText(0, "<PropertyDouble>"); + + testFilter.runOnETAllPrim("ceiling(17.55e1) eq 18") + .is("<<ceiling(<17.55e1>)> eq <18>>") + .left() + .isMethod(MethodKind.CEILING, 1) + .isParameterText(0, "<17.55e1>"); + + testFilter.runOnETAllPrim("ceiling(PropertyDecimal) eq 18") + .is("<<ceiling(<PropertyDecimal>)> eq <18>>") + .left() + .isMethod(MethodKind.CEILING, 1) + .isParameterText(0, "<PropertyDecimal>"); + + testFilter.runOnETAllPrim("ceiling(17.55) eq 18") + .is("<<ceiling(<17.55>)> eq <18>>") + .left() + .isMethod(MethodKind.CEILING, 1) + .isParameterText(0, "<17.55>"); + + testFilter.runOnETAllPrim("totaloffsetminutes(PropertyDateTimeOffset) eq 4711") + .is("<<totaloffsetminutes(<PropertyDateTimeOffset>)> eq <4711>>") + .left() + .isMethod(MethodKind.TOTALOFFSETMINUTES, 1) + .isParameterText(0, "<PropertyDateTimeOffset>"); + + testFilter.runOnETAllPrim("totaloffsetminutes(2013-09-25T12:34:56.123456789012-10:24) eq 4711") + .is("<<totaloffsetminutes(<2013-09-25T12:34:56.123456789012-10:24>)> eq <4711>>") + .left() + .isMethod(MethodKind.TOTALOFFSETMINUTES, 1) + .isParameterText(0, "<2013-09-25T12:34:56.123456789012-10:24>"); + + testFilter.runOnETAllPrim("mindatetime() ne null") + .is("<<mindatetime()> ne <null>>") + .left().isMethod(MethodKind.MINDATETIME, 0); + + testFilter.runOnETAllPrim("mindatetime() eq 2013-09-25T12:34:56.123456789012-10:24") + .is("<<mindatetime()> eq <2013-09-25T12:34:56.123456789012-10:24>>") + .left() + .isMethod(MethodKind.MINDATETIME, 0); + + testFilter.runOnETAllPrim("maxdatetime() ne null") + .is("<<maxdatetime()> ne <null>>") + .left().isMethod(MethodKind.MAXDATETIME, 0); + + testFilter.runOnETAllPrim("maxdatetime() eq 2013-09-25T12:34:56.123456789012-10:24") + .is("<<maxdatetime()> eq <2013-09-25T12:34:56.123456789012-10:24>>") + .left() + .isMethod(MethodKind.MAXDATETIME, 0); + + testFilter.runOnETAllPrim("now() ne null") + .is("<<now()> ne <null>>") + .left().isMethod(MethodKind.NOW, 0); + + testFilter.runOnETAllPrim("now() eq 2013-09-25T12:34:56.123456789012-10:24") + .is("<<now()> eq <2013-09-25T12:34:56.123456789012-10:24>>") + .left() + .isMethod(MethodKind.NOW, 0); + + testFilter.runOnETTwoKeyNav("$it/PropertyString eq 'SomeString'") + .is("<<$it/PropertyString> eq <'SomeString'>>") + .left() + .goPath() + .first().isUriPathInfoKind(UriResourceKind.it) + .isType(EntityTypeProvider.nameETTwoKeyNav, false) + .n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false); + + testFilter.runOnCTTwoPrim("$it/PropertyString eq 'SomeString'") + .is("<<$it/PropertyString> eq <'SomeString'>>") + .left() + .goPath() + .first().isUriPathInfoKind(UriResourceKind.it) + .isType(ComplexTypeProvider.nameCTTwoPrim, false) + .n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false); + + testFilter.runOnString("$it eq 'Walldorf'") + .is("<<$it> eq <'Walldorf'>>") + .left() + .goPath() + .first().isUriPathInfoKind(UriResourceKind.it) + .isType(PropertyProvider.nameString, false); + + testFilter.runOnString("endswith($it,'company.com')") + .is("<endswith(<$it>,<'company.com'>)>") + .isMethod(MethodKind.ENDSWITH, 2) + .isParameterText(0, "<$it>") + .isParameterText(1, "<'company.com'>") + .goParameter(0) + .goPath() + .first().isUriPathInfoKind(UriResourceKind.it) + .isType(PropertyProvider.nameString, false); + + testFilter.runOnString("endswith($it,'company.com') eq false") + .is("<<endswith(<$it>,<'company.com'>)> eq <false>>") + .left() + .isMethod(MethodKind.ENDSWITH, 2) + .isParameterText(0, "<$it>") + .isParameterText(1, "<'company.com'>") + .goParameter(0) + .goPath() + .first().isUriPathInfoKind(UriResourceKind.it) + .isType(PropertyProvider.nameString, false); + + testFilter.runOnETTwoKeyNav("endswith(PropertyComp/PropertyComp/PropertyString,'dorf')") + .is("<endswith(<PropertyComp/PropertyComp/PropertyString>,<'dorf'>)>") + .isMethod(MethodKind.ENDSWITH, 2) + .goParameter(0).goPath() + .first().isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false) + .n().isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTAllPrim, false) + .n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false).goUpFilterValidator() + .root().goParameter(1).isLiteral("'dorf'"); + + testFilter.runOnETTwoKeyNav("endswith(PropertyComp/PropertyComp/PropertyString,'dorf') eq true") + .is("<<endswith(<PropertyComp/PropertyComp/PropertyString>,<'dorf'>)> eq <true>>") + .isBinary(BinaryOperatorKind.EQ) + .left().isMethod(MethodKind.ENDSWITH, 2) + .goParameter(0).goPath() + .first().isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false) + .n().isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTAllPrim, false) + .n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false).goUpFilterValidator() + .root().left().goParameter(1).isLiteral("'dorf'"); + + testFilter.runOnETTwoKeyNav("endswith('Walldorf','dorf')") + .is("<endswith(<'Walldorf'>,<'dorf'>)>") + .isMethod(MethodKind.ENDSWITH, 2) + .goParameter(0).isLiteral("'Walldorf'") + .root().goParameter(1).isLiteral("'dorf'"); + + testFilter.runOnETTwoKeyNav("endswith('Walldorf','dorf') eq true") + .is("<<endswith(<'Walldorf'>,<'dorf'>)> eq <true>>") + .isBinary(BinaryOperatorKind.EQ) + .left().isMethod(MethodKind.ENDSWITH, 2) + .goParameter(0).isLiteral("'Walldorf'") + .root().left().goParameter(1).isLiteral("'dorf'"); + + testFilter.runOnETKeyNav("startswith(PropertyCompAllPrim/PropertyString,'Wall')") + .is("<startswith(<PropertyCompAllPrim/PropertyString>,<'Wall'>)>") + .isMethod(MethodKind.STARTSWITH, 2) + .goParameter(0).goPath() + .first().isComplexProperty("PropertyCompAllPrim", ComplexTypeProvider.nameCTAllPrim, false) + .n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false).goUpFilterValidator() + .root().goParameter(1).isLiteral("'Wall'"); + + testFilter.runOnETKeyNav("startswith(PropertyCompAllPrim/PropertyString,'Wall') eq true") + .is("<<startswith(<PropertyCompAllPrim/PropertyString>,<'Wall'>)> eq <true>>") + .isBinary(BinaryOperatorKind.EQ) + .left().isMethod(MethodKind.STARTSWITH, 2) + .goParameter(0).goPath() + .first().isComplexProperty("PropertyCompAllPrim", ComplexTypeProvider.nameCTAllPrim, false) + .n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false).goUpFilterValidator() + .root().left().goParameter(1).isLiteral("'Wall'"); + + testFilter.runOnETKeyNav("startswith('Walldorf','Wall')") + .is("<startswith(<'Walldorf'>,<'Wall'>)>") + .isMethod(MethodKind.STARTSWITH, 2) + .goParameter(0).isLiteral("'Walldorf'") + .root().goParameter(1).isLiteral("'Wall'"); + + testFilter.runOnETKeyNav("startswith('Walldorf','Wall') eq true") + .is("<<startswith(<'Walldorf'>,<'Wall'>)> eq <true>>") + .isBinary(BinaryOperatorKind.EQ) + .left().isMethod(MethodKind.STARTSWITH, 2) + .goParameter(0).isLiteral("'Walldorf'") + .root().left().goParameter(1).isLiteral("'Wall'"); + + testFilter.runOnETTwoKeyNav("contains(PropertyComp/PropertyComp/PropertyString,'Wall')") + .is("<contains(<PropertyComp/PropertyComp/PropertyString>,<'Wall'>)>") + .isMethod(MethodKind.CONTAINS, 2) + .goParameter(0).goPath() + .first().isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false) + .n().isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTAllPrim, false) + .n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false).goUpFilterValidator() + .root().goParameter(1).isLiteral("'Wall'"); + + testFilter.runOnETTwoKeyNav("contains(PropertyComp/PropertyComp/PropertyString,'Wall') eq true") + .is("<<contains(<PropertyComp/PropertyComp/PropertyString>,<'Wall'>)> eq <true>>") + .isBinary(BinaryOperatorKind.EQ) + .left().isMethod(MethodKind.CONTAINS, 2) + .goParameter(0).goPath() + .first().isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false) + .n().isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTAllPrim, false) + .n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false).goUpFilterValidator() + .root().left().goParameter(1).isLiteral("'Wall'"); + + testFilter.runOnETTwoKeyNav("contains('Walldorf','Wall')") + .is("<contains(<'Walldorf'>,<'Wall'>)>") + .isMethod(MethodKind.CONTAINS, 2) + .goParameter(0).isLiteral("'Walldorf'") + .root().goParameter(1).isLiteral("'Wall'"); + + testFilter.runOnETTwoKeyNav("contains('Walldorf','Wall') eq true") + .is("<<contains(<'Walldorf'>,<'Wall'>)> eq <true>>") + .isBinary(BinaryOperatorKind.EQ) + .left().isMethod(MethodKind.CONTAINS, 2) + .goParameter(0).isLiteral("'Walldorf'") + .root().left().goParameter(1).isLiteral("'Wall'"); + + testFilter.runOnETTwoKeyNav("PropertyComp/PropertyComp/PropertyInt16 eq " + + "$root/ESTwoKeyNav(PropertyInt16=1,PropertyString='2')/PropertyInt16") + .is("<<PropertyComp/PropertyComp/PropertyInt16> eq <$root/ESTwoKeyNav/PropertyInt16>>") + .root().left() + .goPath() + .first().isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false) + .n().isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTAllPrim, false) + .n().isPrimitiveProperty("PropertyInt16", PropertyProvider.nameInt16, false) + .goUpFilterValidator() + .root().right() + .goPath() + .first().isUriPathInfoKind(UriResourceKind.root) + .n().isEntitySet("ESTwoKeyNav") + .isKeyPredicate(0, "PropertyInt16", "1") + .isKeyPredicate(1, "PropertyString", "'2'") + .n().isPrimitiveProperty("PropertyInt16", PropertyProvider.nameInt16, false); + + testFilter.runOnETTwoKeyNavEx("startswith(CollPropertyString,'wrong')") + .isExSemantic(MessageKeys.COLLECTION_NOT_ALLOWED); + } + + @Test + public void castMethod() throws Exception { + testFilter.runOnETKeyNav("cast(olingo.odata.test1.ETBaseTwoKeyNav) ne null") + .is("<<cast(<olingo.odata.test1.ETBaseTwoKeyNav>)> ne <null>>") + .left() + .isMethod(MethodKind.CAST, 1) + .isParameterText(0, "<olingo.odata.test1.ETBaseTwoKeyNav>") + .goParameter(0).isTypedLiteral(EntityTypeProvider.nameETBaseTwoKeyNav); + + testFilter.runOnETKeyNav("cast(PropertyCompTwoPrim,olingo.odata.test1.CTBase) ne null") + .is("<<cast(<PropertyCompTwoPrim>,<olingo.odata.test1.CTBase>)> ne <null>>") + .left() + .isMethod(MethodKind.CAST, 2) + .isParameterText(0, "<PropertyCompTwoPrim>") + .isParameterText(1, "<olingo.odata.test1.CTBase>") + .goParameter(0).goPath().first() + .isComplexProperty("PropertyCompTwoPrim", ComplexTypeProvider.nameCTTwoPrim, false) + .goUpFilterValidator() + .root().left() + .goParameter(1).isTypedLiteral(ComplexTypeProvider.nameCTBase); + + testFilter.runOnETKeyNav("cast($it,olingo.odata.test1.CTBase) ne null") + .is("<<cast(<$it>,<olingo.odata.test1.CTBase>)> ne <null>>") + .left() + .isMethod(MethodKind.CAST, 2) + .isParameterText(0, "<$it>") + .isParameterText(1, "<olingo.odata.test1.CTBase>") + .goParameter(0).goPath().first() + .isIt().isType(EntityTypeProvider.nameETKeyNav, false) + .goUpFilterValidator() + .root().left() + .goParameter(1).isTypedLiteral(ComplexTypeProvider.nameCTBase); + + testFilter.runOnETKeyNav("concat(PropertyString,cast(PropertyCompAllPrim/PropertyInt16,Edm.String)) ne ''") + .is("<<concat(<PropertyString>,<cast(<PropertyCompAllPrim/PropertyInt16>,<Edm.String>)>)> ne <''>>") + .left() + .isMethod(MethodKind.CONCAT, 2) + .isParameterText(0, "<PropertyString>") + .isParameterText(1, "<cast(<PropertyCompAllPrim/PropertyInt16>,<Edm.String>)>") + .goParameter(1) + .isMethod(MethodKind.CAST, 2) + .isParameterText(0, "<PropertyCompAllPrim/PropertyInt16>") + .isParameterText(1, "<Edm.String>"); + + testFilter.runOnETKeyNav("cast($it,olingo.odata.test1.CTBase) eq cast($it,olingo.odata.test1.CTBase)") + .is("<<cast(<$it>,<olingo.odata.test1.CTBase>)> eq <cast(<$it>,<olingo.odata.test1.CTBase>)>>") + .left() + .isMethod(MethodKind.CAST, 2) + .isParameterText(0, "<$it>") + .isParameterText(1, "<olingo.odata.test1.CTBase>") + .goParameter(0).goPath().first() + .isIt().isType(EntityTypeProvider.nameETKeyNav, false) + .goUpFilterValidator() + .root().left() + .goParameter(1).isTypedLiteral(ComplexTypeProvider.nameCTBase) + .root().right() + .isMethod(MethodKind.CAST, 2) + .isParameterText(0, "<$it>") + .isParameterText(1, "<olingo.odata.test1.CTBase>") + .goParameter(0).goPath().first() + .isIt().isType(EntityTypeProvider.nameETKeyNav, false) + .goUpFilterValidator() + .root().right() + .goParameter(1).isTypedLiteral(ComplexTypeProvider.nameCTBase); + + testFilter.runOnInt32("cast(Edm.Int32) gt 0") + .is("<<cast(<Edm.Int32>)> gt <0>>") + .left() + .isMethod(MethodKind.CAST, 1) + .goParameter(0).isTypedLiteral(PropertyProvider.nameInt32); + + testFilter.runOnDateTimeOffset("cast(Edm.DateTimeOffset) ne null") + .is("<<cast(<Edm.DateTimeOffset>)> ne <null>>") + .left() + .isMethod(MethodKind.CAST, 1) + .goParameter(0).isTypedLiteral(PropertyProvider.nameDateTimeOffset); + + testFilter.runOnDuration("cast(Edm.Duration) ne null") + .is("<<cast(<Edm.Duration>)> ne <null>>") + .left() + .isMethod(MethodKind.CAST, 1) + .goParameter(0).isTypedLiteral(PropertyProvider.nameDuration); + + testFilter.runOnTimeOfDay("cast(Edm.TimeOfDay) ne null") + .is("<<cast(<Edm.TimeOfDay>)> ne <null>>") + .left() + .isMethod(MethodKind.CAST, 1) + .goParameter(0).isTypedLiteral(PropertyProvider.nameTimeOfDay); + + testFilter.runOnETKeyNav("cast(CollPropertyInt16,Edm.Int32) ne null") + .is("<<cast(<CollPropertyInt16>,<Edm.Int32>)> ne <null>>") + .left() + .isMethod(MethodKind.CAST, 2) + .goParameter(0).goPath().first() + .isPrimitiveProperty("CollPropertyInt16", PropertyProvider.nameInt16, true) + .goUpFilterValidator().root().left() + .goParameter(1).isTypedLiteral(PropertyProvider.nameInt32); + + testFilter.runOnETTwoKeyNav( + "cast(PropertyComp/PropertyComp/PropertyDateTimeOffset,Edm.DateTimeOffset) ne null") + .is("<<cast(<PropertyComp/PropertyComp/PropertyDateTimeOffset>,<Edm.DateTimeOffset>)> ne <null>>") + .left() + .isMethod(MethodKind.CAST, 2) + .goParameter(0).goPath() + .first().isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false) + .n().isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTAllPrim, false) + .n().isPrimitiveProperty("PropertyDateTimeOffset", PropertyProvider.nameDateTimeOffset, false) + .goUpFilterValidator().root().left() + .goParameter(1).isTypedLiteral(PropertyProvider.nameDateTimeOffset); + + testFilter.runOnETTwoKeyNav("cast(PropertyComp/PropertyComp/PropertyDuration,Edm.Duration) ne null") + .is("<<cast(<PropertyComp/PropertyComp/PropertyDuration>,<Edm.Duration>)> ne <null>>") + .left() + .isMethod(MethodKind.CAST, 2) + .goParameter(0).goPath() + .first().isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false) + .n().isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTAllPrim, false) + .n().isPrimitiveProperty("PropertyDuration", PropertyProvider.nameDuration, false) + .goUpFilterValidator().root().left() + .goParameter(1).isTypedLiteral(PropertyProvider.nameDuration); + + testFilter.runOnETTwoKeyNav("cast(PropertyComp/PropertyComp/PropertyTimeOfDay,Edm.TimeOfDay) ne null") + .is("<<cast(<PropertyComp/PropertyComp/PropertyTimeOfDay>,<Edm.TimeOfDay>)> ne <null>>") + .left() + .isMethod(MethodKind.CAST, 2) + .goParameter(0).goPath() + .first().isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false) + .n().isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTAllPrim, false) + .n().isPrimitiveProperty("PropertyTimeOfDay", PropertyProvider.nameTimeOfDay, false) + .goUpFilterValidator().root().left() + .goParameter(1).isTypedLiteral(PropertyProvider.nameTimeOfDay); + + testFilter.runOnETKeyNav("cast(PropertyCompAllPrim,olingo.odata.test1.CTTwoPrim) ne null") + .is("<<cast(<PropertyCompAllPrim>,<olingo.odata.test1.CTTwoPrim>)> ne <null>>") + .left() + .isMethod(MethodKind.CAST, 2) + .goParameter(0).goPath() + .first().isComplexProperty("PropertyCompAllPrim", ComplexTypeProvider.nameCTAllPrim, false) + .goUpFilterValidator().root().left() + .goParameter(1).isTypedLiteral(ComplexTypeProvider.nameCTTwoPrim); + + testFilter.runOnETKeyNav("cast(NavPropertyETKeyNavOne,olingo.odata.test1.ETKeyPrimNav) ne null") + .is("<<cast(<NavPropertyETKeyNavOne>,<olingo.odata.test1.ETKeyPrimNav>)> ne <null>>") + .left() + .isMethod(MethodKind.CAST, 2) + .goParameter(0).goPath() + .first().isNavProperty("NavPropertyETKeyNavOne", EntityTypeProvider.nameETKeyNav, false) + .goUpFilterValidator().root().left() + .goParameter(1).isTypedLiteral(EntityTypeProvider.nameETKeyPrimNav); + + testFilter.runOnETAllPrim( + "olingo.odata.test1.UFCRTCTTwoPrimTwoParam(ParameterInt16=1,ParameterString='1') ne null") + .left() + .goPath() + .isFunction("UFCRTCTTwoPrimTwoParam") + .isParameter(0, "ParameterInt16", "1") + .isParameter(1, "ParameterString", "'1'"); + + testFilter.runOnETKeyNavEx("cast(NavPropertyETKeyPrimNavOne,olingo.odata.test1.ETKeyNav)") + .isExSemantic(MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE); + } + + @Test + public void lambdaFunctions() throws Exception { + + testFilter.runOnETTwoKeyNav("CollPropertyComp/all(l:true)") + .is("<CollPropertyComp/<ALL;<true>>>"); + + testFilter.runOnETTwoKeyNav("CollPropertyComp/all(x:x/PropertyInt16 eq 2)") + .is("<CollPropertyComp/<ALL;<<x/PropertyInt16> eq <2>>>>"); + + testFilter.runOnETTwoKeyNav("CollPropertyComp/any(l:true)") + .is("<CollPropertyComp/<ANY;<true>>>"); + testFilter.runOnETTwoKeyNav("CollPropertyComp/any()") + .is("<CollPropertyComp/<ANY;>>"); + + testFilter.runOnETKeyNav("NavPropertyETTwoKeyNavMany/any(d:d/PropertyString eq 'SomeString')") + .is("<NavPropertyETTwoKeyNavMany/<ANY;<<d/PropertyString> eq <'SomeString'>>>>") + .root().goPath() + .first().isNavProperty("NavPropertyETTwoKeyNavMany", EntityTypeProvider.nameETTwoKeyNav, true) + .n().isUriPathInfoKind(UriResourceKind.lambdaAny) + .goLambdaExpression() + .isBinary(BinaryOperatorKind.EQ) + .left().goPath() + .first().isUriPathInfoKind(UriResourceKind.lambdaVariable) + .isType(EntityTypeProvider.nameETTwoKeyNav, false) + .n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false); + + testFilter.runOnETKeyNav("NavPropertyETTwoKeyNavMany/any()") + .is("<NavPropertyETTwoKeyNavMany/<ANY;>>"); + + testFilter.runOnETKeyNav("NavPropertyETTwoKeyNavOne/CollPropertyString/any(d:d eq 'SomeString')") + .is("<NavPropertyETTwoKeyNavOne/CollPropertyString/<ANY;<<d> eq <'SomeString'>>>>") + .root().goPath() + .first().isNavProperty("NavPropertyETTwoKeyNavOne", EntityTypeProvider.nameETTwoKeyNav, false) + .n().isPrimitiveProperty("CollPropertyString", PropertyProvider.nameString, true) + .n().isUriPathInfoKind(UriResourceKind.lambdaAny) + .goLambdaExpression() + .isBinary(BinaryOperatorKind.EQ) + .left().goPath() + .first().isUriPathInfoKind(UriResourceKind.lambdaVariable) + .isType(PropertyProvider.nameString, false); + + testFilter.runOnETKeyNav("NavPropertyETTwoKeyNavOne/olingo.odata.test1.BFCETTwoKeyNavRTESTwoKeyNav()" + + "/any(d:d/PropertyComp/PropertyInt16 eq 6)") + .is("<NavPropertyETTwoKeyNavOne/BFCETTwoKeyNavRTESTwoKeyNav/<ANY;<<d/PropertyComp/PropertyInt16> eq <6>>>>") + .root().goPath() + .first().isNavProperty("NavPropertyETTwoKeyNavOne", EntityTypeProvider.nameETTwoKeyNav, false) + .n().isFunction("BFCETTwoKeyNavRTESTwoKeyNav") + .n().isUriPathInfoKind(UriResourceKind.lambdaAny) + .goLambdaExpression() + .isBinary(BinaryOperatorKind.EQ) + .left().goPath() + .first().isUriPathInfoKind(UriResourceKind.lambdaVariable) + .isType(EntityTypeProvider.nameETTwoKeyNav, false) + .n().isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false) + .n().isPrimitiveProperty("PropertyInt16", PropertyProvider.nameInt16, false); + + testFilter.runOnETKeyNav("NavPropertyETTwoKeyNavMany/any(d:d/PropertyInt16 eq 1 or " + + "d/CollPropertyString/any(e:e eq 'SomeString'))") + .is("<NavPropertyETTwoKeyNavMany/<ANY;<<<d/PropertyInt16> eq <1>>" + + " or <d/CollPropertyString/<ANY;<<e> eq <'SomeString'>>>>>>>") + .root().goPath() + .first().isNavProperty("NavPropertyETTwoKeyNavMany", EntityTypeProvider.nameETTwoKeyNav, true) + .n().isUriPathInfoKind(UriResourceKind.lambdaAny) + .goLambdaExpression() + .root().isBinary(BinaryOperatorKind.OR) + .root().left() + .isBinary(BinaryOperatorKind.EQ) + .left() + .goPath() + .first().isUriPathInfoKind(UriResourceKind.lambdaVariable) + .isType(EntityTypeProvider.nameETTwoKeyNav, false) + .n().isPrimitiveProperty("PropertyInt16", PropertyProvider.nameInt16, false) + .goUpFilterValidator() + .root().right() + .goPath() + .first().isUriPathInfoKind(UriResourceKind.lambdaVariable) + .isType(EntityTypeProvider.nameETTwoKeyNav, false) + .n().isUriPathInfoKind(UriResourceKind.primitiveProperty) + .isPrimitiveProperty("CollPropertyString", PropertyProvider.nameString, true) + .n().isUriPathInfoKind(UriResourceKind.lambdaAny) + .goLambdaExpression() + .root().left().goPath() + .first().isUriPathInfoKind(UriResourceKind.lambdaVariable) + .isType(PropertyProvider.nameString, false); + + testFilter.runOnETKeyNav("NavPropertyETTwoKeyNavMany/any(d:d/PropertyInt16 eq 1 or " + + "d/CollPropertyString/any(e:e eq 'SomeString'))") + .is("<NavPropertyETTwoKeyNavMany/<ANY;<<<d/PropertyInt16> eq <1>> or " + + "<d/CollPropertyString/<ANY;<<e> eq <'SomeString'>>>>>>>") + .root().goPath() + .first().isNavProperty("NavPropertyETTwoKeyNavMany", EntityTypeProvider.nameETTwoKeyNav, true) + .n().isUriPathInfoKind(UriResourceKind.lambdaAny) + .goLambdaExpression() + .root().isBinary(BinaryOperatorKind.OR) + .root().left() + .isBinary(BinaryOperatorKind.EQ) + .left() + .goPath() + .first().isUriPathInfoKind(UriResourceKind.lambdaVariable) + .isType(EntityTypeProvider.nameETTwoKeyNav, false) + .n().isPrimitiveProperty("PropertyInt16", PropertyProvider.nameInt16, false) + .goUpFilterValidator() + .root().right() + .goPath() + .first().isUriPathInfoKind(UriResourceKind.lambdaVariable) + .isType(EntityTypeProvider.nameETTwoKeyNav, false) + .n().isType(PropertyProvider.nameString, true) + .n().isUriPathInfoKind(UriResourceKind.lambdaAny) + .goLambdaExpression() + .root().left().goPath() + .first().isUriPathInfoKind(UriResourceKind.lambdaVariable) + .isType(PropertyProvider.nameString, false); + + testFilter.runOnETKeyNav("NavPropertyETTwoKeyNavMany/any(d:d/PropertyString eq 'SomeString' and " + + "d/CollPropertyString/any(e:e eq d/PropertyString))") + .is("<NavPropertyETTwoKeyNavMany/<ANY;<<<d/PropertyString> eq <'SomeString'>> and " + + "<d/CollPropertyString/<ANY;<<e> eq <d/PropertyString>>>>>>>") + .root().goPath() + .first().isNavProperty("NavPropertyETTwoKeyNavMany", EntityTypeProvider.nameETTwoKeyNav, true) + .n().isUriPathInfoKind(UriResourceKind.lambdaAny) + .goLambdaExpression() + .root().isBinary(BinaryOperatorKind.AND) + .root().left() + .isBinary(BinaryOperatorKind.EQ) + .left() + .goPath() + .first().isUriPathInfoKind(UriResourceKind.lambdaVariable) + .isType(EntityTypeProvider.nameETTwoKeyNav, false) + .n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false) + .goUpFilterValidator() + .root().right() + .goPath() + .first().isUriPathInfoKind(UriResourceKind.lambdaVariable) + .isType(EntityTypeProvider.nameETTwoKeyNav, false) + .n().isType(PropertyProvider.nameString, true) + .n().isUriPathInfoKind(UriResourceKind.lambdaAny) + .goLambdaExpression() + .root().left().goPath() + .first().isUriPathInfoKind(UriResourceKind.lambdaVariable) + .isType(PropertyProvider.nameString, false) + .goUpFilterValidator() + .root().right().goPath() + .first().isUriPathInfoKind(UriResourceKind.lambdaVariable) + .n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false); + + testFilter.runOnETKeyNavEx("any()") + .isExSemantic(MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE); + testFilter.runOnETKeyNavEx("any(d:d/PropertyInt16 eq 1)") + .isExSemantic(MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE); + } + + @Test + public void isOfMethod() throws Exception { + testFilter.runOnETKeyNav("isof(olingo.odata.test1.ETTwoKeyNav)") + .is("<isof(<olingo.odata.test1.ETTwoKeyNav>)>") + .root() + .isMethod(MethodKind.ISOF, 1) + .goParameter(0).isTypedLiteral(EntityTypeProvider.nameETTwoKeyNav); + + testFilter.runOnETKeyNav("isof(olingo.odata.test1.ETBaseTwoKeyNav) eq true") + .is("<<isof(<olingo.odata.test1.ETBaseTwoKeyNav>)> eq <true>>") + .root().isBinary(BinaryOperatorKind.EQ) + .left() + .isMethod(MethodKind.ISOF, 1) + .goParameter(0).isTypedLiteral(EntityTypeProvider.nameETBaseTwoKeyNav); + + testFilter + .runOnETKeyNav("isof(olingo.odata.test1.ETBaseTwoKeyNav) eq true and PropertyCompNav/PropertyInt16 eq 1") + .is("<<<isof(<olingo.odata.test1.ETBaseTwoKeyNav>)> eq <true>> and <<PropertyCompNav/PropertyInt16> eq <1>>>") + .root().isBinary(BinaryOperatorKind.AND) + .left().isBinary(BinaryOperatorKind.EQ) + .left().isMethod(MethodKind.ISOF, 1) + .goParameter(0).isTypedLiteral(EntityTypeProvider.nameETBaseTwoKeyNav); + + testFilter.runOnETKeyNav("isof(NavPropertyETKeyNavOne,olingo.odata.test1.ETKeyNav) eq true") + .is("<<isof(<NavPropertyETKeyNavOne>,<olingo.odata.test1.ETKeyNav>)> eq <true>>") + .root().isBinary(BinaryOperatorKind.EQ) + .left().isMethod(MethodKind.ISOF, 2) + .goParameter(0).goPath().isNavProperty("NavPropertyETKeyNavOne", EntityTypeProvider.nameETKeyNav, false) + .goUpFilterValidator() + .root().left().goParameter(1).isTypedLiteral(EntityTypeProvider.nameETKeyNav); + + testFilter.runOnETKeyNav("isof(PropertyCompTwoPrim,olingo.odata.test1.CTTwoPrim)") + .is("<isof(<PropertyCompTwoPrim>,<olingo.odata.test1.CTTwoPrim>)>") + .root().isMethod(MethodKind.ISOF, 2) + .goParameter(0).goPath().isComplexProperty("PropertyCompTwoPrim", ComplexTypeProvider.nameCTTwoPrim, false) + .goUpFilterValidator() + .root().goParameter(1).isTypedLiteral(ComplexTypeProvider.nameCTTwoPrim); + + testFilter.runOnETKeyNav("isof(PropertyCompTwoPrim,olingo.odata.test1.CTTwoBase)") + .is("<isof(<PropertyCompTwoPrim>,<olingo.odata.test1.CTTwoBase>)>") + .root().isMethod(MethodKind.ISOF, 2) + .goParameter(0).goPath().isComplexProperty("PropertyCompTwoPrim", ComplexTypeProvider.nameCTTwoPrim, false) + .goUpFilterValidator() + .root().goParameter(1).isTypedLiteral(ComplexTypeProvider.nameCTTwoBase); + + testFilter.runOnETKeyNav("isof(PropertyCompTwoPrim,olingo.odata.test1.CTTwoPrim) eq true") + .is("<<isof(<PropertyCompTwoPrim>,<olingo.odata.test1.CTTwoPrim>)> eq <true>>") + .root().left().isMethod(MethodKind.ISOF, 2) + .goParameter(0).goPath().isComplexProperty("PropertyCompTwoPrim", ComplexTypeProvider.nameCTTwoPrim, false) + .goUpFilterValidator() + .root().left().goParameter(1).isTypedLiteral(ComplexTypeProvider.nameCTTwoPrim); + + testFilter.runOnETKeyNav("isof($it,olingo.odata.test1.CTTwoPrim)") + .is("<isof(<$it>,<olingo.odata.test1.CTTwoPrim>)>") + .root() + .isMethod(MethodKind.ISOF, 2) + .goParameter(0).goPath().isIt().goUpFilterValidator() + .root().goParameter(1).isTypedLiteral(ComplexTypeProvider.nameCTTwoPrim); + + testFilter.runOnETKeyNav("isof($it,olingo.odata.test1.CTTwoBase) eq f
<TRUNCATED>
