You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by ch...@apache.org on 2016/01/12 14:08:02 UTC
[01/30] olingo-odata4 git commit: [OLINGO-834] URI resource-path
parser in Java
Repository: olingo-odata4
Updated Branches:
refs/heads/master 0d6f4821f -> b0866014d
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/927ecb93/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestUriParserImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestUriParserImpl.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestUriParserImpl.java
index 9011bc4..e6612ff 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestUriParserImpl.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestUriParserImpl.java
@@ -28,7 +28,6 @@ import org.apache.olingo.server.api.edmx.EdmxReference;
import org.apache.olingo.server.api.uri.UriInfoKind;
import org.apache.olingo.server.api.uri.UriResourceKind;
import org.apache.olingo.server.api.uri.queryoption.expression.MethodKind;
-import org.apache.olingo.server.core.uri.parser.UriParserException;
import org.apache.olingo.server.core.uri.parser.UriParserSemanticException;
import org.apache.olingo.server.core.uri.parser.UriParserSyntaxException;
import org.apache.olingo.server.core.uri.testutil.FilterValidator;
@@ -186,11 +185,11 @@ public class TestUriParserImpl {
.isType(EntityTypeProvider.nameETTwoKeyTwoPrim, false);
testUri.runEx(ContainerProvider.AIRT_STRING + "/invalidElement")
- .isExSemantic(UriParserSemanticException.MessageKeys.RESOURCE_PART_ONLY_FOR_TYPED_PARTS);
+ .isExValidation(UriValidationException.MessageKeys.UNALLOWED_RESOURCE_PATH);
}
@Test
- public void runCount() {
+ public void count() {
// count entity set
testRes.run("ESAllPrim/$count")
@@ -338,7 +337,7 @@ public class TestUriParserImpl {
.isKeyPredicate(0, "PropertyInt16", "1");
// with two keys
- testRes.run("ESTwoKeyTwoPrim(PropertyInt16=1, PropertyString='ABC')")
+ testRes.run("ESTwoKeyTwoPrim(PropertyInt16=1,PropertyString='ABC')")
.isEntitySet("ESTwoKeyTwoPrim")
.isKeyPredicate(0, "PropertyInt16", "1")
.isKeyPredicate(1, "PropertyString", "'ABC'");
@@ -562,14 +561,14 @@ public class TestUriParserImpl {
}
@Test
- public void testUnary() throws UriParserException {
+ public void unary() throws Exception {
testFilter.runOnETAllPrim("not PropertyBoolean").isCompr("<not <PropertyBoolean>>");
testFilter.runOnETAllPrim("- PropertyInt16 eq PropertyInt16").isCompr("<<- <PropertyInt16>> eq <PropertyInt16>>");
testFilter.runOnETAllPrim("-PropertyInt16 eq PropertyInt16").isCompr("<<- <PropertyInt16>> eq <PropertyInt16>>");
}
@Test
- public void testFilterComplexMixedPriority() throws UriParserException {
+ public void filterComplexMixedPriority() throws Exception {
testFilter.runOnETAllPrim("PropertyInt16 or PropertyInt32 and PropertyInt64")
.isCompr("<<PropertyInt16> or <<PropertyInt32> and <PropertyInt64>>>");
testFilter.runOnETAllPrim("PropertyInt16 or PropertyInt32 and PropertyInt64 eq PropertyByte")
@@ -594,7 +593,7 @@ public class TestUriParserImpl {
}
@Test
- public void testFilterSimpleSameBinaryBinaryBinaryPriority() throws UriParserException {
+ public void filterSimpleSameBinaryBinaryBinaryPriority() throws Exception {
testFilter.runOnETAllPrim("1 add 2 add 3 add 4").isCompr("<<< <1> add <2>> add <3>> add <4>>");
testFilter.runOnETAllPrim("1 add 2 add 3 div 4").isCompr("<< <1> add <2>> add <<3> div <4>>>");
testFilter.runOnETAllPrim("1 add 2 div 3 add 4").isCompr("<< <1> add <<2> div <3>>> add <4>>");
@@ -1101,7 +1100,7 @@ public class TestUriParserImpl {
}
@Test
- public void testGeo() throws UriParserException {
+ public void geo() throws Exception {
testFilter.runOnETAllPrim("geo.distance(PropertySByte,PropertySByte)")
.is("<geo.distance(<PropertySByte>,<PropertySByte>)>")
.isMethod(MethodKind.GEODISTANCE, 2);
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/927ecb93/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/parser/ParserTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/parser/ParserTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/parser/ParserTest.java
index 3d67c48..f54ad04 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/parser/ParserTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/parser/ParserTest.java
@@ -55,7 +55,7 @@ public class ParserTest {
EdmEntityType productsType = Mockito.mock(EdmEntityType.class);
final FullQualifiedName nameProducts = new FullQualifiedName("NS", "Products");
- Mockito.when(mockEdm.getEntityContainer(null)).thenReturn(container);
+ Mockito.when(mockEdm.getEntityContainer()).thenReturn(container);
Mockito.when(typeCategory.getName()).thenReturn("Category");
Mockito.when(typeCategory.getNamespace()).thenReturn("NS");
Mockito.when(esCategory.getEntityType()).thenReturn(typeCategory);
@@ -97,7 +97,7 @@ public class ParserTest {
EdmEntityType typeProduct = Mockito.mock(EdmEntityType.class);
FullQualifiedName fqnProduct = new FullQualifiedName("NS", "Products");
- Mockito.when(mockEdm.getEntityContainer(null)).thenReturn(container);
+ Mockito.when(mockEdm.getEntityContainer()).thenReturn(container);
Mockito.when(typeCategory.getName()).thenReturn(fqnCategory.getName());
Mockito.when(typeCategory.getNamespace()).thenReturn(fqnCategory.getNamespace());
Mockito.when(typeCategory.getFullQualifiedName()).thenReturn(fqnCategory);
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/927ecb93/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/FilterValidator.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/FilterValidator.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/FilterValidator.java
index 309a25f..0800dd0 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/FilterValidator.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/FilterValidator.java
@@ -28,7 +28,9 @@ import java.util.List;
import org.apache.olingo.commons.api.edm.Edm;
import org.apache.olingo.commons.api.edm.EdmType;
import org.apache.olingo.commons.api.edm.FullQualifiedName;
+import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.ODataApplicationException;
+import org.apache.olingo.server.api.ODataLibraryException;
import org.apache.olingo.server.api.uri.UriInfo;
import org.apache.olingo.server.api.uri.UriInfoKind;
import org.apache.olingo.server.api.uri.UriResource;
@@ -51,8 +53,10 @@ import org.apache.olingo.server.core.uri.parser.UriParserSemanticException;
import org.apache.olingo.server.core.uri.parser.UriParserSyntaxException;
import org.apache.olingo.server.core.uri.queryoption.expression.MemberImpl;
import org.apache.olingo.server.core.uri.queryoption.expression.MethodImpl;
+import org.apache.olingo.server.core.uri.validator.UriValidationException;
public class FilterValidator implements TestValidator {
+ private final OData odata = OData.newInstance();
private Edm edm;
private TestValidator invokedByValidator;
@@ -62,7 +66,7 @@ public class FilterValidator implements TestValidator {
private Expression curExpression;
private Expression rootExpression;
- private UriParserException exception;
+ private ODataLibraryException exception;
// --- Setup ---
public FilterValidator setUriResourcePathValidator(final ResourceValidator uriResourcePathValidator) {
@@ -107,15 +111,18 @@ public class FilterValidator implements TestValidator {
// --- Execution ---
- public FilterValidator runOrderByOnETAllPrim(final String orderBy) throws UriParserException {
+ public FilterValidator runOrderByOnETAllPrim(final String orderBy)
+ throws UriParserException, UriValidationException {
return runUriOrderBy("ESAllPrim", "$orderby=" + orderBy.trim());
}
- public FilterValidator runOrderByOnETTwoKeyNav(final String orderBy) throws UriParserException {
+ public FilterValidator runOrderByOnETTwoKeyNav(final String orderBy)
+ throws UriParserException, UriValidationException {
return runUriOrderBy("ESTwoKeyNav", "$orderby=" + orderBy.trim());
}
- public FilterValidator runOrderByOnETMixEnumDefCollComp(final String orderBy) throws UriParserException {
+ public FilterValidator runOrderByOnETMixEnumDefCollComp(final String orderBy)
+ throws UriParserException, UriValidationException {
return runUriOrderBy("ESMixEnumDefCollComp", "$orderby=" + orderBy.trim());
}
@@ -123,15 +130,17 @@ public class FilterValidator implements TestValidator {
return runUriOrderByEx("ESTwoKeyNav", "$orderby=" + orderBy.trim());
}
- public FilterValidator runOnETTwoKeyNav(final String filter) throws UriParserException {
+ public FilterValidator runOnETTwoKeyNav(final String filter) throws UriParserException, UriValidationException {
return runUri("ESTwoKeyNav", "$filter=" + filter.trim());
}
- public FilterValidator runOnETMixEnumDefCollComp(final String filter) throws UriParserException {
+ public FilterValidator runOnETMixEnumDefCollComp(final String filter)
+ throws UriParserException, UriValidationException {
return runUri("ESMixEnumDefCollComp", "$filter=" + filter.trim());
}
- public FilterValidator runOnETTwoKeyNavSingle(final String filter) throws UriParserException {
+ public FilterValidator runOnETTwoKeyNavSingle(final String filter)
+ throws UriParserException, UriValidationException {
return runUri("SINav", "$filter=" + filter.trim());
}
@@ -139,11 +148,11 @@ public class FilterValidator implements TestValidator {
return runUriEx("ESTwoKeyNav", "$filter=" + filter.trim());
}
- public FilterValidator runOnETAllPrim(final String filter) throws UriParserException {
+ public FilterValidator runOnETAllPrim(final String filter) throws UriParserException, UriValidationException {
return runUri("ESAllPrim(1)", "$filter=" + filter.trim());
}
- public FilterValidator runOnETKeyNav(final String filter) throws UriParserException {
+ public FilterValidator runOnETKeyNav(final String filter) throws UriParserException, UriValidationException {
return runUri("ESKeyNav(1)", "$filter=" + filter.trim());
}
@@ -151,35 +160,36 @@ public class FilterValidator implements TestValidator {
return runUriEx("ESKeyNav(1)", "$filter=" + filter.trim());
}
- public FilterValidator runOnCTTwoPrim(final String filter) throws UriParserException {
+ public FilterValidator runOnCTTwoPrim(final String filter) throws UriParserException, UriValidationException {
return runUri("SINav/PropertyCompTwoPrim", "$filter=" + filter.trim());
}
- public FilterValidator runOnString(final String filter) throws UriParserException {
+ public FilterValidator runOnString(final String filter) throws UriParserException, UriValidationException {
return runUri("SINav/PropertyString", "$filter=" + filter.trim());
}
- public FilterValidator runOnInt32(final String filter) throws UriParserException {
+ public FilterValidator runOnInt32(final String filter) throws UriParserException, UriValidationException {
return runUri("ESCollAllPrim(1)/CollPropertyInt32", "$filter=" + filter.trim());
}
- public FilterValidator runOnDateTimeOffset(final String filter) throws UriParserException {
+ public FilterValidator runOnDateTimeOffset(final String filter) throws UriParserException, UriValidationException {
return runUri("ESCollAllPrim(1)/CollPropertyDateTimeOffset", "$filter=" + filter.trim());
}
- public FilterValidator runOnDuration(final String filter) throws UriParserException {
+ public FilterValidator runOnDuration(final String filter) throws UriParserException, UriValidationException {
return runUri("ESCollAllPrim(1)/CollPropertyDuration", "$filter=" + filter.trim());
}
- public FilterValidator runOnTimeOfDay(final String filter) throws UriParserException {
+ public FilterValidator runOnTimeOfDay(final String filter) throws UriParserException, UriValidationException {
return runUri("ESCollAllPrim(1)/CollPropertyTimeOfDay", "$filter=" + filter.trim());
}
- public FilterValidator runUri(final String path, final String query) throws UriParserException {
- Parser parser = new Parser();
+ public FilterValidator runUri(final String path, final String query)
+ throws UriParserException, UriValidationException {
+ Parser parser = new Parser(edm, odata);
UriInfo uriInfo = null;
- uriInfo = parser.parseUri(path, query, null, edm);
+ uriInfo = parser.parseUri(path, query, null);
if (uriInfo.getKind() != UriInfoKind.resource) {
fail("Filtervalidator can only be used on resourcePaths");
@@ -193,19 +203,19 @@ public class FilterValidator implements TestValidator {
public FilterValidator runUriEx(final String path, final String query) {
exception = null;
try {
- new Parser().parseUri(path, query, null, edm);
+ new Parser(edm, odata).parseUri(path, query, null);
fail("Expected exception not thrown.");
} catch (final UriParserException e) {
exception = e;
+ } catch (final UriValidationException e) {
+ exception = e;
}
return this;
}
- public FilterValidator runUriOrderBy(final String path, final String query) throws UriParserException {
- Parser parser = new Parser();
- UriInfo uriInfo = null;
-
- uriInfo = parser.parseUri(path, query, null, edm);
+ public FilterValidator runUriOrderBy(final String path, final String query)
+ throws UriParserException, UriValidationException {
+ final UriInfo uriInfo = new Parser(edm, odata).parseUri(path, query, null);
if (uriInfo.getKind() != UriInfoKind.resource) {
fail("Filtervalidator can only be used on resourcePaths");
@@ -218,10 +228,12 @@ public class FilterValidator implements TestValidator {
public FilterValidator runUriOrderByEx(final String path, final String query) {
exception = null;
try {
- new Parser().parseUri(path, query, null, edm);
+ new Parser(edm, odata).parseUri(path, query, null);
fail("Expected exception not thrown.");
} catch (final UriParserException e) {
exception = e;
+ } catch (final UriValidationException e) {
+ exception = e;
}
return this;
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/927ecb93/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/ParserWithLogging.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/ParserWithLogging.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/ParserWithLogging.java
index 6b2b0df..5ebc57e 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/ParserWithLogging.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/ParserWithLogging.java
@@ -20,6 +20,8 @@ package org.apache.olingo.server.core.uri.testutil;
import org.antlr.v4.runtime.DefaultErrorStrategy;
import org.antlr.v4.runtime.DiagnosticErrorListener;
+import org.apache.olingo.commons.api.edm.Edm;
+import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.core.uri.antlr.UriParserParser;
import org.apache.olingo.server.core.uri.parser.Parser;
@@ -27,7 +29,8 @@ public class ParserWithLogging extends Parser {
TestErrorLogger errorCollector1;
TestErrorLogger errorCollector2;
- public ParserWithLogging() {
+ public ParserWithLogging(final Edm edm, final OData odata) {
+ super(edm, odata);
errorCollector1 = new TestErrorLogger("Stage 1", 1);
errorCollector2 = new TestErrorLogger("Stage 2", 1);
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/927ecb93/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/ResourceValidator.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/ResourceValidator.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/ResourceValidator.java
index 994b6b2..d70b204 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/ResourceValidator.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/ResourceValidator.java
@@ -30,6 +30,8 @@ import org.apache.olingo.commons.api.edm.EdmElement;
import org.apache.olingo.commons.api.edm.EdmType;
import org.apache.olingo.commons.api.edm.FullQualifiedName;
import org.apache.olingo.commons.api.http.HttpMethod;
+import org.apache.olingo.server.api.OData;
+import org.apache.olingo.server.api.ODataLibraryException;
import org.apache.olingo.server.api.uri.UriInfo;
import org.apache.olingo.server.api.uri.UriInfoKind;
import org.apache.olingo.server.api.uri.UriInfoResource;
@@ -50,11 +52,11 @@ import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
import org.apache.olingo.server.api.uri.queryoption.SelectItem;
import org.apache.olingo.server.api.uri.queryoption.SelectOption;
import org.apache.olingo.server.core.uri.UriResourceWithKeysImpl;
-import org.apache.olingo.server.core.uri.parser.UriParserException;
import org.apache.olingo.server.core.uri.validator.UriValidationException;
import org.apache.olingo.server.core.uri.validator.UriValidator;
public class ResourceValidator implements TestValidator {
+ private final OData odata = OData.newInstance();
private Edm edm;
private TestValidator invokedBy;
private UriInfo uriInfo = null;
@@ -83,13 +85,13 @@ public class ResourceValidator implements TestValidator {
// --- Execution ---
public ResourceValidator run(final String path) {
- ParserWithLogging testParser = new ParserWithLogging();
+ ParserWithLogging testParser = new ParserWithLogging(edm, odata);
UriInfo uriInfoTmp = null;
uriPathInfo = null;
try {
- uriInfoTmp = testParser.parseUri(path, null, null, edm);
- } catch (final UriParserException e) {
+ uriInfoTmp = testParser.parseUri(path, null, null);
+ } catch (final ODataLibraryException e) {
fail("Exception occurred while parsing the URI: " + path + "\n"
+ " Message: " + e.getMessage());
}
@@ -279,7 +281,8 @@ public class ResourceValidator implements TestValidator {
// input parameter type may be null in order to assert that the collectionTypeFilter is not set
EdmType actualType = uriPathInfoKeyPred.getTypeFilterOnCollection();
- assertEquals(expectedType, expectedType == null ? actualType : actualType.getFullQualifiedName());
+ assertEquals(expectedType,
+ expectedType == null || actualType == null ? actualType : actualType.getFullQualifiedName());
return this;
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/927ecb93/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/TestUriValidator.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/TestUriValidator.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/TestUriValidator.java
index 0d5fb4a..1dbe62b 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/TestUriValidator.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/TestUriValidator.java
@@ -28,6 +28,7 @@ import org.apache.olingo.commons.api.edm.Edm;
import org.apache.olingo.commons.api.edm.EdmType;
import org.apache.olingo.commons.api.edm.FullQualifiedName;
import org.apache.olingo.commons.api.http.HttpMethod;
+import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.ODataLibraryException;
import org.apache.olingo.server.api.uri.UriInfo;
import org.apache.olingo.server.api.uri.UriInfoKind;
@@ -44,6 +45,7 @@ import org.apache.olingo.server.core.uri.validator.UriValidationException;
import org.apache.olingo.server.core.uri.validator.UriValidator;
public class TestUriValidator implements TestValidator {
+ private final OData odata = OData.newInstance();
private Edm edm;
private UriInfo uriInfo;
@@ -62,17 +64,14 @@ public class TestUriValidator implements TestValidator {
public TestUriValidator run(final String path, final String query)
throws UriParserException, UriValidationException {
- Parser parser = new Parser();
- UriValidator validator = new UriValidator();
-
- uriInfo = parser.parseUri(path, query, null, edm);
- validator.validate(uriInfo, HttpMethod.GET);
+ uriInfo = new Parser(edm, odata).parseUri(path, query, null);
+ new UriValidator().validate(uriInfo, HttpMethod.GET);
return this;
}
public TestUriValidator run(final String path, final String query, final String fragment)
throws UriParserException, UriValidationException {
- uriInfo = new Parser().parseUri(path, query, fragment, edm);
+ uriInfo = new Parser(edm, odata).parseUri(path, query, fragment);
new UriValidator().validate(uriInfo, HttpMethod.GET);
return this;
}
@@ -82,10 +81,9 @@ public class TestUriValidator implements TestValidator {
}
public TestUriValidator runEx(final String path, final String query) {
- Parser parser = new Parser();
uriInfo = null;
try {
- uriInfo = parser.parseUri(path, query, null, edm);
+ uriInfo = new Parser(edm, odata).parseUri(path, query, null);
new UriValidator().validate(uriInfo, HttpMethod.GET);
fail("Exception expected");
} catch (UriParserException e) {
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/927ecb93/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/validator/UriValidatorTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/validator/UriValidatorTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/validator/UriValidatorTest.java
index 0e8b2e6..868f9b8 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/validator/UriValidatorTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/validator/UriValidatorTest.java
@@ -323,7 +323,8 @@ public class UriValidatorTest {
{ URI_ACTION_ES, QO_ID }
};
- private static final Edm edm = OData.newInstance().createServiceMetadata(
+ private static final OData odata = OData.newInstance();
+ private static final Edm edm = odata.createServiceMetadata(
new EdmTechProvider(), Collections.<EdmxReference> emptyList()).getEdm();
@Test
@@ -419,24 +420,24 @@ public class UriValidatorTest {
public void checkKeys() throws Exception {
final TestUriValidator testUri = new TestUriValidator().setEdm(edm);
- testUri.run("ESTwoKeyNav(PropertyInt16=1, PropertyString='abc')");
+ testUri.run("ESTwoKeyNav(PropertyInt16=1,PropertyString='abc')");
- testUri.runEx("ESTwoKeyNav(xxx=1, yyy='abc')")
+ testUri.runEx("ESTwoKeyNav(xxx=1,yyy='abc')")
.isExValidation(UriValidationException.MessageKeys.INVALID_KEY_PROPERTY);
testUri.runEx("ESCollAllPrim(null)").isExValidation(UriValidationException.MessageKeys.INVALID_KEY_PROPERTY);
testUri.runEx("ESAllPrim(PropertyInt16='1')")
- .isExValidation(UriValidationException.MessageKeys.INVALID_KEY_PROPERTY);
+ .isExSemantic(UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE);
testUri.runEx("ESAllPrim(12345678901234567890)")
.isExValidation(UriValidationException.MessageKeys.INVALID_KEY_PROPERTY);
testUri.runEx("ESTwoKeyNav(PropertyInt16=1,PropertyString=1)")
- .isExValidation(UriValidationException.MessageKeys.INVALID_KEY_PROPERTY);
+ .isExSemantic(UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE);
testUri.runEx("ESTwoKeyNav(PropertyInt16=1,PropertyInt16=1)")
.isExValidation(UriValidationException.MessageKeys.DOUBLE_KEY_PROPERTY);
testUri.runEx("ESAllPrim(0)/NavPropertyETTwoPrimMany(xxx=42)")
.isExValidation(UriValidationException.MessageKeys.INVALID_KEY_PROPERTY);
testUri.runEx("ESAllPrim(0)/NavPropertyETTwoPrimMany(PropertyInt16='1')")
- .isExValidation(UriValidationException.MessageKeys.INVALID_KEY_PROPERTY);
+ .isExSemantic(UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE);
}
@Test
@@ -499,7 +500,7 @@ public class UriValidatorTest {
private void validate(final String path, final String query, final HttpMethod method) {
try {
- new UriValidator().validate(new Parser().parseUri(path, query, null, edm), method);
+ new UriValidator().validate(new Parser(edm, odata).parseUri(path, query, null), method);
} catch (final UriParserException e) {
fail("Failed for uri: " + path + '?' + query);
} catch (final UriValidationException e) {
@@ -510,7 +511,7 @@ public class UriValidatorTest {
private void validateWrong(final String path, final String query, final HttpMethod method,
final UriValidationException.MessageKeys expectedMessageKey) {
try {
- new UriValidator().validate(new Parser().parseUri(path, query, null, edm), method);
+ new UriValidator().validate(new Parser(edm, odata).parseUri(path, query, null), method);
fail("Validation Exception not thrown: " + method + ' ' + path + '?' + query);
} catch (final UriParserException e) {
fail("Wrong Exception thrown: " + method + ' ' + path + '?' + query);
[18/30] olingo-odata4 git commit: [OLINGO-834] ExpressionParser
parses path expressions
Posted by ch...@apache.org.
[OLINGO-834] ExpressionParser parses path expressions
Signed-off-by: Christian Amend <ch...@sap.com>
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/a8091658
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/a8091658
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/a8091658
Branch: refs/heads/master
Commit: a809165896e8315a04b566e11bd1637c26044c7d
Parents: 104ecf4
Author: Klaus Straubinger <kl...@sap.com>
Authored: Fri Dec 18 16:42:51 2015 +0100
Committer: Christian Amend <ch...@sap.com>
Committed: Mon Dec 21 10:10:35 2015 +0100
----------------------------------------------------------------------
.../deserializer/helper/ExpandTreeBuilder.java | 14 +-
.../server/core/uri/UriResourceActionImpl.java | 44 +-
.../uri/UriResourceComplexPropertyImpl.java | 18 +-
.../server/core/uri/UriResourceCountImpl.java | 10 +-
.../core/uri/UriResourceEntitySetImpl.java | 19 +-
.../core/uri/UriResourceFunctionImpl.java | 48 +-
.../olingo/server/core/uri/UriResourceImpl.java | 6 +-
.../server/core/uri/UriResourceItImpl.java | 31 +-
.../core/uri/UriResourceLambdaAllImpl.java | 26 +-
.../core/uri/UriResourceLambdaAnyImpl.java | 25 +-
.../core/uri/UriResourceLambdaVarImpl.java | 32 +-
.../uri/UriResourceNavigationPropertyImpl.java | 21 +-
.../uri/UriResourcePrimitivePropertyImpl.java | 20 +-
.../server/core/uri/UriResourceRefImpl.java | 10 +-
.../server/core/uri/UriResourceRootImpl.java | 31 +-
.../core/uri/UriResourceSingletonImpl.java | 21 +-
.../uri/UriResourceStartingTypeFilterImpl.java | 33 +-
.../server/core/uri/UriResourceTypedImpl.java | 11 +-
.../server/core/uri/UriResourceValueImpl.java | 9 +-
.../core/uri/parser/ExpressionParser.java | 560 ++++++++++-
.../server/core/uri/parser/FilterParser.java | 49 +
.../server/core/uri/parser/OrderByParser.java | 61 ++
.../olingo/server/core/uri/parser/Parser.java | 123 +--
.../server/core/uri/parser/ParserHelper.java | 335 ++++++-
.../core/uri/parser/ResourcePathParser.java | 323 +-----
.../server/core/uri/parser/SelectParser.java | 10 +-
.../server/core/uri/parser/UriContext.java | 7 +-
.../core/uri/parser/UriParseTreeVisitor.java | 124 +--
.../server/core/uri/parser/UriTokenizer.java | 36 +-
.../uri/queryoption/expression/MemberImpl.java | 5 +
.../olingo/server/core/uri/UriInfoImplTest.java | 10 +-
.../core/uri/parser/ExpressionParserTest.java | 21 +-
.../core/uri/parser/UriTokenizerTest.java | 31 +-
.../server/core/uri/UriResourceImplTest.java | 156 ++-
.../core/uri/antlr/TestFullResourcePath.java | 979 +++++++++----------
.../core/uri/antlr/TestUriParserImpl.java | 36 +-
.../queryoption/expression/ExpressionTest.java | 12 +-
37 files changed, 1816 insertions(+), 1491 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/helper/ExpandTreeBuilder.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/helper/ExpandTreeBuilder.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/helper/ExpandTreeBuilder.java
index 549cf33..7577e7b 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/helper/ExpandTreeBuilder.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/helper/ExpandTreeBuilder.java
@@ -27,14 +27,8 @@ public abstract class ExpandTreeBuilder {
public abstract ExpandTreeBuilder expand(EdmNavigationProperty edmNavigationProperty);
protected ExpandItemImpl buildExpandItem(final EdmNavigationProperty edmNavigationProperty) {
- final ExpandItemImpl expandItem = new ExpandItemImpl();
- final UriInfoImpl uriInfo = new UriInfoImpl();
- final UriResourceNavigationPropertyImpl resourceNavigation = new UriResourceNavigationPropertyImpl();
-
- resourceNavigation.setNavigationProperty(edmNavigationProperty);
- uriInfo.addResourcePart(resourceNavigation);
- expandItem.setResourcePath(uriInfo);
-
- return expandItem;
+ return new ExpandItemImpl()
+ .setResourcePath(new UriInfoImpl()
+ .addResourcePart(new UriResourceNavigationPropertyImpl(edmNavigationProperty)));
}
-}
\ No newline at end of file
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceActionImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceActionImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceActionImpl.java
index 4126110..1853942 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceActionImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceActionImpl.java
@@ -31,11 +31,19 @@ import org.apache.olingo.server.api.uri.UriResourceKind;
*/
public class UriResourceActionImpl extends UriResourceImpl implements UriResourceAction {
- protected EdmAction action;
- protected EdmActionImport actionImport;
+ private final EdmActionImport actionImport;
+ private final EdmAction action;
- public UriResourceActionImpl() {
+ public UriResourceActionImpl(final EdmActionImport actionImport) {
super(UriResourceKind.action);
+ this.actionImport = actionImport;
+ this.action = actionImport.getUnboundAction();
+ }
+
+ public UriResourceActionImpl(final EdmAction action) {
+ super(UriResourceKind.action);
+ this.actionImport = null;
+ this.action = action;
}
@Override
@@ -43,38 +51,21 @@ public class UriResourceActionImpl extends UriResourceImpl implements UriResourc
return action;
}
- public UriResourceActionImpl setAction(final EdmAction action) {
- this.action = action;
- return this;
- }
-
@Override
public EdmActionImport getActionImport() {
return actionImport;
}
- public UriResourceActionImpl setActionImport(final EdmActionImport actionImport) {
- this.actionImport = actionImport;
- setAction(actionImport.getUnboundAction());
- return this;
- }
-
@Override
public boolean isCollection() {
- if (action.getReturnType() != null) {
- return action.getReturnType().isCollection();
- }
- return false;
+ return action.getReturnType() != null && action.getReturnType().isCollection();
}
@Override
public EdmType getType() {
- if (action.getReturnType() != null) {
- return action.getReturnType().getType();
- }
- return null;
+ return action.getReturnType() == null ? null : action.getReturnType().getType();
}
-
+
@Override
public String getSegmentValue(final boolean includeFilters) {
return actionImport == null ? (action == null ? "" : action.getName()) : actionImport.getName();
@@ -84,14 +75,9 @@ public class UriResourceActionImpl extends UriResourceImpl implements UriResourc
public String getSegmentValue() {
return getSegmentValue(false);
}
-
+
@Override
public String toString(final boolean includeFilters) {
return getSegmentValue(includeFilters);
}
-
- @Override
- public String toString() {
- return getSegmentValue();
- }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceComplexPropertyImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceComplexPropertyImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceComplexPropertyImpl.java
index 63db69c..9c83f24 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceComplexPropertyImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceComplexPropertyImpl.java
@@ -26,10 +26,11 @@ import org.apache.olingo.server.api.uri.UriResourceKind;
public class UriResourceComplexPropertyImpl extends UriResourceTypedImpl implements UriResourceComplexProperty {
- protected EdmProperty property;
+ private final EdmProperty property;
- public UriResourceComplexPropertyImpl() {
+ public UriResourceComplexPropertyImpl(final EdmProperty property) {
super(UriResourceKind.complexProperty);
+ this.property = property;
}
@Override
@@ -37,11 +38,6 @@ public class UriResourceComplexPropertyImpl extends UriResourceTypedImpl impleme
return property;
}
- public UriResourceComplexPropertyImpl setProperty(final EdmProperty property) {
- this.property = property;
- return this;
- }
-
@Override
public EdmComplexType getComplexType() {
return (EdmComplexType) getType();
@@ -63,13 +59,7 @@ public class UriResourceComplexPropertyImpl extends UriResourceTypedImpl impleme
}
@Override
- public String getSegmentValue(){
+ public String getSegmentValue() {
return property.getName();
}
-
- @Override
- public String toString() {
- return getSegmentValue();
- }
-
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceCountImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceCountImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceCountImpl.java
index e1859a6..90dc4f5 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceCountImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceCountImpl.java
@@ -26,15 +26,9 @@ public class UriResourceCountImpl extends UriResourceImpl implements UriResource
public UriResourceCountImpl() {
super(UriResourceKind.count);
}
-
- @Override
- public String getSegmentValue(){
- return "$count";
- }
@Override
- public String toString() {
- return getSegmentValue();
+ public String getSegmentValue() {
+ return "$count";
}
-
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceEntitySetImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceEntitySetImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceEntitySetImpl.java
index 4675964..ea21fe5 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceEntitySetImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceEntitySetImpl.java
@@ -25,10 +25,12 @@ import org.apache.olingo.server.api.uri.UriResourceEntitySet;
import org.apache.olingo.server.api.uri.UriResourceKind;
public class UriResourceEntitySetImpl extends UriResourceWithKeysImpl implements UriResourceEntitySet {
- protected EdmEntitySet edmEntitySet = null;
- public UriResourceEntitySetImpl() {
+ private final EdmEntitySet edmEntitySet;
+
+ public UriResourceEntitySetImpl(final EdmEntitySet edmEntitySet) {
super(UriResourceKind.entitySet);
+ this.edmEntitySet = edmEntitySet;
}
@Override
@@ -36,11 +38,6 @@ public class UriResourceEntitySetImpl extends UriResourceWithKeysImpl implements
return edmEntitySet;
}
- public UriResourceEntitySetImpl setEntitSet(final EdmEntitySet edmES) {
- edmEntitySet = edmES;
- return this;
- }
-
@Override
public EdmEntityType getEntityType() {
return edmEntitySet.getEntityType();
@@ -57,13 +54,7 @@ public class UriResourceEntitySetImpl extends UriResourceWithKeysImpl implements
}
@Override
- public String getSegmentValue(){
+ public String getSegmentValue() {
return edmEntitySet.getName();
}
-
-
- @Override
- public String toString() {
- return getSegmentValue();
- }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceFunctionImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceFunctionImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceFunctionImpl.java
index a47a6ab..7784062 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceFunctionImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceFunctionImpl.java
@@ -33,13 +33,16 @@ import org.apache.olingo.server.api.uri.UriResourceKind;
*/
public class UriResourceFunctionImpl extends UriResourceWithKeysImpl implements UriResourceFunction {
- protected List<UriParameter> parameters;
- protected EdmFunction function;
- protected EdmFunctionImport functionImport;
- private boolean isParameterListFilled = false;
+ private final EdmFunctionImport functionImport;
+ private final EdmFunction function;
+ private final List<UriParameter> parameters;
- public UriResourceFunctionImpl() {
+ public UriResourceFunctionImpl(final EdmFunctionImport edmFunctionImport, final EdmFunction function,
+ final List<UriParameter> parameters) {
super(UriResourceKind.function);
+ this.functionImport = edmFunctionImport;
+ this.function = function;
+ this.parameters = parameters;
}
@Override
@@ -49,34 +52,16 @@ public class UriResourceFunctionImpl extends UriResourceWithKeysImpl implements
Collections.unmodifiableList(parameters);
}
- public UriResourceFunctionImpl setParameters(final List<UriParameter> parameters) {
- isParameterListFilled = true;
- this.parameters = parameters;
- return this;
- }
-
@Override
public EdmFunction getFunction() {
return function;
}
- public UriResourceFunctionImpl setFunction(final EdmFunction function) {
- this.function = function;
- return this;
- }
-
@Override
public EdmFunctionImport getFunctionImport() {
return functionImport;
}
- public UriResourceFunctionImpl setFunctionImport(final EdmFunctionImport edmFunctionImport,
- final List<UriParameter> parameters) {
- functionImport = edmFunctionImport;
- setParameters(parameters);
- return this;
- }
-
@Override
public EdmType getType() {
return function.getReturnType().getType();
@@ -89,21 +74,6 @@ public class UriResourceFunctionImpl extends UriResourceWithKeysImpl implements
@Override
public String getSegmentValue() {
- if (functionImport != null) {
- return functionImport.getName();
- } else if (function != null) {
- return function.getName();
- }
- return "";
+ return functionImport == null ? (function == null ? "" : function.getName()) : functionImport.getName();
}
-
- @Override
- public String toString() {
- return getSegmentValue();
- }
-
- public boolean isParameterListFilled() {
- return isParameterListFilled;
- }
-
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceImpl.java
index 9fbcbd0..db991a8 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceImpl.java
@@ -22,7 +22,7 @@ import org.apache.olingo.server.api.uri.UriResource;
import org.apache.olingo.server.api.uri.UriResourceKind;
/**
- * Covers Functionimports and BoundFunction in URI
+ * Abstract class for resource-path elements in URI.
*/
public abstract class UriResourceImpl implements UriResource {
protected UriResourceKind kind;
@@ -36,4 +36,8 @@ public abstract class UriResourceImpl implements UriResource {
return kind;
}
+ @Override
+ public String toString() {
+ return getSegmentValue();
+ }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceItImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceItImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceItImpl.java
index fc31910..e7db56c 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceItImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceItImpl.java
@@ -27,11 +27,13 @@ import org.apache.olingo.server.api.uri.UriResourceKind;
*/
public class UriResourceItImpl extends UriResourceWithKeysImpl implements UriResourceIt {
- private EdmType type;
- private boolean isCollection;
+ private final EdmType type;
+ private final boolean isCollection;
- public UriResourceItImpl() {
+ public UriResourceItImpl(final EdmType type, final boolean isCollection) {
super(UriResourceKind.it);
+ this.type = type;
+ this.isCollection = isCollection;
}
@Override
@@ -39,32 +41,13 @@ public class UriResourceItImpl extends UriResourceWithKeysImpl implements UriRes
return type;
}
- public UriResourceItImpl setType(final EdmType type) {
- this.type = type;
- return this;
- }
-
@Override
public boolean isCollection() {
- if (keyPredicates != null) {
- return false;
- }
- return isCollection;
+ return keyPredicates == null && isCollection;
}
- public UriResourceItImpl setCollection(final boolean isCollection) {
- this.isCollection = isCollection;
- return this;
- }
-
@Override
- public String getSegmentValue(){
+ public String getSegmentValue() {
return "$it";
}
-
- @Override
- public String toString() {
- return getSegmentValue();
- }
-
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceLambdaAllImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceLambdaAllImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceLambdaAllImpl.java
index d980777..4f5a4fa 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceLambdaAllImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceLambdaAllImpl.java
@@ -19,7 +19,6 @@
package org.apache.olingo.server.core.uri;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
-import org.apache.olingo.commons.api.edm.EdmProperty;
import org.apache.olingo.commons.api.edm.EdmType;
import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory;
import org.apache.olingo.server.api.uri.UriResourceKind;
@@ -28,12 +27,13 @@ import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
public class UriResourceLambdaAllImpl extends UriResourceTypedImpl implements UriResourceLambdaAll {
- protected EdmProperty property;
- private String lambdaVariable;
- private Expression expression;
+ private final String lambdaVariable;
+ private final Expression expression;
- public UriResourceLambdaAllImpl() {
+ public UriResourceLambdaAllImpl(final String lambdaVariable, final Expression expression) {
super(UriResourceKind.lambdaAll);
+ this.lambdaVariable = lambdaVariable;
+ this.expression = expression;
}
@Override
@@ -51,29 +51,13 @@ public class UriResourceLambdaAllImpl extends UriResourceTypedImpl implements Ur
return lambdaVariable;
}
- public UriResourceLambdaAllImpl setLamdaVariable(final String lambdaVariable) {
- this.lambdaVariable = lambdaVariable;
- return this;
- }
-
@Override
public Expression getExpression() {
return expression;
}
- public UriResourceLambdaAllImpl setExpression(final Expression expression) {
- this.expression = expression;
- return this;
- }
-
@Override
public String getSegmentValue() {
return "all";
}
-
- @Override
- public String toString() {
- return getSegmentValue();
- }
-
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceLambdaAnyImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceLambdaAnyImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceLambdaAnyImpl.java
index fe5dfee..b586a09 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceLambdaAnyImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceLambdaAnyImpl.java
@@ -19,7 +19,6 @@
package org.apache.olingo.server.core.uri;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
-import org.apache.olingo.commons.api.edm.EdmProperty;
import org.apache.olingo.commons.api.edm.EdmType;
import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory;
import org.apache.olingo.server.api.uri.UriResourceKind;
@@ -28,12 +27,13 @@ import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
public class UriResourceLambdaAnyImpl extends UriResourceTypedImpl implements UriResourceLambdaAny {
- protected EdmProperty property;
- private String lambdaVariable;
- private Expression expression;
+ private final String lambdaVariable;
+ private final Expression expression;
- public UriResourceLambdaAnyImpl() {
+ public UriResourceLambdaAnyImpl(final String lambdaVariable, final Expression expression) {
super(UriResourceKind.lambdaAny);
+ this.lambdaVariable = lambdaVariable;
+ this.expression = expression;
}
@Override
@@ -51,28 +51,13 @@ public class UriResourceLambdaAnyImpl extends UriResourceTypedImpl implements Ur
return lambdaVariable;
}
- public UriResourceLambdaAnyImpl setLamdaVariable(final String lambdaVariable) {
- this.lambdaVariable = lambdaVariable;
- return this;
- }
-
@Override
public Expression getExpression() {
return expression;
}
- public UriResourceLambdaAnyImpl setExpression(final Expression expression) {
- this.expression = expression;
- return this;
- }
-
@Override
public String getSegmentValue() {
return "any";
}
-
- @Override
- public String toString() {
- return getSegmentValue();
- }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceLambdaVarImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceLambdaVarImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceLambdaVarImpl.java
index 2eb7607..306807a 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceLambdaVarImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceLambdaVarImpl.java
@@ -24,12 +24,13 @@ import org.apache.olingo.server.api.uri.UriResourceLambdaVariable;
public class UriResourceLambdaVarImpl extends UriResourceTypedImpl implements UriResourceLambdaVariable {
- private EdmType type;
- private boolean isCollection;
- private String variableText;
+ private final String variableText;
+ private final EdmType type;
- public UriResourceLambdaVarImpl() {
+ public UriResourceLambdaVarImpl(final String variableText, final EdmType type) {
super(UriResourceKind.lambdaVariable);
+ this.variableText = variableText;
+ this.type = type;
}
@Override
@@ -37,39 +38,18 @@ public class UriResourceLambdaVarImpl extends UriResourceTypedImpl implements Ur
return variableText;
}
- public UriResourceLambdaVarImpl setVariableText(final String variableText) {
- this.variableText = variableText;
- return this;
- }
-
@Override
public EdmType getType() {
return type;
}
- public UriResourceLambdaVarImpl setType(final EdmType type) {
- this.type = type;
- return this;
-
- }
-
@Override
public boolean isCollection() {
- return isCollection;
- }
-
- public UriResourceLambdaVarImpl setCollection(final boolean isCollection) {
- this.isCollection = isCollection;
- return this;
+ return false;
}
@Override
public String getSegmentValue() {
return variableText;
}
-
- @Override
- public String toString() {
- return getSegmentValue();
- }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceNavigationPropertyImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceNavigationPropertyImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceNavigationPropertyImpl.java
index f4390b5..1d8b321 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceNavigationPropertyImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceNavigationPropertyImpl.java
@@ -25,10 +25,11 @@ import org.apache.olingo.server.api.uri.UriResourceNavigation;
public class UriResourceNavigationPropertyImpl extends UriResourceWithKeysImpl implements UriResourceNavigation {
- protected EdmNavigationProperty navigationProperty;
+ private final EdmNavigationProperty navigationProperty;
- public UriResourceNavigationPropertyImpl() {
+ public UriResourceNavigationPropertyImpl(final EdmNavigationProperty property) {
super(UriResourceKind.navigationProperty);
+ navigationProperty = property;
}
@Override
@@ -36,12 +37,6 @@ public class UriResourceNavigationPropertyImpl extends UriResourceWithKeysImpl i
return navigationProperty;
}
- public UriResourceNavigationPropertyImpl setNavigationProperty(final EdmNavigationProperty property) {
- navigationProperty = property;
- return this;
-
- }
-
@Override
public EdmType getType() {
return navigationProperty.getType();
@@ -51,15 +46,9 @@ public class UriResourceNavigationPropertyImpl extends UriResourceWithKeysImpl i
public boolean isCollection() {
return navigationProperty.isCollection() && keyPredicates == null;
}
-
- @Override
- public String getSegmentValue(){
- return navigationProperty.getName();
- }
@Override
- public String toString() {
- return getSegmentValue();
+ public String getSegmentValue() {
+ return navigationProperty.getName();
}
-
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourcePrimitivePropertyImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourcePrimitivePropertyImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourcePrimitivePropertyImpl.java
index d470ef4..bb04142 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourcePrimitivePropertyImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourcePrimitivePropertyImpl.java
@@ -25,10 +25,11 @@ import org.apache.olingo.server.api.uri.UriResourcePrimitiveProperty;
public class UriResourcePrimitivePropertyImpl extends UriResourceTypedImpl implements UriResourcePrimitiveProperty {
- EdmProperty property;
+ private final EdmProperty property;
- public UriResourcePrimitivePropertyImpl() {
+ public UriResourcePrimitivePropertyImpl(final EdmProperty property) {
super(UriResourceKind.primitiveProperty);
+ this.property = property;
}
@Override
@@ -36,11 +37,6 @@ public class UriResourcePrimitivePropertyImpl extends UriResourceTypedImpl imple
return property;
}
- public UriResourcePrimitivePropertyImpl setProperty(final EdmProperty property) {
- this.property = property;
- return this;
- }
-
@Override
public EdmType getType() {
return property.getType();
@@ -50,15 +46,9 @@ public class UriResourcePrimitivePropertyImpl extends UriResourceTypedImpl imple
public boolean isCollection() {
return property.isCollection();
}
-
- @Override
- public String getSegmentValue(){
- return property.getName();
- }
@Override
- public String toString() {
- return getSegmentValue();
+ public String getSegmentValue() {
+ return property.getName();
}
-
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceRefImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceRefImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceRefImpl.java
index 0c45f9a..6f01936 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceRefImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceRefImpl.java
@@ -25,16 +25,10 @@ public class UriResourceRefImpl extends UriResourceImpl implements UriResourceRe
public UriResourceRefImpl() {
super(UriResourceKind.ref);
-
- }
- @Override
- public String getSegmentValue(){
- return "$ref";
}
@Override
- public String toString() {
- return getSegmentValue();
+ public String getSegmentValue() {
+ return "$ref";
}
-
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceRootImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceRootImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceRootImpl.java
index 5d8737f..761899f 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceRootImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceRootImpl.java
@@ -24,11 +24,13 @@ import org.apache.olingo.server.api.uri.UriResourceRoot;
public class UriResourceRootImpl extends UriResourceWithKeysImpl implements UriResourceRoot {
- private EdmType type;
- private boolean isCollection;
+ private final EdmType type;
+ private final boolean isCollection;
- public UriResourceRootImpl() {
+ public UriResourceRootImpl(final EdmType type, final boolean isCollection) {
super(UriResourceKind.root);
+ this.type = type;
+ this.isCollection = isCollection;
}
@Override
@@ -36,32 +38,13 @@ public class UriResourceRootImpl extends UriResourceWithKeysImpl implements UriR
return type;
}
- public UriResourceRootImpl setType(final EdmType type) {
- this.type = type;
- return this;
- }
-
@Override
public boolean isCollection() {
- if (keyPredicates != null) {
- return false;
- }
- return isCollection;
+ return keyPredicates == null && isCollection;
}
- public UriResourceRootImpl setCollection(final boolean isCollection) {
- this.isCollection = isCollection;
- return this;
- }
-
@Override
- public String getSegmentValue(){
+ public String getSegmentValue() {
return "$root";
}
-
- @Override
- public String toString() {
- return getSegmentValue();
- }
-
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceSingletonImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceSingletonImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceSingletonImpl.java
index 72289f6..381a518 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceSingletonImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceSingletonImpl.java
@@ -26,10 +26,11 @@ import org.apache.olingo.server.api.uri.UriResourceSingleton;
public class UriResourceSingletonImpl extends UriResourceTypedImpl implements UriResourceSingleton {
- private EdmSingleton singleton;
+ private final EdmSingleton singleton;
- public UriResourceSingletonImpl() {
+ public UriResourceSingletonImpl(final EdmSingleton singleton) {
super(UriResourceKind.singleton);
+ this.singleton = singleton;
}
@Override
@@ -37,12 +38,6 @@ public class UriResourceSingletonImpl extends UriResourceTypedImpl implements Ur
return singleton;
}
- public UriResourceSingletonImpl setSingleton(final EdmSingleton singleton) {
-
- this.singleton = singleton;
- return this;
- }
-
@Override
public EdmEntityType getEntityTypeFilter() {
return (EdmEntityType) typeFilter;
@@ -62,15 +57,9 @@ public class UriResourceSingletonImpl extends UriResourceTypedImpl implements Ur
public boolean isCollection() {
return false;
}
-
- @Override
- public String getSegmentValue(){
- return singleton.getName();
- }
@Override
- public String toString() {
- return getSegmentValue();
+ public String getSegmentValue() {
+ return singleton.getName();
}
-
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceStartingTypeFilterImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceStartingTypeFilterImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceStartingTypeFilterImpl.java
index 24d3713..09af068 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceStartingTypeFilterImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceStartingTypeFilterImpl.java
@@ -23,11 +23,13 @@ import org.apache.olingo.server.api.uri.UriResourceKind;
public class UriResourceStartingTypeFilterImpl extends UriResourceWithKeysImpl {
- private EdmType type;
- private boolean isCollection;
+ private final EdmType type;
+ private final boolean isCollection;
- public UriResourceStartingTypeFilterImpl() {
+ public UriResourceStartingTypeFilterImpl(final EdmType type, final boolean isCollection) {
super(null);
+ this.type = type;
+ this.isCollection = isCollection;
}
@Override
@@ -40,32 +42,13 @@ public class UriResourceStartingTypeFilterImpl extends UriResourceWithKeysImpl {
return type;
}
- public UriResourceStartingTypeFilterImpl setType(final EdmType type) {
- this.type = type;
- return this;
- }
-
@Override
public boolean isCollection() {
- if (keyPredicates != null) {
- return false;
- }
- return isCollection;
- }
-
- public UriResourceStartingTypeFilterImpl setCollection(final boolean isCollection) {
- this.isCollection = isCollection;
- return this;
+ return keyPredicates == null && isCollection;
}
@Override
- public String getSegmentValue(){
- return type.getNamespace() + "." + type.getName();
+ public String getSegmentValue() {
+ return type.getFullQualifiedName().getFullQualifiedNameAsString();
}
-
- @Override
- public String toString() {
- return getSegmentValue();
- }
-
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceTypedImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceTypedImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceTypedImpl.java
index d6710ad..9930a7e 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceTypedImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceTypedImpl.java
@@ -41,14 +41,9 @@ public abstract class UriResourceTypedImpl extends UriResourceImpl implements Ur
}
public String getSegmentValue(final boolean includeFilters) {
- if (includeFilters) {
- if (typeFilter != null) {
- return getSegmentValue() + "/" + typeFilter.getFullQualifiedName().toString();
- } else {
- return getSegmentValue();
- }
- }
- return getSegmentValue();
+ return includeFilters && typeFilter != null ?
+ getSegmentValue() + "/" + typeFilter.getFullQualifiedName().getFullQualifiedNameAsString() :
+ getSegmentValue();
}
@Override
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceValueImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceValueImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceValueImpl.java
index 73f86c4..d2b70d5 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceValueImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceValueImpl.java
@@ -25,17 +25,10 @@ public class UriResourceValueImpl extends UriResourceImpl implements UriResource
public UriResourceValueImpl() {
super(UriResourceKind.value);
-
}
@Override
- public String getSegmentValue(){
+ public String getSegmentValue() {
return "$value";
}
-
- @Override
- public String toString() {
- return getSegmentValue();
- }
-
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java
index 61c023d..2f7fdb2 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java
@@ -18,20 +18,41 @@
*/
package org.apache.olingo.server.core.uri.parser;
+import java.util.ArrayDeque;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
+import java.util.Deque;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.olingo.commons.api.edm.Edm;
+import org.apache.olingo.commons.api.edm.EdmComplexType;
+import org.apache.olingo.commons.api.edm.EdmElement;
+import org.apache.olingo.commons.api.edm.EdmEntitySet;
+import org.apache.olingo.commons.api.edm.EdmEntityType;
+import org.apache.olingo.commons.api.edm.EdmEnumType;
+import org.apache.olingo.commons.api.edm.EdmFunction;
+import org.apache.olingo.commons.api.edm.EdmNavigationProperty;
import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
+import org.apache.olingo.commons.api.edm.EdmProperty;
+import org.apache.olingo.commons.api.edm.EdmReturnType;
+import org.apache.olingo.commons.api.edm.EdmSingleton;
+import org.apache.olingo.commons.api.edm.EdmStructuredType;
import org.apache.olingo.commons.api.edm.EdmType;
import org.apache.olingo.commons.api.edm.EdmTypeDefinition;
import org.apache.olingo.commons.api.edm.FullQualifiedName;
import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
import org.apache.olingo.server.api.OData;
+import org.apache.olingo.server.api.uri.UriParameter;
+import org.apache.olingo.server.api.uri.UriResourceFunction;
+import org.apache.olingo.server.api.uri.UriResourceLambdaVariable;
+import org.apache.olingo.server.api.uri.UriResourceNavigation;
+import org.apache.olingo.server.api.uri.UriResourcePartTyped;
import org.apache.olingo.server.api.uri.queryoption.expression.Alias;
import org.apache.olingo.server.api.uri.queryoption.expression.Binary;
import org.apache.olingo.server.api.uri.queryoption.expression.BinaryOperatorKind;
@@ -45,12 +66,32 @@ import org.apache.olingo.server.api.uri.queryoption.expression.MethodKind;
import org.apache.olingo.server.api.uri.queryoption.expression.TypeLiteral;
import org.apache.olingo.server.api.uri.queryoption.expression.Unary;
import org.apache.olingo.server.api.uri.queryoption.expression.UnaryOperatorKind;
+import org.apache.olingo.server.core.uri.UriInfoImpl;
+import org.apache.olingo.server.core.uri.UriResourceComplexPropertyImpl;
+import org.apache.olingo.server.core.uri.UriResourceCountImpl;
+import org.apache.olingo.server.core.uri.UriResourceEntitySetImpl;
+import org.apache.olingo.server.core.uri.UriResourceFunctionImpl;
+import org.apache.olingo.server.core.uri.UriResourceItImpl;
+import org.apache.olingo.server.core.uri.UriResourceLambdaAllImpl;
+import org.apache.olingo.server.core.uri.UriResourceLambdaAnyImpl;
+import org.apache.olingo.server.core.uri.UriResourceLambdaVarImpl;
+import org.apache.olingo.server.core.uri.UriResourceNavigationPropertyImpl;
+import org.apache.olingo.server.core.uri.UriResourcePrimitivePropertyImpl;
+import org.apache.olingo.server.core.uri.UriResourceRootImpl;
+import org.apache.olingo.server.core.uri.UriResourceSingletonImpl;
+import org.apache.olingo.server.core.uri.UriResourceStartingTypeFilterImpl;
+import org.apache.olingo.server.core.uri.UriResourceTypedImpl;
+import org.apache.olingo.server.core.uri.UriResourceWithKeysImpl;
import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind;
import org.apache.olingo.server.core.uri.queryoption.expression.AliasImpl;
import org.apache.olingo.server.core.uri.queryoption.expression.BinaryImpl;
+import org.apache.olingo.server.core.uri.queryoption.expression.EnumerationImpl;
import org.apache.olingo.server.core.uri.queryoption.expression.LiteralImpl;
+import org.apache.olingo.server.core.uri.queryoption.expression.MemberImpl;
import org.apache.olingo.server.core.uri.queryoption.expression.MethodImpl;
+import org.apache.olingo.server.core.uri.queryoption.expression.TypeLiteralImpl;
import org.apache.olingo.server.core.uri.queryoption.expression.UnaryImpl;
+import org.apache.olingo.server.core.uri.validator.UriValidationException;
public class ExpressionParser {
private static final Map<TokenKind, BinaryOperatorKind> tokenToBinaryOperator;
@@ -129,7 +170,7 @@ public class ExpressionParser {
Map<TokenKind, EdmPrimitiveTypeKind> temp = new HashMap<TokenKind, EdmPrimitiveTypeKind>();
temp.put(TokenKind.BooleanValue, EdmPrimitiveTypeKind.Boolean);
temp.put(TokenKind.StringValue, EdmPrimitiveTypeKind.String);
- // TODO:Check if int64 is correct here or if it has to be single instead
+ // TODO: Check if int64 is correct here or if it has to be decimal or single or double instead.
temp.put(TokenKind.IntegerValue, EdmPrimitiveTypeKind.Int64);
temp.put(TokenKind.GuidValue, EdmPrimitiveTypeKind.Guid);
temp.put(TokenKind.DateValue, EdmPrimitiveTypeKind.Date);
@@ -147,20 +188,27 @@ public class ExpressionParser {
private final OData odata;
private UriTokenizer tokenizer;
+ private Deque<UriResourceLambdaVariable> lambdaVariables = new ArrayDeque<UriResourceLambdaVariable>();
+ private EdmType referringType;
+ private Collection<String> crossjoinEntitySetNames;
public ExpressionParser(final Edm edm, final OData odata) {
this.edm = edm;
this.odata = odata;
}
- public Expression parse(UriTokenizer tokenizer) throws UriParserException {
+ public Expression parse(UriTokenizer tokenizer, final EdmType referringType,
+ final Collection<String> crossjoinEntitySetNames)
+ throws UriParserException, UriValidationException {
// Initialize tokenizer.
this.tokenizer = tokenizer;
+ this.referringType = referringType;
+ this.crossjoinEntitySetNames = crossjoinEntitySetNames;
return parseExpression();
}
- private Expression parseExpression() throws UriParserException {
+ private Expression parseExpression() throws UriParserException, UriValidationException {
Expression left = parseAnd();
while (tokenizer.next(TokenKind.OrOperator)) {
final Expression right = parseAnd();
@@ -172,7 +220,7 @@ public class ExpressionParser {
return left;
}
- private Expression parseAnd() throws UriParserException {
+ private Expression parseAnd() throws UriParserException, UriValidationException {
Expression left = parseExprEquality();
while (tokenizer.next(TokenKind.AndOperator)) {
final Expression right = parseExprEquality();
@@ -184,7 +232,7 @@ public class ExpressionParser {
return left;
}
- private Expression parseExprEquality() throws UriParserException {
+ private Expression parseExprEquality() throws UriParserException, UriValidationException {
Expression left = parseExprRel();
TokenKind operatorTokenKind = ParserHelper.next(tokenizer, TokenKind.EqualsOperator, TokenKind.NotEqualsOperator);
// Null for everything other than EQ or NE
@@ -199,7 +247,7 @@ public class ExpressionParser {
}
// TODO: The 'isof' method has relational precedence and should appear here.
- private Expression parseExprRel() throws UriParserException {
+ private Expression parseExprRel() throws UriParserException, UriValidationException {
Expression left = parseExprAdd();
TokenKind operatorTokenKind = ParserHelper.next(tokenizer,
TokenKind.GreaterThanOperator, TokenKind.GreaterThanOrEqualsOperator,
@@ -217,7 +265,7 @@ public class ExpressionParser {
return left;
}
- private Expression parseExprAdd() throws UriParserException {
+ private Expression parseExprAdd() throws UriParserException, UriValidationException {
Expression left = parseExprMul();
TokenKind operatorTokenKind = ParserHelper.next(tokenizer, TokenKind.AddOperator, TokenKind.SubOperator);
// Null for everything other than ADD or SUB
@@ -231,7 +279,7 @@ public class ExpressionParser {
return left;
}
- private Expression parseExprMul() throws UriParserException {
+ private Expression parseExprMul() throws UriParserException, UriValidationException {
Expression left = parseExprUnary();
TokenKind operatorTokenKind = ParserHelper.next(tokenizer,
TokenKind.MulOperator, TokenKind.DivOperator, TokenKind.ModOperator);
@@ -255,7 +303,22 @@ public class ExpressionParser {
}
// TODO: The 'cast' method has unary precedence and should appear here.
- private Expression parseExprUnary() throws UriParserException {
+ private Expression parseExprUnary() throws UriParserException, UriValidationException {
+ // Negative numbers start with a minus indistinguishable from an unary minus operator.
+ // So we read numbers (and primitive values starting with numbers) right here.
+ // TODO: Find a better idea how to solve this problem.
+ final TokenKind numberTokenKind = ParserHelper.next(tokenizer,
+ TokenKind.DoubleValue, TokenKind.DecimalValue, TokenKind.GuidValue,
+ TokenKind.DateTimeOffsetValue, TokenKind.DateValue, TokenKind.TimeOfDayValue,
+ TokenKind.IntegerValue);
+ if (numberTokenKind != null) {
+ final EdmPrimitiveTypeKind primitiveTypeKind = tokenToPrimitiveType.get(numberTokenKind);
+ final EdmPrimitiveType type = primitiveTypeKind == null ?
+ // Null handling
+ null :
+ odata.createPrimitiveTypeInstance(primitiveTypeKind);
+ return new LiteralImpl(tokenizer.getText(), type);
+ }
Expression left = null;
TokenKind operatorTokenKind = ParserHelper.next(tokenizer, TokenKind.MINUS, TokenKind.NotOperator);
// Null for everything other than - or NOT
@@ -279,13 +342,11 @@ public class ExpressionParser {
return left;
}
- private Expression parseExprPrimary() throws UriParserException {
+ private Expression parseExprPrimary() throws UriParserException, UriValidationException {
final Expression left = parseExprValue();
if (isEnumType(left) && tokenizer.next(TokenKind.HasOperator)) {
ParserHelper.requireNext(tokenizer, TokenKind.EnumValue);
- final String primitiveValueLiteral = tokenizer.getText();
- final Expression right = new LiteralImpl(primitiveValueLiteral, getEnumType(primitiveValueLiteral));
- checkEnumLiteral(right);
+ final Expression right = createEnumExpression(tokenizer.getText());
return new BinaryImpl(left, BinaryOperatorKind.HAS, right,
odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Boolean));
} else {
@@ -293,7 +354,7 @@ public class ExpressionParser {
}
}
- private Expression parseExprValue() throws UriParserException {
+ private Expression parseExprValue() throws UriParserException, UriValidationException {
if (tokenizer.next(TokenKind.OPEN)) {
final Expression expression = parseExpression();
ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
@@ -310,51 +371,49 @@ public class ExpressionParser {
}
if (tokenizer.next(TokenKind.ROOT)) {
- // TODO: Consume $root expression.
+ return parseFirstMemberExpr(TokenKind.ROOT);
}
if (tokenizer.next(TokenKind.IT)) {
- // TODO: Consume $it expression.
+ return parseFirstMemberExpr(TokenKind.IT);
}
- TokenKind nextPrimitive = ParserHelper.nextPrimitive(tokenizer);
+ final TokenKind nextPrimitive = ParserHelper.nextPrimitiveValue(tokenizer);
if (nextPrimitive != null) {
final String primitiveValueLiteral = tokenizer.getText();
- final EdmPrimitiveTypeKind primitiveTypeKind = tokenToPrimitiveType.get(nextPrimitive);
- EdmPrimitiveType type;
- if (primitiveTypeKind == null) {
- if (nextPrimitive == TokenKind.EnumValue) {
- type = getEnumType(primitiveValueLiteral);
- } else {
- // Null handling
- type = null;
- }
+ if (nextPrimitive == TokenKind.EnumValue) {
+ return createEnumExpression(primitiveValueLiteral);
} else {
- type = odata.createPrimitiveTypeInstance(primitiveTypeKind);
+ final EdmPrimitiveTypeKind primitiveTypeKind = tokenToPrimitiveType.get(nextPrimitive);
+ final EdmPrimitiveType type = primitiveTypeKind == null ?
+ // Null handling
+ null :
+ odata.createPrimitiveTypeInstance(primitiveTypeKind);
+ return new LiteralImpl(primitiveValueLiteral, type);
}
- return new LiteralImpl(primitiveValueLiteral, type);
}
// The method token text includes the opening parenthesis so that method calls can be recognized unambiguously.
// OData identifiers have to be considered after that.
- TokenKind nextMethod = nextMethod();
+ final TokenKind nextMethod = nextMethod();
if (nextMethod != null) {
MethodKind methodKind = tokenToMethod.get(nextMethod);
return new MethodImpl(methodKind, parseMethodParameters(methodKind));
}
if (tokenizer.next(TokenKind.QualifiedName)) {
- // TODO: Consume typecast or bound-function expression.
+ return parseFirstMemberExpr(TokenKind.QualifiedName);
}
if (tokenizer.next(TokenKind.ODataIdentifier)) {
- // TODO: Consume property-path or lambda-variable expression.
+ return parseFirstMemberExpr(TokenKind.ODataIdentifier);
}
- throw new UriParserSyntaxException("Unexpected token", UriParserSyntaxException.MessageKeys.SYNTAX);
+ throw new UriParserSyntaxException("Unexpected token.", UriParserSyntaxException.MessageKeys.SYNTAX);
}
- private List<Expression> parseMethodParameters(final MethodKind methodKind) throws UriParserException {
+ private List<Expression> parseMethodParameters(final MethodKind methodKind)
+ throws UriParserException, UriValidationException {
List<Expression> parameters = new ArrayList<Expression>();
switch (methodKind) {
// Must have no parameter.
@@ -477,6 +536,411 @@ public class ExpressionParser {
return parameters;
}
+ private Expression parseFirstMemberExpr(final TokenKind lastTokenKind)
+ throws UriParserException, UriValidationException {
+
+ final UriInfoImpl uriInfo = new UriInfoImpl();
+ EdmType startTypeFilter = null;
+
+ if (lastTokenKind == TokenKind.ROOT) {
+ parseDollarRoot(uriInfo);
+ } else if (lastTokenKind == TokenKind.IT) {
+ parseDollarIt(uriInfo);
+ } else if (lastTokenKind == TokenKind.ODataIdentifier) {
+ parseFirstMemberODataIdentifier(uriInfo);
+ } else if (lastTokenKind == TokenKind.QualifiedName) {
+ // Special handling for leading type casts and type literals
+ final FullQualifiedName fullQualifiedName = new FullQualifiedName(tokenizer.getText());
+ EdmStructuredType structuredType = edm.getEntityType(fullQualifiedName);
+ if (structuredType == null) {
+ structuredType = edm.getComplexType(fullQualifiedName);
+ }
+
+ if (structuredType != null) {
+ if (tokenizer.next(TokenKind.SLASH)) {
+ // Leading type cast
+ checkStructuredTypeFilter(referringType, structuredType);
+ startTypeFilter = structuredType;
+
+ final TokenKind tokenKind = ParserHelper.next(tokenizer, TokenKind.QualifiedName, TokenKind.ODataIdentifier);
+ parseMemberExpression(tokenKind, uriInfo, new UriResourceStartingTypeFilterImpl(structuredType, false),
+ false);
+ } else {
+ // Type literal
+ checkStructuredTypeFilter(referringType, structuredType);
+ return new TypeLiteralImpl(structuredType);
+ }
+ } else {
+ // Must be bound or unbound function. // TODO: Is unbound function allowed?
+ parseFunction(fullQualifiedName, uriInfo, referringType, true);
+ }
+ }
+
+ return new MemberImpl(uriInfo, startTypeFilter);
+ }
+
+ private void parseDollarRoot(UriInfoImpl uriInfo) throws UriParserException, UriValidationException {
+ UriResourceRootImpl rootResource = new UriResourceRootImpl(referringType, true);
+ uriInfo.addResourcePart(rootResource);
+ ParserHelper.requireNext(tokenizer, TokenKind.SLASH);
+ ParserHelper.requireNext(tokenizer, TokenKind.ODataIdentifier);
+ final String name = tokenizer.getText();
+ UriResourcePartTyped resource = null;
+ final EdmEntitySet entitySet = edm.getEntityContainer().getEntitySet(name);
+ if (entitySet == null) {
+ final EdmSingleton singleton = edm.getEntityContainer().getSingleton(name);
+ if (singleton == null) {
+ throw new UriParserSemanticException("EntitySet or singleton expected.",
+ UriParserSemanticException.MessageKeys.UNKNOWN_PART, name);
+ } else {
+ resource = new UriResourceSingletonImpl(singleton);
+ }
+ } else {
+ ParserHelper.requireNext(tokenizer, TokenKind.OPEN);
+ final List<UriParameter> keyPredicates =
+ ParserHelper.parseKeyPredicate(tokenizer, entitySet.getEntityType(), null);
+ resource = new UriResourceEntitySetImpl(entitySet).setKeyPredicates(keyPredicates);
+ }
+ uriInfo.addResourcePart(resource);
+ parseSingleNavigationExpr(uriInfo, resource);
+ }
+
+ private void parseDollarIt(UriInfoImpl uriInfo) throws UriParserException, UriValidationException {
+ UriResourceItImpl itResource = new UriResourceItImpl(referringType,
+ referringType instanceof EdmEntityType); // TODO: Determine isCollection.
+ uriInfo.addResourcePart(itResource);
+ if (tokenizer.next(TokenKind.SLASH)) {
+ final TokenKind tokenKind = ParserHelper.next(tokenizer, TokenKind.QualifiedName, TokenKind.ODataIdentifier);
+ parseMemberExpression(tokenKind, uriInfo, itResource, true);
+ }
+ }
+
+ private void parseFirstMemberODataIdentifier(UriInfoImpl uriInfo) throws UriParserException, UriValidationException {
+ final String name = tokenizer.getText();
+
+ // For a crossjoin, the identifier must be an entity-set name.
+ if (crossjoinEntitySetNames != null && !crossjoinEntitySetNames.isEmpty()) {
+ if (crossjoinEntitySetNames.contains(name)) {
+ final UriResourceEntitySetImpl resource =
+ new UriResourceEntitySetImpl(edm.getEntityContainer().getEntitySet(name));
+ uriInfo.addResourcePart(resource);
+ if (tokenizer.next(TokenKind.SLASH)) {
+ final TokenKind tokenKind = ParserHelper.next(tokenizer, TokenKind.QualifiedName, TokenKind.ODataIdentifier);
+ parseMemberExpression(tokenKind, uriInfo, resource, true);
+ }
+ return;
+ } else {
+ throw new UriParserSemanticException("Unknown crossjoin entity set.",
+ UriParserSemanticException.MessageKeys.UNKNOWN_PART, name);
+ }
+ }
+
+ // Check if the OData identifier is a lambda variable, otherwise it must be a property.
+ UriResourceLambdaVariable lambdaVariable = null;
+ for (final UriResourceLambdaVariable variable : lambdaVariables) {
+ if (variable.getVariableName().equals(name)) {
+ lambdaVariable = variable;
+ break;
+ }
+ }
+ if (lambdaVariable != null) {
+ // Copy lambda variable into new resource, just in case ...
+ final UriResourceLambdaVariable lambdaResource =
+ new UriResourceLambdaVarImpl(lambdaVariable.getVariableName(), lambdaVariable.getType());
+ uriInfo.addResourcePart(lambdaResource);
+ if (tokenizer.next(TokenKind.SLASH)) {
+ final TokenKind tokenKind = ParserHelper.next(tokenizer, TokenKind.QualifiedName, TokenKind.ODataIdentifier);
+ parseMemberExpression(tokenKind, uriInfo, lambdaResource, true);
+ }
+ } else {
+ // Must be a property.
+ parseMemberExpression(TokenKind.ODataIdentifier, uriInfo, null, true); // TODO: Find last resource.
+ }
+ }
+
+ private void parseMemberExpression(final TokenKind lastTokenKind, UriInfoImpl uriInfo,
+ final UriResourcePartTyped lastResource, final boolean allowTypeFilter)
+ throws UriParserException, UriValidationException {
+
+ if (lastTokenKind == TokenKind.QualifiedName) {
+ // Type cast or bound function
+ final FullQualifiedName fullQualifiedName = new FullQualifiedName(tokenizer.getText());
+ final EdmEntityType edmEntityType = edm.getEntityType(fullQualifiedName);
+
+ if (edmEntityType != null) {
+ if (allowTypeFilter) {
+ setTypeFilter(lastResource, edmEntityType);
+ } else {
+ throw new UriParserSemanticException("Type filters are not chainable.",
+ UriParserSemanticException.MessageKeys.TYPE_FILTER_NOT_CHAINABLE,
+ lastResource.getType().getFullQualifiedName().getFullQualifiedNameAsString(),
+ fullQualifiedName.getFullQualifiedNameAsString());
+ }
+ } else {
+ parseBoundFunction(fullQualifiedName, uriInfo, lastResource);
+ }
+ } else if (lastTokenKind == TokenKind.ODataIdentifier) {
+ parsePropertyPathExpr(uriInfo, lastResource);
+ } else {
+ throw new UriParserSyntaxException("Unexpected token.", UriParserSyntaxException.MessageKeys.SYNTAX);
+ }
+ }
+
+ private void setTypeFilter(UriResourcePartTyped lastResource, final EdmEntityType entityTypeFilter)
+ throws UriParserException {
+ checkStructuredTypeFilter(lastResource.getType(), entityTypeFilter);
+ if (lastResource instanceof UriResourceTypedImpl) {
+ ((UriResourceTypedImpl) lastResource).setTypeFilter(entityTypeFilter);
+ } else if (lastResource instanceof UriResourceWithKeysImpl) {
+ ((UriResourceWithKeysImpl) lastResource).setEntryTypeFilter(entityTypeFilter);
+ }
+ }
+
+ private void parsePropertyPathExpr(UriInfoImpl uriInfo, final UriResourcePartTyped lastResource)
+ throws UriParserException, UriValidationException {
+
+ final String oDataIdentifier = tokenizer.getText();
+
+ final EdmType lastType = lastResource == null ? referringType : ParserHelper.getTypeInformation(lastResource);
+ if (!(lastType instanceof EdmStructuredType)) {
+ throw new UriParserSemanticException("Property paths must follow a structured type.",
+ UriParserSemanticException.MessageKeys.ONLY_FOR_STRUCTURAL_TYPES, oDataIdentifier);
+ }
+
+ final EdmStructuredType structuredType = (EdmStructuredType) lastType;
+ final EdmElement property = structuredType.getProperty(oDataIdentifier);
+
+ if (property == null) {
+ throw new UriParserSemanticException("Unknown property.",
+ UriParserSemanticException.MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE, oDataIdentifier);
+ }
+
+ if (property.getType() instanceof EdmComplexType) {
+ final UriResourceComplexPropertyImpl complexResource =
+ new UriResourceComplexPropertyImpl((EdmProperty) property);
+ uriInfo.addResourcePart(complexResource);
+
+ if (property.isCollection()) {
+ parseCollectionPathExpr(uriInfo, complexResource);
+ } else {
+ parseComplexPathExpr(uriInfo, complexResource);
+ }
+ } else if (property instanceof EdmNavigationProperty) {
+ // Nav. property; maybe a collection
+ final UriResourceNavigationPropertyImpl navigationResource =
+ new UriResourceNavigationPropertyImpl((EdmNavigationProperty) property);
+ navigationResource.setKeyPredicates(
+ ParserHelper.parseNavigationKeyPredicate(tokenizer, (EdmNavigationProperty) property));
+ uriInfo.addResourcePart(navigationResource);
+
+ if (navigationResource.isCollection()) {
+ parseCollectionNavigationExpr(uriInfo, navigationResource);
+ } else {
+ parseSingleNavigationExpr(uriInfo, navigationResource);
+ }
+ } else {
+ // Primitive type or Enum type
+ final UriResourcePrimitivePropertyImpl primitiveResource =
+ new UriResourcePrimitivePropertyImpl((EdmProperty) property);
+ uriInfo.addResourcePart(primitiveResource);
+
+ if (property.isCollection()) {
+ parseCollectionPathExpr(uriInfo, primitiveResource);
+ } else {
+ parseSinglePathExpr(uriInfo, primitiveResource);
+ }
+ }
+ }
+
+ private void parseSingleNavigationExpr(UriInfoImpl uriInfo, final UriResourcePartTyped lastResource)
+ throws UriParserException, UriValidationException {
+ // TODO: Is that correct?
+ if (tokenizer.next(TokenKind.SLASH)) {
+ final TokenKind tokenKind = ParserHelper.next(tokenizer, TokenKind.QualifiedName, TokenKind.ODataIdentifier);
+ parseMemberExpression(tokenKind, uriInfo, lastResource, true);
+ }
+ }
+
+ private void parseCollectionNavigationExpr(UriInfoImpl uriInfo, UriResourcePartTyped lastResource)
+ throws UriParserException, UriValidationException {
+ // TODO: Is type cast missing?
+ if (tokenizer.next(TokenKind.OPEN)) {
+ if (lastResource instanceof UriResourceNavigation) {
+ ((UriResourceNavigationPropertyImpl) lastResource).setKeyPredicates(
+ ParserHelper.parseNavigationKeyPredicate(tokenizer,
+ ((UriResourceNavigationPropertyImpl) lastResource).getProperty()));
+ } else if (lastResource instanceof UriResourceFunction
+ && ((UriResourceFunction) lastResource).getType() instanceof EdmEntityType) {
+ ((UriResourceFunctionImpl) lastResource).setKeyPredicates(
+ ParserHelper.parseKeyPredicate(tokenizer,
+ (EdmEntityType) ((UriResourceFunction) lastResource).getType(),
+ null));
+ } else {
+ throw new UriParserSemanticException("Unknown or wrong resource type.",
+ UriParserSemanticException.MessageKeys.NOT_IMPLEMENTED, lastResource.toString());
+ }
+ parseSingleNavigationExpr(uriInfo, lastResource);
+ }
+ parseCollectionPathExpr(uriInfo, lastResource);
+ }
+
+ private void parseSinglePathExpr(UriInfoImpl uriInfo, final UriResourcePartTyped lastResource)
+ throws UriParserException, UriValidationException {
+ if (tokenizer.next(TokenKind.SLASH)) {
+ ParserHelper.requireNext(tokenizer, TokenKind.QualifiedName);
+ parseBoundFunction(new FullQualifiedName(tokenizer.getText()), uriInfo, lastResource);
+ }
+ }
+
+ private void parseComplexPathExpr(UriInfoImpl uriInfo, final UriResourcePartTyped lastResource)
+ throws UriParserException, UriValidationException {
+
+ if (tokenizer.next(TokenKind.SLASH)) {
+ if (tokenizer.next(TokenKind.QualifiedName)) {
+ final FullQualifiedName fullQualifiedName = new FullQualifiedName(tokenizer.getText());
+ final EdmEntityType edmEntityType = edm.getEntityType(fullQualifiedName);
+
+ if (edmEntityType != null) {
+ setTypeFilter(lastResource, edmEntityType);
+ if (tokenizer.next(TokenKind.SLASH)) {
+ parseComplexPathRestExpr(uriInfo, lastResource);
+ }
+ } else {
+ // Must be a bound function.
+ parseBoundFunction(fullQualifiedName, uriInfo, lastResource);
+ }
+ } else {
+ parseComplexPathRestExpr(uriInfo, lastResource);
+ }
+ }
+ }
+
+ private void parseComplexPathRestExpr(UriInfoImpl uriInfo, final UriResourcePartTyped lastResource)
+ throws UriParserException, UriValidationException {
+ if (tokenizer.next(TokenKind.QualifiedName)) {
+ final FullQualifiedName fullQualifiedName = new FullQualifiedName(tokenizer.getText());
+ // Must be a bound function.
+ parseBoundFunction(fullQualifiedName, uriInfo, lastResource);
+ } else if (tokenizer.next(TokenKind.ODataIdentifier)) {
+ parsePropertyPathExpr(uriInfo, lastResource);
+ } else {
+ throw new UriParserSyntaxException("Unexpected token.", UriParserSyntaxException.MessageKeys.SYNTAX);
+ }
+ }
+
+ private void parseCollectionPathExpr(UriInfoImpl uriInfo, final UriResourcePartTyped lastResource)
+ throws UriParserException, UriValidationException {
+
+ if (tokenizer.next(TokenKind.SLASH)) {
+ if (tokenizer.next(TokenKind.COUNT)) {
+ uriInfo.addResourcePart(new UriResourceCountImpl());
+ } else if (tokenizer.next(TokenKind.ANY)) {
+ uriInfo.addResourcePart(parseLambdaRest(TokenKind.ANY, lastResource));
+ } else if (tokenizer.next(TokenKind.ALL)) {
+ uriInfo.addResourcePart(parseLambdaRest(TokenKind.ALL, lastResource));
+ } else if (tokenizer.next(TokenKind.QualifiedName)) {
+ final FullQualifiedName fullQualifiedName = new FullQualifiedName(tokenizer.getText());
+ parseBoundFunction(fullQualifiedName, uriInfo, lastResource);
+ }
+ }
+ }
+
+ private void parseFunction(final FullQualifiedName fullQualifiedName, UriInfoImpl uriInfo,
+ final EdmType lastType, final boolean lastIsCollection) throws UriParserException, UriValidationException {
+
+ final List<UriParameter> parameters = ParserHelper.parseFunctionParameters(tokenizer, true);
+ final List<String> parameterNames = ParserHelper.getParameterNames(parameters);
+ final EdmFunction boundFunction = edm.getBoundFunction(fullQualifiedName,
+ lastType.getFullQualifiedName(), lastIsCollection, parameterNames);
+
+ if (boundFunction != null) {
+ parseFunctionRest(uriInfo, boundFunction, parameters);
+ return;
+ }
+
+ final EdmFunction unboundFunction = edm.getUnboundFunction(fullQualifiedName, parameterNames);
+ if (unboundFunction != null) {
+ parseFunctionRest(uriInfo, unboundFunction, parameters);
+ return;
+ }
+
+ throw new UriParserSemanticException("No function found.",
+ UriParserSemanticException.MessageKeys.FUNCTION_NOT_FOUND, fullQualifiedName.getFullQualifiedNameAsString());
+ }
+
+ private void parseBoundFunction(final FullQualifiedName fullQualifiedName, UriInfoImpl uriInfo,
+ final UriResourcePartTyped lastResource) throws UriParserException, UriValidationException {
+ final List<UriParameter> parameters = ParserHelper.parseFunctionParameters(tokenizer, true);
+ final List<String> parameterNames = ParserHelper.getParameterNames(parameters);
+ final EdmFunction boundFunction = edm.getBoundFunction(fullQualifiedName,
+ lastResource.getType().getFullQualifiedName(), lastResource.isCollection(), parameterNames);
+ if (boundFunction == null) {
+ throw new UriParserSemanticException("Bound function not found.",
+ UriParserSemanticException.MessageKeys.FUNCTION_NOT_FOUND, fullQualifiedName.getFullQualifiedNameAsString());
+ }
+ parseFunctionRest(uriInfo, boundFunction, parameters);
+ }
+
+ private void parseFunctionRest(UriInfoImpl uriInfo, final EdmFunction function,
+ final List<UriParameter> parameters) throws UriParserException, UriValidationException {
+ final UriResourceFunction functionResource = new UriResourceFunctionImpl(null, function, parameters);
+ uriInfo.addResourcePart(functionResource);
+
+ final EdmReturnType edmReturnType = function.getReturnType();
+ final EdmType edmType = edmReturnType.getType();
+ final boolean isCollection = edmReturnType.isCollection();
+
+ if (function.isComposable()) {
+ if (edmType instanceof EdmEntityType ) {
+ if (isCollection) {
+ parseCollectionNavigationExpr(uriInfo, null); // TODO: Get navigation property.
+ } else {
+ parseSingleNavigationExpr(uriInfo, null); // TODO: Get navigation property.
+ }
+ } else if (edmType instanceof EdmComplexType) {
+ if (isCollection) {
+ parseCollectionPathExpr(uriInfo, functionResource);
+ } else {
+ parseComplexPathExpr(uriInfo, functionResource);
+ }
+ } else if (edmType instanceof EdmPrimitiveType) {
+ if (isCollection) {
+ parseCollectionPathExpr(uriInfo, functionResource);
+ } else {
+ parseSinglePathExpr(uriInfo, functionResource);
+ }
+ }
+ } else if (tokenizer.next(TokenKind.SLASH)) {
+ throw new UriValidationException("Function is not composable.",
+ UriValidationException.MessageKeys.UNALLOWED_RESOURCE_PATH, "");
+ }
+ }
+
+ private UriResourcePartTyped parseLambdaRest(final TokenKind lastTokenKind, final UriResourcePartTyped lastResource)
+ throws UriParserException, UriValidationException {
+
+ ParserHelper.requireNext(tokenizer, TokenKind.OPEN);
+ if (lastTokenKind == TokenKind.ANY && tokenizer.next(TokenKind.CLOSE)) {
+ return new UriResourceLambdaAnyImpl(null, null);
+ }
+ ParserHelper.requireNext(tokenizer, TokenKind.ODataIdentifier);
+ final String lambbdaVariable = tokenizer.getText();
+ ParserHelper.requireNext(tokenizer, TokenKind.COLON);
+ lambdaVariables.addFirst(new UriResourceLambdaVarImpl(lambbdaVariable,
+ lastResource == null ? referringType : lastResource.getType()));
+ final Expression lambdaPredicateExpr = parseExpression();
+ lambdaVariables.removeFirst();
+ // TODO: The ABNF suggests that the "lambaPredicateExpr" must contain at least one lambdaVariable.
+ ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
+ if (lastTokenKind == TokenKind.ALL) {
+ return new UriResourceLambdaAllImpl(lambbdaVariable, lambdaPredicateExpr);
+ } else if (lastTokenKind == TokenKind.ANY) {
+ return new UriResourceLambdaAnyImpl(lambbdaVariable, lambdaPredicateExpr);
+ } else {
+ throw new UriParserSyntaxException("Unexpected token.", UriParserSyntaxException.MessageKeys.SYNTAX);
+ }
+ }
+
private TokenKind nextMethod() {
return ParserHelper.next(tokenizer,
TokenKind.CeilingMethod,
@@ -580,9 +1044,9 @@ public class ExpressionParser {
}
}
- private EdmPrimitiveType getEnumType(final String primitiveValueLiteral) throws UriParserException {
+ private EdmEnumType getEnumType(final String primitiveValueLiteral) throws UriParserException {
final String enumTypeName = primitiveValueLiteral.substring(0, primitiveValueLiteral.indexOf('\''));
- final EdmPrimitiveType type = edm.getEnumType(new FullQualifiedName(enumTypeName));
+ final EdmEnumType type = edm.getEnumType(new FullQualifiedName(enumTypeName));
if (type == null) {
throw new UriParserSemanticException("Unknown Enum type '" + enumTypeName + "'.",
UriParserSemanticException.MessageKeys.UNKNOWN_TYPE, enumTypeName);
@@ -599,13 +1063,16 @@ public class ExpressionParser {
EdmPrimitiveTypeKind.Byte, EdmPrimitiveTypeKind.SByte);
}
- private void checkEnumLiteral(final Expression expression) throws UriParserException {
- if (expression == null
- || !(expression instanceof Literal)
- || ((Literal) expression).getType() == null
- || ((Literal) expression).getType().getKind() != EdmTypeKind.ENUM) {
- throw new UriParserSemanticException("Enum literal expected.",
- UriParserSemanticException.MessageKeys.UNKNOWN_TYPE, ""); // TODO: better message
+ private Enumeration createEnumExpression(final String primitiveValueLiteral) throws UriParserException {
+ final EdmEnumType enumType = getEnumType(primitiveValueLiteral);
+ // TODO: Can the Enumeration interface be changed to handle the value as a whole?
+ try {
+ return new EnumerationImpl(enumType,
+ Arrays.asList(enumType.fromUriLiteral(primitiveValueLiteral).split(",")));
+ } catch (final EdmPrimitiveTypeException e) {
+ // TODO: Better error message.
+ throw new UriParserSemanticException("Wrong enumeration value.", e,
+ UriParserSemanticException.MessageKeys.UNKNOWN_PART, primitiveValueLiteral);
}
}
@@ -664,4 +1131,13 @@ public class ExpressionParser {
throw new UriParserSemanticException("Incompatible types.",
UriParserSemanticException.MessageKeys.UNKNOWN_TYPE, ""); // TODO: better message
}
+
+ private void checkStructuredTypeFilter(final EdmType type, final EdmStructuredType filterType)
+ throws UriParserException {
+ if (!filterType.compatibleTo(type)) {
+ throw new UriParserSemanticException("Incompatible type filter.",
+ UriParserSemanticException.MessageKeys.INCOMPATIBLE_TYPE_FILTER,
+ filterType.getFullQualifiedName().getFullQualifiedNameAsString());
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/FilterParser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/FilterParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/FilterParser.java
new file mode 100644
index 0000000..a3376e0
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/FilterParser.java
@@ -0,0 +1,49 @@
+/*
+ * 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.Collection;
+
+import org.apache.olingo.commons.api.edm.Edm;
+import org.apache.olingo.commons.api.edm.EdmStructuredType;
+import org.apache.olingo.server.api.OData;
+import org.apache.olingo.server.api.uri.queryoption.FilterOption;
+import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
+import org.apache.olingo.server.core.uri.queryoption.FilterOptionImpl;
+import org.apache.olingo.server.core.uri.validator.UriValidationException;
+
+public class FilterParser {
+
+ private final Edm edm;
+ private final OData odata;
+
+ public FilterParser(final Edm edm, final OData odata) {
+ this.edm = edm;
+ this.odata = odata;
+ }
+
+ public FilterOption parse(UriTokenizer tokenizer, final EdmStructuredType referencedType,
+ final Collection<String> crossjoinEntitySetNames)
+ throws UriParserException, UriValidationException {
+ final Expression filterExpression = new ExpressionParser(edm, odata)
+ .parse(tokenizer, referencedType, crossjoinEntitySetNames);
+ // TODO: Check that the expression is boolean.
+ return new FilterOptionImpl().setExpression(filterExpression);
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/OrderByParser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/OrderByParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/OrderByParser.java
new file mode 100644
index 0000000..5ea8cb7
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/OrderByParser.java
@@ -0,0 +1,61 @@
+/*
+ * 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.Collection;
+
+import org.apache.olingo.commons.api.edm.Edm;
+import org.apache.olingo.commons.api.edm.EdmStructuredType;
+import org.apache.olingo.server.api.OData;
+import org.apache.olingo.server.api.uri.queryoption.OrderByOption;
+import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
+import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind;
+import org.apache.olingo.server.core.uri.queryoption.OrderByItemImpl;
+import org.apache.olingo.server.core.uri.queryoption.OrderByOptionImpl;
+import org.apache.olingo.server.core.uri.validator.UriValidationException;
+
+public class OrderByParser {
+
+ private final Edm edm;
+ private final OData odata;
+
+ public OrderByParser(final Edm edm, final OData odata) {
+ this.edm = edm;
+ this.odata = odata;
+ }
+
+ public OrderByOption parse(UriTokenizer tokenizer, final EdmStructuredType referencedType,
+ final Collection<String> crossjoinEntitySetNames)
+ throws UriParserException, UriValidationException {
+ OrderByOptionImpl orderByOption = new OrderByOptionImpl();
+ do {
+ final Expression orderByExpression = new ExpressionParser(edm, odata)
+ .parse(tokenizer, referencedType, crossjoinEntitySetNames);
+ OrderByItemImpl item = new OrderByItemImpl();
+ item.setExpression(orderByExpression);
+ if (tokenizer.next(TokenKind.AscSuffix)) {
+ item.setDescending(false);
+ } else if (tokenizer.next(TokenKind.DescSuffix)) {
+ item.setDescending(true);
+ }
+ orderByOption.addOrder(item);
+ } while (tokenizer.next(TokenKind.COMMA));
+ return orderByOption;
+ }
+}
[15/30] olingo-odata4 git commit: [OLINGO-834] ExpressionParser
parses path expressions
Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java
index e9f1c07..ec9cc22 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java
@@ -82,13 +82,8 @@ public class TestFullResourcePath {
.isKeyPredicate(0, "PropertyEnumString", "olingo.odata.test1.ENString'String1'")
.isKeyPredicate(1, "PropertyDefString", "'abc'");
- testUri
- .run("ESMixEnumDefCollComp", "$filter=PropertyEnumString has Namespace1_Alias.ENString'String1'")
- .goPath()
- .at(0)
- .isEntitySet("ESMixEnumDefCollComp")
- .goUpUriValidator()
- .goFilter().is("<<PropertyEnumString> has <olingo.odata.test1.ENString<String1>>>");
+ testFilter.runOnETMixEnumDefCollComp("PropertyEnumString has Namespace1_Alias.ENString'String1'")
+ .is("<<PropertyEnumString> has <olingo.odata.test1.ENString<String1>>>");
testUri
.run("ESMixEnumDefCollComp(PropertyEnumString=Namespace1_Alias.ENString'String1',PropertyDefString='abc')")
@@ -100,7 +95,7 @@ public class TestFullResourcePath {
}
@Test
- public void testFunctionBound_varOverloading() throws Exception {
+ public void functionBound_varOverloading() throws Exception {
// on ESTwoKeyNav
testUri.run("ESTwoKeyNav/olingo.odata.test1.BFCESTwoKeyNavRTESTwoKeyNav()").goPath()
.at(0)
@@ -941,7 +936,10 @@ public class TestFullResourcePath {
testUri.run("$crossjoin(ESKeyNav,ESTwoKeyNav)")
.isKind(UriInfoKind.crossjoin)
.isCrossJoinEntityList(Arrays.asList("ESKeyNav", "ESTwoKeyNav"));
+ }
+ @Test
+ public void crossjoinFilter() throws Exception {
testUri.run("$crossjoin(ESTwoPrim,ESMixPrimCollComp)",
"$filter=ESTwoPrim/PropertyString eq ESMixPrimCollComp/PropertyComp/PropertyString")
.goFilter()
@@ -950,7 +948,7 @@ public class TestFullResourcePath {
}
@Test
- public void runCrossjoinError() throws Exception {
+ public void crossjoinError() throws Exception {
testUri.runEx("$crossjoin").isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
testUri.runEx("$crossjoin/error").isExSyntax(UriParserSyntaxException.MessageKeys.MUST_BE_LAST_SEGMENT);
testUri.runEx("$crossjoin()").isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
@@ -1031,20 +1029,20 @@ public class TestFullResourcePath {
}
@Test
- public void resourcePathWithApostrophe() {
+ public void resourcePathWithApostrophe() throws Exception {
testUri.runEx("ESAllPrim'").isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
testUri.runEx("ESAllPrim'InvalidStuff").isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
- testUri.runEx("ESAllPrim", "$filter=PropertyInt16' eq 0")
- .isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
+ testFilter.runOnETKeyNavEx("PropertyInt16' eq 0")
+ .isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
- testUri.runEx("ESAllPrim", "$filter=PropertyInt16 eq' 0")
- .isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
+ testFilter.runOnETKeyNavEx("PropertyInt16 eq' 0")
+ .isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
- testUri.runEx("ESAllPrim", "$filter=PropertyInt16 eq 0'")
- .isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
+ testFilter.runOnETKeyNavEx("PropertyInt16 eq 0'")
+ .isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
- testUri.runEx("ESAllPrim", "$filter=PropertyInt16 eq 'dsd''")
+ testFilter.runOnETKeyNavEx("PropertyInt16 eq 'dsd''")
.isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
}
@@ -1334,14 +1332,6 @@ public class TestFullResourcePath {
@Test
public void runEsNameKeyCast() throws Exception {
- // testUri.runEx("ESTwoPrim(1)/olingo.odata.test1.ETBase(1)")
- // .isExSemantic(MessageKeys.xxx);
-
- // testUri.runEx("ESTwoPrim/olingo.odata.test1.ETBase(1)/olingo.odata.test1.ETTwoBase(1)")
- // .isExSemantic(MessageKeys.xxx);
-
- testUri.runEx("ESBase/olingo.odata.test1.ETTwoPrim(1)").isExSemantic(MessageKeys.INCOMPATIBLE_TYPE_FILTER);
-
testUri.run("ESTwoPrim(1)/olingo.odata.test1.ETBase")
.isKind(UriInfoKind.resource).goPath()
.first()
@@ -1388,6 +1378,15 @@ public class TestFullResourcePath {
.isEntitySet("ESTwoPrim")
.isType(EntityTypeProvider.nameETTwoPrim)
.isTypeFilterOnCollection(EntityTypeProvider.nameETTwoBase);
+
+ // TODO: Keys cannot be specified twice.
+ //testUri.runEx("ESTwoPrim(1)/olingo.odata.test1.ETBase(1)")
+ // .isExSemantic(MessageKeys.INCOMPATIBLE_TYPE_FILTER);
+
+ //testUri.runEx("ESTwoPrim/olingo.odata.test1.ETBase(1)/olingo.odata.test1.ETTwoBase(1)")
+ // .isExSemantic(MessageKeys.TYPE_FILTER_NOT_CHAINABLE);
+
+ testUri.runEx("ESBase/olingo.odata.test1.ETTwoPrim(1)").isExSemantic(MessageKeys.INCOMPATIBLE_TYPE_FILTER);
}
@Test
@@ -2620,9 +2619,7 @@ public class TestFullResourcePath {
.goExpand().first()
.isExpandStartType(EntityTypeProvider.nameETBaseTwoKeyNav)
.goPath().first()
- // .isType(EntityTypeProvider.nameETTwoKeyNav)
- // .isTypeFilterOnEntry(EntityTypeProvider.nameETBaseTwoKeyNav)
- // .n()
+ .isType(EntityTypeProvider.nameETKeyNav)
.isNavProperty("NavPropertyETKeyNavMany", EntityTypeProvider.nameETKeyNav, true);
testUri.run("ESTwoKeyNav(PropertyInt16=1,PropertyString='2')",
@@ -2633,9 +2630,7 @@ public class TestFullResourcePath {
.goExpand().first()
.isExpandStartType(EntityTypeProvider.nameETBaseTwoKeyNav)
.goPath().first()
- // .isType(EntityTypeProvider.nameETTwoKeyNav)
- // .isTypeFilterOnEntry(EntityTypeProvider.nameETBaseTwoKeyNav)
- // .n()
+ .isType(EntityTypeProvider.nameETTwoKeyNav)
.isNavProperty("NavPropertyETTwoKeyNavMany", EntityTypeProvider.nameETTwoKeyNav, true);
testUri.run("ESTwoKeyNav(PropertyInt16=1,PropertyString='2')",
@@ -2647,9 +2642,7 @@ public class TestFullResourcePath {
.goExpand().first()
.isExpandStartType(EntityTypeProvider.nameETBaseTwoKeyNav)
.goPath().first()
- // .isType(EntityTypeProvider.nameETTwoKeyNav)
- // .isTypeFilterOnEntry(EntityTypeProvider.nameETBaseTwoKeyNav)
- // .n()
+ .isType(EntityTypeProvider.nameETTwoKeyNav)
.isNavProperty("NavPropertyETTwoKeyNavMany", EntityTypeProvider.nameETTwoKeyNav, true)
.isTypeFilterOnCollection(EntityTypeProvider.nameETTwoBaseTwoKeyNav);
@@ -2658,11 +2651,7 @@ public class TestFullResourcePath {
.goExpand().first()
.isExpandStartType(EntityTypeProvider.nameETBaseTwoKeyNav)
.goPath().first()
- // .isType(EntityTypeProvider.nameETTwoKeyNav)
- // .isTypeFilterOnCollection(EntityTypeProvider.nameETBaseTwoKeyNav)
- // .n()
- .isComplex("PropertyCompNav")
- .isType(ComplexTypeProvider.nameCTBasePrimCompNav)
+ .isComplexProperty("PropertyCompNav", ComplexTypeProvider.nameCTBasePrimCompNav, false)
.n()
.isNavProperty("NavPropertyETTwoKeyNavOne", EntityTypeProvider.nameETTwoKeyNav, false);
@@ -2672,11 +2661,8 @@ public class TestFullResourcePath {
.goExpand().first()
.isExpandStartType(EntityTypeProvider.nameETBaseTwoKeyNav)
.goPath().first()
- // .isType(EntityTypeProvider.nameETTwoKeyNav)
- // .isTypeFilterOnCollection(EntityTypeProvider.nameETBaseTwoKeyNav)
- // .n()
- .isComplex("PropertyCompNav")
- .isType(ComplexTypeProvider.nameCTBasePrimCompNav)
+ .isComplexProperty("PropertyCompNav", ComplexTypeProvider.nameCTBasePrimCompNav, false)
+ .isTypeFilter(ComplexTypeProvider.nameCTTwoBasePrimCompNav)
.n()
.isNavProperty("NavPropertyETTwoKeyNavOne", EntityTypeProvider.nameETTwoKeyNav, false);
@@ -2704,10 +2690,7 @@ public class TestFullResourcePath {
.goExpand().first()
.isExpandStartType(EntityTypeProvider.nameETBaseTwoKeyNav)
.goPath().first()
- // .isUriPathInfoKind(UriResourceKind.startingTypeFilter)
- // .isType(EntityTypeProvider.nameETTwoKeyNav)
- // .isTypeFilterOnEntry(EntityTypeProvider.nameETBaseTwoKeyNav)
- // .n().isNavProperty("NavPropertyETTwoKeyNavMany", EntityTypeProvider.nameETTwoKeyNav, true)
+ .isNavProperty("NavPropertyETTwoKeyNavMany", EntityTypeProvider.nameETTwoKeyNav, true)
.isType(EntityTypeProvider.nameETTwoKeyNav)
.isTypeFilterOnCollection(EntityTypeProvider.nameETTwoBaseTwoKeyNav)
.goUpExpandValidator()
@@ -3246,7 +3229,9 @@ public class TestFullResourcePath {
}
+ // TODO
@Test
+ @Ignore
public void filter() throws Exception {
testFilter.runOnETTwoKeyNav("PropertyString")
@@ -3311,9 +3296,6 @@ public class TestFullResourcePath {
.root().left()
.isType(PropertyProvider.nameDate)
.isMember().isMemberStartType(EntityTypeProvider.nameETBaseTwoKeyNav).goPath()
- // .first().isUriPathInfoKind(UriResourceKind.startingTypeFilter)
- // .isType(EntityTypeProvider.nameETTwoKeyNav).isTypeFilterOnCollection(EntityTypeProvider.nameETBaseTwoKeyNav)
- // .n().isPrimitiveProperty("PropertyDate", PropertyProvider.nameDate, false)
.first().isPrimitiveProperty("PropertyDate", PropertyProvider.nameDate, false)
.goUpFilterValidator()
.root().right()
@@ -3324,9 +3306,6 @@ public class TestFullResourcePath {
.root().left()
.isType(PropertyProvider.nameString)
.isMember().isMemberStartType(ComplexTypeProvider.nameCTBase).goPath()
- // .first().isUriPathInfoKind(UriResourceKind.startingTypeFilter)
- // .isType(EntityTypeProvider.nameCTTwoPrim).isTypeFilterOnEntry(ComplexTypeProvider.nameCTBase)
- // .n().isPrimitiveProperty("AdditionalPropString", PropertyProvider.nameString, false)
.first().isPrimitiveProperty("AdditionalPropString", PropertyProvider.nameString, false)
.goUpFilterValidator()
.root().right()
@@ -3352,19 +3331,18 @@ public class TestFullResourcePath {
.isExSemantic(MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE);
// TODO: This should throw an exception because the top node of the filter tree must be boolean.
// testFilter.runOnETTwoKeyNavEx("PropertyComp")
- // .isExSemantic(MessageKeys.XYZ);
+ // .isExSemantic(MessageKeys.UNKNOWN_TYPE);
testFilter.runOnETTwoKeyNavEx("PropertyComp/invalid")
.isExSemantic(MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE);
testFilter.runOnETTwoKeyNavEx("concat('a','b')/invalid").isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
testFilter.runOnETTwoKeyNavEx("PropertyComp/concat('a','b')")
.isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
- // TODO: These should throw exceptions because the types are incompatible.
- // testFilter.runOnETTwoKeyNavEx("PropertyComp/PropertyInt16 eq '1'")
- // .isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
- // testFilter.runOnETTwoKeyNavEx("PropertyComp/PropertyComp/PropertyDate eq 1")
- // .isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
- // testFilter.runOnETTwoKeyNavEx("PropertyComp/PropertyComp/PropertyString eq 1")
- // .isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
+ testFilter.runOnETTwoKeyNavEx("PropertyComp/PropertyInt16 eq '1'")
+ .isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
+ testFilter.runOnETTwoKeyNavEx("PropertyComp/PropertyComp/PropertyDate eq 1")
+ .isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
+ testFilter.runOnETTwoKeyNavEx("PropertyComp/PropertyComp/PropertyString eq 1")
+ .isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
testFilter.runOnETTwoKeyNavEx("PropertyComp/PropertyInt64 eq 1")
.isExSemantic(MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE);
testFilter.runOnETTwoKeyNavEx("NavPropertyETKeyNavMany/PropertyInt16 gt 42")
@@ -3788,8 +3766,155 @@ public class TestFullResourcePath {
.right().isLiteral("INF").isType(PropertyProvider.nameDecimal);
}
+ // TODO
@Test
+ @Ignore
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().isTrue();
+
+ 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().isComplex("PropertyCompMixedEnumDef")
+ .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().isComplex("PropertyCompMixedEnumDef")
+ .n().isPrimitiveProperty("PropertyEnumString", EnumTypeProvider.nameENString, false)
+ .goUpFilterValidator()
+ .root().right().goPath()
+ .first().isComplex("PropertyCompMixedEnumDef")
+ .n().isPrimitiveProperty("PropertyEnumString", EnumTypeProvider.nameENString, false);
+
testFilter.runOnETAllPrim("PropertyByte mod 0")
.is("<<PropertyByte> mod <0>>");
@@ -3953,9 +4078,10 @@ public class TestFullResourcePath {
.isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false);
}
+ // TODO: $it on primitive types?
@Test
- public void filterPMethods() throws Exception {
-
+ @Ignore
+ public void methods() throws Exception {
testFilter.runOnETKeyNav("indexof(PropertyString,'47') eq 5")
.is("<<indexof(<PropertyString>,<'47'>)> eq <5>>")
.root().left()
@@ -4024,16 +4150,6 @@ public class TestFullResourcePath {
.isParameterText(0, "<PropertyString>")
.isParameterText(1, "<'bar'>");
- testFilter.runOnETKeyNav("concat(PropertyString, cast(PropertyCompAllPrim/PropertyInt16,Edm.String))")
- .is("<concat(<PropertyString>,<cast(<PropertyCompAllPrim/PropertyInt16>,<Edm.String>)>)>")
- .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("length(PropertyString) eq 32")
.is("<<length(<PropertyString>)> eq <32>>")
.root().left()
@@ -4416,59 +4532,167 @@ public class TestFullResourcePath {
.isType(EntityTypeProvider.nameETTwoKeyNav, true)
.n().isPrimitiveProperty("CollPropertyString", PropertyProvider.nameString, true);
- 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().isComplex("PropertyComp").isType(ComplexTypeProvider.nameCTPrimComp, false)
- .n().isComplex("PropertyComp").isType(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.runOnETKeyNav("cast(olingo.odata.test1.ETBaseTwoKeyNav)")
- .is("<cast(<olingo.odata.test1.ETBaseTwoKeyNav>)>")
- .root()
- .isMethod(MethodKind.CAST, 1)
- .isParameterText(0, "<olingo.odata.test1.ETBaseTwoKeyNav>")
- .goParameter(0)
- .isTypedLiteral(EntityTypeProvider.nameETBaseTwoKeyNav);
+ testFilter.runOnETTwoKeyNav("endswith(PropertyComp/PropertyComp/PropertyString,'dorf')")
+ .is("<endswith(<PropertyComp/PropertyComp/PropertyString>,<'dorf'>)>")
+ .isMethod(MethodKind.ENDSWITH, 2)
+ .goParameter(0).goPath()
+ .first().isComplex("PropertyComp")
+ .n().isComplex("PropertyComp")
+ .n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false).goUpFilterValidator()
+ .root().goParameter(1).isLiteral("'dorf'");
- testFilter.runOnETKeyNav("cast(PropertyCompTwoPrim,olingo.odata.test1.CTBase)")
- .is("<cast(<PropertyCompTwoPrim>,<olingo.odata.test1.CTBase>)>")
- .root()
- .isMethod(MethodKind.CAST, 2)
- .isParameterText(0, "<PropertyCompTwoPrim>")
- .isParameterText(1, "<olingo.odata.test1.CTBase>")
- .goParameter(0).goPath().first()
- .isComplex("PropertyCompTwoPrim").isType(ComplexTypeProvider.nameCTTwoPrim, false)
- .goUpFilterValidator()
- .root()
- .goParameter(1)
- .isTypedLiteral(ComplexTypeProvider.nameCTBase);
+ 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().isComplex("PropertyComp")
+ .n().isComplex("PropertyComp")
+ .n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false).goUpFilterValidator()
+ .root().left().goParameter(1).isLiteral("'dorf'");
- testFilter.runOnETKeyNav("cast($it,olingo.odata.test1.CTBase)")
- .is("<cast(<$it>,<olingo.odata.test1.CTBase>)>")
- .root()
- .isMethod(MethodKind.CAST, 2)
- .isParameterText(0, "<$it>")
- .isParameterText(1, "<olingo.odata.test1.CTBase>")
- .goParameter(0).goPath().first()
- .isIt().isType(EntityTypeProvider.nameETKeyNav, false)
- .goUpFilterValidator()
- .root()
- .goParameter(1).isTypedLiteral(ComplexTypeProvider.nameCTBase);
+ testFilter.runOnETTwoKeyNav("endswith('Walldorf','dorf')")
+ .is("<endswith(<'Walldorf'>,<'dorf'>)>")
+ .isMethod(MethodKind.ENDSWITH, 2)
+ .goParameter(0).isLiteral("'Walldorf'")
+ .root().goParameter(1).isLiteral("'dorf'");
- 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>)>>")
+ 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().isComplex("PropertyCompAllPrim")
+ .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().isComplex("PropertyCompAllPrim")
+ .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().isComplex("PropertyComp")
+ .n().isComplex("PropertyComp")
+ .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().isComplex("PropertyComp")
+ .n().isComplex("PropertyComp")
+ .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().isComplex("PropertyComp").isType(ComplexTypeProvider.nameCTPrimComp, false)
+ .n().isComplex("PropertyComp").isType(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);
+ }
+
+ // TODO: Implement cast method.
+ @Test
+ @Ignore
+ public void castMethod() throws Exception {
+ testFilter.runOnETKeyNav("cast(olingo.odata.test1.ETBaseTwoKeyNav)")
+ .is("<cast(<olingo.odata.test1.ETBaseTwoKeyNav>)>")
+ .root()
+ .isMethod(MethodKind.CAST, 1)
+ .isParameterText(0, "<olingo.odata.test1.ETBaseTwoKeyNav>")
+ .goParameter(0)
+ .isTypedLiteral(EntityTypeProvider.nameETBaseTwoKeyNav);
+
+ testFilter.runOnETKeyNav("cast(PropertyCompTwoPrim,olingo.odata.test1.CTBase)")
+ .is("<cast(<PropertyCompTwoPrim>,<olingo.odata.test1.CTBase>)>")
+ .root()
+ .isMethod(MethodKind.CAST, 2)
+ .isParameterText(0, "<PropertyCompTwoPrim>")
+ .isParameterText(1, "<olingo.odata.test1.CTBase>")
+ .goParameter(0).goPath().first()
+ .isComplex("PropertyCompTwoPrim").isType(ComplexTypeProvider.nameCTTwoPrim, false)
+ .goUpFilterValidator()
+ .root()
+ .goParameter(1)
+ .isTypedLiteral(ComplexTypeProvider.nameCTBase);
+
+ testFilter.runOnETKeyNav("cast($it,olingo.odata.test1.CTBase)")
+ .is("<cast(<$it>,<olingo.odata.test1.CTBase>)>")
+ .root()
+ .isMethod(MethodKind.CAST, 2)
+ .isParameterText(0, "<$it>")
+ .isParameterText(1, "<olingo.odata.test1.CTBase>")
+ .goParameter(0).goPath().first()
+ .isIt().isType(EntityTypeProvider.nameETKeyNav, false)
+ .goUpFilterValidator()
+ .root()
+ .goParameter(1).isTypedLiteral(ComplexTypeProvider.nameCTBase);
+
+ testFilter.runOnETKeyNav("concat(PropertyString,cast(PropertyCompAllPrim/PropertyInt16,Edm.String))")
+ .is("<concat(<PropertyString>,<cast(<PropertyCompAllPrim/PropertyInt16>,<Edm.String>)>)>")
+ .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>)>>")
.root().left()
.isMethod(MethodKind.CAST, 2)
.isParameterText(0, "<$it>")
@@ -4563,26 +4787,22 @@ public class TestFullResourcePath {
.goUpFilterValidator().root()
.goParameter(1).isTypedLiteral(EntityTypeProvider.nameETKeyPrimNav);
+ testFilter.runOnETAllPrim("olingo.odata.test1.UFCRTCTTwoPrimTwoParam(ParameterInt16=null,ParameterString=null)")
+ .goPath()
+ .isFunction("UFCRTCTTwoPrimTwoParam")
+ .isParameter(0, "ParameterInt16", null)
+ .isParameter(1, "ParameterString", null);
+
testFilter.runOnETKeyNavEx("cast(NavPropertyETKeyPrimNavOne,olingo.odata.test1.ETKeyNav)")
.isExSemantic(MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE);
testFilter.runOnETKeyNav("any()")
.isMember().goPath().first().isUriPathInfoKind(UriResourceKind.lambdaAny);
}
+ // TODO: Check whether lambda expressions really are allowed on complex collections.
@Test
+ @Ignore
public void lambdaFunctions() throws Exception {
-
- testFilter.runOnETKeyNav("any(d:d/PropertyInt16 eq 1)")
- .is("<<ANY;<<d/PropertyInt16> eq <1>>>>")
- .root().goPath()
- .first().isUriPathInfoKind(UriResourceKind.lambdaAny)
- .goLambdaExpression()
- .isBinary(BinaryOperatorKind.EQ)
- .left().goPath()
- .first().isUriPathInfoKind(UriResourceKind.lambdaVariable)
- .isType(EntityTypeProvider.nameETKeyNav, false)
- .n().isPrimitiveProperty("PropertyInt16", PropertyProvider.nameInt16, false);
-
testFilter.runOnETKeyNav("NavPropertyETTwoKeyNavMany/any(d:d/PropertyString eq 'SomeString')")
.is("<NavPropertyETTwoKeyNavMany/<ANY;<<d/PropertyString> eq <'SomeString'>>>>")
.root().goPath()
@@ -4610,7 +4830,7 @@ public class TestFullResourcePath {
.first().isUriPathInfoKind(UriResourceKind.lambdaVariable)
.isType(PropertyProvider.nameString, false);
- testFilter.runOnETKeyNav(" NavPropertyETTwoKeyNavOne/olingo.odata.test1.BFCETTwoKeyNavRTESTwoKeyNav()"
+ 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()
@@ -4625,8 +4845,8 @@ public class TestFullResourcePath {
.n().isComplex("PropertyComp")
.n().isPrimitiveProperty("PropertyInt16", PropertyProvider.nameInt16, false);
- testFilter.runOnETKeyNav("NavPropertyETTwoKeyNavMany/any(d:d/PropertyInt16 eq 1 or d/any"
- + "(e:e/CollPropertyString eq 'SomeString'))")
+ testFilter.runOnETKeyNav("NavPropertyETTwoKeyNavMany/any(d:d/PropertyInt16 eq 1 or "
+ + "d/any(e:e/CollPropertyString eq 'SomeString'))")
.is("<NavPropertyETTwoKeyNavMany/<ANY;<<<d/PropertyInt16> eq <1>> or "
+ "<d/<ANY;<<e/CollPropertyString> eq <'SomeString'>>>>>>>")
.root().goPath()
@@ -4653,8 +4873,8 @@ public class TestFullResourcePath {
.isType(EntityTypeProvider.nameETTwoKeyNav, false)
.n().isPrimitiveProperty("CollPropertyString", PropertyProvider.nameString, true);
- testFilter.runOnETKeyNav("NavPropertyETTwoKeyNavMany/any(d:d/PropertyInt16 eq 1 or d/CollPropertyString/any"
- + "(e:e eq 'SomeString'))")
+ 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()
@@ -4681,9 +4901,8 @@ public class TestFullResourcePath {
.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))")
+ 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()
@@ -4714,11 +4933,14 @@ public class TestFullResourcePath {
.first().isUriPathInfoKind(UriResourceKind.lambdaVariable)
.n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false);
+ testFilter.runOnETKeyNavEx("any(d:d/PropertyInt16 eq 1)")
+ .isExSemantic(MessageKeys.PROPERTY_NOT_IN_TYPE);
}
+ // TODO: Implement isof method.
@Test
- public void runIsOf() throws Exception {
-
+ @Ignore
+ public void isOfMethod() throws Exception {
testFilter.runOnETKeyNav("isof(olingo.odata.test1.ETTwoKeyNav)")
.is("<isof(<olingo.odata.test1.ETTwoKeyNav>)>")
.root()
@@ -4903,271 +5125,16 @@ public class TestFullResourcePath {
.goUpFilterValidator()
.root().right().isEnum(EnumTypeProvider.nameENString, Arrays.asList("String3"));
- testFilter.runOnETMixEnumDefCollComp("PropertyEnumString has olingo.odata.test1.ENString'String,String3'")
- .is("<<PropertyEnumString> has <olingo.odata.test1.ENString<String,String3>>>")
- .isBinary(BinaryOperatorKind.HAS)
- .root().left().goPath()
- .first().isPrimitiveProperty("PropertyEnumString", EnumTypeProvider.nameENString, false)
- .goUpFilterValidator()
- .root().right().isEnum(EnumTypeProvider.nameENString, Arrays.asList("String", "String3"));
-
- testFilter.runOnETMixEnumDefCollComp("PropertyEnumString has null")
- .is("<<PropertyEnumString> has <null>>")
- .root()
+ testFilter.runOnETMixEnumDefCollComp("PropertyEnumString has olingo.odata.test1.ENString'String1,String3'")
+ .is("<<PropertyEnumString> has <olingo.odata.test1.ENString<String1,String3>>>")
.isBinary(BinaryOperatorKind.HAS)
.root().left().goPath()
.first().isPrimitiveProperty("PropertyEnumString", EnumTypeProvider.nameENString, false)
.goUpFilterValidator()
- .root().right().isNull();
-
- testFilter.runOnETTwoKeyNav("endswith(PropertyComp/PropertyComp/PropertyString,'dorf')")
- .is("<endswith(<PropertyComp/PropertyComp/PropertyString>,<'dorf'>)>")
- .isMethod(MethodKind.ENDSWITH, 2)
- .goParameter(0).goPath()
- .first().isComplex("PropertyComp")
- .n().isComplex("PropertyComp")
- .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().isComplex("PropertyComp")
- .n().isComplex("PropertyComp")
- .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().isComplex("PropertyCompAllPrim")
- .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().isComplex("PropertyCompAllPrim")
- .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().isComplex("PropertyComp")
- .n().isComplex("PropertyComp")
- .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().isComplex("PropertyComp")
- .n().isComplex("PropertyComp")
- .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.runOnETAllPrim("olingo.odata.test1.UFCRTCTTwoPrimTwoParam(ParameterInt16=null,ParameterString=null)")
- .goPath()
- .isFunction("UFCRTCTTwoPrimTwoParam")
- .isParameter(0, "ParameterInt16", null)
- .isParameter(1, "ParameterString", null);
-
- testFilter.runOnETAllPrim("PropertyBoolean eq true")
- .is("<<PropertyBoolean> eq <true>>")
- .isBinary(BinaryOperatorKind.EQ)
- .root().left().goPath().isPrimitiveProperty("PropertyBoolean", PropertyProvider.nameBoolean, false)
- .goUpFilterValidator()
- .root().right().isTrue();
-
- testFilter.runOnETAllPrim("PropertyBoolean eq 2")
- .is("<<PropertyBoolean> eq <2>>");
-
- 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().isComplex("PropertyCompMixedEnumDef")
- .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().isComplex("PropertyCompMixedEnumDef")
- .n().isPrimitiveProperty("PropertyEnumString", EnumTypeProvider.nameENString, false)
- .goUpFilterValidator()
- .root().right().goPath()
- .first().isComplex("PropertyCompMixedEnumDef")
- .n().isPrimitiveProperty("PropertyEnumString", EnumTypeProvider.nameENString, false);
+ .root().right().isEnum(EnumTypeProvider.nameENString, Arrays.asList("String1", "String3"));
+ testFilter.runUriEx("ESMixEnumDefCollComp", "$filter=PropertyEnumString has null")
+ .isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
testFilter.runUriEx("ESMixEnumDefCollComp", "$filter=PropertyEnumString has ENString'String1'")
.isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
testFilter.runUriEx("ESMixEnumDefCollComp", "$filter=PropertyEnumString has wrongNamespace.ENString'String1'")
@@ -5192,6 +5159,28 @@ public class TestFullResourcePath {
@Test
public void orderby() throws Exception {
+ testFilter.runOrderByOnETTwoKeyNav("PropertyString")
+ .isSortOrder(0, false)
+ .goOrder(0).goPath()
+ .first().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false);
+
+ testFilter.runOrderByOnETTwoKeyNav("PropertyComp")
+ .isSortOrder(0, false)
+ .goOrder(0).goPath()
+ .first().isComplex("PropertyComp");
+
+ testFilter.runOrderByOnETTwoKeyNav("PropertyComp/PropertyComp")
+ .isSortOrder(0, false)
+ .goOrder(0).goPath()
+ .first().isComplex("PropertyComp")
+ .n().isComplex("PropertyComp");
+
+ testFilter.runOrderByOnETTwoKeyNav("PropertyComp/PropertyComp/PropertyDate")
+ .isSortOrder(0, false)
+ .goOrder(0).goPath()
+ .first().isComplex("PropertyComp")
+ .n().isComplex("PropertyComp")
+ .n().isPrimitiveProperty("PropertyDate", PropertyProvider.nameDate, false);
testFilter.runOrderByOnETTwoKeyNav("olingo.odata.test1.UFCRTETAllPrimTwoParam("
+ "ParameterString=@ParamStringAlias,ParameterInt16=@ParamInt16Alias)/PropertyString eq 'SomeString'")
@@ -5215,8 +5204,8 @@ public class TestFullResourcePath {
.goOrder(0).right().isLiteral("'SomeString'");
testFilter.runOrderByOnETTwoKeyNav("olingo.odata.test1.UFCRTETAllPrimTwoParam("
- + "ParameterString=@ParamStringAlias,ParameterInt16=@ParamInt16Alias)/PropertyString eq 'SomeString' desc"
- + ", PropertyString eq '1'")
+ + "ParameterString=@ParamStringAlias,ParameterInt16=@ParamInt16Alias)/PropertyString eq 'SomeString' desc,"
+ + "PropertyString eq '1'")
.isSortOrder(0, true)
.goOrder(0).isBinary(BinaryOperatorKind.EQ).left().goPath()
.first().isFunction("UFCRTETAllPrimTwoParam").goUpFilterValidator()
@@ -5241,20 +5230,8 @@ public class TestFullResourcePath {
.n().isComplex("PropertyComp")
.n().isPrimitiveProperty("PropertyDate", PropertyProvider.nameDate, false);
- testFilter.runOrderByOnETTwoKeyNav("PropertyString")
- .isSortOrder(0, false)
- .goOrder(0).goPath()
- .first().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false);
-
- testFilter.runOrderByOnETTwoKeyNav("PropertyComp/PropertyComp/PropertyDate")
- .isSortOrder(0, false)
- .goOrder(0).goPath()
- .first().isComplex("PropertyComp")
- .n().isComplex("PropertyComp")
- .n().isPrimitiveProperty("PropertyDate", PropertyProvider.nameDate, false);
-
- testFilter.runOrderByOnETTwoKeyNav("PropertyComp/PropertyComp/PropertyDate "
- + "eq 2013-11-12 desc, PropertyString eq 'SomeString' desc")
+ testFilter.runOrderByOnETTwoKeyNav("PropertyComp/PropertyComp/PropertyDate eq 2013-11-12 desc,"
+ + "PropertyString eq 'SomeString' desc")
.isSortOrder(0, true)
.goOrder(0).isBinary(BinaryOperatorKind.EQ)
.left().goPath()
@@ -5267,17 +5244,7 @@ public class TestFullResourcePath {
.goUpFilterValidator()
.goOrder(1).right().isLiteral("'SomeString'");
- testFilter.runOrderByOnETTwoKeyNav("PropertyComp")
- .isSortOrder(0, false)
- .goOrder(0).goPath()
- .first().isComplex("PropertyComp");
- testFilter.runOrderByOnETTwoKeyNav("PropertyComp/PropertyComp")
- .isSortOrder(0, false)
- .goOrder(0).goPath()
- .first().isComplex("PropertyComp")
- .n().isComplex("PropertyComp");
-
- testFilter.runOrderByOnETTwoKeyNav("PropertyComp desc, PropertyComp/PropertyInt16 eq 1")
+ testFilter.runOrderByOnETTwoKeyNav("PropertyComp desc,PropertyComp/PropertyInt16 eq 1")
.isSortOrder(0, true)
.goOrder(0).goPath()
.first().isComplex("PropertyComp").goUpFilterValidator()
@@ -5419,17 +5386,17 @@ public class TestFullResourcePath {
.goUpFilterValidator()
.goOrder(0).right().isLiteral("9223372036854775807");
- testFilter.runOrderByOnETAllPrim("PropertyBinary eq binary'0FAB7B'")
+ testFilter.runOrderByOnETAllPrim("PropertyBinary eq binary'VGVzdA=='")
.isSortOrder(0, false)
.goOrder(0).left().goPath().isPrimitiveProperty("PropertyBinary", PropertyProvider.nameBinary, false)
.goUpFilterValidator()
- .goOrder(0).right().isLiteral("binary'0FAB7B'");
+ .goOrder(0).right().isLiteral("binary'VGVzdA=='");
- testFilter.runOrderByOnETAllPrim("PropertyBinary eq binary'0FAB7B' desc")
+ testFilter.runOrderByOnETAllPrim("PropertyBinary eq binary'VGVzdA==' desc")
.isSortOrder(0, true)
.goOrder(0).left().goPath().isPrimitiveProperty("PropertyBinary", PropertyProvider.nameBinary, false)
.goUpFilterValidator()
- .goOrder(0).right().isLiteral("binary'0FAB7B'");
+ .goOrder(0).right().isLiteral("binary'VGVzdA=='");
testFilter.runOrderByOnETAllPrim("PropertyDate eq 2013-09-25")
.isSortOrder(0, false)
@@ -5518,15 +5485,15 @@ public class TestFullResourcePath {
.goOrder(0).right().isEnum(EnumTypeProvider.nameENString, Arrays.asList("String1"));
testFilter.runOrderByOnETTwoKeyNavEx("PropertyInt16 1")
- .isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
+ .isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
testFilter.runOrderByOnETTwoKeyNavEx("PropertyInt16, PropertyInt32 PropertyDuration")
.isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
testFilter.runOrderByOnETTwoKeyNavEx("PropertyInt16 PropertyInt32, PropertyDuration desc")
- .isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
+ .isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
testFilter.runOrderByOnETTwoKeyNavEx("PropertyInt16 asc, PropertyInt32 PropertyDuration desc")
.isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
testFilter.runOrderByOnETTwoKeyNavEx("PropertyInt16 asc desc")
- .isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
+ .isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
testFilter.runOrderByOnETTwoKeyNavEx("undefined")
.isExSemantic(MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE);
testFilter.runOrderByOnETTwoKeyNavEx("PropertyComp/undefined")
@@ -5779,7 +5746,7 @@ public class TestFullResourcePath {
}
@Test
- public void KeyPredicatesInDoubleExpandedFilter() throws Exception {
+ public void keyPredicatesInDoubleExpandedFilter() throws Exception {
testUri.run("ESKeyNav(0)", "$expand=NavPropertyETTwoKeyNavMany($expand=NavPropertyETTwoKeyNavMany"
+ "($filter=NavPropertyETTwoKeyNavMany(PropertyInt16=1,PropertyString='2')/PropertyInt16 eq 1))")
.goPath().goExpand()
@@ -5791,15 +5758,15 @@ public class TestFullResourcePath {
}
@Test
- public void filterSystemQueryOptionAnyWithKeyAny() throws Exception {
- testUri.runEx("ESAllPrim", "$filter=NavPropertyETTwoPrimMany(1)/any(d:d/PropertyInt16 eq 0)")
- .isExSemantic(MessageKeys.KEY_NOT_ALLOWED);
+ public void filterSystemQueryOptionManyWithKeyAny() throws Exception {
+ testFilter.runUriEx("ESAllPrim", "$filter=NavPropertyETTwoPrimMany(1)/any(d:d/PropertyInt16 eq 0)")
+ .isExSemantic(MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE);
}
@Test
- public void filterSystemQueryOptionAnyWithKeyAll() throws Exception {
- testUri.runEx("ESAllPrim", "$filter=NavPropertyETTwoPrimMany(1)/all(d:d/PropertyInt16 eq 0)")
- .isExSemantic(MessageKeys.KEY_NOT_ALLOWED);
+ public void filterSystemQueryOptionManyWithKeyAll() throws Exception {
+ testFilter.runUriEx("ESAllPrim", "$filter=NavPropertyETTwoPrimMany(1)/all(d:d/PropertyInt16 eq 0)")
+ .isExSemantic(MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE);
}
@Test
@@ -5896,87 +5863,103 @@ public class TestFullResourcePath {
.at(3).isNavProperty(entitySetName, nameETNavProp, true);
}
+ // TODO: Better type determination for literal numbers.
@Test
+ @Ignore
public void filterLiteralTypes() throws Exception {
- testUri.run("ESAllPrim", "$filter='1' eq 42")
- .goFilter().isBinary(BinaryOperatorKind.EQ)
- .left().isLiteral("'1'").isLiteralType(oData.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.String))
+ testFilter.runOnETAllPrim("-1000 eq 42")
+ .isBinary(BinaryOperatorKind.EQ)
+ .left().isLiteral("-1000").isLiteralType(oData.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int16))
.root()
.right().isLiteral("42").isLiteralType(oData.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.SByte));
- testUri.run("ESAllPrim", "$filter=127 eq 128")
- .goFilter().isBinary(BinaryOperatorKind.EQ)
+ testFilter.runOnETAllPrim("127 eq 128")
+ .isBinary(BinaryOperatorKind.EQ)
.left().isLiteral("127").isLiteralType(oData.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.SByte))
.root()
.right().isLiteral("128").isLiteralType(oData.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Byte));
- testUri.run("ESAllPrim", "$filter=null eq 42.1")
- .goFilter().isBinary(BinaryOperatorKind.EQ)
+ testFilter.runOnETAllPrim("null eq 42.1")
+ .isBinary(BinaryOperatorKind.EQ)
.left().isLiteral("null").isNullLiteralType()
.root()
.right().isLiteral("42.1").isLiteralType(oData.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Decimal));
- testUri.run("ESAllPrim", "$filter=15.6E300 eq 3.4E37")
- .goFilter().isBinary(BinaryOperatorKind.EQ)
+ testFilter.runOnETAllPrim("15.6E300 eq 3.4E37")
+ .isBinary(BinaryOperatorKind.EQ)
.left().isLiteral("15.6E300")
.isLiteralType(oData.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Double))
.root()
.right().isLiteral("3.4E37").isLiteralType(oData.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Double));
- testUri.run("ESAllPrim", "$filter=15.55555555555555555555555555555555555555555555 eq 3.1")
- .goFilter().isBinary(BinaryOperatorKind.EQ)
+ testFilter.runOnETAllPrim("15.55555555555555555555555555555555555555555555 eq 3.1")
+ .isBinary(BinaryOperatorKind.EQ)
.left().isLiteral("15.55555555555555555555555555555555555555555555")
.isLiteralType(oData.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Decimal))
.root()
.right().isLiteral("3.1").isLiteralType(oData.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Decimal));
- testUri.run("ESAllPrim", "$filter=duration'PT1H2S' eq 2012-12-03")
- .goFilter().isBinary(BinaryOperatorKind.EQ)
+ testFilter.runOnETAllPrim("duration'PT1H2S' eq duration'PT3602S'")
+ .isBinary(BinaryOperatorKind.EQ)
.left().isLiteral("duration'PT1H2S'")
.isLiteralType(oData.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Duration))
.root()
+ .right().isLiteral("duration'PT3602S'")
+ .isLiteralType(oData.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Duration));
+
+ testFilter.runOnETAllPrim("2013-11-02 ne 2012-12-03")
+ .isBinary(BinaryOperatorKind.NE)
+ .left().isLiteral("2013-11-02").isLiteralType(oData.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Date))
+ .root()
.right().isLiteral("2012-12-03").isLiteralType(oData.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Date));
- testUri.run("ESAllPrim", "$filter=true eq 2012-12-03T07:16:23Z")
- .goFilter().isBinary(BinaryOperatorKind.EQ)
- .left().isLiteral("true").isLiteralType(oData.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Boolean))
+ testFilter.runOnETAllPrim("null eq 2012-12-03T07:16:23Z")
+ .isBinary(BinaryOperatorKind.EQ)
+ .left().isLiteral("null")
+ .isNullLiteralType()
.root()
.right().isLiteral("2012-12-03T07:16:23Z")
.isLiteralType(oData.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.DateTimeOffset));
- testUri.run("ESAllPrim", "$filter=07:59:59.999 eq 01234567-89ab-cdef-0123-456789abcdef")
- .goFilter().isBinary(BinaryOperatorKind.EQ)
+ testFilter.runOnETAllPrim("07:59:59.999 eq null")
+ .isBinary(BinaryOperatorKind.EQ)
.left().isLiteral("07:59:59.999")
.isLiteralType(oData.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.TimeOfDay))
.root()
+ .right().isLiteral("null").isNullLiteralType();
+
+ testFilter.runOnETAllPrim("null eq 01234567-89ab-cdef-0123-456789abcdef")
+ .isBinary(BinaryOperatorKind.EQ)
+ .left().isLiteral("null").isNullLiteralType()
+ .root()
.right().isLiteral("01234567-89ab-cdef-0123-456789abcdef")
.isLiteralType(oData.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Guid));
- testUri.run("ESAllPrim", "$filter=binary'0FAB7B' eq true")
- .goFilter().isBinary(BinaryOperatorKind.EQ)
- .left().isLiteral("binary'0FAB7B'").isLiteralType(
+ testFilter.runOnETAllPrim("binary'VGVzdA==' eq null")
+ .isBinary(BinaryOperatorKind.EQ)
+ .left().isLiteral("binary'VGVzdA=='").isLiteralType(
oData.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Binary))
.root()
- .right().isLiteral("true").isLiteralType(oData.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Boolean));
+ .right().isLiteral("null").isNullLiteralType();
- testUri.run("ESAllPrim", "$filter=" + Short.MIN_VALUE + " eq " + Short.MAX_VALUE)
- .goFilter().isBinary(BinaryOperatorKind.EQ)
+ testFilter.runOnETAllPrim(Short.MIN_VALUE + " eq " + Short.MAX_VALUE)
+ .isBinary(BinaryOperatorKind.EQ)
.left().isLiteral(Short.toString(Short.MIN_VALUE))
.isLiteralType(oData.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int16))
.root()
.right().isLiteral(Short.toString(Short.MAX_VALUE))
.isLiteralType(oData.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int16));
- testUri.run("ESAllPrim", "$filter=" + Integer.MIN_VALUE + " eq " + Integer.MAX_VALUE)
- .goFilter().isBinary(BinaryOperatorKind.EQ)
+ testFilter.runOnETAllPrim(Integer.MIN_VALUE + " eq " + Integer.MAX_VALUE)
+ .isBinary(BinaryOperatorKind.EQ)
.left().isLiteral(Integer.toString(Integer.MIN_VALUE))
.isLiteralType(oData.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int32))
.root()
.right().isLiteral(Integer.toString(Integer.MAX_VALUE))
.isLiteralType(oData.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int32));
- testUri.run("ESAllPrim", "$filter=" + Long.MIN_VALUE + " eq " + Long.MAX_VALUE)
- .goFilter().isBinary(BinaryOperatorKind.EQ)
+ testFilter.runOnETAllPrim(Long.MIN_VALUE + " eq " + Long.MAX_VALUE)
+ .isBinary(BinaryOperatorKind.EQ)
.left().isLiteral(Long.toString(Long.MIN_VALUE))
.isLiteralType(oData.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int64))
.root()
@@ -6016,34 +5999,35 @@ public class TestFullResourcePath {
.at(1).isFunction("BFCESTwoKeyNavRTStringParam").isParameterAlias(0, "ParameterComp", "@p1")
.isInAliasToValueMap("@p1", "{\"PropertyInt16\":1,\"PropertyString\":\"" + stringValueDecoded + "\"}");
- testUri.run("ESTwoKeyNav", "$filter=olingo.odata.test1.BFCESTwoKeyNavRTStringParam"
+ testFilter.runOnETTwoKeyNav("olingo.odata.test1.BFCESTwoKeyNavRTStringParam"
+ "(ParameterComp={\"PropertyString\":\"Test\",\"PropertyInt16\":1}) eq 'Test'")
- .goFilter().left().is("<<BFCESTwoKeyNavRTStringParam> eq <'Test'>>")
- .isParameterText(0, "{\"PropertyString\":\"Test\",\"PropertyInt16\":1}");
+ .is("<<BFCESTwoKeyNavRTStringParam> eq <'Test'>>")
+ .isBinary(BinaryOperatorKind.EQ)
+ .left().isParameterText(0, "{\"PropertyString\":\"Test\",\"PropertyInt16\":1}");
- testUri.run("ESTwoKeyNav", "$filter=olingo.odata.test1.BFCESTwoKeyNavRTStringParam"
+ testFilter.runOnETTwoKeyNav("olingo.odata.test1.BFCESTwoKeyNavRTStringParam"
+ "(ParameterComp={\"PropertyString\":\"" + stringValueEncoded + "\",\"PropertyInt16\":1}) eq 'Test'")
- .goFilter().left().is("<<BFCESTwoKeyNavRTStringParam> eq <'Test'>>")
- .isParameterText(0, "{\"PropertyString\":\"" + stringValueDecoded + "\",\"PropertyInt16\":1}");
+ .is("<<BFCESTwoKeyNavRTStringParam> eq <'Test'>>")
+ .left().isParameterText(0, "{\"PropertyString\":\"" + stringValueDecoded + "\",\"PropertyInt16\":1}");
testUri.run("ESTwoKeyNav", "$filter=olingo.odata.test1.BFCESTwoKeyNavRTStringParam"
- + "(ParameterComp=@p1) eq 0&@p1={\"PropertyInt16\":1,\"PropertyString\":\"1\"}");
+ + "(ParameterComp=@p1) eq '0'&@p1={\"PropertyInt16\":1,\"PropertyString\":\"1\"}");
testUri.run("ESTwoKeyNav", "$filter=olingo.odata.test1.BFCESTwoKeyNavRTStringParam"
- + "(ParameterComp=@p1) eq 0&@p1={\"PropertyInt16\":1,\"PropertyString\":null}")
+ + "(ParameterComp=@p1) eq '0'&@p1={\"PropertyInt16\":1,\"PropertyString\":null}")
.goFilter().left().isParameterText(0, null);
testUri.run("ESTwoKeyNav", "$filter=olingo.odata.test1.BFCESTwoKeyNavRTStringParam"
- + "(ParameterComp=@p1) eq 0&@p1={}");
+ + "(ParameterComp=@p1) eq '0'&@p1={}");
testUri.run("ESTwoKeyNav", "$filter=olingo.odata.test1.BFCESTwoKeyNavRTStringParam"
- + "(ParameterComp=@p1) eq 0&@p1={\"PropertyInt16\":[1,2,3],\"PropertyString\":\"1\"}");
+ + "(ParameterComp=@p1) eq '0'&@p1={\"PropertyInt16\":[1,2,3],\"PropertyString\":\"1\"}");
testUri.run("ESTwoKeyNav", "$filter=olingo.odata.test1.BFCESTwoKeyNavRTStringParam"
- + "(ParameterComp=@p1) eq 0&@p1={\"PropertyInt16\":[\"1\",\"2\",\"3\"],\"PropertyString\":\"1\"}");
+ + "(ParameterComp=@p1) eq '0'&@p1={\"PropertyInt16\":[\"1\",\"2\",\"3\"],\"PropertyString\":\"1\"}");
testUri.run("ESTwoKeyNav", "$filter=olingo.odata.test1.BFCESTwoKeyNavRTStringParam"
- + "(ParameterComp=@p1) eq 0&@p1={\"PropertyInt16\":[{\"Prop1\":123,\"Prop2\":\"Test\",\"Prop3\":[1,2,3]},"
+ + "(ParameterComp=@p1) eq '0'&@p1={\"PropertyInt16\":[{\"Prop1\":123,\"Prop2\":\"Test\",\"Prop3\":[1,2,3]},"
+ "{\"Prop1\":{\"Prop1\":[\"Prop\\\":{]\"]}}],\"PropertyString\":\"1\"}");
testUri.run("FINRTByteNineParam(ParameterEnum=null,ParameterDef='x',ParameterComp=@c,"
@@ -6057,7 +6041,7 @@ public class TestFullResourcePath {
testUri.runEx("ESTwoKeyNav/olingo.odata.test1.BFCESTwoKeyNavRTStringParam"
+ "(ParameterComp={\"PropertyInt16\":1,\"PropertyString\":\"Test\"})")
- .isExSemantic(MessageKeys.INVALID_KEY_VALUE);
+ .isExSemantic(MessageKeys.COMPLEX_PARAMETER_IN_RESOURCE_PATH);
testUri.runEx("FICRTCTTwoPrimTwoParam(ParameterInt16=1,ParameterString=null)")
.isExValidation(UriValidationException.MessageKeys.MISSING_PARAMETER);
@@ -6081,34 +6065,33 @@ public class TestFullResourcePath {
testUri.runEx("FICRTCollCTTwoPrimTwoParam(ParameterInt16=1,ParameterString=@test)", "@test=null&@test='1'")
.isExSyntax(UriParserSyntaxException.MessageKeys.DUPLICATED_ALIAS);
- testUri.runEx("ESAllPrim", "$filter=FINRTInt16() eq 0")
- .isExSemantic(MessageKeys.FUNCTION_IMPORT_NOT_ALLOWED);
+ testFilter.runOnETKeyNavEx("FINRTInt16() eq 0")
+ .isExSemantic(MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE);
testUri.runEx("ESTwoKeyNav", "$filter=olingo.odata.test1.BFCESTwoKeyNavRTStringParam"
- + "(ParameterComp=@p1) eq 0&@p1={\"PropertyInt16\":1,\"PropertyString\":\"1\"")
+ + "(ParameterComp=@p1) eq '0'&@p1={\"PropertyInt16\":1,\"PropertyString\":\"1\"")
.isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
testUri.runEx("ESTwoKeyNav", "$filter=olingo.odata.test1.BFCESTwoKeyNavRTStringParam"
- + "(ParameterComp=@p1) eq 0&@p1={\"PropertyInt16\":1,\"PropertyString\":\"1\"}}")
+ + "(ParameterComp=@p1) eq '0'&@p1={\"PropertyInt16\":1,\"PropertyString\":\"1\"}}")
.isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
testUri.runEx("ESTwoKeyNav", "$filter=olingo.odata.test1.BFCESTwoKeyNavRTStringParam"
- + "(ParameterComp=@p1) eq 0&@p1={\"PropertyInt16\":[1,2,3]],\"PropertyString\":\"1\"}")
+ + "(ParameterComp=@p1) eq '0'&@p1={\"PropertyInt16\":[1,2,3]],\"PropertyString\":\"1\"}")
.isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
testUri.runEx("ESTwoKeyNav", "$filter=olingo.odata.test1.BFCESTwoKeyNavRTStringParam"
- + "(ParameterComp=@p1) eq 0&@p1={\"PropertyInt16\":[1,2,3,\"PropertyString\":\"1\"}")
+ + "(ParameterComp=@p1) eq '0'&@p1={\"PropertyInt16\":[1,2,3,\"PropertyString\":\"1\"}")
.isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
testUri.runEx("ESTwoKeyNav", "$filter=olingo.odata.test1.BFCESTwoKeyNavRTStringParam"
- + "(ParameterComp=@p1) eq 0&@p1={\"PropertyInt16\":[1,2,3},\"PropertyString\":\"1\"}")
+ + "(ParameterComp=@p1) eq '0'&@p1={\"PropertyInt16\":[1,2,3},\"PropertyString\":\"1\"}")
.isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
}
@Test
- @Ignore("Key predicates in filter/orderby expression are not validated currently")
- public void testKeyPredicatesInExpressions() throws Exception {
- testUri.run("ESTwoKeyNav", "$filter=NavPropertyETTwoKeyNavMany(PropertyString='1',PropertyInt16=1)"
+ public void keyPredicatesInExpressions() throws Exception {
+ testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavMany(PropertyString='1',PropertyInt16=1)"
+ "/PropertyInt16 eq 1");
testUri.runEx("ESTwoKeyNav", "$filter=NavPropertyETTwoKeyNavMany(Prop='22',P=2)/PropertyInt16 eq 0")
.isExValidation(UriValidationException.MessageKeys.INVALID_KEY_PROPERTY);
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestUriParserImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestUriParserImpl.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestUriParserImpl.java
index 19f5946..8790766 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestUriParserImpl.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestUriParserImpl.java
@@ -38,6 +38,7 @@ import org.apache.olingo.server.tecsvc.provider.ContainerProvider;
import org.apache.olingo.server.tecsvc.provider.EdmTechProvider;
import org.apache.olingo.server.tecsvc.provider.EntityTypeProvider;
import org.apache.olingo.server.tecsvc.provider.PropertyProvider;
+import org.junit.Ignore;
import org.junit.Test;
public class TestUriParserImpl {
@@ -561,11 +562,12 @@ public class TestUriParserImpl {
@Test
public void unary() throws Exception {
testFilter.runOnETAllPrim("not PropertyBoolean").isCompr("<not <PropertyBoolean>>");
- testFilter.runOnETAllPrim("- PropertyInt16 eq PropertyInt16").isCompr("<<- <PropertyInt16>> eq <PropertyInt16>>");
testFilter.runOnETAllPrim("-PropertyInt16 eq PropertyInt16").isCompr("<<- <PropertyInt16>> eq <PropertyInt16>>");
}
+ // TODO: Use correct types.
@Test
+ @Ignore
public void filterComplexMixedPriority() throws Exception {
testFilter.runOnETAllPrim("PropertyInt16 or PropertyInt32 and PropertyInt64")
.isCompr("<<PropertyInt16> or <<PropertyInt32> and <PropertyInt64>>>");
@@ -1069,28 +1071,21 @@ public class TestUriParserImpl {
}
@Test
- public void testLambda() throws Exception {
- testUri.run("ESTwoKeyNav", "$filter=CollPropertyComp/all( l : true )")
- .goFilter().is("<CollPropertyComp/<ALL;<true>>>");
-
- testUri.run("ESTwoKeyNav", "$filter=CollPropertyComp/all( x : x/PropertyInt16 eq 2)")
- .goFilter().is("<CollPropertyComp/<ALL;<<x/PropertyInt16> eq <2>>>>");
-
- testUri.run("ESTwoKeyNav", "$filter=CollPropertyComp/any( l : true )")
- .goFilter().is("<CollPropertyComp/<ANY;<true>>>");
- testUri.run("ESTwoKeyNav", "$filter=CollPropertyComp/any( )")
- .goFilter().is("<CollPropertyComp/<ANY;>>");
-
- testUri.run("ESTwoKeyNav", "$filter=all( l : true )")
- .goFilter().is("<<ALL;<true>>>");
- testUri.run("ESTwoKeyNav", "$filter=any( l : true )")
- .goFilter().is("<<ANY;<true>>>");
- testUri.run("ESTwoKeyNav", "$filter=any( )")
- .goFilter().is("<<ANY;>>");
+ public void lambda() 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;>>");
}
@Test
- public void testCustomQueryOption() throws Exception {
+ public void customQueryOption() throws Exception {
testUri.run("ESTwoKeyNav", "custom")
.isCustomParameter(0, "custom", "");
testUri.run("ESTwoKeyNav", "custom=ABC")
@@ -1098,6 +1093,7 @@ public class TestUriParserImpl {
}
@Test
+ @Ignore("Geo types are not supported yet.")
public void geo() throws Exception {
testFilter.runOnETAllPrim("geo.distance(PropertySByte,PropertySByte)")
.is("<geo.distance(<PropertySByte>,<PropertySByte>)>")
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/queryoption/expression/ExpressionTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/queryoption/expression/ExpressionTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/queryoption/expression/ExpressionTest.java
index 864b17a..fad718b 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/queryoption/expression/ExpressionTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/queryoption/expression/ExpressionTest.java
@@ -128,7 +128,7 @@ public class ExpressionTest {
// UriResourceImpl
EdmAction action = edm.getUnboundAction(ActionProvider.nameUARTString);
UriInfoResource uriInfo = new UriInfoImpl().setKind(UriInfoKind.resource).addResourcePart(
- new UriResourceActionImpl().setAction(action)).asUriInfoResource();
+ new UriResourceActionImpl(action)).asUriInfoResource();
MemberImpl expression = new MemberImpl(uriInfo, null);
assertEquals(action.getReturnType().getType(), expression.getType());
@@ -142,7 +142,7 @@ public class ExpressionTest {
// UriResourceImplTyped check collection = true case
action = edm.getUnboundAction(ActionProvider.nameUARTCollStringTwoParam);
expression = new MemberImpl(new UriInfoImpl().setKind(UriInfoKind.resource)
- .addResourcePart(new UriResourceActionImpl().setAction(action))
+ .addResourcePart(new UriResourceActionImpl(action))
.asUriInfoResource(),
null);
assertTrue(expression.isCollection());
@@ -150,7 +150,7 @@ public class ExpressionTest {
// UriResourceImplTyped with filter
EdmFunction function = edm.getUnboundFunction(FunctionProvider.nameUFCRTETKeyNav, null);
expression = new MemberImpl(new UriInfoImpl().setKind(UriInfoKind.resource).addResourcePart(
- new UriResourceFunctionImpl().setFunction(function).setEntryTypeFilter(entityType))
+ new UriResourceFunctionImpl(null, function, null).setEntryTypeFilter(entityType))
.asUriInfoResource(),
null);
assertEquals(entityType, expression.getType());
@@ -158,7 +158,7 @@ public class ExpressionTest {
// UriResourceImplKeyPred
function = edm.getUnboundFunction(FunctionProvider.nameUFCRTETKeyNav, null);
expression = new MemberImpl(new UriInfoImpl().setKind(UriInfoKind.resource).addResourcePart(
- new UriResourceFunctionImpl().setFunction(function))
+ new UriResourceFunctionImpl(null, function, null))
.asUriInfoResource(),
null);
assertEquals(function.getReturnType().getType(), expression.getType());
@@ -167,7 +167,7 @@ public class ExpressionTest {
EdmEntityType entityBaseType = edm.getEntityType(EntityTypeProvider.nameETBaseTwoKeyNav);
function = edm.getUnboundFunction(FunctionProvider.nameUFCRTCollETTwoKeyNavParam, Arrays.asList("ParameterInt16"));
expression = new MemberImpl(new UriInfoImpl().setKind(UriInfoKind.resource).addResourcePart(
- new UriResourceFunctionImpl().setFunction(function).setEntryTypeFilter(entityBaseType))
+ new UriResourceFunctionImpl(null, function, null).setEntryTypeFilter(entityBaseType))
.asUriInfoResource(),
null);
assertEquals(entityBaseType, expression.getType());
@@ -176,7 +176,7 @@ public class ExpressionTest {
entityBaseType = edm.getEntityType(EntityTypeProvider.nameETBaseTwoKeyNav);
function = edm.getUnboundFunction(FunctionProvider.nameUFCRTCollETTwoKeyNavParam, Arrays.asList("ParameterInt16"));
expression = new MemberImpl(new UriInfoImpl().setKind(UriInfoKind.resource).addResourcePart(
- new UriResourceFunctionImpl().setFunction(function).setCollectionTypeFilter(entityBaseType))
+ new UriResourceFunctionImpl(null, function, null).setCollectionTypeFilter(entityBaseType))
.asUriInfoResource(),
null);
assertEquals(entityBaseType, expression.getType());
[06/30] olingo-odata4 git commit: Merge branch 'master' into
refactorUriParsing
Posted by ch...@apache.org.
Merge branch 'master' into refactorUriParsing
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/7bc932aa
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/7bc932aa
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/7bc932aa
Branch: refs/heads/master
Commit: 7bc932aae980251776ff014712b0a1f7de679b46
Parents: 83f11b9 a47e9f6
Author: Christian Amend <ch...@sap.com>
Authored: Thu Dec 10 15:32:44 2015 +0100
Committer: Christian Amend <ch...@sap.com>
Committed: Thu Dec 10 15:32:44 2015 +0100
----------------------------------------------------------------------
.../edm/primitivetype/EdmDateTimeOffset.java | 8 +++++-
.../primitivetype/EdmDateTimeOffsetTest.java | 16 ++++++++++--
.../edm/primitivetype/EdmTimeOfDayTest.java | 26 +++++++++++++++++++-
3 files changed, 46 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
[09/30] olingo-odata4 git commit: [OLINGO-834] $select parser in Java
+ clean-up
Posted by ch...@apache.org.
[OLINGO-834] $select parser in Java + clean-up
Signed-off-by: Christian Amend <ch...@sap.com>
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/d7e23bf8
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/d7e23bf8
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/d7e23bf8
Branch: refs/heads/master
Commit: d7e23bf89a61df8fdbe53728f201a2686c7f79fc
Parents: ef19c9b
Author: Klaus Straubinger <kl...@sap.com>
Authored: Thu Dec 10 14:56:58 2015 +0100
Committer: Christian Amend <ch...@sap.com>
Committed: Thu Dec 10 15:51:45 2015 +0100
----------------------------------------------------------------------
.../uri/parser/CheckFullContextListener.java | 60 ---
.../olingo/server/core/uri/parser/Parser.java | 507 ++++++++++---------
.../olingo/server/core/uri/parser/RawUri.java | 46 --
.../server/core/uri/parser/SelectParser.java | 241 +++++++++
.../server/core/uri/parser/UriContext.java | 17 +-
.../server/core/uri/parser/UriDecoder.java | 74 +--
.../core/uri/parser/UriParseTreeVisitor.java | 176 ++-----
.../server/core/uri/parser/UriTokenizer.java | 166 ++++--
.../olingo/server/core/uri/UriInfoImplTest.java | 204 ++++++++
.../server/core/uri/parser/UriDecoderTest.java | 94 ++++
.../core/uri/parser/UriTokenizerTest.java | 13 +-
.../olingo/server/core/uri/UriInfoImplTest.java | 212 --------
.../core/uri/antlr/TestFullResourcePath.java | 159 +++++-
.../core/uri/antlr/TestUriParserImpl.java | 60 ---
.../server/core/uri/parser/RawUriTest.java | 150 ------
.../core/uri/testutil/ParserWithLogging.java | 59 ---
.../core/uri/testutil/ResourceValidator.java | 3 +-
.../core/uri/testutil/TestErrorLogger.java | 105 ----
.../core/uri/testutil/TokenValidator.java | 70 +--
.../core/uri/testutil/UriLexerWithTrace.java | 85 ----
20 files changed, 1164 insertions(+), 1337 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/d7e23bf8/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/CheckFullContextListener.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/CheckFullContextListener.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/CheckFullContextListener.java
deleted file mode 100644
index 86efdca..0000000
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/CheckFullContextListener.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.BitSet;
-
-import org.antlr.v4.runtime.DiagnosticErrorListener;
-import org.antlr.v4.runtime.Parser;
-import org.antlr.v4.runtime.RecognitionException;
-import org.antlr.v4.runtime.Recognizer;
-import org.antlr.v4.runtime.atn.ATNConfigSet;
-import org.antlr.v4.runtime.dfa.DFA;
-
-class CheckFullContextListener extends DiagnosticErrorListener {
-
- @Override
- public void syntaxError(final Recognizer<?, ?> recognizer, final Object offendingSymbol, final int line,
- final int charPositionInLine,
- final String msg, final RecognitionException e) {
- // System.err.println("syntaxError detected");
- }
-
- @Override
- public void reportAmbiguity(final Parser recognizer, final DFA dfa, final int startIndex, final int stopIndex,
- final boolean exact,
- final BitSet ambigAlts, final ATNConfigSet configs) {
- // System.err.println("reportAmbiguity detected");
- }
-
- @Override
- public void reportAttemptingFullContext(final Parser recognizer, final DFA dfa, final int startIndex,
- final int stopIndex,
- final BitSet conflictingAlts, final ATNConfigSet configs) {
- // System.err.println("reportAttemptingFullContext detected");
- }
-
- @Override
- public void reportContextSensitivity(final Parser recognizer, final DFA dfa, final int startIndex,
- final int stopIndex, final int prediction,
- final ATNConfigSet configs) {
- // System.err.println("reportContextSensitivity detected");
- }
-
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/d7e23bf8/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
index 5caaaeb..0b53e69 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
@@ -26,11 +26,13 @@ import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.RecognitionException;
-import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.atn.PredictionMode;
import org.antlr.v4.runtime.misc.ParseCancellationException;
import org.apache.olingo.commons.api.edm.Edm;
import org.apache.olingo.commons.api.edm.EdmEntityContainer;
+import org.apache.olingo.commons.api.edm.EdmEntitySet;
+import org.apache.olingo.commons.api.edm.EdmStructuredType;
+import org.apache.olingo.commons.api.edm.EdmType;
import org.apache.olingo.commons.api.ex.ODataRuntimeException;
import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.uri.UriInfo;
@@ -45,28 +47,28 @@ import org.apache.olingo.server.api.uri.UriResourceValue;
import org.apache.olingo.server.api.uri.queryoption.AliasQueryOption;
import org.apache.olingo.server.api.uri.queryoption.CustomQueryOption;
import org.apache.olingo.server.api.uri.queryoption.FilterOption;
+import org.apache.olingo.server.api.uri.queryoption.QueryOption;
import org.apache.olingo.server.api.uri.queryoption.SystemQueryOption;
import org.apache.olingo.server.api.uri.queryoption.SystemQueryOptionKind;
import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
import org.apache.olingo.server.core.uri.UriInfoImpl;
import org.apache.olingo.server.core.uri.UriResourceStartingTypeFilterImpl;
+import org.apache.olingo.server.core.uri.UriResourceTypedImpl;
+import org.apache.olingo.server.core.uri.UriResourceWithKeysImpl;
import org.apache.olingo.server.core.uri.antlr.UriLexer;
import org.apache.olingo.server.core.uri.antlr.UriParserParser;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandItemsEOFContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.FilterExpressionEOFContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.OrderByEOFContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.SelectEOFContext;
import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind;
import org.apache.olingo.server.core.uri.parser.search.SearchParser;
import org.apache.olingo.server.core.uri.queryoption.AliasQueryOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.CountOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.CustomQueryOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.ExpandOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.FilterOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.FormatOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.IdOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.OrderByOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.SelectOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.SkipOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.SkipTokenOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.TopOptionImpl;
@@ -79,12 +81,11 @@ public class Parser {
private static final String AT = "@";
private static final String NULL = "null";
- int logLevel = 0;
private final Edm edm;
private final OData odata;
private enum ParserEntryRules {
- ExpandItems, FilterExpression, Orderby, Select
+ ExpandItems, FilterExpression, Orderby
}
public Parser(final Edm edm, final OData odata) {
@@ -98,242 +99,268 @@ public class Parser {
UriContext context = new UriContext();
UriParseTreeVisitor uriParseTreeVisitor = new UriParseTreeVisitor(edm, context);
- try {
- final RawUri uri = UriDecoder.decodeUri(path, query, fragment, 0); // -> 0 segments are before the service url
-
- // first, read the decoded path segments
- final String firstSegment = uri.pathSegmentListDecoded.isEmpty() ? "" : uri.pathSegmentListDecoded.get(0);
-
- if (firstSegment.isEmpty()) {
- ensureLastSegment(firstSegment, 0, uri.pathSegmentListDecoded.size());
- context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.service);
-
- } else if (firstSegment.equals("$batch")) {
- ensureLastSegment(firstSegment, 1, uri.pathSegmentListDecoded.size());
- context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.batch);
-
- } else if (firstSegment.equals("$metadata")) {
- ensureLastSegment(firstSegment, 1, uri.pathSegmentListDecoded.size());
- context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.metadata);
- context.contextUriInfo.setFragment(uri.fragment);
-
- } else if (firstSegment.equals("$all")) {
- ensureLastSegment(firstSegment, 1, uri.pathSegmentListDecoded.size());
- context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.all);
-
- } else if (firstSegment.equals("$entity")) {
- if (uri.pathSegmentListDecoded.size() > 1) {
- final String typeCastSegment = uri.pathSegmentListDecoded.get(1);
- ensureLastSegment(typeCastSegment, 2, uri.pathSegmentListDecoded.size());
- context.contextUriInfo = new ResourcePathParser(edm, odata).parseDollarEntityTypeCast(typeCastSegment);
- context.contextTypes.push(
- uriParseTreeVisitor.new TypeInformation(context.contextUriInfo.getEntityTypeCast(), false));
- } else {
- context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.entityId);
- }
+ final List<String> pathSegmentsDecoded = UriDecoder.splitAndDecodePath(path);
+ final int numberOfSegments = pathSegmentsDecoded.size();
- } else if (firstSegment.startsWith("$crossjoin")) {
- ensureLastSegment(firstSegment, 1, uri.pathSegmentListDecoded.size());
- context.contextUriInfo = new ResourcePathParser(edm, odata)
- .parseCrossjoinSegment(uri.pathSegmentListDecoded.get(0));
- final EdmEntityContainer container = edm.getEntityContainer();
- for (final String name : context.contextUriInfo.getEntitySetNames()) {
- context.contextTypes.push(
- uriParseTreeVisitor.new TypeInformation(container.getEntitySet(name).getEntityType(), true));
- }
+ // first, read the decoded path segments
+ final String firstSegment = numberOfSegments == 0 ? "" : pathSegmentsDecoded.get(0);
+
+ if (firstSegment.isEmpty()) {
+ ensureLastSegment(firstSegment, 0, numberOfSegments);
+ context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.service);
+ } else if (firstSegment.equals("$batch")) {
+ ensureLastSegment(firstSegment, 1, numberOfSegments);
+ context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.batch);
+
+ } else if (firstSegment.equals("$metadata")) {
+ ensureLastSegment(firstSegment, 1, numberOfSegments);
+ context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.metadata);
+ context.contextUriInfo.setFragment(fragment);
+
+ } else if (firstSegment.equals("$all")) {
+ ensureLastSegment(firstSegment, 1, numberOfSegments);
+ context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.all);
+ // This loads nearly the whole schema, but sooner or later '$all' needs all entity sets anyway.
+ for (final EdmEntitySet entitySet : edm.getEntityContainer().getEntitySets()) {
+ context.contextTypes.push(entitySet.getEntityType());
+ }
+ context.isCollection = true;
+
+ } else if (firstSegment.equals("$entity")) {
+ if (numberOfSegments > 1) {
+ final String typeCastSegment = pathSegmentsDecoded.get(1);
+ ensureLastSegment(typeCastSegment, 2, numberOfSegments);
+ context.contextUriInfo = new ResourcePathParser(edm, odata).parseDollarEntityTypeCast(typeCastSegment);
+ context.contextTypes.push(context.contextUriInfo.getEntityTypeCast());
} else {
- context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.resource);
- final ResourcePathParser resourcePathParser = new ResourcePathParser(edm, odata);
- int count = 0;
- UriResource lastSegment = null;
- for (final String pathSegment : uri.pathSegmentListDecoded) {
- count++;
- final UriResource segment = resourcePathParser.parsePathSegment(pathSegment, lastSegment);
- if (segment != null) {
- if (segment instanceof UriResourceCount
- || segment instanceof UriResourceRef
- || segment instanceof UriResourceValue) {
- ensureLastSegment(pathSegment, count, uri.pathSegmentListDecoded.size());
- } else if (segment instanceof UriResourceAction
- || segment instanceof UriResourceFunction
- && !((UriResourceFunction) segment).getFunction().isComposable()) {
- if (count < uri.pathSegmentListDecoded.size()) {
- throw new UriValidationException(
- "The segment of an action or of a non-composable function must be the last resource-path segment.",
- UriValidationException.MessageKeys.UNALLOWED_RESOURCE_PATH,
- uri.pathSegmentListDecoded.get(count));
- }
- lastSegment = segment;
- } else if (segment instanceof UriResourceStartingTypeFilterImpl) {
- throw new UriParserSemanticException("First resource-path segment must not be namespace-qualified.",
- UriParserSemanticException.MessageKeys.NAMESPACE_NOT_ALLOWED_AT_FIRST_ELEMENT);
- } else {
- lastSegment = segment;
+ context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.entityId);
+ // The type of the entity is not known until the $id query option has been parsed.
+ }
+ context.isCollection = false;
+
+ } else if (firstSegment.startsWith("$crossjoin")) {
+ ensureLastSegment(firstSegment, 1, numberOfSegments);
+ context.contextUriInfo = new ResourcePathParser(edm, odata).parseCrossjoinSegment(firstSegment);
+ final EdmEntityContainer container = edm.getEntityContainer();
+ for (final String name : context.contextUriInfo.getEntitySetNames()) {
+ context.contextTypes.push(container.getEntitySet(name).getEntityType());
+ }
+ context.isCollection = true;
+
+ } else {
+ context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.resource);
+ final ResourcePathParser resourcePathParser = new ResourcePathParser(edm, odata);
+ int count = 0;
+ UriResource lastSegment = null;
+ for (final String pathSegment : pathSegmentsDecoded) {
+ count++;
+ final UriResource segment = resourcePathParser.parsePathSegment(pathSegment, lastSegment);
+ if (segment != null) {
+ if (segment instanceof UriResourceCount
+ || segment instanceof UriResourceRef
+ || segment instanceof UriResourceValue) {
+ ensureLastSegment(pathSegment, count, numberOfSegments);
+ } else if (segment instanceof UriResourceAction
+ || segment instanceof UriResourceFunction
+ && !((UriResourceFunction) segment).getFunction().isComposable()) {
+ if (count < numberOfSegments) {
+ throw new UriValidationException(
+ "The segment of an action or of a non-composable function must be the last resource-path segment.",
+ UriValidationException.MessageKeys.UNALLOWED_RESOURCE_PATH,
+ pathSegmentsDecoded.get(count));
}
- context.contextUriInfo.addResourcePart(segment);
+ lastSegment = segment;
+ } else if (segment instanceof UriResourceStartingTypeFilterImpl) {
+ throw new UriParserSemanticException("First resource-path segment must not be namespace-qualified.",
+ UriParserSemanticException.MessageKeys.NAMESPACE_NOT_ALLOWED_AT_FIRST_ELEMENT);
+ } else {
+ lastSegment = segment;
}
+ context.contextUriInfo.addResourcePart(segment);
}
+ }
- if (lastSegment instanceof UriResourcePartTyped) {
- UriResourcePartTyped typed = (UriResourcePartTyped) lastSegment;
-
- UriParseTreeVisitor.TypeInformation myType = uriParseTreeVisitor.getTypeInformation(typed);
- UriParseTreeVisitor.TypeInformation typeInfo =
- uriParseTreeVisitor.new TypeInformation(myType.type, typed.isCollection());
- context.contextTypes.push(typeInfo);
+ if (lastSegment instanceof UriResourcePartTyped) {
+ final UriResourcePartTyped typed = (UriResourcePartTyped) lastSegment;
+ final EdmType type = getTypeInformation(typed);
+ if (type != null) { // could be null for, e.g., actions without return type
+ context.contextTypes.push(type);
}
+ context.isCollection = typed.isCollection();
}
+ }
- // second, read the system query options and the custom query options
- for (final RawUri.QueryOption option : uri.queryOptionListDecoded) {
- if (option.name.startsWith("$")) {
- SystemQueryOption systemOption = null;
- if (option.name.equals(SystemQueryOptionKind.FILTER.toString())) {
+ // second, read the system query options and the custom query options
+ final List<QueryOption> options = UriDecoder.splitAndDecodeOptions(query);
+ for (final QueryOption option : options) {
+ final String optionName = option.getName();
+ final String optionValue = option.getText();
+ if (optionName.startsWith("$")) {
+ SystemQueryOption systemOption = null;
+ if (optionName.equals(SystemQueryOptionKind.FILTER.toString())) {
+ try {
FilterExpressionEOFContext ctxFilterExpression =
- (FilterExpressionEOFContext) parseRule(option.value, ParserEntryRules.FilterExpression);
+ (FilterExpressionEOFContext) parseRule(optionValue, ParserEntryRules.FilterExpression);
systemOption = (FilterOptionImpl) uriParseTreeVisitor.visitFilterExpressionEOF(ctxFilterExpression);
+ } catch (final ParseCancellationException e) {
+ throw e.getCause() instanceof UriParserException ?
+ (UriParserException) e.getCause() :
+ new UriParserSyntaxException("Syntax error", e, UriParserSyntaxException.MessageKeys.SYNTAX);
+ }
- } else if (option.name.equals(SystemQueryOptionKind.FORMAT.toString())) {
- FormatOptionImpl formatOption = new FormatOptionImpl();
- formatOption.setName(option.name);
- formatOption.setText(option.value);
- if (option.value.equalsIgnoreCase(JSON)
- || option.value.equalsIgnoreCase(XML)
- || option.value.equalsIgnoreCase(ATOM)
- || isFormatSyntaxValid(option.value)) {
- formatOption.setFormat(option.value);
- } else {
- throw new UriParserSyntaxException("Illegal value of $format option!",
- UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION_FORMAT, option.value);
- }
- systemOption = formatOption;
+ } else if (optionName.equals(SystemQueryOptionKind.FORMAT.toString())) {
+ FormatOptionImpl formatOption = new FormatOptionImpl();
+ formatOption.setText(optionValue);
+ if (optionValue.equalsIgnoreCase(JSON)
+ || optionValue.equalsIgnoreCase(XML)
+ || optionValue.equalsIgnoreCase(ATOM)
+ || isFormatSyntaxValid(optionValue)) {
+ formatOption.setFormat(optionValue);
+ } else {
+ throw new UriParserSyntaxException("Illegal value of $format option!",
+ UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION_FORMAT, optionValue);
+ }
+ systemOption = formatOption;
- } else if (option.name.equals(SystemQueryOptionKind.EXPAND.toString())) {
+ } else if (optionName.equals(SystemQueryOptionKind.EXPAND.toString())) {
+ try {
ExpandItemsEOFContext ctxExpandItems =
- (ExpandItemsEOFContext) parseRule(option.value, ParserEntryRules.ExpandItems);
+ (ExpandItemsEOFContext) parseRule(optionValue, ParserEntryRules.ExpandItems);
systemOption = (ExpandOptionImpl) uriParseTreeVisitor.visitExpandItemsEOF(ctxExpandItems);
+ } catch (final ParseCancellationException e) {
+ throw e.getCause() instanceof UriParserException ?
+ (UriParserException) e.getCause() :
+ new UriParserSyntaxException("Syntax error", e, UriParserSyntaxException.MessageKeys.SYNTAX);
+ }
- } else if (option.name.equals(SystemQueryOptionKind.ID.toString())) {
- IdOptionImpl idOption = new IdOptionImpl();
- idOption.setName(option.name);
- idOption.setText(option.value);
- idOption.setValue(option.value);
- systemOption = idOption;
+ } else if (optionName.equals(SystemQueryOptionKind.ID.toString())) {
+ IdOptionImpl idOption = new IdOptionImpl();
+ idOption.setText(optionValue);
+ idOption.setValue(optionValue);
+ systemOption = idOption;
- } else if (option.name.equals(SystemQueryOptionKind.LEVELS.toString())) {
- throw new UriParserSyntaxException("System query option '$levels' is allowed only inside '$expand'!",
- UriParserSyntaxException.MessageKeys.SYSTEM_QUERY_OPTION_LEVELS_NOT_ALLOWED_HERE);
+ } else if (optionName.equals(SystemQueryOptionKind.LEVELS.toString())) {
+ throw new UriParserSyntaxException("System query option '$levels' is allowed only inside '$expand'!",
+ UriParserSyntaxException.MessageKeys.SYSTEM_QUERY_OPTION_LEVELS_NOT_ALLOWED_HERE);
- } else if (option.name.equals(SystemQueryOptionKind.ORDERBY.toString())) {
+ } else if (optionName.equals(SystemQueryOptionKind.ORDERBY.toString())) {
+ try {
OrderByEOFContext ctxOrderByExpression =
- (OrderByEOFContext) parseRule(option.value, ParserEntryRules.Orderby);
+ (OrderByEOFContext) parseRule(optionValue, ParserEntryRules.Orderby);
systemOption = (OrderByOptionImpl) uriParseTreeVisitor.visitOrderByEOF(ctxOrderByExpression);
+ } catch (final ParseCancellationException e) {
+ throw e.getCause() instanceof UriParserException ?
+ (UriParserException) e.getCause() :
+ new UriParserSyntaxException("Syntax error", e, UriParserSyntaxException.MessageKeys.SYNTAX);
+ }
- } else if (option.name.equals(SystemQueryOptionKind.SEARCH.toString())) {
- systemOption = new SearchParser().parse(option.value);
+ } else if (optionName.equals(SystemQueryOptionKind.SEARCH.toString())) {
+ systemOption = new SearchParser().parse(optionValue);
+
+ } else if (optionName.equals(SystemQueryOptionKind.SELECT.toString())) {
+ UriTokenizer selectTokenizer = new UriTokenizer(optionValue);
+ systemOption = new SelectParser(edm).parse(selectTokenizer,
+ context.contextTypes.peek() instanceof EdmStructuredType ?
+ (EdmStructuredType) context.contextTypes.peek() :
+ null,
+ context.isCollection);
+ if (!selectTokenizer.next(TokenKind.EOF)) {
+ throw new UriParserSyntaxException("Illegal value of $select option!",
+ UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION,
+ optionName, optionValue);
+ }
- } else if (option.name.equals(SystemQueryOptionKind.SELECT.toString())) {
- SelectEOFContext ctxSelectEOF =
- (SelectEOFContext) parseRule(option.value, ParserEntryRules.Select);
- systemOption = (SelectOptionImpl) uriParseTreeVisitor.visitSelectEOF(ctxSelectEOF);
+ } else if (optionName.equals(SystemQueryOptionKind.SKIP.toString())) {
+ SkipOptionImpl skipOption = new SkipOptionImpl();
+ skipOption.setText(optionValue);
+ try {
+ skipOption.setValue(Integer.parseInt(optionValue));
+ } catch (final NumberFormatException e) {
+ throw new UriParserSyntaxException("Illegal value of $skip option!", e,
+ UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION,
+ optionName, optionValue);
+ }
+ systemOption = skipOption;
- } else if (option.name.equals(SystemQueryOptionKind.SKIP.toString())) {
- SkipOptionImpl skipOption = new SkipOptionImpl();
- skipOption.setName(option.name);
- skipOption.setText(option.value);
- try {
- skipOption.setValue(Integer.parseInt(option.value));
- } catch (final NumberFormatException e) {
- throw new UriParserSyntaxException("Illegal value of $skip option!", e,
- UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION,
- option.name, option.value);
- }
- systemOption = skipOption;
-
- } else if (option.name.equals(SystemQueryOptionKind.SKIPTOKEN.toString())) {
- SkipTokenOptionImpl skipTokenOption = new SkipTokenOptionImpl();
- skipTokenOption.setName(option.name);
- skipTokenOption.setText(option.value);
- skipTokenOption.setValue(option.value);
- systemOption = skipTokenOption;
-
- } else if (option.name.equals(SystemQueryOptionKind.TOP.toString())) {
- TopOptionImpl topOption = new TopOptionImpl();
- topOption.setName(option.name);
- topOption.setText(option.value);
- try {
- topOption.setValue(Integer.parseInt(option.value));
- } catch (final NumberFormatException e) {
- throw new UriParserSyntaxException("Illegal value of $top option!", e,
- UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION,
- option.name, option.value);
- }
- systemOption = topOption;
-
- } else if (option.name.equals(SystemQueryOptionKind.COUNT.toString())) {
- CountOptionImpl inlineCountOption = new CountOptionImpl();
- inlineCountOption.setName(option.name);
- inlineCountOption.setText(option.value);
- if (option.value.equals("true") || option.value.equals("false")) {
- inlineCountOption.setValue(Boolean.parseBoolean(option.value));
- } else {
- throw new UriParserSyntaxException("Illegal value of $count option!",
- UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION,
- option.name, option.value);
- }
- systemOption = inlineCountOption;
+ } else if (optionName.equals(SystemQueryOptionKind.SKIPTOKEN.toString())) {
+ SkipTokenOptionImpl skipTokenOption = new SkipTokenOptionImpl();
+ skipTokenOption.setText(optionValue);
+ skipTokenOption.setValue(optionValue);
+ systemOption = skipTokenOption;
- } else {
- throw new UriParserSyntaxException("Unknown system query option!",
- UriParserSyntaxException.MessageKeys.UNKNOWN_SYSTEM_QUERY_OPTION, option.name);
- }
+ } else if (optionName.equals(SystemQueryOptionKind.TOP.toString())) {
+ TopOptionImpl topOption = new TopOptionImpl();
+ topOption.setText(optionValue);
try {
- context.contextUriInfo.setSystemQueryOption(systemOption);
- } catch (final ODataRuntimeException e) {
- throw new UriParserSyntaxException("Double system query option!", e,
- UriParserSyntaxException.MessageKeys.DOUBLE_SYSTEM_QUERY_OPTION, option.name);
+ topOption.setValue(Integer.parseInt(optionValue));
+ } catch (final NumberFormatException e) {
+ throw new UriParserSyntaxException("Illegal value of $top option!", e,
+ UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION,
+ optionName, optionValue);
}
+ systemOption = topOption;
- } else if (option.name.startsWith(AT)) {
- if (context.contextUriInfo.getAlias(option.name) == null) {
- // TODO: Create a proper alias-value parser that can parse also common expressions.
- Expression expression = null;
- if (!option.value.isEmpty() && (option.value.charAt(0) == '[' || option.value.charAt(0) == '{')) {
- UriTokenizer tokenizer = new UriTokenizer(option.value);
- if (!(tokenizer.next(TokenKind.jsonArrayOrObject) && tokenizer.next(TokenKind.EOF))) {
- throw new UriParserSyntaxException("Illegal value for alias '" + option.name + "'.",
- UriParserSyntaxException.MessageKeys.SYNTAX);
- }
- } else {
+ } else if (optionName.equals(SystemQueryOptionKind.COUNT.toString())) {
+ CountOptionImpl inlineCountOption = new CountOptionImpl();
+ inlineCountOption.setText(optionValue);
+ if (optionValue.equals("true") || optionValue.equals("false")) {
+ inlineCountOption.setValue(Boolean.parseBoolean(optionValue));
+ } else {
+ throw new UriParserSyntaxException("Illegal value of $count option!",
+ UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION,
+ optionName, optionValue);
+ }
+ systemOption = inlineCountOption;
+
+ } else {
+ throw new UriParserSyntaxException("Unknown system query option!",
+ UriParserSyntaxException.MessageKeys.UNKNOWN_SYSTEM_QUERY_OPTION, optionName);
+ }
+ try {
+ context.contextUriInfo.setSystemQueryOption(systemOption);
+ } catch (final ODataRuntimeException e) {
+ throw new UriParserSyntaxException("Double system query option!", e,
+ UriParserSyntaxException.MessageKeys.DOUBLE_SYSTEM_QUERY_OPTION, optionName);
+ }
+
+ } else if (optionName.startsWith(AT)) {
+ if (context.contextUriInfo.getAlias(optionName) == null) {
+ // TODO: Create a proper alias-value parser that can parse also common expressions.
+ Expression expression = null;
+ UriTokenizer aliasTokenizer = new UriTokenizer(optionValue);
+ if (aliasTokenizer.next(TokenKind.jsonArrayOrObject)) {
+ if (!aliasTokenizer.next(TokenKind.EOF)) {
+ throw new UriParserSyntaxException("Illegal value for alias '" + optionName + "'.",
+ UriParserSyntaxException.MessageKeys.SYNTAX);
+ }
+ } else {
+ try {
final FilterExpressionEOFContext filterExpCtx =
- (FilterExpressionEOFContext) parseRule(option.value, ParserEntryRules.FilterExpression);
+ (FilterExpressionEOFContext) parseRule(optionValue, ParserEntryRules.FilterExpression);
expression = ((FilterOption) uriParseTreeVisitor.visitFilterExpressionEOF(filterExpCtx))
.getExpression();
+ } catch (final ParseCancellationException e) {
+ throw e.getCause() instanceof UriParserException ?
+ (UriParserException) e.getCause() :
+ new UriParserSyntaxException("Syntax error", e, UriParserSyntaxException.MessageKeys.SYNTAX);
}
- context.contextUriInfo.addAlias((AliasQueryOption) new AliasQueryOptionImpl()
- .setAliasValue(expression)
- .setName(option.name)
- .setText(NULL.equals(option.value) ? null : option.value));
- } else {
- throw new UriParserSyntaxException("Alias already specified! Name: " + option.name,
- UriParserSyntaxException.MessageKeys.DUPLICATED_ALIAS, option.name);
}
-
+ context.contextUriInfo.addAlias((AliasQueryOption) new AliasQueryOptionImpl()
+ .setAliasValue(expression)
+ .setName(optionName)
+ .setText(NULL.equals(optionValue) ? null : optionValue));
} else {
- context.contextUriInfo.addCustomQueryOption((CustomQueryOption)
- new CustomQueryOptionImpl()
- .setName(option.name)
- .setText(option.value));
+ throw new UriParserSyntaxException("Alias already specified! Name: " + optionName,
+ UriParserSyntaxException.MessageKeys.DUPLICATED_ALIAS, optionName);
}
- }
- return context.contextUriInfo;
- } catch (ParseCancellationException e) {
- throw e.getCause() instanceof UriParserException ?
- (UriParserException) e.getCause() :
- new UriParserSyntaxException("Syntax error", e, UriParserSyntaxException.MessageKeys.SYNTAX);
+ } else {
+ context.contextUriInfo.addCustomQueryOption((CustomQueryOption) option);
+ }
}
+
+ return context.contextUriInfo;
}
private void ensureLastSegment(final String segment, final int pos, final int size)
@@ -349,6 +376,30 @@ public class Parser {
return index > 0 && index < value.length() - 1 && index == value.lastIndexOf('/');
}
+ protected static EdmType getTypeInformation(final UriResourcePartTyped resourcePart) {
+ EdmType type = null;
+ if (resourcePart instanceof UriResourceWithKeysImpl) {
+ final UriResourceWithKeysImpl lastPartWithKeys = (UriResourceWithKeysImpl) resourcePart;
+ if (lastPartWithKeys.getTypeFilterOnEntry() != null) {
+ type = lastPartWithKeys.getTypeFilterOnEntry();
+ } else if (lastPartWithKeys.getTypeFilterOnCollection() != null) {
+ type = lastPartWithKeys.getTypeFilterOnCollection();
+ } else {
+ type = lastPartWithKeys.getType();
+ }
+
+ } else if (resourcePart instanceof UriResourceTypedImpl) {
+ final UriResourceTypedImpl lastPartTyped = (UriResourceTypedImpl) resourcePart;
+ type = lastPartTyped.getTypeFilter() == null ?
+ lastPartTyped.getType() :
+ lastPartTyped.getTypeFilter();
+ } else {
+ type = resourcePart.getType();
+ }
+
+ return type;
+ }
+
private ParserRuleContext parseRule(final String input, final ParserEntryRules entryPoint)
throws UriParserSyntaxException {
UriParserParser parser = null;
@@ -362,17 +413,11 @@ public class Parser {
try {
// create parser
- if (logLevel > 0) {
- //TODO: Discuss if we should keep this code
- lexer = new UriLexer(new ANTLRInputStream(input));
- showTokens(input, lexer.getAllTokens());
- }
-
lexer = new UriLexer(new ANTLRInputStream(input));
parser = new UriParserParser(new CommonTokenStream(lexer));
// Set error strategy
- addStage1ErrorStategy(parser);
+ addStage1ErrorStrategy(parser);
// Set error collector
addStage1ErrorListener(parser);
@@ -394,9 +439,6 @@ public class Parser {
lexer.mode(Lexer.DEFAULT_MODE);
ret = parser.expandItemsEOF();
break;
- case Select:
- ret = parser.selectEOF();
- break;
default:
break;
@@ -411,7 +453,7 @@ public class Parser {
parser = new UriParserParser(new CommonTokenStream(lexer));
// Set error strategy
- addStage2ErrorStategy(parser);
+ addStage2ErrorStrategy(parser);
// Set error collector
addStage2ErrorListener(parser);
@@ -433,9 +475,6 @@ public class Parser {
lexer.mode(Lexer.DEFAULT_MODE);
ret = parser.expandItemsEOF();
break;
- case Select:
- ret = parser.selectEOF();
- break;
default:
break;
}
@@ -454,13 +493,13 @@ public class Parser {
return ret;
}
- protected void addStage1ErrorStategy(final UriParserParser parser) {
+ protected void addStage1ErrorStrategy(final UriParserParser parser) {
// Throw exception at first syntax error
parser.setErrorHandler(new BailErrorStrategy());
}
- protected void addStage2ErrorStategy(final UriParserParser parser) {
+ protected void addStage2ErrorStrategy(final UriParserParser parser) {
// Throw exception at first syntax error
parser.setErrorHandler(new BailErrorStrategy());
}
@@ -468,36 +507,10 @@ public class Parser {
protected void addStage1ErrorListener(final UriParserParser parser) {
// No error logging to System.out or System.err, only exceptions used (depending on ErrorStrategy)
parser.removeErrorListeners();
- parser.addErrorListener(new CheckFullContextListener());
-
}
protected void addStage2ErrorListener(final UriParserParser parser) {
// No error logging to System.out or System.err, only exceptions used (depending on ErrorStrategy)
parser.removeErrorListeners();
}
-
- public void showTokens(final String input, final List<? extends Token> list) {
- boolean first = true;
- System.out.println("input: " + input);
- String nL = "\n";
- StringBuilder out = new StringBuilder("[").append(nL);
- for (Token token : list) {
- if (!first) {
- out.append(",");
- first = false;
- }
- int index = token.getType();
- out.append("\"").append(token.getText()).append("\"").append(" ");
- if (index != -1) {
- out.append(UriLexer.VOCABULARY.getDisplayName(index));
- } else {
- out.append(index);
- }
- out.append(nL);
- }
- out.append(']');
- System.out.println("tokens: " + out.toString());
- }
-
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/d7e23bf8/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/RawUri.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/RawUri.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/RawUri.java
deleted file mode 100644
index 42e0a0f..0000000
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/RawUri.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.List;
-
-public class RawUri {
- public String uri;
- public String scheme;
- public String authority;
- public String path;
- public String queryOptionString;
- public String fragment;
- public List<QueryOption> queryOptionList;
- public List<QueryOption> queryOptionListDecoded;
-
- public List<String> pathSegmentList;
- public List<String> pathSegmentListDecoded;
-
- public static class QueryOption {
- public String name;
- public String value;
-
- QueryOption(final String name, final String value) {
- this.name = name;
- this.value = value;
- }
-
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/d7e23bf8/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/SelectParser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/SelectParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/SelectParser.java
new file mode 100644
index 0000000..3d933d2
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/SelectParser.java
@@ -0,0 +1,241 @@
+/*
+ * 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.ArrayList;
+import java.util.List;
+
+import org.apache.olingo.commons.api.edm.Edm;
+import org.apache.olingo.commons.api.edm.EdmAction;
+import org.apache.olingo.commons.api.edm.EdmComplexType;
+import org.apache.olingo.commons.api.edm.EdmFunction;
+import org.apache.olingo.commons.api.edm.EdmNavigationProperty;
+import org.apache.olingo.commons.api.edm.EdmProperty;
+import org.apache.olingo.commons.api.edm.EdmStructuredType;
+import org.apache.olingo.commons.api.edm.FullQualifiedName;
+import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
+import org.apache.olingo.server.api.uri.UriInfoKind;
+import org.apache.olingo.server.api.uri.UriResourcePartTyped;
+import org.apache.olingo.server.api.uri.queryoption.SelectItem;
+import org.apache.olingo.server.api.uri.queryoption.SelectOption;
+import org.apache.olingo.server.core.uri.UriInfoImpl;
+import org.apache.olingo.server.core.uri.UriResourceActionImpl;
+import org.apache.olingo.server.core.uri.UriResourceComplexPropertyImpl;
+import org.apache.olingo.server.core.uri.UriResourceFunctionImpl;
+import org.apache.olingo.server.core.uri.UriResourceNavigationPropertyImpl;
+import org.apache.olingo.server.core.uri.UriResourcePrimitivePropertyImpl;
+import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind;
+import org.apache.olingo.server.core.uri.queryoption.SelectItemImpl;
+import org.apache.olingo.server.core.uri.queryoption.SelectOptionImpl;
+import org.apache.olingo.server.core.uri.validator.UriValidationException;
+
+public class SelectParser {
+
+ private final Edm edm;
+
+ public SelectParser(final Edm edm) {
+ this.edm = edm;
+ }
+
+ public SelectOption parse(UriTokenizer tokenizer, final EdmStructuredType referencedType,
+ final boolean referencedIsCollection) throws UriParserException, UriValidationException {
+ List<SelectItem> selectItems = new ArrayList<SelectItem>();
+ SelectItem item;
+ do {
+ item = parseItem(tokenizer, referencedType, referencedIsCollection);
+ selectItems.add(item);
+ } while (tokenizer.next(TokenKind.COMMA));
+
+ return new SelectOptionImpl().setSelectItems(selectItems);
+ }
+
+ private SelectItem parseItem(UriTokenizer tokenizer,
+ final EdmStructuredType referencedType, final boolean referencedIsCollection) throws UriParserException {
+ SelectItemImpl item = new SelectItemImpl();
+ if (tokenizer.next(TokenKind.STAR)) {
+ item.setStar(true);
+
+ } else if (tokenizer.next(TokenKind.QualifiedName)) {
+ // The namespace or its alias could consist of dot-separated OData identifiers.
+ final FullQualifiedName allOperationsInSchema = parseAllOperationsInSchema(tokenizer);
+ if (allOperationsInSchema != null) {
+ item.addAllOperationsInSchema(allOperationsInSchema);
+
+ } else {
+ ensureReferencedTypeNotNull(referencedType);
+ final FullQualifiedName qualifiedName = new FullQualifiedName(tokenizer.getText());
+ EdmStructuredType type = edm.getEntityType(qualifiedName);
+ if (type == null) {
+ type = edm.getComplexType(qualifiedName);
+ }
+ if (type == null) {
+ item.setResourcePath(new UriInfoImpl().setKind(UriInfoKind.resource).addResourcePart(
+ parseBoundOperation(tokenizer, qualifiedName, referencedType, referencedIsCollection)));
+
+ } else {
+ if (type.compatibleTo(referencedType)) {
+ item.setTypeFilter(type);
+ if (tokenizer.next(TokenKind.SLASH)) {
+ requireNext(tokenizer, TokenKind.ODataIdentifier);
+ UriInfoImpl resource = new UriInfoImpl().setKind(UriInfoKind.resource);
+ addSelectPath(tokenizer, type, resource);
+ item.setResourcePath(resource);
+ }
+ } else {
+ throw new UriParserSemanticException("The type cast is not compatible.",
+ UriParserSemanticException.MessageKeys.INCOMPATIBLE_TYPE_FILTER, type.getName());
+ }
+ }
+ }
+
+ } else {
+ requireNext(tokenizer, TokenKind.ODataIdentifier);
+ // The namespace or its alias could be a single OData identifier.
+ final FullQualifiedName allOperationsInSchema = parseAllOperationsInSchema(tokenizer);
+ if (allOperationsInSchema != null) {
+ item.addAllOperationsInSchema(allOperationsInSchema);
+
+ } else {
+ ensureReferencedTypeNotNull(referencedType);
+ UriInfoImpl resource = new UriInfoImpl().setKind(UriInfoKind.resource);
+ addSelectPath(tokenizer, referencedType, resource);
+ item.setResourcePath(resource);
+ }
+ }
+
+ return item;
+ }
+
+ private FullQualifiedName parseAllOperationsInSchema(UriTokenizer tokenizer) throws UriParserException {
+ final String name = tokenizer.getText();
+ if (tokenizer.next(TokenKind.DOT)) {
+ if (tokenizer.next(TokenKind.STAR)) {
+ // TODO: Validate the namespace without loading the whole schema.
+ return new FullQualifiedName(name, tokenizer.getText());
+ } else {
+ throw new UriParserSemanticException("Expected star after dot.",
+ UriParserSemanticException.MessageKeys.UNKNOWN_PART, "");
+ }
+ }
+ return null;
+ }
+
+ private void ensureReferencedTypeNotNull(final EdmStructuredType referencedType) throws UriParserException {
+ if (referencedType == null) {
+ throw new UriParserSemanticException("The referenced part is not typed.",
+ UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PARTS, "select");
+ }
+ }
+
+ private UriResourcePartTyped parseBoundOperation(UriTokenizer tokenizer, final FullQualifiedName qualifiedName,
+ final EdmStructuredType referencedType, final boolean referencedIsCollection) throws UriParserException {
+ final EdmAction boundAction = edm.getBoundAction(qualifiedName,
+ referencedType.getFullQualifiedName(),
+ referencedIsCollection);
+ if (boundAction == null) {
+ final List<String> parameterNames = parseFunctionParameterNames(tokenizer);
+ final EdmFunction boundFunction = edm.getBoundFunction(qualifiedName,
+ referencedType.getFullQualifiedName(), referencedIsCollection, parameterNames);
+ if (boundFunction == null) {
+ throw new UriParserSemanticException("Function not found.",
+ UriParserSemanticException.MessageKeys.UNKNOWN_PART, qualifiedName.getFullQualifiedNameAsString());
+ } else {
+ return new UriResourceFunctionImpl().setFunction(boundFunction);
+ }
+ } else {
+ return new UriResourceActionImpl().setAction(boundAction);
+ }
+ }
+
+ private List<String> parseFunctionParameterNames(UriTokenizer tokenizer) throws UriParserException {
+ List<String> names = new ArrayList<String>();
+ if (tokenizer.next(TokenKind.OPEN)) {
+ do {
+ requireNext(tokenizer, TokenKind.ODataIdentifier);
+ names.add(tokenizer.getText());
+ } while (tokenizer.next(TokenKind.COMMA));
+ requireNext(tokenizer, TokenKind.CLOSE);
+ }
+ return names;
+ }
+
+ private void addSelectPath(UriTokenizer tokenizer, final EdmStructuredType referencedType, UriInfoImpl resource)
+ throws UriParserException {
+ final String name = tokenizer.getText();
+ final EdmProperty property = referencedType.getStructuralProperty(name);
+
+ if (property == null) {
+ final EdmNavigationProperty navigationProperty = referencedType.getNavigationProperty(name);
+ if (navigationProperty == null) {
+ throw new UriParserSemanticException("Selected property not found.",
+ UriParserSemanticException.MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE,
+ referencedType.getName(), name);
+ } else {
+ resource.addResourcePart(new UriResourceNavigationPropertyImpl().setNavigationProperty(navigationProperty));
+ }
+
+ } else if (property.isPrimitive()
+ || property.getType().getKind() == EdmTypeKind.ENUM
+ || property.getType().getKind() == EdmTypeKind.DEFINITION) {
+ resource.addResourcePart(new UriResourcePrimitivePropertyImpl().setProperty(property));
+
+ } else {
+ UriResourceComplexPropertyImpl complexPart = new UriResourceComplexPropertyImpl().setProperty(property);
+ resource.addResourcePart(complexPart);
+ if (tokenizer.next(TokenKind.SLASH)) {
+ if (tokenizer.next(TokenKind.QualifiedName)) {
+ final FullQualifiedName qualifiedName = new FullQualifiedName(tokenizer.getText());
+ final EdmComplexType type = edm.getComplexType(qualifiedName);
+ if (type == null) {
+ throw new UriParserSemanticException("Type not found.",
+ UriParserSemanticException.MessageKeys.UNKNOWN_TYPE, qualifiedName.getFullQualifiedNameAsString());
+ } else if (type.compatibleTo(property.getType())) {
+ complexPart.setTypeFilter(type);
+ if (tokenizer.next(TokenKind.SLASH)) {
+ if (tokenizer.next(TokenKind.ODataIdentifier)) {
+ addSelectPath(tokenizer, type, resource);
+ } else {
+ throw new UriParserSemanticException("Unknown part after '/'.",
+ UriParserSemanticException.MessageKeys.UNKNOWN_PART, "");
+ }
+ }
+ } else {
+ throw new UriParserSemanticException("The type cast is not compatible.",
+ UriParserSemanticException.MessageKeys.INCOMPATIBLE_TYPE_FILTER, type.getName());
+ }
+ } else if (tokenizer.next(TokenKind.ODataIdentifier)) {
+ addSelectPath(tokenizer, (EdmStructuredType) property.getType(), resource);
+ } else if (tokenizer.next(TokenKind.SLASH)) {
+ throw new UriParserSyntaxException("Illegal $select expression.",
+ UriParserSyntaxException.MessageKeys.SYNTAX);
+ } else {
+ throw new UriParserSemanticException("Unknown part after '/'.",
+ UriParserSemanticException.MessageKeys.UNKNOWN_PART, "");
+ }
+ }
+ }
+ }
+
+ private void requireNext(UriTokenizer tokenizer, final TokenKind kind) throws UriParserSyntaxException {
+ if (!tokenizer.next(kind)) {
+ throw new UriParserSyntaxException("Illegal $select expression.",
+ UriParserSyntaxException.MessageKeys.SYNTAX);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/d7e23bf8/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriContext.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriContext.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriContext.java
index b6b6fda..c0db85b 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriContext.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriContext.java
@@ -18,11 +18,11 @@
*/
package org.apache.olingo.server.core.uri.parser;
-import java.util.Stack;
+import java.util.ArrayDeque;
+import java.util.Deque;
import org.apache.olingo.commons.api.edm.EdmType;
import org.apache.olingo.server.core.uri.UriInfoImpl;
-import org.apache.olingo.server.core.uri.parser.UriParseTreeVisitor.TypeInformation;
import org.apache.olingo.server.core.uri.queryoption.ExpandItemImpl;
import org.apache.olingo.server.core.uri.queryoption.SelectItemImpl;
@@ -33,9 +33,9 @@ import org.apache.olingo.server.core.uri.queryoption.SelectItemImpl;
public class UriContext {
public static class LambdaVariables {
- public boolean isCollection;
public String name;
public EdmType type;
+ public boolean isCollection;
}
/**
@@ -43,11 +43,14 @@ public class UriContext {
* As lambda functions can be nested there may be more than one allowed lambda variables at a time while parsing a
* $filter or $orderby expressions.
*/
- public Stack<LambdaVariables> allowedLambdaVariables;
+ public Deque<LambdaVariables> allowedLambdaVariables;
/**
* Used to stack type information for nested $expand, $filter query options and other cases.
*/
- public Stack<TypeInformation> contextTypes;
+ public Deque<EdmType> contextTypes;
+
+ /** Whether the context types are collections. */
+ public boolean isCollection;
// CHECKSTYLE:OFF (Maven checkstyle)
/**
@@ -106,8 +109,8 @@ public class UriContext {
contextExpandItemPath = null;
contextReadingFunctionParameters = false;
contextSelectItem = null;
- contextTypes = new Stack<UriParseTreeVisitor.TypeInformation>();
- allowedLambdaVariables = new Stack<UriContext.LambdaVariables>();
+ contextTypes = new ArrayDeque<EdmType>();
+ allowedLambdaVariables = new ArrayDeque<UriContext.LambdaVariables>();
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/d7e23bf8/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriDecoder.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriDecoder.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriDecoder.java
index 4649ac5..4dd7e1c 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriDecoder.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriDecoder.java
@@ -25,53 +25,42 @@ import java.util.LinkedList;
import java.util.List;
import org.apache.olingo.commons.core.Decoder;
+import org.apache.olingo.server.api.uri.queryoption.QueryOption;
+import org.apache.olingo.server.core.uri.queryoption.CustomQueryOptionImpl;
public class UriDecoder {
- public static RawUri decodeUri(final String path, final String query, final String fragment,
- final int skipSegments) throws UriParserSyntaxException {
- RawUri rawUri = new RawUri();
-
- rawUri.path = path;
- rawUri.queryOptionString = query;
- rawUri.fragment = fragment;
-
- rawUri.pathSegmentList = splitPath(path, skipSegments);
- rawUri.queryOptionList = splitOptions(query);
- decode(rawUri);
-
- return rawUri;
- }
-
- private static void decode(final RawUri rawUri) throws UriParserSyntaxException {
- rawUri.pathSegmentListDecoded = new ArrayList<String>();
- for (String segment : rawUri.pathSegmentList) {
- rawUri.pathSegmentListDecoded.add(decode(segment));
- }
-
- rawUri.queryOptionListDecoded = new ArrayList<RawUri.QueryOption>();
- for (RawUri.QueryOption optionPair : rawUri.queryOptionList) {
- rawUri.queryOptionListDecoded.add(new RawUri.QueryOption(
- decode(optionPair.name),
- decode(optionPair.value)));
+ /** Splits the path string at '/' characters and percent-decodes the resulting path segments. */
+ protected static List<String> splitAndDecodePath(final String path) throws UriParserSyntaxException {
+ List<String> pathSegmentsDecoded = new ArrayList<String>();
+ for (final String segment : splitSkipEmpty(path, '/')) {
+ pathSegmentsDecoded.add(decode(segment));
}
+ return pathSegmentsDecoded;
}
- private static List<RawUri.QueryOption> splitOptions(final String queryOptionString) {
- if (queryOptionString == null) {
+ /**
+ * Splits the query-option string at '&' characters, the resulting parts at '=' characters,
+ * and separately percent-decodes names and values of the resulting name-value pairs.
+ */
+ protected static List<QueryOption> splitAndDecodeOptions(final String queryOptionString)
+ throws UriParserSyntaxException {
+ if (queryOptionString == null || queryOptionString.isEmpty()) {
return Collections.emptyList();
}
- List<RawUri.QueryOption> queryOptionList = new ArrayList<RawUri.QueryOption>();
- for (String option : splitSkipEmpty(queryOptionString, '&')) {
+ List<QueryOption> queryOptions = new ArrayList<QueryOption>();
+ for (final String option : splitSkipEmpty(queryOptionString, '&')) {
final List<String> pair = splitFirst(option, '=');
- queryOptionList.add(new RawUri.QueryOption(pair.get(0), pair.get(1)));
+ queryOptions.add(new CustomQueryOptionImpl()
+ .setName(decode(pair.get(0)))
+ .setText(decode(pair.get(1))));
}
- return queryOptionList;
+ return queryOptions;
}
private static List<String> splitFirst(final String input, final char c) {
- int pos = input.indexOf(c, 0);
+ int pos = input.indexOf(c);
if (pos >= 0) {
return Arrays.asList(input.substring(0, pos), input.substring(pos + 1));
} else {
@@ -79,21 +68,14 @@ public class UriDecoder {
}
}
- private static List<String> splitPath(final String path, final int skipSegments) {
- List<String> list = splitSkipEmpty(path, '/');
-
- return skipSegments > 0 ? list.subList(skipSegments, list.size()) : list;
- }
-
/**
- * Split the input string at given character and drop all empty elements.
- *
+ * Splits the input string at the given character and drops all empty elements.
* @param input string to split
* @param c character at which to split
* @return list of elements (can be empty)
*/
- static List<String> splitSkipEmpty(final String input, final char c) {
- if(input.isEmpty() || input.length() == 1 && input.charAt(0) == c) {
+ private static List<String> splitSkipEmpty(final String input, final char c) {
+ if (input.isEmpty() || input.length() == 1 && input.charAt(0) == c) {
return Collections.emptyList();
}
@@ -103,20 +85,20 @@ public class UriDecoder {
int end;
while ((end = input.indexOf(c, start)) >= 0) {
- if(start != end) {
+ if (start != end) {
list.add(input.substring(start, end));
}
start = end + 1;
}
- if(input.charAt(input.length()-1) != c) {
+ if (input.charAt(input.length() - 1) != c) {
list.add(input.substring(start));
}
return list;
}
- public static String decode(final String encoded) throws UriParserSyntaxException {
+ private static String decode(final String encoded) throws UriParserSyntaxException {
try {
return Decoder.decode(encoded);
} catch (final IllegalArgumentException e) {
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/d7e23bf8/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
index 8740d66..c58327b 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
@@ -82,9 +82,7 @@ import org.apache.olingo.server.core.uri.UriResourceStartingTypeFilterImpl;
import org.apache.olingo.server.core.uri.UriResourceTypedImpl;
import org.apache.olingo.server.core.uri.UriResourceValueImpl;
import org.apache.olingo.server.core.uri.UriResourceWithKeysImpl;
-import org.apache.olingo.server.core.uri.antlr.UriLexer;
-import org.apache.olingo.server.core.uri.antlr.UriParserBaseVisitor;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser;
+import org.apache.olingo.server.core.uri.antlr.*;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.AllEOFContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.AllExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltAddContext;
@@ -106,7 +104,6 @@ import org.apache.olingo.server.core.uri.antlr.UriParserParser.CeilingMethodCall
import org.apache.olingo.server.core.uri.antlr.UriParserParser.ConcatMethodCallExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.ConstSegmentContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.ContainsMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.CrossjoinEOFContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.DateLiteralContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.DateMethodCallExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.DatetimeoffsetLiteralContext;
@@ -151,7 +148,6 @@ import org.apache.olingo.server.core.uri.antlr.UriParserParser.NamespaceContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.NaninfinityLiteralContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.NowMethodCallExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.NullruleLiteralContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.OdataIdentifierContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.OrderByContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.OrderByEOFContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.OrderByItemContext;
@@ -226,20 +222,6 @@ import org.apache.olingo.server.core.uri.queryoption.expression.UnaryImpl;
*/
public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
- public class TypeInformation {
-
- boolean isCollection;
-
- EdmType type;
-
- TypeInformation(final EdmType type, final boolean isCollection) {
- this.type = type;
- this.isCollection = isCollection;
- }
-
- public TypeInformation() {}
- }
-
public UriContext context = null;
public Edm edm;
@@ -277,36 +259,6 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
return null;
}
- TypeInformation getTypeInformation(final UriResource lastResourcePart) {
-
- TypeInformation typeInformation = new TypeInformation();
- if (lastResourcePart instanceof UriResourceWithKeysImpl) {
- UriResourceWithKeysImpl lastPartWithKeys = (UriResourceWithKeysImpl) lastResourcePart;
-
- if (lastPartWithKeys.getTypeFilterOnEntry() != null) {
- typeInformation.type = lastPartWithKeys.getTypeFilterOnEntry();
- } else if (lastPartWithKeys.getTypeFilterOnCollection() != null) {
- typeInformation.type = lastPartWithKeys.getTypeFilterOnCollection();
- } else {
- typeInformation.type = lastPartWithKeys.getType();
- }
- typeInformation.isCollection = lastPartWithKeys.isCollection();
-
- } else if (lastResourcePart instanceof UriResourceTypedImpl) {
- UriResourceTypedImpl lastPartTyped = (UriResourceTypedImpl) lastResourcePart;
-
- if (lastPartTyped.getTypeFilter() != null) {
- typeInformation.type = lastPartTyped.getTypeFilter();
- } else {
- typeInformation.type = lastPartTyped.getType();
- }
-
- typeInformation.isCollection = lastPartTyped.isCollection();
- }
-
- return typeInformation;
- }
-
public UriResourceTypedImpl readResourcePathSegment(final PathSegmentContext ctx) {
final boolean checkFirst =
@@ -318,10 +270,10 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
boolean searchInContainer = true;
// validate if context type and according property is available
// otherwise search in container for first element
- if (checkFirst && ctx.vNS == null && !context.contextTypes.empty()) {
- TypeInformation source = context.contextTypes.peek();
- if (source.type instanceof EdmStructuredType) {
- EdmStructuredType str = (EdmStructuredType) source.type;
+ if (checkFirst && ctx.vNS == null && !context.contextTypes.isEmpty()) {
+ EdmType sourceType = context.contextTypes.peek();
+ if (sourceType instanceof EdmStructuredType) {
+ EdmStructuredType str = (EdmStructuredType) sourceType;
EdmElement property = str.getProperty(odi);
if (property != null) {
searchInContainer = false;
@@ -418,11 +370,12 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
}
}
- final TypeInformation source;
+ EdmType sourceType;
+ boolean sourceIsCollection = false;
final UriResource lastResourcePart = context.contextUriInfo.getLastResourcePart();
if (lastResourcePart == null) {
- if (context.contextTypes.empty()) {
+ if (context.contextTypes.isEmpty()) {
if (checkFirst && ctx.vNS == null) {
throw wrap(new UriParserSemanticException(
"Cannot find EntitySet, Singleton, ActionImport or FunctionImport with name '" + odi + "'.",
@@ -432,15 +385,15 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
"Resource part '" + odi + "' can only applied on typed resource parts",
UriParserSemanticException.MessageKeys.RESOURCE_PART_ONLY_FOR_TYPED_PARTS, odi));
}
- source = context.contextTypes.peek();
+ sourceType = context.contextTypes.peek();
+ sourceIsCollection = context.isCollection;
+ } else if (lastResourcePart instanceof UriResourcePartTyped) {
+ sourceType = Parser.getTypeInformation((UriResourcePartTyped) lastResourcePart);
+ sourceIsCollection = ((UriResourcePartTyped) lastResourcePart).isCollection();
} else {
- source = getTypeInformation(lastResourcePart);
-
- if (source.type == null) {
- throw wrap(new UriParserSemanticException(
- "Resource part '" + odi + "' can only be applied on typed resource parts.",
- UriParserSemanticException.MessageKeys.RESOURCE_PART_ONLY_FOR_TYPED_PARTS, odi));
- }
+ throw wrap(new UriParserSemanticException(
+ "Resource part '" + odi + "' can only be applied on typed resource parts.",
+ UriParserSemanticException.MessageKeys.RESOURCE_PART_ONLY_FOR_TYPED_PARTS, odi));
}
if (ctx.vNS == null) { // without namespace
@@ -456,7 +409,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
return null;
}
- if (!(source.type instanceof EdmStructuredType)) {
+ if (!(sourceType instanceof EdmStructuredType)) {
throw wrap(new UriParserSemanticException(
"Cannot parse '" + odi + "'; previous path segment is not a structural type.",
UriParserSemanticException.MessageKeys.RESOURCE_PART_MUST_BE_PRECEDED_BY_STRUCTURAL_TYPE, odi));
@@ -465,12 +418,12 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
if ((ctx.depth() <= 2 // path evaluation for the resource path
|| lastResourcePart instanceof UriResourceTypedImpl
|| lastResourcePart instanceof UriResourceNavigationPropertyImpl)
- && source.isCollection) {
+ && sourceIsCollection) {
throw wrap(new UriParserSemanticException("Property '" + odi + "' is not allowed after collection.",
UriParserSemanticException.MessageKeys.PROPERTY_AFTER_COLLECTION, odi));
}
- EdmStructuredType structType = (EdmStructuredType) source.type;
+ EdmStructuredType structType = (EdmStructuredType) sourceType;
EdmElement property = structType.getProperty(odi);
if (property == null) {
@@ -520,12 +473,12 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
FullQualifiedName fullFilterName = getFullNameFromContext(ctx.vNS, odi);
// EdmType lastType = getLastType(lastTyped);
- if (source.type instanceof EdmEntityType) {
+ if (sourceType instanceof EdmEntityType) {
EdmEntityType filterEntityType = edm.getEntityType(fullFilterName);
if (filterEntityType != null) {
// is entity type cast
- if (!(filterEntityType.compatibleTo(source.type))) {
+ if (!(filterEntityType.compatibleTo(sourceType))) {
throw wrap(new UriParserSemanticException(
"Entity typefilter not compatible to previous path segment: " + fullFilterName.toString(),
UriParserSemanticException.MessageKeys.INCOMPATIBLE_TYPE_FILTER, fullFilterName.toString()));
@@ -535,8 +488,8 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
// this may be the case if a member expression within a filter starts with a typeCast
UriResourceStartingTypeFilterImpl uriResource = new UriResourceStartingTypeFilterImpl()
.setType(filterEntityType)
- .setCollection(source.isCollection);
- if (source.isCollection) {
+ .setCollection(sourceIsCollection);
+ if (sourceIsCollection) {
uriResource.setCollectionTypeFilter(filterEntityType);
} else {
uriResource.setEntryTypeFilter(filterEntityType);
@@ -590,18 +543,18 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
}
}
- } else if (source.type instanceof EdmComplexType) {
+ } else if (sourceType instanceof EdmComplexType) {
EdmComplexType filterComplexType = edm.getComplexType(fullFilterName);
if (filterComplexType != null) {
// is complex type cast
- if (!(filterComplexType.compatibleTo(source.type))) {
+ if (!(filterComplexType.compatibleTo(sourceType))) {
throw wrap(new UriParserSemanticException(
- "Complex typefilter '" + getName(source.type) + "'not compatible type of previous path segment '"
+ "Complex typefilter '" + getName(sourceType) + "'not compatible type of previous path segment '"
+ getName(filterComplexType) + "'",
- UriParserSemanticException.MessageKeys.INCOMPATIBLE_TYPE_FILTER, getName(source.type)));
+ UriParserSemanticException.MessageKeys.INCOMPATIBLE_TYPE_FILTER, getName(sourceType)));
}
// is simple complex type cast
@@ -609,9 +562,9 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
// this may be the case if a member expression within a filter starts with a typeCast
UriResourceStartingTypeFilterImpl uriResource = new UriResourceStartingTypeFilterImpl()
.setType(filterComplexType)
- .setCollection(source.isCollection);
+ .setCollection(sourceIsCollection);
- if (source.isCollection) {
+ if (sourceIsCollection) {
uriResource.setCollectionTypeFilter(filterComplexType);
} else {
uriResource.setEntryTypeFilter(filterComplexType);
@@ -666,10 +619,10 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
}
}
- FullQualifiedName fullBindingTypeName = new FullQualifiedName(source.type.getNamespace(), source.type.getName());
+ FullQualifiedName fullBindingTypeName = sourceType.getFullQualifiedName();
// check for action
- EdmAction action = edm.getBoundAction(fullFilterName, fullBindingTypeName, source.isCollection);
+ EdmAction action = edm.getBoundAction(fullFilterName, fullBindingTypeName, sourceIsCollection);
if (action != null) {
UriResourceActionImpl pathInfoAction = new UriResourceActionImpl();
pathInfoAction.setAction(action);
@@ -694,7 +647,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
names.add(item.getName());
}
- EdmFunction function = edm.getBoundFunction(fullFilterName, fullBindingTypeName, source.isCollection, names);
+ EdmFunction function = edm.getBoundFunction(fullFilterName, fullBindingTypeName, sourceIsCollection, names);
if (function != null) {
UriResourceFunctionImpl pathInfoFunction = new UriResourceFunctionImpl()
@@ -767,7 +720,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
UriContext.LambdaVariables var = new UriContext.LambdaVariables();
var.name = ctx.vLV.getText();
- var.type = getTypeInformation(obj).type;
+ var.type = Parser.getTypeInformation((UriResourcePartTyped) obj);
var.isCollection = false;
all.setLamdaVariable(ctx.vLV.getText());
@@ -907,11 +860,9 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
context.contextUriInfo.setEntityTypeCast(type);
// contextUriInfo = uriInfo;
- context.contextTypes.push(new TypeInformation(context.contextUriInfo.getEntityTypeCast(), true));
+ context.contextTypes.push(context.contextUriInfo.getEntityTypeCast());
+ context.isCollection = true; // TODO: check!
- // @SuppressWarnings("unchecked")
- // List<QueryOptionImpl> list = (List<QueryOptionImpl>) ctx.vEO.accept(this);
- // uriInfo.setQueryOptions(list);
return null;
}
@@ -998,7 +949,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
UriContext.LambdaVariables var = new UriContext.LambdaVariables();
var.name = ctx.vLV.getText();
- var.type = getTypeInformation(lastResourcePart).type;
+ var.type = Parser.getTypeInformation((UriResourcePartTyped) lastResourcePart);
var.isCollection = false;
any.setLamdaVariable(ctx.vLV.getText());
@@ -1147,33 +1098,6 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
}
@Override
- public Object visitCrossjoinEOF(final CrossjoinEOFContext ctx) {
- UriInfoImpl crossJoin = new UriInfoImpl().setKind(UriInfoKind.crossjoin);
-
- for (OdataIdentifierContext obj : ctx.vlODI) {
- String odi = obj.getText();
- crossJoin.addEntitySetName(odi);
-
- EdmEntitySet edmEntitySet = edmEntityContainer.getEntitySet(odi);
- if (edmEntitySet == null) {
- throw wrap(new UriParserSemanticException("Expected EntityTypeName",
- UriParserSemanticException.MessageKeys.UNKNOWN_PART, odi));
- }
-
- EdmEntityType type = edmEntitySet.getEntityType();
- if (type == null) {
- throw wrap(new UriParserSemanticException("Expected EntityTypeName",
- UriParserSemanticException.MessageKeys.UNKNOWN_ENTITY_TYPE, odi));
- }
- // contextUriInfo = uriInfo;
- context.contextTypes.push(new TypeInformation(type, true));
- }
-
- context.contextUriInfo = crossJoin;
- return null;
- }
-
- @Override
public Object visitDateMethodCallExpr(final DateMethodCallExprContext ctx) {
return new MethodImpl()
.setMethod(MethodKind.DATE)
@@ -1372,23 +1296,24 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
if (context.contextExpandItemPath == null) {
// use the type of the last resource path segement
UriResourceTypedImpl lastSegment = (UriResourceTypedImpl) context.contextUriInfo.getLastResourcePart();
- targetType = getTypeInformation(lastSegment).type;
+ targetType = Parser.getTypeInformation(lastSegment);
isColl = lastSegment.isCollection();
} else {
if (context.contextExpandItemPath.getResourcePath() == null) {
// use the type of the last resource path segement
UriResourceTypedImpl lastSegment = (UriResourceTypedImpl) context.contextUriInfo.getLastResourcePart();
- targetType = getTypeInformation(lastSegment).type;
+ targetType = Parser.getTypeInformation(lastSegment);
isColl = lastSegment.isCollection();
} else {
// use the type of the last ''expand'' path segement
UriInfoImpl info = (UriInfoImpl) context.contextExpandItemPath.getResourcePath();
- targetType = getTypeInformation(info.getLastResourcePart()).type;
+ targetType = Parser.getTypeInformation((UriResourcePartTyped) info.getLastResourcePart());
isColl = ((UriResourcePartTyped) info.getLastResourcePart()).isCollection();
}
}
- context.contextTypes.push(new TypeInformation(targetType, isColl));
+ context.contextTypes.push(targetType);
+ context.isCollection = isColl;
if (ctx.vC != null) {
UriInfoImpl resourcePath = (UriInfoImpl) context.contextExpandItemPath.getResourcePath();
@@ -1546,12 +1471,11 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
throw wrap(new UriParserSemanticException("Expression '" + ctx.getText() + "' is not allowed as key value.",
UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, ctx.getText()));
}
- TypeInformation lastTypeInfo = context.contextTypes.peek();
if (ctx.vIt != null || ctx.vIts != null) {
UriResourceItImpl pathInfoIT = new UriResourceItImpl();
- pathInfoIT.setType(lastTypeInfo.type);
- pathInfoIT.setCollection(lastTypeInfo.isCollection);
+ pathInfoIT.setType(context.contextTypes.peek());
+ pathInfoIT.setCollection(context.isCollection);
uriInfoImplpath.addResourcePart(pathInfoIT);
}
@@ -2101,7 +2025,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
UriResourceRootImpl pathInfoRoot = new UriResourceRootImpl();
pathInfoRoot.setCollection(lastType.isCollection());
- pathInfoRoot.setType(getTypeInformation(lastType).type);
+ pathInfoRoot.setType(Parser.getTypeInformation(lastType));
UriInfoImpl uriInfoImplpath = new UriInfoImpl().setKind(UriInfoKind.resource);
uriInfoImplpath.addResourcePart(pathInfoRoot);
@@ -2194,12 +2118,12 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
EdmType prevType = null;
if (context.contextSelectItem.getResourcePath() == null) {
- prevType = context.contextTypes.peek().type;
+ prevType = context.contextTypes.peek();
} else {
UriInfoImpl uriInfo = (UriInfoImpl) context.contextSelectItem.getResourcePath();
UriResource last = uriInfo.getLastResourcePart();
- prevType = getTypeInformation(last).type;
+ prevType = Parser.getTypeInformation((UriResourcePartTyped) last);
if (prevType == null) {
throw wrap(new UriParserSemanticException("prev segment not typed",
UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PARTS, "select"));
@@ -2278,7 +2202,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
// contextSelectItem.addQualifiedThing(fullName);
if (context.contextSelectItem.getResourcePath() == null) {
- EdmType prevType = context.contextTypes.peek().type;
+ EdmType prevType = context.contextTypes.peek();
// check for complex type cast
if (prevType instanceof EdmComplexType) {
@@ -2331,7 +2255,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
throw wrap(new UriParserSemanticException("prev segment typed",
UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PARTS, "select"));
}
- EdmType prevType = getTypeInformation(last).type;
+ EdmType prevType = Parser.getTypeInformation((UriResourcePartTyped) last);
if (prevType instanceof EdmComplexType) {
EdmComplexType ct = edm.getComplexType(fullName);
@@ -2367,7 +2291,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
EdmType prevType = null;
if (context.contextSelectItem.getResourcePath() == null) {
- prevType = context.contextTypes.peek().type;
+ prevType = context.contextTypes.peek();
} else {
UriInfoImpl uriInfo = (UriInfoImpl) context.contextSelectItem.getResourcePath();
UriResource last = uriInfo.getLastResourcePart();
@@ -2375,7 +2299,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
throw wrap(new UriParserSemanticException("prev segment typed",
UriParserSemanticException.MessageKeys.PREVIOUS_PART_TYPED));
}
- prevType = getTypeInformation(last).type;
+ prevType = Parser.getTypeInformation((UriResourcePartTyped) last);
}
final FullQualifiedName finalTypeName = prevType.getFullQualifiedName();
[10/30] olingo-odata4 git commit: [OLINGO-834] clean-up Expression
implementations
Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/208f26c7/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/BinaryImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/BinaryImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/BinaryImpl.java
index c3530c0..3f2e8f2 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/BinaryImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/BinaryImpl.java
@@ -25,21 +25,16 @@ import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
import org.apache.olingo.server.api.uri.queryoption.expression.ExpressionVisitException;
import org.apache.olingo.server.api.uri.queryoption.expression.ExpressionVisitor;
-public class BinaryImpl extends ExpressionImpl implements Binary {
+public class BinaryImpl implements Binary {
- private BinaryOperatorKind operator;
- private ExpressionImpl left;
- private ExpressionImpl right;
+ private final Expression left;
+ private final BinaryOperatorKind operator;
+ private final Expression right;
- public BinaryImpl() {
- // TODO: Delete
- }
-
- public BinaryImpl(Expression left, BinaryOperatorKind operator, Expression right) {
- // TODO:DeleteCast
- this.left = (ExpressionImpl) left;
+ public BinaryImpl(final Expression left, final BinaryOperatorKind operator, final Expression right) {
+ this.left = left;
this.operator = operator;
- this.right = (ExpressionImpl) right;
+ this.right = right;
}
@Override
@@ -47,30 +42,16 @@ public class BinaryImpl extends ExpressionImpl implements Binary {
return operator;
}
- public Binary setOperator(final BinaryOperatorKind operator) {
- this.operator = operator;
- return this;
- }
-
@Override
public Expression getLeftOperand() {
return left;
}
- public void setLeftOperand(final ExpressionImpl operand) {
- left = operand;
- }
-
@Override
public Expression getRightOperand() {
return right;
}
- public void setRightOperand(final ExpressionImpl operand) {
- right = operand;
-
- }
-
@Override
public <T> T accept(final ExpressionVisitor<T> visitor) throws ExpressionVisitException, ODataApplicationException {
T left = this.left.accept(visitor);
@@ -82,5 +63,4 @@ public class BinaryImpl extends ExpressionImpl implements Binary {
public String toString() {
return "{" + left + " " + operator.name() + " " + right + '}';
}
-
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/208f26c7/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/EnumerationImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/EnumerationImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/EnumerationImpl.java
index 8f7df3a..256b8d1 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/EnumerationImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/EnumerationImpl.java
@@ -18,7 +18,7 @@
*/
package org.apache.olingo.server.core.uri.queryoption.expression;
-import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import org.apache.olingo.commons.api.edm.EdmEnumType;
@@ -27,19 +27,14 @@ import org.apache.olingo.server.api.uri.queryoption.expression.Enumeration;
import org.apache.olingo.server.api.uri.queryoption.expression.ExpressionVisitException;
import org.apache.olingo.server.api.uri.queryoption.expression.ExpressionVisitor;
-public class EnumerationImpl extends ExpressionImpl implements Enumeration {
+public class EnumerationImpl implements Enumeration {
- private EdmEnumType type;
- private List<String> values = new ArrayList<String>();
+ private final EdmEnumType type;
+ private final List<String> values;
- @Override
- public List<String> getValues() {
- return values;
- }
-
- public EnumerationImpl addValue(final String enumValue) {
- values.add(enumValue);
- return this;
+ public EnumerationImpl(final EdmEnumType type, final List<String> values) {
+ this.type = type;
+ this.values = values;
}
@Override
@@ -47,14 +42,15 @@ public class EnumerationImpl extends ExpressionImpl implements Enumeration {
return type;
}
- public EnumerationImpl setType(final EdmEnumType type) {
- this.type = type;
- return this;
+ @Override
+ public List<String> getValues() {
+ return values == null ?
+ Collections.<String> emptyList() :
+ Collections.unmodifiableList(values);
}
@Override
public <T> T accept(final ExpressionVisitor<T> visitor) throws ExpressionVisitException, ODataApplicationException {
return visitor.visitEnum(type, values);
}
-
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/208f26c7/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/ExpressionImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/ExpressionImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/ExpressionImpl.java
deleted file mode 100644
index c9cc707..0000000
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/ExpressionImpl.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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.queryoption.expression;
-
-import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
-
-public abstract class ExpressionImpl implements Expression {
- // No additional methods needed for now.
-}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/208f26c7/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/LambdaRefImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/LambdaRefImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/LambdaRefImpl.java
index 8198204..824943a 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/LambdaRefImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/LambdaRefImpl.java
@@ -23,23 +23,21 @@ import org.apache.olingo.server.api.uri.queryoption.expression.ExpressionVisitEx
import org.apache.olingo.server.api.uri.queryoption.expression.ExpressionVisitor;
import org.apache.olingo.server.api.uri.queryoption.expression.LambdaRef;
-public class LambdaRefImpl extends ExpressionImpl implements LambdaRef {
+public class LambdaRefImpl implements LambdaRef {
- private String variableText;
+ private final String variableText;
+
+ public LambdaRefImpl(final String text) {
+ variableText = text;
+ }
@Override
public String getVariableName() {
return variableText;
}
- public LambdaRefImpl setVariableText(final String text) {
- variableText = text;
- return this;
- }
-
@Override
public <T> T accept(final ExpressionVisitor<T> visitor) throws ExpressionVisitException, ODataApplicationException {
return visitor.visitLambdaReference(variableText);
}
-
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/208f26c7/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/LiteralImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/LiteralImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/LiteralImpl.java
index e275fdd..8a3cc8a 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/LiteralImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/LiteralImpl.java
@@ -24,16 +24,12 @@ import org.apache.olingo.server.api.uri.queryoption.expression.ExpressionVisitEx
import org.apache.olingo.server.api.uri.queryoption.expression.ExpressionVisitor;
import org.apache.olingo.server.api.uri.queryoption.expression.Literal;
-public class LiteralImpl extends ExpressionImpl implements Literal {
+public class LiteralImpl implements Literal {
- private String text;
- private EdmType type;
+ private final String text;
+ private final EdmType type;
- public LiteralImpl() {
-
- }
-
- public LiteralImpl(String text, EdmType type) {
+ public LiteralImpl(final String text, final EdmType type) {
this.text = text;
this.type = type;
}
@@ -43,21 +39,11 @@ public class LiteralImpl extends ExpressionImpl implements Literal {
return text;
}
- public LiteralImpl setText(final String text) {
- this.text = text;
- return this;
- }
-
@Override
public EdmType getType() {
return type;
}
- public LiteralImpl setType(final EdmType type) {
- this.type = type;
- return this;
- }
-
@Override
public <T> T accept(final ExpressionVisitor<T> visitor) throws ExpressionVisitException, ODataApplicationException {
return visitor.visitLiteral(this);
@@ -65,7 +51,6 @@ public class LiteralImpl extends ExpressionImpl implements Literal {
@Override
public String toString() {
- return "" + text;
+ return text == null ? "" : text;
}
-
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/208f26c7/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/MemberImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/MemberImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/MemberImpl.java
index 5f6162f..a71e382 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/MemberImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/MemberImpl.java
@@ -30,19 +30,24 @@ import org.apache.olingo.server.core.uri.UriResourceImpl;
import org.apache.olingo.server.core.uri.UriResourceTypedImpl;
import org.apache.olingo.server.core.uri.UriResourceWithKeysImpl;
-public class MemberImpl extends ExpressionImpl implements Member {
+public class MemberImpl implements Member {
- private UriInfoResource path;
- private EdmType startTypeFilter;
+ private final UriInfoResource path;
+ private final EdmType startTypeFilter;
+
+ public MemberImpl(final UriInfoResource path, final EdmType startTypeFilter) {
+ this.path = path;
+ this.startTypeFilter = startTypeFilter;
+ }
@Override
public UriInfoResource getResourcePath() {
return path;
}
- public Member setResourcePath(final UriInfoResource pathSegments) {
- path = pathSegments;
- return this;
+ @Override
+ public EdmType getStartTypeFilter() {
+ return startTypeFilter;
}
@Override
@@ -89,15 +94,4 @@ public class MemberImpl extends ExpressionImpl implements Member {
}
return false;
}
-
- @Override
- public EdmType getStartTypeFilter() {
- return startTypeFilter;
- }
-
- public MemberImpl setTypeFilter(final EdmType startTypeFilter) {
- this.startTypeFilter = startTypeFilter;
- return this;
- }
-
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/208f26c7/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/MethodImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/MethodImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/MethodImpl.java
index 8175c85..1c8ce64 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/MethodImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/MethodImpl.java
@@ -19,6 +19,7 @@
package org.apache.olingo.server.core.uri.queryoption.expression;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import org.apache.olingo.server.api.ODataApplicationException;
@@ -28,17 +29,14 @@ import org.apache.olingo.server.api.uri.queryoption.expression.ExpressionVisitor
import org.apache.olingo.server.api.uri.queryoption.expression.Method;
import org.apache.olingo.server.api.uri.queryoption.expression.MethodKind;
-public class MethodImpl extends ExpressionImpl implements Method {
+public class MethodImpl implements Method {
- private MethodKind method;
- private List<ExpressionImpl> parameters = new ArrayList<ExpressionImpl>();
+ private final MethodKind method;
+ private final List<Expression> parameters;
- public MethodImpl() {
- // TODO: Delete constructor
- }
-
- public MethodImpl(MethodKind method) {
+ public MethodImpl(final MethodKind method, final List<Expression> parameters) {
this.method = method;
+ this.parameters = parameters;
}
@Override
@@ -46,48 +44,26 @@ public class MethodImpl extends ExpressionImpl implements Method {
return method;
}
- public MethodImpl setMethod(final MethodKind methodCalls) {
- method = methodCalls;
- return this;
- }
-
@Override
public List<Expression> getParameters() {
- List<Expression> list = new ArrayList<Expression>();
- for (ExpressionImpl item : parameters) {
- list.add(item);
- }
- return list;
- }
-
- public MethodImpl addParameter(final ExpressionImpl readCommonExpression) {
- parameters.add(readCommonExpression);
- return this;
+ return parameters == null ?
+ Collections.<Expression> emptyList() :
+ Collections.unmodifiableList(parameters);
}
@Override
public <T> T accept(final ExpressionVisitor<T> visitor) throws ExpressionVisitException, ODataApplicationException {
List<T> userParameters = new ArrayList<T>();
- for (ExpressionImpl parameter : parameters) {
- userParameters.add(parameter.accept(visitor));
+ if (parameters != null) {
+ for (final Expression parameter : parameters) {
+ userParameters.add(parameter.accept(visitor));
+ }
}
return visitor.visitMethodCall(method, userParameters);
}
@Override
public String toString() {
- String parametersString = "[";
- boolean first = true;
- for (Expression exp : parameters) {
- if(first){
- first = false;
- parametersString = parametersString + exp.toString();
- }else {
- parametersString = parametersString + ", " + exp.toString();
- }
- }
- parametersString = parametersString + "]";
- return "{" + method + " " + parametersString + "}";
+ return "{" + method + " " + parameters + "}";
}
-
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/208f26c7/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/TypeLiteralImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/TypeLiteralImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/TypeLiteralImpl.java
index f5f6f06..336c203 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/TypeLiteralImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/TypeLiteralImpl.java
@@ -24,23 +24,21 @@ import org.apache.olingo.server.api.uri.queryoption.expression.ExpressionVisitEx
import org.apache.olingo.server.api.uri.queryoption.expression.ExpressionVisitor;
import org.apache.olingo.server.api.uri.queryoption.expression.TypeLiteral;
-public class TypeLiteralImpl extends ExpressionImpl implements TypeLiteral {
+public class TypeLiteralImpl implements TypeLiteral {
- private EdmType type;
+ private final EdmType type;
+
+ public TypeLiteralImpl(final EdmType type) {
+ this.type = type;
+ }
@Override
public EdmType getType() {
return type;
}
- public TypeLiteralImpl setType(final EdmType type) {
- this.type = type;
- return this;
- }
-
@Override
public <T> T accept(final ExpressionVisitor<T> visitor) throws ExpressionVisitException, ODataApplicationException {
return visitor.visitTypeLiteral(type);
}
-
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/208f26c7/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/UnaryImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/UnaryImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/UnaryImpl.java
index f1edf91..2438d27 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/UnaryImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/UnaryImpl.java
@@ -25,18 +25,14 @@ import org.apache.olingo.server.api.uri.queryoption.expression.ExpressionVisitor
import org.apache.olingo.server.api.uri.queryoption.expression.Unary;
import org.apache.olingo.server.api.uri.queryoption.expression.UnaryOperatorKind;
-public class UnaryImpl extends ExpressionImpl implements Unary {
+public class UnaryImpl implements Unary {
- private UnaryOperatorKind operator;
- private ExpressionImpl expression;
+ private final UnaryOperatorKind operator;
+ private final Expression expression;
- public UnaryImpl() {
-
- }
-
- public UnaryImpl(UnaryOperatorKind operator, Expression expression) {
+ public UnaryImpl(final UnaryOperatorKind operator, final Expression expression) {
this.operator = operator;
- this.expression = (ExpressionImpl) expression;
+ this.expression = expression;
}
@Override
@@ -44,19 +40,11 @@ public class UnaryImpl extends ExpressionImpl implements Unary {
return operator;
}
- public void setOperator(final UnaryOperatorKind operator) {
- this.operator = operator;
- }
-
@Override
public Expression getOperand() {
return expression;
}
- public void setOperand(final ExpressionImpl expression) {
- this.expression = expression;
- }
-
@Override
public <T> T accept(final ExpressionVisitor<T> visitor) throws ExpressionVisitException, ODataApplicationException {
T operand = expression.accept(visitor);
@@ -67,5 +55,4 @@ public class UnaryImpl extends ExpressionImpl implements Unary {
public String toString() {
return "{" + operator + " " + expression + '}';
}
-
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/208f26c7/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/expression/FilterParserTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/expression/FilterParserTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/expression/FilterParserTest.java
deleted file mode 100644
index 7bfc369..0000000
--- a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/expression/FilterParserTest.java
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * 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.expression;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-import java.util.ArrayList;
-
-import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
-import org.apache.olingo.server.core.uri.expression.FilterParser.TokenKind;
-import org.apache.olingo.server.core.uri.expression.FilterParser.Tokenizer;
-import org.apache.olingo.server.core.uri.expression.FilterParser.Token;
-import org.junit.Test;
-
-public class FilterParserTest {
-
- @Test
- public void equality() {
- Expression expression = parseExpression(TokenKind.EQ_OP);
- assertEquals("{5 EQ 5}", expression.toString());
-
- expression = parseExpression(TokenKind.NE_OP);
- assertEquals("{5 NE 5}", expression.toString());
- }
-
- @Test
- public void relational() {
- Expression expression = parseExpression(TokenKind.GT_OP);
- assertEquals("{5 GT 5}", expression.toString());
-
- expression = parseExpression(TokenKind.GE_OP);
- assertEquals("{5 GE 5}", expression.toString());
-
- expression = parseExpression(TokenKind.LT_OP);
- assertEquals("{5 LT 5}", expression.toString());
-
- expression = parseExpression(TokenKind.LE_OP);
- assertEquals("{5 LE 5}", expression.toString());
- }
-
- @Test
- public void additive() {
- Expression expression = parseExpression(TokenKind.ADD_OP);
- assertEquals("{5 ADD 5}", expression.toString());
-
- expression = parseExpression(TokenKind.SUB_OP);
- assertEquals("{5 SUB 5}", expression.toString());
- }
-
- @Test
- public void multiplicative() {
- Expression expression = parseExpression(TokenKind.MUL_OP);
- assertEquals("{5 MUL 5}", expression.toString());
-
- expression = parseExpression(TokenKind.DIV_OP);
- assertEquals("{5 DIV 5}", expression.toString());
-
- expression = parseExpression(TokenKind.MOD_OP);
- assertEquals("{5 MOD 5}", expression.toString());
- }
-
- @Test
- public void unary() {
- ArrayList<Token> tokens = new ArrayList<Token>();
- tokens.add(new Token(TokenKind.MINUS, ""));
- tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
- Tokenizer tokenizer = new Tokenizer(tokens);
- Expression expression = new FilterParser().parse(tokenizer);
- assertEquals("{- 5}", expression.toString());
-
- tokens = new ArrayList<Token>();
- tokens.add(new Token(TokenKind.NOT, ""));
- tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
- tokenizer = new Tokenizer(tokens);
- expression = new FilterParser().parse(tokenizer);
- assertEquals("{not 5}", expression.toString());
- }
-
- @Test
- public void grouping() {
- ArrayList<Token> tokens = new ArrayList<Token>();
- tokens.add(new Token(TokenKind.MINUS, ""));
- tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
- tokens.add(new Token(TokenKind.ADD_OP, ""));
- tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
- Tokenizer tokenizer = new Tokenizer(tokens);
- Expression expression = new FilterParser().parse(tokenizer);
- assertEquals("{{- 5} ADD 5}", expression.toString());
-
- tokens = new ArrayList<Token>();
- tokens.add(new Token(TokenKind.MINUS, ""));
- tokens.add(new Token(TokenKind.OPEN, ""));
- tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
- tokens.add(new Token(TokenKind.ADD_OP, ""));
- tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
- tokens.add(new Token(TokenKind.CLOSE, ""));
- tokenizer = new Tokenizer(tokens);
- expression = new FilterParser().parse(tokenizer);
- assertEquals("{- {5 ADD 5}}", expression.toString());
- }
-
- @Test
- public void noParameterMethods() {
- Expression expression = parseMethod(TokenKind.Now);
- assertEquals("{now []}", expression.toString());
-
- expression = parseMethod(TokenKind.Maxdatetime);
- assertEquals("{maxdatetime []}", expression.toString());
-
- expression = parseMethod(TokenKind.Mindatetime);
- assertEquals("{mindatetime []}", expression.toString());
- }
-
- @Test
- public void oneParameterMethods() {
- Expression expression = parseMethod(TokenKind.Length, TokenKind.PrimitiveStringValue);
- assertEquals("{length [String1]}", expression.toString());
-
- expression = parseMethod(TokenKind.Tolower, TokenKind.PrimitiveStringValue);
- assertEquals("{tolower [String1]}", expression.toString());
-
- expression = parseMethod(TokenKind.Toupper, TokenKind.PrimitiveStringValue);
- assertEquals("{toupper [String1]}", expression.toString());
-
- expression = parseMethod(TokenKind.Trim, TokenKind.PrimitiveStringValue);
- assertEquals("{trim [String1]}", expression.toString());
-
- expression = parseMethod(TokenKind.Year, TokenKind.PrimitiveDateValue);
- assertEquals("{year [Date1]}", expression.toString());
-
- expression = parseMethod(TokenKind.Month, TokenKind.PrimitiveDateValue);
- assertEquals("{month [Date1]}", expression.toString());
-
- expression = parseMethod(TokenKind.Day, TokenKind.PrimitiveDateValue);
- assertEquals("{day [Date1]}", expression.toString());
-
- expression = parseMethod(TokenKind.Hour, TokenKind.PrimitiveDateTimeOffsetValue);
- assertEquals("{hour [DateTimeOffset1]}", expression.toString());
-
- expression = parseMethod(TokenKind.Minute, TokenKind.PrimitiveDateTimeOffsetValue);
- assertEquals("{minute [DateTimeOffset1]}", expression.toString());
-
- expression = parseMethod(TokenKind.Second, TokenKind.PrimitiveDateTimeOffsetValue);
- assertEquals("{second [DateTimeOffset1]}", expression.toString());
- }
-
- @Test
- public void twoParameterMethods() {
-
- }
-
- private Expression parseMethod(TokenKind... kind) {
- ArrayList<Token> tokens = new ArrayList<Token>();
- tokens.add(new Token(kind[0], ""));
-
- for (int i = 1; i < kind.length; i++) {
- String text = null;
- switch (kind[i]) {
- case PrimitiveStringValue:
- text = "String" + i;
- break;
- case PrimitiveDateValue:
- text = "Date" + i;
- break;
- case PrimitiveDateTimeOffsetValue:
- text = "DateTimeOffset" + i;
- break;
- default:
- text = "" + i;
- break;
- }
- tokens.add(new Token(kind[i], text));
- }
-
- tokens.add(new Token(TokenKind.CLOSE, ""));
- Tokenizer tokenizer = new Tokenizer(tokens);
- Expression expression = new FilterParser().parse(tokenizer);
- assertNotNull(expression);
- return expression;
- }
-
- private Expression parseExpression(TokenKind operator) {
- ArrayList<Token> tokens = new ArrayList<Token>();
- tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
- tokens.add(new Token(operator, ""));
- tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
- Tokenizer tokenizer = new Tokenizer(tokens);
-
- Expression expression = new FilterParser().parse(tokenizer);
- assertNotNull(expression);
- return expression;
- }
-}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/208f26c7/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java
new file mode 100644
index 0000000..7da823e
--- /dev/null
+++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java
@@ -0,0 +1,210 @@
+/*
+ * 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.ArrayList;
+
+import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
+import org.apache.olingo.server.core.uri.parser.ExpressionParser.Token;
+import org.apache.olingo.server.core.uri.parser.ExpressionParser.TokenKind;
+import org.apache.olingo.server.core.uri.parser.ExpressionParser.Tokenizer;
+import org.junit.Test;
+
+public class ExpressionParserTest {
+
+ @Test
+ public void equality() throws Exception {
+ Expression expression = parseExpression(TokenKind.EQ_OP);
+ assertEquals("{5 EQ 5}", expression.toString());
+
+ expression = parseExpression(TokenKind.NE_OP);
+ assertEquals("{5 NE 5}", expression.toString());
+ }
+
+ @Test
+ public void relational() throws Exception {
+ Expression expression = parseExpression(TokenKind.GT_OP);
+ assertEquals("{5 GT 5}", expression.toString());
+
+ expression = parseExpression(TokenKind.GE_OP);
+ assertEquals("{5 GE 5}", expression.toString());
+
+ expression = parseExpression(TokenKind.LT_OP);
+ assertEquals("{5 LT 5}", expression.toString());
+
+ expression = parseExpression(TokenKind.LE_OP);
+ assertEquals("{5 LE 5}", expression.toString());
+ }
+
+ @Test
+ public void additive() throws Exception {
+ Expression expression = parseExpression(TokenKind.ADD_OP);
+ assertEquals("{5 ADD 5}", expression.toString());
+
+ expression = parseExpression(TokenKind.SUB_OP);
+ assertEquals("{5 SUB 5}", expression.toString());
+ }
+
+ @Test
+ public void multiplicative() throws Exception {
+ Expression expression = parseExpression(TokenKind.MUL_OP);
+ assertEquals("{5 MUL 5}", expression.toString());
+
+ expression = parseExpression(TokenKind.DIV_OP);
+ assertEquals("{5 DIV 5}", expression.toString());
+
+ expression = parseExpression(TokenKind.MOD_OP);
+ assertEquals("{5 MOD 5}", expression.toString());
+ }
+
+ @Test
+ public void unary() throws Exception {
+ ArrayList<Token> tokens = new ArrayList<Token>();
+ tokens.add(new Token(TokenKind.MINUS, ""));
+ tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
+ Tokenizer tokenizer = new Tokenizer(tokens);
+ Expression expression = new ExpressionParser().parse(tokenizer);
+ assertEquals("{- 5}", expression.toString());
+
+ tokens = new ArrayList<Token>();
+ tokens.add(new Token(TokenKind.NOT, ""));
+ tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
+ tokenizer = new Tokenizer(tokens);
+ expression = new ExpressionParser().parse(tokenizer);
+ assertEquals("{not 5}", expression.toString());
+ }
+
+ @Test
+ public void grouping() throws Exception {
+ ArrayList<Token> tokens = new ArrayList<Token>();
+ tokens.add(new Token(TokenKind.MINUS, ""));
+ tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
+ tokens.add(new Token(TokenKind.ADD_OP, ""));
+ tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
+ Tokenizer tokenizer = new Tokenizer(tokens);
+ Expression expression = new ExpressionParser().parse(tokenizer);
+ assertEquals("{{- 5} ADD 5}", expression.toString());
+
+ tokens = new ArrayList<Token>();
+ tokens.add(new Token(TokenKind.MINUS, ""));
+ tokens.add(new Token(TokenKind.OPEN, ""));
+ tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
+ tokens.add(new Token(TokenKind.ADD_OP, ""));
+ tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
+ tokens.add(new Token(TokenKind.CLOSE, ""));
+ tokenizer = new Tokenizer(tokens);
+ expression = new ExpressionParser().parse(tokenizer);
+ assertEquals("{- {5 ADD 5}}", expression.toString());
+ }
+
+ @Test
+ public void noParameterMethods() throws Exception {
+ Expression expression = parseMethod(TokenKind.Now);
+ assertEquals("{now []}", expression.toString());
+
+ expression = parseMethod(TokenKind.Maxdatetime);
+ assertEquals("{maxdatetime []}", expression.toString());
+
+ expression = parseMethod(TokenKind.Mindatetime);
+ assertEquals("{mindatetime []}", expression.toString());
+ }
+
+ @Test
+ public void oneParameterMethods() throws Exception {
+ Expression expression = parseMethod(TokenKind.Length, TokenKind.PrimitiveStringValue);
+ assertEquals("{length [String1]}", expression.toString());
+
+ expression = parseMethod(TokenKind.Tolower, TokenKind.PrimitiveStringValue);
+ assertEquals("{tolower [String1]}", expression.toString());
+
+ expression = parseMethod(TokenKind.Toupper, TokenKind.PrimitiveStringValue);
+ assertEquals("{toupper [String1]}", expression.toString());
+
+ expression = parseMethod(TokenKind.Trim, TokenKind.PrimitiveStringValue);
+ assertEquals("{trim [String1]}", expression.toString());
+
+ expression = parseMethod(TokenKind.Year, TokenKind.PrimitiveDateValue);
+ assertEquals("{year [Date1]}", expression.toString());
+
+ expression = parseMethod(TokenKind.Month, TokenKind.PrimitiveDateValue);
+ assertEquals("{month [Date1]}", expression.toString());
+
+ expression = parseMethod(TokenKind.Day, TokenKind.PrimitiveDateValue);
+ assertEquals("{day [Date1]}", expression.toString());
+
+ expression = parseMethod(TokenKind.Hour, TokenKind.PrimitiveDateTimeOffsetValue);
+ assertEquals("{hour [DateTimeOffset1]}", expression.toString());
+
+ expression = parseMethod(TokenKind.Minute, TokenKind.PrimitiveDateTimeOffsetValue);
+ assertEquals("{minute [DateTimeOffset1]}", expression.toString());
+
+ expression = parseMethod(TokenKind.Second, TokenKind.PrimitiveDateTimeOffsetValue);
+ assertEquals("{second [DateTimeOffset1]}", expression.toString());
+ }
+
+ @Test
+ public void twoParameterMethods() {
+
+ }
+
+ private Expression parseMethod(TokenKind... kind) throws UriParserException {
+ ArrayList<Token> tokens = new ArrayList<Token>();
+ tokens.add(new Token(kind[0], ""));
+
+ for (int i = 1; i < kind.length; i++) {
+ String text = null;
+ switch (kind[i]) {
+ case PrimitiveStringValue:
+ text = "String" + i;
+ break;
+ case PrimitiveDateValue:
+ text = "Date" + i;
+ break;
+ case PrimitiveDateTimeOffsetValue:
+ text = "DateTimeOffset" + i;
+ break;
+ default:
+ text = "" + i;
+ break;
+ }
+ tokens.add(new Token(kind[i], text));
+ }
+
+ tokens.add(new Token(TokenKind.CLOSE, ""));
+ Tokenizer tokenizer = new Tokenizer(tokens);
+ Expression expression = new ExpressionParser().parse(tokenizer);
+ assertNotNull(expression);
+ return expression;
+ }
+
+ private Expression parseExpression(TokenKind operator) throws UriParserException {
+ ArrayList<Token> tokens = new ArrayList<Token>();
+ tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
+ tokens.add(new Token(operator, ""));
+ tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
+ Tokenizer tokenizer = new Tokenizer(tokens);
+
+ Expression expression = new ExpressionParser().parse(tokenizer);
+ assertNotNull(expression);
+ return expression;
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/208f26c7/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/UriResourceImplTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/UriResourceImplTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/UriResourceImplTest.java
index a5d0ea3..a945d11 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/UriResourceImplTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/UriResourceImplTest.java
@@ -43,7 +43,7 @@ import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.edmx.EdmxReference;
import org.apache.olingo.server.api.uri.UriParameter;
import org.apache.olingo.server.api.uri.UriResourceKind;
-import org.apache.olingo.server.core.uri.queryoption.expression.ExpressionImpl;
+import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
import org.apache.olingo.server.core.uri.queryoption.expression.LiteralImpl;
import org.apache.olingo.server.tecsvc.provider.ActionProvider;
import org.apache.olingo.server.tecsvc.provider.ComplexTypeProvider;
@@ -59,7 +59,7 @@ public class UriResourceImplTest {
@Test
public void testUriParameterImpl() {
UriParameterImpl impl = new UriParameterImpl();
- ExpressionImpl expression = new LiteralImpl().setText("Expression");
+ Expression expression = new LiteralImpl("Expression", null);
impl.setText("Text");
impl.setName("A");
@@ -105,7 +105,7 @@ public class UriResourceImplTest {
UriResourceLambdaAllImpl impl = new UriResourceLambdaAllImpl();
assertEquals(UriResourceKind.lambdaAll, impl.getKind());
- ExpressionImpl expression = new LiteralImpl().setText("Expression");
+ Expression expression = new LiteralImpl("Expression", null);
impl.setExpression(expression);
impl.setLamdaVariable("A");
@@ -121,7 +121,7 @@ public class UriResourceImplTest {
UriResourceLambdaAnyImpl impl = new UriResourceLambdaAnyImpl();
assertEquals(UriResourceKind.lambdaAny, impl.getKind());
- ExpressionImpl expression = new LiteralImpl().setText("Expression");
+ Expression expression = new LiteralImpl("Expression", null);
impl.setExpression(expression);
impl.setLamdaVariable("A");
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/208f26c7/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/queryoption/QueryOptionTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/queryoption/QueryOptionTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/queryoption/QueryOptionTest.java
index 93cdf86..db9f5be 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/queryoption/QueryOptionTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/queryoption/QueryOptionTest.java
@@ -44,7 +44,7 @@ public class QueryOptionTest {
public void testAliasQueryOption() {
AliasQueryOptionImpl option = new AliasQueryOptionImpl();
- Expression expression = new LiteralImpl();
+ Expression expression = new LiteralImpl(null, null);
option.setAliasValue(expression);
assertEquals(expression, option.getValue());
@@ -132,7 +132,7 @@ public class QueryOptionTest {
FilterOptionImpl option = new FilterOptionImpl();
assertEquals(SystemQueryOptionKind.FILTER, option.getKind());
- AliasImpl expression = new AliasImpl();
+ AliasImpl expression = new AliasImpl(null);
option.setExpression(expression);
assertEquals(expression, option.getExpression());
@@ -184,7 +184,7 @@ public class QueryOptionTest {
public void testOrderByItemImpl() {
OrderByItemImpl option = new OrderByItemImpl();
- AliasImpl expression = new AliasImpl();
+ AliasImpl expression = new AliasImpl(null);
option.setExpression(expression);
assertEquals(expression, option.getExpression());
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/208f26c7/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/queryoption/expression/ExpressionTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/queryoption/expression/ExpressionTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/queryoption/expression/ExpressionTest.java
index e8a9b38..ec5ce6e 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/queryoption/expression/ExpressionTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/queryoption/expression/ExpressionTest.java
@@ -37,6 +37,7 @@ import org.apache.olingo.server.api.edmx.EdmxReference;
import org.apache.olingo.server.api.uri.UriInfoKind;
import org.apache.olingo.server.api.uri.UriInfoResource;
import org.apache.olingo.server.api.uri.queryoption.expression.BinaryOperatorKind;
+import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
import org.apache.olingo.server.api.uri.queryoption.expression.ExpressionVisitException;
import org.apache.olingo.server.api.uri.queryoption.expression.MethodKind;
import org.apache.olingo.server.api.uri.queryoption.expression.UnaryOperatorKind;
@@ -56,7 +57,7 @@ public class ExpressionTest {
new EdmTechProvider(), Collections.<EdmxReference> emptyList()).getEdm();
@Test
- public void testSupportedOperators() {
+ public void supportedOperators() {
assertEquals(UnaryOperatorKind.MINUS, UnaryOperatorKind.get("-"));
assertEquals(null, UnaryOperatorKind.get("XXX"));
@@ -68,28 +69,21 @@ public class ExpressionTest {
}
@Test
- public void testAliasExpression() throws ExpressionVisitException, ODataApplicationException {
- AliasImpl expression = new AliasImpl();
-
- expression.setParameter("Test");
+ public void aliasExpression() throws ExpressionVisitException, ODataApplicationException {
+ AliasImpl expression = new AliasImpl("Test");
assertEquals("Test", expression.getParameterName());
String output = expression.accept(new FilterTreeToText());
assertEquals("<Test>", output);
-
}
@Test
- public void testBinaryExpression() throws ExpressionVisitException, ODataApplicationException {
- BinaryImpl expression = new BinaryImpl();
-
- ExpressionImpl expressionLeft = new LiteralImpl().setText("A");
- ExpressionImpl expressionRight = new LiteralImpl().setText("B");
+ public void binaryExpression() throws ExpressionVisitException, ODataApplicationException {
+ Expression expressionLeft = new LiteralImpl("A", null);
+ Expression expressionRight = new LiteralImpl("B", null);
- expression.setLeftOperand(expressionLeft);
- expression.setRightOperand(expressionRight);
- expression.setOperator(BinaryOperatorKind.SUB);
+ BinaryImpl expression = new BinaryImpl(expressionLeft, BinaryOperatorKind.SUB, expressionRight);
assertEquals(expressionLeft, expression.getLeftOperand());
assertEquals(expressionRight, expression.getRightOperand());
@@ -100,50 +94,39 @@ public class ExpressionTest {
}
@Test
- public void testEnumerationExpression() throws ExpressionVisitException, ODataApplicationException {
- EnumerationImpl expression = new EnumerationImpl();
+ public void enumerationExpression() throws ExpressionVisitException, ODataApplicationException {
EdmEnumType type = edm.getEnumType(EnumTypeProvider.nameENString);
assertNotNull(type);
- expression.setType(type);
-
+ EnumerationImpl expression = new EnumerationImpl(type, Arrays.asList("A", "B"));
assertEquals(type, expression.getType());
-
- expression.addValue("A");
- expression.addValue("B");
assertEquals("A", expression.getValues().get(0));
assertEquals("B", expression.getValues().get(1));
assertEquals("<olingo.odata.test1.ENString<A,B>>", expression.accept(new FilterTreeToText()));
}
@Test
- public void testLambdaRefExpression() throws ExpressionVisitException, ODataApplicationException {
- LambdaRefImpl expression = new LambdaRefImpl();
- expression.setVariableText("A");
+ public void lambdaRefExpression() throws ExpressionVisitException, ODataApplicationException {
+ LambdaRefImpl expression = new LambdaRefImpl("A");
assertEquals("A", expression.getVariableName());
-
assertEquals("<A>", expression.accept(new FilterTreeToText()));
-
}
@Test
- public void testLiteralExpresion() throws ExpressionVisitException, ODataApplicationException {
- LiteralImpl expression = new LiteralImpl();
- expression.setText("A");
+ public void literalExpression() throws ExpressionVisitException, ODataApplicationException {
+ LiteralImpl expression = new LiteralImpl("A", null);
assertEquals("A", expression.getText());
-
assertEquals("<A>", expression.accept(new FilterTreeToText()));
}
@Test
- public void testMemberExpression() throws ExpressionVisitException, ODataApplicationException {
- MemberImpl expression = new MemberImpl();
+ public void memberExpression() throws ExpressionVisitException, ODataApplicationException {
EdmEntityType entityType = edm.getEntityType(EntityTypeProvider.nameETKeyNav);
// UriResourceImpl
EdmAction action = edm.getUnboundAction(ActionProvider.nameUARTString);
UriInfoResource uriInfo = new UriInfoImpl().setKind(UriInfoKind.resource).addResourcePart(
new UriResourceActionImpl().setAction(action)).asUriInfoResource();
- expression.setResourcePath(uriInfo);
+ MemberImpl expression = new MemberImpl(uriInfo, null);
assertEquals(action.getReturnType().getType(), expression.getType());
// check accept and path
@@ -155,45 +138,50 @@ public class ExpressionTest {
// UriResourceImplTyped check collection = true case
action = edm.getUnboundAction(ActionProvider.nameUARTCollStringTwoParam);
- expression.setResourcePath(new UriInfoImpl().setKind(UriInfoKind.resource)
+ expression = new MemberImpl(new UriInfoImpl().setKind(UriInfoKind.resource)
.addResourcePart(new UriResourceActionImpl().setAction(action))
- .asUriInfoResource());
+ .asUriInfoResource(),
+ null);
assertTrue(expression.isCollection());
// UriResourceImplTyped with filter
EdmFunction function = edm.getUnboundFunction(FunctionProvider.nameUFCRTETKeyNav, null);
- expression.setResourcePath(new UriInfoImpl().setKind(UriInfoKind.resource).addResourcePart(
+ expression = new MemberImpl(new UriInfoImpl().setKind(UriInfoKind.resource).addResourcePart(
new UriResourceFunctionImpl().setFunction(function).setEntryTypeFilter(entityType))
- .asUriInfoResource());
+ .asUriInfoResource(),
+ null);
assertEquals(entityType, expression.getType());
// UriResourceImplKeyPred
function = edm.getUnboundFunction(FunctionProvider.nameUFCRTETKeyNav, null);
- expression.setResourcePath(new UriInfoImpl().setKind(UriInfoKind.resource).addResourcePart(
+ expression = new MemberImpl(new UriInfoImpl().setKind(UriInfoKind.resource).addResourcePart(
new UriResourceFunctionImpl().setFunction(function))
- .asUriInfoResource());
+ .asUriInfoResource(),
+ null);
assertEquals(function.getReturnType().getType(), expression.getType());
// UriResourceImplKeyPred typeFilter on entry
EdmEntityType entityBaseType = edm.getEntityType(EntityTypeProvider.nameETBaseTwoKeyNav);
function = edm.getUnboundFunction(FunctionProvider.nameUFCRTCollETTwoKeyNavParam, Arrays.asList("ParameterInt16"));
- expression.setResourcePath(new UriInfoImpl().setKind(UriInfoKind.resource).addResourcePart(
+ expression = new MemberImpl(new UriInfoImpl().setKind(UriInfoKind.resource).addResourcePart(
new UriResourceFunctionImpl().setFunction(function).setEntryTypeFilter(entityBaseType))
- .asUriInfoResource());
+ .asUriInfoResource(),
+ null);
assertEquals(entityBaseType, expression.getType());
// UriResourceImplKeyPred typeFilter on entry
entityBaseType = edm.getEntityType(EntityTypeProvider.nameETBaseTwoKeyNav);
function = edm.getUnboundFunction(FunctionProvider.nameUFCRTCollETTwoKeyNavParam, Arrays.asList("ParameterInt16"));
- expression.setResourcePath(new UriInfoImpl().setKind(UriInfoKind.resource).addResourcePart(
+ expression = new MemberImpl(new UriInfoImpl().setKind(UriInfoKind.resource).addResourcePart(
new UriResourceFunctionImpl().setFunction(function).setCollectionTypeFilter(entityBaseType))
- .asUriInfoResource());
+ .asUriInfoResource(),
+ null);
assertEquals(entityBaseType, expression.getType());
// no typed
entityBaseType = edm.getEntityType(EntityTypeProvider.nameETBaseTwoKeyNav);
function = edm.getUnboundFunction(FunctionProvider.nameUFCRTCollETTwoKeyNavParam, Arrays.asList("ParameterInt16"));
- expression.setResourcePath(new UriInfoImpl().setKind(UriInfoKind.all));
+ expression = new MemberImpl(new UriInfoImpl().setKind(UriInfoKind.all), null);
assertEquals(null, expression.getType());
// no typed collection else case
@@ -201,14 +189,10 @@ public class ExpressionTest {
}
@Test
- public void testMethodCallExpression() throws ExpressionVisitException, ODataApplicationException {
- MethodImpl expression = new MethodImpl();
- expression.setMethod(MethodKind.CONCAT);
-
- ExpressionImpl p0 = new LiteralImpl().setText("A");
- ExpressionImpl p1 = new LiteralImpl().setText("B");
- expression.addParameter(p0);
- expression.addParameter(p1);
+ public void methodCallExpression() throws ExpressionVisitException, ODataApplicationException {
+ Expression p0 = new LiteralImpl("A", null);
+ Expression p1 = new LiteralImpl("B", null);
+ MethodImpl expression = new MethodImpl(MethodKind.CONCAT, Arrays.asList(p0, p1));
assertEquals(MethodKind.CONCAT, expression.getMethod());
assertEquals("<concat(<A>,<B>)>", expression.accept(new FilterTreeToText()));
@@ -218,27 +202,22 @@ public class ExpressionTest {
}
@Test
- public void testTypeLiteralExpression() throws ExpressionVisitException, ODataApplicationException {
- TypeLiteralImpl expression = new TypeLiteralImpl();
+ public void typeLiteralExpression() throws ExpressionVisitException, ODataApplicationException {
EdmEntityType entityBaseType = edm.getEntityType(EntityTypeProvider.nameETBaseTwoKeyNav);
- expression.setType(entityBaseType);
+ TypeLiteralImpl expression = new TypeLiteralImpl(entityBaseType);
assertEquals(entityBaseType, expression.getType());
assertEquals("<olingo.odata.test1.ETBaseTwoKeyNav>", expression.accept(new FilterTreeToText()));
}
@Test
- public void testUnaryExpression() throws ExpressionVisitException, ODataApplicationException {
- UnaryImpl expression = new UnaryImpl();
- expression.setOperator(UnaryOperatorKind.MINUS);
-
- ExpressionImpl operand = new LiteralImpl().setText("A");
- expression.setOperand(operand);
+ public void unaryExpression() throws ExpressionVisitException, ODataApplicationException {
+ Expression operand = new LiteralImpl("A", null);
+ UnaryImpl expression = new UnaryImpl(UnaryOperatorKind.MINUS, operand);
assertEquals(UnaryOperatorKind.MINUS, expression.getOperator());
assertEquals(operand, expression.getOperand());
assertEquals("<- <A>>", expression.accept(new FilterTreeToText()));
}
-
}
[03/30] olingo-odata4 git commit: [OLINGO-834] URI resource-path
parser in Java
Posted by ch...@apache.org.
[OLINGO-834] URI resource-path parser in Java
Signed-off-by: Michael Bolz <mi...@sap.com>
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/927ecb93
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/927ecb93
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/927ecb93
Branch: refs/heads/master
Commit: 927ecb93e34a8a1d4b5ff1dfefb96882b50a028b
Parents: d88913f
Author: Klaus Straubinger <kl...@sap.com>
Authored: Fri Dec 4 15:47:51 2015 +0100
Committer: Michael Bolz <mi...@sap.com>
Committed: Mon Dec 7 13:17:50 2015 +0100
----------------------------------------------------------------------
.../olingo/fit/tecsvc/client/BasicITCase.java | 2 +-
.../core/edm/primitivetype/EdmBinary.java | 12 +-
.../edm/provider/EdmActionImportImplTest.java | 2 +-
.../core/edm/provider/EdmProviderImplTest.java | 4 +-
.../core/edm/provider/EdmSchemaImplTest.java | 1 +
.../apache/olingo/server/core/ErrorHandler.java | 8 +-
.../olingo/server/core/ServiceDispatcher.java | 4 +-
.../olingo/server/core/ServiceRequest.java | 6 +-
.../apache/olingo/server/core/ODataHandler.java | 4 +-
.../olingo/server/core/uri/UriHelperImpl.java | 9 +-
.../uri/UriResourceNavigationPropertyImpl.java | 5 +-
.../core/uri/UriResourceWithKeysImpl.java | 3 +-
.../olingo/server/core/uri/parser/Parser.java | 202 +++---
.../core/uri/parser/ResourcePathParser.java | 692 +++++++++++++++++++
.../core/uri/parser/UriParseTreeVisitor.java | 2 +-
.../server/core/uri/parser/UriTokenizer.java | 592 ++++++++++++++++
.../server/core/uri/validator/UriValidator.java | 74 +-
.../core/uri/parser/UriTokenizerTest.java | 369 ++++++++++
.../uri/parser/search/SearchTokenizerTest.java | 1 -
.../server/tecsvc/data/DataProviderTest.java | 4 +-
.../server/core/PreconditionsValidatorTest.java | 25 +-
.../serializer/utils/ContextURLHelperTest.java | 4 +-
.../olingo/server/core/uri/UriHelperTest.java | 4 +-
.../server/core/uri/UriResourceImplTest.java | 14 +-
.../core/uri/antlr/TestFullResourcePath.java | 154 +++--
.../core/uri/antlr/TestUriParserImpl.java | 15 +-
.../server/core/uri/parser/ParserTest.java | 4 +-
.../core/uri/testutil/FilterValidator.java | 62 +-
.../core/uri/testutil/ParserWithLogging.java | 5 +-
.../core/uri/testutil/ResourceValidator.java | 13 +-
.../core/uri/testutil/TestUriValidator.java | 14 +-
.../core/uri/validator/UriValidatorTest.java | 17 +-
32 files changed, 1973 insertions(+), 354 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/927ecb93/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BasicITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BasicITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BasicITCase.java
index a09cafa..c8e4848 100644
--- a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BasicITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BasicITCase.java
@@ -245,7 +245,7 @@ public class BasicITCase extends AbstractParamTecSvcITCase {
} catch (final ODataClientErrorException e) {
assertEquals(HttpStatusCode.BAD_REQUEST.getStatusCode(), e.getStatusLine().getStatusCode());
final ODataError error = e.getODataError();
- assertThat(error.getMessage(), containsString("key property"));
+ assertThat(error.getMessage(), containsString("key"));
}
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/927ecb93/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmBinary.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmBinary.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmBinary.java
index 735250a..bdbc3fa 100644
--- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmBinary.java
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmBinary.java
@@ -133,19 +133,19 @@ public class EdmBinary extends SingletonPrimitiveType {
final Boolean isNullable, final Integer maxLength, final Integer precision,
final Integer scale, final Boolean isUnicode) {
- return value == null
- ? isNullable == null || isNullable
- : isBase64(value.getBytes(UTF_8)) && validateMaxLength(value, maxLength);
+ return value == null ?
+ isNullable == null || isNullable :
+ isBase64(value.getBytes(UTF_8)) && validateMaxLength(value, maxLength);
}
private static boolean validateMaxLength(final String value, final Integer maxLength) {
- return maxLength == null ? true
- : // Every three bytes are represented as four base-64 characters.
+ return maxLength == null ? true :
+ // Every three bytes are represented as four base-64 characters.
// Additionally, there could be up to two padding "=" characters
// if the number of bytes is not a multiple of three,
// and there could be line feeds, possibly with carriage returns.
maxLength >= (value.length() - lineEndingsLength(value)) * 3 / 4
- - (value.endsWith("==") ? 2 : value.endsWith("=") ? 1 : 0);
+ - (value.endsWith("==") ? 2 : value.endsWith("=") ? 1 : 0);
}
private static int lineEndingsLength(final String value) {
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/927ecb93/lib/commons-core/src/test/java/org/apache/olingo/server/core/edm/provider/EdmActionImportImplTest.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/test/java/org/apache/olingo/server/core/edm/provider/EdmActionImportImplTest.java b/lib/commons-core/src/test/java/org/apache/olingo/server/core/edm/provider/EdmActionImportImplTest.java
index 02824f4..e4cd593 100644
--- a/lib/commons-core/src/test/java/org/apache/olingo/server/core/edm/provider/EdmActionImportImplTest.java
+++ b/lib/commons-core/src/test/java/org/apache/olingo/server/core/edm/provider/EdmActionImportImplTest.java
@@ -96,7 +96,7 @@ public class EdmActionImportImplTest {
String target = "nonExisting";
CsdlActionImport providerActionImport = new CsdlActionImport().setName("actionImportName").setEntitySet(target);
EdmProviderImpl edm = mock(EdmProviderImpl.class);
- when(edm.getEntityContainer(null)).thenReturn(container);
+ when(edm.getEntityContainer()).thenReturn(container);
EdmActionImport actionImport = new EdmActionImportImpl(edm, container, providerActionImport);
actionImport.getReturnedEntitySet();
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/927ecb93/lib/commons-core/src/test/java/org/apache/olingo/server/core/edm/provider/EdmProviderImplTest.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/test/java/org/apache/olingo/server/core/edm/provider/EdmProviderImplTest.java b/lib/commons-core/src/test/java/org/apache/olingo/server/core/edm/provider/EdmProviderImplTest.java
index 6ce6ab8..7ba529a 100644
--- a/lib/commons-core/src/test/java/org/apache/olingo/server/core/edm/provider/EdmProviderImplTest.java
+++ b/lib/commons-core/src/test/java/org/apache/olingo/server/core/edm/provider/EdmProviderImplTest.java
@@ -183,7 +183,7 @@ public class EdmProviderImplTest {
when(localProvider.getAliasInfos()).thenThrow(new ODataException("msg"));
Edm localEdm = new EdmProviderImpl(localProvider);
- localEdm.getEntityContainer(null);
+ localEdm.getEntityContainer();
}
@Test
@@ -193,7 +193,7 @@ public class EdmProviderImplTest {
assertEquals(FQN.getNamespace(), entityContainer.getNamespace());
assertEquals(FQN.getName(), entityContainer.getName());
- entityContainer = edm.getEntityContainer(null);
+ entityContainer = edm.getEntityContainer();
assertNotNull(entityContainer);
assertEquals(FQN.getNamespace(), entityContainer.getNamespace());
assertEquals(FQN.getName(), entityContainer.getName());
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/927ecb93/lib/commons-core/src/test/java/org/apache/olingo/server/core/edm/provider/EdmSchemaImplTest.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/test/java/org/apache/olingo/server/core/edm/provider/EdmSchemaImplTest.java b/lib/commons-core/src/test/java/org/apache/olingo/server/core/edm/provider/EdmSchemaImplTest.java
index e6502af..2c95ce1 100644
--- a/lib/commons-core/src/test/java/org/apache/olingo/server/core/edm/provider/EdmSchemaImplTest.java
+++ b/lib/commons-core/src/test/java/org/apache/olingo/server/core/edm/provider/EdmSchemaImplTest.java
@@ -229,6 +229,7 @@ public class EdmSchemaImplTest {
assertTrue(container == edm.getEntityContainer(new FullQualifiedName(schema.getNamespace(), container.getName())));
assertTrue(container == edm.getEntityContainer(null));
+ assertTrue(container == edm.getEntityContainer());
}
private class LocalProvider implements CsdlEdmProvider {
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/927ecb93/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ErrorHandler.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ErrorHandler.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ErrorHandler.java
index 5f425da..33f65cd 100644
--- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ErrorHandler.java
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ErrorHandler.java
@@ -90,13 +90,15 @@ public class ErrorHandler {
final ODataServerError serverError) {
ContentType requestedContentType;
try {
- UriInfo uriInfo = new Parser().parseUri(request.getRawODataPath(), request.getRawQueryPath(),
- null, this.metadata.getEdm());
+ final UriInfo uriInfo = new Parser(metadata.getEdm(), odata)
+ .parseUri(request.getRawODataPath(), request.getRawQueryPath(), null);
requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
request, this.customContent, RepresentationType.ERROR);
} catch (final ContentNegotiatorException e) {
requestedContentType = ContentType.JSON;
- } catch (UriParserException e) {
+ } catch (final UriParserException e) {
+ requestedContentType = ContentType.JSON;
+ } catch (final UriValidationException e) {
requestedContentType = ContentType.JSON;
}
processError(response, serverError, requestedContentType);
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/927ecb93/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceDispatcher.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceDispatcher.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceDispatcher.java
index 17ec358..45de757 100644
--- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceDispatcher.java
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceDispatcher.java
@@ -76,8 +76,8 @@ public class ServiceDispatcher extends RequestURLHierarchyVisitor {
public void execute(ODataRequest odRequest, ODataResponse odResponse)
throws ODataLibraryException, ODataApplicationException {
- UriInfo uriInfo = new Parser().parseUri(odRequest.getRawODataPath(), odRequest.getRawQueryPath(), null,
- this.metadata.getEdm());
+ UriInfo uriInfo = new Parser(this.metadata.getEdm(), odata)
+ .parseUri(odRequest.getRawODataPath(), odRequest.getRawQueryPath(), null);
new UriValidator().validate(uriInfo, odRequest.getMethod());
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/927ecb93/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceRequest.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceRequest.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceRequest.java
index 8195b85..0796144 100644
--- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceRequest.java
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceRequest.java
@@ -47,6 +47,7 @@ import org.apache.olingo.server.api.uri.UriInfo;
import org.apache.olingo.server.core.requests.DataRequest;
import org.apache.olingo.server.core.uri.parser.Parser;
import org.apache.olingo.server.core.uri.parser.UriParserException;
+import org.apache.olingo.server.core.uri.validator.UriValidationException;
public abstract class ServiceRequest {
protected OData odata;
@@ -240,7 +241,7 @@ public abstract class ServiceRequest {
return null;
}
- public DataRequest parseLink(URI uri) throws UriParserException, URISyntaxException {
+ public DataRequest parseLink(URI uri) throws UriParserException, UriValidationException, URISyntaxException {
String path = "/";
URI servicePath = new URI(getODataRequest().getRawBaseUri());
path = servicePath.getPath();
@@ -253,8 +254,7 @@ public abstract class ServiceRequest {
rawPath = rawPath.substring(e+path.length());
}
- UriInfo uriInfo = new Parser().parseUri(rawPath, uri.getQuery(), null,
- this.serviceMetadata.getEdm());
+ UriInfo uriInfo = new Parser(serviceMetadata.getEdm(), odata).parseUri(rawPath, uri.getQuery(), null);
ServiceDispatcher dispatcher = new ServiceDispatcher(odata, serviceMetadata, null, customContentType);
dispatcher.visit(uriInfo);
return (DataRequest)dispatcher.request;
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/927ecb93/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java
index 12f2dfd..8c2e286 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java
@@ -129,8 +129,8 @@ public class ODataHandler {
final int measurementUriParser = debugger.startRuntimeMeasurement("UriParser", "parseUri");
try {
- uriInfo = new Parser().parseUri(request.getRawODataPath(), request.getRawQueryPath(), null,
- serviceMetadata.getEdm());
+ uriInfo = new Parser(serviceMetadata.getEdm(), odata)
+ .parseUri(request.getRawODataPath(), request.getRawQueryPath(), null);
} catch (final ODataLibraryException e) {
debugger.stopRuntimeMeasurement(measurementUriParser);
debugger.stopRuntimeMeasurement(measurementHandle);
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/927ecb93/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriHelperImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriHelperImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriHelperImpl.java
index c463765..3bc5ad0 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriHelperImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriHelperImpl.java
@@ -29,6 +29,7 @@ import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
import org.apache.olingo.commons.api.edm.EdmProperty;
import org.apache.olingo.commons.api.edm.EdmStructuredType;
import org.apache.olingo.commons.core.Encoder;
+import org.apache.olingo.server.api.ODataLibraryException;
import org.apache.olingo.server.api.deserializer.DeserializerException;
import org.apache.olingo.server.api.deserializer.DeserializerException.MessageKeys;
import org.apache.olingo.server.api.serializer.SerializerException;
@@ -39,9 +40,9 @@ import org.apache.olingo.server.api.uri.UriResourceEntitySet;
import org.apache.olingo.server.api.uri.UriResourceKind;
import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
import org.apache.olingo.server.api.uri.queryoption.SelectOption;
+import org.apache.olingo.server.core.ODataImpl;
import org.apache.olingo.server.core.serializer.utils.ContextURLHelper;
import org.apache.olingo.server.core.uri.parser.Parser;
-import org.apache.olingo.server.core.uri.parser.UriParserException;
public class UriHelperImpl implements UriHelper {
@@ -107,8 +108,8 @@ public class UriHelperImpl implements UriHelper {
oDataPath = oDataPath.startsWith("/") ? oDataPath : "/" + oDataPath;
try {
- final List<UriResource> uriResourceParts = new Parser().parseUri(oDataPath, null, null, edm)
- .getUriResourceParts();
+ final List<UriResource> uriResourceParts =
+ new Parser(edm, new ODataImpl()).parseUri(oDataPath, null, null).getUriResourceParts();
if (uriResourceParts.size() == 1 && uriResourceParts.get(0).getKind() == UriResourceKind.entitySet) {
final UriResourceEntitySet entityUriResource = (UriResourceEntitySet) uriResourceParts.get(0);
@@ -117,7 +118,7 @@ public class UriHelperImpl implements UriHelper {
throw new DeserializerException("Invalid entity binding link", MessageKeys.INVALID_ENTITY_BINDING_LINK,
entityId);
- } catch (UriParserException e) {
+ } catch (final ODataLibraryException e) {
throw new DeserializerException("Invalid entity binding link", e, MessageKeys.INVALID_ENTITY_BINDING_LINK,
entityId);
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/927ecb93/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceNavigationPropertyImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceNavigationPropertyImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceNavigationPropertyImpl.java
index 1a4fa44..f4390b5 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceNavigationPropertyImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceNavigationPropertyImpl.java
@@ -49,10 +49,7 @@ public class UriResourceNavigationPropertyImpl extends UriResourceWithKeysImpl i
@Override
public boolean isCollection() {
- if (keyPredicates != null) {
- return false;
- }
- return navigationProperty.isCollection();
+ return navigationProperty.isCollection() && keyPredicates == null;
}
@Override
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/927ecb93/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceWithKeysImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceWithKeysImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceWithKeysImpl.java
index 54d62a1..c300d78 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceWithKeysImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceWithKeysImpl.java
@@ -18,7 +18,6 @@
*/
package org.apache.olingo.server.core.uri;
-import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -48,7 +47,7 @@ public abstract class UriResourceWithKeysImpl extends UriResourceImpl implements
public List<UriParameter> getKeyPredicates() {
return keyPredicates == null ?
Collections.<UriParameter> emptyList() :
- new ArrayList<UriParameter>(keyPredicates);
+ Collections.unmodifiableList(keyPredicates);
}
public UriResourceWithKeysImpl setKeyPredicates(final List<UriParameter> list) {
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/927ecb93/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
index d12b853..5caaaeb 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
@@ -18,7 +18,6 @@
*/
package org.apache.olingo.server.core.uri.parser;
-import java.util.ArrayList;
import java.util.List;
import org.antlr.v4.runtime.ANTLRInputStream;
@@ -31,11 +30,15 @@ import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.atn.PredictionMode;
import org.antlr.v4.runtime.misc.ParseCancellationException;
import org.apache.olingo.commons.api.edm.Edm;
+import org.apache.olingo.commons.api.edm.EdmEntityContainer;
import org.apache.olingo.commons.api.ex.ODataRuntimeException;
+import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.uri.UriInfo;
import org.apache.olingo.server.api.uri.UriInfoKind;
import org.apache.olingo.server.api.uri.UriResource;
+import org.apache.olingo.server.api.uri.UriResourceAction;
import org.apache.olingo.server.api.uri.UriResourceCount;
+import org.apache.olingo.server.api.uri.UriResourceFunction;
import org.apache.olingo.server.api.uri.UriResourcePartTyped;
import org.apache.olingo.server.api.uri.UriResourceRef;
import org.apache.olingo.server.api.uri.UriResourceValue;
@@ -46,18 +49,14 @@ import org.apache.olingo.server.api.uri.queryoption.SystemQueryOption;
import org.apache.olingo.server.api.uri.queryoption.SystemQueryOptionKind;
import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
import org.apache.olingo.server.core.uri.UriInfoImpl;
+import org.apache.olingo.server.core.uri.UriResourceStartingTypeFilterImpl;
import org.apache.olingo.server.core.uri.antlr.UriLexer;
import org.apache.olingo.server.core.uri.antlr.UriParserParser;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.AllEOFContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.BatchEOFContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.CrossjoinEOFContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.EntityEOFContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandItemsEOFContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.FilterExpressionEOFContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.MetadataEOFContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.OrderByEOFContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.PathSegmentEOFContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.SelectEOFContext;
+import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind;
import org.apache.olingo.server.core.uri.parser.search.SearchParser;
import org.apache.olingo.server.core.uri.queryoption.AliasQueryOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.CountOptionImpl;
@@ -71,6 +70,7 @@ import org.apache.olingo.server.core.uri.queryoption.SelectOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.SkipOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.SkipTokenOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.TopOptionImpl;
+import org.apache.olingo.server.core.uri.validator.UriValidationException;
public class Parser {
private static final String ATOM = "atom";
@@ -78,19 +78,22 @@ public class Parser {
private static final String XML = "xml";
private static final String AT = "@";
private static final String NULL = "null";
+
int logLevel = 0;
+ private final Edm edm;
+ private final OData odata;
private enum ParserEntryRules {
- All, Batch, CrossJoin, Entity, ExpandItems, FilterExpression, Metadata, PathSegment, Orderby, Select, Search
+ ExpandItems, FilterExpression, Orderby, Select
}
- public Parser setLogLevel(final int logLevel) {
- this.logLevel = logLevel;
- return this;
+ public Parser(final Edm edm, final OData odata) {
+ this.edm = edm;
+ this.odata = odata;
}
- public UriInfo parseUri(final String path, final String query, final String fragment, final Edm edm)
- throws UriParserException {
+ public UriInfo parseUri(final String path, final String query, final String fragment)
+ throws UriParserException, UriValidationException {
UriContext context = new UriContext();
UriParseTreeVisitor uriParseTreeVisitor = new UriParseTreeVisitor(edm, context);
@@ -104,65 +107,74 @@ public class Parser {
if (firstSegment.isEmpty()) {
ensureLastSegment(firstSegment, 0, uri.pathSegmentListDecoded.size());
context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.service);
- } else if (firstSegment.startsWith("$batch")) {
- ensureLastSegment(firstSegment, 1, uri.pathSegmentListDecoded.size());
- BatchEOFContext ctxBatchEOF =
- (BatchEOFContext) parseRule(uri.pathSegmentListDecoded.get(0), ParserEntryRules.Batch);
- uriParseTreeVisitor.visitBatchEOF(ctxBatchEOF);
- } else if (firstSegment.startsWith("$metadata")) {
+ } else if (firstSegment.equals("$batch")) {
ensureLastSegment(firstSegment, 1, uri.pathSegmentListDecoded.size());
- MetadataEOFContext ctxMetadataEOF =
- (MetadataEOFContext) parseRule(uri.pathSegmentListDecoded.get(0), ParserEntryRules.Metadata);
-
- uriParseTreeVisitor.visitMetadataEOF(ctxMetadataEOF);
+ context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.batch);
+ } else if (firstSegment.equals("$metadata")) {
+ ensureLastSegment(firstSegment, 1, uri.pathSegmentListDecoded.size());
+ context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.metadata);
context.contextUriInfo.setFragment(uri.fragment);
- } else if (firstSegment.startsWith("$entity")) {
- context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.entityId);
+ } else if (firstSegment.equals("$all")) {
+ ensureLastSegment(firstSegment, 1, uri.pathSegmentListDecoded.size());
+ context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.all);
+
+ } else if (firstSegment.equals("$entity")) {
if (uri.pathSegmentListDecoded.size() > 1) {
final String typeCastSegment = uri.pathSegmentListDecoded.get(1);
ensureLastSegment(typeCastSegment, 2, uri.pathSegmentListDecoded.size());
- EntityEOFContext ctxEntityEOF =
- (EntityEOFContext) parseRule(typeCastSegment, ParserEntryRules.Entity);
- uriParseTreeVisitor.visitEntityEOF(ctxEntityEOF);
+ context.contextUriInfo = new ResourcePathParser(edm, odata).parseDollarEntityTypeCast(typeCastSegment);
+ context.contextTypes.push(
+ uriParseTreeVisitor.new TypeInformation(context.contextUriInfo.getEntityTypeCast(), false));
+ } else {
+ context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.entityId);
}
- } else if (firstSegment.startsWith("$all")) {
- ensureLastSegment(firstSegment, 1, uri.pathSegmentListDecoded.size());
- AllEOFContext ctxResourcePathEOF =
- (AllEOFContext) parseRule(uri.pathSegmentListDecoded.get(0), ParserEntryRules.All);
-
- uriParseTreeVisitor.visitAllEOF(ctxResourcePathEOF);
} else if (firstSegment.startsWith("$crossjoin")) {
ensureLastSegment(firstSegment, 1, uri.pathSegmentListDecoded.size());
- CrossjoinEOFContext ctxResourcePathEOF =
- (CrossjoinEOFContext) parseRule(uri.pathSegmentListDecoded.get(0), ParserEntryRules.CrossJoin);
-
- uriParseTreeVisitor.visitCrossjoinEOF(ctxResourcePathEOF);
- } else {
- List<PathSegmentEOFContext> ctxPathSegments = new ArrayList<PathSegmentEOFContext>();
- for (String pathSegment : uri.pathSegmentListDecoded) {
- PathSegmentEOFContext ctxPathSegment =
- (PathSegmentEOFContext) parseRule(pathSegment, ParserEntryRules.PathSegment);
- ctxPathSegments.add(ctxPathSegment);
+ context.contextUriInfo = new ResourcePathParser(edm, odata)
+ .parseCrossjoinSegment(uri.pathSegmentListDecoded.get(0));
+ final EdmEntityContainer container = edm.getEntityContainer();
+ for (final String name : context.contextUriInfo.getEntitySetNames()) {
+ context.contextTypes.push(
+ uriParseTreeVisitor.new TypeInformation(container.getEntitySet(name).getEntityType(), true));
}
+ } else {
context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.resource);
-
- for (PathSegmentEOFContext ctxPathSegment : ctxPathSegments) {
- // add checks for batch, entity, metadata, all, crossjoin
- uriParseTreeVisitor.visitPathSegmentEOF(ctxPathSegment);
+ final ResourcePathParser resourcePathParser = new ResourcePathParser(edm, odata);
+ int count = 0;
+ UriResource lastSegment = null;
+ for (final String pathSegment : uri.pathSegmentListDecoded) {
+ count++;
+ final UriResource segment = resourcePathParser.parsePathSegment(pathSegment, lastSegment);
+ if (segment != null) {
+ if (segment instanceof UriResourceCount
+ || segment instanceof UriResourceRef
+ || segment instanceof UriResourceValue) {
+ ensureLastSegment(pathSegment, count, uri.pathSegmentListDecoded.size());
+ } else if (segment instanceof UriResourceAction
+ || segment instanceof UriResourceFunction
+ && !((UriResourceFunction) segment).getFunction().isComposable()) {
+ if (count < uri.pathSegmentListDecoded.size()) {
+ throw new UriValidationException(
+ "The segment of an action or of a non-composable function must be the last resource-path segment.",
+ UriValidationException.MessageKeys.UNALLOWED_RESOURCE_PATH,
+ uri.pathSegmentListDecoded.get(count));
+ }
+ lastSegment = segment;
+ } else if (segment instanceof UriResourceStartingTypeFilterImpl) {
+ throw new UriParserSemanticException("First resource-path segment must not be namespace-qualified.",
+ UriParserSemanticException.MessageKeys.NAMESPACE_NOT_ALLOWED_AT_FIRST_ELEMENT);
+ } else {
+ lastSegment = segment;
+ }
+ context.contextUriInfo.addResourcePart(segment);
+ }
}
- UriResource lastSegment = context.contextUriInfo.getLastResourcePart();
- if (lastSegment instanceof UriResourceCount
- || lastSegment instanceof UriResourceRef
- || lastSegment instanceof UriResourceValue) {
- final List<UriResource> parts = context.contextUriInfo.getUriResourceParts();
- lastSegment = parts.get(parts.size() - 2);
- }
if (lastSegment instanceof UriResourcePartTyped) {
UriResourcePartTyped typed = (UriResourcePartTyped) lastSegment;
@@ -174,13 +186,12 @@ public class Parser {
}
// second, read the system query options and the custom query options
- for (RawUri.QueryOption option : uri.queryOptionListDecoded) {
+ for (final RawUri.QueryOption option : uri.queryOptionListDecoded) {
if (option.name.startsWith("$")) {
SystemQueryOption systemOption = null;
if (option.name.equals(SystemQueryOptionKind.FILTER.toString())) {
FilterExpressionEOFContext ctxFilterExpression =
(FilterExpressionEOFContext) parseRule(option.value, ParserEntryRules.FilterExpression);
-
systemOption = (FilterOptionImpl) uriParseTreeVisitor.visitFilterExpressionEOF(ctxFilterExpression);
} else if (option.name.equals(SystemQueryOptionKind.FORMAT.toString())) {
@@ -201,7 +212,6 @@ public class Parser {
} else if (option.name.equals(SystemQueryOptionKind.EXPAND.toString())) {
ExpandItemsEOFContext ctxExpandItems =
(ExpandItemsEOFContext) parseRule(option.value, ParserEntryRules.ExpandItems);
-
systemOption = (ExpandOptionImpl) uriParseTreeVisitor.visitExpandItemsEOF(ctxExpandItems);
} else if (option.name.equals(SystemQueryOptionKind.ID.toString())) {
@@ -210,22 +220,24 @@ public class Parser {
idOption.setText(option.value);
idOption.setValue(option.value);
systemOption = idOption;
+
} else if (option.name.equals(SystemQueryOptionKind.LEVELS.toString())) {
throw new UriParserSyntaxException("System query option '$levels' is allowed only inside '$expand'!",
UriParserSyntaxException.MessageKeys.SYSTEM_QUERY_OPTION_LEVELS_NOT_ALLOWED_HERE);
+
} else if (option.name.equals(SystemQueryOptionKind.ORDERBY.toString())) {
OrderByEOFContext ctxOrderByExpression =
(OrderByEOFContext) parseRule(option.value, ParserEntryRules.Orderby);
-
systemOption = (OrderByOptionImpl) uriParseTreeVisitor.visitOrderByEOF(ctxOrderByExpression);
+
} else if (option.name.equals(SystemQueryOptionKind.SEARCH.toString())) {
- SearchParser searchParser = new SearchParser();
- systemOption = searchParser.parse(option.value);
+ systemOption = new SearchParser().parse(option.value);
+
} else if (option.name.equals(SystemQueryOptionKind.SELECT.toString())) {
SelectEOFContext ctxSelectEOF =
(SelectEOFContext) parseRule(option.value, ParserEntryRules.Select);
-
systemOption = (SelectOptionImpl) uriParseTreeVisitor.visitSelectEOF(ctxSelectEOF);
+
} else if (option.name.equals(SystemQueryOptionKind.SKIP.toString())) {
SkipOptionImpl skipOption = new SkipOptionImpl();
skipOption.setName(option.name);
@@ -238,12 +250,14 @@ public class Parser {
option.name, option.value);
}
systemOption = skipOption;
+
} else if (option.name.equals(SystemQueryOptionKind.SKIPTOKEN.toString())) {
SkipTokenOptionImpl skipTokenOption = new SkipTokenOptionImpl();
skipTokenOption.setName(option.name);
skipTokenOption.setText(option.value);
skipTokenOption.setValue(option.value);
systemOption = skipTokenOption;
+
} else if (option.name.equals(SystemQueryOptionKind.TOP.toString())) {
TopOptionImpl topOption = new TopOptionImpl();
topOption.setName(option.name);
@@ -256,6 +270,7 @@ public class Parser {
option.name, option.value);
}
systemOption = topOption;
+
} else if (option.name.equals(SystemQueryOptionKind.COUNT.toString())) {
CountOptionImpl inlineCountOption = new CountOptionImpl();
inlineCountOption.setName(option.name);
@@ -268,6 +283,7 @@ public class Parser {
option.name, option.value);
}
systemOption = inlineCountOption;
+
} else {
throw new UriParserSyntaxException("Unknown system query option!",
UriParserSyntaxException.MessageKeys.UNKNOWN_SYSTEM_QUERY_OPTION, option.name);
@@ -278,12 +294,23 @@ public class Parser {
throw new UriParserSyntaxException("Double system query option!", e,
UriParserSyntaxException.MessageKeys.DOUBLE_SYSTEM_QUERY_OPTION, option.name);
}
+
} else if (option.name.startsWith(AT)) {
if (context.contextUriInfo.getAlias(option.name) == null) {
- final FilterExpressionEOFContext filterExpCtx =
- (FilterExpressionEOFContext) parseRule(option.value, ParserEntryRules.FilterExpression);
- final Expression expression = ((FilterOption) uriParseTreeVisitor.visitFilterExpressionEOF(filterExpCtx))
- .getExpression();
+ // TODO: Create a proper alias-value parser that can parse also common expressions.
+ Expression expression = null;
+ if (!option.value.isEmpty() && (option.value.charAt(0) == '[' || option.value.charAt(0) == '{')) {
+ UriTokenizer tokenizer = new UriTokenizer(option.value);
+ if (!(tokenizer.next(TokenKind.jsonArrayOrObject) && tokenizer.next(TokenKind.EOF))) {
+ throw new UriParserSyntaxException("Illegal value for alias '" + option.name + "'.",
+ UriParserSyntaxException.MessageKeys.SYNTAX);
+ }
+ } else {
+ final FilterExpressionEOFContext filterExpCtx =
+ (FilterExpressionEOFContext) parseRule(option.value, ParserEntryRules.FilterExpression);
+ expression = ((FilterOption) uriParseTreeVisitor.visitFilterExpressionEOF(filterExpCtx))
+ .getExpression();
+ }
context.contextUriInfo.addAlias((AliasQueryOption) new AliasQueryOptionImpl()
.setAliasValue(expression)
.setName(option.name)
@@ -292,6 +319,7 @@ public class Parser {
throw new UriParserSyntaxException("Alias already specified! Name: " + option.name,
UriParserSyntaxException.MessageKeys.DUPLICATED_ALIAS, option.name);
}
+
} else {
context.contextUriInfo.addCustomQueryOption((CustomQueryOption)
new CustomQueryOptionImpl()
@@ -354,21 +382,6 @@ public class Parser {
// parse
switch (entryPoint) {
- case All:
- ret = parser.allEOF();
- break;
- case Batch:
- ret = parser.batchEOF();
- break;
- case CrossJoin:
- ret = parser.crossjoinEOF();
- break;
- case Metadata:
- ret = parser.metadataEOF();
- break;
- case PathSegment:
- ret = parser.pathSegmentEOF();
- break;
case FilterExpression:
lexer.mode(Lexer.DEFAULT_MODE);
ret = parser.filterExpressionEOF();
@@ -381,15 +394,9 @@ public class Parser {
lexer.mode(Lexer.DEFAULT_MODE);
ret = parser.expandItemsEOF();
break;
- case Entity:
- ret = parser.entityEOF();
- break;
case Select:
ret = parser.selectEOF();
break;
- case Search:
- ret = parser.searchInline();
- break;
default:
break;
@@ -414,21 +421,6 @@ public class Parser {
// parse
switch (entryPoint) {
- case All:
- ret = parser.allEOF();
- break;
- case Batch:
- ret = parser.batchEOF();
- break;
- case CrossJoin:
- ret = parser.crossjoinEOF();
- break;
- case Metadata:
- ret = parser.metadataEOF();
- break;
- case PathSegment:
- ret = parser.pathSegmentEOF();
- break;
case FilterExpression:
lexer.mode(Lexer.DEFAULT_MODE);
ret = parser.filterExpressionEOF();
@@ -441,15 +433,9 @@ public class Parser {
lexer.mode(Lexer.DEFAULT_MODE);
ret = parser.expandItemsEOF();
break;
- case Entity:
- ret = parser.entityEOF();
- break;
case Select:
ret = parser.selectEOF();
break;
- case Search:
- ret = parser.searchInline();
- break;
default:
break;
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/927ecb93/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ResourcePathParser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ResourcePathParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ResourcePathParser.java
new file mode 100644
index 0000000..9852011
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ResourcePathParser.java
@@ -0,0 +1,692 @@
+/*
+ * 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.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.commons.api.edm.Edm;
+import org.apache.olingo.commons.api.edm.EdmAction;
+import org.apache.olingo.commons.api.edm.EdmActionImport;
+import org.apache.olingo.commons.api.edm.EdmEntityContainer;
+import org.apache.olingo.commons.api.edm.EdmEntitySet;
+import org.apache.olingo.commons.api.edm.EdmEntityType;
+import org.apache.olingo.commons.api.edm.EdmFunction;
+import org.apache.olingo.commons.api.edm.EdmFunctionImport;
+import org.apache.olingo.commons.api.edm.EdmKeyPropertyRef;
+import org.apache.olingo.commons.api.edm.EdmNavigationProperty;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
+import org.apache.olingo.commons.api.edm.EdmProperty;
+import org.apache.olingo.commons.api.edm.EdmSingleton;
+import org.apache.olingo.commons.api.edm.EdmStructuredType;
+import org.apache.olingo.commons.api.edm.EdmType;
+import org.apache.olingo.commons.api.edm.EdmTypeDefinition;
+import org.apache.olingo.commons.api.edm.FullQualifiedName;
+import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
+import org.apache.olingo.server.api.OData;
+import org.apache.olingo.server.api.uri.UriInfoKind;
+import org.apache.olingo.server.api.uri.UriParameter;
+import org.apache.olingo.server.api.uri.UriResource;
+import org.apache.olingo.server.api.uri.UriResourcePartTyped;
+import org.apache.olingo.server.core.uri.UriInfoImpl;
+import org.apache.olingo.server.core.uri.UriParameterImpl;
+import org.apache.olingo.server.core.uri.UriResourceActionImpl;
+import org.apache.olingo.server.core.uri.UriResourceComplexPropertyImpl;
+import org.apache.olingo.server.core.uri.UriResourceCountImpl;
+import org.apache.olingo.server.core.uri.UriResourceEntitySetImpl;
+import org.apache.olingo.server.core.uri.UriResourceFunctionImpl;
+import org.apache.olingo.server.core.uri.UriResourceNavigationPropertyImpl;
+import org.apache.olingo.server.core.uri.UriResourcePrimitivePropertyImpl;
+import org.apache.olingo.server.core.uri.UriResourceRefImpl;
+import org.apache.olingo.server.core.uri.UriResourceSingletonImpl;
+import org.apache.olingo.server.core.uri.UriResourceTypedImpl;
+import org.apache.olingo.server.core.uri.UriResourceValueImpl;
+import org.apache.olingo.server.core.uri.UriResourceWithKeysImpl;
+import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind;
+import org.apache.olingo.server.core.uri.validator.UriValidationException;
+
+public class ResourcePathParser {
+
+ private final Edm edm;
+ private final EdmEntityContainer edmEntityContainer;
+ private final OData odata;
+ private UriTokenizer tokenizer;
+
+ public ResourcePathParser(final Edm edm, final OData odata) {
+ this.edm = edm;
+ edmEntityContainer = edm.getEntityContainer();
+ this.odata = odata;
+ }
+
+ public UriResource parsePathSegment(final String pathSegment, UriResource previous)
+ throws UriParserException, UriValidationException {
+ tokenizer = new UriTokenizer(pathSegment);
+
+ // The order is important.
+ // A qualified name should not be parsed as identifier and let the tokenizer halt at '.'.
+
+ if (previous == null) {
+ if (tokenizer.next(TokenKind.QualifiedName)) {
+ throw new UriParserSemanticException("The initial segment must not be namespace-qualified.",
+ UriParserSemanticException.MessageKeys.NAMESPACE_NOT_ALLOWED_AT_FIRST_ELEMENT,
+ new FullQualifiedName(tokenizer.getText()).getNamespace());
+ } else if (tokenizer.next(TokenKind.ODataIdentifier)) {
+ return leadingResourcePathSegment();
+ }
+
+ } else {
+ if (tokenizer.next(TokenKind.REF)) {
+ return ref(previous);
+ } else if (tokenizer.next(TokenKind.VALUE)) {
+ return value(previous);
+ } else if (tokenizer.next(TokenKind.COUNT)) {
+ return count(previous);
+ } else if (tokenizer.next(TokenKind.QualifiedName)) {
+ return boundOperationOrTypeCast(previous);
+ } else if (tokenizer.next(TokenKind.ODataIdentifier)) {
+ return navigationOrProperty(previous);
+ }
+ }
+
+ throw new UriParserSyntaxException("Unexpected start of resource-path segment.",
+ UriParserSyntaxException.MessageKeys.SYNTAX);
+ }
+
+ public UriInfoImpl parseDollarEntityTypeCast(final String pathSegment) throws UriParserException {
+ UriInfoImpl uriInfo = new UriInfoImpl().setKind(UriInfoKind.entityId);
+ tokenizer = new UriTokenizer(pathSegment);
+ requireNext(TokenKind.QualifiedName);
+ final String name = tokenizer.getText();
+ requireTokenEnd();
+ final EdmEntityType type = edm.getEntityType(new FullQualifiedName(name));
+ if (type == null) {
+ throw new UriParserSemanticException("Type '" + name + "' not found.",
+ UriParserSemanticException.MessageKeys.UNKNOWN_TYPE, name);
+ } else {
+ uriInfo.setEntityTypeCast(type);
+ }
+ return uriInfo;
+ }
+
+ public UriInfoImpl parseCrossjoinSegment(final String pathSegment) throws UriParserException {
+ UriInfoImpl uriInfo = new UriInfoImpl().setKind(UriInfoKind.crossjoin);
+ tokenizer = new UriTokenizer(pathSegment);
+ requireNext(TokenKind.CROSSJOIN);
+ requireNext(TokenKind.OPEN);
+ // At least one entity-set name is mandatory. Try to fetch all.
+ do {
+ requireNext(TokenKind.ODataIdentifier);
+ final String name = tokenizer.getText();
+ final EdmEntitySet edmEntitySet = edmEntityContainer.getEntitySet(name);
+ if (edmEntitySet == null) {
+ throw new UriParserSemanticException("Expected Entity Set Name.",
+ UriParserSemanticException.MessageKeys.UNKNOWN_PART, name);
+ } else {
+ uriInfo.addEntitySetName(name);
+ }
+ } while (tokenizer.next(TokenKind.COMMA));
+ requireNext(TokenKind.CLOSE);
+ requireTokenEnd();
+ return uriInfo;
+ }
+
+ private UriResource ref(final UriResource previous) throws UriParserException {
+ requireTokenEnd();
+ requireTyped(previous, "$ref");
+ if (((UriResourcePartTyped) previous).getType() instanceof EdmEntityType) {
+ return new UriResourceRefImpl();
+ } else {
+ throw new UriParserSemanticException("$ref is only allowed on entity types.",
+ UriParserSemanticException.MessageKeys.ONLY_FOR_ENTITY_TYPES, "$ref");
+ }
+ }
+
+ private UriResource value(final UriResource previous) throws UriParserException {
+ requireTokenEnd();
+ requireTyped(previous, "$value");
+ if (!((UriResourcePartTyped) previous).isCollection()) {
+ return new UriResourceValueImpl();
+ } else {
+ throw new UriParserSemanticException("$value is only allowed on typed path segments.",
+ UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PARTS, "$value");
+ }
+ }
+
+ private UriResource count(final UriResource previous) throws UriParserException {
+ requireTokenEnd();
+ requireTyped(previous, "$count");
+ if (((UriResourcePartTyped) previous).isCollection()) {
+ return new UriResourceCountImpl();
+ } else {
+ throw new UriParserSemanticException("$count is only allowed on collections.",
+ UriParserSemanticException.MessageKeys.ONLY_FOR_COLLECTIONS, "$count");
+ }
+ }
+
+ private UriResource leadingResourcePathSegment() throws UriParserException, UriValidationException {
+ final String oDataIdentifier = tokenizer.getText();
+
+ final EdmEntitySet edmEntitySet = edmEntityContainer.getEntitySet(oDataIdentifier);
+ if (edmEntitySet != null) {
+ final UriResourceEntitySetImpl entitySetResource = new UriResourceEntitySetImpl().setEntitSet(edmEntitySet);
+
+ if (tokenizer.next(TokenKind.OPEN)) {
+ final List<UriParameter> keyPredicates = keyPredicate(entitySetResource.getEntityType(), null);
+ entitySetResource.setKeyPredicates(keyPredicates);
+ }
+
+ requireTokenEnd();
+ return entitySetResource;
+ }
+
+ final EdmSingleton edmSingleton = edmEntityContainer.getSingleton(oDataIdentifier);
+ if (edmSingleton != null) {
+ requireTokenEnd();
+ return new UriResourceSingletonImpl().setSingleton(edmSingleton);
+ }
+
+ final EdmActionImport edmActionImport = edmEntityContainer.getActionImport(oDataIdentifier);
+ if (edmActionImport != null) {
+ requireTokenEnd();
+ return new UriResourceActionImpl().setActionImport(edmActionImport);
+ }
+
+ final EdmFunctionImport edmFunctionImport = edmEntityContainer.getFunctionImport(oDataIdentifier);
+ if (edmFunctionImport != null) {
+ return functionCall(edmFunctionImport, null, null, false);
+ }
+
+ if (tokenizer.next(TokenKind.OPEN) || tokenizer.next(TokenKind.EOF)) {
+ throw new UriParserSemanticException("Unexpected start of resource-path segment.",
+ UriParserSemanticException.MessageKeys.RESOURCE_NOT_FOUND, oDataIdentifier);
+ } else {
+ throw new UriParserSyntaxException("Unexpected start of resource-path segment.",
+ UriParserSyntaxException.MessageKeys.SYNTAX);
+ }
+ }
+
+ private UriResource navigationOrProperty(final UriResource previous)
+ throws UriParserException, UriValidationException {
+ final String name = tokenizer.getText();
+
+ UriResourcePartTyped previousTyped = null;
+ EdmStructuredType structType = null;
+ requireTyped(previous, name);
+ if (((UriResourcePartTyped) previous).getType() instanceof EdmStructuredType) {
+ previousTyped = (UriResourcePartTyped) previous;
+ final EdmType previousTypeFilter = getPreviousTypeFilter(previousTyped);
+ structType = (EdmStructuredType) (previousTypeFilter == null ? previousTyped.getType() : previousTypeFilter);
+ } else {
+ throw new UriParserSemanticException(
+ "Cannot parse '" + name + "'; previous path segment is not a structural type.",
+ UriParserSemanticException.MessageKeys.RESOURCE_PART_MUST_BE_PRECEDED_BY_STRUCTURAL_TYPE, name);
+ }
+
+ if (previousTyped.isCollection()) {
+ throw new UriParserSemanticException("Property '" + name + "' is not allowed after collection.",
+ UriParserSemanticException.MessageKeys.PROPERTY_AFTER_COLLECTION, name);
+ }
+
+ final EdmProperty property = structType.getStructuralProperty(name);
+ if (property != null) {
+ return property.isPrimitive()
+ || property.getType().getKind() == EdmTypeKind.ENUM
+ || property.getType().getKind() == EdmTypeKind.DEFINITION ?
+ new UriResourcePrimitivePropertyImpl().setProperty(property) :
+ new UriResourceComplexPropertyImpl().setProperty(property);
+ }
+ final EdmNavigationProperty navigationProperty = structType.getNavigationProperty(name);
+ if (navigationProperty == null) {
+ throw new UriParserSemanticException("Property '" + name + "' not found in type '"
+ + structType.getFullQualifiedName().getFullQualifiedNameAsString() + "'",
+ UriParserSemanticException.MessageKeys.PROPERTY_NOT_IN_TYPE,
+ structType.getFullQualifiedName().getFullQualifiedNameAsString(), name);
+ }
+ List<UriParameter> keyPredicate = null;
+ if (tokenizer.next(TokenKind.OPEN)) {
+ if (navigationProperty.isCollection()) {
+ keyPredicate = keyPredicate(navigationProperty.getType(), navigationProperty.getPartner());
+ } else {
+ throw new UriParserSemanticException("A key is not allowed on non-collection navigation properties.",
+ UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED);
+ }
+ }
+ requireTokenEnd();
+ return new UriResourceNavigationPropertyImpl()
+ .setNavigationProperty(navigationProperty)
+ .setKeyPredicates(keyPredicate);
+ }
+
+ private UriResource boundOperationOrTypeCast(UriResource previous)
+ throws UriParserException, UriValidationException {
+ final FullQualifiedName name = new FullQualifiedName(tokenizer.getText());
+ requireTyped(previous, name.getFullQualifiedNameAsString());
+ final UriResourcePartTyped previousTyped = (UriResourcePartTyped) previous;
+ final EdmType previousTypeFilter = getPreviousTypeFilter(previousTyped);
+ final EdmType previousType = previousTypeFilter == null ? previousTyped.getType() : previousTypeFilter;
+ final EdmAction boundAction = edm.getBoundAction(name,
+ previousType.getFullQualifiedName(),
+ previousTyped.isCollection());
+ if (boundAction != null) {
+ requireTokenEnd();
+ return new UriResourceActionImpl().setAction(boundAction);
+ }
+ EdmStructuredType type = edm.getEntityType(name);
+ if (type == null) {
+ type = edm.getComplexType(name);
+ }
+ if (type != null) {
+ return typeCast(name, type, previousTyped);
+ }
+ if (tokenizer.next(TokenKind.EOF)) {
+ throw new UriParserSemanticException("Type '" + name.getFullQualifiedNameAsString() + "' not found.",
+ UriParserSemanticException.MessageKeys.UNKNOWN_TYPE, name.getFullQualifiedNameAsString());
+ }
+ return functionCall(null, name,
+ previousType.getFullQualifiedName(),
+ previousTyped.isCollection());
+ }
+
+ private void requireTyped(final UriResource previous, final String forWhat) throws UriParserException {
+ if (previous == null || !(previous instanceof UriResourcePartTyped)) {
+ throw new UriParserSemanticException("Path segment before '" + forWhat + "' is not typed.",
+ UriParserSemanticException.MessageKeys.PREVIOUS_PART_NOT_TYPED, forWhat);
+ }
+ }
+
+ private List<UriParameter> keyPredicate(final EdmEntityType edmEntityType, final EdmNavigationProperty partner)
+ throws UriParserException, UriValidationException {
+ final List<EdmKeyPropertyRef> keyPropertyRefs = edmEntityType.getKeyPropertyRefs();
+ if (tokenizer.next(TokenKind.CLOSE)) {
+ throw new UriParserSemanticException(
+ "Expected " + keyPropertyRefs.size() + " key predicates but none.",
+ UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
+ Integer.toString(keyPropertyRefs.size()), "0");
+ }
+ List<UriParameter> keys = new ArrayList<UriParameter>();
+ Map<String, String> referencedNames = new HashMap<String, String>();
+
+ if (partner != null) {
+ // Prepare list of potentially missing keys to be filled from referential constraints.
+ for (final String name : edmEntityType.getKeyPredicateNames()) {
+ final String referencedName = partner.getReferencingPropertyName(name);
+ if (referencedName != null) {
+ referencedNames.put(name, referencedName);
+ }
+ }
+ }
+
+ if (tokenizer.next(TokenKind.ODataIdentifier)) {
+ keys.addAll(compoundKey(edmEntityType));
+ } else if (keyPropertyRefs.size() - referencedNames.size() == 1) {
+ for (final EdmKeyPropertyRef candidate : keyPropertyRefs) {
+ if (referencedNames.get(candidate.getName()) == null) {
+ keys.add(simpleKey(candidate));
+ break;
+ }
+ }
+ } else {
+ throw new UriParserSemanticException(
+ "Expected " + (keyPropertyRefs.size() -referencedNames.size()) + " key predicates but found one.",
+ UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
+ Integer.toString(keyPropertyRefs.size() - referencedNames.size()), "1");
+ }
+
+ if (keys.size() < keyPropertyRefs.size() && partner != null) {
+ // Fill missing keys from referential constraints.
+ for (final String name : edmEntityType.getKeyPredicateNames()) {
+ boolean found = false;
+ for (final UriParameter key : keys) {
+ if (name.equals(key.getName())) {
+ found = true;
+ break;
+ }
+ }
+ if (!found && referencedNames.get(name) != null) {
+ keys.add(0, new UriParameterImpl().setName(name).setReferencedProperty(referencedNames.get(name)));
+ }
+ }
+ }
+
+ // Check that all key predicates are filled from the URI.
+ if (keys.size() < keyPropertyRefs.size()) {
+ throw new UriParserSemanticException(
+ "Expected " + keyPropertyRefs.size() + " key predicates but found " + keys.size() + ".",
+ UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
+ Integer.toString(keyPropertyRefs.size()), Integer.toString(keys.size()));
+ } else {
+ return keys;
+ }
+ }
+
+ private UriParameter simpleKey(final EdmKeyPropertyRef edmKeyPropertyRef)
+ throws UriParserException, UriValidationException {
+ final EdmProperty edmProperty = edmKeyPropertyRef == null ? null : edmKeyPropertyRef.getProperty();
+ if (nextPrimitiveTypeValue(
+ edmProperty == null ? null : (EdmPrimitiveType) edmProperty.getType(),
+ edmProperty == null ? false : edmProperty.isNullable())) {
+ final String literalValue = tokenizer.getText();
+ requireNext(TokenKind.CLOSE);
+ return createUriParameter(edmProperty, edmKeyPropertyRef.getName(), literalValue);
+ } else {
+ throw new UriParserSemanticException("The key value is not valid.",
+ UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, edmKeyPropertyRef.getName());
+ }
+ }
+
+ private List<UriParameter> compoundKey(final EdmEntityType edmEntityType)
+ throws UriParserException, UriValidationException {
+
+ List<UriParameter> parameters = new ArrayList<UriParameter>();
+ List<String> parameterNames = new ArrayList<String>();
+
+ // To validate that each key predicate is exactly specified once, we use a list to pick from.
+ List<String> remainingKeyNames = new ArrayList<String>(edmEntityType.getKeyPredicateNames());
+
+ // At least one key predicate is mandatory. Try to fetch all.
+ boolean hasComma = false;
+ do {
+ final String keyPredicateName = tokenizer.getText();
+ if (parameterNames.contains(keyPredicateName)) {
+ throw new UriValidationException("Duplicated key property " + keyPredicateName,
+ UriValidationException.MessageKeys.DOUBLE_KEY_PROPERTY, keyPredicateName);
+ }
+ if (remainingKeyNames.isEmpty()) {
+ throw new UriParserSemanticException("Too many key properties.",
+ UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
+ Integer.toString(parameters.size()), Integer.toString(parameters.size() + 1));
+ }
+ if (!remainingKeyNames.remove(keyPredicateName)) {
+ throw new UriValidationException("Unknown key property " + keyPredicateName,
+ UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, keyPredicateName);
+ }
+ parameters.add(keyValuePair(keyPredicateName, edmEntityType));
+ parameterNames.add(keyPredicateName);
+ hasComma = tokenizer.next(TokenKind.COMMA);
+ if (hasComma) {
+ requireNext(TokenKind.ODataIdentifier);
+ }
+ } while (hasComma);
+ requireNext(TokenKind.CLOSE);
+
+ return parameters;
+ }
+
+ private UriParameter keyValuePair(final String keyPredicateName, final EdmEntityType edmEntityType)
+ throws UriParserException, UriValidationException {
+ final EdmKeyPropertyRef keyPropertyRef = edmEntityType.getKeyPropertyRef(keyPredicateName);
+ final EdmProperty edmProperty = keyPropertyRef == null ? null : keyPropertyRef.getProperty();
+ if (edmProperty == null) {
+ throw new UriValidationException(keyPredicateName + " is not a valid key property name.",
+ UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, keyPredicateName);
+ }
+ requireNext(TokenKind.EQ);
+ if (tokenizer.next(TokenKind.COMMA) || tokenizer.next(TokenKind.CLOSE) || tokenizer.next(TokenKind.EOF)) {
+ throw new UriParserSyntaxException("Key value expected.", UriParserSyntaxException.MessageKeys.SYNTAX);
+ }
+ if (nextPrimitiveTypeValue((EdmPrimitiveType) edmProperty.getType(), edmProperty.isNullable())) {
+ return createUriParameter(edmProperty, keyPredicateName, tokenizer.getText());
+ } else {
+ throw new UriParserSemanticException(keyPredicateName + " has not a valid key value.",
+ UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, keyPredicateName);
+ }
+ }
+
+ private UriParameter createUriParameter(final EdmProperty edmProperty, final String parameterName,
+ final String literalValue) throws UriParserException, UriValidationException {
+ if (literalValue.startsWith("@")) {
+ return new UriParameterImpl()
+ .setName(parameterName)
+ .setAlias(literalValue);
+ }
+
+ final EdmPrimitiveType primitiveType = (EdmPrimitiveType) edmProperty.getType();
+ try {
+ if (!(primitiveType.validate(primitiveType.fromUriLiteral(literalValue), edmProperty.isNullable(),
+ edmProperty.getMaxLength(), edmProperty.getPrecision(), edmProperty.getScale(), edmProperty.isUnicode()))) {
+ throw new UriValidationException("Invalid key property",
+ UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, parameterName);
+ }
+ } catch (final EdmPrimitiveTypeException e) {
+ throw new UriValidationException("Invalid key property",
+ UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, parameterName);
+ }
+
+ return new UriParameterImpl()
+ .setName(parameterName)
+ .setText("null".equals(literalValue) ? null : literalValue);
+ }
+
+ private UriResource typeCast(final FullQualifiedName name, final EdmStructuredType type,
+ final UriResourcePartTyped previousTyped) throws UriParserException, UriValidationException {
+ if (type.compatibleTo(previousTyped.getType())) {
+ EdmType previousTypeFilter = null;
+ if (previousTyped instanceof UriResourceWithKeysImpl) {
+ if (previousTyped.isCollection()) {
+ previousTypeFilter = ((UriResourceWithKeysImpl) previousTyped).getTypeFilterOnCollection();
+ if (previousTypeFilter != null) {
+ throw new UriParserSemanticException("Type filters are not chainable.",
+ UriParserSemanticException.MessageKeys.TYPE_FILTER_NOT_CHAINABLE,
+ previousTypeFilter.getName(), type.getName());
+ }
+ ((UriResourceWithKeysImpl) previousTyped).setCollectionTypeFilter(type);
+ } else {
+ previousTypeFilter = ((UriResourceWithKeysImpl) previousTyped).getTypeFilterOnEntry();
+ if (previousTypeFilter != null) {
+ throw new UriParserSemanticException("Type filters are not chainable.",
+ UriParserSemanticException.MessageKeys.TYPE_FILTER_NOT_CHAINABLE,
+ previousTypeFilter.getName(), type.getName());
+ }
+ ((UriResourceWithKeysImpl) previousTyped).setEntryTypeFilter(type);
+ }
+ if (tokenizer.next(TokenKind.OPEN)) {
+ ((UriResourceWithKeysImpl) previousTyped).setKeyPredicates(
+ keyPredicate((EdmEntityType) type, null));
+ }
+ } else {
+ previousTypeFilter = ((UriResourceTypedImpl) previousTyped).getTypeFilter();
+ if (previousTypeFilter != null) {
+ throw new UriParserSemanticException("Type filters are not chainable.",
+ UriParserSemanticException.MessageKeys.TYPE_FILTER_NOT_CHAINABLE,
+ previousTypeFilter.getName(), type.getName());
+ }
+ ((UriResourceTypedImpl) previousTyped).setTypeFilter(type);
+ }
+ requireTokenEnd();
+ return null;
+ } else {
+ throw new UriParserSemanticException(
+ "Type filter not compatible to previous path segment: " + name.getFullQualifiedNameAsString(),
+ UriParserSemanticException.MessageKeys.INCOMPATIBLE_TYPE_FILTER, name.getFullQualifiedNameAsString());
+ }
+ }
+
+ private EdmType getPreviousTypeFilter(final UriResourcePartTyped previousTyped) {
+ if (previousTyped instanceof UriResourceWithKeysImpl) {
+ return ((UriResourceWithKeysImpl) previousTyped).getTypeFilterOnEntry() == null ?
+ ((UriResourceWithKeysImpl) previousTyped).getTypeFilterOnCollection() :
+ ((UriResourceWithKeysImpl) previousTyped).getTypeFilterOnEntry();
+ } else {
+ return ((UriResourceTypedImpl) previousTyped).getTypeFilter();
+ }
+ }
+
+ private UriResource functionCall(final EdmFunctionImport edmFunctionImport,
+ final FullQualifiedName boundFunctionName, final FullQualifiedName bindingParameterTypeName,
+ final boolean isBindingParameterCollection) throws UriParserException, UriValidationException {
+ final List<UriParameter> parameters = functionParameters();
+ List<String> names = new ArrayList<String>();
+ for (final UriParameter parameter : parameters) {
+ names.add(parameter.getName());
+ }
+ EdmFunction function = null;
+ if (edmFunctionImport != null) {
+ function = edmFunctionImport.getUnboundFunction(names);
+ if (function == null) {
+ throw new UriParserSemanticException(
+ "Function of function import '" + edmFunctionImport.getName() + "' "
+ + "with parameters " + names.toString() + " not found.",
+ UriParserSemanticException.MessageKeys.FUNCTION_NOT_FOUND, edmFunctionImport.getName(), names.toString());
+ }
+ } else {
+ function = edm.getBoundFunction(boundFunctionName,
+ bindingParameterTypeName, isBindingParameterCollection, names);
+ if (function == null) {
+ throw new UriParserSemanticException(
+ "Function " + boundFunctionName + " not found.",
+ UriParserSemanticException.MessageKeys.UNKNOWN_PART, boundFunctionName.getFullQualifiedNameAsString());
+ }
+ }
+ UriResourceFunctionImpl resource = new UriResourceFunctionImpl()
+ .setFunctionImport(edmFunctionImport, null)
+ .setFunction(function)
+ .setParameters(parameters);
+ if (tokenizer.next(TokenKind.OPEN)) {
+ if (function.getReturnType() != null
+ && function.getReturnType().getType().getKind() == EdmTypeKind.ENTITY
+ && function.getReturnType().isCollection()) {
+ resource.setKeyPredicates(
+ keyPredicate((EdmEntityType) function.getReturnType().getType(), null));
+ } else {
+ throw new UriParserSemanticException("A key is not allowed.",
+ UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED);
+ }
+ }
+ requireTokenEnd();
+ return resource;
+ }
+
+ private List<UriParameter> functionParameters() throws UriParserException {
+ List<UriParameter> parameters = new ArrayList<UriParameter>();
+ requireNext(TokenKind.OPEN);
+ if (tokenizer.next(TokenKind.CLOSE)) {
+ return parameters;
+ }
+ do {
+ requireNext(TokenKind.ODataIdentifier);
+ final String name = tokenizer.getText();
+ if (parameters.contains(name)) {
+ throw new UriParserSemanticException("Duplicated function parameter " + name,
+ UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, name);
+ }
+ requireNext(TokenKind.EQ);
+ if (tokenizer.next(TokenKind.COMMA) || tokenizer.next(TokenKind.CLOSE) || tokenizer.next(TokenKind.EOF)) {
+ throw new UriParserSyntaxException("Parameter value expected.", UriParserSyntaxException.MessageKeys.SYNTAX);
+ }
+ if (nextPrimitiveValue()) {
+ final String literalValue = tokenizer.getText();
+ UriParameterImpl parameter = new UriParameterImpl().setName(name);
+ parameters.add(literalValue.startsWith("@") ?
+ parameter.setAlias(literalValue) :
+ parameter.setText("null".equals(literalValue) ? null : literalValue));
+ } else {
+ throw new UriParserSemanticException("Wrong parameter value.",
+ UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, "");
+ }
+ } while (tokenizer.next(TokenKind.COMMA));
+ requireNext(TokenKind.CLOSE);
+ return parameters;
+ }
+
+ private void requireNext(final TokenKind kind) throws UriParserException {
+ if (!tokenizer.next(kind)) {
+ throw new UriParserSyntaxException("Expected token '" + kind.toString() + "' not found.",
+ UriParserSyntaxException.MessageKeys.SYNTAX);
+ }
+ }
+
+ private void requireTokenEnd() throws UriParserException {
+ requireNext(TokenKind.EOF);
+ }
+
+ private boolean nextPrimitiveTypeValue(final EdmPrimitiveType primitiveType, final boolean nullable) {
+ final EdmPrimitiveType type = primitiveType instanceof EdmTypeDefinition ?
+ ((EdmTypeDefinition) primitiveType).getUnderlyingType() :
+ primitiveType;
+ if (tokenizer.next(TokenKind.ParameterAliasName)) {
+ return true;
+ } else if (nullable && tokenizer.next(TokenKind.NULL)) {
+ return true;
+
+ } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Boolean).equals(type)) {
+ return tokenizer.next(TokenKind.PrimitiveBooleanValue);
+ } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.String).equals(type)) {
+ return tokenizer.next(TokenKind.PrimitiveStringValue);
+ } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.SByte).equals(type)
+ || odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Byte).equals(type)
+ || odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int16).equals(type)
+ || odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int32).equals(type)
+ || odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int64).equals(type)) {
+ return tokenizer.next(TokenKind.PrimitiveIntegerValue);
+ } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Guid).equals(type)) {
+ return tokenizer.next(TokenKind.PrimitiveGuidValue);
+ } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Date).equals(type)) {
+ return tokenizer.next(TokenKind.PrimitiveDateValue);
+ } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.DateTimeOffset).equals(type)) {
+ return tokenizer.next(TokenKind.PrimitiveDateTimeOffsetValue);
+ } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.TimeOfDay).equals(type)) {
+ return tokenizer.next(TokenKind.PrimitiveTimeOfDayValue);
+ } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Decimal).equals(type)) {
+ // The order is important.
+ // A decimal value should not be parsed as integer and let the tokenizer stop at the decimal point.
+ return tokenizer.next(TokenKind.PrimitiveDecimalValue)
+ || tokenizer.next(TokenKind.PrimitiveIntegerValue);
+ } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Double).equals(type)) {
+ // The order is important.
+ // A floating-point value should not be parsed as decimal and let the tokenizer stop at 'E'.
+ // A decimal value should not be parsed as integer and let the tokenizer stop at the decimal point.
+ return tokenizer.next(TokenKind.PrimitiveDoubleValue)
+ || tokenizer.next(TokenKind.PrimitiveDecimalValue)
+ || tokenizer.next(TokenKind.PrimitiveIntegerValue);
+ } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Duration).equals(type)) {
+ return tokenizer.next(TokenKind.PrimitiveDurationValue);
+ } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Binary).equals(type)) {
+ return tokenizer.next(TokenKind.PrimitiveBinaryValue);
+ } else if (type.getKind() == EdmTypeKind.ENUM) {
+ return tokenizer.next(TokenKind.PrimitiveEnumValue);
+ } else {
+ return false;
+ }
+ }
+
+ private boolean nextPrimitiveValue() {
+ return tokenizer.next(TokenKind.ParameterAliasName)
+ || tokenizer.next(TokenKind.NULL)
+ || tokenizer.next(TokenKind.PrimitiveBooleanValue)
+ || tokenizer.next(TokenKind.PrimitiveStringValue)
+
+ // The order of the next seven expressions is important in order to avoid
+ // finding partly parsed tokens (counter-intuitive as it may be, even a GUID may start with digits ...).
+ || tokenizer.next(TokenKind.PrimitiveDoubleValue)
+ || tokenizer.next(TokenKind.PrimitiveDecimalValue)
+ || tokenizer.next(TokenKind.PrimitiveGuidValue)
+ || tokenizer.next(TokenKind.PrimitiveDateTimeOffsetValue)
+ || tokenizer.next(TokenKind.PrimitiveDateValue)
+ || tokenizer.next(TokenKind.PrimitiveTimeOfDayValue)
+ || tokenizer.next(TokenKind.PrimitiveIntegerValue)
+
+ || tokenizer.next(TokenKind.PrimitiveDurationValue)
+ || tokenizer.next(TokenKind.PrimitiveBinaryValue)
+ || tokenizer.next(TokenKind.PrimitiveEnumValue);
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/927ecb93/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
index 1e33a19..8740d66 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
@@ -250,7 +250,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
public UriParseTreeVisitor(final Edm edm, final UriContext context) {
this.edm = edm;
this.context = context;
- edmEntityContainer = edm.getEntityContainer(null);
+ edmEntityContainer = edm.getEntityContainer();
}
@Override
[29/30] olingo-odata4 git commit: [OLINGO-834] Adjust LICENSE file
Posted by ch...@apache.org.
[OLINGO-834] Adjust LICENSE file
I removed the Antlr and treelayout bsd license.
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/53d2e8bb
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/53d2e8bb
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/53d2e8bb
Branch: refs/heads/master
Commit: 53d2e8bb8c81433a96a235b8a0f8a485278cd0b6
Parents: 40be3e4
Author: Christian Amend <ch...@sap.com>
Authored: Fri Jan 8 10:03:04 2016 +0100
Committer: Christian Amend <ch...@sap.com>
Committed: Fri Jan 8 10:03:04 2016 +0100
----------------------------------------------------------------------
dist/server-lib/src/main/resources/LICENSE | 67 --------------------
dist/server-lib/src/main/resources/NOTICE | 31 +--------
fit/pom.xml | 1 -
.../olingo/server/core/uri/parser/RawUri.java | 46 --------------
.../queryoption/expression/ExpressionImpl.java | 25 --------
5 files changed, 1 insertion(+), 169 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/53d2e8bb/dist/server-lib/src/main/resources/LICENSE
----------------------------------------------------------------------
diff --git a/dist/server-lib/src/main/resources/LICENSE b/dist/server-lib/src/main/resources/LICENSE
index f858fe4..1685307 100644
--- a/dist/server-lib/src/main/resources/LICENSE
+++ b/dist/server-lib/src/main/resources/LICENSE
@@ -205,73 +205,6 @@ See the License for the specific language governing permissions and
limitations under the License.
-From: 'abego Software GmbH, Germany' (http://abego-software.de) - abego
-TreeLayout Core (http://code.google.com/p/treelayout/)
-org.abego.treelayout:org.abego.treelayout.core:jar:1.0.1 License: BSD 3-Clause
-"New" or "Revised" License (BSD-3-Clause)
-(http://treelayout.googlecode.com/files/LICENSE.TXT)
-
-[The "BSD license"]
-Copyright (c) 2011, abego Software GmbH, Germany (http://www.abego.org)
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-1. Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-3. Neither the name of the abego Software GmbH nor the names of its
- contributors may be used to endorse or promote products derived from this
- software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-
-
-
-
-From: 'ANTLR' (http://www.antlr.org) - ANTLR 4 Runtime
-(http://www.antlr.org/antlr4-runtime) org.antlr:antlr4-runtime:jar:4.1 License:
-The BSD License (http://www.antlr.org/license.html)
-
-[The BSD License]
-Copyright (c) 2012 Terence Parr and Sam Harwell
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer. Redistributions in binary
- form must reproduce the above copyright notice, this list of conditions and
- the following disclaimer in the documentation and/or other materials
- provided with the distribution. Neither the name of the author nor the
- names of its contributors may be used to endorse or promote products
- derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
From: 'fasterxml.com' (http://fasterxml.com) - Stax2 API
(http://wiki.fasterxml.com/WoodstoxStax2)
org.codehaus.woodstox:stax2-api:bundle:3.1.4 License: The BSD License
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/53d2e8bb/dist/server-lib/src/main/resources/NOTICE
----------------------------------------------------------------------
diff --git a/dist/server-lib/src/main/resources/NOTICE b/dist/server-lib/src/main/resources/NOTICE
index 5a87ef7..bb34cf8 100644
--- a/dist/server-lib/src/main/resources/NOTICE
+++ b/dist/server-lib/src/main/resources/NOTICE
@@ -18,33 +18,4 @@ FasterXML.com (http://fasterxml.com).
## Credits
A list of contributors may be found from CREDITS file, which is included
in some artifacts (usually source distributions); but is always available
-from the source code management (SCM) system project uses.
-
-This distribution includes TreeLayout Core (http://code.google.com/p/treelayout/)
-Copyright (c) 2011, abego Software GmbH, Germany (http://www.abego.org)
-All rights reserved.
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-1. Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-3. Neither the name of the abego Software GmbH nor the names of its
- contributors may be used to endorse or promote products derived from this
- software without specific prior written permission.
-(http://treelayout.googlecode.com/files/LICENSE.TXT)
-
-This distribution includes ANTLR 4 Runtime (http://www.antlr.org/antlr4-runtime)
-Copyright (c) 2012 Terence Parr and Sam Harwell
-All rights reserved.
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-Redistributions of source code must retain the above copyright notice,
-this list of conditions and the following disclaimer.
-Redistributions in binary form must reproduce the above copyright notice,
-this list of conditions and the following disclaimer in the documentation
-and/or other materials provided with the distribution.
-Neither the name of the author nor the names of its contributors may be used to
-endorse or promote products derived from this software without specific prior written permission.
-(http://www.antlr.org/license.html)
+from the source code management (SCM) system project uses.
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/53d2e8bb/fit/pom.xml
----------------------------------------------------------------------
diff --git a/fit/pom.xml b/fit/pom.xml
index 34eff39..08dd7fc 100644
--- a/fit/pom.xml
+++ b/fit/pom.xml
@@ -239,7 +239,6 @@
<exclude>org/apache/olingo/**/tecsvc/**/*.class</exclude>
<exclude>org/apache/olingo/**/fit/**/*.class</exclude>
<exclude>org/apache/olingo/**/testutil/**/*.class</exclude>
- <exclude>org/apache/olingo/**/antlr/**/*.class</exclude>
</excludes>
</instrumentation>
<check/>
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/53d2e8bb/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/RawUri.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/RawUri.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/RawUri.java
deleted file mode 100644
index 231317f..0000000
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/RawUri.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.List;
-
-public class RawUri {
- public String uri;
- public String scheme;
- public String authority;
- public String path;
- public String queryOptionString;
- public String fragment;
- public List<QueryOption> queryOptionList;
- public List<QueryOption> queryOptionListDecoded;
-
- public List<String> pathSegmentList;
- public List<String> pathSegmentListDecoded;
-
- public static class QueryOption {
- public String name;
- public String value;
-
- QueryOption(final String name, final String value) {
- this.name = name;
- this.value = value;
- }
-
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/53d2e8bb/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/ExpressionImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/ExpressionImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/ExpressionImpl.java
deleted file mode 100644
index e64a363..0000000
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/ExpressionImpl.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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.queryoption.expression;
-
-import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
-
-public abstract class ExpressionImpl implements Expression {
- // No additional methods needed for now.
-}
[26/30] olingo-odata4 git commit: Merge branch 'master' into
OLINGO-834_Filter_Parser
Posted by ch...@apache.org.
Merge branch 'master' into OLINGO-834_Filter_Parser
Conflicts:
lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceComplexPropertyImpl.java
lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceCountImpl.java
lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceEntitySetImpl.java
lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceItImpl.java
lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceLambdaAllImpl.java
lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceLambdaAnyImpl.java
lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceLambdaVarImpl.java
lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceNavigationPropertyImpl.java
lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourcePrimitivePropertyImpl.java
lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceRefImpl.java
lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceRootImpl.java
lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceSingletonImpl.java
lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceStartingTypeFilterImpl.java
lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceWithKeysImpl.java
lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/CheckFullContextListener.java
lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/RawUri.java
lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriContext.java
lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriDecoder.java
lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParserSemanticException.java
lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/ExpressionImpl.java
lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java
lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/search/SearchParserAndTokenizerTest.java
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/010642c5
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/010642c5
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/010642c5
Branch: refs/heads/master
Commit: 010642c506d593c83cfb136cd9f5ddb815bf8ba7
Parents: 8925274 0d6f482
Author: Christian Amend <ch...@sap.com>
Authored: Thu Jan 7 14:27:27 2016 +0100
Committer: Christian Amend <ch...@sap.com>
Committed: Thu Jan 7 14:27:27 2016 +0100
----------------------------------------------------------------------
dist/android-lib/pom.xml | 2 +-
dist/client-lib/pom.xml | 2 +-
dist/javadoc/pom.xml | 2 +-
dist/pom.xml | 2 +-
dist/server-lib/pom.xml | 2 +-
ext/client-android/pom.xml | 2 +-
ext/client-proxy/pom.xml | 2 +-
ext/karaf/karaf-features/pom.xml | 2 +-
ext/karaf/karaf-fit/pom.xml | 2 +-
ext/karaf/pom.xml | 2 +-
ext/pojogen-maven-plugin/pom.xml | 2 +-
ext/pom.xml | 2 +-
fit/pom.xml | 2 +-
lib/client-api/pom.xml | 2 +-
lib/client-core/pom.xml | 2 +-
.../olingo/client/core/uri/URIBuilderImpl.java | 4 +-
.../olingo/client/core/uri/URIBuilderTest.java | 15 +-
lib/commons-api/pom.xml | 2 +-
lib/commons-core/pom.xml | 2 +-
lib/pom.xml | 2 +-
lib/server-api/pom.xml | 2 +-
.../apache/olingo/server/api/HttpHeaders.java | 4 +-
.../org/apache/olingo/server/api/OData.java | 6 +-
.../server/api/ODataApplicationException.java | 4 +-
.../olingo/server/api/ODataHttpHandler.java | 4 +-
.../server/api/ODataLibraryException.java | 4 +-
.../apache/olingo/server/api/ODataRequest.java | 6 +-
.../apache/olingo/server/api/ODataResponse.java | 5 +-
.../olingo/server/api/ODataServerError.java | 4 +-
.../olingo/server/api/ServiceMetadata.java | 4 +-
.../olingo/server/api/batch/BatchFacade.java | 106 +++++-----
.../olingo/server/api/batch/package-info.java | 4 +-
.../server/api/debug/DebugInformation.java | 16 +-
.../server/api/debug/DebugResponseHelper.java | 4 +-
.../olingo/server/api/debug/DebugSupport.java | 9 +-
.../server/api/debug/DefaultDebugSupport.java | 8 +-
.../server/api/debug/RuntimeMeasurement.java | 12 +-
.../olingo/server/api/debug/package-info.java | 4 +-
.../api/deserializer/DeserializerException.java | 4 +-
.../api/deserializer/DeserializerResult.java | 4 +-
.../deserializer/FixedFormatDeserializer.java | 12 +-
.../api/deserializer/ODataDeserializer.java | 10 +-
.../batch/BatchDeserializerException.java | 14 +-
.../api/deserializer/batch/BatchOptions.java | 8 +-
.../deserializer/batch/BatchRequestPart.java | 4 +-
.../deserializer/batch/ODataResponsePart.java | 8 +-
.../api/deserializer/batch/package-info.java | 4 +-
.../server/api/deserializer/package-info.java | 4 +-
.../server/api/etag/CustomETagSupport.java | 4 +-
.../olingo/server/api/etag/ETagHelper.java | 22 +-
.../server/api/etag/PreconditionException.java | 4 +-
.../api/etag/ServiceMetadataETagSupport.java | 6 +-
.../olingo/server/api/etag/package-info.java | 4 +-
.../apache/olingo/server/api/package-info.java | 4 +-
.../olingo/server/api/prefer/Preferences.java | 13 +-
.../server/api/prefer/PreferencesApplied.java | 16 +-
.../olingo/server/api/prefer/package-info.java | 4 +-
.../ActionComplexCollectionProcessor.java | 4 +-
.../api/processor/ActionComplexProcessor.java | 4 +-
.../ActionEntityCollectionProcessor.java | 4 +-
.../api/processor/ActionEntityProcessor.java | 4 +-
.../ActionPrimitiveCollectionProcessor.java | 4 +-
.../api/processor/ActionPrimitiveProcessor.java | 4 +-
.../api/processor/ActionVoidProcessor.java | 4 +-
.../server/api/processor/BatchProcessor.java | 4 +-
.../processor/ComplexCollectionProcessor.java | 4 +-
.../server/api/processor/ComplexProcessor.java | 4 +-
.../CountComplexCollectionProcessor.java | 4 +-
.../CountEntityCollectionProcessor.java | 4 +-
.../CountPrimitiveCollectionProcessor.java | 4 +-
.../server/api/processor/DefaultProcessor.java | 4 +-
.../server/api/processor/DeltaProcessor.java | 30 +--
.../processor/EntityCollectionProcessor.java | 4 +-
.../server/api/processor/EntityProcessor.java | 6 +-
.../server/api/processor/ErrorProcessor.java | 6 +-
.../api/processor/MediaEntityProcessor.java | 4 +-
.../server/api/processor/MetadataProcessor.java | 4 +-
.../processor/PrimitiveCollectionProcessor.java | 4 +-
.../api/processor/PrimitiveProcessor.java | 6 +-
.../api/processor/PrimitiveValueProcessor.java | 6 +-
.../olingo/server/api/processor/Processor.java | 4 +-
.../processor/ReferenceCollectionProcessor.java | 4 +-
.../api/processor/ReferenceProcessor.java | 4 +-
.../api/processor/ServiceDocumentProcessor.java | 4 +-
.../server/api/processor/package-info.java | 5 +-
.../serializer/BatchSerializerException.java | 7 +-
.../serializer/ComplexSerializerOptions.java | 10 +-
.../serializer/CustomContentTypeSupport.java | 4 +-
.../EntityCollectionSerializerOptions.java | 8 +-
.../api/serializer/EntitySerializerOptions.java | 8 +-
.../api/serializer/FixedFormatSerializer.java | 6 +-
.../server/api/serializer/ODataSerializer.java | 52 ++---
.../serializer/PrimitiveSerializerOptions.java | 10 +-
.../PrimitiveValueSerializerOptions.java | 4 +-
.../ReferenceCollectionSerializerOptions.java | 12 +-
.../serializer/ReferenceSerializerOptions.java | 4 +-
.../api/serializer/RepresentationType.java | 4 +-
.../api/serializer/SerializerException.java | 4 +-
.../server/api/serializer/SerializerResult.java | 4 +-
.../server/api/serializer/package-info.java | 4 +-
.../apache/olingo/server/api/uri/UriHelper.java | 10 +-
.../apache/olingo/server/api/uri/UriInfo.java | 6 +-
.../olingo/server/api/uri/UriInfoAll.java | 6 +-
.../olingo/server/api/uri/UriInfoBatch.java | 6 +-
.../olingo/server/api/uri/UriInfoCrossjoin.java | 8 +-
.../olingo/server/api/uri/UriInfoEntityId.java | 4 +-
.../olingo/server/api/uri/UriInfoKind.java | 4 +-
.../olingo/server/api/uri/UriInfoMetadata.java | 4 +-
.../olingo/server/api/uri/UriInfoResource.java | 4 +-
.../olingo/server/api/uri/UriInfoService.java | 6 +-
.../olingo/server/api/uri/UriParameter.java | 4 +-
.../olingo/server/api/uri/UriResource.java | 4 +-
.../server/api/uri/UriResourceAction.java | 4 +-
.../api/uri/UriResourceComplexProperty.java | 4 +-
.../olingo/server/api/uri/UriResourceCount.java | 6 +-
.../server/api/uri/UriResourceEntitySet.java | 4 +-
.../server/api/uri/UriResourceFunction.java | 4 +-
.../olingo/server/api/uri/UriResourceIt.java | 4 +-
.../olingo/server/api/uri/UriResourceKind.java | 4 +-
.../server/api/uri/UriResourceLambdaAll.java | 4 +-
.../server/api/uri/UriResourceLambdaAny.java | 4 +-
.../api/uri/UriResourceLambdaVariable.java | 4 +-
.../server/api/uri/UriResourceNavigation.java | 4 +-
.../server/api/uri/UriResourcePartTyped.java | 6 +-
.../api/uri/UriResourcePrimitiveProperty.java | 6 +-
.../server/api/uri/UriResourceProperty.java | 4 +-
.../olingo/server/api/uri/UriResourceRef.java | 6 +-
.../olingo/server/api/uri/UriResourceRoot.java | 6 +-
.../server/api/uri/UriResourceSingleton.java | 4 +-
.../olingo/server/api/uri/UriResourceValue.java | 6 +-
.../olingo/server/api/uri/package-info.java | 6 +-
.../api/uri/queryoption/AliasQueryOption.java | 4 +-
.../server/api/uri/queryoption/CountOption.java | 4 +-
.../api/uri/queryoption/CustomQueryOption.java | 6 +-
.../server/api/uri/queryoption/ExpandItem.java | 4 +-
.../api/uri/queryoption/ExpandOption.java | 4 +-
.../api/uri/queryoption/FilterOption.java | 4 +-
.../api/uri/queryoption/FormatOption.java | 4 +-
.../server/api/uri/queryoption/IdOption.java | 4 +-
.../api/uri/queryoption/LevelsExpandOption.java | 4 +-
.../server/api/uri/queryoption/OrderByItem.java | 4 +-
.../api/uri/queryoption/OrderByOption.java | 4 +-
.../server/api/uri/queryoption/QueryOption.java | 4 +-
.../api/uri/queryoption/SearchOption.java | 4 +-
.../server/api/uri/queryoption/SelectItem.java | 4 +-
.../api/uri/queryoption/SelectOption.java | 4 +-
.../server/api/uri/queryoption/SkipOption.java | 4 +-
.../api/uri/queryoption/SkipTokenOption.java | 4 +-
.../api/uri/queryoption/SystemQueryOption.java | 4 +-
.../uri/queryoption/SystemQueryOptionKind.java | 4 +-
.../server/api/uri/queryoption/TopOption.java | 4 +-
.../api/uri/queryoption/expression/Alias.java | 4 +-
.../api/uri/queryoption/expression/Binary.java | 4 +-
.../expression/BinaryOperatorKind.java | 4 +-
.../uri/queryoption/expression/Enumeration.java | 4 +-
.../uri/queryoption/expression/Expression.java | 6 +-
.../expression/ExpressionVisitException.java | 4 +-
.../expression/ExpressionVisitor.java | 4 +-
.../uri/queryoption/expression/LambdaRef.java | 4 +-
.../api/uri/queryoption/expression/Literal.java | 10 +-
.../api/uri/queryoption/expression/Member.java | 4 +-
.../api/uri/queryoption/expression/Method.java | 4 +-
.../uri/queryoption/expression/MethodKind.java | 4 +-
.../uri/queryoption/expression/TypeLiteral.java | 4 +-
.../api/uri/queryoption/expression/Unary.java | 4 +-
.../expression/UnaryOperatorKind.java | 4 +-
.../expression/VisitableExpression.java | 4 +-
.../queryoption/expression/package-info.java | 4 +-
.../api/uri/queryoption/package-info.java | 4 +-
.../uri/queryoption/search/SearchBinary.java | 4 +-
.../search/SearchBinaryOperatorKind.java | 4 +-
.../queryoption/search/SearchExpression.java | 18 +-
.../api/uri/queryoption/search/SearchTerm.java | 4 +-
.../api/uri/queryoption/search/SearchUnary.java | 5 +-
.../search/SearchUnaryOperatorKind.java | 4 +-
.../uri/queryoption/search/package-info.java | 4 +-
.../olingo/server/api/ODataRequestTest.java | 4 +-
.../server/api/TranslatedExceptionsTest.java | 4 +-
.../api/prefer/PreferencesAppliedTest.java | 22 +-
lib/server-core-ext/pom.xml | 2 +-
lib/server-core/pom.xml | 2 +-
.../olingo/server/core/ContentNegotiator.java | 18 +-
.../server/core/ContentNegotiatorException.java | 4 +-
.../server/core/DefaultRedirectProcessor.java | 4 +-
.../olingo/server/core/ODataDispatcher.java | 132 ++++++------
.../server/core/ODataExceptionHelper.java | 14 +-
.../apache/olingo/server/core/ODataHandler.java | 18 +-
.../server/core/ODataHandlerException.java | 6 +-
.../server/core/ODataHttpHandlerImpl.java | 8 +-
.../apache/olingo/server/core/ODataImpl.java | 10 +-
.../olingo/server/core/RedirectProcessor.java | 4 +-
.../olingo/server/core/ServiceMetadataImpl.java | 8 +-
.../core/batchhandler/BatchFacadeImpl.java | 8 +-
.../server/core/batchhandler/BatchHandler.java | 4 +-
.../core/batchhandler/BatchPartHandler.java | 6 +-
.../BatchReferenceRewriter.java | 4 +-
.../core/debug/DebugResponseHelperImpl.java | 118 +++++------
.../olingo/server/core/debug/DebugTab.java | 5 +-
.../olingo/server/core/debug/DebugTabBody.java | 12 +-
.../server/core/debug/DebugTabRequest.java | 28 +--
.../server/core/debug/DebugTabResponse.java | 14 +-
.../server/core/debug/DebugTabRuntime.java | 34 +--
.../server/core/debug/DebugTabServer.java | 14 +-
.../server/core/debug/DebugTabStacktrace.java | 24 +--
.../olingo/server/core/debug/DebugTabUri.java | 49 +++--
.../core/debug/ExpressionJsonVisitor.java | 12 +-
.../server/core/debug/ServerCoreDebugger.java | 12 +-
.../deserializer/DeserializerResultImpl.java | 4 +-
.../FixedFormatDeserializerImpl.java | 10 +-
.../core/deserializer/batch/BatchBodyPart.java | 8 +-
.../deserializer/batch/BatchChangeSetPart.java | 4 +-
.../deserializer/batch/BatchLineReader.java | 44 ++--
.../core/deserializer/batch/BatchParser.java | 10 +-
.../deserializer/batch/BatchParserCommon.java | 14 +-
.../core/deserializer/batch/BatchPart.java | 4 +-
.../deserializer/batch/BatchQueryOperation.java | 4 +-
.../batch/BatchRequestTransformator.java | 20 +-
.../batch/BatchTransformatorCommon.java | 8 +-
.../server/core/deserializer/batch/Header.java | 4 +-
.../core/deserializer/batch/HeaderField.java | 4 +-
.../batch/HttpRequestStatusLine.java | 6 +-
.../server/core/deserializer/batch/Line.java | 4 +-
.../deserializer/helper/ExpandTreeBuilder.java | 4 +-
.../helper/ExpandTreeBuilderImpl.java | 4 +-
.../json/ODataJsonDeserializer.java | 113 +++++-----
.../deserializer/xml/ODataXmlDeserializer.java | 34 +--
.../olingo/server/core/etag/ETagHelperImpl.java | 8 +-
.../server/core/etag/ETagInformation.java | 4 +-
.../olingo/server/core/etag/ETagParser.java | 22 +-
.../core/etag/PreconditionsValidator.java | 14 +-
.../olingo/server/core/prefer/PreferParser.java | 40 ++--
.../server/core/prefer/PreferencesImpl.java | 13 +-
.../serializer/AbstractODataSerializer.java | 7 +-
.../serializer/AsyncResponseSerializer.java | 18 +-
.../serializer/BatchResponseSerializer.java | 45 ++--
.../serializer/FixedFormatSerializerImpl.java | 6 +-
.../core/serializer/SerializerResultImpl.java | 4 +-
.../serializer/json/ODataErrorSerializer.java | 4 +-
.../serializer/json/ODataJsonSerializer.java | 94 ++++-----
.../json/ServiceDocumentJsonSerializer.java | 12 +-
.../serializer/utils/CircleStreamBuffer.java | 4 +-
.../serializer/utils/ContentTypeHelper.java | 16 +-
.../serializer/utils/ContextURLBuilder.java | 22 +-
.../core/serializer/utils/ContextURLHelper.java | 17 +-
.../serializer/utils/ExpandSelectHelper.java | 4 +-
.../xml/MetadataDocumentXmlSerializer.java | 38 ++--
.../core/serializer/xml/ODataXmlSerializer.java | 27 +--
.../xml/ServiceDocumentXmlSerializer.java | 12 +-
.../olingo/server/core/uri/UriHelperImpl.java | 8 +-
.../olingo/server/core/uri/UriInfoImpl.java | 4 +-
.../server/core/uri/UriParameterImpl.java | 4 +-
.../server/core/uri/UriResourceActionImpl.java | 8 +-
.../uri/UriResourceComplexPropertyImpl.java | 4 +-
.../server/core/uri/UriResourceCountImpl.java | 4 +-
.../core/uri/UriResourceEntitySetImpl.java | 6 +-
.../core/uri/UriResourceFunctionImpl.java | 6 +-
.../olingo/server/core/uri/UriResourceImpl.java | 4 +-
.../server/core/uri/UriResourceItImpl.java | 4 +-
.../core/uri/UriResourceLambdaAllImpl.java | 4 +-
.../core/uri/UriResourceLambdaAnyImpl.java | 4 +-
.../core/uri/UriResourceLambdaVarImpl.java | 4 +-
.../uri/UriResourceNavigationPropertyImpl.java | 4 +-
.../uri/UriResourcePrimitivePropertyImpl.java | 4 +-
.../server/core/uri/UriResourceRefImpl.java | 4 +-
.../server/core/uri/UriResourceRootImpl.java | 4 +-
.../core/uri/UriResourceSingletonImpl.java | 4 +-
.../uri/UriResourceStartingTypeFilterImpl.java | 4 +-
.../server/core/uri/UriResourceTypedImpl.java | 5 +-
.../server/core/uri/UriResourceValueImpl.java | 4 +-
.../core/uri/UriResourceWithKeysImpl.java | 4 +-
.../uri/parser/CheckFullContextListener.java | 60 ++++++
.../olingo/server/core/uri/parser/Parser.java | 4 +-
.../olingo/server/core/uri/parser/RawUri.java | 46 +++++
.../server/core/uri/parser/UriDecoder.java | 4 +-
.../core/uri/parser/UriParserException.java | 4 +-
.../uri/parser/UriParserSemanticException.java | 8 +-
.../uri/parser/UriParserSyntaxException.java | 6 +-
.../uri/parser/search/SearchBinaryImpl.java | 7 +-
.../uri/parser/search/SearchExpressionImpl.java | 4 +-
.../core/uri/parser/search/SearchParser.java | 60 +++---
.../parser/search/SearchParserException.java | 6 +-
.../uri/parser/search/SearchQueryToken.java | 9 +-
.../core/uri/parser/search/SearchTermImpl.java | 6 +-
.../core/uri/parser/search/SearchTokenizer.java | 129 ++++++------
.../parser/search/SearchTokenizerException.java | 6 +-
.../core/uri/parser/search/SearchUnaryImpl.java | 6 +-
.../uri/queryoption/AliasQueryOptionImpl.java | 4 +-
.../core/uri/queryoption/CountOptionImpl.java | 4 +-
.../uri/queryoption/CustomQueryOptionImpl.java | 4 +-
.../core/uri/queryoption/ExpandItemImpl.java | 8 +-
.../core/uri/queryoption/ExpandOptionImpl.java | 4 +-
.../core/uri/queryoption/FilterOptionImpl.java | 4 +-
.../core/uri/queryoption/FormatOptionImpl.java | 4 +-
.../core/uri/queryoption/IdOptionImpl.java | 4 +-
.../core/uri/queryoption/LevelsOptionImpl.java | 4 +-
.../core/uri/queryoption/OrderByItemImpl.java | 4 +-
.../core/uri/queryoption/OrderByOptionImpl.java | 4 +-
.../core/uri/queryoption/QueryOptionImpl.java | 4 +-
.../core/uri/queryoption/SearchOptionImpl.java | 6 +-
.../core/uri/queryoption/SelectItemImpl.java | 4 +-
.../core/uri/queryoption/SelectOptionImpl.java | 4 +-
.../core/uri/queryoption/SkipOptionImpl.java | 4 +-
.../uri/queryoption/SkipTokenOptionImpl.java | 4 +-
.../uri/queryoption/SystemQueryOptionImpl.java | 4 +-
.../core/uri/queryoption/TopOptionImpl.java | 4 +-
.../uri/queryoption/expression/AliasImpl.java | 4 +-
.../uri/queryoption/expression/BinaryImpl.java | 4 +-
.../queryoption/expression/EnumerationImpl.java | 4 +-
.../queryoption/expression/ExpressionImpl.java | 25 +++
.../queryoption/expression/LambdaRefImpl.java | 4 +-
.../uri/queryoption/expression/LiteralImpl.java | 4 +-
.../uri/queryoption/expression/MemberImpl.java | 4 +-
.../uri/queryoption/expression/MethodImpl.java | 4 +-
.../queryoption/expression/TypeLiteralImpl.java | 4 +-
.../uri/queryoption/expression/UnaryImpl.java | 4 +-
.../uri/validator/UriValidationException.java | 7 +-
.../server/core/uri/validator/UriValidator.java | 161 ++++++++-------
.../server/core/ContentNegotiatorTest.java | 8 +-
.../olingo/server/core/ExceptionHelperTest.java | 6 +-
.../server/core/ODataHttpHandlerImplTest.java | 6 +-
.../olingo/server/core/ODataImplTest.java | 4 +-
.../core/TranslatedExceptionSubclassesTest.java | 4 +-
.../batchhandler/MockedBatchHandlerTest.java | 4 +-
.../server/core/debug/AbstractDebugTabTest.java | 8 +-
.../server/core/debug/DebugTabBodyTest.java | 4 +-
.../server/core/debug/DebugTabRequestTest.java | 4 +-
.../server/core/debug/DebugTabResponseTest.java | 4 +-
.../server/core/debug/DebugTabServerTest.java | 6 +-
.../core/debug/ServerCoreDebuggerTest.java | 6 +-
.../FixedFormatDeserializerTest.java | 4 +-
.../deserializer/batch/BatchLineReaderTest.java | 4 +-
.../batch/BatchParserCommonTest.java | 4 +-
.../batch/BatchRequestParserTest.java | 16 +-
.../core/deserializer/batch/HeaderTest.java | 4 +-
.../batch/HttpRequestStatusLineTest.java | 4 +-
.../json/ODataJsonDeserializerBasicTest.java | 4 +-
.../olingo/server/core/etag/ETagHelperTest.java | 4 +-
.../olingo/server/core/etag/ETagParserTest.java | 4 +-
.../server/core/prefer/PreferencesTest.java | 8 +-
.../serializer/AsyncResponseSerializerTest.java | 18 +-
.../serializer/BatchResponseSerializerTest.java | 20 +-
.../serializer/FixedFormatSerializerTest.java | 4 +-
.../json/ServerErrorSerializerTest.java | 8 +-
.../utils/CircleStreamBufferTest.java | 5 +-
.../serializer/utils/ContextURLBuilderTest.java | 4 +-
.../xml/MetadataDocumentXmlSerializerTest.java | 205 ++++++++++---------
.../xml/ServerErrorXmlSerializerTest.java | 18 +-
.../xml/ServiceDocumentXmlSerializerTest.java | 24 +--
.../search/SearchParserAndTokenizerTest.java | 88 ++++----
.../uri/parser/search/SearchParserTest.java | 17 +-
.../uri/parser/search/SearchTokenizerTest.java | 112 +++++-----
lib/server-tecsvc/pom.xml | 2 +-
lib/server-test/pom.xml | 2 +-
pom.xml | 2 +-
samples/client/pom.xml | 2 +-
samples/osgi/server/pom.xml | 2 +-
samples/pom.xml | 2 +-
samples/server/pom.xml | 2 +-
samples/tutorials/p0_all/pom.xml | 4 +-
samples/tutorials/p10_media/pom.xml | 4 +-
samples/tutorials/p11_batch/pom.xml | 4 +-
samples/tutorials/p12_deep_insert/pom.xml | 4 +-
.../p12_deep_insert_preparation/pom.xml | 4 +-
samples/tutorials/p1_read/pom.xml | 4 +-
samples/tutorials/p2_readep/pom.xml | 4 +-
samples/tutorials/p3_write/pom.xml | 4 +-
samples/tutorials/p4_navigation/pom.xml | 4 +-
samples/tutorials/p5_queryoptions-tcs/pom.xml | 4 +-
samples/tutorials/p6_queryoptions-es/pom.xml | 4 +-
samples/tutorials/p7_queryoptions-o/pom.xml | 4 +-
samples/tutorials/p8_queryoptions-f/pom.xml | 4 +-
samples/tutorials/p9_action/pom.xml | 4 +-
samples/tutorials/p9_action_preparation/pom.xml | 4 +-
samples/tutorials/pom.xml | 2 +-
374 files changed, 2042 insertions(+), 1851 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/010642c5/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/queryoption/ExpandItem.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/010642c5/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/010642c5/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/helper/ExpandTreeBuilder.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/010642c5/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriHelperImpl.java
----------------------------------------------------------------------
diff --cc lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriHelperImpl.java
index 3bc5ad0,f1bd75e..b2917f4
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriHelperImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriHelperImpl.java
@@@ -108,11 -107,11 +108,11 @@@ public class UriHelperImpl implements U
oDataPath = oDataPath.startsWith("/") ? oDataPath : "/" + oDataPath;
try {
- final List<UriResource> uriResourceParts = new Parser().parseUri(oDataPath, null, null, edm)
- .getUriResourceParts();
+ final List<UriResource> uriResourceParts =
+ new Parser(edm, new ODataImpl()).parseUri(oDataPath, null, null).getUriResourceParts();
if (uriResourceParts.size() == 1 && uriResourceParts.get(0).getKind() == UriResourceKind.entitySet) {
final UriResourceEntitySet entityUriResource = (UriResourceEntitySet) uriResourceParts.get(0);
-
+
return entityUriResource;
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/010642c5/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceActionImpl.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/010642c5/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceComplexPropertyImpl.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/010642c5/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceCountImpl.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/010642c5/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceEntitySetImpl.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/010642c5/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceFunctionImpl.java
----------------------------------------------------------------------
diff --cc lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceFunctionImpl.java
index 7784062,42361e0..433ebb5
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceFunctionImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceFunctionImpl.java
@@@ -49,9 -46,15 +49,9 @@@ public class UriResourceFunctionImpl ex
public List<UriParameter> getParameters() {
return parameters == null ?
Collections.<UriParameter> emptyList() :
- Collections.unmodifiableList(parameters);
+ Collections.unmodifiableList(parameters);
}
- public UriResourceFunctionImpl setParameters(final List<UriParameter> parameters) {
- isParameterListFilled = true;
- this.parameters = parameters;
- return this;
- }
-
@Override
public EdmFunction getFunction() {
return function;
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/010642c5/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceImpl.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/010642c5/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceItImpl.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/010642c5/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceLambdaAllImpl.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/010642c5/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceLambdaAnyImpl.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/010642c5/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceLambdaVarImpl.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/010642c5/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceNavigationPropertyImpl.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/010642c5/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourcePrimitivePropertyImpl.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/010642c5/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceRefImpl.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/010642c5/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceRootImpl.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/010642c5/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceSingletonImpl.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/010642c5/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceStartingTypeFilterImpl.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/010642c5/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceTypedImpl.java
----------------------------------------------------------------------
diff --cc lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceTypedImpl.java
index 9930a7e,cdfa013..d44b9e6
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceTypedImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceTypedImpl.java
@@@ -40,10 -40,16 +40,11 @@@ public abstract class UriResourceTypedI
return this;
}
+ @Override
public String getSegmentValue(final boolean includeFilters) {
- if (includeFilters) {
- if (typeFilter != null) {
- return getSegmentValue() + "/" + typeFilter.getFullQualifiedName().toString();
- } else {
- return getSegmentValue();
- }
- }
- return getSegmentValue();
+ return includeFilters && typeFilter != null ?
+ getSegmentValue() + "/" + typeFilter.getFullQualifiedName().getFullQualifiedNameAsString() :
+ getSegmentValue();
}
@Override
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/010642c5/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceValueImpl.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/010642c5/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceWithKeysImpl.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/010642c5/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/010642c5/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriDecoder.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/010642c5/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParserSemanticException.java
----------------------------------------------------------------------
diff --cc lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParserSemanticException.java
index cc31e34,33dd321..8f5aa67
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParserSemanticException.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParserSemanticException.java
@@@ -79,14 -79,12 +79,14 @@@ public class UriParserSemanticExceptio
/** parameter: not implemented part */
NOT_IMPLEMENTED,
/** parameter: namespace **/
- NAMESPACE_NOT_ALLOWED_AT_FIRST_ELEMENT,
+ NAMESPACE_NOT_ALLOWED_AT_FIRST_ELEMENT,
/** parameter: complex parameter value */
- COMPLEX_PARAMETER_IN_RESOURCE_PATH,
+ COMPLEX_PARAMETER_IN_RESOURCE_PATH,
/** parameter: function import name */
- FUNCTION_IMPORT_NOT_ALLOWED;
-
+ FUNCTION_IMPORT_NOT_ALLOWED,
+ /** parameters: left type, right type */
+ TYPES_NOT_COMPATIBLE;
+
@Override
public String getKey() {
return name();
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/010642c5/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/OrderByItemImpl.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/010642c5/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/AliasImpl.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/010642c5/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/BinaryImpl.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/010642c5/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/EnumerationImpl.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/010642c5/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/LambdaRefImpl.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/010642c5/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/LiteralImpl.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/010642c5/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/MemberImpl.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/010642c5/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/MethodImpl.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/010642c5/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/TypeLiteralImpl.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/010642c5/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/UnaryImpl.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/010642c5/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java
----------------------------------------------------------------------
diff --cc lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java
index 3ccd97a,9ffe696..149d1fc
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java
@@@ -222,7 -223,14 +222,6 @@@ public class UriValidator
private RowIndexForUriType rowIndexForResourceKind(final UriInfo uriInfo) throws UriValidationException {
RowIndexForUriType idx;
-
- final int nonComposableFunctionIndex = getIndexOfLastNonComposableFunction(uriInfo);
- if (nonComposableFunctionIndex != -1 && (uriInfo.getUriResourceParts().size() - 1) > nonComposableFunctionIndex) {
- throw new UriValidationException("Non composable functions followed by further resource parts are not allowed",
- UriValidationException.MessageKeys.UNALLOWED_RESOURCE_PATH,
- uriInfo.getUriResourceParts().get(nonComposableFunctionIndex + 1).getSegmentValue());
- }
--
int lastPathSegmentIndex = uriInfo.getUriResourceParts().size() - 1;
UriResource lastPathSegment = uriInfo.getUriResourceParts().get(lastPathSegmentIndex);
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/010642c5/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/search/SearchParserAndTokenizerTest.java
----------------------------------------------------------------------
diff --cc lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/search/SearchParserAndTokenizerTest.java
index f3e50a2,40c6200..9bb7d6f
--- a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/search/SearchParserAndTokenizerTest.java
+++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/search/SearchParserAndTokenizerTest.java
@@@ -119,71 -119,71 +119,71 @@@ public class SearchParserAndTokenizerTe
*/
@Test
public void searchQueryPhraseAbnfTestcases() throws Exception {
- // <TestCase Name="5.1.7 Search - simple phrase" Rule="queryOptions">
+ // <TestCase Name="5.1.7 Search - simple phrase" Rule="queryOptions">
assertQuery("\"blue green\"").resultsIn("'blue green'");
- // <TestCase Name="5.1.7 Search - simple phrase" Rule="queryOptions">
+ // <TestCase Name="5.1.7 Search - simple phrase" Rule="queryOptions">
assertQuery("\"blue green\"").resultsIn("'blue green'");
- // <TestCase Name="5.1.7 Search - phrase with escaped double-quote" Rule="queryOptions">
- // <Input>$search="blue\"green"</Input>
+ // <TestCase Name="5.1.7 Search - phrase with escaped double-quote" Rule="queryOptions">
+ // <Input>$search="blue\"green"</Input>
assertQuery("\"blue\\\"green\"").resultsIn("'blue\"green'");
- // <TestCase Name="5.1.7 Search - phrase with escaped backslash" Rule="queryOptions">
- // <Input>$search="blue\\green"</Input>
+ // <TestCase Name="5.1.7 Search - phrase with escaped backslash" Rule="queryOptions">
+ // <Input>$search="blue\\green"</Input>
assertQuery("\"blue\\\\green\"").resultsIn("'blue\\green'");
- // <TestCase Name="5.1.7 Search - phrase with unescaped double-quote" Rule="queryOptions" FailAt="14">
+ // <TestCase Name="5.1.7 Search - phrase with unescaped double-quote" Rule="queryOptions" FailAt="14">
assertQuery("\"blue\"green\"").resultsIn(SearchParserException.MessageKeys.TOKENIZER_EXCEPTION);
- // <TestCase Name="5.1.7 Search - phrase with unescaped double-quote" Rule="queryOptions" FailAt="16">
+ // <TestCase Name="5.1.7 Search - phrase with unescaped double-quote" Rule="queryOptions" FailAt="16">
assertQuery("\"blue\"green\"").resultsIn(SearchParserException.MessageKeys.TOKENIZER_EXCEPTION);
- // <TestCase Name="5.1.7 Search - implicit AND" Rule="queryOptions">
- // <Input>$search=blue green</Input>
+ // <TestCase Name="5.1.7 Search - implicit AND" Rule="queryOptions">
+ // <Input>$search=blue green</Input>
assertQuery("blue green").resultsIn("{'blue' AND 'green'}");
- // <TestCase Name="5.1.7 Search - implicit AND, encoced" Rule="queryOptions">
+ // <TestCase Name="5.1.7 Search - implicit AND, encoced" Rule="queryOptions">
assertQuery("blue green").resultsIn("{'blue' AND 'green'}");
- // <TestCase Name="5.1.7 Search - AND" Rule="queryOptions">
- // <Input>$search=blue AND green</Input>
+ // <TestCase Name="5.1.7 Search - AND" Rule="queryOptions">
+ // <Input>$search=blue AND green</Input>
assertQuery("blue AND green").resultsIn("{'blue' AND 'green'}");
- // <TestCase Name="5.1.7 Search - OR" Rule="queryOptions">
- // <Input>$search=blue OR green</Input>
+ // <TestCase Name="5.1.7 Search - OR" Rule="queryOptions">
+ // <Input>$search=blue OR green</Input>
assertQuery("blue OR green").resultsIn("{'blue' OR 'green'}");
- // <TestCase Name="5.1.7 Search - NOT" Rule="queryOptions">
- // <Input>$search=blue NOT green</Input>
+ // <TestCase Name="5.1.7 Search - NOT" Rule="queryOptions">
+ // <Input>$search=blue NOT green</Input>
assertQuery("blue NOT green").resultsIn("{'blue' AND {NOT 'green'}}");
- // <TestCase Name="5.1.7 Search - only NOT" Rule="queryOptions">
- // <Input>$search=NOT blue</Input>
+ // <TestCase Name="5.1.7 Search - only NOT" Rule="queryOptions">
+ // <Input>$search=NOT blue</Input>
assertQuery("NOT blue").resultsIn("{NOT 'blue'}");
- // <TestCase Name="5.1.7 Search - multiple" Rule="queryOptions">
- // <Input>$search=foo AND bar OR foo AND baz OR that AND bar OR that AND baz</Input>
+ // <TestCase Name="5.1.7 Search - multiple" Rule="queryOptions">
+ // <Input>$search=foo AND bar OR foo AND baz OR that AND bar OR that AND baz</Input>
assertQuery("foo AND bar OR foo AND baz OR that AND bar OR that AND baz")
- .resultsIn("{{{{'foo' AND 'bar'} OR {'foo' AND 'baz'}} OR {'that' AND 'bar'}} OR {'that' AND 'baz'}}");
+ .resultsIn("{{{{'foo' AND 'bar'} OR {'foo' AND 'baz'}} OR {'that' AND 'bar'}} OR {'that' AND 'baz'}}");
- // <TestCase Name="5.1.7 Search - multiple" Rule="queryOptions">
- // <Input>$search=(foo OR that) AND (bar OR baz)</Input>
+ // <TestCase Name="5.1.7 Search - multiple" Rule="queryOptions">
+ // <Input>$search=(foo OR that) AND (bar OR baz)</Input>
assertQuery("(foo OR that) AND (bar OR baz)").resultsIn("{{'foo' OR 'that'} AND {'bar' OR 'baz'}}");
- // <TestCase Name="5.1.7 Search - grouping" Rule="queryOptions">
- // <Input>$search=foo AND (bar OR baz)</Input>
+ // <TestCase Name="5.1.7 Search - grouping" Rule="queryOptions">
+ // <Input>$search=foo AND (bar OR baz)</Input>
assertQuery("foo AND (bar OR baz)").resultsIn("{'foo' AND {'bar' OR 'baz'}}");
- // <TestCase Name="5.1.7 Search - grouping" Rule="queryOptions">
- // <Input>$search=(foo AND bar) OR baz</Input>
+ // <TestCase Name="5.1.7 Search - grouping" Rule="queryOptions">
+ // <Input>$search=(foo AND bar) OR baz</Input>
assertQuery("(foo AND bar) OR baz").resultsIn("{{'foo' AND 'bar'} OR 'baz'}");
- // <TestCase Name="5.1.7 Search - grouping" Rule="queryOptions">
- // <Input>$search=(NOT foo) OR baz</Input>
+ // <TestCase Name="5.1.7 Search - grouping" Rule="queryOptions">
+ // <Input>$search=(NOT foo) OR baz</Input>
assertQuery("(NOT foo) OR baz").resultsIn("{{NOT 'foo'} OR 'baz'}");
- // <TestCase Name="5.1.7 Search - grouping" Rule="queryOptions">
- // <Input>$search=(NOT foo)</Input>
+ // <TestCase Name="5.1.7 Search - grouping" Rule="queryOptions">
+ // <Input>$search=(NOT foo)</Input>
assertQuery("(NOT foo)").resultsIn("{NOT 'foo'}");
- // <TestCase Name="5.1.7 Search - on entity set" Rule="odataUri">
- // <Input>http://serviceRoot/Products?$search=blue</Input>
+ // <TestCase Name="5.1.7 Search - on entity set" Rule="odataUri">
+ // <Input>http://serviceRoot/Products?$search=blue</Input>
assertQuery("blue").resultsIn("'blue'");
// below cases can not be tested here
@@@ -198,13 -198,19 +198,19 @@@
}
private static class Validator {
- private boolean log;
private final String searchQuery;
- private Validator(String searchQuery) {
+ private Validator(final String searchQuery) {
this.searchQuery = searchQuery;
}
- private void resultsIn(SearchParserException.MessageKey key) throws SearchTokenizerException {
+ private static Validator init(final String searchQuery) {
+ return new Validator(searchQuery);
+ }
+
+ private void resultsIn(final SearchParserException.MessageKey key)
+ throws SearchTokenizerException {
++
try {
resultsIn(searchQuery);
} catch (SearchParserException e) {
[22/30] olingo-odata4 git commit: [OLINGO-834] $expand parser in Java
+ clean-up
Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
index f505a21..3b673a6 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
@@ -40,6 +40,15 @@ public class UriTokenizer {
ROOT,
IT,
+ EXPAND,
+ FILTER,
+ LEVELS,
+ ORDERBY,
+ SEARCH,
+ SELECT,
+ SKIP,
+ TOP,
+
ANY,
ALL,
@@ -53,8 +62,9 @@ public class UriTokenizer {
EQ,
STAR,
PLUS,
- MINUS,
+
NULL,
+ MAX,
// variable-value tokens (convention: mixed case)
ODataIdentifier,
@@ -76,6 +86,13 @@ public class UriTokenizer {
jsonArrayOrObject,
+ Word,
+ Phrase,
+
+ OrOperatorSearch,
+ AndOperatorSearch,
+ NotOperatorSearch,
+
OrOperator,
AndOperator,
EqualsOperator,
@@ -90,6 +107,7 @@ public class UriTokenizer {
MulOperator,
DivOperator,
ModOperator,
+ MinusOperator,
NotOperator,
CastMethod,
@@ -161,6 +179,10 @@ public class UriTokenizer {
boolean found = false;
final int previousIndex = index;
switch (allowedTokenKind) {
+ case EOF:
+ found = index >= parseString.length();
+ break;
+
// Constants
case REF:
found = nextConstant("$ref");
@@ -181,6 +203,31 @@ public class UriTokenizer {
found = nextConstant("$it");
break;
+ case EXPAND:
+ found = nextConstant("$expand");
+ break;
+ case FILTER:
+ found = nextConstant("$filter");
+ break;
+ case LEVELS:
+ found = nextConstant("$levels");
+ break;
+ case ORDERBY:
+ found = nextConstant("$orderby");
+ break;
+ case SEARCH:
+ found = nextConstant("$search");
+ break;
+ case SELECT:
+ found = nextConstant("$select");
+ break;
+ case SKIP:
+ found = nextConstant("$skip");
+ break;
+ case TOP:
+ found = nextConstant("$top");
+ break;
+
case ANY:
found = nextConstant("any");
break;
@@ -218,14 +265,12 @@ public class UriTokenizer {
case PLUS:
found = nextCharacter('+');
break;
- case MINUS:
- found = nextMinus();
- break;
+
case NULL:
found = nextConstant("null");
break;
- case EOF:
- found = index >= parseString.length();
+ case MAX:
+ found = nextConstant("max");
break;
// Identifiers
@@ -282,6 +327,25 @@ public class UriTokenizer {
found = nextJsonArrayOrObject();
break;
+ // Search
+ case Word:
+ found = nextWord();
+ break;
+ case Phrase:
+ found = nextPhrase();
+ break;
+
+ // Operators in Search Expressions
+ case OrOperatorSearch:
+ found = nextBinaryOperator("OR");
+ break;
+ case AndOperatorSearch:
+ found = nextAndOperatorSearch();
+ break;
+ case NotOperatorSearch:
+ found = nextUnaryOperator("NOT");
+ break;
+
// Operators
case OrOperator:
found = nextBinaryOperator("or");
@@ -325,8 +389,12 @@ public class UriTokenizer {
case ModOperator:
found = nextBinaryOperator("mod");
break;
+ case MinusOperator:
+ // To avoid unnecessary minus operators for negative numbers, we have to check what follows the minus sign.
+ found = nextCharacter('-') && !nextDigit() && !nextConstant("INF");
+ break;
case NotOperator:
- found = nextConstant("not") && nextWhitespace();
+ found = nextUnaryOperator("not");
break;
// Methods
@@ -444,27 +512,6 @@ public class UriTokenizer {
return found;
}
- private boolean nextMinus() {
- if(parseString.startsWith("-", index)) {
- final int lastGoodIndex = index;
-
- if(nextDoubleValue()) {
- index = lastGoodIndex;
- return false;
- } else if(nextDecimalValue()) {
- index = lastGoodIndex;
- return false;
- } else if(nextIntegerValue(true)) {
- index = lastGoodIndex;
- return false;
- } else {
- index++;
- return true;
- }
- }
- return false;
- }
-
/**
* Moves past the given string constant if found; otherwise leaves the index unchanged.
* @return whether the constant has been found at the current index
@@ -569,34 +616,6 @@ public class UriTokenizer {
}
return count > 0;
}
-
- /**
- * Moves past the given whitespace-surrounded operator constant if found;
- * otherwise leaves the index unchanged.
- * @return whether the operator has been found at the current index
- */
- private boolean nextBinaryOperator(final String operator) {
- return nextWhitespace() && nextConstant(operator) && nextWhitespace();
- }
-
- /**
- * Moves past the given method name and its immediately following opening parenthesis if found;
- * otherwise leaves the index unchanged.
- * @return whether the method has been found at the current index
- */
- private boolean nextMethod(final String methodName) {
- return nextConstant(methodName) && nextCharacter('(');
- }
-
- /**
- * Moves past (required) whitespace and the given suffix name if found;
- * otherwise leaves the index unchanged.
- * @return whether the suffix has been found at the current index
- */
- private boolean nextSuffix(final String suffixName) {
- return nextWhitespace() && nextConstant(suffixName);
- }
-
/**
* Moves past an OData identifier if found; otherwise leaves the index unchanged.
* @return whether an OData identifier has been found at the current index
@@ -650,6 +669,38 @@ public class UriTokenizer {
}
}
+ /**
+ * Moves past the given whitespace-surrounded operator constant if found.
+ * @return whether the operator has been found at the current index
+ */
+ private boolean nextBinaryOperator(final String operator) {
+ return nextWhitespace() && nextConstant(operator) && nextWhitespace();
+ }
+
+ /**
+ * Moves past the given whitespace-suffixed operator constant if found.
+ * @return whether the operator has been found at the current index
+ */
+ private boolean nextUnaryOperator(final String operator) {
+ return nextConstant(operator) && nextWhitespace();
+ }
+
+ /**
+ * Moves past the given method name and its immediately following opening parenthesis if found.
+ * @return whether the method has been found at the current index
+ */
+ private boolean nextMethod(final String methodName) {
+ return nextConstant(methodName) && nextCharacter('(');
+ }
+
+ /**
+ * Moves past (required) whitespace and the given suffix name if found.
+ * @return whether the suffix has been found at the current index
+ */
+ private boolean nextSuffix(final String suffixName) {
+ return nextWhitespace() && nextConstant(suffixName);
+ }
+
private boolean nextParameterAliasName() {
return nextCharacter('@') && nextODataIdentifier();
}
@@ -978,4 +1029,52 @@ public class UriTokenizer {
return false;
}
}
+
+ private boolean nextAndOperatorSearch() {
+ if (nextWhitespace()) {
+ final int lastGoodIndex = index;
+ if (nextUnaryOperator("OR")) {
+ return false;
+ } else if (!(nextUnaryOperator("AND"))) {
+ index = lastGoodIndex;
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private boolean nextWord() {
+ int count = 0;
+ while (index < parseString.length()) {
+ final int code = parseString.codePointAt(index);
+ if (Character.isUnicodeIdentifierStart(code)) {
+ count++;
+ // Unicode characters outside of the Basic Multilingual Plane are represented as two Java characters.
+ index += Character.isSupplementaryCodePoint(code) ? 2 : 1;
+ } else {
+ break;
+ }
+ }
+ final String word = parseString.substring(index - count, index);
+ return count > 0 && !("OR".equals(word) || "AND".equals(word) || "NOT".equals(word));
+ }
+
+ private boolean nextPhrase() {
+ if (nextCharacter('"')) {
+ do {
+ if (nextCharacter('\\')) {
+ if (!(nextCharacter('\\') || nextCharacter('"'))) {
+ return false;
+ }
+ } else if (nextCharacter('"')) {
+ return true;
+ } else {
+ index++;
+ }
+ } while (index < parseString.length());
+ return false;
+ }
+ return false;
+ }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/AliasImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/AliasImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/AliasImpl.java
index c7d7c20..8c8dab9 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/AliasImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/AliasImpl.java
@@ -41,4 +41,8 @@ public class AliasImpl implements Alias {
return visitor.visitAlias(parameterName);
}
+ @Override
+ public String toString() {
+ return parameterName;
+ }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/EnumerationImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/EnumerationImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/EnumerationImpl.java
index 256b8d1..a238104 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/EnumerationImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/EnumerationImpl.java
@@ -53,4 +53,10 @@ public class EnumerationImpl implements Enumeration {
public <T> T accept(final ExpressionVisitor<T> visitor) throws ExpressionVisitException, ODataApplicationException {
return visitor.visitEnum(type, values);
}
+
+ @Override
+ public String toString() {
+ return type == null ? null :
+ type.getFullQualifiedName().getFullQualifiedNameAsString() + getValues();
+ }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/LambdaRefImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/LambdaRefImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/LambdaRefImpl.java
index 824943a..16232b8 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/LambdaRefImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/LambdaRefImpl.java
@@ -40,4 +40,9 @@ public class LambdaRefImpl implements LambdaRef {
public <T> T accept(final ExpressionVisitor<T> visitor) throws ExpressionVisitException, ODataApplicationException {
return visitor.visitLambdaReference(variableText);
}
+
+ @Override
+ public String toString() {
+ return variableText;
+ }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/TypeLiteralImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/TypeLiteralImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/TypeLiteralImpl.java
index 336c203..6a2a1c6 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/TypeLiteralImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/TypeLiteralImpl.java
@@ -41,4 +41,9 @@ public class TypeLiteralImpl implements TypeLiteral {
public <T> T accept(final ExpressionVisitor<T> visitor) throws ExpressionVisitException, ODataApplicationException {
return visitor.visitTypeLiteral(type);
}
+
+ @Override
+ public String toString() {
+ return type == null ? null : type.getFullQualifiedName().getFullQualifiedNameAsString();
+ }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties b/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
index 0b43f70..e178fed 100644
--- a/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
+++ b/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
@@ -81,11 +81,11 @@ UriParserSemanticException.COMPLEX_PROPERTY_OF_ENTITY_TYPE_EXPECTED=A complex pr
UriParserSemanticException.NOT_FOR_ENTITY_TYPE=Not allowed for entity type.
UriParserSemanticException.PREVIOUS_PART_TYPED=The previous part is typed.
UriParserSemanticException.RESOURCE_NOT_FOUND=Cannot find EntitySet, Singleton, ActionImport or FunctionImport with name '%1$s'.
-UriParserSemanticException.NOT_IMPLEMENTED=%1$s is not implemented!
-UriParserSemanticException.NAMESPACE_NOT_ALLOWED_AT_FIRST_ELEMENT=Namespace is not allowed for Entity Sets, Singeltons, Action Imports and Function Imports. Found '%1$s'.
-UriParserSemanticException.COMPLEX_PARAMETER_IN_RESOURCE_PATH=Complex parameters must not appear in resource path segments. Found: '%1$s'.
+UriParserSemanticException.NOT_IMPLEMENTED='%1$s' is not implemented!
+UriParserSemanticException.NAMESPACE_NOT_ALLOWED_AT_FIRST_ELEMENT=Namespace is not allowed for Entity Sets, Singletons, Action Imports and Function Imports; found '%1$s'.
+UriParserSemanticException.COMPLEX_PARAMETER_IN_RESOURCE_PATH=Complex parameters must not appear in resource path segments; found: '%1$s'.
UriParserSemanticException.FUNCTION_IMPORT_NOT_ALLOWED=Function Imports are not allowed in $filter or $orderby. Found: '%1$s'.
-UriParserSemanticException.TYPES_NOT_COMPATIBLE=Types are not compatible. Left type: '%1$s', right type: '%1$s'.
+UriParserSemanticException.TYPES_NOT_COMPATIBLE=The types '%1$s' and '%2$s' are not compatible.
UriValidationException.UNSUPPORTED_QUERY_OPTION=The query option '%1$s' is not supported.
UriValidationException.UNSUPPORTED_URI_KIND=The URI kind '%1$s' is not supported.
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java
index 4ab7fce..94d5373 100644
--- a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java
+++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java
@@ -22,9 +22,11 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
import java.util.Locale;
+import org.apache.olingo.commons.api.edm.Edm;
import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind;
@@ -260,9 +262,17 @@ public class ExpressionParserTest {
expression = parseMethod(TokenKind.SubstringMethod, "'abc'", "1");
assertEquals("{substring ['abc', 1]}", expression.toString());
+ assertEquals("{cast [Edm.SByte]}", parseMethod(TokenKind.CastMethod, "Edm.SByte").toString());
+ assertEquals("{cast [42, Edm.SByte]}", parseMethod(TokenKind.CastMethod, "42", "Edm.SByte").toString());
+
+ assertEquals("{isof [Edm.SByte]}", parseMethod(TokenKind.IsofMethod, "Edm.SByte").toString());
+ assertEquals("{isof [42, Edm.SByte]}", parseMethod(TokenKind.IsofMethod, "42", "Edm.SByte").toString());
+
wrongExpression("substring('abc')");
wrongExpression("substring('abc',1,2,3)");
wrongExpression("substring(1,2)");
+ wrongExpression("cast(1,2)");
+ wrongExpression("isof(Edm.Int16,2)");
}
private Expression parseMethod(TokenKind kind, String... parameters)
@@ -288,7 +298,7 @@ public class ExpressionParserTest {
private Expression parseExpression(final String expressionString)
throws UriParserException, UriValidationException {
UriTokenizer tokenizer = new UriTokenizer(expressionString);
- Expression expression = new ExpressionParser(null, odata).parse(tokenizer, null, null);
+ Expression expression = new ExpressionParser(mock(Edm.class), odata).parse(tokenizer, null, null);
assertNotNull(expression);
assertTrue(tokenizer.next(TokenKind.EOF));
return expression;
@@ -296,7 +306,7 @@ public class ExpressionParserTest {
private void wrongExpression(final String expressionString) {
try {
- new ExpressionParser(null, odata).parse(new UriTokenizer(expressionString), null, null);
+ new ExpressionParser(mock(Edm.class), odata).parse(new UriTokenizer(expressionString), null, null);
fail("Expected exception not thrown.");
} catch (final UriParserException e) {
assertNotNull(e);
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java
index af45e80..e130457 100644
--- a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java
+++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java
@@ -76,7 +76,7 @@ public class UriTokenizerTest {
assertTrue(tokenizer.next(TokenKind.STAR));
assertTrue(tokenizer.next(TokenKind.SLASH));
assertTrue(tokenizer.next(TokenKind.PLUS));
- assertTrue(tokenizer.next(TokenKind.MINUS));
+ assertTrue(tokenizer.next(TokenKind.MinusOperator));
assertTrue(tokenizer.next(TokenKind.EOF));
tokenizer = new UriTokenizer("any(a:true) or all(b:false)");
@@ -97,6 +97,45 @@ public class UriTokenizerTest {
}
@Test
+ public void systemQueryOptions() {
+ UriTokenizer tokenizer = new UriTokenizer("$expand=*;$filter=true;$levels=max;$orderby=false");
+ assertTrue(tokenizer.next(TokenKind.EXPAND));
+ assertTrue(tokenizer.next(TokenKind.EQ));
+ assertTrue(tokenizer.next(TokenKind.STAR));
+ assertTrue(tokenizer.next(TokenKind.SEMI));
+ assertTrue(tokenizer.next(TokenKind.FILTER));
+ assertTrue(tokenizer.next(TokenKind.EQ));
+ assertTrue(tokenizer.next(TokenKind.BooleanValue));
+ assertTrue(tokenizer.next(TokenKind.SEMI));
+ assertTrue(tokenizer.next(TokenKind.LEVELS));
+ assertTrue(tokenizer.next(TokenKind.EQ));
+ assertTrue(tokenizer.next(TokenKind.MAX));
+ assertTrue(tokenizer.next(TokenKind.SEMI));
+ assertTrue(tokenizer.next(TokenKind.ORDERBY));
+ assertTrue(tokenizer.next(TokenKind.EQ));
+ assertTrue(tokenizer.next(TokenKind.BooleanValue));
+ assertTrue(tokenizer.next(TokenKind.EOF));
+
+ tokenizer = new UriTokenizer("$search=A;$select=*;$skip=1;$top=2");
+ assertTrue(tokenizer.next(TokenKind.SEARCH));
+ assertTrue(tokenizer.next(TokenKind.EQ));
+ assertTrue(tokenizer.next(TokenKind.ODataIdentifier));
+ assertTrue(tokenizer.next(TokenKind.SEMI));
+ assertTrue(tokenizer.next(TokenKind.SELECT));
+ assertTrue(tokenizer.next(TokenKind.EQ));
+ assertTrue(tokenizer.next(TokenKind.STAR));
+ assertTrue(tokenizer.next(TokenKind.SEMI));
+ assertTrue(tokenizer.next(TokenKind.SKIP));
+ assertTrue(tokenizer.next(TokenKind.EQ));
+ assertTrue(tokenizer.next(TokenKind.IntegerValue));
+ assertTrue(tokenizer.next(TokenKind.SEMI));
+ assertTrue(tokenizer.next(TokenKind.TOP));
+ assertTrue(tokenizer.next(TokenKind.EQ));
+ assertTrue(tokenizer.next(TokenKind.IntegerValue));
+ assertTrue(tokenizer.next(TokenKind.EOF));
+ }
+
+ @Test
public void identifier() {
assertTrue(new UriTokenizer("name").next(TokenKind.ODataIdentifier));
assertTrue(new UriTokenizer("_name").next(TokenKind.ODataIdentifier));
@@ -390,11 +429,11 @@ public class UriTokenizerTest {
assertTrue(tokenizer.next(TokenKind.IntegerValue));
assertTrue(tokenizer.next(TokenKind.EOF));
- tokenizer = new UriTokenizer("1ne 2");
+ tokenizer = new UriTokenizer("-1ne 2");
assertTrue(tokenizer.next(TokenKind.IntegerValue));
assertFalse(tokenizer.next(TokenKind.NotEqualsOperator));
- tokenizer = new UriTokenizer("1 ne2");
+ tokenizer = new UriTokenizer("1 ne-2");
assertTrue(tokenizer.next(TokenKind.IntegerValue));
assertFalse(tokenizer.next(TokenKind.NotEqualsOperator));
@@ -404,6 +443,11 @@ public class UriTokenizerTest {
assertTrue(tokenizer.next(TokenKind.IntegerValue));
assertTrue(tokenizer.next(TokenKind.EOF));
+ assertTrue(new UriTokenizer("-x").next(TokenKind.MinusOperator));
+ assertFalse(new UriTokenizer("-1").next(TokenKind.MinusOperator));
+ assertFalse(new UriTokenizer("-INF").next(TokenKind.MinusOperator));
+ assertFalse(new UriTokenizer("+").next(TokenKind.MinusOperator));
+
assertFalse(new UriTokenizer("nottrue").next(TokenKind.NotOperator));
assertFalse(new UriTokenizer("no true").next(TokenKind.NotOperator));
@@ -484,6 +528,38 @@ public class UriTokenizerTest {
wrongToken(TokenKind.DescSuffix, " desc", 'D');
}
+ @Test
+ public void search() {
+ UriTokenizer tokenizer = new UriTokenizer("a AND b OR NOT \"c\" d");
+ assertTrue(tokenizer.next(TokenKind.Word));
+ assertTrue(tokenizer.next(TokenKind.AndOperatorSearch));
+ assertTrue(tokenizer.next(TokenKind.Word));
+ assertFalse(tokenizer.next(TokenKind.AndOperatorSearch));
+ assertTrue(tokenizer.next(TokenKind.OrOperatorSearch));
+ assertTrue(tokenizer.next(TokenKind.NotOperatorSearch));
+ assertTrue(tokenizer.next(TokenKind.Phrase));
+ assertTrue(tokenizer.next(TokenKind.AndOperatorSearch));
+ assertTrue(tokenizer.next(TokenKind.Word));
+ assertFalse(tokenizer.next(TokenKind.AndOperatorSearch));
+ assertFalse(tokenizer.next(TokenKind.Word));
+ assertFalse(tokenizer.next(TokenKind.Phrase));
+ assertTrue(tokenizer.next(TokenKind.EOF));
+
+ assertTrue(new UriTokenizer("\"a\\\\x\\\"\"").next(TokenKind.Phrase));
+ assertFalse(new UriTokenizer("\"a\\\"").next(TokenKind.Phrase));
+ assertFalse(new UriTokenizer("\"a\\x\"").next(TokenKind.Phrase));
+ wrongToken(TokenKind.Phrase, "\"a\"", '\\');
+
+ final String outsideBmpLetter = String.valueOf(Character.toChars(0x10330));
+ assertTrue(new UriTokenizer("\"" + outsideBmpLetter + "\"").next(TokenKind.Phrase));
+
+ assertTrue(new UriTokenizer(outsideBmpLetter).next(TokenKind.Word));
+ assertFalse(new UriTokenizer("1").next(TokenKind.Word));
+ assertFalse(new UriTokenizer("AND").next(TokenKind.Word));
+ assertFalse(new UriTokenizer("OR").next(TokenKind.Word));
+ assertFalse(new UriTokenizer("NOT").next(TokenKind.Word));
+ }
+
private void wrongToken(final TokenKind kind, final String value, final char disturbCharacter) {
assertFalse(new UriTokenizer(disturbCharacter + value).next(kind));
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/search/SearchParserAndTokenizerTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/search/SearchParserAndTokenizerTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/search/SearchParserAndTokenizerTest.java
index e028cfe..f3e50a2 100644
--- a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/search/SearchParserAndTokenizerTest.java
+++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/search/SearchParserAndTokenizerTest.java
@@ -35,7 +35,7 @@ public class SearchParserAndTokenizerTest {
assertQuery("a AND b AND c").resultsIn("{{'a' AND 'b'} AND 'c'}");
assertQuery("a OR b").resultsIn("{'a' OR 'b'}");
assertQuery("a OR b OR c").resultsIn("{{'a' OR 'b'} OR 'c'}");
-
+
assertQuery("NOT a NOT b").resultsIn("{{NOT 'a'} AND {NOT 'b'}}");
assertQuery("NOT a AND NOT b").resultsIn("{{NOT 'a'} AND {NOT 'b'}}");
assertQuery("NOT a OR NOT b").resultsIn("{{NOT 'a'} OR {NOT 'b'}}");
@@ -59,16 +59,16 @@ public class SearchParserAndTokenizerTest {
assertQuery("a AND (b OR c)").resultsIn("{'a' AND {'b' OR 'c'}}");
assertQuery("(a OR b) AND NOT c").resultsIn("{{'a' OR 'b'} AND {NOT 'c'}}");
assertQuery("(a OR B) AND (c OR d AND NOT e OR (f))")
- .resultsIn("{{'a' OR 'B'} AND {{'c' OR {'d' AND {NOT 'e'}}} OR 'f'}}");
+ .resultsIn("{{'a' OR 'B'} AND {{'c' OR {'d' AND {NOT 'e'}}} OR 'f'}}");
assertQuery("(a OR B) (c OR d NOT e OR (f))")
- .resultsIn("{{'a' OR 'B'} AND {{'c' OR {'d' AND {NOT 'e'}}} OR 'f'}}");
+ .resultsIn("{{'a' OR 'B'} AND {{'c' OR {'d' AND {NOT 'e'}}} OR 'f'}}");
assertQuery("((((a))))").resultsIn("'a'");
assertQuery("((((a)))) ((((a))))").resultsIn("{'a' AND 'a'}");
assertQuery("((((a)))) OR ((((a))))").resultsIn("{'a' OR 'a'}");
assertQuery("((((((a)))) ((((c))) OR (((C)))) ((((a))))))").resultsIn("{{'a' AND {'c' OR 'C'}} AND 'a'}");
assertQuery("((((\"a\")))) OR ((((\"a\"))))").resultsIn("{'a' OR 'a'}");
}
-
+
@Test
public void parseImplicitAnd() throws Exception {
assertQuery("a b").resultsIn("{'a' AND 'b'}");
@@ -103,7 +103,7 @@ public class SearchParserAndTokenizerTest {
assertQuery("((a AND b OR c)").resultsIn(SearchParserException.MessageKeys.MISSING_CLOSE);
assertQuery("a AND (b OR c").resultsIn(SearchParserException.MessageKeys.MISSING_CLOSE);
assertQuery("(a AND ((b OR c)").resultsIn(SearchParserException.MessageKeys.MISSING_CLOSE);
-
+
assertQuery("NOT NOT a").resultsIn(SearchParserException.MessageKeys.INVALID_NOT_OPERAND);
assertQuery("NOT (a)").resultsIn(SearchParserException.MessageKeys.TOKENIZER_EXCEPTION);
}
@@ -186,7 +186,6 @@ public class SearchParserAndTokenizerTest {
// <Input>http://serviceRoot/Products?$search=blue</Input>
assertQuery("blue").resultsIn("'blue'");
-
// below cases can not be tested here
// <TestCase Name="5.1.7 Search - on entity container" Rule="odataUri">
// <Input>http://serviceRoot/Model.Container/$all?$search=blue</Input>
@@ -194,68 +193,47 @@ public class SearchParserAndTokenizerTest {
// <Input>http://serviceRoot/$all?$search=blue</Input>
}
-
private static Validator assertQuery(String searchQuery) {
- return Validator.init(searchQuery);
+ return new Validator(searchQuery);
}
private static class Validator {
- private boolean log;
private final String searchQuery;
private Validator(String searchQuery) {
this.searchQuery = searchQuery;
}
- private static Validator init(String searchQuery) {
- return new Validator(searchQuery);
- }
-
- @SuppressWarnings("unused")
- private Validator withLogging() {
- log = true;
- return this;
- }
-
- private void resultsIn(SearchParserException.MessageKey key)
- throws SearchTokenizerException {
+ private void resultsIn(SearchParserException.MessageKey key) throws SearchTokenizerException {
try {
resultsIn(searchQuery);
} catch (SearchParserException e) {
Assert.assertEquals("SearchParserException with unexpected message '" + e.getMessage() +
"' was thrown.", key, e.getMessageKey());
- if(log) {
- System.out.println("Caught SearchParserException with message key " +
- e.getMessageKey() + " and message " + e.getMessage());
- }
return;
}
Assert.fail("SearchParserException with message key " + key.getKey() + " was not thrown.");
}
-
+
public void resultsInExpectedTerm(final String actualToken) throws SearchTokenizerException {
try {
resultsIn(searchQuery);
- } catch(SearchParserException e) {
+ } catch (SearchParserException e) {
Assert.assertEquals(SearchParserException.MessageKeys.EXPECTED_DIFFERENT_TOKEN, e.getMessageKey());
Assert.assertEquals("Expected PHRASE||WORD found: " + actualToken, e.getMessage());
}
}
-
+
private void resultsIn(String expectedSearchExpression) throws SearchTokenizerException, SearchParserException {
final SearchExpression searchExpression = getSearchExpression();
Assert.assertEquals(expectedSearchExpression, searchExpression.toString());
}
private SearchExpression getSearchExpression() throws SearchParserException, SearchTokenizerException {
- SearchParser tokenizer = new SearchParser();
- SearchOption result = tokenizer.parse(searchQuery);
+ SearchOption result = new SearchParser().parse(searchQuery);
Assert.assertNotNull(result);
final SearchExpression searchExpression = result.getSearchExpression();
Assert.assertNotNull(searchExpression);
- if (log) {
- System.out.println(searchExpression);
- }
return searchExpression;
}
}
[24/30] olingo-odata4 git commit: [OLINGO-834] $expand parser in Java
+ clean-up
Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriContext.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriContext.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriContext.java
deleted file mode 100644
index 36a0887..0000000
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriContext.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * 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.ArrayDeque;
-import java.util.Deque;
-
-import org.apache.olingo.commons.api.edm.EdmType;
-import org.apache.olingo.server.core.uri.UriInfoImpl;
-import org.apache.olingo.server.core.uri.queryoption.ExpandItemImpl;
-import org.apache.olingo.server.core.uri.queryoption.SelectItemImpl;
-
-/**
- * UriContext object used for holding information for URI parsing.
- *
- */
-public class UriContext {
-
- public static class LambdaVariable {
- public String name;
- public EdmType type;
- }
-
- /**
- * Hold all currently allowed lambda variables
- * As lambda functions can be nested there may be more than one allowed lambda variables at a time while parsing a
- * $filter or $orderby expressions.
- */
- public Deque<LambdaVariable> allowedLambdaVariables;
- /**
- * Used to stack type information for nested $expand, $filter query options and other cases.
- */
- public Deque<EdmType> contextTypes;
-
- /** Whether the context types are collections. */
- public boolean isCollection;
-
- // CHECKSTYLE:OFF (Maven checkstyle)
- /**
- * Set within method
- * {@link org.apache.olingo.server.core.uri.antlr.UriParserBaseVisitor#visitExpandItem(org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandItemContext ctx)}
- * and
- * {@link org.apache.olingo.server.core.uri.antlr.UriParserBaseVisitor#visitExpandPathExtension(org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandPathExtensionContext ctx)}
- * to allow nodes
- * deeper in the expand tree at
- * {@link org.apache.olingo.server.core.uri.antlr.UriParserBaseVisitor#visitExpandPathExtension(org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandPathExtensionContext ctx)}
- * appending path
- * segments to the currently processed {@link ExpandItemImpl}.
- */
- public ExpandItemImpl contextExpandItemPath;
- // CHECKSTYLE:ON (Maven checkstyle)
-
- //CHECKSTYLE:OFF (Maven checkstyle)
- /**
- * Set to true in method {@link UriParseTreeVisitor#visitExpandPath} right before
- * calling {@link org.apache.olingo.server.core.uri.parser.UriParseTreeVisitor#readResourcePathSegment}
- * After reading the path the variable is set back to false
- *
- * readResourcePathSegment handles all navigation properties, it depends on the context if key predicates are allowed or not.
- * In case of expand
- */
- public boolean contextVisitExpandResourcePath;
- //CHECKSTYLE:ON (Maven checkstyle)
-
- // CHECKSTYLE:OFF (Maven checkstyle)
- /**
- * Set within method
- * {@link org.apache.olingo.server.core.uri.antlr.UriParserBaseVisitor#visitSelectItem(org.apache.olingo.server.core.uri.antlr.UriParserParser.SelectItemContext ctx)}
- * to allow
- * nodes
- * deeper in the expand tree at
- * {@link org.apache.olingo.server.core.uri.antlr.UriParserBaseVisitor#visitSelectSegment(org.apache.olingo.server.core.uri.antlr.UriParserParser.SelectSegmentContext ctx)}
- * appending path segments to the
- * currently processed {@link SelectItemImpl}.
- */
- public SelectItemImpl contextSelectItem;
- // CHECKSTYLE:ON (Maven checkstyle)
- /**
- * Stores the currently processed UriInfo objects. There is one URI Info object for the resource path
- * and one for each new first member access within $filter and $orderBy options.
- */
- public UriInfoImpl contextUriInfo;
- public boolean contextReadingFunctionParameters;
-
- /**
- * Set to true if the parser operates on query part.
- */
- public boolean contextReadingQueryPart;
-
- public UriContext() {
-
- contextExpandItemPath = null;
- contextReadingFunctionParameters = false;
- contextSelectItem = null;
- contextTypes = new ArrayDeque<EdmType>();
- allowedLambdaVariables = new ArrayDeque<UriContext.LambdaVariable>();
-
- }
-}
\ No newline at end of file
[02/30] olingo-odata4 git commit: [OLINGO-834] URI resource-path
parser in Java
Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/927ecb93/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
new file mode 100644
index 0000000..87e09ad
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
@@ -0,0 +1,592 @@
+/*
+ * 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;
+
+/**
+ * <p>Simple OData URI tokenizer that works on a given string by keeping an index.</p>
+ * <p>As far as feasible, it tries to work on character basis, assuming this to be faster than string operations.
+ * Since only the index is "moved", backing out while parsing a token is easy and used throughout.
+ * There is intentionally no method to push back tokens (although it would be easy to add such a method)
+ * because this tokenizer should behave like a classical token-consuming tokenizer.</p>
+ */
+public class UriTokenizer {
+
+ public enum TokenKind {
+ EOF, // signals the end of the string to be parsed
+
+ // constant-value tokens (convention: uppercase)
+ REF,
+ VALUE,
+ COUNT,
+ CROSSJOIN,
+ OPEN,
+ CLOSE,
+ COMMA,
+ SEMI,
+ EQ,
+ NULL,
+
+ // variable-value tokens (convention: mixed case)
+ ODataIdentifier,
+ QualifiedName,
+ ParameterAliasName,
+
+ PrimitiveBooleanValue,
+ PrimitiveStringValue,
+ PrimitiveIntegerValue,
+ PrimitiveGuidValue,
+ PrimitiveDateValue,
+ PrimitiveDateTimeOffsetValue,
+ PrimitiveTimeOfDayValue,
+ PrimitiveDecimalValue,
+ PrimitiveDoubleValue,
+ PrimitiveDurationValue,
+ PrimitiveBinaryValue,
+ PrimitiveEnumValue,
+
+ jsonArrayOrObject
+ }
+
+ private final String pathSegment;
+
+ private int startIndex = 0;
+ private int index = 0;
+
+ public UriTokenizer(final String pathSegment) {
+ this.pathSegment = pathSegment == null ? "" : pathSegment;
+ }
+
+ /** Returns the string value corresponding to the last successful {@link #next(TokenKind)} call. */
+ public String getText() {
+ return pathSegment.substring(startIndex, index);
+ }
+
+ /**
+ * Tries to find a token of the given token kind at the current index.
+ * The order in which this method is called with different token kinds is important,
+ * not only for performance reasons but also if tokens can start with the same characters
+ * (e.g., a qualified name starts with an OData identifier).
+ * @param allowedTokenKind the kind of token to expect
+ * @return <code>true</code> if the token is found; <code>false</code> otherwise
+ * @see #getText()
+ */
+ public boolean next(final TokenKind allowedTokenKind) {
+ if (allowedTokenKind == null) {
+ return false;
+ }
+
+ boolean found = false;
+ final int previousIndex = index;
+ switch (allowedTokenKind) {
+ // Constants
+ case REF:
+ found = nextConstant("$ref");
+ break;
+ case VALUE:
+ found = nextConstant("$value");
+ break;
+ case COUNT:
+ found = nextConstant("$count");
+ break;
+ case CROSSJOIN:
+ found = nextConstant("$crossjoin");
+ break;
+ case OPEN:
+ found = nextCharacter('(');
+ break;
+ case CLOSE:
+ found = nextCharacter(')');
+ break;
+ case COMMA:
+ found = nextCharacter(',');
+ break;
+ case SEMI:
+ found = nextCharacter(';');
+ break;
+ case EQ:
+ found = nextCharacter('=');
+ break;
+ case NULL:
+ found = nextConstant("null");
+ break;
+ case EOF:
+ found = index >= pathSegment.length();
+ break;
+
+ // Identifiers
+ case ODataIdentifier:
+ found = nextODataIdentifier();
+ break;
+ case QualifiedName:
+ found = nextQualifiedName();
+ break;
+ case ParameterAliasName:
+ found = nextParameterAliasName();
+ break;
+
+ // Primitive Values
+ case PrimitiveBooleanValue:
+ found = nextBooleanValue();
+ break;
+ case PrimitiveStringValue:
+ found = nextStringValue();
+ break;
+ case PrimitiveIntegerValue:
+ found = nextIntegerValue(true);
+ break;
+ case PrimitiveGuidValue:
+ found = nextGuidValue();
+ break;
+ case PrimitiveDateValue:
+ found = nextDateValue();
+ break;
+ case PrimitiveDateTimeOffsetValue:
+ found = nextDateTimeOffsetValue();
+ break;
+ case PrimitiveTimeOfDayValue:
+ found = nextTimeOfDayValue();
+ break;
+ case PrimitiveDecimalValue:
+ found = nextDecimalValue();
+ break;
+ case PrimitiveDoubleValue:
+ found = nextDoubleValue();
+ break;
+ case PrimitiveDurationValue:
+ found = nextDurationValue();
+ break;
+ case PrimitiveBinaryValue:
+ found = nextBinaryValue();
+ break;
+ case PrimitiveEnumValue:
+ found = nextEnumValue();
+ break;
+
+ // Primitive Values
+ case jsonArrayOrObject:
+ found = nextJsonArrayOrObject();
+ break;
+ }
+
+ if (found) {
+ startIndex = previousIndex;
+ } else {
+ index = previousIndex;
+ }
+ return found;
+ }
+
+ private boolean nextConstant(final String constant) {
+ if (pathSegment.startsWith(constant, index)) {
+ index += constant.length();
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private boolean nextConstantIgnoreCase(final String constant) {
+ final int length = constant.length();
+ if (index + length <= pathSegment.length()
+ && constant.equalsIgnoreCase(pathSegment.substring(index, index + length))) {
+ index += length;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Moves past the given character if found; otherwise leaves the index unchanged.
+ * @return whether the given character has been found at the current index
+ */
+ private boolean nextCharacter(final char character) {
+ if (index < pathSegment.length() && pathSegment.charAt(index) == character) {
+ index++;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Moves past the next character if it is in the given character range;
+ * otherwise leaves the index unchanged.
+ * @return whether the given character has been found at the current index
+ */
+ private boolean nextCharacterRange(final char from, final char to) {
+ if (index < pathSegment.length()) {
+ final char code = pathSegment.charAt(index);
+ if (code >= from && code <= to) {
+ index++;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Moves past a digit character ('0' to '9') if found; otherwise leaves the index unchanged.
+ * @return whether a digit character has been found at the current index
+ */
+ private boolean nextDigit() {
+ return nextCharacterRange('0', '9');
+ }
+
+ /**
+ * Moves past a hexadecimal digit character ('0' to '9', 'A' to 'F', or 'a' to 'f') if found;
+ * otherwise leaves the index unchanged.
+ * @return whether a hexadecimal digit character has been found at the current index
+ */
+ private boolean nextHexDigit() {
+ return nextCharacterRange('0', '9') || nextCharacterRange('A', 'F') || nextCharacterRange('a', 'f');
+ }
+
+ /**
+ * Moves past a base64 character ('0' to '9', 'A' to 'Z', 'a' to 'z', '-', or '_') if found;
+ * otherwise leaves the index unchanged.
+ * @return whether a base64 character has been found at the current index
+ */
+ private boolean nextBase64() {
+ return nextCharacterRange('0', '9') || nextCharacterRange('A', 'Z') || nextCharacterRange('a', 'z')
+ || nextCharacter('-') || nextCharacter('_');
+ }
+
+ /**
+ * Moves past a sign character ('+' or '-') if found; otherwise leaves the index unchanged.
+ * @return whether a sign character has been found at the current index
+ */
+ private boolean nextSign() {
+ return nextCharacter('+') || nextCharacter('-');
+ }
+
+ private boolean nextODataIdentifier() {
+ int count = 0;
+ if (index < pathSegment.length()) {
+ int code = pathSegment.codePointAt(index);
+ if (Character.isUnicodeIdentifierStart(code) || code == '_') {
+ count++;
+ // Unicode characters outside of the Basic Multilingual Plane are represented as two Java characters.
+ index += Character.isSupplementaryCodePoint(code) ? 2 : 1;
+ while (index < pathSegment.length() && count < 128) {
+ code = pathSegment.codePointAt(index);
+ if (Character.isUnicodeIdentifierPart(code) && !Character.isISOControl(code)) {
+ count++;
+ // Unicode characters outside of the Basic Multilingual Plane are represented as two Java characters.
+ index += Character.isSupplementaryCodePoint(code) ? 2 : 1;
+ } else {
+ break;
+ }
+ }
+ }
+ }
+ return count > 0;
+ }
+
+ private boolean nextQualifiedName() {
+ int count = 0;
+ do {
+ if (nextODataIdentifier()) {
+ count++;
+ } else {
+ return false;
+ }
+ } while (nextCharacter('.'));
+ return count >= 2;
+ }
+
+ private boolean nextParameterAliasName() {
+ return nextCharacter('@') && nextODataIdentifier();
+ }
+
+ private boolean nextBooleanValue() {
+ return nextConstantIgnoreCase("true") || nextConstantIgnoreCase("false");
+ }
+
+ private boolean nextStringValue() {
+ if (!nextCharacter('\'')) {
+ return false;
+ }
+ while (index < pathSegment.length()) {
+ if (pathSegment.charAt(index) == '\'') {
+ // If a single quote is followed by another single quote,
+ // it represents one single quote within the string literal,
+ // otherwise it marks the end of the string literal.
+ if (index + 1 < pathSegment.length() && pathSegment.charAt(index + 1) == '\'') {
+ index++;
+ } else {
+ break;
+ }
+ }
+ index++;
+ }
+ return nextCharacter('\'');
+ }
+
+ private boolean nextIntegerValue(final boolean signed) {
+ if (signed) {
+ nextSign();
+ }
+ boolean hasDigits = false;
+ while (nextDigit()) {
+ hasDigits = true;
+ }
+ return hasDigits;
+ }
+
+ /** Finds and returns only decimal-number tokens with a fractional part.
+ * Whole numbers must be found with {@link #nextIntegerValue()}.
+ */
+ private boolean nextDecimalValue() {
+ return nextIntegerValue(true) && nextCharacter('.') && nextIntegerValue(false);
+ }
+
+ /**
+ * Finds and returns only floating-point-number tokens with an exponential part
+ * and the special three constants "NaN", "-INF", and "INF".
+ * Whole numbers must be found with {@link #nextIntegerValue()}.
+ * Decimal numbers must be found with {@link #nextDecimalValue()}.
+ */
+ private boolean nextDoubleValue() {
+ if (nextConstant("NaN") || nextConstant("-INF") || nextConstant("INF")) {
+ return true;
+ } else {
+ if (!nextIntegerValue(true)) {
+ return false;
+ }
+ if (nextCharacter('.') && !nextIntegerValue(false)) {
+ return false;
+ }
+ return (nextCharacter('E') || nextCharacter('e')) && nextIntegerValue(true);
+ }
+ }
+
+ private boolean nextGuidValue() {
+ return nextHexDigit() && nextHexDigit() && nextHexDigit() && nextHexDigit()
+ && nextHexDigit() && nextHexDigit() && nextHexDigit() && nextHexDigit()
+ && nextCharacter('-')
+ && nextHexDigit() && nextHexDigit() && nextHexDigit() && nextHexDigit()
+ && nextCharacter('-')
+ && nextHexDigit() && nextHexDigit() && nextHexDigit() && nextHexDigit()
+ && nextCharacter('-')
+ && nextHexDigit() && nextHexDigit() && nextHexDigit() && nextHexDigit()
+ && nextCharacter('-')
+ && nextHexDigit() && nextHexDigit() && nextHexDigit() && nextHexDigit()
+ && nextHexDigit() && nextHexDigit() && nextHexDigit() && nextHexDigit()
+ && nextHexDigit() && nextHexDigit() && nextHexDigit() && nextHexDigit();
+ }
+
+ private boolean nextYear() {
+ nextCharacter('-');
+ if (nextCharacter('0')) {
+ return nextDigit() && nextDigit() && nextDigit();
+ } else if (nextCharacterRange('1', '9')) {
+ int count = 0;
+ while (nextDigit()) {
+ count++;
+ }
+ return count >= 3;
+ } else {
+ return false;
+ }
+ }
+
+ private boolean nextDateValue() {
+ return nextYear()
+ && nextCharacter('-')
+ && (nextCharacter('0') && nextCharacterRange('1', '9')
+ || nextCharacter('1') && nextCharacterRange('0', '2'))
+ && nextCharacter('-')
+ && (nextCharacter('0') && nextCharacterRange('1', '9')
+ || nextCharacterRange('1', '2') && nextDigit()
+ || nextCharacter('3') && nextCharacterRange('0', '1'));
+ }
+
+ private boolean nextHours() {
+ return nextCharacterRange('0', '1') && nextDigit()
+ || nextCharacter('2') && nextCharacterRange('0', '3');
+ }
+
+ private boolean nextMinutesOrSeconds() {
+ return nextCharacterRange('0', '5') && nextDigit();
+ }
+
+ private boolean nextDateTimeOffsetValue() {
+ return nextDateValue()
+ && (nextCharacter('T') || nextCharacter('t'))
+ && nextTimeOfDayValue()
+ && (nextCharacter('Z')
+ || nextCharacter('z')
+ || nextSign() && nextHours() && nextCharacter(':') && nextMinutesOrSeconds());
+ }
+
+ private boolean nextTimeOfDayValue() {
+ if (nextHours() && nextCharacter(':') && nextMinutesOrSeconds()) {
+ if (nextCharacter(':')) {
+ if (nextMinutesOrSeconds()) {
+ if (nextCharacter('.') && !nextIntegerValue(false)) {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private boolean nextDurationValue() {
+ if (nextConstantIgnoreCase("duration") && nextCharacter('\'')) {
+ nextSign();
+ if (nextCharacter('P') || nextCharacter('p')) {
+ if (nextIntegerValue(false)) {
+ if (!(nextCharacter('D') || nextCharacter('d'))) {
+ return false;
+ }
+ }
+ if (nextCharacter('T') || nextCharacter('t')) {
+ boolean hasNumber = false;
+ if (nextIntegerValue(false)) {
+ hasNumber = true;
+ if (nextCharacter('H') || nextCharacter('h')) {
+ hasNumber = false;
+ }
+ }
+ if (hasNumber || nextIntegerValue(false)) {
+ hasNumber = true;
+ if (nextCharacter('M') || nextCharacter('m')) {
+ hasNumber = false;
+ }
+ }
+ if (hasNumber || nextIntegerValue(false)) {
+ if (nextCharacter('.')) {
+ if (!nextIntegerValue(false)) {
+ return false;
+ }
+ }
+ if (!(nextCharacter('S') || nextCharacter('s'))) {
+ return false;
+ }
+ }
+ }
+ return nextCharacter('\'');
+ }
+ }
+ return false;
+ }
+
+ private boolean nextBinaryValue() {
+ if (nextConstantIgnoreCase("binary") && nextCharacter('\'')) {
+ int lastGoodIndex = index;
+ while (nextBase64() && nextBase64() && nextBase64() && nextBase64()) {
+ lastGoodIndex += 4;
+ }
+ index = lastGoodIndex;
+ if (nextBase64() && nextBase64()
+ && (nextCharacter('A') || nextCharacter('E') || nextCharacter('I') || nextCharacter('M')
+ || nextCharacter('Q') || nextCharacter('U') || nextCharacter('Y') || nextCharacter('c')
+ || nextCharacter('g') || nextCharacter('k') || nextCharacter('o') || nextCharacter('s')
+ || nextCharacter('w') || nextCharacter('0') || nextCharacter('4') || nextCharacter('8'))) {
+ nextCharacter('=');
+ } else {
+ index = lastGoodIndex;
+ if (nextBase64()) {
+ if (nextCharacter('A') || nextCharacter('Q') || nextCharacter('g') || nextCharacter('w')) {
+ nextConstant("==");
+ } else {
+ return false;
+ }
+ }
+ }
+ return nextCharacter('\'');
+ }
+ return false;
+ }
+
+ private boolean nextEnumValue() {
+ if (nextQualifiedName() && nextCharacter('\'')) {
+ do {
+ if (!(nextODataIdentifier() || nextIntegerValue(true))) {
+ return false;
+ }
+ } while (nextCharacter(','));
+ return nextCharacter('\'');
+ }
+ return false;
+ }
+
+ private boolean nextJsonString() {
+ if (nextCharacter('"')) {
+ do {
+ if (nextCharacter('\\')) {
+ if (!(nextCharacter('b') || nextCharacter('t')
+ || nextCharacter('n') || nextCharacter('f') || nextCharacter('r')
+ || nextCharacter('"') || nextCharacter('/') || nextCharacter('\\')
+ || nextCharacter('u') && nextHexDigit() && nextHexDigit() && nextHexDigit() && nextHexDigit())) {
+ return false;
+ }
+ } else if (nextCharacter('"')) {
+ return true;
+ } else {
+ index++;
+ }
+ } while (index < pathSegment.length());
+ return false;
+ }
+ return false;
+ }
+
+ private boolean nextJsonValue() {
+ return nextConstant("null") || nextConstant("true") || nextConstant("false")
+ // If a double or decimal number is not found, the index must be reset; the internal methods don't do that.
+ || next(TokenKind.PrimitiveDoubleValue) || next(TokenKind.PrimitiveDecimalValue) || nextIntegerValue(true)
+ || nextJsonString()
+ || nextJsonArrayOrObject();
+ }
+
+ private boolean nextJsonMember() {
+ return nextJsonString() && nextCharacter(':') && nextJsonValue();
+ }
+
+ private boolean nextJsonArrayOrObject() {
+ if (nextCharacter('[')) {
+ if (nextJsonValue()) {
+ while (nextCharacter(',')) {
+ if (!nextJsonValue()) {
+ return false;
+ }
+ }
+ }
+ return nextCharacter(']');
+ } else if (nextCharacter('{')) {
+ if (nextJsonMember()) {
+ while (nextCharacter(',')) {
+ if (!nextJsonMember()) {
+ return false;
+ }
+ }
+ }
+ return nextCharacter('}');
+ } else {
+ return false;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/927ecb93/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java
index f840e8e..3ccd97a 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java
@@ -24,7 +24,6 @@ import java.util.Map;
import org.apache.olingo.commons.api.edm.EdmEntityType;
import org.apache.olingo.commons.api.edm.EdmFunction;
-import org.apache.olingo.commons.api.edm.EdmFunctionImport;
import org.apache.olingo.commons.api.edm.EdmKeyPropertyRef;
import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
@@ -223,14 +222,7 @@ public class UriValidator {
private RowIndexForUriType rowIndexForResourceKind(final UriInfo uriInfo) throws UriValidationException {
RowIndexForUriType idx;
-
- final int nonComposableFunctionIndex = getIndexOfLastNonComposableFunction(uriInfo);
- if(nonComposableFunctionIndex != -1 && (uriInfo.getUriResourceParts().size() - 1) > nonComposableFunctionIndex) {
- throw new UriValidationException("Non composable functions followed by further resource parts are not allowed",
- UriValidationException.MessageKeys.UNALLOWED_RESOURCE_PATH,
- uriInfo.getUriResourceParts().get(nonComposableFunctionIndex + 1).getSegmentValue());
- }
-
+
int lastPathSegmentIndex = uriInfo.getUriResourceParts().size() - 1;
UriResource lastPathSegment = uriInfo.getUriResourceParts().get(lastPathSegmentIndex);
@@ -249,11 +241,7 @@ public class UriValidator {
idx = rowIndexForEntitySet(lastPathSegment);
break;
case function:
- if(nonComposableFunctionIndex == -1) {
- idx = rowIndexForFunction(lastPathSegment);
- } else {
- idx = RowIndexForUriType.none;
- }
+ idx = rowIndexForFunction(lastPathSegment);
break;
case primitiveProperty:
idx = rowIndexForPrimitiveProperty(lastPathSegment);
@@ -278,21 +266,6 @@ public class UriValidator {
return idx;
}
- private int getIndexOfLastNonComposableFunction(final UriInfo uriInfo) {
- for(int i = 0; i < uriInfo.getUriResourceParts().size(); i++) {
- final UriResource resourcePath = uriInfo.getUriResourceParts().get(i);
-
- if(resourcePath instanceof UriResourceFunction) {
- final UriResourceFunction resourceFuntion = (UriResourceFunction) resourcePath;
- if(!resourceFuntion.getFunction().isComposable()) {
- return i;
- }
- }
- }
-
- return -1;
- }
-
private RowIndexForUriType rowIndexForValue(final UriInfo uriInfo) throws UriValidationException {
RowIndexForUriType idx;
int secondLastPathSegmentIndex = uriInfo.getUriResourceParts().size() - 2;
@@ -309,9 +282,7 @@ public class UriValidator {
break;
case function:
UriResourceFunction uriFunction = (UriResourceFunction) secondLastPathSegment;
- final EdmFunctionImport functionImport = uriFunction.getFunctionImport();
- final EdmFunction function = functionImport == null ?
- uriFunction.getFunction() : functionImport.getUnboundFunctions().get(0);
+ final EdmFunction function = uriFunction.getFunction();
idx = function.getReturnType().getType().getKind() == EdmTypeKind.ENTITY ?
RowIndexForUriType.mediaStream : RowIndexForUriType.propertyPrimitiveValue;
break;
@@ -351,32 +322,33 @@ public class UriValidator {
}
private RowIndexForUriType rowIndexForFunction(final UriResource lastPathSegment) throws UriValidationException {
- RowIndexForUriType idx;
- UriResourceFunction urf = (UriResourceFunction) lastPathSegment;
- EdmReturnType rt = urf.getFunction().getReturnType();
+ final UriResourceFunction uriFunction = (UriResourceFunction) lastPathSegment;
+ final EdmReturnType returnType = uriFunction.getFunction().getReturnType();
- if(!urf.getFunction().isComposable()) {
+ if (!uriFunction.getFunction().isComposable()) {
return RowIndexForUriType.none;
}
-
-
- switch (rt.getType().getKind()) {
+
+ RowIndexForUriType idx;
+ switch (returnType.getType().getKind()) {
case ENTITY:
- idx = rt.isCollection() && urf.getKeyPredicates().isEmpty() ?
+ idx = returnType.isCollection() && uriFunction.getKeyPredicates().isEmpty() ?
RowIndexForUriType.entitySet : RowIndexForUriType.entity;
break;
case PRIMITIVE:
case ENUM:
case DEFINITION:
- idx = rt.isCollection() ? RowIndexForUriType.propertyPrimitiveCollection : RowIndexForUriType.propertyPrimitive;
+ idx = returnType.isCollection() ? RowIndexForUriType.propertyPrimitiveCollection :
+ RowIndexForUriType.propertyPrimitive;
break;
case COMPLEX:
- idx = rt.isCollection() ? RowIndexForUriType.propertyComplexCollection : RowIndexForUriType.propertyComplex;
+ idx = returnType.isCollection() ? RowIndexForUriType.propertyComplexCollection :
+ RowIndexForUriType.propertyComplex;
break;
default:
- throw new UriValidationException("Unsupported function return type: " + rt.getType().getKind(),
+ throw new UriValidationException("Unsupported function return type: " + returnType.getType().getKind(),
UriValidationException.MessageKeys.UNSUPPORTED_FUNCTION_RETURN_TYPE,
- rt.getType().getKind().toString());
+ returnType.getType().getKind().toString());
}
return idx;
@@ -447,9 +419,7 @@ public class UriValidator {
break;
case function:
final UriResourceFunction uriFunction = (UriResourceFunction) secondLastPathSegment;
- final EdmFunctionImport functionImport = uriFunction.getFunctionImport();
- final EdmFunction function = functionImport == null ?
- uriFunction.getFunction() : functionImport.getUnboundFunctions().get(0);
+ final EdmFunction function = uriFunction.getFunction();
final EdmType returnType = function.getReturnType().getType();
switch (returnType.getKind()) {
case ENTITY:
@@ -560,8 +530,8 @@ public class UriValidator {
private void validateParameters(final UriInfo uriInfo) throws UriValidationException {
for (UriResource pathSegment : uriInfo.getUriResourceParts()) {
final boolean isFunction = pathSegment.getKind() == UriResourceKind.function;
-
- if(isFunction) {
+
+ if (isFunction) {
final UriResourceFunction functionPathSegement = (UriResourceFunction) pathSegment;
final EdmFunction edmFuntion = functionPathSegement.getFunction();
@@ -613,7 +583,7 @@ public class UriValidator {
for (UriResource pathSegment : uriInfo.getUriResourceParts()) {
final boolean isEntitySet = pathSegment.getKind() == UriResourceKind.entitySet;
final boolean isEntityColFunction = isEntityColFunction(pathSegment);
-
+
if (isEntitySet || pathSegment.getKind() == UriResourceKind.navigationProperty || isEntityColFunction) {
final List<UriParameter> keyPredicates = isEntitySet ?
((UriResourceEntitySet) pathSegment).getKeyPredicates() :
@@ -680,7 +650,7 @@ public class UriValidator {
}
private boolean isEntityColFunction(final UriResource pathSegment) {
- if(pathSegment.getKind() == UriResourceKind.function) {
+ if (pathSegment.getKind() == UriResourceKind.function) {
final UriResourceFunction resourceFunction = (UriResourceFunction) pathSegment;
final EdmReturnType returnType = resourceFunction.getFunction().getReturnType();
@@ -689,7 +659,7 @@ public class UriValidator {
return false;
}
}
-
+
private void validatePropertyOperations(final UriInfo uriInfo, final HttpMethod method)
throws UriValidationException {
final List<UriResource> parts = uriInfo.getUriResourceParts();
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/927ecb93/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java
new file mode 100644
index 0000000..a9e97ce
--- /dev/null
+++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java
@@ -0,0 +1,369 @@
+/*
+ * 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind;
+import org.junit.Test;
+
+public class UriTokenizerTest {
+
+ @Test
+ public void nullOK() {
+ assertFalse(new UriTokenizer(null).next(null));
+ assertTrue(new UriTokenizer(null).next(TokenKind.EOF));
+ }
+
+ @Test
+ public void constants() {
+ final UriTokenizer tokenizer = new UriTokenizer("$ref");
+ assertTrue(tokenizer.next(TokenKind.REF));
+ assertEquals("$ref", tokenizer.getText());
+ assertTrue(tokenizer.next(TokenKind.EOF));
+ assertTrue(tokenizer.next(TokenKind.EOF));
+
+ assertTrue(new UriTokenizer("$value").next(TokenKind.VALUE));
+ assertTrue(new UriTokenizer("$count").next(TokenKind.COUNT));
+ assertTrue(new UriTokenizer("$crossjoin").next(TokenKind.CROSSJOIN));
+ assertTrue(new UriTokenizer("null").next(TokenKind.NULL));
+
+ wrongToken(TokenKind.REF, "$ref", 'x');
+ }
+
+ @Test
+ public void sequence() {
+ final UriTokenizer tokenizer = new UriTokenizer("(A=1,B=2);");
+ assertTrue(tokenizer.next(TokenKind.OPEN));
+ assertFalse(tokenizer.next(TokenKind.OPEN));
+ assertTrue(tokenizer.next(TokenKind.ODataIdentifier));
+ assertEquals("A", tokenizer.getText());
+ assertTrue(tokenizer.next(TokenKind.EQ));
+ assertTrue(tokenizer.next(TokenKind.PrimitiveIntegerValue));
+ assertEquals("1", tokenizer.getText());
+ assertTrue(tokenizer.next(TokenKind.COMMA));
+ assertTrue(tokenizer.next(TokenKind.ODataIdentifier));
+ assertEquals("B", tokenizer.getText());
+ assertTrue(tokenizer.next(TokenKind.EQ));
+ assertTrue(tokenizer.next(TokenKind.PrimitiveIntegerValue));
+ assertEquals("2", tokenizer.getText());
+ assertFalse(tokenizer.next(TokenKind.EOF));
+ assertTrue(tokenizer.next(TokenKind.CLOSE));
+ assertTrue(tokenizer.next(TokenKind.SEMI));
+ assertTrue(tokenizer.next(TokenKind.EOF));
+ }
+
+ @Test
+ public void identifier() {
+ assertTrue(new UriTokenizer("name").next(TokenKind.ODataIdentifier));
+ assertTrue(new UriTokenizer("_name").next(TokenKind.ODataIdentifier));
+ assertFalse(new UriTokenizer("1name").next(TokenKind.ODataIdentifier));
+ assertFalse(new UriTokenizer("").next(TokenKind.ODataIdentifier));
+
+ final String outsideBmpLetter = String.valueOf(Character.toChars(0x10330));
+ UriTokenizer tokenizer = new UriTokenizer(
+ outsideBmpLetter + "name1\u0300a\u0600b\uFE4F" + outsideBmpLetter + "end\b");
+ assertTrue(tokenizer.next(TokenKind.ODataIdentifier));
+ assertEquals(outsideBmpLetter + "name1\u0300a\u0600b\uFE4F" + outsideBmpLetter + "end", tokenizer.getText());
+
+ // Identifiers consist of up to 128 characters. Check that the identifier does not have more characters.
+ final String name = "Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch"; // Do you know this village?
+ tokenizer = new UriTokenizer(name + '_' + name + "_0123456789X");
+ assertTrue(tokenizer.next(TokenKind.ODataIdentifier));
+ assertEquals(name + '_' + name + "_0123456789", tokenizer.getText());
+ tokenizer.next(TokenKind.ODataIdentifier);
+ assertEquals("X", tokenizer.getText());
+
+ wrongToken(TokenKind.ODataIdentifier, "_", '.');
+ wrongToken(TokenKind.ODataIdentifier, "_", ',');
+ }
+
+ @Test
+ public void qualifiedName() {
+ assertTrue(new UriTokenizer("namespace.name").next(TokenKind.QualifiedName));
+
+ final UriTokenizer tokenizer = new UriTokenizer("multi.part.namespace.name");
+ assertTrue(tokenizer.next(TokenKind.QualifiedName));
+ assertTrue(tokenizer.next(TokenKind.EOF));
+
+ assertFalse(new UriTokenizer("name").next(TokenKind.QualifiedName));
+ assertFalse(new UriTokenizer("namespace..name").next(TokenKind.QualifiedName));
+ assertFalse(new UriTokenizer("").next(TokenKind.QualifiedName));
+ wrongToken(TokenKind.QualifiedName, "namespace._", ',');
+ }
+
+ @Test
+ public void alias() {
+ assertTrue(new UriTokenizer("@name").next(TokenKind.ParameterAliasName));
+ assertTrue(new UriTokenizer("@_name").next(TokenKind.ParameterAliasName));
+ assertFalse(new UriTokenizer("name").next(TokenKind.ParameterAliasName));
+ assertFalse(new UriTokenizer("@").next(TokenKind.ParameterAliasName));
+ assertFalse(new UriTokenizer("@1").next(TokenKind.ParameterAliasName));
+ }
+
+ @Test
+ public void booleanValue() {
+ assertTrue(new UriTokenizer("true").next(TokenKind.PrimitiveBooleanValue));
+ assertTrue(new UriTokenizer("tRuE").next(TokenKind.PrimitiveBooleanValue));
+ assertTrue(new UriTokenizer("false").next(TokenKind.PrimitiveBooleanValue));
+ assertTrue(new UriTokenizer("False").next(TokenKind.PrimitiveBooleanValue));
+
+ wrongToken(TokenKind.PrimitiveBooleanValue, "true", 'x');
+ }
+
+ @Test
+ public void string() {
+ assertTrue(new UriTokenizer("'ABC'").next(TokenKind.PrimitiveStringValue));
+ assertTrue(new UriTokenizer("'€\uFDFC'").next(TokenKind.PrimitiveStringValue));
+ assertTrue(new UriTokenizer('\'' + String.valueOf(Character.toChars(0x1F603)) + '\'')
+ .next(TokenKind.PrimitiveStringValue));
+
+ final UriTokenizer tokenizer = new UriTokenizer("'AB''''C'''D");
+ assertTrue(tokenizer.next(TokenKind.PrimitiveStringValue));
+ assertEquals("'AB''''C'''", tokenizer.getText());
+ assertTrue(tokenizer.next(TokenKind.ODataIdentifier));
+ assertEquals("D", tokenizer.getText());
+
+ assertFalse(new UriTokenizer("A").next(TokenKind.PrimitiveStringValue));
+ assertFalse(new UriTokenizer("'A").next(TokenKind.PrimitiveStringValue));
+ }
+
+ @Test
+ public void integer() {
+ assertTrue(new UriTokenizer("1").next(TokenKind.PrimitiveIntegerValue));
+ assertTrue(new UriTokenizer("1.").next(TokenKind.PrimitiveIntegerValue));
+ assertFalse(new UriTokenizer(".1").next(TokenKind.PrimitiveIntegerValue));
+ assertTrue(new UriTokenizer("-1").next(TokenKind.PrimitiveIntegerValue));
+ assertTrue(new UriTokenizer("1234567890").next(TokenKind.PrimitiveIntegerValue));
+ }
+
+ @Test
+ public void guid() {
+ assertTrue(new UriTokenizer("12345678-abcd-ef12-1234-567890ABCDEF").next(TokenKind.PrimitiveGuidValue));
+ wrongToken(TokenKind.PrimitiveGuidValue, "12345678-1234-1234-1234-123456789ABC", 'G');
+ }
+
+ @Test
+ public void date() {
+ assertTrue(new UriTokenizer("12345-12-25").next(TokenKind.PrimitiveDateValue));
+ assertTrue(new UriTokenizer("-0001-12-24").next(TokenKind.PrimitiveDateValue));
+ assertFalse(new UriTokenizer("1234-13-01").next(TokenKind.PrimitiveDateValue));
+ assertFalse(new UriTokenizer("1234-12-32").next(TokenKind.PrimitiveDateValue));
+ assertFalse(new UriTokenizer("123-01-01").next(TokenKind.PrimitiveDateValue));
+ assertFalse(new UriTokenizer("1234-00-01").next(TokenKind.PrimitiveDateValue));
+ assertFalse(new UriTokenizer("1234-01-00").next(TokenKind.PrimitiveDateValue));
+ wrongToken(TokenKind.PrimitiveDateValue, "2000-12-29", 'A');
+ wrongToken(TokenKind.PrimitiveDateValue, "0001-01-01", 'A');
+ wrongToken(TokenKind.PrimitiveDateValue, "-12345-01-31", 'A');
+ }
+
+ @Test
+ public void dateTimeOffset() {
+ assertTrue(new UriTokenizer("1234-12-25T11:12:13.456Z").next(TokenKind.PrimitiveDateTimeOffsetValue));
+ assertTrue(new UriTokenizer("-1234-12-25t01:12z").next(TokenKind.PrimitiveDateTimeOffsetValue));
+ assertTrue(new UriTokenizer("-1234-12-25T21:22:23+01:00").next(TokenKind.PrimitiveDateTimeOffsetValue));
+ assertTrue(new UriTokenizer("1234-12-25T11:12:13-00:30").next(TokenKind.PrimitiveDateTimeOffsetValue));
+ assertFalse(new UriTokenizer("1234-10-01").next(TokenKind.PrimitiveDateTimeOffsetValue));
+ wrongToken(TokenKind.PrimitiveDateTimeOffsetValue, "-1234-12-25T11:12:13.456+01:00", 'P');
+ }
+
+ @Test
+ public void timeOfDay() {
+ assertTrue(new UriTokenizer("11:12:13").next(TokenKind.PrimitiveTimeOfDayValue));
+ assertTrue(new UriTokenizer("11:12:13.456").next(TokenKind.PrimitiveTimeOfDayValue));
+ assertFalse(new UriTokenizer("24:00:00").next(TokenKind.PrimitiveTimeOfDayValue));
+ assertFalse(new UriTokenizer("01:60:00").next(TokenKind.PrimitiveTimeOfDayValue));
+ assertFalse(new UriTokenizer("01:00:60").next(TokenKind.PrimitiveTimeOfDayValue));
+ assertFalse(new UriTokenizer("01:00:00.").next(TokenKind.PrimitiveTimeOfDayValue));
+ assertFalse(new UriTokenizer("0:02:03").next(TokenKind.PrimitiveTimeOfDayValue));
+ assertFalse(new UriTokenizer("01:0:03").next(TokenKind.PrimitiveTimeOfDayValue));
+ assertFalse(new UriTokenizer("01:02:0").next(TokenKind.PrimitiveTimeOfDayValue));
+ wrongToken(TokenKind.PrimitiveTimeOfDayValue, "11:12", '-');
+ }
+
+ @Test
+ public void decimal() {
+ assertTrue(new UriTokenizer("1.2").next(TokenKind.PrimitiveDecimalValue));
+ assertFalse(new UriTokenizer(".1").next(TokenKind.PrimitiveDecimalValue));
+ assertTrue(new UriTokenizer("-12.34").next(TokenKind.PrimitiveDecimalValue));
+ assertTrue(new UriTokenizer("1234567890.0123456789").next(TokenKind.PrimitiveDecimalValue));
+ assertFalse(new UriTokenizer("0,1").next(TokenKind.PrimitiveDecimalValue));
+ assertFalse(new UriTokenizer("0..1").next(TokenKind.PrimitiveDecimalValue));
+ }
+
+ @Test
+ public void doubleValue() {
+ assertTrue(new UriTokenizer("NaN").next(TokenKind.PrimitiveDoubleValue));
+ assertTrue(new UriTokenizer("-INF").next(TokenKind.PrimitiveDoubleValue));
+ assertTrue(new UriTokenizer("INF").next(TokenKind.PrimitiveDoubleValue));
+ assertFalse(new UriTokenizer("inf").next(TokenKind.PrimitiveDoubleValue));
+ assertTrue(new UriTokenizer("1.2E3").next(TokenKind.PrimitiveDoubleValue));
+ assertTrue(new UriTokenizer("-12.34e-05").next(TokenKind.PrimitiveDoubleValue));
+ assertTrue(new UriTokenizer("1E2").next(TokenKind.PrimitiveDoubleValue));
+ assertFalse(new UriTokenizer("1.E2").next(TokenKind.PrimitiveDoubleValue));
+ wrongToken(TokenKind.PrimitiveDoubleValue, "-12.34E+5", 'i');
+ }
+
+ @Test
+ public void duration() {
+ assertTrue(new UriTokenizer("duration'P'").next(TokenKind.PrimitiveDurationValue));
+ assertTrue(new UriTokenizer("DURATION'P1D'").next(TokenKind.PrimitiveDurationValue));
+ assertTrue(new UriTokenizer("duration'PT'").next(TokenKind.PrimitiveDurationValue));
+ assertTrue(new UriTokenizer("duration'PT1H'").next(TokenKind.PrimitiveDurationValue));
+ assertTrue(new UriTokenizer("duration'pt1M'").next(TokenKind.PrimitiveDurationValue));
+ assertTrue(new UriTokenizer("duration'PT1S'").next(TokenKind.PrimitiveDurationValue));
+ assertTrue(new UriTokenizer("duration'PT1.2s'").next(TokenKind.PrimitiveDurationValue));
+ assertTrue(new UriTokenizer("duration'-p1dt2h3m4.5s'").next(TokenKind.PrimitiveDurationValue));
+ assertFalse(new UriTokenizer("-p1dt2h3m4.5s").next(TokenKind.PrimitiveDurationValue));
+ assertFalse(new UriTokenizer("duration'-p1dt2h3m4.5s").next(TokenKind.PrimitiveDurationValue));
+ assertFalse(new UriTokenizer("duration'2h3m4s'").next(TokenKind.PrimitiveDurationValue));
+ wrongToken(TokenKind.PrimitiveDurationValue, "duration'P1DT2H3M4.5S'", ':');
+ }
+
+ @Test
+ public void binary() {
+ assertTrue(new UriTokenizer("binary''").next(TokenKind.PrimitiveBinaryValue));
+ assertTrue(new UriTokenizer("Binary'bm93'").next(TokenKind.PrimitiveBinaryValue));
+
+ // all cases with three base64 characters (and one fill character) at the end
+ assertTrue(new UriTokenizer("binary'QUA='").next(TokenKind.PrimitiveBinaryValue));
+ assertTrue(new UriTokenizer("binary'QUE='").next(TokenKind.PrimitiveBinaryValue));
+ assertTrue(new UriTokenizer("binary'QUI='").next(TokenKind.PrimitiveBinaryValue));
+ assertTrue(new UriTokenizer("binary'QUM='").next(TokenKind.PrimitiveBinaryValue));
+ assertTrue(new UriTokenizer("binary'QUQ='").next(TokenKind.PrimitiveBinaryValue));
+ assertTrue(new UriTokenizer("binary'QUU='").next(TokenKind.PrimitiveBinaryValue));
+ assertTrue(new UriTokenizer("binary'QUY='").next(TokenKind.PrimitiveBinaryValue));
+ assertTrue(new UriTokenizer("binary'QUc='").next(TokenKind.PrimitiveBinaryValue));
+ assertTrue(new UriTokenizer("binary'QUg='").next(TokenKind.PrimitiveBinaryValue));
+ assertTrue(new UriTokenizer("binary'QUk='").next(TokenKind.PrimitiveBinaryValue));
+ assertTrue(new UriTokenizer("binary'QUo='").next(TokenKind.PrimitiveBinaryValue));
+ assertTrue(new UriTokenizer("binary'QUs='").next(TokenKind.PrimitiveBinaryValue));
+ assertTrue(new UriTokenizer("binary'QUw='").next(TokenKind.PrimitiveBinaryValue));
+ assertTrue(new UriTokenizer("binary'QU0='").next(TokenKind.PrimitiveBinaryValue));
+ assertTrue(new UriTokenizer("binary'QU4='").next(TokenKind.PrimitiveBinaryValue));
+ assertTrue(new UriTokenizer("binary'QU8='").next(TokenKind.PrimitiveBinaryValue));
+ assertFalse(new UriTokenizer("binary'QUB='").next(TokenKind.PrimitiveBinaryValue));
+
+ // all cases with two base64 characters (and two fill characters) at the end
+ assertTrue(new UriTokenizer("BINARY'VGVzdA=='").next(TokenKind.PrimitiveBinaryValue));
+ assertTrue(new UriTokenizer("binary'U-RnZQ=='").next(TokenKind.PrimitiveBinaryValue));
+ assertTrue(new UriTokenizer("binary'Yg=='").next(TokenKind.PrimitiveBinaryValue));
+ assertTrue(new UriTokenizer("binary'Yw=='").next(TokenKind.PrimitiveBinaryValue));
+
+ // without optional fill character
+ assertTrue(new UriTokenizer("binary'T0RhdGE'").next(TokenKind.PrimitiveBinaryValue));
+
+ // special character '_' (the other, '-', already has been used above)
+ assertTrue(new UriTokenizer("binary'V_ZydGVy'").next(TokenKind.PrimitiveBinaryValue));
+
+ wrongToken(TokenKind.PrimitiveBinaryValue, "binary'VGVzdA=='", '+');
+ }
+
+ @Test
+ public void enumValue() {
+ assertTrue(new UriTokenizer("namespace.name'value'").next(TokenKind.PrimitiveEnumValue));
+ assertTrue(new UriTokenizer("namespace.name'flag1,flag2,-3'").next(TokenKind.PrimitiveEnumValue));
+ assertFalse(new UriTokenizer("namespace.name'1flag'").next(TokenKind.PrimitiveEnumValue));
+ assertFalse(new UriTokenizer("namespace.name'flag1,,flag2'").next(TokenKind.PrimitiveEnumValue));
+ assertFalse(new UriTokenizer("namespace.name',value'").next(TokenKind.PrimitiveEnumValue));
+ assertFalse(new UriTokenizer("namespace.name'value,'").next(TokenKind.PrimitiveEnumValue));
+ assertFalse(new UriTokenizer("namespace.name''").next(TokenKind.PrimitiveEnumValue));
+ assertFalse(new UriTokenizer("'1'").next(TokenKind.PrimitiveEnumValue));
+ assertFalse(new UriTokenizer("1").next(TokenKind.PrimitiveEnumValue));
+ wrongToken(TokenKind.PrimitiveEnumValue, "namespace.name'_1,_2,3'", ';');
+ }
+
+ @Test
+ public void json() {
+ // Empty string or JSON values are not allowed.
+ assertFalse(new UriTokenizer("").next(TokenKind.jsonArrayOrObject));
+ assertFalse(new UriTokenizer("1").next(TokenKind.jsonArrayOrObject));
+
+ // object with values
+ assertTrue(new UriTokenizer("{}").next(TokenKind.jsonArrayOrObject));
+ assertTrue(new UriTokenizer("{\"name\":0}").next(TokenKind.jsonArrayOrObject));
+ assertTrue(new UriTokenizer("{\"name\":true}").next(TokenKind.jsonArrayOrObject));
+ assertTrue(new UriTokenizer("{\"name\":false}").next(TokenKind.jsonArrayOrObject));
+ assertTrue(new UriTokenizer("{\"name\":null}").next(TokenKind.jsonArrayOrObject));
+ assertTrue(new UriTokenizer("{\"name\":\"value\"}").next(TokenKind.jsonArrayOrObject));
+ assertTrue(new UriTokenizer("{\"name\":\"value\",\"name2\":null}").next(TokenKind.jsonArrayOrObject));
+
+ // array with values
+ assertTrue(new UriTokenizer("[]").next(TokenKind.jsonArrayOrObject));
+ assertTrue(new UriTokenizer("[1]").next(TokenKind.jsonArrayOrObject));
+ assertTrue(new UriTokenizer("[true]").next(TokenKind.jsonArrayOrObject));
+ assertTrue(new UriTokenizer("[false]").next(TokenKind.jsonArrayOrObject));
+ assertTrue(new UriTokenizer("[null]").next(TokenKind.jsonArrayOrObject));
+ assertTrue(new UriTokenizer("[\"value\"]").next(TokenKind.jsonArrayOrObject));
+ assertTrue(new UriTokenizer("[\"\"]").next(TokenKind.jsonArrayOrObject));
+ assertTrue(new UriTokenizer("[\"\\b\\t\\f\\r\\nn\\/\\\\x\\uFE4Fu\\\"\"]").next(TokenKind.jsonArrayOrObject));
+ assertTrue(new UriTokenizer("[1,2.0,3.4E5]").next(TokenKind.jsonArrayOrObject));
+ assertTrue(new UriTokenizer("[\"value\",null]").next(TokenKind.jsonArrayOrObject));
+
+ // nesting
+ assertTrue(new UriTokenizer("[{\"name\":\"value\"},{\"name\":\"value2\"}]").next(TokenKind.jsonArrayOrObject));
+ assertTrue(new UriTokenizer("{\"name\":{\"name2\":\"value\"}}").next(TokenKind.jsonArrayOrObject));
+
+ // unbalanced opening and closing
+ assertFalse(new UriTokenizer("{").next(TokenKind.jsonArrayOrObject));
+ assertFalse(new UriTokenizer("}").next(TokenKind.jsonArrayOrObject));
+ assertFalse(new UriTokenizer("[").next(TokenKind.jsonArrayOrObject));
+ assertFalse(new UriTokenizer("]").next(TokenKind.jsonArrayOrObject));
+ assertFalse(new UriTokenizer("{]").next(TokenKind.jsonArrayOrObject));
+
+ // missing values
+ assertFalse(new UriTokenizer("[1,]").next(TokenKind.jsonArrayOrObject));
+ assertFalse(new UriTokenizer("[,1]").next(TokenKind.jsonArrayOrObject));
+ assertFalse(new UriTokenizer("[1,,2]").next(TokenKind.jsonArrayOrObject));
+ assertFalse(new UriTokenizer("[1,x]").next(TokenKind.jsonArrayOrObject));
+ assertFalse(new UriTokenizer("{\"name\":1,}").next(TokenKind.jsonArrayOrObject));
+ assertFalse(new UriTokenizer("{,\"name\":1}").next(TokenKind.jsonArrayOrObject));
+ assertFalse(new UriTokenizer("{\"name\":1,,\"name2\":2}").next(TokenKind.jsonArrayOrObject));
+ assertFalse(new UriTokenizer("{\"name\":1,x}").next(TokenKind.jsonArrayOrObject));
+ assertFalse(new UriTokenizer("{\"name\":1,\"name2\"}").next(TokenKind.jsonArrayOrObject));
+ assertFalse(new UriTokenizer("{\"name\":1,\"name2\":}").next(TokenKind.jsonArrayOrObject));
+
+ // wrong JSON strings
+ assertFalse(new UriTokenizer("[\"a").next(TokenKind.jsonArrayOrObject));
+ assertFalse(new UriTokenizer("[\"a]").next(TokenKind.jsonArrayOrObject));
+ assertFalse(new UriTokenizer("[\"a\"\"]").next(TokenKind.jsonArrayOrObject));
+ assertFalse(new UriTokenizer("[\"\\x\"]").next(TokenKind.jsonArrayOrObject));
+ assertFalse(new UriTokenizer("[\"\\ux\"]").next(TokenKind.jsonArrayOrObject));
+ assertFalse(new UriTokenizer("[\"\\u1\"]").next(TokenKind.jsonArrayOrObject));
+ assertFalse(new UriTokenizer("[\"\\u12x\"]").next(TokenKind.jsonArrayOrObject));
+ assertFalse(new UriTokenizer("[\"\\u123x\"]").next(TokenKind.jsonArrayOrObject));
+ }
+
+ private void wrongToken(final TokenKind kind, final String value, final char disturbCharacter) {
+ assertFalse(new UriTokenizer(disturbCharacter + value).next(kind));
+
+ final UriTokenizer tokenizer = new UriTokenizer(value + disturbCharacter);
+ assertTrue(tokenizer.next(kind));
+ assertEquals(value, tokenizer.getText());
+
+ // Place the disturbing character at every position in the value string
+ // and check that this leads to a failed token recognition.
+ for (int index = 0; index < value.length(); index++) {
+ assertFalse("Error at index " + index,
+ new UriTokenizer(value.substring(0, index) + disturbCharacter + value.substring(index + 1)).next(kind));
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/927ecb93/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/search/SearchTokenizerTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/search/SearchTokenizerTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/search/SearchTokenizerTest.java
index c2a390a..7547687 100644
--- a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/search/SearchTokenizerTest.java
+++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/search/SearchTokenizerTest.java
@@ -31,7 +31,6 @@ import java.util.Iterator;
import java.util.List;
import org.junit.Assert;
-import org.junit.Ignore;
import org.junit.Test;
public class SearchTokenizerTest {
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/927ecb93/lib/server-tecsvc/src/test/java/org/apache/olingo/server/tecsvc/data/DataProviderTest.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/test/java/org/apache/olingo/server/tecsvc/data/DataProviderTest.java b/lib/server-tecsvc/src/test/java/org/apache/olingo/server/tecsvc/data/DataProviderTest.java
index 93c3c9a..6bd6463 100644
--- a/lib/server-tecsvc/src/test/java/org/apache/olingo/server/tecsvc/data/DataProviderTest.java
+++ b/lib/server-tecsvc/src/test/java/org/apache/olingo/server/tecsvc/data/DataProviderTest.java
@@ -29,7 +29,6 @@ import org.apache.olingo.commons.api.data.Property;
import org.apache.olingo.commons.api.edm.Edm;
import org.apache.olingo.commons.api.edm.EdmEntityContainer;
import org.apache.olingo.commons.api.edm.EdmEntitySet;
-import org.apache.olingo.commons.api.edm.FullQualifiedName;
import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.edmx.EdmxReference;
import org.apache.olingo.server.api.uri.UriParameter;
@@ -44,8 +43,7 @@ public class DataProviderTest {
private final Edm edm =
oData.createServiceMetadata(new EdmTechProvider(), Collections.<EdmxReference> emptyList())
.getEdm();
- private final EdmEntityContainer entityContainer = edm.getEntityContainer(
- new FullQualifiedName("olingo.odata.test1", "Container"));
+ private final EdmEntityContainer entityContainer = edm.getEntityContainer();
private final EdmEntitySet esAllPrim = entityContainer.getEntitySet("ESAllPrim");
private final EdmEntitySet esAllKey = entityContainer.getEntitySet("ESAllKey");
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/927ecb93/lib/server-test/src/test/java/org/apache/olingo/server/core/PreconditionsValidatorTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/PreconditionsValidatorTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/PreconditionsValidatorTest.java
index 5e3499c..bf68fb3 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/PreconditionsValidatorTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/PreconditionsValidatorTest.java
@@ -41,7 +41,7 @@ import org.apache.olingo.server.api.uri.UriResourceValue;
import org.apache.olingo.server.core.etag.PreconditionsValidator;
import org.apache.olingo.server.core.uri.parser.Parser;
import org.apache.olingo.server.core.uri.parser.UriParserException;
-import org.apache.olingo.server.core.uri.parser.UriParserSemanticException;
+import org.apache.olingo.server.core.uri.validator.UriValidationException;
import org.apache.olingo.server.tecsvc.provider.EdmTechProvider;
import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
@@ -49,7 +49,8 @@ import org.mockito.stubbing.Answer;
public class PreconditionsValidatorTest {
- private static final Edm edm = OData.newInstance().createServiceMetadata(
+ private static final OData odata = OData.newInstance();
+ private static final Edm edm = odata.createServiceMetadata(
new EdmTechProvider(), Collections.<EdmxReference> emptyList()).getEdm();
// -------------- POSITIVE TESTS --------------------------------------------------------------------------------
@@ -140,7 +141,7 @@ public class PreconditionsValidatorTest {
@Test
public void simpleEntityValueValidationNotActiveForMedia() throws Exception {
- final UriInfo uriInfo = new Parser().parseUri("ESMedia(1)/$value", null, null, edm);
+ final UriInfo uriInfo = new Parser(edm, odata).parseUri("ESMedia(1)/$value", null, null);
CustomETagSupport support = mock(CustomETagSupport.class);
when(support.hasETag(any(EdmBindingTarget.class))).thenReturn(true);
@@ -185,21 +186,17 @@ public class PreconditionsValidatorTest {
assertFalse(mustValidate("SINav/NavPropertyETKeyNavOne/$ref", "ESKeyNav"));
}
- @Test(expected = UriParserSemanticException.class)
- public void resourceSegmentAfterActionMustLeadToUriParserException() throws Exception {
- mustValidate("ESKeyNav(1)/Namespace1_Alias.BAETTwoKeyNavRTETTwoKeyNav/PropertyInt16", "ESKeyNav");
- }
-
- @Test(expected = UriParserSemanticException.class)
- public void valueMustBeLastSegment() throws Exception {
- mustValidate("ESMedia(1)/$value/PropertyInt16", "ESMedia");
+ @Test
+ public void nonResourceMustBeIgnored() throws Exception {
+ assertFalse(mustValidate("$all", null));
}
private boolean mustValidate(final String uri, final String entitySetName)
- throws UriParserException, PreconditionException {
- final UriInfo uriInfo = new Parser().parseUri(uri, null, null, edm);
+ throws UriParserException, UriValidationException, PreconditionException {
+ final UriInfo uriInfo = new Parser(edm, odata).parseUri(uri, null, null);
final List<UriResource> parts = uriInfo.getUriResourceParts();
- final boolean isMedia = parts.get(parts.size() - 1) instanceof UriResourceValue
+ final boolean isMedia = parts.size() >= 2
+ && parts.get(parts.size() - 1) instanceof UriResourceValue
&& parts.get(parts.size() - 2) instanceof UriResourceEntitySet;
CustomETagSupport support = mock(CustomETagSupport.class);
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/927ecb93/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/utils/ContextURLHelperTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/utils/ContextURLHelperTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/utils/ContextURLHelperTest.java
index fe86896..92b069d 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/utils/ContextURLHelperTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/utils/ContextURLHelperTest.java
@@ -28,7 +28,6 @@ import org.apache.olingo.commons.api.edm.Edm;
import org.apache.olingo.commons.api.edm.EdmEntityContainer;
import org.apache.olingo.commons.api.edm.EdmEntitySet;
import org.apache.olingo.commons.api.edm.EdmProperty;
-import org.apache.olingo.commons.api.edm.FullQualifiedName;
import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.edmx.EdmxReference;
import org.apache.olingo.server.api.uri.UriParameter;
@@ -45,8 +44,7 @@ public class ContextURLHelperTest {
private static final Edm edm = OData.newInstance().createServiceMetadata(
new EdmTechProvider(), Collections.<EdmxReference> emptyList()).getEdm();
- private static final EdmEntityContainer entityContainer = edm.getEntityContainer(
- new FullQualifiedName("olingo.odata.test1", "Container"));
+ private static final EdmEntityContainer entityContainer = edm.getEntityContainer();
@Test
public void buildSelect() throws Exception {
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/927ecb93/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/UriHelperTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/UriHelperTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/UriHelperTest.java
index 781f48d..d3dba46 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/UriHelperTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/UriHelperTest.java
@@ -25,7 +25,6 @@ import org.apache.olingo.commons.api.data.ValueType;
import org.apache.olingo.commons.api.edm.Edm;
import org.apache.olingo.commons.api.edm.EdmEntityContainer;
import org.apache.olingo.commons.api.edm.EdmEntitySet;
-import org.apache.olingo.commons.api.edm.FullQualifiedName;
import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.edmx.EdmxReference;
import org.apache.olingo.server.api.serializer.SerializerException;
@@ -40,8 +39,7 @@ public class UriHelperTest {
private static final OData odata = OData.newInstance();
private static final Edm edm = odata.createServiceMetadata(
new EdmTechProvider(), Collections.<EdmxReference> emptyList()).getEdm();
- private static final EdmEntityContainer container = edm.getEntityContainer(
- new FullQualifiedName("olingo.odata.test1", "Container"));
+ private static final EdmEntityContainer container = edm.getEntityContainer();
private static final UriHelper helper = odata.createUriHelper();
private final DataProvider data = new DataProvider(odata, edm);
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/927ecb93/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/UriResourceImplTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/UriResourceImplTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/UriResourceImplTest.java
index 27b879d..a5d0ea3 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/UriResourceImplTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/UriResourceImplTest.java
@@ -86,7 +86,7 @@ public class UriResourceImplTest {
// action import
impl = new UriResourceActionImpl();
- EdmActionImport actionImport = edm.getEntityContainer(null).getActionImport("AIRTCTTwoPrimParam");
+ EdmActionImport actionImport = edm.getEntityContainer().getActionImport("AIRTCTTwoPrimParam");
impl.setActionImport(actionImport);
assertEquals(actionImport, impl.getActionImport());
assertEquals(actionImport.getUnboundAction(), impl.getAction());
@@ -94,7 +94,7 @@ public class UriResourceImplTest {
assertEquals("AIRTCTTwoPrimParam", impl.toString());
assertEquals(actionImport.getUnboundAction().getReturnType().getType(), impl.getType());
- actionImport = edm.getEntityContainer(null).getActionImport("AIRT");
+ actionImport = edm.getEntityContainer().getActionImport("AIRT");
impl.setActionImport(actionImport);
assertFalse(impl.isCollection());
assertNull(impl.getType());
@@ -184,7 +184,7 @@ public class UriResourceImplTest {
UriResourceEntitySetImpl impl = new UriResourceEntitySetImpl();
assertEquals(UriResourceKind.entitySet, impl.getKind());
- EdmEntitySet entitySet = edm.getEntityContainer(null).getEntitySet("ESAllPrim");
+ EdmEntitySet entitySet = edm.getEntityContainer().getEntitySet("ESAllPrim");
impl.setEntitSet(entitySet);
assertEquals("ESAllPrim", impl.toString());
@@ -207,7 +207,7 @@ public class UriResourceImplTest {
assertEquals("", impl.toString());
// function
- EdmFunction function = edm.getEntityContainer(null).getFunctionImport("FINRTInt16")
+ EdmFunction function = edm.getEntityContainer().getFunctionImport("FINRTInt16")
.getUnboundFunction(Collections.<String> emptyList());
assertNotNull(function);
impl.setFunction(function);
@@ -219,14 +219,14 @@ public class UriResourceImplTest {
// function import
impl = new UriResourceFunctionImpl();
- EdmFunctionImport functionImport = edm.getEntityContainer(null).getFunctionImport("FINRTInt16");
+ EdmFunctionImport functionImport = edm.getEntityContainer().getFunctionImport("FINRTInt16");
impl.setFunctionImport(functionImport, Collections.<UriParameter> emptyList());
assertEquals(functionImport, impl.getFunctionImport());
assertEquals("FINRTInt16", impl.toString());
// function collection
impl = new UriResourceFunctionImpl();
- functionImport = edm.getEntityContainer(null).getFunctionImport("FICRTCollESTwoKeyNavParam");
+ functionImport = edm.getEntityContainer().getFunctionImport("FICRTCollESTwoKeyNavParam");
assertNotNull(function);
UriParameter parameter = new UriParameterImpl().setName("ParameterInt16");
impl.setFunctionImport(functionImport, Collections.singletonList(parameter));
@@ -414,7 +414,7 @@ public class UriResourceImplTest {
UriResourceSingletonImpl impl = new UriResourceSingletonImpl();
assertEquals(UriResourceKind.singleton, impl.getKind());
- EdmSingleton singleton = edm.getEntityContainer(null).getSingleton("SINav");
+ EdmSingleton singleton = edm.getEntityContainer().getSingleton("SINav");
EdmEntityType entityTypeBaseColl = edm.getEntityType(EntityTypeProvider.nameETBaseTwoKeyNav);
impl.setSingleton(singleton);
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/927ecb93/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java
index 379345e..11acede 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java
@@ -34,12 +34,10 @@ import org.apache.olingo.commons.api.edm.FullQualifiedName;
import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.commons.core.Encoder;
import org.apache.olingo.server.api.OData;
-import org.apache.olingo.server.api.ODataApplicationException;
import org.apache.olingo.server.api.edmx.EdmxReference;
import org.apache.olingo.server.api.uri.UriInfoKind;
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.ExpressionVisitException;
import org.apache.olingo.server.api.uri.queryoption.expression.MethodKind;
import org.apache.olingo.server.core.uri.parser.UriParserException;
import org.apache.olingo.server.core.uri.parser.UriParserSemanticException;
@@ -934,14 +932,20 @@ public class TestFullResourcePath {
}
@Test
- public void runCrossjoin() throws Exception {
+ public void crossjoin() throws Exception {
testUri.run("$crossjoin(ESKeyNav)")
.isKind(UriInfoKind.crossjoin)
.isCrossJoinEntityList(Arrays.asList("ESKeyNav"));
- testUri.run("$crossjoin(ESKeyNav, ESTwoKeyNav)")
+ testUri.run("$crossjoin(ESKeyNav,ESTwoKeyNav)")
.isKind(UriInfoKind.crossjoin)
.isCrossJoinEntityList(Arrays.asList("ESKeyNav", "ESTwoKeyNav"));
+
+ testUri.run("$crossjoin(ESTwoPrim,ESMixPrimCollComp)",
+ "$filter=ESTwoPrim/PropertyString eq ESMixPrimCollComp/PropertyComp/PropertyString")
+ .goFilter()
+ .isBinary(BinaryOperatorKind.EQ)
+ .is("<<ESTwoPrim/PropertyString> eq <ESMixPrimCollComp/PropertyComp/PropertyString>>");
}
@Test
@@ -951,6 +955,8 @@ public class TestFullResourcePath {
testUri.runEx("$crossjoin()").isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
testUri.runEx("$crossjoin(ESKeyNav, ESTwoKeyNav)/invalid")
.isExSyntax(UriParserSyntaxException.MessageKeys.MUST_BE_LAST_SEGMENT);
+ testUri.runEx("$crossjoin(ESKeyNav)/$ref")
+ .isExSyntax(UriParserSyntaxException.MessageKeys.MUST_BE_LAST_SEGMENT);
}
@Test
@@ -982,15 +988,16 @@ public class TestFullResourcePath {
}
@Test
- public void runEsNameError() {
+ public void esNameError() {
- testUri.runEx("ESAllPrim/$count/$ref").isExSemantic(MessageKeys.ONLY_FOR_TYPED_PROPERTIES);
- testUri.runEx("ESAllPrim/$ref/$count").isExSemantic(MessageKeys.ONLY_FOR_TYPED_PARTS);
- testUri.runEx("ESAllPrim/$ref/invalid").isExSemantic(MessageKeys.RESOURCE_PART_ONLY_FOR_TYPED_PARTS);
- testUri.runEx("ESAllPrim/$count/invalid").isExSemantic(MessageKeys.RESOURCE_PART_ONLY_FOR_TYPED_PARTS);
+ testUri.runEx("ESAllPrim/$count/$ref").isExSyntax(UriParserSyntaxException.MessageKeys.MUST_BE_LAST_SEGMENT);
+ testUri.runEx("ESAllPrim/$ref/$count").isExSyntax(UriParserSyntaxException.MessageKeys.MUST_BE_LAST_SEGMENT);
+ testUri.runEx("ESAllPrim/$ref/invalid").isExSyntax(UriParserSyntaxException.MessageKeys.MUST_BE_LAST_SEGMENT);
+ testUri.runEx("ESAllPrim/$count/invalid").isExSyntax(UriParserSyntaxException.MessageKeys.MUST_BE_LAST_SEGMENT);
testUri.runEx("ESAllPrim/PropertyString").isExSemantic(MessageKeys.PROPERTY_AFTER_COLLECTION);
testUri.runEx("ESAllPrim(1)/whatever").isExSemantic(MessageKeys.PROPERTY_NOT_IN_TYPE);
- testUri.runEx("ESAllPrim(PropertyInt16)").isExSemantic(MessageKeys.INVALID_KEY_VALUE);
+ testUri.runEx("ESAllPrim('1')").isExSemantic(MessageKeys.INVALID_KEY_VALUE);
+ testUri.runEx("ESAllPrim(PropertyInt16)").isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
testUri.runEx("ESAllPrim(PropertyInt16=)").isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
testUri.runEx("ESAllPrim(PropertyInt16=1,Invalid='1')").isExSemantic(MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES);
@@ -1023,8 +1030,7 @@ public class TestFullResourcePath {
}
@Test
- public void runResourcePathWithApostrophe() {
- // TODO Currently "'" is not allowed in OData identifiers, but the specification allows this character (Unicode Cf)
+ public void resourcePathWithApostrophe() {
testUri.runEx("ESAllPrim'").isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
testUri.runEx("ESAllPrim'InvalidStuff").isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
@@ -1070,7 +1076,7 @@ public class TestFullResourcePath {
.isKeyPredicate(0, "PropertyInt16", "0");
testUri.runEx("FICRTCollETMixPrimCollCompTwoParam(ParameterString='1',ParameterInt16=1)(PropertyInt16 eq 0)")
- .isExSemantic(MessageKeys.INVALID_KEY_VALUE);
+ .isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
// PropertyInt32 does not exist
testUri.runEx("FICRTCollETMixPrimCollCompTwoParam(ParameterString='1',ParameterInt16=1)(PropertyInt32=0)")
@@ -1078,7 +1084,7 @@ public class TestFullResourcePath {
testUri.runEx("FICRTCollETMixPrimCollCompTwoParam(ParameterString='1',ParameterInt16=1)"
+ "(PropertyInt16=0,PropertyInt16=1)")
- .isExSemantic(MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES);
+ .isExValidation(UriValidationException.MessageKeys.DOUBLE_KEY_PROPERTY);
testUri.run("FICRTCollCTTwoPrimTwoParam(ParameterString='1',ParameterInt16=1)")
.isKind(UriInfoKind.resource)
@@ -1117,13 +1123,13 @@ public class TestFullResourcePath {
.isKeyPredicate(1, "PropertyString", "'1'");
testUri.runEx("FICRTCollESTwoKeyNavParam(ParameterInt16=1)(PropertyInt16 eq 1)")
- .isExSemantic(MessageKeys.INVALID_KEY_VALUE);
+ .isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
testUri.runEx("FICRTCollESTwoKeyNavParam(ParameterInt16=1)(PropertyInt16=1)")
.isExSemantic(MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES);
testUri.runEx("FICRTCollESTwoKeyNavParam(ParameterInt16=1)(PropertyInt16=1,PropertyInt32=1,PropertyString='1')")
- .isExSemantic(MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES);
+ .isExValidation(UriValidationException.MessageKeys.INVALID_KEY_PROPERTY);
testUri.runEx("FICRTCollESTwoKeyNavParam(ParameterInt16=1)()")
.isExSemantic(MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES);
@@ -1193,11 +1199,9 @@ public class TestFullResourcePath {
testUri.runEx("FICRTCollETMixPrimCollCompTwoParam(ParameterInt16=1,ParameterString='1')", "$skiptoken=5")
.isExValidation(UriValidationException.MessageKeys.SYSTEM_QUERY_OPTION_NOT_ALLOWED);
- // $search is currently not implemented. Please change this exception if the implementation is done.
- // FIXME (151106:mibo): check after finish of OLINGO-568
-// testUri.runEx("FICRTCollETMixPrimCollCompTwoParam(ParameterInt16=1,ParameterString='1')", "$search=test")
-// .isExSemantic(MessageKeys.NOT_IMPLEMENTED);
-
+ testUri.runEx("FICRTCollETMixPrimCollCompTwoParam(ParameterInt16=1,ParameterString='1')", "$search=test")
+ .isExValidation(UriValidationException.MessageKeys.SYSTEM_QUERY_OPTION_NOT_ALLOWED);
+
testUri.run("ESAllPrim/olingo.odata.test1.BFNESAllPrimRTCTAllPrim()")
.isKind(UriInfoKind.resource)
.goPath().first()
@@ -1296,8 +1300,8 @@ public class TestFullResourcePath {
.isKeyPredicate(2, "KeyAlias2", "'3'")
.isKeyPredicate(3, "KeyAlias3", "'4'");
- testUri.runEx("ESTwoPrim(wrong)").isExSemantic(MessageKeys.INVALID_KEY_VALUE);
- testUri.runEx("ESTwoPrim(PropertyInt16=wrong)").isExSemantic(MessageKeys.INVALID_KEY_VALUE);
+ testUri.runEx("ESTwoPrim('wrong')").isExSemantic(MessageKeys.INVALID_KEY_VALUE);
+ testUri.runEx("ESTwoPrim(PropertyInt16='wrong')").isExSemantic(MessageKeys.INVALID_KEY_VALUE);
}
@Test
@@ -1794,7 +1798,7 @@ public class TestFullResourcePath {
@Test
public void runEsNamePpNpRc() throws Exception {
- // checks for using referential constrains to fill missing keys
+ // checks for using referential constraints to fill missing keys
testUri.run("ESKeyNav(1)/NavPropertyETTwoKeyNavMany('2')").goPath()
.first()
.isEntitySet("ESKeyNav")
@@ -2037,7 +2041,6 @@ public class TestFullResourcePath {
@Test
public void runFunctionImpEs() throws Exception {
- /**/
testUri.run("FICRTESMixPrimCollCompTwoParam(ParameterInt16=1,ParameterString='2')")
.isKind(UriInfoKind.resource).goPath()
.first()
@@ -2805,8 +2808,8 @@ public class TestFullResourcePath {
}
@Test
- @Ignore("$search currently not implemented")
- public void runDuplicatedSearchExpand() throws UriParserException, UriValidationException {
+ @Ignore("$search in expand currently not implemented")
+ public void duplicatedSearchExpand() throws Exception {
testUri.runEx("ESKeyNav", "$expand=NavPropertyETKeyNavOne($search=Test;$search=Test)")
.isExSyntax(UriParserSyntaxException.MessageKeys.DOUBLE_SYSTEM_QUERY_OPTION);
}
@@ -2931,13 +2934,8 @@ public class TestFullResourcePath {
testUri.run("$batch")
.isKind(UriInfoKind.batch);
- testUri.run("$crossjoin(ESKeyNav)")
- .isKind(UriInfoKind.crossjoin)
- .isCrossJoinEntityList(Arrays.asList("ESKeyNav"));
-
testUri.runEx("$metadata/$ref").isExSyntax(UriParserSyntaxException.MessageKeys.MUST_BE_LAST_SEGMENT);
testUri.runEx("$batch/$ref").isExSyntax(UriParserSyntaxException.MessageKeys.MUST_BE_LAST_SEGMENT);
- testUri.runEx("$crossjoin(ESKeyNav)/$ref").isExSyntax(UriParserSyntaxException.MessageKeys.MUST_BE_LAST_SEGMENT);
testUri.runEx("$all/$ref").isExSyntax(UriParserSyntaxException.MessageKeys.MUST_BE_LAST_SEGMENT);
testUri.runEx("$entity/olingo.odata.test1.ETKeyNav/$ref")
.isExSyntax(UriParserSyntaxException.MessageKeys.MUST_BE_LAST_SEGMENT);
@@ -3142,7 +3140,7 @@ public class TestFullResourcePath {
}
@Test
- public void testFilter() throws UriParserException {
+ public void filter() throws Exception {
testFilter.runOnETTwoKeyNav("PropertyString")
.is("<PropertyString>")
@@ -3684,7 +3682,7 @@ public class TestFullResourcePath {
}
@Test
- public void testFilterProperties() throws UriParserException {
+ public void filterProperties() throws Exception {
testFilter.runOnETAllPrim("PropertyByte mod 0")
.is("<<PropertyByte> mod <0>>");
@@ -3849,7 +3847,7 @@ public class TestFullResourcePath {
}
@Test
- public void testFilterPMethods() throws ExpressionVisitException, ODataApplicationException, UriParserException {
+ public void filterPMethods() throws Exception {
testFilter.runOnETKeyNav("indexof(PropertyString,'47') eq 5")
.is("<<indexof(<PropertyString>,<'47'>)> eq <5>>")
@@ -4465,7 +4463,7 @@ public class TestFullResourcePath {
}
@Test
- public void runLamdbaFunctions() throws ExpressionVisitException, ODataApplicationException, UriParserException {
+ public void lambdaFunctions() throws Exception {
testFilter.runOnETKeyNav("any(d:d/PropertyInt16 eq 1)")
.is("<<ANY;<<d/PropertyInt16> eq <1>>>>")
@@ -4612,7 +4610,7 @@ public class TestFullResourcePath {
}
@Test
- public void runIsOf() throws ExpressionVisitException, ODataApplicationException, UriParserException {
+ public void runIsOf() throws Exception {
testFilter.runOnETKeyNav("isof(olingo.odata.test1.ETTwoKeyNav)")
.is("<isof(<olingo.odata.test1.ETTwoKeyNav>)>")
@@ -4757,7 +4755,7 @@ public class TestFullResourcePath {
}
@Test
- public void testHas() throws ExpressionVisitException, ODataApplicationException, UriParserException {
+ public void has() throws Exception {
testFilter.runOnETMixEnumDefCollComp("PropertyEnumString has olingo.odata.test1.ENString'String1'")
.is("<<PropertyEnumString> has <olingo.odata.test1.ENString<String1>>>")
@@ -5086,7 +5084,7 @@ public class TestFullResourcePath {
}
@Test
- public void testOrderby() throws UriParserException, UnsupportedEncodingException {
+ public void orderby() throws Exception {
testFilter.runOrderByOnETTwoKeyNav("olingo.odata.test1.UFCRTETAllPrimTwoParam("
+ "ParameterString=@ParamStringAlias,ParameterInt16=@ParamInt16Alias)/PropertyString eq 'SomeString'")
@@ -5429,7 +5427,7 @@ public class TestFullResourcePath {
}
@Test
- public void testSearch() throws Exception {
+ public void search() throws Exception {
testUri.run("ESTwoKeyNav", "$search=abc");
testUri.run("ESTwoKeyNav", "$search=NOT abc");
@@ -5462,6 +5460,9 @@ public class TestFullResourcePath {
testUri.run("ESTwoKeyNav", "$search=abc AND (def OR ghi)");
testUri.run("ESTwoKeyNav", "$search=abc AND (def ghi)");
+ // search in function-import return value
+ testUri.run("FICRTCollESTwoKeyNavParam(ParameterInt16=1)", "$search=test");
+
// percent encoded characters
testUri.run("ESTwoKeyNav", "$search=%41%42%43");
testUri.run("ESTwoKeyNav", "$search=\"100%25\"");
@@ -5484,7 +5485,6 @@ public class TestFullResourcePath {
/**
* https://tools.oasis-open.org/version-control/browse/wsvn/odata/trunk/spec/ABNF/odata-abnf-testcases.xml
- * @throws Exception
*/
@Test
public void searchQueryPhraseAbnfTestcases() throws Exception {
@@ -5568,10 +5568,10 @@ public class TestFullResourcePath {
}
@Test
- public void testErrors() {
+ public void errors() {
testUri.runEx("FICRTString(wrong1='ABC')/olingo.odata.test1.BFCStringRTESTwoKeyNav()")
.isExSemantic(MessageKeys.FUNCTION_NOT_FOUND);
- testUri.runEx("FICRTString(wrong1='ABC', wrong2=1)/olingo.odata.test1.BFCStringRTESTwoKeyNav()")
+ testUri.runEx("FICRTString(wrong1='ABC',wrong2=1)/olingo.odata.test1.BFCStringRTESTwoKeyNav()")
.isExSemantic(MessageKeys.FUNCTION_NOT_FOUND);
// type filter for entity incompatible
@@ -5620,14 +5620,14 @@ public class TestFullResourcePath {
// Actions must not be followed by anything.
testUri.runEx(ContainerProvider.AIRT_STRING + "/$value")
- .isExValidation(UriValidationException.MessageKeys.UNALLOWED_KIND_BEFORE_VALUE);
+ .isExValidation(UriValidationException.MessageKeys.UNALLOWED_RESOURCE_PATH);
testUri.runEx(ContainerProvider.AIRTCT_TWO_PRIM_PARAM + "/PropertyInt16")
- .isExSemantic(MessageKeys.RESOURCE_PART_ONLY_FOR_TYPED_PARTS);
+ .isExValidation(UriValidationException.MessageKeys.UNALLOWED_RESOURCE_PATH);
testUri.runEx("ESTwoKeyNav(PropertyInt16=1,PropertyString='2')/"
+ "olingo.odata.test1.BAETTwoKeyNavRTETTwoKeyNav/olingo.odata.test1.ETTwoKeyNav")
- .isExSemantic(MessageKeys.RESOURCE_PART_ONLY_FOR_TYPED_PARTS);
+ .isExValidation(UriValidationException.MessageKeys.UNALLOWED_RESOURCE_PATH);
testUri.runEx("ESTwoKeyNav/olingo.odata.test1.BAESTwoKeyNavRTESTwoKeyNav/$count")
- .isExValidation(UriValidationException.MessageKeys.UNALLOWED_KIND_BEFORE_COUNT);
+ .isExValidation(UriValidationException.MessageKeys.UNALLOWED_RESOURCE_PATH);
}
@Test
@@ -5646,7 +5646,7 @@ public class TestFullResourcePath {
@Test
public void multipleKeysInResourcePath() throws Exception {
// See OLINGO-730
- testUri.runEx("ESAllPrim(32767)(1)(2)").isExSemantic(MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES);
+ testUri.runEx("ESAllPrim(32767)(1)(2)").isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
}
@Test
@@ -5705,9 +5705,9 @@ public class TestFullResourcePath {
@Test
public void navigationWithMoreThanOneKey() throws Exception {
- testUri.runEx("ESKeyNav(1)/NavPropertyETTwoKeyNavMany(PropertyInt=1,PropertyString='2')"
- + "(PropertyInt=1,PropertyString='2')")
- .isExSemantic(MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES);
+ testUri.runEx("ESKeyNav(1)/NavPropertyETTwoKeyNavMany(PropertyInt16=1,PropertyString='2')"
+ + "(PropertyInt16=1,PropertyString='2')")
+ .isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
}
@Test
@@ -5724,10 +5724,14 @@ public class TestFullResourcePath {
testUri.runEx("FICRTETKeyNav()/SINav").isExSemantic(MessageKeys.PROPERTY_NOT_IN_TYPE);
testUri.runEx("FICRTETKeyNav()/FICRTString()").isExSemantic(MessageKeys.PROPERTY_NOT_IN_TYPE);
testUri.runEx("FICRTETKeyNav()/AIRTString").isExSemantic(MessageKeys.PROPERTY_NOT_IN_TYPE);
- testUri.runEx("AIRTESAllPrimParam/ESAllPrim(0)").isExSemantic(MessageKeys.RESOURCE_PART_ONLY_FOR_TYPED_PARTS);
- testUri.runEx("AIRTESAllPrimParam/SINav").isExSemantic(MessageKeys.RESOURCE_PART_ONLY_FOR_TYPED_PARTS);
- testUri.runEx("AIRTESAllPrimParam/FICRTString()").isExSemantic(MessageKeys.RESOURCE_PART_ONLY_FOR_TYPED_PARTS);
- testUri.runEx("AIRTESAllPrimParam/AIRTString").isExSemantic(MessageKeys.RESOURCE_PART_ONLY_FOR_TYPED_PARTS);
+ testUri.runEx("AIRTESAllPrimParam/ESAllPrim(0)")
+ .isExValidation(UriValidationException.MessageKeys.UNALLOWED_RESOURCE_PATH);
+ testUri.runEx("AIRTESAllPrimParam/SINav")
+ .isExValidation(UriValidationException.MessageKeys.UNALLOWED_RESOURCE_PATH);
+ testUri.runEx("AIRTESAllPrimParam/FICRTString()")
+ .isExValidation(UriValidationException.MessageKeys.UNALLOWED_RESOURCE_PATH);
+ testUri.runEx("AIRTESAllPrimParam/AIRTString")
+ .isExValidation(UriValidationException.MessageKeys.UNALLOWED_RESOURCE_PATH);
}
@Test
@@ -5737,7 +5741,7 @@ public class TestFullResourcePath {
}
@Test
- public void testFirstResourcePathWithNamespace() {
+ public void firstResourcePathWithNamespace() {
testUri.runEx("olingo.odata.test1.ESAllPrim").isExSemantic(MessageKeys.NAMESPACE_NOT_ALLOWED_AT_FIRST_ELEMENT);
testUri.runEx("olingo.odata.test1.ESAllPrim(0)").isExSemantic(MessageKeys.NAMESPACE_NOT_ALLOWED_AT_FIRST_ELEMENT);
testUri.runEx("olingo.odata.test1.FINRTInt16()").isExSemantic(MessageKeys.NAMESPACE_NOT_ALLOWED_AT_FIRST_ELEMENT);
@@ -5764,7 +5768,7 @@ public class TestFullResourcePath {
Mockito.when(entityType.getFullQualifiedName()).thenReturn(nameETNavProp);
Mockito.when(entityType.getKeyPredicateNames()).thenReturn(Collections.singletonList(keyPropertyName));
Mockito.when(entityType.getKeyPropertyRefs()).thenReturn(Collections.singletonList(keyPropertyRef));
- Mockito.when(entityType.getProperty(entitySetName)).thenReturn(navProperty);
+ Mockito.when(entityType.getNavigationProperty(entitySetName)).thenReturn(navProperty);
Mockito.when(navProperty.getType()).thenReturn(entityType);
EdmEntitySet entitySet = Mockito.mock(EdmEntitySet.class);
Mockito.when(entitySet.getName()).thenReturn(entitySetName);
@@ -5772,7 +5776,7 @@ public class TestFullResourcePath {
EdmEntityContainer container = Mockito.mock(EdmEntityContainer.class);
Mockito.when(container.getEntitySet(entitySetName)).thenReturn(entitySet);
Edm mockedEdm = Mockito.mock(Edm.class);
- Mockito.when(mockedEdm.getEntityContainer(null)).thenReturn(container);
+ Mockito.when(mockedEdm.getEntityContainer()).thenReturn(container);
new TestUriValidator().setEdm(mockedEdm)
.run("ESNavProp(1)/ESNavProp(2)/ESNavProp(3)/ESNavProp")
.goPath()
@@ -5886,11 +5890,11 @@ public class TestFullResourcePath {
@Test
public void functionsWithComplexParameters() throws Exception {
testUri.run("ESTwoKeyNav/olingo.odata.test1.BFCESTwoKeyNavRTStringParam"
- + "(ParameterComp=@p1)", "@p1={\"PropertyInt16\":1,\"ProperyString\":\"1\"}")
+ + "(ParameterComp=@p1)", "@p1={\"PropertyInt16\":1,\"PropertyString\":\"1\"}")
.goPath()
.at(0).isEntitySet("ESTwoKeyNav")
.at(1).isFunction("BFCESTwoKeyNavRTStringParam").isParameterAlias(0, "ParameterComp", "@p1")
- .isInAliasToValueMap("@p1", "{\"PropertyInt16\":1,\"ProperyString\":\"1\"}");
+ .isInAliasToValueMap("@p1", "{\"PropertyInt16\":1,\"PropertyString\":\"1\"}");
// Test JSON String lexer rule =\"3,Int16=abc},\\\nabc&test%test\b\f\r\t\u0022\\}\\{\\)\\(\\]\\[}
final String stringValueEncoded = "=\\\"3,Int16=abc},\\\\\\nabc%26test%25test\\b\\f\\r\\t\\u0022\\\\}\\\\{\\\\)"
@@ -5899,11 +5903,11 @@ public class TestFullResourcePath {
+ "\\\\(\\\\]\\\\[}";
testUri.run("ESTwoKeyNav/olingo.odata.test1.BFCESTwoKeyNavRTStringParam"
- + "(ParameterComp=@p1)", "@p1={\"PropertyInt16\":1,\"ProperyString\":\"" + stringValueEncoded + "\"}")
+ + "(ParameterComp=@p1)", "@p1={\"PropertyInt16\":1,\"PropertyString\":\"" + stringValueEncoded + "\"}")
.goPath()
.at(0).isEntitySet("ESTwoKeyNav")
.at(1).isFunction("BFCESTwoKeyNavRTStringParam").isParameterAlias(0, "ParameterComp", "@p1")
- .isInAliasToValueMap("@p1", "{\"PropertyInt16\":1,\"ProperyString\":\"" + stringValueDecoded + "\"}");
+ .isInAliasToValueMap("@p1", "{\"PropertyInt16\":1,\"PropertyString\":\"" + stringValueDecoded + "\"}");
testUri.run("ESTwoKeyNav", "$filter=olingo.odata.test1.BFCESTwoKeyNavRTStringParam"
+ "(ParameterComp={\"PropertyString\":\"Test\",\"PropertyInt16\":1}) eq 'Test'")
@@ -5916,24 +5920,24 @@ public class TestFullResourcePath {
.isParameterText(0, "{\"PropertyString\":\"" + stringValueDecoded + "\",\"PropertyInt16\":1}");
testUri.run("ESTwoKeyNav", "$filter=olingo.odata.test1.BFCESTwoKeyNavRTStringParam"
- + "(ParameterComp=@p1) eq 0&@p1={\"PropertyInt16\":1,\"ProperyString\":\"1\"}");
+ + "(ParameterComp=@p1) eq 0&@p1={\"PropertyInt16\":1,\"PropertyString\":\"1\"}");
testUri.run("ESTwoKeyNav", "$filter=olingo.odata.test1.BFCESTwoKeyNavRTStringParam"
- + "(ParameterComp=@p1) eq 0&@p1={\"PropertyInt16\":1,\"ProperyString\":null}")
+ + "(ParameterComp=@p1) eq 0&@p1={\"PropertyInt16\":1,\"PropertyString\":null}")
.goFilter().left().isParameterText(0, null);
testUri.run("ESTwoKeyNav", "$filter=olingo.odata.test1.BFCESTwoKeyNavRTStringParam"
+ "(ParameterComp=@p1) eq 0&@p1={}");
testUri.run("ESTwoKeyNav", "$filter=olingo.odata.test1.BFCESTwoKeyNavRTStringParam"
- + "(ParameterComp=@p1) eq 0&@p1={\"PropertyInt16\":[1,2,3],\"ProperyString\":\"1\"}");
+ + "(ParameterComp=@p1) eq 0&@p1={\"PropertyInt16\":[1,2,3],\"PropertyString\":\"1\"}");
testUri.run("ESTwoKeyNav", "$filter=olingo.odata.test1.BFCESTwoKeyNavRTStringParam"
- + "(ParameterComp=@p1) eq 0&@p1={\"PropertyInt16\":[\"1\",\"2\",\"3\"],\"ProperyString\":\"1\"}");
+ + "(ParameterComp=@p1) eq 0&@p1={\"PropertyInt16\":[\"1\",\"2\",\"3\"],\"PropertyString\":\"1\"}");
testUri.run("ESTwoKeyNav", "$filter=olingo.odata.test1.BFCESTwoKeyNavRTStringParam"
+ "(ParameterComp=@p1) eq 0&@p1={\"PropertyInt16\":[{\"Prop1\":123,\"Prop2\":\"Test\",\"Prop3\":[1,2,3]},"
- + "{\"Prop1\":{\"Prop1\":[\"Prop\\\":{]\"]}}],\"ProperyString\":\"1\"}");
+ + "{\"Prop1\":{\"Prop1\":[\"Prop\\\":{]\"]}}],\"PropertyString\":\"1\"}");
testUri.run("FINRTByteNineParam(ParameterEnum=null,ParameterDef='x',ParameterComp=@c,"
+ "ParameterETTwoPrim=@c,CollParameterByte=@e,CollParameterEnum=@e,CollParameterDef=@e,"
@@ -5941,12 +5945,12 @@ public class TestFullResourcePath {
"@c={}&@e=[]");
testUri.runEx("ESTwoKeyNav/olingo.odata.test1.BFCESTwoKeyNavRTStringParam"
- + "(ParameterComp=@p1)", "@p1={\"PropertyInt16\":1,\"ProperyString\":'1'}")
+ + "(ParameterComp=@p1)", "@p1={\"PropertyInt16\":1,\"PropertyString\":'1'}")
.isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
testUri.runEx("ESTwoKeyNav/olingo.odata.test1.BFCESTwoKeyNavRTStringParam"
+ "(ParameterComp={\"PropertyInt16\":1,\"PropertyString\":\"Test\"})")
- .isExSemantic(UriParserSemanticException.MessageKeys.COMPLEX_PARAMETER_IN_RESOURCE_PATH);
+ .isExSemantic(UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE);
testUri.runEx("FICRTCTTwoPrimTwoParam(ParameterInt16=1,ParameterString=null)")
.isExValidation(UriValidationException.MessageKeys.MISSING_PARAMETER);
@@ -5959,7 +5963,7 @@ public class TestFullResourcePath {
testUri.run("FICRTCTTwoPrimTwoParam(ParameterInt16=1,ParameterString=@test)", "@test='null'");
- testUri.runEx("FICRTCTTwoPrimTwoParam(ParameterInt16=1,ParameterString=@test, UnknownParam=1)", "@test='null'")
+ testUri.runEx("FICRTCTTwoPrimTwoParam(ParameterInt16=1,ParameterString=@test,UnknownParam=1)", "@test='null'")
.isExSemantic(UriParserSemanticException.MessageKeys.FUNCTION_NOT_FOUND);
testUri.run("FICRTCollCTTwoPrimTwoParam(ParameterInt16=1,ParameterString=@test)", "@test='null'");
@@ -5974,23 +5978,23 @@ public class TestFullResourcePath {
.isExSemantic(UriParserSemanticException.MessageKeys.FUNCTION_IMPORT_NOT_ALLOWED);
testUri.runEx("ESTwoKeyNav", "$filter=olingo.odata.test1.BFCESTwoKeyNavRTStringParam"
- + "(ParameterComp=@p1) eq 0&@p1={\"PropertyInt16\":1,\"ProperyString\":\"1\"")
+ + "(ParameterComp=@p1) eq 0&@p1={\"PropertyInt16\":1,\"PropertyString\":\"1\"")
.isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
testUri.runEx("ESTwoKeyNav", "$filter=olingo.odata.test1.BFCESTwoKeyNavRTStringParam"
- + "(ParameterComp=@p1) eq 0&@p1={\"PropertyInt16\":1,\"ProperyString\":\"1\"}}")
+ + "(ParameterComp=@p1) eq 0&@p1={\"PropertyInt16\":1,\"PropertyString\":\"1\"}}")
.isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
testUri.runEx("ESTwoKeyNav", "$filter=olingo.odata.test1.BFCESTwoKeyNavRTStringParam"
- + "(ParameterComp=@p1) eq 0&@p1={\"PropertyInt16\":[1,2,3]],\"ProperyString\":\"1\"}")
+ + "(ParameterComp=@p1) eq 0&@p1={\"PropertyInt16\":[1,2,3]],\"PropertyString\":\"1\"}")
.isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
testUri.runEx("ESTwoKeyNav", "$filter=olingo.odata.test1.BFCESTwoKeyNavRTStringParam"
- + "(ParameterComp=@p1) eq 0&@p1={\"PropertyInt16\":[1,2,3,\"ProperyString\":\"1\"}")
+ + "(ParameterComp=@p1) eq 0&@p1={\"PropertyInt16\":[1,2,3,\"PropertyString\":\"1\"}")
.isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
testUri.runEx("ESTwoKeyNav", "$filter=olingo.odata.test1.BFCESTwoKeyNavRTStringParam"
- + "(ParameterComp=@p1) eq 0&@p1={\"PropertyInt16\":[1,2,3},\"ProperyString\":\"1\"}")
+ + "(ParameterComp=@p1) eq 0&@p1={\"PropertyInt16\":[1,2,3},\"PropertyString\":\"1\"}")
.isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
}
[13/30] olingo-odata4 git commit: [OLINGO-834] ExpressionParser uses
UriTokenizer
Posted by ch...@apache.org.
[OLINGO-834] ExpressionParser uses UriTokenizer
Signed-off-by: Christian Amend <ch...@sap.com>
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/2f3bc286
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/2f3bc286
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/2f3bc286
Branch: refs/heads/master
Commit: 2f3bc2866befb2f8f75a81ecb4952950dc3913df
Parents: 208f26c
Author: Klaus Straubinger <kl...@sap.com>
Authored: Fri Dec 11 16:48:38 2015 +0100
Committer: Christian Amend <ch...@sap.com>
Committed: Mon Dec 14 10:12:22 2015 +0100
----------------------------------------------------------------------
.../core/uri/parser/ExpressionParser.java | 499 +++++++------------
.../olingo/server/core/uri/parser/Parser.java | 8 +
.../server/core/uri/parser/ParserHelper.java | 65 +++
.../core/uri/parser/ResourcePathParser.java | 130 +++--
.../server/core/uri/parser/SelectParser.java | 15 +-
.../server/core/uri/parser/UriTokenizer.java | 291 ++++++++++-
.../uri/queryoption/expression/UnaryImpl.java | 2 +-
.../core/uri/parser/ExpressionParserTest.java | 174 +++----
.../core/uri/parser/UriTokenizerTest.java | 313 +++++++-----
9 files changed, 841 insertions(+), 656 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2f3bc286/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java
index 854536d..3b04089 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java
@@ -32,6 +32,7 @@ import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
import org.apache.olingo.server.api.uri.queryoption.expression.Method;
import org.apache.olingo.server.api.uri.queryoption.expression.MethodKind;
import org.apache.olingo.server.api.uri.queryoption.expression.UnaryOperatorKind;
+import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind;
import org.apache.olingo.server.core.uri.queryoption.expression.AliasImpl;
import org.apache.olingo.server.core.uri.queryoption.expression.BinaryImpl;
import org.apache.olingo.server.core.uri.queryoption.expression.LiteralImpl;
@@ -39,75 +40,73 @@ import org.apache.olingo.server.core.uri.queryoption.expression.MethodImpl;
import org.apache.olingo.server.core.uri.queryoption.expression.UnaryImpl;
public class ExpressionParser {
- private Tokenizer tokenizer;
-
private static final Map<TokenKind, BinaryOperatorKind> tokenToBinaryOperator;
static {
- Map<TokenKind, BinaryOperatorKind> temp = new HashMap<ExpressionParser.TokenKind, BinaryOperatorKind>();
- temp.put(TokenKind.OR_OP, BinaryOperatorKind.OR);
- temp.put(TokenKind.AND_OP, BinaryOperatorKind.AND);
+ Map<TokenKind, BinaryOperatorKind> temp = new HashMap<TokenKind, BinaryOperatorKind>();
+ temp.put(TokenKind.OrOperator, BinaryOperatorKind.OR);
+ temp.put(TokenKind.AndOperator, BinaryOperatorKind.AND);
- temp.put(TokenKind.EQ_OP, BinaryOperatorKind.EQ);
- temp.put(TokenKind.NE_OP, BinaryOperatorKind.NE);
+ temp.put(TokenKind.EqualsOperator, BinaryOperatorKind.EQ);
+ temp.put(TokenKind.NotEqualsOperator, BinaryOperatorKind.NE);
- temp.put(TokenKind.GT_OP, BinaryOperatorKind.GT);
- temp.put(TokenKind.GE_OP, BinaryOperatorKind.GE);
- temp.put(TokenKind.LT_OP, BinaryOperatorKind.LT);
- temp.put(TokenKind.LE_OP, BinaryOperatorKind.LE);
+ temp.put(TokenKind.GreaterThanOperator, BinaryOperatorKind.GT);
+ temp.put(TokenKind.GreaterThanOrEqualsOperator, BinaryOperatorKind.GE);
+ temp.put(TokenKind.LessThanOperator, BinaryOperatorKind.LT);
+ temp.put(TokenKind.LessThanOrEqualsOperator, BinaryOperatorKind.LE);
- temp.put(TokenKind.ADD_OP, BinaryOperatorKind.ADD);
- temp.put(TokenKind.SUB_OP, BinaryOperatorKind.SUB);
+ temp.put(TokenKind.AddOperator, BinaryOperatorKind.ADD);
+ temp.put(TokenKind.SubOperator, BinaryOperatorKind.SUB);
- temp.put(TokenKind.MUL_OP, BinaryOperatorKind.MUL);
- temp.put(TokenKind.DIV_OP, BinaryOperatorKind.DIV);
- temp.put(TokenKind.MOD_OP, BinaryOperatorKind.MOD);
+ temp.put(TokenKind.MulOperator, BinaryOperatorKind.MUL);
+ temp.put(TokenKind.DivOperator, BinaryOperatorKind.DIV);
+ temp.put(TokenKind.ModOperator, BinaryOperatorKind.MOD);
tokenToBinaryOperator = Collections.unmodifiableMap(temp);
}
private static final Map<TokenKind, UnaryOperatorKind> tokenToUnaryOperator;
static {
- Map<TokenKind, UnaryOperatorKind> temp = new HashMap<ExpressionParser.TokenKind, UnaryOperatorKind>();
+ Map<TokenKind, UnaryOperatorKind> temp = new HashMap<TokenKind, UnaryOperatorKind>();
temp.put(TokenKind.MINUS, UnaryOperatorKind.MINUS);
- temp.put(TokenKind.NOT, UnaryOperatorKind.NOT);
+ temp.put(TokenKind.NotOperator, UnaryOperatorKind.NOT);
tokenToUnaryOperator = Collections.unmodifiableMap(temp);
}
private static final Map<TokenKind, MethodKind> tokenToMethod;
static {
- Map<TokenKind, MethodKind> temp = new HashMap<ExpressionParser.TokenKind, MethodKind>();
- temp.put(TokenKind.Cast, MethodKind.CAST);
- temp.put(TokenKind.Ceiling, MethodKind.CEILING);
- temp.put(TokenKind.Concat, MethodKind.CONCAT);
- temp.put(TokenKind.Contains, MethodKind.CONTAINS);
- temp.put(TokenKind.Date, MethodKind.DATE);
- temp.put(TokenKind.Day, MethodKind.DAY);
- temp.put(TokenKind.Endswith, MethodKind.ENDSWITH);
- temp.put(TokenKind.Floor, MethodKind.FLOOR);
- temp.put(TokenKind.Fractionalseconds, MethodKind.FRACTIONALSECONDS);
- temp.put(TokenKind.GeoDistance, MethodKind.GEODISTANCE);
- temp.put(TokenKind.GeoIntersects, MethodKind.GEOINTERSECTS);
- temp.put(TokenKind.GeoLength, MethodKind.GEOLENGTH);
- temp.put(TokenKind.Hour, MethodKind.HOUR);
- temp.put(TokenKind.Indexof, MethodKind.INDEXOF);
- temp.put(TokenKind.Isof, MethodKind.ISOF);
- temp.put(TokenKind.Length, MethodKind.LENGTH);
- temp.put(TokenKind.Maxdatetime, MethodKind.MAXDATETIME);
- temp.put(TokenKind.Mindatetime, MethodKind.MINDATETIME);
- temp.put(TokenKind.Minute, MethodKind.MINUTE);
- temp.put(TokenKind.Month, MethodKind.MONTH);
- temp.put(TokenKind.Now, MethodKind.NOW);
- temp.put(TokenKind.Round, MethodKind.ROUND);
- temp.put(TokenKind.Second, MethodKind.SECOND);
- temp.put(TokenKind.Startswith, MethodKind.STARTSWITH);
- temp.put(TokenKind.Substring, MethodKind.SUBSTRING);
- temp.put(TokenKind.Time, MethodKind.TIME);
- temp.put(TokenKind.Tolower, MethodKind.TOLOWER);
- temp.put(TokenKind.Totaloffsetminutes, MethodKind.TOTALOFFSETMINUTES);
- temp.put(TokenKind.Totalseconds, MethodKind.TOTALSECONDS);
- temp.put(TokenKind.Toupper, MethodKind.TOUPPER);
- temp.put(TokenKind.Trim, MethodKind.TRIM);
- temp.put(TokenKind.Year, MethodKind.YEAR);
+ Map<TokenKind, MethodKind> temp = new HashMap<TokenKind, MethodKind>();
+ temp.put(TokenKind.CastMethod, MethodKind.CAST);
+ temp.put(TokenKind.CeilingMethod, MethodKind.CEILING);
+ temp.put(TokenKind.ConcatMethod, MethodKind.CONCAT);
+ temp.put(TokenKind.ContainsMethod, MethodKind.CONTAINS);
+ temp.put(TokenKind.DateMethod, MethodKind.DATE);
+ temp.put(TokenKind.DayMethod, MethodKind.DAY);
+ temp.put(TokenKind.EndswithMethod, MethodKind.ENDSWITH);
+ temp.put(TokenKind.FloorMethod, MethodKind.FLOOR);
+ temp.put(TokenKind.FractionalsecondsMethod, MethodKind.FRACTIONALSECONDS);
+ temp.put(TokenKind.GeoDistanceMethod, MethodKind.GEODISTANCE);
+ temp.put(TokenKind.GeoIntersectsMethod, MethodKind.GEOINTERSECTS);
+ temp.put(TokenKind.GeoLengthMethod, MethodKind.GEOLENGTH);
+ temp.put(TokenKind.HourMethod, MethodKind.HOUR);
+ temp.put(TokenKind.IndexofMethod, MethodKind.INDEXOF);
+ temp.put(TokenKind.IsofMethod, MethodKind.ISOF);
+ temp.put(TokenKind.LengthMethod, MethodKind.LENGTH);
+ temp.put(TokenKind.MaxdatetimeMethod, MethodKind.MAXDATETIME);
+ temp.put(TokenKind.MindatetimeMethod, MethodKind.MINDATETIME);
+ temp.put(TokenKind.MinuteMethod, MethodKind.MINUTE);
+ temp.put(TokenKind.MonthMethod, MethodKind.MONTH);
+ temp.put(TokenKind.NowMethod, MethodKind.NOW);
+ temp.put(TokenKind.RoundMethod, MethodKind.ROUND);
+ temp.put(TokenKind.SecondMethod, MethodKind.SECOND);
+ temp.put(TokenKind.StartswithMethod, MethodKind.STARTSWITH);
+ temp.put(TokenKind.SubstringMethod, MethodKind.SUBSTRING);
+ temp.put(TokenKind.TimeMethod, MethodKind.TIME);
+ temp.put(TokenKind.TolowerMethod, MethodKind.TOLOWER);
+ temp.put(TokenKind.TotaloffsetminutesMethod, MethodKind.TOTALOFFSETMINUTES);
+ temp.put(TokenKind.TotalsecondsMethod, MethodKind.TOTALSECONDS);
+ temp.put(TokenKind.ToupperMethod, MethodKind.TOUPPER);
+ temp.put(TokenKind.TrimMethod, MethodKind.TRIM);
+ temp.put(TokenKind.YearMethod, MethodKind.YEAR);
tokenToMethod = Collections.unmodifiableMap(temp);
}
@@ -115,24 +114,26 @@ public class ExpressionParser {
private static final Map<TokenKind, EdmPrimitiveTypeKind> tokenToPrimitiveType;
static {
/* Enum and null are not present in the map. These have to be handled differently */
- Map<TokenKind, EdmPrimitiveTypeKind> temp = new HashMap<ExpressionParser.TokenKind, EdmPrimitiveTypeKind>();
- temp.put(TokenKind.PrimitiveBooleanValue, EdmPrimitiveTypeKind.Boolean);
- temp.put(TokenKind.PrimitiveStringValue, EdmPrimitiveTypeKind.String);
+ Map<TokenKind, EdmPrimitiveTypeKind> temp = new HashMap<TokenKind, EdmPrimitiveTypeKind>();
+ temp.put(TokenKind.BooleanValue, EdmPrimitiveTypeKind.Boolean);
+ temp.put(TokenKind.StringValue, EdmPrimitiveTypeKind.String);
// TODO:Check if int64 is correct here or if it has to be single instead
- temp.put(TokenKind.PrimitiveIntegerValue, EdmPrimitiveTypeKind.Int64);
- temp.put(TokenKind.PrimitiveGuidValue, EdmPrimitiveTypeKind.Guid);
- temp.put(TokenKind.PrimitiveDateValue, EdmPrimitiveTypeKind.Date);
- temp.put(TokenKind.PrimitiveDateTimeOffsetValue, EdmPrimitiveTypeKind.DateTimeOffset);
- temp.put(TokenKind.PrimitiveTimeOfDayValue, EdmPrimitiveTypeKind.TimeOfDay);
- temp.put(TokenKind.PrimitiveDecimalValue, EdmPrimitiveTypeKind.Decimal);
- temp.put(TokenKind.PrimitiveDoubleValue, EdmPrimitiveTypeKind.Double);
- temp.put(TokenKind.PrimitiveDurationValue, EdmPrimitiveTypeKind.Duration);
- temp.put(TokenKind.PrimitiveBinaryValue, EdmPrimitiveTypeKind.Binary);
+ temp.put(TokenKind.IntegerValue, EdmPrimitiveTypeKind.Int64);
+ temp.put(TokenKind.GuidValue, EdmPrimitiveTypeKind.Guid);
+ temp.put(TokenKind.DateValue, EdmPrimitiveTypeKind.Date);
+ temp.put(TokenKind.DateTimeOffsetValue, EdmPrimitiveTypeKind.DateTimeOffset);
+ temp.put(TokenKind.TimeOfDayValue, EdmPrimitiveTypeKind.TimeOfDay);
+ temp.put(TokenKind.DecimalValue, EdmPrimitiveTypeKind.Decimal);
+ temp.put(TokenKind.DoubleValue, EdmPrimitiveTypeKind.Double);
+ temp.put(TokenKind.DurationValue, EdmPrimitiveTypeKind.Duration);
+ temp.put(TokenKind.BinaryValue, EdmPrimitiveTypeKind.Binary);
tokenToPrimitiveType = Collections.unmodifiableMap(temp);
}
- public Expression parse(Tokenizer tokenizer) throws UriParserException {
+ private UriTokenizer tokenizer;
+
+ public Expression parse(UriTokenizer tokenizer) throws UriParserException {
// Initialize tokenizer.
this.tokenizer = tokenizer;
@@ -141,23 +142,17 @@ public class ExpressionParser {
private Expression parseExpression() throws UriParserException {
Expression left = parseAnd();
-
- while (is(TokenKind.OR_OP) != null) {
- tokenizer.getText();
-
- Expression right = parseAnd();
+ while (tokenizer.next(TokenKind.OrOperator)) {
+ final Expression right = parseAnd();
left = new BinaryImpl(left, BinaryOperatorKind.OR, right);
}
-
return left;
}
private Expression parseAnd() throws UriParserException {
Expression left = parseExprEquality();
- while (is(TokenKind.AND_OP) != null) {
- tokenizer.getText();
-
- Expression right = parseExprEquality();
+ while (tokenizer.next(TokenKind.AndOperator)) {
+ final Expression right = parseExprEquality();
left = new BinaryImpl(left, BinaryOperatorKind.AND, right);
}
return left;
@@ -165,110 +160,107 @@ public class ExpressionParser {
private Expression parseExprEquality() throws UriParserException {
Expression left = parseExprRel();
-
- TokenKind nextTokenKind = is(TokenKind.EQ_OP, TokenKind.NE_OP);
+ TokenKind operatorTokenKind = ParserHelper.next(tokenizer, TokenKind.EqualsOperator, TokenKind.NotEqualsOperator);
// Null for everything other than EQ or NE
- while (nextTokenKind != null) {
- tokenizer.getText();
-
- Expression right = parseExprEquality();
- left = new BinaryImpl(left, tokenToBinaryOperator.get(nextTokenKind), right);
- nextTokenKind = is(TokenKind.EQ_OP, TokenKind.NE_OP);
+ while (operatorTokenKind != null) {
+ final Expression right = parseExprEquality();
+ left = new BinaryImpl(left, tokenToBinaryOperator.get(operatorTokenKind), right);
+ operatorTokenKind = ParserHelper.next(tokenizer, TokenKind.EqualsOperator, TokenKind.NotEqualsOperator);
}
-
return left;
}
private Expression parseExprRel() throws UriParserException {
Expression left = parseExprAdd();
-
- TokenKind nextTokenKind = is(TokenKind.GT_OP, TokenKind.GE_OP, TokenKind.LT_OP, TokenKind.LE_OP);
+ TokenKind operatorTokenKind = ParserHelper.next(tokenizer,
+ TokenKind.GreaterThanOperator, TokenKind.GreaterThanOrEqualsOperator,
+ TokenKind.LessThanOperator, TokenKind.LessThanOrEqualsOperator);
// Null for everything other than GT or GE or LT or LE
- while (nextTokenKind != null) {
- tokenizer.getText();
-
- Expression right = parseExprAdd();
- left = new BinaryImpl(left, tokenToBinaryOperator.get(nextTokenKind), right);
- nextTokenKind = is(TokenKind.GT_OP, TokenKind.GE_OP, TokenKind.LT_OP, TokenKind.LE_OP);
+ while (operatorTokenKind != null) {
+ final Expression right = parseExprAdd();
+ left = new BinaryImpl(left, tokenToBinaryOperator.get(operatorTokenKind), right);
+ operatorTokenKind = ParserHelper.next(tokenizer,
+ TokenKind.GreaterThanOperator, TokenKind.GreaterThanOrEqualsOperator,
+ TokenKind.LessThanOperator, TokenKind.LessThanOrEqualsOperator);
}
-
return left;
}
private Expression parseExprAdd() throws UriParserException {
Expression left = parseExprMul();
-
- TokenKind nextTokenKind = is(TokenKind.ADD_OP, TokenKind.SUB_OP);
+ TokenKind operatorTokenKind = ParserHelper.next(tokenizer, TokenKind.AddOperator, TokenKind.SubOperator);
// Null for everything other than ADD or SUB
- while (nextTokenKind != null) {
- tokenizer.getText();
-
- Expression right = parseExprMul();
- left = new BinaryImpl(left, tokenToBinaryOperator.get(nextTokenKind), right);
- nextTokenKind = is(TokenKind.ADD_OP, TokenKind.SUB_OP);
+ while (operatorTokenKind != null) {
+ final Expression right = parseExprMul();
+ left = new BinaryImpl(left, tokenToBinaryOperator.get(operatorTokenKind), right);
+ operatorTokenKind = ParserHelper.next(tokenizer, TokenKind.AddOperator, TokenKind.SubOperator);
}
-
return left;
}
private Expression parseExprMul() throws UriParserException {
Expression left = parseExprUnary();
-
- TokenKind nextTokenKind = is(TokenKind.MUL_OP, TokenKind.DIV_OP, TokenKind.MOD_OP);
+ TokenKind operatorTokenKind = ParserHelper.next(tokenizer,
+ TokenKind.MulOperator, TokenKind.DivOperator, TokenKind.ModOperator);
// Null for everything other than MUL or DIV or MOD
- while (nextTokenKind != null) {
- tokenizer.getText();
-
- Expression right = parseExprUnary();
- left = new BinaryImpl(left, tokenToBinaryOperator.get(nextTokenKind), right);
- nextTokenKind = is(TokenKind.MUL_OP, TokenKind.DIV_OP, TokenKind.MOD_OP);
+ while (operatorTokenKind != null) {
+ final Expression right = parseExprUnary();
+ left = new BinaryImpl(left, tokenToBinaryOperator.get(operatorTokenKind), right);
+ operatorTokenKind = ParserHelper.next(tokenizer,
+ TokenKind.MulOperator, TokenKind.DivOperator, TokenKind.ModOperator);
}
-
return left;
}
private Expression parseExprUnary() throws UriParserException {
Expression left = null;
- TokenKind nextTokenKind = is(TokenKind.MINUS, TokenKind.NOT);
+ TokenKind operatorTokenKind = ParserHelper.next(tokenizer, TokenKind.MINUS, TokenKind.NotOperator);
// Null for everything other than - or NOT
- while (nextTokenKind != null) {
- tokenizer.getText();
-
- Expression exp = parseExprValue();
- left = new UnaryImpl(tokenToUnaryOperator.get(nextTokenKind), exp);
- nextTokenKind = is(TokenKind.MINUS, TokenKind.NOT);
+ while (operatorTokenKind != null) {
+ final Expression expression = parseExprValue();
+ left = new UnaryImpl(tokenToUnaryOperator.get(operatorTokenKind), expression);
+ operatorTokenKind = ParserHelper.next(tokenizer, TokenKind.MINUS, TokenKind.NotOperator);
}
-
if (left == null) {
left = parseExprValue();
}
-
return left;
}
private Expression parseExprValue() throws UriParserException {
- if (is(TokenKind.OPEN) != null) {
- tokenizer.getText();
- Expression exp = parseExpression();
- require(TokenKind.CLOSE);
- return exp;
+ if (tokenizer.next(TokenKind.OPEN)) {
+ final Expression expression = parseExpression();
+ ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
+ return expression;
}
- if (is(TokenKind.ParameterAlias) != null) {
+ if (tokenizer.next(TokenKind.ParameterAliasName)) {
return new AliasImpl(tokenizer.getText());
}
- if (is(TokenKind.RootExpr) != null) {
- tokenizer.getText();
- // TODO: Consume $root Expression.
+ if (tokenizer.next(TokenKind.jsonArrayOrObject)) {
+ // TODO: Can the type be determined?
+ return new LiteralImpl(tokenizer.getText(), null);
}
- TokenKind nextPrimitive = isPrimitive();
+ if (tokenizer.next(TokenKind.ROOT)) {
+ // TODO: Consume $root expression.
+ }
+
+ if (tokenizer.next(TokenKind.IT)) {
+ // TODO: Consume $it expression.
+ }
+
+ if (tokenizer.next(TokenKind.QualifiedName)) {
+ // TODO: Consume typecast or bound-function expression.
+ }
+
+ TokenKind nextPrimitive = ParserHelper.nextPrimitive(tokenizer);
if (nextPrimitive != null) {
- EdmPrimitiveTypeKind primitiveTypeKind = tokenToPrimitiveType.get(nextPrimitive);
+ final EdmPrimitiveTypeKind primitiveTypeKind = tokenToPrimitiveType.get(nextPrimitive);
EdmPrimitiveType type;
if (primitiveTypeKind == null) {
- if (nextPrimitive == TokenKind.PrimitiveEnumValue) {
+ if (nextPrimitive == TokenKind.EnumValue) {
// TODO: Get enum type.
type = null;
} else {
@@ -281,22 +273,16 @@ public class ExpressionParser {
return new LiteralImpl(tokenizer.getText(), type);
}
- TokenKind nextMethod = isMethod();
+ TokenKind nextMethod = nextMethod();
if (nextMethod != null) {
MethodKind methodKind = tokenToMethod.get(nextMethod);
List<Expression> parameters = new ArrayList<Expression>();
- // Consume Method name.
- tokenizer.getText();
- if (is(TokenKind.CLOSE) != null) {
- // Consume closing parenthesis.
- tokenizer.getText();
- } else {
- parameters.add(parseExpression());
- while (is(TokenKind.COMMA) != null) {
- tokenizer.getText();
+ // The method token text includes the opening parenthesis!
+ if (!tokenizer.next(TokenKind.CLOSE)) {
+ do {
parameters.add(parseExpression());
- }
- require(TokenKind.CLOSE);
+ } while (tokenizer.next(TokenKind.COMMA));
+ ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
}
MethodImpl methodImpl = new MethodImpl(methodKind, parameters);
@@ -305,6 +291,10 @@ public class ExpressionParser {
return methodImpl;
}
+ if (tokenizer.next(TokenKind.ODataIdentifier)) {
+ // TODO: Consume property-path or lambda-variable expression.
+ }
+
throw new UriParserSyntaxException("Unexpected token", UriParserSyntaxException.MessageKeys.SYNTAX);
}
@@ -356,7 +346,7 @@ public class ExpressionParser {
case NOW:
case MAXDATETIME:
case MINDATETIME:
- if (size != 0) {
+ if (size > 0) {
throw new UriParserSemanticException("The method '" + method.getMethod() + "' must have no parameters.",
null); // TODO: message key
}
@@ -384,192 +374,39 @@ public class ExpressionParser {
}
}
- private String require(TokenKind required) throws UriParserException {
- if (is(required) == null) {
- throw new UriParserSyntaxException("Required token: " + required,
- UriParserSyntaxException.MessageKeys.SYNTAX);
- }
- return tokenizer.getText();
- }
-
- private TokenKind is(TokenKind... kind) {
- for (int i = 0; i < kind.length; i++) {
- if (tokenizer.next(kind[i])) {
- return kind[i];
- }
- }
- return null;
- }
-
- private TokenKind isMethod() {
- return is(TokenKind.Cast,
- TokenKind.Ceiling,
- TokenKind.Concat,
- TokenKind.Contains,
- TokenKind.Date,
- TokenKind.Day,
- TokenKind.Endswith,
- TokenKind.Floor,
- TokenKind.Fractionalseconds,
- TokenKind.GeoDistance,
- TokenKind.GeoIntersects,
- TokenKind.GeoLength,
- TokenKind.Hour,
- TokenKind.Indexof,
- TokenKind.Isof,
- TokenKind.Length,
- TokenKind.Maxdatetime,
- TokenKind.Mindatetime,
- TokenKind.Minute,
- TokenKind.Month,
- TokenKind.Now,
- TokenKind.Round,
- TokenKind.Second,
- TokenKind.Startswith,
- TokenKind.Substring,
- TokenKind.Time,
- TokenKind.Tolower,
- TokenKind.Totaloffsetminutes,
- TokenKind.Totalseconds,
- TokenKind.Toupper,
- TokenKind.Trim,
- TokenKind.Year);
- }
-
- private TokenKind isPrimitive() {
- return is(TokenKind.PrimitiveNullValue,
- TokenKind.PrimitiveBooleanValue,
- TokenKind.PrimitiveStringValue,
-
- // The order of the next seven expressions is important in order to avoid
- // finding partly parsed tokens (counter-intuitive as it may be, even a GUID may start with digits ...).
- TokenKind.PrimitiveDoubleValue,
- TokenKind.PrimitiveDecimalValue,
- TokenKind.PrimitiveGuidValue,
- TokenKind.PrimitiveDateTimeOffsetValue,
- TokenKind.PrimitiveDateValue,
- TokenKind.PrimitiveTimeOfDayValue,
- TokenKind.PrimitiveIntegerValue,
- TokenKind.PrimitiveDurationValue,
- TokenKind.PrimitiveBinaryValue,
- TokenKind.PrimitiveEnumValue);
- }
-
- public enum TokenKind {
- // BINARY
- OR_OP,
- AND_OP,
-
- EQ_OP,
- NE_OP,
-
- GT_OP,
- GE_OP,
- LT_OP,
- LE_OP,
-
- ADD_OP,
- SUB_OP,
-
- MUL_OP,
- DIV_OP,
- MOD_OP,
-
- MINUS,
- NOT,
-
- // Grouping
- OPEN,
- CLOSE,
-
- // PrimitiveValues
- PrimitiveNullValue,
- PrimitiveBooleanValue,
-
- PrimitiveStringValue,
- PrimitiveIntegerValue,
- PrimitiveGuidValue,
- PrimitiveDateValue,
- PrimitiveDateTimeOffsetValue,
- PrimitiveTimeOfDayValue,
- PrimitiveDecimalValue,
- PrimitiveDoubleValue,
- PrimitiveDurationValue,
- PrimitiveBinaryValue,
- PrimitiveEnumValue,
-
- // ExpressionValues
- ParameterAlias,
- ArrayOrObject,
- RootExpr,
- IT,
-
- // BuiltInMethods
- Cast,
- Ceiling,
- Concat,
- Contains,
- Date,
- Day,
- Endswith,
- Floor,
- Fractionalseconds,
- GeoDistance,
- GeoIntersects,
- GeoLength,
- Hour,
- Indexof,
- Isof,
- Length,
- Maxdatetime,
- Mindatetime,
- Minute,
- Month,
- Now,
- Round,
- Second,
- Startswith,
- Substring,
- Time,
- Tolower,
- Totaloffsetminutes,
- Totalseconds,
- Toupper,
- Trim,
- Year,
- COMMA
- }
-
- public static class Token {
- TokenKind kind;
- String text;
-
- public Token(TokenKind kind, String text) {
- this.kind = kind;
- this.text = text;
- }
- }
-
- public static class Tokenizer {
- private List<Token> tokens;
- int counter = 0;
-
- public Tokenizer(List<Token> tokens) {
- this.tokens = tokens;
- }
-
- public boolean next(TokenKind expectedKind) {
- if (counter < tokens.size() && expectedKind == tokens.get(counter).kind) {
- return true;
- }
- return false;
- }
-
- public String getText() {
- String text = tokens.get(counter).text;
- counter++;
- return text;
- }
+ private TokenKind nextMethod() {
+ return ParserHelper.next(tokenizer,
+ TokenKind.CastMethod,
+ TokenKind.CeilingMethod,
+ TokenKind.ConcatMethod,
+ TokenKind.ContainsMethod,
+ TokenKind.DateMethod,
+ TokenKind.DayMethod,
+ TokenKind.EndswithMethod,
+ TokenKind.FloorMethod,
+ TokenKind.FractionalsecondsMethod,
+ TokenKind.GeoDistanceMethod,
+ TokenKind.GeoIntersectsMethod,
+ TokenKind.GeoLengthMethod,
+ TokenKind.HourMethod,
+ TokenKind.IndexofMethod,
+ TokenKind.IsofMethod,
+ TokenKind.LengthMethod,
+ TokenKind.MaxdatetimeMethod,
+ TokenKind.MindatetimeMethod,
+ TokenKind.MinuteMethod,
+ TokenKind.MonthMethod,
+ TokenKind.NowMethod,
+ TokenKind.RoundMethod,
+ TokenKind.SecondMethod,
+ TokenKind.StartswithMethod,
+ TokenKind.SubstringMethod,
+ TokenKind.TimeMethod,
+ TokenKind.TolowerMethod,
+ TokenKind.TotaloffsetminutesMethod,
+ TokenKind.TotalsecondsMethod,
+ TokenKind.ToupperMethod,
+ TokenKind.TrimMethod,
+ TokenKind.YearMethod);
}
-
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2f3bc286/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
index 0b53e69..2a994d3 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
@@ -208,6 +208,14 @@ public class Parser {
(UriParserException) e.getCause() :
new UriParserSyntaxException("Syntax error", e, UriParserSyntaxException.MessageKeys.SYNTAX);
}
+// UriTokenizer filterTokenizer = new UriTokenizer(optionValue);
+// systemOption = new FilterOptionImpl().setExpression(
+// new ExpressionParser().parse(filterTokenizer));
+// if (!filterTokenizer.next(TokenKind.EOF)) {
+// throw new UriParserSyntaxException("Illegal value of $filter option!",
+// UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION,
+// optionName, optionValue);
+// }
} else if (optionName.equals(SystemQueryOptionKind.FORMAT.toString())) {
FormatOptionImpl formatOption = new FormatOptionImpl();
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2f3bc286/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java
new file mode 100644
index 0000000..e811575
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java
@@ -0,0 +1,65 @@
+/*
+ * 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 org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind;
+
+public class ParserHelper {
+
+ public static void requireNext(UriTokenizer tokenizer, final TokenKind required) throws UriParserException {
+ if (!tokenizer.next(required)) {
+ throw new UriParserSyntaxException("Expected token '" + required.toString() + "' not found.",
+ UriParserSyntaxException.MessageKeys.SYNTAX);
+ }
+ }
+
+ public static void requireTokenEnd(UriTokenizer tokenizer) throws UriParserException {
+ requireNext(tokenizer, TokenKind.EOF);
+ }
+
+ public static TokenKind next(UriTokenizer tokenizer, final TokenKind... kind) {
+ for (int i = 0; i < kind.length; i++) {
+ if (tokenizer.next(kind[i])) {
+ return kind[i];
+ }
+ }
+ return null;
+ }
+
+ public static TokenKind nextPrimitive(UriTokenizer tokenizer) {
+ return next(tokenizer,
+ TokenKind.NULL,
+ TokenKind.BooleanValue,
+ TokenKind.StringValue,
+
+ // The order of the next seven expressions is important in order to avoid
+ // finding partly parsed tokens (counter-intuitive as it may be, even a GUID may start with digits ...).
+ TokenKind.DoubleValue,
+ TokenKind.DecimalValue,
+ TokenKind.GuidValue,
+ TokenKind.DateTimeOffsetValue,
+ TokenKind.DateValue,
+ TokenKind.TimeOfDayValue,
+ TokenKind.IntegerValue,
+
+ TokenKind.DurationValue,
+ TokenKind.BinaryValue,
+ TokenKind.EnumValue);
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2f3bc286/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ResourcePathParser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ResourcePathParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ResourcePathParser.java
index 9852011..5d2fbde 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ResourcePathParser.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ResourcePathParser.java
@@ -115,9 +115,9 @@ public class ResourcePathParser {
public UriInfoImpl parseDollarEntityTypeCast(final String pathSegment) throws UriParserException {
UriInfoImpl uriInfo = new UriInfoImpl().setKind(UriInfoKind.entityId);
tokenizer = new UriTokenizer(pathSegment);
- requireNext(TokenKind.QualifiedName);
+ ParserHelper.requireNext(tokenizer, TokenKind.QualifiedName);
final String name = tokenizer.getText();
- requireTokenEnd();
+ ParserHelper.requireTokenEnd(tokenizer);
final EdmEntityType type = edm.getEntityType(new FullQualifiedName(name));
if (type == null) {
throw new UriParserSemanticException("Type '" + name + "' not found.",
@@ -131,11 +131,11 @@ public class ResourcePathParser {
public UriInfoImpl parseCrossjoinSegment(final String pathSegment) throws UriParserException {
UriInfoImpl uriInfo = new UriInfoImpl().setKind(UriInfoKind.crossjoin);
tokenizer = new UriTokenizer(pathSegment);
- requireNext(TokenKind.CROSSJOIN);
- requireNext(TokenKind.OPEN);
+ ParserHelper.requireNext(tokenizer, TokenKind.CROSSJOIN);
+ ParserHelper.requireNext(tokenizer, TokenKind.OPEN);
// At least one entity-set name is mandatory. Try to fetch all.
do {
- requireNext(TokenKind.ODataIdentifier);
+ ParserHelper.requireNext(tokenizer, TokenKind.ODataIdentifier);
final String name = tokenizer.getText();
final EdmEntitySet edmEntitySet = edmEntityContainer.getEntitySet(name);
if (edmEntitySet == null) {
@@ -145,13 +145,13 @@ public class ResourcePathParser {
uriInfo.addEntitySetName(name);
}
} while (tokenizer.next(TokenKind.COMMA));
- requireNext(TokenKind.CLOSE);
- requireTokenEnd();
+ ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
+ ParserHelper.requireTokenEnd(tokenizer);
return uriInfo;
}
private UriResource ref(final UriResource previous) throws UriParserException {
- requireTokenEnd();
+ ParserHelper.requireTokenEnd(tokenizer);
requireTyped(previous, "$ref");
if (((UriResourcePartTyped) previous).getType() instanceof EdmEntityType) {
return new UriResourceRefImpl();
@@ -162,7 +162,7 @@ public class ResourcePathParser {
}
private UriResource value(final UriResource previous) throws UriParserException {
- requireTokenEnd();
+ ParserHelper.requireTokenEnd(tokenizer);
requireTyped(previous, "$value");
if (!((UriResourcePartTyped) previous).isCollection()) {
return new UriResourceValueImpl();
@@ -173,7 +173,7 @@ public class ResourcePathParser {
}
private UriResource count(final UriResource previous) throws UriParserException {
- requireTokenEnd();
+ ParserHelper.requireTokenEnd(tokenizer);
requireTyped(previous, "$count");
if (((UriResourcePartTyped) previous).isCollection()) {
return new UriResourceCountImpl();
@@ -195,19 +195,19 @@ public class ResourcePathParser {
entitySetResource.setKeyPredicates(keyPredicates);
}
- requireTokenEnd();
+ ParserHelper.requireTokenEnd(tokenizer);
return entitySetResource;
}
final EdmSingleton edmSingleton = edmEntityContainer.getSingleton(oDataIdentifier);
if (edmSingleton != null) {
- requireTokenEnd();
+ ParserHelper.requireTokenEnd(tokenizer);
return new UriResourceSingletonImpl().setSingleton(edmSingleton);
}
final EdmActionImport edmActionImport = edmEntityContainer.getActionImport(oDataIdentifier);
if (edmActionImport != null) {
- requireTokenEnd();
+ ParserHelper.requireTokenEnd(tokenizer);
return new UriResourceActionImpl().setActionImport(edmActionImport);
}
@@ -271,7 +271,7 @@ public class ResourcePathParser {
UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED);
}
}
- requireTokenEnd();
+ ParserHelper.requireTokenEnd(tokenizer);
return new UriResourceNavigationPropertyImpl()
.setNavigationProperty(navigationProperty)
.setKeyPredicates(keyPredicate);
@@ -288,7 +288,7 @@ public class ResourcePathParser {
previousType.getFullQualifiedName(),
previousTyped.isCollection());
if (boundAction != null) {
- requireTokenEnd();
+ ParserHelper.requireTokenEnd(tokenizer);
return new UriResourceActionImpl().setAction(boundAction);
}
EdmStructuredType type = edm.getEntityType(name);
@@ -386,7 +386,7 @@ public class ResourcePathParser {
edmProperty == null ? null : (EdmPrimitiveType) edmProperty.getType(),
edmProperty == null ? false : edmProperty.isNullable())) {
final String literalValue = tokenizer.getText();
- requireNext(TokenKind.CLOSE);
+ ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
return createUriParameter(edmProperty, edmKeyPropertyRef.getName(), literalValue);
} else {
throw new UriParserSemanticException("The key value is not valid.",
@@ -424,10 +424,10 @@ public class ResourcePathParser {
parameterNames.add(keyPredicateName);
hasComma = tokenizer.next(TokenKind.COMMA);
if (hasComma) {
- requireNext(TokenKind.ODataIdentifier);
+ ParserHelper.requireNext(tokenizer, TokenKind.ODataIdentifier);
}
} while (hasComma);
- requireNext(TokenKind.CLOSE);
+ ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
return parameters;
}
@@ -440,7 +440,7 @@ public class ResourcePathParser {
throw new UriValidationException(keyPredicateName + " is not a valid key property name.",
UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, keyPredicateName);
}
- requireNext(TokenKind.EQ);
+ ParserHelper.requireNext(tokenizer, TokenKind.EQ);
if (tokenizer.next(TokenKind.COMMA) || tokenizer.next(TokenKind.CLOSE) || tokenizer.next(TokenKind.EOF)) {
throw new UriParserSyntaxException("Key value expected.", UriParserSyntaxException.MessageKeys.SYNTAX);
}
@@ -512,7 +512,7 @@ public class ResourcePathParser {
}
((UriResourceTypedImpl) previousTyped).setTypeFilter(type);
}
- requireTokenEnd();
+ ParserHelper.requireTokenEnd(tokenizer);
return null;
} else {
throw new UriParserSemanticException(
@@ -572,53 +572,42 @@ public class ResourcePathParser {
UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED);
}
}
- requireTokenEnd();
+ ParserHelper.requireTokenEnd(tokenizer);
return resource;
}
private List<UriParameter> functionParameters() throws UriParserException {
List<UriParameter> parameters = new ArrayList<UriParameter>();
- requireNext(TokenKind.OPEN);
+ ParserHelper.requireNext(tokenizer, TokenKind.OPEN);
if (tokenizer.next(TokenKind.CLOSE)) {
return parameters;
}
do {
- requireNext(TokenKind.ODataIdentifier);
+ ParserHelper.requireNext(tokenizer, TokenKind.ODataIdentifier);
final String name = tokenizer.getText();
if (parameters.contains(name)) {
throw new UriParserSemanticException("Duplicated function parameter " + name,
UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, name);
}
- requireNext(TokenKind.EQ);
+ ParserHelper.requireNext(tokenizer, TokenKind.EQ);
if (tokenizer.next(TokenKind.COMMA) || tokenizer.next(TokenKind.CLOSE) || tokenizer.next(TokenKind.EOF)) {
throw new UriParserSyntaxException("Parameter value expected.", UriParserSyntaxException.MessageKeys.SYNTAX);
}
- if (nextPrimitiveValue()) {
+ if (tokenizer.next(TokenKind.ParameterAliasName)) {
+ parameters.add(new UriParameterImpl().setName(name).setAlias(tokenizer.getText()));
+ } else if (nextPrimitiveValue()) {
final String literalValue = tokenizer.getText();
- UriParameterImpl parameter = new UriParameterImpl().setName(name);
- parameters.add(literalValue.startsWith("@") ?
- parameter.setAlias(literalValue) :
- parameter.setText("null".equals(literalValue) ? null : literalValue));
+ parameters.add(new UriParameterImpl().setName(name)
+ .setText("null".equals(literalValue) ? null : literalValue));
} else {
throw new UriParserSemanticException("Wrong parameter value.",
UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, "");
}
} while (tokenizer.next(TokenKind.COMMA));
- requireNext(TokenKind.CLOSE);
+ ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
return parameters;
}
- private void requireNext(final TokenKind kind) throws UriParserException {
- if (!tokenizer.next(kind)) {
- throw new UriParserSyntaxException("Expected token '" + kind.toString() + "' not found.",
- UriParserSyntaxException.MessageKeys.SYNTAX);
- }
- }
-
- private void requireTokenEnd() throws UriParserException {
- requireNext(TokenKind.EOF);
- }
-
private boolean nextPrimitiveTypeValue(final EdmPrimitiveType primitiveType, final boolean nullable) {
final EdmPrimitiveType type = primitiveType instanceof EdmTypeDefinition ?
((EdmTypeDefinition) primitiveType).getUnderlyingType() :
@@ -629,64 +618,63 @@ public class ResourcePathParser {
return true;
} else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Boolean).equals(type)) {
- return tokenizer.next(TokenKind.PrimitiveBooleanValue);
+ return tokenizer.next(TokenKind.BooleanValue);
} else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.String).equals(type)) {
- return tokenizer.next(TokenKind.PrimitiveStringValue);
+ return tokenizer.next(TokenKind.StringValue);
} else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.SByte).equals(type)
|| odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Byte).equals(type)
|| odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int16).equals(type)
|| odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int32).equals(type)
|| odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int64).equals(type)) {
- return tokenizer.next(TokenKind.PrimitiveIntegerValue);
+ return tokenizer.next(TokenKind.IntegerValue);
} else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Guid).equals(type)) {
- return tokenizer.next(TokenKind.PrimitiveGuidValue);
+ return tokenizer.next(TokenKind.GuidValue);
} else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Date).equals(type)) {
- return tokenizer.next(TokenKind.PrimitiveDateValue);
+ return tokenizer.next(TokenKind.DateValue);
} else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.DateTimeOffset).equals(type)) {
- return tokenizer.next(TokenKind.PrimitiveDateTimeOffsetValue);
+ return tokenizer.next(TokenKind.DateTimeOffsetValue);
} else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.TimeOfDay).equals(type)) {
- return tokenizer.next(TokenKind.PrimitiveTimeOfDayValue);
+ return tokenizer.next(TokenKind.TimeOfDayValue);
} else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Decimal).equals(type)) {
// The order is important.
// A decimal value should not be parsed as integer and let the tokenizer stop at the decimal point.
- return tokenizer.next(TokenKind.PrimitiveDecimalValue)
- || tokenizer.next(TokenKind.PrimitiveIntegerValue);
+ return tokenizer.next(TokenKind.DecimalValue)
+ || tokenizer.next(TokenKind.IntegerValue);
} else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Double).equals(type)) {
// The order is important.
// A floating-point value should not be parsed as decimal and let the tokenizer stop at 'E'.
// A decimal value should not be parsed as integer and let the tokenizer stop at the decimal point.
- return tokenizer.next(TokenKind.PrimitiveDoubleValue)
- || tokenizer.next(TokenKind.PrimitiveDecimalValue)
- || tokenizer.next(TokenKind.PrimitiveIntegerValue);
+ return tokenizer.next(TokenKind.DoubleValue)
+ || tokenizer.next(TokenKind.DecimalValue)
+ || tokenizer.next(TokenKind.IntegerValue);
} else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Duration).equals(type)) {
- return tokenizer.next(TokenKind.PrimitiveDurationValue);
+ return tokenizer.next(TokenKind.DurationValue);
} else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Binary).equals(type)) {
- return tokenizer.next(TokenKind.PrimitiveBinaryValue);
+ return tokenizer.next(TokenKind.BinaryValue);
} else if (type.getKind() == EdmTypeKind.ENUM) {
- return tokenizer.next(TokenKind.PrimitiveEnumValue);
+ return tokenizer.next(TokenKind.EnumValue);
} else {
return false;
}
}
private boolean nextPrimitiveValue() {
- return tokenizer.next(TokenKind.ParameterAliasName)
- || tokenizer.next(TokenKind.NULL)
- || tokenizer.next(TokenKind.PrimitiveBooleanValue)
- || tokenizer.next(TokenKind.PrimitiveStringValue)
+ return tokenizer.next(TokenKind.NULL)
+ || tokenizer.next(TokenKind.BooleanValue)
+ || tokenizer.next(TokenKind.StringValue)
// The order of the next seven expressions is important in order to avoid
// finding partly parsed tokens (counter-intuitive as it may be, even a GUID may start with digits ...).
- || tokenizer.next(TokenKind.PrimitiveDoubleValue)
- || tokenizer.next(TokenKind.PrimitiveDecimalValue)
- || tokenizer.next(TokenKind.PrimitiveGuidValue)
- || tokenizer.next(TokenKind.PrimitiveDateTimeOffsetValue)
- || tokenizer.next(TokenKind.PrimitiveDateValue)
- || tokenizer.next(TokenKind.PrimitiveTimeOfDayValue)
- || tokenizer.next(TokenKind.PrimitiveIntegerValue)
-
- || tokenizer.next(TokenKind.PrimitiveDurationValue)
- || tokenizer.next(TokenKind.PrimitiveBinaryValue)
- || tokenizer.next(TokenKind.PrimitiveEnumValue);
+ || tokenizer.next(TokenKind.DoubleValue)
+ || tokenizer.next(TokenKind.DecimalValue)
+ || tokenizer.next(TokenKind.GuidValue)
+ || tokenizer.next(TokenKind.DateTimeOffsetValue)
+ || tokenizer.next(TokenKind.DateValue)
+ || tokenizer.next(TokenKind.TimeOfDayValue)
+ || tokenizer.next(TokenKind.IntegerValue)
+
+ || tokenizer.next(TokenKind.DurationValue)
+ || tokenizer.next(TokenKind.BinaryValue)
+ || tokenizer.next(TokenKind.EnumValue);
}
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2f3bc286/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/SelectParser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/SelectParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/SelectParser.java
index 3d933d2..b257e68 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/SelectParser.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/SelectParser.java
@@ -92,7 +92,7 @@ public class SelectParser {
if (type.compatibleTo(referencedType)) {
item.setTypeFilter(type);
if (tokenizer.next(TokenKind.SLASH)) {
- requireNext(tokenizer, TokenKind.ODataIdentifier);
+ ParserHelper.requireNext(tokenizer, TokenKind.ODataIdentifier);
UriInfoImpl resource = new UriInfoImpl().setKind(UriInfoKind.resource);
addSelectPath(tokenizer, type, resource);
item.setResourcePath(resource);
@@ -105,7 +105,7 @@ public class SelectParser {
}
} else {
- requireNext(tokenizer, TokenKind.ODataIdentifier);
+ ParserHelper.requireNext(tokenizer, TokenKind.ODataIdentifier);
// The namespace or its alias could be a single OData identifier.
final FullQualifiedName allOperationsInSchema = parseAllOperationsInSchema(tokenizer);
if (allOperationsInSchema != null) {
@@ -167,10 +167,10 @@ public class SelectParser {
List<String> names = new ArrayList<String>();
if (tokenizer.next(TokenKind.OPEN)) {
do {
- requireNext(tokenizer, TokenKind.ODataIdentifier);
+ ParserHelper.requireNext(tokenizer, TokenKind.ODataIdentifier);
names.add(tokenizer.getText());
} while (tokenizer.next(TokenKind.COMMA));
- requireNext(tokenizer, TokenKind.CLOSE);
+ ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
}
return names;
}
@@ -231,11 +231,4 @@ public class SelectParser {
}
}
}
-
- private void requireNext(UriTokenizer tokenizer, final TokenKind kind) throws UriParserSyntaxException {
- if (!tokenizer.next(kind)) {
- throw new UriParserSyntaxException("Illegal $select expression.",
- UriParserSyntaxException.MessageKeys.SYNTAX);
- }
- }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2f3bc286/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
index 8051573..a40f4ec 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
@@ -24,6 +24,8 @@ package org.apache.olingo.server.core.uri.parser;
* Since only the index is "moved", backing out while parsing a token is easy and used throughout.
* There is intentionally no method to push back tokens (although it would be easy to add such a method)
* because this tokenizer should behave like a classical token-consuming tokenizer.</p>
+ * <p>Whitespace is not an extra token but consumed with the tokens that require whitespace.
+ * Optional whitespace is not supported.</p>
*/
public class UriTokenizer {
@@ -35,6 +37,9 @@ public class UriTokenizer {
VALUE,
COUNT,
CROSSJOIN,
+ ROOT,
+ IT,
+
OPEN,
CLOSE,
COMMA,
@@ -44,6 +49,7 @@ public class UriTokenizer {
EQ,
STAR,
PLUS,
+ MINUS,
NULL,
// variable-value tokens (convention: mixed case)
@@ -51,20 +57,68 @@ public class UriTokenizer {
QualifiedName,
ParameterAliasName,
- PrimitiveBooleanValue,
- PrimitiveStringValue,
- PrimitiveIntegerValue,
- PrimitiveGuidValue,
- PrimitiveDateValue,
- PrimitiveDateTimeOffsetValue,
- PrimitiveTimeOfDayValue,
- PrimitiveDecimalValue,
- PrimitiveDoubleValue,
- PrimitiveDurationValue,
- PrimitiveBinaryValue,
- PrimitiveEnumValue,
-
- jsonArrayOrObject
+ BooleanValue,
+ StringValue,
+ IntegerValue,
+ GuidValue,
+ DateValue,
+ DateTimeOffsetValue,
+ TimeOfDayValue,
+ DecimalValue,
+ DoubleValue,
+ DurationValue,
+ BinaryValue,
+ EnumValue,
+
+ jsonArrayOrObject,
+
+ OrOperator,
+ AndOperator,
+ EqualsOperator,
+ NotEqualsOperator,
+ GreaterThanOperator,
+ GreaterThanOrEqualsOperator,
+ LessThanOperator,
+ LessThanOrEqualsOperator,
+ AddOperator,
+ SubOperator,
+ MulOperator,
+ DivOperator,
+ ModOperator,
+ NotOperator,
+
+ CastMethod,
+ CeilingMethod,
+ ConcatMethod,
+ ContainsMethod,
+ DateMethod,
+ DayMethod,
+ EndswithMethod,
+ FloorMethod,
+ FractionalsecondsMethod,
+ GeoDistanceMethod,
+ GeoIntersectsMethod,
+ GeoLengthMethod,
+ HourMethod,
+ IndexofMethod,
+ IsofMethod,
+ LengthMethod,
+ MaxdatetimeMethod,
+ MindatetimeMethod,
+ MinuteMethod,
+ MonthMethod,
+ NowMethod,
+ RoundMethod,
+ SecondMethod,
+ StartswithMethod,
+ SubstringMethod,
+ TimeMethod,
+ TolowerMethod,
+ TotaloffsetminutesMethod,
+ TotalsecondsMethod,
+ ToupperMethod,
+ TrimMethod,
+ YearMethod
}
private final String parseString;
@@ -111,6 +165,13 @@ public class UriTokenizer {
case CROSSJOIN:
found = nextConstant("$crossjoin");
break;
+ case ROOT:
+ found = nextConstant("$root");
+ break;
+ case IT:
+ found = nextConstant("$it");
+ break;
+
case OPEN:
found = nextCharacter('(');
break;
@@ -138,6 +199,9 @@ public class UriTokenizer {
case PLUS:
found = nextCharacter('+');
break;
+ case MINUS:
+ found = nextCharacter('-');
+ break;
case NULL:
found = nextConstant("null");
break;
@@ -157,47 +221,189 @@ public class UriTokenizer {
break;
// Primitive Values
- case PrimitiveBooleanValue:
+ case BooleanValue:
found = nextBooleanValue();
break;
- case PrimitiveStringValue:
+ case StringValue:
found = nextStringValue();
break;
- case PrimitiveIntegerValue:
+ case IntegerValue:
found = nextIntegerValue(true);
break;
- case PrimitiveGuidValue:
+ case GuidValue:
found = nextGuidValue();
break;
- case PrimitiveDateValue:
+ case DateValue:
found = nextDateValue();
break;
- case PrimitiveDateTimeOffsetValue:
+ case DateTimeOffsetValue:
found = nextDateTimeOffsetValue();
break;
- case PrimitiveTimeOfDayValue:
+ case TimeOfDayValue:
found = nextTimeOfDayValue();
break;
- case PrimitiveDecimalValue:
+ case DecimalValue:
found = nextDecimalValue();
break;
- case PrimitiveDoubleValue:
+ case DoubleValue:
found = nextDoubleValue();
break;
- case PrimitiveDurationValue:
+ case DurationValue:
found = nextDurationValue();
break;
- case PrimitiveBinaryValue:
+ case BinaryValue:
found = nextBinaryValue();
break;
- case PrimitiveEnumValue:
+ case EnumValue:
found = nextEnumValue();
break;
- // Primitive Values
+ // Complex or Collection Value
case jsonArrayOrObject:
found = nextJsonArrayOrObject();
break;
+
+ // Operators
+ case OrOperator:
+ found = nextBinaryOperator("or");
+ break;
+ case AndOperator:
+ found = nextBinaryOperator("and");
+ break;
+ case EqualsOperator:
+ found = nextBinaryOperator("eq");
+ break;
+ case NotEqualsOperator:
+ found = nextBinaryOperator("ne");
+ break;
+ case GreaterThanOperator:
+ found = nextBinaryOperator("gt");
+ break;
+ case GreaterThanOrEqualsOperator:
+ found = nextBinaryOperator("ge");
+ break;
+ case LessThanOperator:
+ found = nextBinaryOperator("lt");
+ break;
+ case LessThanOrEqualsOperator:
+ found = nextBinaryOperator("le");
+ break;
+ case AddOperator:
+ found = nextBinaryOperator("add");
+ break;
+ case SubOperator:
+ found = nextBinaryOperator("sub");
+ break;
+ case MulOperator:
+ found = nextBinaryOperator("mul");
+ break;
+ case DivOperator:
+ found = nextBinaryOperator("div");
+ break;
+ case ModOperator:
+ found = nextBinaryOperator("mod");
+ break;
+ case NotOperator:
+ found = nextConstant("not") && nextWhitespace();
+ break;
+
+ // Methods
+ case CastMethod:
+ found = nextMethod("cast");
+ break;
+ case CeilingMethod:
+ found = nextMethod("ceiling");
+ break;
+ case ConcatMethod:
+ found = nextMethod("concat");
+ break;
+ case ContainsMethod:
+ found = nextMethod("contains");
+ break;
+ case DateMethod:
+ found = nextMethod("date");
+ break;
+ case DayMethod:
+ found = nextMethod("day");
+ break;
+ case EndswithMethod:
+ found = nextMethod("endswith");
+ break;
+ case FloorMethod:
+ found = nextMethod("floor");
+ break;
+ case FractionalsecondsMethod:
+ found = nextMethod("fractionalseconds");
+ break;
+ case GeoDistanceMethod:
+ found = nextMethod("geo.distance");
+ break;
+ case GeoIntersectsMethod:
+ found = nextMethod("geo.intersects");
+ break;
+ case GeoLengthMethod:
+ found = nextMethod("geo.length");
+ break;
+ case HourMethod:
+ found = nextMethod("hour");
+ break;
+ case IndexofMethod:
+ found = nextMethod("indexof");
+ break;
+ case IsofMethod:
+ found = nextMethod("isof");
+ break;
+ case LengthMethod:
+ found = nextMethod("length");
+ break;
+ case MaxdatetimeMethod:
+ found = nextMethod("maxdatetime");
+ break;
+ case MindatetimeMethod:
+ found = nextMethod("mindatetime");
+ break;
+ case MinuteMethod:
+ found = nextMethod("minute");
+ break;
+ case MonthMethod:
+ found = nextMethod("month");
+ break;
+ case NowMethod:
+ found = nextMethod("now");
+ break;
+ case RoundMethod:
+ found = nextMethod("round");
+ break;
+ case SecondMethod:
+ found = nextMethod("second");
+ break;
+ case StartswithMethod:
+ found = nextMethod("startswith");
+ break;
+ case SubstringMethod:
+ found = nextMethod("substring");
+ break;
+ case TimeMethod:
+ found = nextMethod("time");
+ break;
+ case TolowerMethod:
+ found = nextMethod("tolower");
+ break;
+ case TotaloffsetminutesMethod:
+ found = nextMethod("totaloffsetminutes");
+ break;
+ case TotalsecondsMethod:
+ found = nextMethod("totalseconds");
+ break;
+ case ToupperMethod:
+ found = nextMethod("toupper");
+ break;
+ case TrimMethod:
+ found = nextMethod("trim");
+ break;
+ case YearMethod:
+ found = nextMethod("year");
+ break;
}
if (found) {
@@ -301,6 +507,37 @@ public class UriTokenizer {
}
/**
+ * Moves past whitespace (space or horizontal tabulator) characters if found;
+ * otherwise leaves the index unchanged.
+ * @return whether whitespace characters have been found at the current index
+ */
+ private boolean nextWhitespace() {
+ int count = 0;
+ while (nextCharacter(' ') || nextCharacter('\t')) {
+ count++;
+ }
+ return count > 0;
+ }
+
+ /**
+ * Moves past the given whitespace-surrounded operator constant if found;
+ * otherwise leaves the index unchanged.
+ * @return whether the operator has been found at the current index
+ */
+ private boolean nextBinaryOperator(final String operator) {
+ return nextWhitespace() && nextConstant(operator) && nextWhitespace();
+ }
+
+ /**
+ * Moves past the given method name and its immediately following opening parenthesis if found;
+ * otherwise leaves the index unchanged.
+ * @return whether the method has been found at the current index
+ */
+ private boolean nextMethod(final String methodName) {
+ return nextConstant(methodName) && nextCharacter('(');
+ }
+
+ /**
* Moves past an OData identifier if found; otherwise leaves the index unchanged.
* @return whether an OData identifier has been found at the current index
*/
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2f3bc286/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/UnaryImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/UnaryImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/UnaryImpl.java
index 2438d27..910997e 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/UnaryImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/UnaryImpl.java
@@ -53,6 +53,6 @@ public class UnaryImpl implements Unary {
@Override
public String toString() {
- return "{" + operator + " " + expression + '}';
+ return "{" + operator.name() + " " + expression + '}';
}
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2f3bc286/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java
index 7da823e..58f2a1f 100644
--- a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java
+++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java
@@ -20,191 +20,157 @@ package org.apache.olingo.server.core.uri.parser;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
-import java.util.ArrayList;
+import java.util.Locale;
import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
-import org.apache.olingo.server.core.uri.parser.ExpressionParser.Token;
-import org.apache.olingo.server.core.uri.parser.ExpressionParser.TokenKind;
-import org.apache.olingo.server.core.uri.parser.ExpressionParser.Tokenizer;
+import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind;
import org.junit.Test;
public class ExpressionParserTest {
@Test
public void equality() throws Exception {
- Expression expression = parseExpression(TokenKind.EQ_OP);
+ Expression expression = parseExpression("5 eq 5");
assertEquals("{5 EQ 5}", expression.toString());
- expression = parseExpression(TokenKind.NE_OP);
+ expression = parseExpression("5 ne 5");
assertEquals("{5 NE 5}", expression.toString());
}
@Test
public void relational() throws Exception {
- Expression expression = parseExpression(TokenKind.GT_OP);
+ Expression expression = parseExpression("5 gt 5");
assertEquals("{5 GT 5}", expression.toString());
- expression = parseExpression(TokenKind.GE_OP);
+ expression = parseExpression("5 ge 5");
assertEquals("{5 GE 5}", expression.toString());
- expression = parseExpression(TokenKind.LT_OP);
+ expression = parseExpression("5 lt 5");
assertEquals("{5 LT 5}", expression.toString());
- expression = parseExpression(TokenKind.LE_OP);
+ expression = parseExpression("5 le 5");
assertEquals("{5 LE 5}", expression.toString());
}
@Test
public void additive() throws Exception {
- Expression expression = parseExpression(TokenKind.ADD_OP);
+ Expression expression = parseExpression("5 add 5");
assertEquals("{5 ADD 5}", expression.toString());
- expression = parseExpression(TokenKind.SUB_OP);
+ expression = parseExpression("5 sub 5");
assertEquals("{5 SUB 5}", expression.toString());
}
@Test
public void multiplicative() throws Exception {
- Expression expression = parseExpression(TokenKind.MUL_OP);
+ Expression expression = parseExpression("5 mul 5");
assertEquals("{5 MUL 5}", expression.toString());
- expression = parseExpression(TokenKind.DIV_OP);
+ expression = parseExpression("5 div 5");
assertEquals("{5 DIV 5}", expression.toString());
- expression = parseExpression(TokenKind.MOD_OP);
+ expression = parseExpression("5 mod 5");
assertEquals("{5 MOD 5}", expression.toString());
}
@Test
public void unary() throws Exception {
- ArrayList<Token> tokens = new ArrayList<Token>();
- tokens.add(new Token(TokenKind.MINUS, ""));
- tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
- Tokenizer tokenizer = new Tokenizer(tokens);
- Expression expression = new ExpressionParser().parse(tokenizer);
- assertEquals("{- 5}", expression.toString());
-
- tokens = new ArrayList<Token>();
- tokens.add(new Token(TokenKind.NOT, ""));
- tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
- tokenizer = new Tokenizer(tokens);
- expression = new ExpressionParser().parse(tokenizer);
- assertEquals("{not 5}", expression.toString());
+ Expression expression = parseExpression("-5");
+ assertEquals("{MINUS 5}", expression.toString());
+
+ assertEquals("{MINUS -1}", parseExpression("--1").toString());
+
+ expression = parseExpression("not 5");
+ assertEquals("{NOT 5}", expression.toString());
}
@Test
public void grouping() throws Exception {
- ArrayList<Token> tokens = new ArrayList<Token>();
- tokens.add(new Token(TokenKind.MINUS, ""));
- tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
- tokens.add(new Token(TokenKind.ADD_OP, ""));
- tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
- Tokenizer tokenizer = new Tokenizer(tokens);
- Expression expression = new ExpressionParser().parse(tokenizer);
- assertEquals("{{- 5} ADD 5}", expression.toString());
-
- tokens = new ArrayList<Token>();
- tokens.add(new Token(TokenKind.MINUS, ""));
- tokens.add(new Token(TokenKind.OPEN, ""));
- tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
- tokens.add(new Token(TokenKind.ADD_OP, ""));
- tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
- tokens.add(new Token(TokenKind.CLOSE, ""));
- tokenizer = new Tokenizer(tokens);
- expression = new ExpressionParser().parse(tokenizer);
- assertEquals("{- {5 ADD 5}}", expression.toString());
+ Expression expression = parseExpression("-5 add 5");
+ assertEquals("{{MINUS 5} ADD 5}", expression.toString());
+
+ expression = parseExpression("-(5 add 5)");
+ assertEquals("{MINUS {5 ADD 5}}", expression.toString());
+ }
+
+ @Test
+ public void precedence() throws Exception {
+ assertEquals("{{MINUS 1} ADD {2 DIV 3}}", parseExpression("-1 add 2 div 3").toString());
+ assertEquals("{true OR {{NOT false} AND true}}", parseExpression("true or not false and true").toString());
}
@Test
public void noParameterMethods() throws Exception {
- Expression expression = parseMethod(TokenKind.Now);
+ Expression expression = parseMethod(TokenKind.NowMethod);
assertEquals("{now []}", expression.toString());
- expression = parseMethod(TokenKind.Maxdatetime);
+ expression = parseMethod(TokenKind.MaxdatetimeMethod);
assertEquals("{maxdatetime []}", expression.toString());
- expression = parseMethod(TokenKind.Mindatetime);
+ expression = parseMethod(TokenKind.MindatetimeMethod);
assertEquals("{mindatetime []}", expression.toString());
}
@Test
public void oneParameterMethods() throws Exception {
- Expression expression = parseMethod(TokenKind.Length, TokenKind.PrimitiveStringValue);
- assertEquals("{length [String1]}", expression.toString());
-
- expression = parseMethod(TokenKind.Tolower, TokenKind.PrimitiveStringValue);
- assertEquals("{tolower [String1]}", expression.toString());
+ final String stringValue = "'abc'";
+ final String dateValue = "1234-12-25";
+ final String dateTimeOffsetValue = "1234-12-25T11:12:13.456Z";
- expression = parseMethod(TokenKind.Toupper, TokenKind.PrimitiveStringValue);
- assertEquals("{toupper [String1]}", expression.toString());
+ Expression expression = parseMethod(TokenKind.LengthMethod, stringValue);
+ assertEquals("{length [" + stringValue + "]}", expression.toString());
- expression = parseMethod(TokenKind.Trim, TokenKind.PrimitiveStringValue);
- assertEquals("{trim [String1]}", expression.toString());
+ expression = parseMethod(TokenKind.TolowerMethod, stringValue);
+ assertEquals("{tolower [" + stringValue + "]}", expression.toString());
- expression = parseMethod(TokenKind.Year, TokenKind.PrimitiveDateValue);
- assertEquals("{year [Date1]}", expression.toString());
+ expression = parseMethod(TokenKind.ToupperMethod, stringValue);
+ assertEquals("{toupper [" + stringValue + "]}", expression.toString());
- expression = parseMethod(TokenKind.Month, TokenKind.PrimitiveDateValue);
- assertEquals("{month [Date1]}", expression.toString());
+ expression = parseMethod(TokenKind.TrimMethod, stringValue);
+ assertEquals("{trim [" + stringValue + "]}", expression.toString());
- expression = parseMethod(TokenKind.Day, TokenKind.PrimitiveDateValue);
- assertEquals("{day [Date1]}", expression.toString());
+ expression = parseMethod(TokenKind.YearMethod, dateValue);
+ assertEquals("{year [" + dateValue + "]}", expression.toString());
- expression = parseMethod(TokenKind.Hour, TokenKind.PrimitiveDateTimeOffsetValue);
- assertEquals("{hour [DateTimeOffset1]}", expression.toString());
+ expression = parseMethod(TokenKind.MonthMethod, dateValue);
+ assertEquals("{month [" + dateValue + "]}", expression.toString());
- expression = parseMethod(TokenKind.Minute, TokenKind.PrimitiveDateTimeOffsetValue);
- assertEquals("{minute [DateTimeOffset1]}", expression.toString());
+ expression = parseMethod(TokenKind.DayMethod, dateValue);
+ assertEquals("{day [" + dateValue + "]}", expression.toString());
- expression = parseMethod(TokenKind.Second, TokenKind.PrimitiveDateTimeOffsetValue);
- assertEquals("{second [DateTimeOffset1]}", expression.toString());
- }
+ expression = parseMethod(TokenKind.HourMethod, dateTimeOffsetValue);
+ assertEquals("{hour [" + dateTimeOffsetValue + "]}", expression.toString());
- @Test
- public void twoParameterMethods() {
+ expression = parseMethod(TokenKind.MinuteMethod, dateTimeOffsetValue);
+ assertEquals("{minute [" + dateTimeOffsetValue + "]}", expression.toString());
+ expression = parseMethod(TokenKind.SecondMethod, dateTimeOffsetValue);
+ assertEquals("{second [" + dateTimeOffsetValue + "]}", expression.toString());
}
- private Expression parseMethod(TokenKind... kind) throws UriParserException {
- ArrayList<Token> tokens = new ArrayList<Token>();
- tokens.add(new Token(kind[0], ""));
-
- for (int i = 1; i < kind.length; i++) {
- String text = null;
- switch (kind[i]) {
- case PrimitiveStringValue:
- text = "String" + i;
- break;
- case PrimitiveDateValue:
- text = "Date" + i;
- break;
- case PrimitiveDateTimeOffsetValue:
- text = "DateTimeOffset" + i;
- break;
- default:
- text = "" + i;
- break;
+ private Expression parseMethod(TokenKind kind, String... parameters) throws UriParserException {
+ String expressionString = kind.name().substring(0, kind.name().indexOf("Method"))
+ .toLowerCase(Locale.ROOT).replace("geo", "geo.") + '(';
+ for (int i = 0; i < parameters.length; i++) {
+ if (i > 0) {
+ expressionString += ',';
}
- tokens.add(new Token(kind[i], text));
+ expressionString += parameters[i];
}
+ expressionString += ')';
- tokens.add(new Token(TokenKind.CLOSE, ""));
- Tokenizer tokenizer = new Tokenizer(tokens);
- Expression expression = new ExpressionParser().parse(tokenizer);
+ Expression expression = parseExpression(expressionString);
assertNotNull(expression);
return expression;
}
- private Expression parseExpression(TokenKind operator) throws UriParserException {
- ArrayList<Token> tokens = new ArrayList<Token>();
- tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
- tokens.add(new Token(operator, ""));
- tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
- Tokenizer tokenizer = new Tokenizer(tokens);
-
+ private Expression parseExpression(final String expressionString) throws UriParserException {
+ UriTokenizer tokenizer = new UriTokenizer(expressionString);
Expression expression = new ExpressionParser().parse(tokenizer);
assertNotNull(expression);
+ assertTrue(tokenizer.next(TokenKind.EOF));
return expression;
}
}
[17/30] olingo-odata4 git commit: [OLINGO-834] ExpressionParser
parses path expressions
Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
index 2a994d3..118c649 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
@@ -46,29 +46,22 @@ import org.apache.olingo.server.api.uri.UriResourceRef;
import org.apache.olingo.server.api.uri.UriResourceValue;
import org.apache.olingo.server.api.uri.queryoption.AliasQueryOption;
import org.apache.olingo.server.api.uri.queryoption.CustomQueryOption;
-import org.apache.olingo.server.api.uri.queryoption.FilterOption;
import org.apache.olingo.server.api.uri.queryoption.QueryOption;
import org.apache.olingo.server.api.uri.queryoption.SystemQueryOption;
import org.apache.olingo.server.api.uri.queryoption.SystemQueryOptionKind;
import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
import org.apache.olingo.server.core.uri.UriInfoImpl;
import org.apache.olingo.server.core.uri.UriResourceStartingTypeFilterImpl;
-import org.apache.olingo.server.core.uri.UriResourceTypedImpl;
-import org.apache.olingo.server.core.uri.UriResourceWithKeysImpl;
import org.apache.olingo.server.core.uri.antlr.UriLexer;
import org.apache.olingo.server.core.uri.antlr.UriParserParser;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandItemsEOFContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.FilterExpressionEOFContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.OrderByEOFContext;
import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind;
import org.apache.olingo.server.core.uri.parser.search.SearchParser;
import org.apache.olingo.server.core.uri.queryoption.AliasQueryOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.CountOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.ExpandOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.FilterOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.FormatOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.IdOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.OrderByOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.SkipOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.SkipTokenOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.TopOptionImpl;
@@ -84,9 +77,7 @@ public class Parser {
private final Edm edm;
private final OData odata;
- private enum ParserEntryRules {
- ExpandItems, FilterExpression, Orderby
- }
+ private enum ParserEntryRules { ExpandItems }
public Parser(final Edm edm, final OData odata) {
this.edm = edm;
@@ -131,7 +122,7 @@ public class Parser {
if (numberOfSegments > 1) {
final String typeCastSegment = pathSegmentsDecoded.get(1);
ensureLastSegment(typeCastSegment, 2, numberOfSegments);
- context.contextUriInfo = new ResourcePathParser(edm, odata).parseDollarEntityTypeCast(typeCastSegment);
+ context.contextUriInfo = new ResourcePathParser(edm).parseDollarEntityTypeCast(typeCastSegment);
context.contextTypes.push(context.contextUriInfo.getEntityTypeCast());
} else {
context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.entityId);
@@ -141,7 +132,7 @@ public class Parser {
} else if (firstSegment.startsWith("$crossjoin")) {
ensureLastSegment(firstSegment, 1, numberOfSegments);
- context.contextUriInfo = new ResourcePathParser(edm, odata).parseCrossjoinSegment(firstSegment);
+ context.contextUriInfo = new ResourcePathParser(edm).parseCrossjoinSegment(firstSegment);
final EdmEntityContainer container = edm.getEntityContainer();
for (final String name : context.contextUriInfo.getEntitySetNames()) {
context.contextTypes.push(container.getEntitySet(name).getEntityType());
@@ -150,7 +141,7 @@ public class Parser {
} else {
context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.resource);
- final ResourcePathParser resourcePathParser = new ResourcePathParser(edm, odata);
+ final ResourcePathParser resourcePathParser = new ResourcePathParser(edm);
int count = 0;
UriResource lastSegment = null;
for (final String pathSegment : pathSegmentsDecoded) {
@@ -183,7 +174,7 @@ public class Parser {
if (lastSegment instanceof UriResourcePartTyped) {
final UriResourcePartTyped typed = (UriResourcePartTyped) lastSegment;
- final EdmType type = getTypeInformation(typed);
+ final EdmType type = ParserHelper.getTypeInformation(typed);
if (type != null) { // could be null for, e.g., actions without return type
context.contextTypes.push(type);
}
@@ -199,23 +190,13 @@ public class Parser {
if (optionName.startsWith("$")) {
SystemQueryOption systemOption = null;
if (optionName.equals(SystemQueryOptionKind.FILTER.toString())) {
- try {
- FilterExpressionEOFContext ctxFilterExpression =
- (FilterExpressionEOFContext) parseRule(optionValue, ParserEntryRules.FilterExpression);
- systemOption = (FilterOptionImpl) uriParseTreeVisitor.visitFilterExpressionEOF(ctxFilterExpression);
- } catch (final ParseCancellationException e) {
- throw e.getCause() instanceof UriParserException ?
- (UriParserException) e.getCause() :
- new UriParserSyntaxException("Syntax error", e, UriParserSyntaxException.MessageKeys.SYNTAX);
- }
-// UriTokenizer filterTokenizer = new UriTokenizer(optionValue);
-// systemOption = new FilterOptionImpl().setExpression(
-// new ExpressionParser().parse(filterTokenizer));
-// if (!filterTokenizer.next(TokenKind.EOF)) {
-// throw new UriParserSyntaxException("Illegal value of $filter option!",
-// UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION,
-// optionName, optionValue);
-// }
+ UriTokenizer filterTokenizer = new UriTokenizer(optionValue);
+ systemOption = new FilterParser(edm, odata).parse(filterTokenizer,
+ context.contextTypes.peek() instanceof EdmStructuredType ?
+ (EdmStructuredType) context.contextTypes.peek() :
+ null,
+ context.contextUriInfo.getEntitySetNames());
+ checkOptionEOF(filterTokenizer, optionName, optionValue);
} else if (optionName.equals(SystemQueryOptionKind.FORMAT.toString())) {
FormatOptionImpl formatOption = new FormatOptionImpl();
@@ -253,15 +234,13 @@ public class Parser {
UriParserSyntaxException.MessageKeys.SYSTEM_QUERY_OPTION_LEVELS_NOT_ALLOWED_HERE);
} else if (optionName.equals(SystemQueryOptionKind.ORDERBY.toString())) {
- try {
- OrderByEOFContext ctxOrderByExpression =
- (OrderByEOFContext) parseRule(optionValue, ParserEntryRules.Orderby);
- systemOption = (OrderByOptionImpl) uriParseTreeVisitor.visitOrderByEOF(ctxOrderByExpression);
- } catch (final ParseCancellationException e) {
- throw e.getCause() instanceof UriParserException ?
- (UriParserException) e.getCause() :
- new UriParserSyntaxException("Syntax error", e, UriParserSyntaxException.MessageKeys.SYNTAX);
- }
+ UriTokenizer orderByTokenizer = new UriTokenizer(optionValue);
+ systemOption = new OrderByParser(edm, odata).parse(orderByTokenizer,
+ context.contextTypes.peek() instanceof EdmStructuredType ?
+ (EdmStructuredType) context.contextTypes.peek() :
+ null,
+ context.contextUriInfo.getEntitySetNames());
+ checkOptionEOF(orderByTokenizer, optionName, optionValue);
} else if (optionName.equals(SystemQueryOptionKind.SEARCH.toString())) {
systemOption = new SearchParser().parse(optionValue);
@@ -273,11 +252,7 @@ public class Parser {
(EdmStructuredType) context.contextTypes.peek() :
null,
context.isCollection);
- if (!selectTokenizer.next(TokenKind.EOF)) {
- throw new UriParserSyntaxException("Illegal value of $select option!",
- UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION,
- optionName, optionValue);
- }
+ checkOptionEOF(selectTokenizer, optionName, optionValue);
} else if (optionName.equals(SystemQueryOptionKind.SKIP.toString())) {
SkipOptionImpl skipOption = new SkipOptionImpl();
@@ -343,15 +318,12 @@ public class Parser {
UriParserSyntaxException.MessageKeys.SYNTAX);
}
} else {
- try {
- final FilterExpressionEOFContext filterExpCtx =
- (FilterExpressionEOFContext) parseRule(optionValue, ParserEntryRules.FilterExpression);
- expression = ((FilterOption) uriParseTreeVisitor.visitFilterExpressionEOF(filterExpCtx))
- .getExpression();
- } catch (final ParseCancellationException e) {
- throw e.getCause() instanceof UriParserException ?
- (UriParserException) e.getCause() :
- new UriParserSyntaxException("Syntax error", e, UriParserSyntaxException.MessageKeys.SYNTAX);
+ UriTokenizer aliasValueTokenizer = new UriTokenizer(optionValue);
+ expression = new ExpressionParser(edm, odata).parse(aliasValueTokenizer, null,
+ context.contextUriInfo.getEntitySetNames());
+ if (!aliasValueTokenizer.next(TokenKind.EOF)) {
+ throw new UriParserSyntaxException("Illegal value for alias '" + optionName + "'.",
+ UriParserSyntaxException.MessageKeys.SYNTAX);
}
}
context.contextUriInfo.addAlias((AliasQueryOption) new AliasQueryOptionImpl()
@@ -384,28 +356,13 @@ public class Parser {
return index > 0 && index < value.length() - 1 && index == value.lastIndexOf('/');
}
- protected static EdmType getTypeInformation(final UriResourcePartTyped resourcePart) {
- EdmType type = null;
- if (resourcePart instanceof UriResourceWithKeysImpl) {
- final UriResourceWithKeysImpl lastPartWithKeys = (UriResourceWithKeysImpl) resourcePart;
- if (lastPartWithKeys.getTypeFilterOnEntry() != null) {
- type = lastPartWithKeys.getTypeFilterOnEntry();
- } else if (lastPartWithKeys.getTypeFilterOnCollection() != null) {
- type = lastPartWithKeys.getTypeFilterOnCollection();
- } else {
- type = lastPartWithKeys.getType();
- }
-
- } else if (resourcePart instanceof UriResourceTypedImpl) {
- final UriResourceTypedImpl lastPartTyped = (UriResourceTypedImpl) resourcePart;
- type = lastPartTyped.getTypeFilter() == null ?
- lastPartTyped.getType() :
- lastPartTyped.getTypeFilter();
- } else {
- type = resourcePart.getType();
+ private void checkOptionEOF(UriTokenizer tokenizer, final String optionName, final String optionValue)
+ throws UriParserException {
+ if (!tokenizer.next(TokenKind.EOF)) {
+ throw new UriParserSyntaxException("Illegal value of '" + optionName + "' option!",
+ UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION,
+ optionName, optionValue);
}
-
- return type;
}
private ParserRuleContext parseRule(final String input, final ParserEntryRules entryPoint)
@@ -435,14 +392,6 @@ public class Parser {
// parse
switch (entryPoint) {
- case FilterExpression:
- lexer.mode(Lexer.DEFAULT_MODE);
- ret = parser.filterExpressionEOF();
- break;
- case Orderby:
- lexer.mode(Lexer.DEFAULT_MODE);
- ret = parser.orderByEOF();
- break;
case ExpandItems:
lexer.mode(Lexer.DEFAULT_MODE);
ret = parser.expandItemsEOF();
@@ -471,14 +420,6 @@ public class Parser {
// parse
switch (entryPoint) {
- case FilterExpression:
- lexer.mode(Lexer.DEFAULT_MODE);
- ret = parser.filterExpressionEOF();
- break;
- case Orderby:
- lexer.mode(Lexer.DEFAULT_MODE);
- ret = parser.orderByEOF();
- break;
case ExpandItems:
lexer.mode(Lexer.DEFAULT_MODE);
ret = parser.expandItemsEOF();
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java
index e811575..65ee461 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java
@@ -18,10 +18,35 @@
*/
package org.apache.olingo.server.core.uri.parser;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.commons.api.edm.EdmEntityType;
+import org.apache.olingo.commons.api.edm.EdmKeyPropertyRef;
+import org.apache.olingo.commons.api.edm.EdmNavigationProperty;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
+import org.apache.olingo.commons.api.edm.EdmProperty;
+import org.apache.olingo.commons.api.edm.EdmType;
+import org.apache.olingo.commons.api.edm.EdmTypeDefinition;
+import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
+import org.apache.olingo.server.api.OData;
+import org.apache.olingo.server.api.uri.UriParameter;
+import org.apache.olingo.server.api.uri.UriResourcePartTyped;
+import org.apache.olingo.server.core.ODataImpl;
+import org.apache.olingo.server.core.uri.UriParameterImpl;
+import org.apache.olingo.server.core.uri.UriResourceTypedImpl;
+import org.apache.olingo.server.core.uri.UriResourceWithKeysImpl;
import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind;
+import org.apache.olingo.server.core.uri.validator.UriValidationException;
public class ParserHelper {
+ private static final OData odata = new ODataImpl();
+
public static void requireNext(UriTokenizer tokenizer, final TokenKind required) throws UriParserException {
if (!tokenizer.next(required)) {
throw new UriParserSyntaxException("Expected token '" + required.toString() + "' not found.",
@@ -33,16 +58,16 @@ public class ParserHelper {
requireNext(tokenizer, TokenKind.EOF);
}
- public static TokenKind next(UriTokenizer tokenizer, final TokenKind... kind) {
- for (int i = 0; i < kind.length; i++) {
- if (tokenizer.next(kind[i])) {
- return kind[i];
+ public static TokenKind next(UriTokenizer tokenizer, final TokenKind... kinds) {
+ for (final TokenKind kind : kinds) {
+ if (tokenizer.next(kind)) {
+ return kind;
}
}
return null;
}
- public static TokenKind nextPrimitive(UriTokenizer tokenizer) {
+ public static TokenKind nextPrimitiveValue(UriTokenizer tokenizer) {
return next(tokenizer,
TokenKind.NULL,
TokenKind.BooleanValue,
@@ -62,4 +87,304 @@ public class ParserHelper {
TokenKind.BinaryValue,
TokenKind.EnumValue);
}
+
+ protected static List<UriParameter> parseFunctionParameters(UriTokenizer tokenizer, final boolean withComplex)
+ throws UriParserException {
+ List<UriParameter> parameters = new ArrayList<UriParameter>();
+ ParserHelper.requireNext(tokenizer, TokenKind.OPEN);
+ if (tokenizer.next(TokenKind.CLOSE)) {
+ return parameters;
+ }
+ do {
+ ParserHelper.requireNext(tokenizer, TokenKind.ODataIdentifier);
+ final String name = tokenizer.getText();
+ if (parameters.contains(name)) {
+ throw new UriParserSemanticException("Duplicated function parameter " + name,
+ UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, name);
+ }
+ ParserHelper.requireNext(tokenizer, TokenKind.EQ);
+ if (tokenizer.next(TokenKind.COMMA) || tokenizer.next(TokenKind.CLOSE) || tokenizer.next(TokenKind.EOF)) {
+ throw new UriParserSyntaxException("Parameter value expected.", UriParserSyntaxException.MessageKeys.SYNTAX);
+ }
+ if (tokenizer.next(TokenKind.ParameterAliasName)) {
+ parameters.add(new UriParameterImpl().setName(name).setAlias(tokenizer.getText()));
+ } else if (tokenizer.next(TokenKind.jsonArrayOrObject)) {
+ if (withComplex) {
+ parameters.add(new UriParameterImpl().setName(name).setText(tokenizer.getText()));
+ } else {
+ throw new UriParserSemanticException("A JSON array or object is not allowed as parameter value.",
+ UriParserSemanticException.MessageKeys.COMPLEX_PARAMETER_IN_RESOURCE_PATH, tokenizer.getText());
+ }
+ } else if (nextPrimitiveValue(tokenizer) == null) {
+ throw new UriParserSemanticException("Wrong parameter value.",
+ UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, "");
+ } else {
+ final String literalValue = tokenizer.getText();
+ parameters.add(new UriParameterImpl().setName(name)
+ .setText("null".equals(literalValue) ? null : literalValue));
+ }
+ } while (tokenizer.next(TokenKind.COMMA));
+ ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
+ return parameters;
+ }
+
+ protected static List<UriParameter> parseNavigationKeyPredicate(UriTokenizer tokenizer,
+ final EdmNavigationProperty navigationProperty) throws UriParserException, UriValidationException {
+ if (tokenizer.next(TokenKind.OPEN)) {
+ if (navigationProperty.isCollection()) {
+ return parseKeyPredicate(tokenizer, navigationProperty.getType(), navigationProperty.getPartner());
+ } else {
+ throw new UriParserSemanticException("A key is not allowed on non-collection navigation properties.",
+ UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED);
+ }
+ }
+ return null;
+ }
+
+ protected static List<UriParameter> parseKeyPredicate(UriTokenizer tokenizer, final EdmEntityType edmEntityType,
+ final EdmNavigationProperty partner) throws UriParserException, UriValidationException {
+ final List<EdmKeyPropertyRef> keyPropertyRefs = edmEntityType.getKeyPropertyRefs();
+ if (tokenizer.next(TokenKind.CLOSE)) {
+ throw new UriParserSemanticException(
+ "Expected " + keyPropertyRefs.size() + " key predicates but none.",
+ UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
+ Integer.toString(keyPropertyRefs.size()), "0");
+ }
+ List<UriParameter> keys = new ArrayList<UriParameter>();
+ Map<String, String> referencedNames = new HashMap<String, String>();
+
+ if (partner != null) {
+ // Prepare list of potentially missing keys to be filled from referential constraints.
+ for (final String name : edmEntityType.getKeyPredicateNames()) {
+ final String referencedName = partner.getReferencingPropertyName(name);
+ if (referencedName != null) {
+ referencedNames.put(name, referencedName);
+ }
+ }
+ }
+
+ if (tokenizer.next(TokenKind.ODataIdentifier)) {
+ keys.addAll(compoundKey(tokenizer, edmEntityType));
+ } else if (keyPropertyRefs.size() - referencedNames.size() == 1) {
+ for (final EdmKeyPropertyRef candidate : keyPropertyRefs) {
+ if (referencedNames.get(candidate.getName()) == null) {
+ keys.add(simpleKey(tokenizer, candidate));
+ break;
+ }
+ }
+ } else {
+ throw new UriParserSemanticException(
+ "Expected " + (keyPropertyRefs.size() -referencedNames.size()) + " key predicates but found one.",
+ UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
+ Integer.toString(keyPropertyRefs.size() - referencedNames.size()), "1");
+ }
+
+ if (keys.size() < keyPropertyRefs.size() && partner != null) {
+ // Fill missing keys from referential constraints.
+ for (final String name : edmEntityType.getKeyPredicateNames()) {
+ boolean found = false;
+ for (final UriParameter key : keys) {
+ if (name.equals(key.getName())) {
+ found = true;
+ break;
+ }
+ }
+ if (!found && referencedNames.get(name) != null) {
+ keys.add(0, new UriParameterImpl().setName(name).setReferencedProperty(referencedNames.get(name)));
+ }
+ }
+ }
+
+ // Check that all key predicates are filled from the URI.
+ if (keys.size() < keyPropertyRefs.size()) {
+ throw new UriParserSemanticException(
+ "Expected " + keyPropertyRefs.size() + " key predicates but found " + keys.size() + ".",
+ UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
+ Integer.toString(keyPropertyRefs.size()), Integer.toString(keys.size()));
+ } else {
+ return keys;
+ }
+ }
+
+ private static UriParameter simpleKey(UriTokenizer tokenizer, final EdmKeyPropertyRef edmKeyPropertyRef)
+ throws UriParserException, UriValidationException {
+ final EdmProperty edmProperty = edmKeyPropertyRef == null ? null : edmKeyPropertyRef.getProperty();
+ if (nextPrimitiveTypeValue(tokenizer,
+ edmProperty == null ? null : (EdmPrimitiveType) edmProperty.getType(),
+ edmProperty == null ? false : edmProperty.isNullable())) {
+ final String literalValue = tokenizer.getText();
+ ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
+ return createUriParameter(edmProperty, edmKeyPropertyRef.getName(), literalValue);
+ } else {
+ throw new UriParserSemanticException("The key value is not valid.",
+ UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, edmKeyPropertyRef.getName());
+ }
+ }
+
+ private static List<UriParameter> compoundKey(UriTokenizer tokenizer, final EdmEntityType edmEntityType)
+ throws UriParserException, UriValidationException {
+
+ List<UriParameter> parameters = new ArrayList<UriParameter>();
+ List<String> parameterNames = new ArrayList<String>();
+
+ // To validate that each key predicate is exactly specified once, we use a list to pick from.
+ List<String> remainingKeyNames = new ArrayList<String>(edmEntityType.getKeyPredicateNames());
+
+ // At least one key predicate is mandatory. Try to fetch all.
+ boolean hasComma = false;
+ do {
+ final String keyPredicateName = tokenizer.getText();
+ if (parameterNames.contains(keyPredicateName)) {
+ throw new UriValidationException("Duplicated key property " + keyPredicateName,
+ UriValidationException.MessageKeys.DOUBLE_KEY_PROPERTY, keyPredicateName);
+ }
+ if (remainingKeyNames.isEmpty()) {
+ throw new UriParserSemanticException("Too many key properties.",
+ UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
+ Integer.toString(parameters.size()), Integer.toString(parameters.size() + 1));
+ }
+ if (!remainingKeyNames.remove(keyPredicateName)) {
+ throw new UriValidationException("Unknown key property " + keyPredicateName,
+ UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, keyPredicateName);
+ }
+ parameters.add(keyValuePair(tokenizer, keyPredicateName, edmEntityType));
+ parameterNames.add(keyPredicateName);
+ hasComma = tokenizer.next(TokenKind.COMMA);
+ if (hasComma) {
+ ParserHelper.requireNext(tokenizer, TokenKind.ODataIdentifier);
+ }
+ } while (hasComma);
+ ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
+
+ return parameters;
+ }
+
+ protected static UriParameter keyValuePair(UriTokenizer tokenizer,
+ final String keyPredicateName, final EdmEntityType edmEntityType)
+ throws UriParserException, UriValidationException {
+ final EdmKeyPropertyRef keyPropertyRef = edmEntityType.getKeyPropertyRef(keyPredicateName);
+ final EdmProperty edmProperty = keyPropertyRef == null ? null : keyPropertyRef.getProperty();
+ if (edmProperty == null) {
+ throw new UriValidationException(keyPredicateName + " is not a valid key property name.",
+ UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, keyPredicateName);
+ }
+ ParserHelper.requireNext(tokenizer, TokenKind.EQ);
+ if (tokenizer.next(TokenKind.COMMA) || tokenizer.next(TokenKind.CLOSE) || tokenizer.next(TokenKind.EOF)) {
+ throw new UriParserSyntaxException("Key value expected.", UriParserSyntaxException.MessageKeys.SYNTAX);
+ }
+ if (nextPrimitiveTypeValue(tokenizer, (EdmPrimitiveType) edmProperty.getType(), edmProperty.isNullable())) {
+ return createUriParameter(edmProperty, keyPredicateName, tokenizer.getText());
+ } else {
+ throw new UriParserSemanticException(keyPredicateName + " has not a valid key value.",
+ UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, keyPredicateName);
+ }
+ }
+
+ private static UriParameter createUriParameter(final EdmProperty edmProperty, final String parameterName,
+ final String literalValue) throws UriParserException, UriValidationException {
+ if (literalValue.startsWith("@")) {
+ return new UriParameterImpl()
+ .setName(parameterName)
+ .setAlias(literalValue);
+ }
+
+ final EdmPrimitiveType primitiveType = (EdmPrimitiveType) edmProperty.getType();
+ try {
+ if (!(primitiveType.validate(primitiveType.fromUriLiteral(literalValue), edmProperty.isNullable(),
+ edmProperty.getMaxLength(), edmProperty.getPrecision(), edmProperty.getScale(), edmProperty.isUnicode()))) {
+ throw new UriValidationException("Invalid key property",
+ UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, parameterName);
+ }
+ } catch (final EdmPrimitiveTypeException e) {
+ throw new UriValidationException("Invalid key property",
+ UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, parameterName);
+ }
+
+ return new UriParameterImpl()
+ .setName(parameterName)
+ .setText("null".equals(literalValue) ? null : literalValue);
+ }
+
+ private static boolean nextPrimitiveTypeValue(UriTokenizer tokenizer,
+ final EdmPrimitiveType primitiveType, final boolean nullable) {
+ final EdmPrimitiveType type = primitiveType instanceof EdmTypeDefinition ?
+ ((EdmTypeDefinition) primitiveType).getUnderlyingType() :
+ primitiveType;
+ if (tokenizer.next(TokenKind.ParameterAliasName)) {
+ return true;
+ } else if (nullable && tokenizer.next(TokenKind.NULL)) {
+ return true;
+
+ } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Boolean).equals(type)) {
+ return tokenizer.next(TokenKind.BooleanValue);
+ } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.String).equals(type)) {
+ return tokenizer.next(TokenKind.StringValue);
+ } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.SByte).equals(type)
+ || odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Byte).equals(type)
+ || odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int16).equals(type)
+ || odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int32).equals(type)
+ || odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int64).equals(type)) {
+ return tokenizer.next(TokenKind.IntegerValue);
+ } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Guid).equals(type)) {
+ return tokenizer.next(TokenKind.GuidValue);
+ } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Date).equals(type)) {
+ return tokenizer.next(TokenKind.DateValue);
+ } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.DateTimeOffset).equals(type)) {
+ return tokenizer.next(TokenKind.DateTimeOffsetValue);
+ } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.TimeOfDay).equals(type)) {
+ return tokenizer.next(TokenKind.TimeOfDayValue);
+ } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Decimal).equals(type)) {
+ // The order is important.
+ // A decimal value should not be parsed as integer and let the tokenizer stop at the decimal point.
+ return tokenizer.next(TokenKind.DecimalValue)
+ || tokenizer.next(TokenKind.IntegerValue);
+ } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Double).equals(type)) {
+ // The order is important.
+ // A floating-point value should not be parsed as decimal and let the tokenizer stop at 'E'.
+ // A decimal value should not be parsed as integer and let the tokenizer stop at the decimal point.
+ return tokenizer.next(TokenKind.DoubleValue)
+ || tokenizer.next(TokenKind.DecimalValue)
+ || tokenizer.next(TokenKind.IntegerValue);
+ } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Duration).equals(type)) {
+ return tokenizer.next(TokenKind.DurationValue);
+ } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Binary).equals(type)) {
+ return tokenizer.next(TokenKind.BinaryValue);
+ } else if (type.getKind() == EdmTypeKind.ENUM) {
+ return tokenizer.next(TokenKind.EnumValue);
+ } else {
+ return false;
+ }
+ }
+
+ protected static List<String> getParameterNames(final List<UriParameter> parameters) {
+ List<String> names = new ArrayList<String>();
+ for (final UriParameter parameter : parameters) {
+ names.add(parameter.getName());
+ }
+ return names;
+ }
+
+ protected static EdmType getTypeInformation(final UriResourcePartTyped resourcePart) {
+ EdmType type = null;
+ if (resourcePart instanceof UriResourceWithKeysImpl) {
+ final UriResourceWithKeysImpl lastPartWithKeys = (UriResourceWithKeysImpl) resourcePart;
+ if (lastPartWithKeys.getTypeFilterOnEntry() != null) {
+ type = lastPartWithKeys.getTypeFilterOnEntry();
+ } else if (lastPartWithKeys.getTypeFilterOnCollection() != null) {
+ type = lastPartWithKeys.getTypeFilterOnCollection();
+ } else {
+ type = lastPartWithKeys.getType();
+ }
+
+ } else if (resourcePart instanceof UriResourceTypedImpl) {
+ final UriResourceTypedImpl lastPartTyped = (UriResourceTypedImpl) resourcePart;
+ type = lastPartTyped.getTypeFilter() == null ?
+ lastPartTyped.getType() :
+ lastPartTyped.getTypeFilter();
+ } else {
+ type = resourcePart.getType();
+ }
+
+ return type;
+ }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ResourcePathParser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ResourcePathParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ResourcePathParser.java
index 5d2fbde..1cd4d7a 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ResourcePathParser.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ResourcePathParser.java
@@ -18,10 +18,7 @@
*/
package org.apache.olingo.server.core.uri.parser;
-import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import org.apache.olingo.commons.api.edm.Edm;
import org.apache.olingo.commons.api.edm.EdmAction;
@@ -31,25 +28,18 @@ import org.apache.olingo.commons.api.edm.EdmEntitySet;
import org.apache.olingo.commons.api.edm.EdmEntityType;
import org.apache.olingo.commons.api.edm.EdmFunction;
import org.apache.olingo.commons.api.edm.EdmFunctionImport;
-import org.apache.olingo.commons.api.edm.EdmKeyPropertyRef;
import org.apache.olingo.commons.api.edm.EdmNavigationProperty;
-import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
-import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
-import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
import org.apache.olingo.commons.api.edm.EdmProperty;
import org.apache.olingo.commons.api.edm.EdmSingleton;
import org.apache.olingo.commons.api.edm.EdmStructuredType;
import org.apache.olingo.commons.api.edm.EdmType;
-import org.apache.olingo.commons.api.edm.EdmTypeDefinition;
import org.apache.olingo.commons.api.edm.FullQualifiedName;
import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
-import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.uri.UriInfoKind;
import org.apache.olingo.server.api.uri.UriParameter;
import org.apache.olingo.server.api.uri.UriResource;
import org.apache.olingo.server.api.uri.UriResourcePartTyped;
import org.apache.olingo.server.core.uri.UriInfoImpl;
-import org.apache.olingo.server.core.uri.UriParameterImpl;
import org.apache.olingo.server.core.uri.UriResourceActionImpl;
import org.apache.olingo.server.core.uri.UriResourceComplexPropertyImpl;
import org.apache.olingo.server.core.uri.UriResourceCountImpl;
@@ -69,13 +59,11 @@ public class ResourcePathParser {
private final Edm edm;
private final EdmEntityContainer edmEntityContainer;
- private final OData odata;
private UriTokenizer tokenizer;
- public ResourcePathParser(final Edm edm, final OData odata) {
+ public ResourcePathParser(final Edm edm) {
this.edm = edm;
edmEntityContainer = edm.getEntityContainer();
- this.odata = odata;
}
public UriResource parsePathSegment(final String pathSegment, UriResource previous)
@@ -188,10 +176,11 @@ public class ResourcePathParser {
final EdmEntitySet edmEntitySet = edmEntityContainer.getEntitySet(oDataIdentifier);
if (edmEntitySet != null) {
- final UriResourceEntitySetImpl entitySetResource = new UriResourceEntitySetImpl().setEntitSet(edmEntitySet);
+ final UriResourceEntitySetImpl entitySetResource = new UriResourceEntitySetImpl(edmEntitySet);
if (tokenizer.next(TokenKind.OPEN)) {
- final List<UriParameter> keyPredicates = keyPredicate(entitySetResource.getEntityType(), null);
+ final List<UriParameter> keyPredicates =
+ ParserHelper.parseKeyPredicate(tokenizer, entitySetResource.getEntityType(), null);
entitySetResource.setKeyPredicates(keyPredicates);
}
@@ -202,13 +191,13 @@ public class ResourcePathParser {
final EdmSingleton edmSingleton = edmEntityContainer.getSingleton(oDataIdentifier);
if (edmSingleton != null) {
ParserHelper.requireTokenEnd(tokenizer);
- return new UriResourceSingletonImpl().setSingleton(edmSingleton);
+ return new UriResourceSingletonImpl(edmSingleton);
}
final EdmActionImport edmActionImport = edmEntityContainer.getActionImport(oDataIdentifier);
if (edmActionImport != null) {
ParserHelper.requireTokenEnd(tokenizer);
- return new UriResourceActionImpl().setActionImport(edmActionImport);
+ return new UriResourceActionImpl(edmActionImport);
}
final EdmFunctionImport edmFunctionImport = edmEntityContainer.getFunctionImport(oDataIdentifier);
@@ -252,8 +241,8 @@ public class ResourcePathParser {
return property.isPrimitive()
|| property.getType().getKind() == EdmTypeKind.ENUM
|| property.getType().getKind() == EdmTypeKind.DEFINITION ?
- new UriResourcePrimitivePropertyImpl().setProperty(property) :
- new UriResourceComplexPropertyImpl().setProperty(property);
+ new UriResourcePrimitivePropertyImpl(property) :
+ new UriResourceComplexPropertyImpl(property);
}
final EdmNavigationProperty navigationProperty = structType.getNavigationProperty(name);
if (navigationProperty == null) {
@@ -262,18 +251,9 @@ public class ResourcePathParser {
UriParserSemanticException.MessageKeys.PROPERTY_NOT_IN_TYPE,
structType.getFullQualifiedName().getFullQualifiedNameAsString(), name);
}
- List<UriParameter> keyPredicate = null;
- if (tokenizer.next(TokenKind.OPEN)) {
- if (navigationProperty.isCollection()) {
- keyPredicate = keyPredicate(navigationProperty.getType(), navigationProperty.getPartner());
- } else {
- throw new UriParserSemanticException("A key is not allowed on non-collection navigation properties.",
- UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED);
- }
- }
+ List<UriParameter> keyPredicate = ParserHelper.parseNavigationKeyPredicate(tokenizer, navigationProperty);
ParserHelper.requireTokenEnd(tokenizer);
- return new UriResourceNavigationPropertyImpl()
- .setNavigationProperty(navigationProperty)
+ return new UriResourceNavigationPropertyImpl(navigationProperty)
.setKeyPredicates(keyPredicate);
}
@@ -289,7 +269,7 @@ public class ResourcePathParser {
previousTyped.isCollection());
if (boundAction != null) {
ParserHelper.requireTokenEnd(tokenizer);
- return new UriResourceActionImpl().setAction(boundAction);
+ return new UriResourceActionImpl(boundAction);
}
EdmStructuredType type = edm.getEntityType(name);
if (type == null) {
@@ -314,169 +294,6 @@ public class ResourcePathParser {
}
}
- private List<UriParameter> keyPredicate(final EdmEntityType edmEntityType, final EdmNavigationProperty partner)
- throws UriParserException, UriValidationException {
- final List<EdmKeyPropertyRef> keyPropertyRefs = edmEntityType.getKeyPropertyRefs();
- if (tokenizer.next(TokenKind.CLOSE)) {
- throw new UriParserSemanticException(
- "Expected " + keyPropertyRefs.size() + " key predicates but none.",
- UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
- Integer.toString(keyPropertyRefs.size()), "0");
- }
- List<UriParameter> keys = new ArrayList<UriParameter>();
- Map<String, String> referencedNames = new HashMap<String, String>();
-
- if (partner != null) {
- // Prepare list of potentially missing keys to be filled from referential constraints.
- for (final String name : edmEntityType.getKeyPredicateNames()) {
- final String referencedName = partner.getReferencingPropertyName(name);
- if (referencedName != null) {
- referencedNames.put(name, referencedName);
- }
- }
- }
-
- if (tokenizer.next(TokenKind.ODataIdentifier)) {
- keys.addAll(compoundKey(edmEntityType));
- } else if (keyPropertyRefs.size() - referencedNames.size() == 1) {
- for (final EdmKeyPropertyRef candidate : keyPropertyRefs) {
- if (referencedNames.get(candidate.getName()) == null) {
- keys.add(simpleKey(candidate));
- break;
- }
- }
- } else {
- throw new UriParserSemanticException(
- "Expected " + (keyPropertyRefs.size() -referencedNames.size()) + " key predicates but found one.",
- UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
- Integer.toString(keyPropertyRefs.size() - referencedNames.size()), "1");
- }
-
- if (keys.size() < keyPropertyRefs.size() && partner != null) {
- // Fill missing keys from referential constraints.
- for (final String name : edmEntityType.getKeyPredicateNames()) {
- boolean found = false;
- for (final UriParameter key : keys) {
- if (name.equals(key.getName())) {
- found = true;
- break;
- }
- }
- if (!found && referencedNames.get(name) != null) {
- keys.add(0, new UriParameterImpl().setName(name).setReferencedProperty(referencedNames.get(name)));
- }
- }
- }
-
- // Check that all key predicates are filled from the URI.
- if (keys.size() < keyPropertyRefs.size()) {
- throw new UriParserSemanticException(
- "Expected " + keyPropertyRefs.size() + " key predicates but found " + keys.size() + ".",
- UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
- Integer.toString(keyPropertyRefs.size()), Integer.toString(keys.size()));
- } else {
- return keys;
- }
- }
-
- private UriParameter simpleKey(final EdmKeyPropertyRef edmKeyPropertyRef)
- throws UriParserException, UriValidationException {
- final EdmProperty edmProperty = edmKeyPropertyRef == null ? null : edmKeyPropertyRef.getProperty();
- if (nextPrimitiveTypeValue(
- edmProperty == null ? null : (EdmPrimitiveType) edmProperty.getType(),
- edmProperty == null ? false : edmProperty.isNullable())) {
- final String literalValue = tokenizer.getText();
- ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
- return createUriParameter(edmProperty, edmKeyPropertyRef.getName(), literalValue);
- } else {
- throw new UriParserSemanticException("The key value is not valid.",
- UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, edmKeyPropertyRef.getName());
- }
- }
-
- private List<UriParameter> compoundKey(final EdmEntityType edmEntityType)
- throws UriParserException, UriValidationException {
-
- List<UriParameter> parameters = new ArrayList<UriParameter>();
- List<String> parameterNames = new ArrayList<String>();
-
- // To validate that each key predicate is exactly specified once, we use a list to pick from.
- List<String> remainingKeyNames = new ArrayList<String>(edmEntityType.getKeyPredicateNames());
-
- // At least one key predicate is mandatory. Try to fetch all.
- boolean hasComma = false;
- do {
- final String keyPredicateName = tokenizer.getText();
- if (parameterNames.contains(keyPredicateName)) {
- throw new UriValidationException("Duplicated key property " + keyPredicateName,
- UriValidationException.MessageKeys.DOUBLE_KEY_PROPERTY, keyPredicateName);
- }
- if (remainingKeyNames.isEmpty()) {
- throw new UriParserSemanticException("Too many key properties.",
- UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
- Integer.toString(parameters.size()), Integer.toString(parameters.size() + 1));
- }
- if (!remainingKeyNames.remove(keyPredicateName)) {
- throw new UriValidationException("Unknown key property " + keyPredicateName,
- UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, keyPredicateName);
- }
- parameters.add(keyValuePair(keyPredicateName, edmEntityType));
- parameterNames.add(keyPredicateName);
- hasComma = tokenizer.next(TokenKind.COMMA);
- if (hasComma) {
- ParserHelper.requireNext(tokenizer, TokenKind.ODataIdentifier);
- }
- } while (hasComma);
- ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
-
- return parameters;
- }
-
- private UriParameter keyValuePair(final String keyPredicateName, final EdmEntityType edmEntityType)
- throws UriParserException, UriValidationException {
- final EdmKeyPropertyRef keyPropertyRef = edmEntityType.getKeyPropertyRef(keyPredicateName);
- final EdmProperty edmProperty = keyPropertyRef == null ? null : keyPropertyRef.getProperty();
- if (edmProperty == null) {
- throw new UriValidationException(keyPredicateName + " is not a valid key property name.",
- UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, keyPredicateName);
- }
- ParserHelper.requireNext(tokenizer, TokenKind.EQ);
- if (tokenizer.next(TokenKind.COMMA) || tokenizer.next(TokenKind.CLOSE) || tokenizer.next(TokenKind.EOF)) {
- throw new UriParserSyntaxException("Key value expected.", UriParserSyntaxException.MessageKeys.SYNTAX);
- }
- if (nextPrimitiveTypeValue((EdmPrimitiveType) edmProperty.getType(), edmProperty.isNullable())) {
- return createUriParameter(edmProperty, keyPredicateName, tokenizer.getText());
- } else {
- throw new UriParserSemanticException(keyPredicateName + " has not a valid key value.",
- UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, keyPredicateName);
- }
- }
-
- private UriParameter createUriParameter(final EdmProperty edmProperty, final String parameterName,
- final String literalValue) throws UriParserException, UriValidationException {
- if (literalValue.startsWith("@")) {
- return new UriParameterImpl()
- .setName(parameterName)
- .setAlias(literalValue);
- }
-
- final EdmPrimitiveType primitiveType = (EdmPrimitiveType) edmProperty.getType();
- try {
- if (!(primitiveType.validate(primitiveType.fromUriLiteral(literalValue), edmProperty.isNullable(),
- edmProperty.getMaxLength(), edmProperty.getPrecision(), edmProperty.getScale(), edmProperty.isUnicode()))) {
- throw new UriValidationException("Invalid key property",
- UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, parameterName);
- }
- } catch (final EdmPrimitiveTypeException e) {
- throw new UriValidationException("Invalid key property",
- UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, parameterName);
- }
-
- return new UriParameterImpl()
- .setName(parameterName)
- .setText("null".equals(literalValue) ? null : literalValue);
- }
-
private UriResource typeCast(final FullQualifiedName name, final EdmStructuredType type,
final UriResourcePartTyped previousTyped) throws UriParserException, UriValidationException {
if (type.compatibleTo(previousTyped.getType())) {
@@ -501,7 +318,7 @@ public class ResourcePathParser {
}
if (tokenizer.next(TokenKind.OPEN)) {
((UriResourceWithKeysImpl) previousTyped).setKeyPredicates(
- keyPredicate((EdmEntityType) type, null));
+ ParserHelper.parseKeyPredicate(tokenizer, (EdmEntityType) type, null));
}
} else {
previousTypeFilter = ((UriResourceTypedImpl) previousTyped).getTypeFilter();
@@ -534,11 +351,8 @@ public class ResourcePathParser {
private UriResource functionCall(final EdmFunctionImport edmFunctionImport,
final FullQualifiedName boundFunctionName, final FullQualifiedName bindingParameterTypeName,
final boolean isBindingParameterCollection) throws UriParserException, UriValidationException {
- final List<UriParameter> parameters = functionParameters();
- List<String> names = new ArrayList<String>();
- for (final UriParameter parameter : parameters) {
- names.add(parameter.getName());
- }
+ final List<UriParameter> parameters = ParserHelper.parseFunctionParameters(tokenizer, false);
+ final List<String> names = ParserHelper.getParameterNames(parameters);
EdmFunction function = null;
if (edmFunctionImport != null) {
function = edmFunctionImport.getUnboundFunction(names);
@@ -557,16 +371,13 @@ public class ResourcePathParser {
UriParserSemanticException.MessageKeys.UNKNOWN_PART, boundFunctionName.getFullQualifiedNameAsString());
}
}
- UriResourceFunctionImpl resource = new UriResourceFunctionImpl()
- .setFunctionImport(edmFunctionImport, null)
- .setFunction(function)
- .setParameters(parameters);
+ UriResourceFunctionImpl resource = new UriResourceFunctionImpl(edmFunctionImport, function, parameters);
if (tokenizer.next(TokenKind.OPEN)) {
if (function.getReturnType() != null
&& function.getReturnType().getType().getKind() == EdmTypeKind.ENTITY
&& function.getReturnType().isCollection()) {
resource.setKeyPredicates(
- keyPredicate((EdmEntityType) function.getReturnType().getType(), null));
+ ParserHelper.parseKeyPredicate(tokenizer, (EdmEntityType) function.getReturnType().getType(), null));
} else {
throw new UriParserSemanticException("A key is not allowed.",
UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED);
@@ -575,106 +386,4 @@ public class ResourcePathParser {
ParserHelper.requireTokenEnd(tokenizer);
return resource;
}
-
- private List<UriParameter> functionParameters() throws UriParserException {
- List<UriParameter> parameters = new ArrayList<UriParameter>();
- ParserHelper.requireNext(tokenizer, TokenKind.OPEN);
- if (tokenizer.next(TokenKind.CLOSE)) {
- return parameters;
- }
- do {
- ParserHelper.requireNext(tokenizer, TokenKind.ODataIdentifier);
- final String name = tokenizer.getText();
- if (parameters.contains(name)) {
- throw new UriParserSemanticException("Duplicated function parameter " + name,
- UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, name);
- }
- ParserHelper.requireNext(tokenizer, TokenKind.EQ);
- if (tokenizer.next(TokenKind.COMMA) || tokenizer.next(TokenKind.CLOSE) || tokenizer.next(TokenKind.EOF)) {
- throw new UriParserSyntaxException("Parameter value expected.", UriParserSyntaxException.MessageKeys.SYNTAX);
- }
- if (tokenizer.next(TokenKind.ParameterAliasName)) {
- parameters.add(new UriParameterImpl().setName(name).setAlias(tokenizer.getText()));
- } else if (nextPrimitiveValue()) {
- final String literalValue = tokenizer.getText();
- parameters.add(new UriParameterImpl().setName(name)
- .setText("null".equals(literalValue) ? null : literalValue));
- } else {
- throw new UriParserSemanticException("Wrong parameter value.",
- UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, "");
- }
- } while (tokenizer.next(TokenKind.COMMA));
- ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
- return parameters;
- }
-
- private boolean nextPrimitiveTypeValue(final EdmPrimitiveType primitiveType, final boolean nullable) {
- final EdmPrimitiveType type = primitiveType instanceof EdmTypeDefinition ?
- ((EdmTypeDefinition) primitiveType).getUnderlyingType() :
- primitiveType;
- if (tokenizer.next(TokenKind.ParameterAliasName)) {
- return true;
- } else if (nullable && tokenizer.next(TokenKind.NULL)) {
- return true;
-
- } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Boolean).equals(type)) {
- return tokenizer.next(TokenKind.BooleanValue);
- } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.String).equals(type)) {
- return tokenizer.next(TokenKind.StringValue);
- } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.SByte).equals(type)
- || odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Byte).equals(type)
- || odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int16).equals(type)
- || odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int32).equals(type)
- || odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int64).equals(type)) {
- return tokenizer.next(TokenKind.IntegerValue);
- } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Guid).equals(type)) {
- return tokenizer.next(TokenKind.GuidValue);
- } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Date).equals(type)) {
- return tokenizer.next(TokenKind.DateValue);
- } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.DateTimeOffset).equals(type)) {
- return tokenizer.next(TokenKind.DateTimeOffsetValue);
- } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.TimeOfDay).equals(type)) {
- return tokenizer.next(TokenKind.TimeOfDayValue);
- } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Decimal).equals(type)) {
- // The order is important.
- // A decimal value should not be parsed as integer and let the tokenizer stop at the decimal point.
- return tokenizer.next(TokenKind.DecimalValue)
- || tokenizer.next(TokenKind.IntegerValue);
- } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Double).equals(type)) {
- // The order is important.
- // A floating-point value should not be parsed as decimal and let the tokenizer stop at 'E'.
- // A decimal value should not be parsed as integer and let the tokenizer stop at the decimal point.
- return tokenizer.next(TokenKind.DoubleValue)
- || tokenizer.next(TokenKind.DecimalValue)
- || tokenizer.next(TokenKind.IntegerValue);
- } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Duration).equals(type)) {
- return tokenizer.next(TokenKind.DurationValue);
- } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Binary).equals(type)) {
- return tokenizer.next(TokenKind.BinaryValue);
- } else if (type.getKind() == EdmTypeKind.ENUM) {
- return tokenizer.next(TokenKind.EnumValue);
- } else {
- return false;
- }
- }
-
- private boolean nextPrimitiveValue() {
- return tokenizer.next(TokenKind.NULL)
- || tokenizer.next(TokenKind.BooleanValue)
- || tokenizer.next(TokenKind.StringValue)
-
- // The order of the next seven expressions is important in order to avoid
- // finding partly parsed tokens (counter-intuitive as it may be, even a GUID may start with digits ...).
- || tokenizer.next(TokenKind.DoubleValue)
- || tokenizer.next(TokenKind.DecimalValue)
- || tokenizer.next(TokenKind.GuidValue)
- || tokenizer.next(TokenKind.DateTimeOffsetValue)
- || tokenizer.next(TokenKind.DateValue)
- || tokenizer.next(TokenKind.TimeOfDayValue)
- || tokenizer.next(TokenKind.IntegerValue)
-
- || tokenizer.next(TokenKind.DurationValue)
- || tokenizer.next(TokenKind.BinaryValue)
- || tokenizer.next(TokenKind.EnumValue);
- }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/SelectParser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/SelectParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/SelectParser.java
index b257e68..00f3673 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/SelectParser.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/SelectParser.java
@@ -156,10 +156,10 @@ public class SelectParser {
throw new UriParserSemanticException("Function not found.",
UriParserSemanticException.MessageKeys.UNKNOWN_PART, qualifiedName.getFullQualifiedNameAsString());
} else {
- return new UriResourceFunctionImpl().setFunction(boundFunction);
+ return new UriResourceFunctionImpl(null, boundFunction, null);
}
} else {
- return new UriResourceActionImpl().setAction(boundAction);
+ return new UriResourceActionImpl(boundAction);
}
}
@@ -187,16 +187,16 @@ public class SelectParser {
UriParserSemanticException.MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE,
referencedType.getName(), name);
} else {
- resource.addResourcePart(new UriResourceNavigationPropertyImpl().setNavigationProperty(navigationProperty));
+ resource.addResourcePart(new UriResourceNavigationPropertyImpl(navigationProperty));
}
} else if (property.isPrimitive()
|| property.getType().getKind() == EdmTypeKind.ENUM
|| property.getType().getKind() == EdmTypeKind.DEFINITION) {
- resource.addResourcePart(new UriResourcePrimitivePropertyImpl().setProperty(property));
+ resource.addResourcePart(new UriResourcePrimitivePropertyImpl(property));
} else {
- UriResourceComplexPropertyImpl complexPart = new UriResourceComplexPropertyImpl().setProperty(property);
+ UriResourceComplexPropertyImpl complexPart = new UriResourceComplexPropertyImpl(property);
resource.addResourcePart(complexPart);
if (tokenizer.next(TokenKind.SLASH)) {
if (tokenizer.next(TokenKind.QualifiedName)) {
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriContext.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriContext.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriContext.java
index c0db85b..36a0887 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriContext.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriContext.java
@@ -32,10 +32,9 @@ import org.apache.olingo.server.core.uri.queryoption.SelectItemImpl;
*/
public class UriContext {
- public static class LambdaVariables {
+ public static class LambdaVariable {
public String name;
public EdmType type;
- public boolean isCollection;
}
/**
@@ -43,7 +42,7 @@ public class UriContext {
* As lambda functions can be nested there may be more than one allowed lambda variables at a time while parsing a
* $filter or $orderby expressions.
*/
- public Deque<LambdaVariables> allowedLambdaVariables;
+ public Deque<LambdaVariable> allowedLambdaVariables;
/**
* Used to stack type information for nested $expand, $filter query options and other cases.
*/
@@ -110,7 +109,7 @@ public class UriContext {
contextReadingFunctionParameters = false;
contextSelectItem = null;
contextTypes = new ArrayDeque<EdmType>();
- allowedLambdaVariables = new ArrayDeque<UriContext.LambdaVariables>();
+ allowedLambdaVariables = new ArrayDeque<UriContext.LambdaVariable>();
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
index 9d29ab2..1bab218 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
@@ -252,8 +252,8 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
return new FullQualifiedName(namespace, odi);
}
- private UriContext.LambdaVariables getLambdaVar(final String odi) {
- for (UriContext.LambdaVariables item : context.allowedLambdaVariables) {
+ private UriContext.LambdaVariable getLambdaVar(final String odi) {
+ for (UriContext.LambdaVariable item : context.allowedLambdaVariables) {
if (item.name.equals(odi)) {
return item;
}
@@ -292,7 +292,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
|| parts.get(0) instanceof UriResourceRoot)) {
ensureNamespaceIsNull(ctx.vNS);
context.contextUriInfo.addResourcePart(
- new UriResourceEntitySetImpl().setEntitSet(edmEntitySet));
+ new UriResourceEntitySetImpl(edmEntitySet));
return null;
}
@@ -303,7 +303,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
|| parts.get(0) instanceof UriResourceRoot)) {
ensureNamespaceIsNull(ctx.vNS);
context.contextUriInfo.addResourcePart(
- new UriResourceSingletonImpl().setSingleton(edmSingleton));
+ new UriResourceSingletonImpl(edmSingleton));
return null;
}
@@ -314,7 +314,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
|| parts.get(0) instanceof UriResourceRoot)) {
ensureNamespaceIsNull(ctx.vNS);
context.contextUriInfo.addResourcePart(
- new UriResourceActionImpl().setActionImport(edmActionImport));
+ new UriResourceActionImpl(edmActionImport));
return null;
}
@@ -344,9 +344,6 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
// mark parameters as consumed
ctx.vlNVO.remove(0);
- UriResourceFunctionImpl uriResource = new UriResourceFunctionImpl()
- .setFunctionImport(edmFunctionImport, parameters);
-
// collect parameter names
List<String> names = new ArrayList<String>();
for (UriParameter item : parameters) {
@@ -366,7 +363,9 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
}
ensureNamespaceIsNull(ctx.vNS);
- uriResource.setFunction(edmFunctionImport.getUnboundFunction(names));
+ UriResourceFunctionImpl uriResource = new UriResourceFunctionImpl(edmFunctionImport,
+ edmFunctionImport.getUnboundFunction(names),
+ parameters);
context.contextUriInfo.addResourcePart(uriResource);
return null;
}
@@ -390,7 +389,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
sourceType = context.contextTypes.peek();
sourceIsCollection = context.isCollection;
} else if (lastResourcePart instanceof UriResourcePartTyped) {
- sourceType = Parser.getTypeInformation((UriResourcePartTyped) lastResourcePart);
+ sourceType = ParserHelper.getTypeInformation((UriResourcePartTyped) lastResourcePart);
sourceIsCollection = ((UriResourcePartTyped) lastResourcePart).isCollection();
} else {
throw wrap(new UriParserSemanticException(
@@ -401,12 +400,9 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
if (ctx.vNS == null) { // without namespace
// first check for lambda variable because a newly add property should not shadow a long used lambda variable
- UriContext.LambdaVariables lVar = getLambdaVar(odi);
+ UriContext.LambdaVariable lVar = getLambdaVar(odi);
if (lVar != null) {
- UriResourceLambdaVarImpl lambdaResource = new UriResourceLambdaVarImpl();
- lambdaResource.setVariableText(lVar.name);
- lambdaResource.setType(lVar.type);
- lambdaResource.setCollection(lVar.isCollection);
+ UriResourceLambdaVarImpl lambdaResource = new UriResourceLambdaVarImpl(lVar.name, lVar.type);
context.contextUriInfo.addResourcePart(lambdaResource);
return null;
}
@@ -442,14 +438,13 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
|| property.getType().getKind() == EdmTypeKind.ENUM
|| property.getType().getKind() == EdmTypeKind.DEFINITION) {
// create simple property
- UriResourcePrimitivePropertyImpl simpleResource = new UriResourcePrimitivePropertyImpl()
- .setProperty((EdmProperty) property);
+ UriResourcePrimitivePropertyImpl simpleResource =
+ new UriResourcePrimitivePropertyImpl((EdmProperty) property);
context.contextUriInfo.addResourcePart(simpleResource);
return null;
} else {
// create complex property
- UriResourceComplexPropertyImpl complexResource = new UriResourceComplexPropertyImpl()
- .setProperty((EdmProperty) property);
+ UriResourceComplexPropertyImpl complexResource = new UriResourceComplexPropertyImpl((EdmProperty) property);
context.contextUriInfo.addResourcePart(complexResource);
return null;
}
@@ -461,8 +456,8 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED));
}
- UriResourceNavigationPropertyImpl navigationResource = new UriResourceNavigationPropertyImpl()
- .setNavigationProperty((EdmNavigationProperty) property);
+ UriResourceNavigationPropertyImpl navigationResource =
+ new UriResourceNavigationPropertyImpl((EdmNavigationProperty) property);
context.contextUriInfo.addResourcePart(navigationResource);
return null;
} else {
@@ -488,9 +483,9 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
if (lastResourcePart == null) {
// this may be the case if a member expression within a filter starts with a typeCast
- UriResourceStartingTypeFilterImpl uriResource = new UriResourceStartingTypeFilterImpl()
- .setType(filterEntityType)
- .setCollection(sourceIsCollection);
+ UriResourceStartingTypeFilterImpl uriResource = new UriResourceStartingTypeFilterImpl(
+ filterEntityType,
+ sourceIsCollection);
if (sourceIsCollection) {
uriResource.setCollectionTypeFilter(filterEntityType);
} else {
@@ -562,9 +557,8 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
// is simple complex type cast
if (lastResourcePart == null) {
// this may be the case if a member expression within a filter starts with a typeCast
- UriResourceStartingTypeFilterImpl uriResource = new UriResourceStartingTypeFilterImpl()
- .setType(filterComplexType)
- .setCollection(sourceIsCollection);
+ UriResourceStartingTypeFilterImpl uriResource =
+ new UriResourceStartingTypeFilterImpl(filterComplexType, sourceIsCollection);
if (sourceIsCollection) {
uriResource.setCollectionTypeFilter(filterComplexType);
@@ -626,8 +620,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
// check for action
EdmAction action = edm.getBoundAction(fullFilterName, fullBindingTypeName, sourceIsCollection);
if (action != null) {
- UriResourceActionImpl pathInfoAction = new UriResourceActionImpl();
- pathInfoAction.setAction(action);
+ UriResourceActionImpl pathInfoAction = new UriResourceActionImpl(action);
context.contextUriInfo.addResourcePart(pathInfoAction);
return null;
}
@@ -652,9 +645,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
EdmFunction function = edm.getBoundFunction(fullFilterName, fullBindingTypeName, sourceIsCollection, names);
if (function != null) {
- UriResourceFunctionImpl pathInfoFunction = new UriResourceFunctionImpl()
- .setFunction(function)
- .setParameters(parameters);
+ UriResourceFunctionImpl pathInfoFunction = new UriResourceFunctionImpl(null, function, parameters);
context.contextUriInfo.addResourcePart(pathInfoFunction);
// mark parameters as consumed
@@ -666,9 +657,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
function = edm.getUnboundFunction(fullFilterName, names);
if (function != null) {
- UriResourceFunctionImpl pathInfoFunction = new UriResourceFunctionImpl()
- .setFunction(function)
- .setParameters(parameters);
+ UriResourceFunctionImpl pathInfoFunction = new UriResourceFunctionImpl(null, function, parameters);
context.contextUriInfo.addResourcePart(pathInfoFunction);
// mark parameters as consumed
@@ -706,8 +695,6 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
@Override
public Object visitAllExpr(final AllExprContext ctx) {
- UriResourceLambdaAllImpl all = new UriResourceLambdaAllImpl();
-
UriResource obj = context.contextUriInfo.getLastResourcePart();
if (!(obj instanceof UriResourcePartTyped)) {
throw wrap(new UriParserSemanticException("all only allowed on typed path segments",
@@ -720,16 +707,14 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
}
}
- UriContext.LambdaVariables var = new UriContext.LambdaVariables();
+ UriContext.LambdaVariable var = new UriContext.LambdaVariable();
var.name = ctx.vLV.getText();
- var.type = Parser.getTypeInformation((UriResourcePartTyped) obj);
- var.isCollection = false;
+ var.type = ParserHelper.getTypeInformation((UriResourcePartTyped) obj);
- all.setLamdaVariable(ctx.vLV.getText());
context.allowedLambdaVariables.push(var);
- all.setExpression((Expression) ctx.vLE.accept(this));
+ Expression expression = (Expression) ctx.vLE.accept(this);
context.allowedLambdaVariables.pop();
- return all;
+ return new UriResourceLambdaAllImpl(var.name, expression);
}
@Override
@@ -895,7 +880,6 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
@Override
public Object visitAnyExpr(final AnyExprContext ctx) {
- UriResourceLambdaAnyImpl any = new UriResourceLambdaAnyImpl();
if (ctx.vLV != null) {
UriResourceImpl lastResourcePart = (UriResourceImpl) context.contextUriInfo.getLastResourcePart();
if (!(lastResourcePart instanceof UriResourcePartTyped)) {
@@ -909,17 +893,16 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
}
}
- UriContext.LambdaVariables var = new UriContext.LambdaVariables();
+ UriContext.LambdaVariable var = new UriContext.LambdaVariable();
var.name = ctx.vLV.getText();
- var.type = Parser.getTypeInformation((UriResourcePartTyped) lastResourcePart);
- var.isCollection = false;
+ var.type = ParserHelper.getTypeInformation((UriResourcePartTyped) lastResourcePart);
- any.setLamdaVariable(ctx.vLV.getText());
context.allowedLambdaVariables.push(var);
- any.setExpression((Expression) ctx.vLE.accept(this));
+ Expression expression = (Expression) ctx.vLE.accept(this);
context.allowedLambdaVariables.pop();
+ return new UriResourceLambdaAnyImpl(var.name, expression);
}
- return any;
+ return null;
}
@Override
@@ -1238,18 +1221,18 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
if (context.contextExpandItemPath == null) {
// use the type of the last resource path segement
UriResourceTypedImpl lastSegment = (UriResourceTypedImpl) context.contextUriInfo.getLastResourcePart();
- targetType = Parser.getTypeInformation(lastSegment);
+ targetType = ParserHelper.getTypeInformation(lastSegment);
isColl = lastSegment.isCollection();
} else {
if (context.contextExpandItemPath.getResourcePath() == null) {
// use the type of the last resource path segement
UriResourceTypedImpl lastSegment = (UriResourceTypedImpl) context.contextUriInfo.getLastResourcePart();
- targetType = Parser.getTypeInformation(lastSegment);
+ targetType = ParserHelper.getTypeInformation(lastSegment);
isColl = lastSegment.isCollection();
} else {
// use the type of the last ''expand'' path segement
UriInfoImpl info = (UriInfoImpl) context.contextExpandItemPath.getResourcePath();
- targetType = Parser.getTypeInformation((UriResourcePartTyped) info.getLastResourcePart());
+ targetType = ParserHelper.getTypeInformation((UriResourcePartTyped) info.getLastResourcePart());
isColl = ((UriResourcePartTyped) info.getLastResourcePart()).isCollection();
}
}
@@ -1400,10 +1383,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
}
if (ctx.vIt != null || ctx.vIts != null) {
- UriResourceItImpl pathInfoIT = new UriResourceItImpl();
- pathInfoIT.setType(context.contextTypes.peek());
- pathInfoIT.setCollection(context.isCollection);
- uriInfoImplpath.addResourcePart(pathInfoIT);
+ uriInfoImplpath.addResourcePart(new UriResourceItImpl(context.contextTypes.peek(), context.isCollection));
}
if (ctx.vPs != null) {
@@ -1915,9 +1895,9 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
UriResourcePartTyped lastType = (UriResourcePartTyped) lastResource;
- UriResourceRootImpl pathInfoRoot = new UriResourceRootImpl();
- pathInfoRoot.setCollection(lastType.isCollection());
- pathInfoRoot.setType(Parser.getTypeInformation(lastType));
+ UriResourceRootImpl pathInfoRoot = new UriResourceRootImpl(
+ ParserHelper.getTypeInformation(lastType),
+ lastType.isCollection());
UriInfoImpl uriInfoImplpath = new UriInfoImpl().setKind(UriInfoKind.resource);
uriInfoImplpath.addResourcePart(pathInfoRoot);
@@ -2010,7 +1990,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
UriInfoImpl uriInfo = (UriInfoImpl) context.contextSelectItem.getResourcePath();
UriResource last = uriInfo.getLastResourcePart();
- prevType = Parser.getTypeInformation((UriResourcePartTyped) last);
+ prevType = ParserHelper.getTypeInformation((UriResourcePartTyped) last);
if (prevType == null) {
throw wrap(new UriParserSemanticException("prev segment not typed",
UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PARTS, "select"));
@@ -2038,8 +2018,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
|| property.getType().getKind() == EdmTypeKind.ENUM
|| property.getType().getKind() == EdmTypeKind.DEFINITION) {
- UriResourcePrimitivePropertyImpl simple = new UriResourcePrimitivePropertyImpl();
- simple.setProperty(property);
+ UriResourcePrimitivePropertyImpl simple = new UriResourcePrimitivePropertyImpl(property);
UriInfoImpl uriInfo = (UriInfoImpl) context.contextSelectItem.getResourcePath();
if (uriInfo == null) {
@@ -2059,8 +2038,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
} else {
UriInfoImpl uriInfo = (UriInfoImpl) context.contextSelectItem.getResourcePath();
- UriResourceComplexPropertyImpl complex = new UriResourceComplexPropertyImpl();
- complex.setProperty(property);
+ UriResourceComplexPropertyImpl complex = new UriResourceComplexPropertyImpl(property);
if (uriInfo == null) {
uriInfo = new UriInfoImpl().setKind(UriInfoKind.resource);
@@ -2096,7 +2074,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
EdmComplexType ct = edm.getComplexType(fullName);
if (ct != null) {
if ((ct.compatibleTo(prevType))) {
- UriResourceStartingTypeFilterImpl resourcePart = new UriResourceStartingTypeFilterImpl();
+ UriResourceStartingTypeFilterImpl resourcePart = new UriResourceStartingTypeFilterImpl(null, false);
resourcePart.setCollectionTypeFilter(ct);
UriInfoImpl uriInfo = new UriInfoImpl().setKind(UriInfoKind.resource);
@@ -2115,7 +2093,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
EdmEntityType et = edm.getEntityType(fullName);
if (et != null) {
if ((et.compatibleTo(prevType))) {
- UriResourceStartingTypeFilterImpl resourcePart = new UriResourceStartingTypeFilterImpl();
+ UriResourceStartingTypeFilterImpl resourcePart = new UriResourceStartingTypeFilterImpl(null, false);
resourcePart.setCollectionTypeFilter(et);
UriInfoImpl uriInfo = new UriInfoImpl().setKind(UriInfoKind.resource);
@@ -2142,13 +2120,13 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
throw wrap(new UriParserSemanticException("prev segment typed",
UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PARTS, "select"));
}
- EdmType prevType = Parser.getTypeInformation((UriResourcePartTyped) last);
+ EdmType prevType = ParserHelper.getTypeInformation((UriResourcePartTyped) last);
if (prevType instanceof EdmComplexType) {
EdmComplexType ct = edm.getComplexType(fullName);
if (ct != null) {
if ((ct.compatibleTo(prevType))) {
- UriResourceStartingTypeFilterImpl resourcePart = new UriResourceStartingTypeFilterImpl();
+ UriResourceStartingTypeFilterImpl resourcePart = new UriResourceStartingTypeFilterImpl(null, false);
resourcePart.setCollectionTypeFilter(ct);
uriInfo.addResourcePart(resourcePart);
@@ -2186,7 +2164,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
throw wrap(new UriParserSemanticException("prev segment typed",
UriParserSemanticException.MessageKeys.PREVIOUS_PART_TYPED));
}
- prevType = Parser.getTypeInformation((UriResourcePartTyped) last);
+ prevType = ParserHelper.getTypeInformation((UriResourcePartTyped) last);
}
final FullQualifiedName finalTypeName = prevType.getFullQualifiedName();
@@ -2195,8 +2173,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
EdmAction action = edm.getBoundAction(fullName, finalTypeName, null);
if (action != null) {
- UriResourceActionImpl uriAction = new UriResourceActionImpl();
- uriAction.setAction(action);
+ UriResourceActionImpl uriAction = new UriResourceActionImpl(action);
UriInfoImpl resourcePath = (UriInfoImpl) context.contextSelectItem.getResourcePath();
resourcePath.addResourcePart(uriAction);
@@ -2206,8 +2183,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
EdmFunction function = edm.getBoundFunction(fullName, finalTypeName, null, null);
if (function != null) {
- UriResourceFunctionImpl uriFunction = new UriResourceFunctionImpl();
- uriFunction.setFunction(function);
+ UriResourceFunctionImpl uriFunction = new UriResourceFunctionImpl(null, function, null);
UriInfoImpl resourcePath = (UriInfoImpl) context.contextSelectItem.getResourcePath();
resourcePath.addResourcePart(uriFunction);
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
index 4b43cd9..37f1b76 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
@@ -40,10 +40,14 @@ public class UriTokenizer {
ROOT,
IT,
+ ANY,
+ ALL,
+
OPEN,
CLOSE,
COMMA,
SEMI,
+ COLON,
DOT,
SLASH,
EQ,
@@ -119,7 +123,10 @@ public class UriTokenizer {
TotalsecondsMethod,
ToupperMethod,
TrimMethod,
- YearMethod
+ YearMethod,
+
+ AscSuffix,
+ DescSuffix
}
private final String parseString;
@@ -174,6 +181,13 @@ public class UriTokenizer {
found = nextConstant("$it");
break;
+ case ANY:
+ found = nextConstant("any");
+ break;
+ case ALL:
+ found = nextConstant("all");
+ break;
+
case OPEN:
found = nextCharacter('(');
break;
@@ -186,6 +200,9 @@ public class UriTokenizer {
case SEMI:
found = nextCharacter(';');
break;
+ case COLON:
+ found = nextCharacter(':');
+ break;
case DOT:
found = nextCharacter('.');
break;
@@ -409,6 +426,14 @@ public class UriTokenizer {
case YearMethod:
found = nextMethod("year");
break;
+
+ // Suffixes
+ case AscSuffix:
+ found = nextSuffix("asc");
+ break;
+ case DescSuffix:
+ found = nextSuffix("desc");
+ break;
}
if (found) {
@@ -543,6 +568,15 @@ public class UriTokenizer {
}
/**
+ * Moves past (required) whitespace and the given suffix name if found;
+ * otherwise leaves the index unchanged.
+ * @return whether the suffix has been found at the current index
+ */
+ private boolean nextSuffix(final String suffixName) {
+ return nextWhitespace() && nextConstant(suffixName);
+ }
+
+ /**
* Moves past an OData identifier if found; otherwise leaves the index unchanged.
* @return whether an OData identifier has been found at the current index
*/
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/MemberImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/MemberImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/MemberImpl.java
index a71e382..6ef37e4 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/MemberImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/MemberImpl.java
@@ -94,4 +94,9 @@ public class MemberImpl implements Member {
}
return false;
}
+
+ @Override
+ public String toString() {
+ return path.getUriResourceParts().toString() + (startTypeFilter == null ? "" : startTypeFilter);
+ }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/UriInfoImplTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/UriInfoImplTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/UriInfoImplTest.java
index 4c76e96..68e6637 100644
--- a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/UriInfoImplTest.java
+++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/UriInfoImplTest.java
@@ -25,6 +25,7 @@ import static org.junit.Assert.assertTrue;
import java.util.Arrays;
+import org.apache.olingo.commons.api.edm.EdmAction;
import org.apache.olingo.commons.api.edm.EdmEntityType;
import org.apache.olingo.commons.api.ex.ODataRuntimeException;
import org.apache.olingo.server.api.uri.UriInfo;
@@ -33,9 +34,6 @@ import org.apache.olingo.server.api.uri.UriResourceAction;
import org.apache.olingo.server.api.uri.UriResourceEntitySet;
import org.apache.olingo.server.api.uri.queryoption.AliasQueryOption;
import org.apache.olingo.server.api.uri.queryoption.QueryOption;
-import org.apache.olingo.server.core.uri.UriInfoImpl;
-import org.apache.olingo.server.core.uri.UriResourceActionImpl;
-import org.apache.olingo.server.core.uri.UriResourceEntitySetImpl;
import org.apache.olingo.server.core.uri.queryoption.AliasQueryOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.CountOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.CustomQueryOptionImpl;
@@ -86,9 +84,9 @@ public class UriInfoImplTest {
public void resourceParts() {
UriInfoImpl uriInfo = new UriInfoImpl();
- final UriResourceAction action = new UriResourceActionImpl();
- final UriResourceEntitySet entitySet0 = new UriResourceEntitySetImpl();
- final UriResourceEntitySet entitySet1 = new UriResourceEntitySetImpl();
+ final UriResourceAction action = new UriResourceActionImpl((EdmAction) null);
+ final UriResourceEntitySet entitySet0 = new UriResourceEntitySetImpl(null);
+ final UriResourceEntitySet entitySet1 = new UriResourceEntitySetImpl(null);
uriInfo.addResourcePart(action);
uriInfo.addResourcePart(entitySet0);
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java
index 183ff22..4ab7fce 100644
--- a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java
+++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java
@@ -28,6 +28,7 @@ import java.util.Locale;
import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind;
+import org.apache.olingo.server.core.uri.validator.UriValidationException;
import org.junit.Test;
public class ExpressionParserTest {
@@ -127,7 +128,7 @@ public class ExpressionParserTest {
@Test
public void unary() throws Exception {
Expression expression = parseExpression("-5");
- assertEquals("{MINUS 5}", expression.toString());
+ assertEquals("-5", expression.toString());
assertEquals("{MINUS -1}", parseExpression("--1").toString());
assertEquals("{MINUS duration'PT1M'}", parseExpression("-duration'PT1M'").toString());
@@ -135,13 +136,13 @@ public class ExpressionParserTest {
expression = parseExpression("not false");
assertEquals("{NOT false}", expression.toString());
- wrongExpression("-11:12:13");
+ wrongExpression("not 11:12:13");
}
@Test
public void grouping() throws Exception {
Expression expression = parseExpression("-5 add 5");
- assertEquals("{{MINUS 5} ADD 5}", expression.toString());
+ assertEquals("{-5 ADD 5}", expression.toString());
expression = parseExpression("-(5 add 5)");
assertEquals("{MINUS {5 ADD 5}}", expression.toString());
@@ -149,7 +150,7 @@ public class ExpressionParserTest {
@Test
public void precedence() throws Exception {
- assertEquals("{{MINUS 1} ADD {2 DIV 3}}", parseExpression("-1 add 2 div 3").toString());
+ assertEquals("{-1 ADD {2 DIV 3}}", parseExpression("-1 add 2 div 3").toString());
assertEquals("{true OR {{NOT false} AND true}}", parseExpression("true or not false and true").toString());
}
@@ -264,7 +265,8 @@ public class ExpressionParserTest {
wrongExpression("substring(1,2)");
}
- private Expression parseMethod(TokenKind kind, String... parameters) throws UriParserException {
+ private Expression parseMethod(TokenKind kind, String... parameters)
+ throws UriParserException, UriValidationException {
String expressionString = kind.name().substring(0, kind.name().indexOf("Method"))
.toLowerCase(Locale.ROOT).replace("geo", "geo.") + '(';
boolean first = true;
@@ -283,9 +285,10 @@ public class ExpressionParserTest {
return expression;
}
- private Expression parseExpression(final String expressionString) throws UriParserException {
+ private Expression parseExpression(final String expressionString)
+ throws UriParserException, UriValidationException {
UriTokenizer tokenizer = new UriTokenizer(expressionString);
- Expression expression = new ExpressionParser(null, odata).parse(tokenizer);
+ Expression expression = new ExpressionParser(null, odata).parse(tokenizer, null, null);
assertNotNull(expression);
assertTrue(tokenizer.next(TokenKind.EOF));
return expression;
@@ -293,10 +296,12 @@ public class ExpressionParserTest {
private void wrongExpression(final String expressionString) {
try {
- new ExpressionParser(null, odata).parse(new UriTokenizer(expressionString));
+ new ExpressionParser(null, odata).parse(new UriTokenizer(expressionString), null, null);
fail("Expected exception not thrown.");
} catch (final UriParserException e) {
assertNotNull(e);
+ } catch (final UriValidationException e) {
+ assertNotNull(e);
}
}
}
[28/30] olingo-odata4 git commit: [OLINGO-834] Fix fit maven pom
Posted by ch...@apache.org.
[OLINGO-834] Fix fit maven pom
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/40be3e4a
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/40be3e4a
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/40be3e4a
Branch: refs/heads/master
Commit: 40be3e4a29e72bf5c224c5003a87de25e5ef8d24
Parents: 26080f4
Author: Christian Amend <ch...@sap.com>
Authored: Thu Jan 7 16:16:12 2016 +0100
Committer: Christian Amend <ch...@sap.com>
Committed: Thu Jan 7 16:16:12 2016 +0100
----------------------------------------------------------------------
fit/pom.xml | 7 -------
1 file changed, 7 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/40be3e4a/fit/pom.xml
----------------------------------------------------------------------
diff --git a/fit/pom.xml b/fit/pom.xml
index 516c5f5..34eff39 100644
--- a/fit/pom.xml
+++ b/fit/pom.xml
@@ -208,13 +208,6 @@
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-deploy-plugin</artifactId>
- <configuration>
- <skip>true</skip>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.8</version>
<executions>
[21/30] olingo-odata4 git commit: [OLINGO-834] $expand parser in Java
+ clean-up
Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java
index c27c960..a94026f 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java
@@ -18,29 +18,19 @@
*/
package org.apache.olingo.server.core.uri.antlr;
-import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.Collections;
import org.apache.olingo.commons.api.edm.Edm;
-import org.apache.olingo.commons.api.edm.EdmEntityContainer;
-import org.apache.olingo.commons.api.edm.EdmEntitySet;
-import org.apache.olingo.commons.api.edm.EdmEntityType;
-import org.apache.olingo.commons.api.edm.EdmKeyPropertyRef;
-import org.apache.olingo.commons.api.edm.EdmNavigationProperty;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
-import org.apache.olingo.commons.api.edm.EdmProperty;
import org.apache.olingo.commons.api.edm.FullQualifiedName;
import org.apache.olingo.commons.api.format.ContentType;
-import org.apache.olingo.commons.core.Encoder;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmString;
import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.edmx.EdmxReference;
import org.apache.olingo.server.api.uri.UriInfoKind;
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.UriParserException;
import org.apache.olingo.server.core.uri.parser.UriParserSemanticException.MessageKeys;
import org.apache.olingo.server.core.uri.parser.UriParserSyntaxException;
import org.apache.olingo.server.core.uri.parser.search.SearchParserException;
@@ -56,19 +46,17 @@ import org.apache.olingo.server.tecsvc.provider.EnumTypeProvider;
import org.apache.olingo.server.tecsvc.provider.FunctionProvider;
import org.apache.olingo.server.tecsvc.provider.PropertyProvider;
import org.apache.olingo.server.tecsvc.provider.TypeDefinitionProvider;
-import org.junit.Ignore;
import org.junit.Test;
-import org.mockito.Mockito;
public class TestFullResourcePath {
private static final OData oData = OData.newInstance();
+ private static final Edm edm = oData.createServiceMetadata(
+ new EdmTechProvider(), Collections.<EdmxReference> emptyList()).getEdm();
private final TestUriValidator testUri;
private final FilterValidator testFilter;
public TestFullResourcePath() {
- final Edm edm = oData.createServiceMetadata(new EdmTechProvider(), Collections.<EdmxReference> emptyList())
- .getEdm();
testUri = new TestUriValidator().setEdm(edm);
testFilter = new FilterValidator().setEdm(edm);
}
@@ -1033,16 +1021,10 @@ public class TestFullResourcePath {
public void resourcePathWithApostrophe() throws Exception {
testUri.runEx("ESAllPrim'").isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
testUri.runEx("ESAllPrim'InvalidStuff").isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
-
- testFilter.runOnETKeyNavEx("PropertyInt16' eq 0")
- .isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
-
- testFilter.runOnETKeyNavEx("PropertyInt16 eq' 0")
- .isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
-
+ testFilter.runOnETKeyNavEx("PropertyInt16' eq 0").isExSemantic(MessageKeys.TYPES_NOT_COMPATIBLE);
+ testFilter.runOnETKeyNavEx("PropertyInt16 eq' 0").isExSemantic(MessageKeys.TYPES_NOT_COMPATIBLE);
testFilter.runOnETKeyNavEx("PropertyInt16 eq 0'")
.isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
-
testFilter.runOnETKeyNavEx("PropertyInt16 eq 'dsd''")
.isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
}
@@ -1306,13 +1288,13 @@ public class TestFullResourcePath {
@Test
public void runEsNameParaKeys() throws Exception {
- testUri.run(encode("ESAllKey(PropertyString='O''Neil',PropertyBoolean=true,PropertyByte=255,"
+ testUri.run("ESAllKey(PropertyString='O''Neil',PropertyBoolean=true,PropertyByte=255,"
+ "PropertySByte=-128,PropertyInt16=-32768,PropertyInt32=-2147483648,"
+ "PropertyInt64=-9223372036854775808,PropertyDecimal=1,PropertyDate=2013-09-25,"
+ "PropertyDateTimeOffset=2002-10-10T12:00:00-05:00,"
+ "PropertyDuration=duration'P50903316DT2H25M4S',"
+ "PropertyGuid=12345678-1234-1234-1234-123456789012,"
- + "PropertyTimeOfDay=12:34:55)"))
+ + "PropertyTimeOfDay=12:34:55)")
.isKind(UriInfoKind.resource).goPath()
.first()
.isEntitySet("ESAllKey")
@@ -1380,12 +1362,11 @@ public class TestFullResourcePath {
.isType(EntityTypeProvider.nameETTwoPrim)
.isTypeFilterOnCollection(EntityTypeProvider.nameETTwoBase);
- // TODO: Keys cannot be specified twice.
- //testUri.runEx("ESTwoPrim(1)/olingo.odata.test1.ETBase(1)")
- // .isExSemantic(MessageKeys.INCOMPATIBLE_TYPE_FILTER);
-
- //testUri.runEx("ESTwoPrim/olingo.odata.test1.ETBase(1)/olingo.odata.test1.ETTwoBase(1)")
- // .isExSemantic(MessageKeys.TYPE_FILTER_NOT_CHAINABLE);
+ // Keys cannot be specified twice.
+ testUri.runEx("ESTwoPrim(1)/olingo.odata.test1.ETBase(1)")
+ .isExSemantic(MessageKeys.KEY_NOT_ALLOWED);
+ testUri.runEx("ESTwoPrim/olingo.odata.test1.ETBase(1)/olingo.odata.test1.ETTwoBase(1)")
+ .isExSemantic(MessageKeys.KEY_NOT_ALLOWED);
testUri.runEx("ESBase/olingo.odata.test1.ETTwoPrim(1)").isExSemantic(MessageKeys.INCOMPATIBLE_TYPE_FILTER);
}
@@ -2321,8 +2302,7 @@ public class TestFullResourcePath {
}
@Test
- public void runExpand() throws Exception {
-
+ public void expandStar() throws Exception {
testUri.run("ESKeyNav(1)", "$expand=*")
.isKind(UriInfoKind.resource).goPath().goExpand()
.first()
@@ -2353,7 +2333,10 @@ public class TestFullResourcePath {
.first()
.isSegmentStar()
.isLevelText("max");
+ }
+ @Test
+ public void expandNavigationRef() throws Exception {
testUri.run("ESKeyNav(1)", "$expand=NavPropertyETKeyNavMany/$ref")
.isKind(UriInfoKind.resource).goPath().goExpand()
.first()
@@ -2441,7 +2424,10 @@ public class TestFullResourcePath {
.goUpExpandValidator()
.isSkipText("1")
.isTopText("3");
+ }
+ @Test
+ public void expandNavigationCount() throws Exception {
testUri.run("ESKeyNav(1)", "$expand=NavPropertyETKeyNavMany/$count")
.isKind(UriInfoKind.resource).goPath().goExpand()
.first()
@@ -2467,7 +2453,10 @@ public class TestFullResourcePath {
.n().isCount()
.goUpExpandValidator()
.isFilterSerialized("<<PropertyInt16> gt <1>>");
+ }
+ @Test
+ public void expandNavigationOptions() throws Exception {
testUri.run("ESKeyNav(1)", "$expand=NavPropertyETKeyNavMany($filter=PropertyInt16 eq 1)")
.isKind(UriInfoKind.resource).goPath().goExpand()
.first()
@@ -2521,7 +2510,6 @@ public class TestFullResourcePath {
.isNavProperty("NavPropertyETKeyNavMany", EntityTypeProvider.nameETKeyNav, true)
.isType(EntityTypeProvider.nameETKeyNav, true)
.goUpExpandValidator()
- .isSelectText("PropertyString")
.goSelectItem(0).isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false);
testUri.run("ESKeyNav(1)", "$expand=NavPropertyETKeyNavMany($expand=NavPropertyETTwoKeyNavOne)")
@@ -2562,7 +2550,6 @@ public class TestFullResourcePath {
.isNavProperty("NavPropertyETKeyNavMany", EntityTypeProvider.nameETKeyNav, true)
.isType(EntityTypeProvider.nameETKeyNav, true)
.goUpExpandValidator()
- .isSelectText("PropertyString")
.goSelectItem(0).isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false);
testUri.run("ESKeyNav(1)", "$expand=NavPropertyETKeyNavOne($levels=max)")
@@ -2594,6 +2581,12 @@ public class TestFullResourcePath {
.isSkipText("1")
.isTopText("2");
+ testUri.run("ESKeyNav(1)", "$expand=NavPropertyETKeyNavMany($search=Country AND Western)")
+ .isKind(UriInfoKind.resource).goPath().goExpand()
+ .first().goPath().first().isNavProperty("NavPropertyETKeyNavMany", EntityTypeProvider.nameETKeyNav, true)
+ .goUpExpandValidator()
+ .isSearchSerialized("{'Country' AND 'Western'}");
+
testUri.run("ESTwoKeyNav(PropertyInt16=1,PropertyString='Hugo')", "$expand=NavPropertyETKeyNavMany")
.isKind(UriInfoKind.resource).goPath()
.first()
@@ -2604,7 +2597,10 @@ public class TestFullResourcePath {
.goPath().first()
.isNavProperty("NavPropertyETKeyNavMany", EntityTypeProvider.nameETKeyNav, true)
.isType(EntityTypeProvider.nameETKeyNav, true);
+ }
+ @Test
+ public void expandTypeCasts() throws Exception {
testUri.run("ESTwoKeyNav", "$expand=olingo.odata.test1.ETBaseTwoKeyNav/NavPropertyETKeyNavMany")
.isKind(UriInfoKind.resource).goPath().first()
.goExpand().first()
@@ -2635,15 +2631,13 @@ public class TestFullResourcePath {
.isNavProperty("NavPropertyETTwoKeyNavMany", EntityTypeProvider.nameETTwoKeyNav, true);
testUri.run("ESTwoKeyNav(PropertyInt16=1,PropertyString='2')",
- "$expand=olingo.odata.test1.ETBaseTwoKeyNav"
- + "/NavPropertyETTwoKeyNavMany/olingo.odata.test1.ETTwoBaseTwoKeyNav")
+ "$expand=olingo.odata.test1.ETBaseTwoKeyNav/NavPropertyETTwoKeyNavMany/olingo.odata.test1.ETTwoBaseTwoKeyNav")
.isKind(UriInfoKind.resource).goPath().first()
.isKeyPredicate(0, "PropertyInt16", "1")
.isKeyPredicate(1, "PropertyString", "'2'")
.goExpand().first()
.isExpandStartType(EntityTypeProvider.nameETBaseTwoKeyNav)
.goPath().first()
- .isType(EntityTypeProvider.nameETTwoKeyNav)
.isNavProperty("NavPropertyETTwoKeyNavMany", EntityTypeProvider.nameETTwoKeyNav, true)
.isTypeFilterOnCollection(EntityTypeProvider.nameETTwoBaseTwoKeyNav);
@@ -2724,7 +2718,6 @@ public class TestFullResourcePath {
.isNavProperty("NavPropertyETKeyNavOne", EntityTypeProvider.nameETKeyNav, false)
.isType(EntityTypeProvider.nameETKeyNav)
.goUpExpandValidator()
- .isSelectText("PropertyInt16")
.goSelectItem(0).isPrimitiveProperty("PropertyInt16", PropertyProvider.nameInt16, false);
testUri.run("ESKeyNav", "$expand=NavPropertyETKeyNavOne($select=PropertyCompNav/PropertyInt16)")
@@ -2735,7 +2728,9 @@ public class TestFullResourcePath {
.isNavProperty("NavPropertyETKeyNavOne", EntityTypeProvider.nameETKeyNav, false)
.isType(EntityTypeProvider.nameETKeyNav)
.goUpExpandValidator()
- .isSelectText("PropertyCompNav/PropertyInt16");
+ .goSelectItem(0)
+ .first().isComplexProperty("PropertyCompNav", ComplexTypeProvider.nameCTNavFiveProp, false)
+ .n().isPrimitiveProperty("PropertyInt16", PropertyProvider.nameInt16, false);
testUri.runEx("ESKeyNav", "$expand=undefined")
.isExSemantic(MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE);
@@ -2744,7 +2739,7 @@ public class TestFullResourcePath {
}
@Test
- public void runDuplicatedSystemQueryOptionsInExpand() throws UriParserException, UriValidationException {
+ public void duplicatedSystemQueryOptionsInExpand() throws Exception {
testUri.runEx("ESKeyNav", "$expand=NavPropertyETKeyNavOne($select=PropertyInt16;$select=PropertyInt16)")
.isExSyntax(UriParserSyntaxException.MessageKeys.DOUBLE_SYSTEM_QUERY_OPTION);
@@ -2768,11 +2763,7 @@ public class TestFullResourcePath {
testUri.runEx("ESKeyNav", "$expand=NavPropertyETKeyNavOne($skip=2;$skip=2)")
.isExSyntax(UriParserSyntaxException.MessageKeys.DOUBLE_SYSTEM_QUERY_OPTION);
- }
- @Test
- @Ignore("$search in expand currently not implemented")
- public void duplicatedSearchExpand() throws Exception {
testUri.runEx("ESKeyNav", "$expand=NavPropertyETKeyNavOne($search=Test;$search=Test)")
.isExSyntax(UriParserSyntaxException.MessageKeys.DOUBLE_SYSTEM_QUERY_OPTION);
}
@@ -2906,8 +2897,7 @@ public class TestFullResourcePath {
}
@Test
- public void runTop() throws Exception {
- // top
+ public void top() throws Exception {
testUri.run("ESKeyNav", "$top=1")
.isKind(UriInfoKind.resource).goPath()
.isEntitySet("ESKeyNav")
@@ -2918,20 +2908,16 @@ public class TestFullResourcePath {
.isEntitySet("ESKeyNav")
.isTopText("0");
- testUri.run("ESKeyNav", "$top=-3")
- .isKind(UriInfoKind.resource).goPath()
- .isEntitySet("ESKeyNav")
- .isTopText("-3");
-
testUri.runEx("ESKeyNav", "$top=undefined")
.isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
testUri.runEx("ESKeyNav", "$top=")
.isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
+ testUri.runEx("ESKeyNav", "$top=-3")
+ .isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
}
@Test
- public void runFormat() throws Exception {
- // format
+ public void format() throws Exception {
testUri.run("ESKeyNav(1)", "$format=atom")
.isKind(UriInfoKind.resource).goPath()
.isFormatText("atom");
@@ -2963,8 +2949,7 @@ public class TestFullResourcePath {
}
@Test
- public void runCount() throws Exception {
- // count
+ public void count() throws Exception {
testUri.run("ESAllPrim", "$count=true")
.isKind(UriInfoKind.resource).goPath()
.isInlineCountText("true");
@@ -2979,20 +2964,19 @@ public class TestFullResourcePath {
@Test
public void skip() throws Exception {
- // skip
testUri.run("ESAllPrim", "$skip=3")
.isKind(UriInfoKind.resource).goPath()
.isSkipText("3");
testUri.run("ESAllPrim", "$skip=0")
.isKind(UriInfoKind.resource).goPath()
.isSkipText("0");
- testUri.run("ESAllPrim", "$skip=-3")
- .isKind(UriInfoKind.resource).goPath()
- .isSkipText("-3");
+
testUri.runEx("ESAllPrim", "$skip=F")
.isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
testUri.runEx("ESAllPrim", "$skip=")
.isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
+ testUri.runEx("ESAllPrim", "$skip=-3")
+ .isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
}
@Test
@@ -3000,6 +2984,9 @@ public class TestFullResourcePath {
testUri.run("ESAllPrim", "$skiptoken=foo")
.isKind(UriInfoKind.resource).goPath()
.isSkipTokenText("foo");
+
+ testUri.runEx("ESAllPrim", "$skiptoken=")
+ .isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
}
@Test
@@ -3010,7 +2997,6 @@ public class TestFullResourcePath {
@Test
public void misc() throws Exception {
-
testUri.run("")
.isKind(UriInfoKind.service);
testUri.run("/")
@@ -3227,56 +3213,47 @@ public class TestFullResourcePath {
.isType(EntityTypeProvider.nameETTwoKeyNav)
.isTypeFilterOnEntry(EntityTypeProvider.nameETBaseTwoKeyNav)
.n().isValue();
-
}
- // TODO
@Test
public void filter() throws Exception {
+ testFilter.runOnETAllPrim("PropertyBoolean")
+ .is("<PropertyBoolean>")
+ .isType(PropertyProvider.nameBoolean);
- testFilter.runOnETTwoKeyNav("PropertyString")
- .is("<PropertyString>")
- .isType(PropertyProvider.nameString);
-
- testFilter.runOnETTwoKeyNav("PropertyComp/PropertyInt16")
- .is("<PropertyComp/PropertyInt16>")
- .isType(PropertyProvider.nameInt16);
+ testFilter.runOnETTwoKeyNav("PropertyComp/PropertyInt16 gt 0")
+ .is("<<PropertyComp/PropertyInt16> gt <0>>")
+ .left().isType(PropertyProvider.nameInt16);
- testFilter.runOnETTwoKeyNav("PropertyComp/PropertyComp/PropertyDate")
- .is("<PropertyComp/PropertyComp/PropertyDate>")
- .isType(PropertyProvider.nameDate);
+ testFilter.runOnETTwoKeyNav("PropertyComp/PropertyComp/PropertyDate ne null")
+ .is("<<PropertyComp/PropertyComp/PropertyDate> ne <null>>")
+ .left().isType(PropertyProvider.nameDate);
- testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne")
- .is("<NavPropertyETTwoKeyNavOne>")
- .isType(EntityTypeProvider.nameETTwoKeyNav);
+ testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne eq null")
+ .is("<<NavPropertyETTwoKeyNavOne> eq <null>>")
+ .left().isType(EntityTypeProvider.nameETTwoKeyNav);
- testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne/PropertyString")
- .is("<NavPropertyETTwoKeyNavOne/PropertyString>")
- .isType(PropertyProvider.nameString);
-
- testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne/PropertyComp")
- .is("<NavPropertyETTwoKeyNavOne/PropertyComp>")
- .isType(ComplexTypeProvider.nameCTPrimComp);
+ testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne/PropertyString eq ''")
+ .is("<<NavPropertyETTwoKeyNavOne/PropertyString> eq <''>>")
+ .left().isType(PropertyProvider.nameString);
- testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne/PropertyComp/PropertyComp")
- .is("<NavPropertyETTwoKeyNavOne/PropertyComp/PropertyComp>")
- .isType(ComplexTypeProvider.nameCTAllPrim);
+ testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne/PropertyComp eq null")
+ .is("<<NavPropertyETTwoKeyNavOne/PropertyComp> eq <null>>")
+ .left().isType(ComplexTypeProvider.nameCTPrimComp);
- testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne/PropertyComp/PropertyInt16")
- .is("<NavPropertyETTwoKeyNavOne/PropertyComp/PropertyInt16>")
- .isType(PropertyProvider.nameInt16);
+ 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>>")
- .root().left()
- .isType(PropertyProvider.nameInt16)
- .root().right()
- .isLiteral("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'>>")
- .root().left()
+ .left()
.isType(PropertyProvider.nameString)
.isMember().goPath()
.first()
@@ -3293,7 +3270,7 @@ public class TestFullResourcePath {
testFilter.runOnETTwoKeyNav("olingo.odata.test1.ETBaseTwoKeyNav/PropertyDate eq 2013-11-12")
.is("<<PropertyDate> eq <2013-11-12>>")
- .root().left()
+ .left()
.isType(PropertyProvider.nameDate)
.isMember().isMemberStartType(EntityTypeProvider.nameETBaseTwoKeyNav).goPath()
.first().isPrimitiveProperty("PropertyDate", PropertyProvider.nameDate, false)
@@ -3303,7 +3280,7 @@ public class TestFullResourcePath {
testFilter.runOnCTTwoPrim("olingo.odata.test1.CTBase/AdditionalPropString eq 'SomeString'")
.is("<<AdditionalPropString> eq <'SomeString'>>")
- .root().left()
+ .left()
.isType(PropertyProvider.nameString)
.isMember().isMemberStartType(ComplexTypeProvider.nameCTBase).goPath()
.first().isPrimitiveProperty("AdditionalPropString", PropertyProvider.nameString, false)
@@ -3314,7 +3291,7 @@ public class TestFullResourcePath {
testFilter
.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne/olingo.odata.test1.ETBaseTwoKeyNav/PropertyDate eq 2013-11-12")
.is("<<NavPropertyETTwoKeyNavOne/olingo.odata.test1.ETBaseTwoKeyNav/PropertyDate> eq <2013-11-12>>")
- .root().left()
+ .left()
.isType(PropertyProvider.nameDate)
.root().right()
.isLiteral("2013-11-12");
@@ -3322,20 +3299,15 @@ public class TestFullResourcePath {
testFilter
.runOnETTwoKeyNav("PropertyCompTwoPrim/olingo.odata.test1.CTTwoBase/AdditionalPropString eq 'SomeString'")
.is("<<PropertyCompTwoPrim/olingo.odata.test1.CTTwoBase/AdditionalPropString> eq <'SomeString'>>")
- .root().left()
+ .left()
.isType(PropertyProvider.nameString)
.root().right()
.isLiteral("'SomeString'");
- testFilter.runOnETTwoKeyNavEx("invalid")
- .isExSemantic(MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE);
- // TODO: This should throw an exception because the top node of the filter tree must be boolean.
- // testFilter.runOnETTwoKeyNavEx("PropertyComp")
- // .isExSemantic(MessageKeys.UNKNOWN_TYPE);
- testFilter.runOnETTwoKeyNavEx("PropertyComp/invalid")
- .isExSemantic(MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE);
- testFilter.runOnETTwoKeyNavEx("concat('a','b')/invalid")
- .isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
+ 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("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'")
@@ -3347,437 +3319,307 @@ public class TestFullResourcePath {
testFilter.runOnETTwoKeyNavEx("PropertyComp/PropertyInt64 eq 1")
.isExSemantic(MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE);
testFilter.runOnETTwoKeyNavEx("NavPropertyETKeyNavMany/PropertyInt16 gt 42")
- .isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
+ .isExSemantic(MessageKeys.TYPES_NOT_COMPATIBLE);
testFilter.runOnETTwoKeyNavEx("NavPropertyETKeyNavMany/NavPropertyETTwoKeyNavOne eq null")
- .isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
+ .isExSemantic(MessageKeys.TYPES_NOT_COMPATIBLE);
+ }
+ @Test
+ public void filterBinaryOperators() throws Exception {
testFilter.runOnETAllPrim("PropertySByte eq PropertySByte")
.is("<<PropertySByte> eq <PropertySByte>>")
.isBinary(BinaryOperatorKind.EQ)
- .root().left()
- .isType(PropertyProvider.nameSByte)
- .root().right()
- .isType(PropertyProvider.nameSByte);
+ .left().isType(PropertyProvider.nameSByte)
+ .root().right().isType(PropertyProvider.nameSByte);
testFilter.runOnETAllPrim("PropertySByte ne PropertySByte")
.is("<<PropertySByte> ne <PropertySByte>>")
.isBinary(BinaryOperatorKind.NE)
- .root().left()
- .isType(PropertyProvider.nameSByte)
- .root().right()
- .isType(PropertyProvider.nameSByte);
-
- testFilter.runOnETAllPrim("PropertySByte add PropertySByte")
- .is("<<PropertySByte> add <PropertySByte>>")
- .root().left()
- .isType(PropertyProvider.nameSByte)
- .root().right()
- .isType(PropertyProvider.nameSByte);
-
- testFilter.runOnETAllPrim("PropertyByte add PropertyByte")
- .is("<<PropertyByte> add <PropertyByte>>")
- .root().left()
- .isType(PropertyProvider.nameByte)
- .root().right()
- .isType(PropertyProvider.nameByte);
- testFilter.runOnETAllPrim("PropertyInt16 add PropertyInt16")
- .is("<<PropertyInt16> add <PropertyInt16>>")
- .root().left()
- .isType(PropertyProvider.nameInt16)
- .root().right()
- .isType(PropertyProvider.nameInt16);
- testFilter.runOnETAllPrim("PropertyInt32 add PropertyInt32")
- .is("<<PropertyInt32> add <PropertyInt32>>")
- .root().left()
- .isType(PropertyProvider.nameInt32)
- .root().right()
- .isType(PropertyProvider.nameInt32);
-
- testFilter.runOnETAllPrim("PropertyInt64 add PropertyInt64")
- .is("<<PropertyInt64> add <PropertyInt64>>")
- .root().left()
- .isType(PropertyProvider.nameInt64)
- .root().right()
- .isType(PropertyProvider.nameInt64);
- testFilter.runOnETAllPrim("PropertySingle add PropertySingle")
- .is("<<PropertySingle> add <PropertySingle>>")
- .root().left()
- .isType(PropertyProvider.nameSingle)
- .root().right()
- .isType(PropertyProvider.nameSingle);
- testFilter.runOnETAllPrim("PropertyDouble add PropertyDouble")
- .is("<<PropertyDouble> add <PropertyDouble>>")
- .root().left()
- .isType(PropertyProvider.nameDouble)
- .root().right()
- .isType(PropertyProvider.nameDouble);
- testFilter.runOnETAllPrim("PropertyDecimal add PropertyDecimal")
- .is("<<PropertyDecimal> add <PropertyDecimal>>")
- .root().left()
- .isType(PropertyProvider.nameDecimal)
- .root().right()
- .isType(PropertyProvider.nameDecimal);
- testFilter.runOnETAllPrim("PropertySByte add PropertyDecimal")
- .is("<<PropertySByte> add <PropertyDecimal>>")
- .root().left()
- .isType(PropertyProvider.nameSByte)
- .root().right()
- .isType(PropertyProvider.nameDecimal);
- testFilter.runOnETAllPrim("PropertySByte add PropertyInt32")
- .is("<<PropertySByte> add <PropertyInt32>>")
- .root().left()
- .isType(PropertyProvider.nameSByte)
- .root().right()
- .isType(PropertyProvider.nameInt32);
- testFilter.runOnETAllPrim("PropertySByte add PropertyInt64")
- .is("<<PropertySByte> add <PropertyInt64>>")
- .root().left()
- .isType(PropertyProvider.nameSByte)
- .root().right()
- .isType(PropertyProvider.nameInt64);
- testFilter.runOnETAllPrim("PropertyDateTimeOffset add PropertyDuration")
- .is("<<PropertyDateTimeOffset> add <PropertyDuration>>")
- .root().left()
- .isType(PropertyProvider.nameDateTimeOffset)
- .root().right()
- .isType(PropertyProvider.nameDuration);
- testFilter.runOnETAllPrim("PropertyDuration add PropertyDuration")
- .is("<<PropertyDuration> add <PropertyDuration>>")
- .root().left()
- .isType(PropertyProvider.nameDuration)
- .root().right()
- .isType(PropertyProvider.nameDuration);
- testFilter.runOnETAllPrim("PropertyDate add PropertyDuration")
- .is("<<PropertyDate> add <PropertyDuration>>")
- .root().left()
- .isType(PropertyProvider.nameDate)
- .root().right()
- .isType(PropertyProvider.nameDuration);
- testFilter.runOnETAllPrim("PropertySByte sub PropertySByte")
- .is("<<PropertySByte> sub <PropertySByte>>")
- .root().left()
- .isType(PropertyProvider.nameSByte)
- .root().right()
- .isType(PropertyProvider.nameSByte);
- testFilter.runOnETAllPrim("PropertyByte sub PropertyByte")
- .is("<<PropertyByte> sub <PropertyByte>>")
- .root().left()
- .isType(PropertyProvider.nameByte)
- .root().right()
- .isType(PropertyProvider.nameByte);
- testFilter.runOnETAllPrim("PropertyInt16 sub PropertyInt16")
- .is("<<PropertyInt16> sub <PropertyInt16>>")
- .root().left()
- .isType(PropertyProvider.nameInt16)
- .root().right()
- .isType(PropertyProvider.nameInt16);
- testFilter.runOnETAllPrim("PropertyInt32 sub PropertyInt32")
- .is("<<PropertyInt32> sub <PropertyInt32>>")
- .root().left()
- .isType(PropertyProvider.nameInt32)
- .root().right()
- .isType(PropertyProvider.nameInt32);
- testFilter.runOnETAllPrim("PropertyInt64 sub PropertyInt64")
- .is("<<PropertyInt64> sub <PropertyInt64>>")
- .root().left()
- .isType(PropertyProvider.nameInt64)
- .root().right()
- .isType(PropertyProvider.nameInt64);
- testFilter.runOnETAllPrim("PropertySingle sub PropertySingle")
- .is("<<PropertySingle> sub <PropertySingle>>")
- .root().left()
- .isType(PropertyProvider.nameSingle)
- .root().right()
- .isType(PropertyProvider.nameSingle);
- testFilter.runOnETAllPrim("PropertyDouble sub PropertyDouble")
- .is("<<PropertyDouble> sub <PropertyDouble>>")
- .root().left()
- .isType(PropertyProvider.nameDouble)
- .root().right()
- .isType(PropertyProvider.nameDouble);
- testFilter.runOnETAllPrim("PropertyDecimal sub PropertyDecimal")
- .is("<<PropertyDecimal> sub <PropertyDecimal>>")
- .root().left()
- .isType(PropertyProvider.nameDecimal)
- .root().right()
- .isType(PropertyProvider.nameDecimal);
- testFilter.runOnETAllPrim("PropertyDecimal sub PropertyInt32")
- .is("<<PropertyDecimal> sub <PropertyInt32>>")
- .root().left()
- .isType(PropertyProvider.nameDecimal)
- .root().right()
- .isType(PropertyProvider.nameInt32);
- testFilter.runOnETAllPrim("PropertyDecimal sub PropertyInt64")
- .is("<<PropertyDecimal> sub <PropertyInt64>>")
- .root().left()
- .isType(PropertyProvider.nameDecimal)
- .root().right()
- .isType(PropertyProvider.nameInt64);
- testFilter.runOnETAllPrim("PropertyDecimal sub PropertyByte")
- .is("<<PropertyDecimal> sub <PropertyByte>>")
- .root().left()
- .isType(PropertyProvider.nameDecimal)
- .root().right()
- .isType(PropertyProvider.nameByte);
- testFilter.runOnETAllPrim("PropertyDateTimeOffset sub PropertyDuration")
- .is("<<PropertyDateTimeOffset> sub <PropertyDuration>>")
- .root().left()
- .isType(PropertyProvider.nameDateTimeOffset)
- .root().right()
- .isType(PropertyProvider.nameDuration);
- testFilter.runOnETAllPrim("PropertyDuration sub PropertyDuration")
- .is("<<PropertyDuration> sub <PropertyDuration>>")
- .root().left()
- .isType(PropertyProvider.nameDuration)
- .root().right()
- .isType(PropertyProvider.nameDuration);
- testFilter.runOnETAllPrim("PropertyDateTimeOffset sub PropertyDateTimeOffset")
- .is("<<PropertyDateTimeOffset> sub <PropertyDateTimeOffset>>")
- .root().left()
- .isType(PropertyProvider.nameDateTimeOffset)
- .root().right()
- .isType(PropertyProvider.nameDateTimeOffset);
- testFilter.runOnETAllPrim("PropertyDate sub PropertyDuration")
- .is("<<PropertyDate> sub <PropertyDuration>>")
- .root().left()
- .isType(PropertyProvider.nameDate)
- .root().right()
- .isType(PropertyProvider.nameDuration);
- testFilter.runOnETAllPrim("PropertyDate sub PropertyDate")
- .is("<<PropertyDate> sub <PropertyDate>>")
- .root().left()
- .isType(PropertyProvider.nameDate)
- .root().right()
- .isType(PropertyProvider.nameDate);
- testFilter.runOnETAllPrim("PropertySByte mul PropertySByte")
- .is("<<PropertySByte> mul <PropertySByte>>")
- .root().left()
- .isType(PropertyProvider.nameSByte)
- .root().right()
- .isType(PropertyProvider.nameSByte);
- testFilter.runOnETAllPrim("PropertyByte mul PropertyByte")
- .is("<<PropertyByte> mul <PropertyByte>>")
- .root().left()
- .isType(PropertyProvider.nameByte)
- .root().right()
- .isType(PropertyProvider.nameByte);
- testFilter.runOnETAllPrim("PropertyInt16 mul PropertyInt16")
- .is("<<PropertyInt16> mul <PropertyInt16>>")
- .root().left()
- .isType(PropertyProvider.nameInt16)
- .root().right()
- .isType(PropertyProvider.nameInt16);
- testFilter.runOnETAllPrim("PropertyInt32 mul PropertyInt32")
- .is("<<PropertyInt32> mul <PropertyInt32>>")
- .root().left()
- .isType(PropertyProvider.nameInt32)
- .root().right()
- .isType(PropertyProvider.nameInt32);
- testFilter.runOnETAllPrim("PropertyInt64 mul PropertyInt64")
- .is("<<PropertyInt64> mul <PropertyInt64>>")
- .root().left()
- .isType(PropertyProvider.nameInt64)
- .root().right()
- .isType(PropertyProvider.nameInt64);
- testFilter.runOnETAllPrim("PropertySingle mul PropertySingle")
- .is("<<PropertySingle> mul <PropertySingle>>")
- .root().left()
- .isType(PropertyProvider.nameSingle)
- .root().right()
- .isType(PropertyProvider.nameSingle);
- testFilter.runOnETAllPrim("PropertyDouble mul PropertyDouble")
- .is("<<PropertyDouble> mul <PropertyDouble>>")
- .root().left()
- .isType(PropertyProvider.nameDouble)
- .root().right()
- .isType(PropertyProvider.nameDouble);
- testFilter.runOnETAllPrim("PropertyDecimal mul PropertyDecimal")
- .is("<<PropertyDecimal> mul <PropertyDecimal>>")
- .root().left()
- .isType(PropertyProvider.nameDecimal)
- .root().right()
- .isType(PropertyProvider.nameDecimal);
- testFilter.runOnETAllPrim("PropertyInt64 mul PropertyInt32")
- .is("<<PropertyInt64> mul <PropertyInt32>>")
- .root().left()
- .isType(PropertyProvider.nameInt64)
- .root().right()
- .isType(PropertyProvider.nameInt32);
- testFilter.runOnETAllPrim("PropertyInt64 mul PropertySByte")
- .is("<<PropertyInt64> mul <PropertySByte>>")
- .root().left()
- .isType(PropertyProvider.nameInt64)
- .root().right()
- .isType(PropertyProvider.nameSByte);
- testFilter.runOnETAllPrim("PropertyInt64 mul PropertyDecimal")
- .is("<<PropertyInt64> mul <PropertyDecimal>>")
- .root().left()
- .isType(PropertyProvider.nameInt64)
- .root().right()
- .isType(PropertyProvider.nameDecimal);
- testFilter.runOnETAllPrim("PropertySByte div PropertySByte")
- .is("<<PropertySByte> div <PropertySByte>>")
- .root().left()
- .isType(PropertyProvider.nameSByte)
- .root().right()
- .isType(PropertyProvider.nameSByte);
- testFilter.runOnETAllPrim("PropertyByte div PropertyByte")
- .is("<<PropertyByte> div <PropertyByte>>")
- .root().left()
- .isType(PropertyProvider.nameByte)
- .root().right()
- .isType(PropertyProvider.nameByte);
- testFilter.runOnETAllPrim("PropertyInt16 div PropertyInt16")
- .is("<<PropertyInt16> div <PropertyInt16>>")
- .root().left()
- .isType(PropertyProvider.nameInt16)
- .root().right()
- .isType(PropertyProvider.nameInt16);
- testFilter.runOnETAllPrim("PropertyInt32 div PropertyInt32")
- .is("<<PropertyInt32> div <PropertyInt32>>")
- .root().left()
- .isType(PropertyProvider.nameInt32)
- .root().right()
- .isType(PropertyProvider.nameInt32);
- testFilter.runOnETAllPrim("PropertyInt64 div PropertyInt64")
- .is("<<PropertyInt64> div <PropertyInt64>>")
- .root().left()
- .isType(PropertyProvider.nameInt64)
- .root().right()
- .isType(PropertyProvider.nameInt64);
- testFilter.runOnETAllPrim("PropertySingle div PropertySingle")
- .is("<<PropertySingle> div <PropertySingle>>")
- .root().left()
- .isType(PropertyProvider.nameSingle)
- .root().right()
- .isType(PropertyProvider.nameSingle);
- testFilter.runOnETAllPrim("PropertyDouble div PropertyDouble")
- .is("<<PropertyDouble> div <PropertyDouble>>")
- .root().left()
- .isType(PropertyProvider.nameDouble)
- .root().right()
- .isType(PropertyProvider.nameDouble);
- testFilter.runOnETAllPrim("PropertyDecimal div PropertyDecimal")
- .is("<<PropertyDecimal> div <PropertyDecimal>>")
- .root().left()
- .isType(PropertyProvider.nameDecimal)
- .root().right()
- .isType(PropertyProvider.nameDecimal);
- testFilter.runOnETAllPrim("PropertyByte div PropertyInt32")
- .is("<<PropertyByte> div <PropertyInt32>>")
- .root().left()
- .isType(PropertyProvider.nameByte)
- .root().right()
- .isType(PropertyProvider.nameInt32);
- testFilter.runOnETAllPrim("PropertyByte div PropertyDecimal")
- .is("<<PropertyByte> div <PropertyDecimal>>")
- .root().left()
- .isType(PropertyProvider.nameByte)
- .root().right()
- .isType(PropertyProvider.nameDecimal);
- testFilter.runOnETAllPrim("PropertyByte div PropertySByte")
- .is("<<PropertyByte> div <PropertySByte>>")
- .root().left()
- .isType(PropertyProvider.nameByte)
- .root().right()
- .isType(PropertyProvider.nameSByte);
-
- testFilter.runOnETAllPrim("PropertyByte div 0")
- .is("<<PropertyByte> div <0>>");
-
- testFilter.runOnETAllPrim("0 div 0")
- .is("<<0> div <0>>");
-
- testFilter.runOnETAllPrim("PropertySByte mod PropertySByte")
- .is("<<PropertySByte> mod <PropertySByte>>")
- .root().left()
- .isType(PropertyProvider.nameSByte)
- .root().right()
- .isType(PropertyProvider.nameSByte);
- testFilter.runOnETAllPrim("PropertyByte mod PropertyByte")
- .is("<<PropertyByte> mod <PropertyByte>>")
- .root().left()
- .isType(PropertyProvider.nameByte)
- .root().right()
- .isType(PropertyProvider.nameByte);
- testFilter.runOnETAllPrim("PropertyInt16 mod PropertyInt16")
- .is("<<PropertyInt16> mod <PropertyInt16>>")
- .root().left()
- .isType(PropertyProvider.nameInt16)
- .root().right()
- .isType(PropertyProvider.nameInt16);
- testFilter.runOnETAllPrim("PropertyInt32 mod PropertyInt32")
- .is("<<PropertyInt32> mod <PropertyInt32>>")
- .root().left()
- .isType(PropertyProvider.nameInt32)
- .root().right()
- .isType(PropertyProvider.nameInt32);
- testFilter.runOnETAllPrim("PropertyInt64 mod PropertyInt64")
- .is("<<PropertyInt64> mod <PropertyInt64>>")
- .root().left()
- .isType(PropertyProvider.nameInt64)
- .root().right()
- .isType(PropertyProvider.nameInt64);
- testFilter.runOnETAllPrim("PropertySingle mod PropertySingle")
- .is("<<PropertySingle> mod <PropertySingle>>")
- .root().left()
- .isType(PropertyProvider.nameSingle)
- .root().right()
- .isType(PropertyProvider.nameSingle);
- testFilter.runOnETAllPrim("PropertyDouble mod PropertyDouble")
- .is("<<PropertyDouble> mod <PropertyDouble>>")
- .root().left()
- .isType(PropertyProvider.nameDouble)
- .root().right()
- .isType(PropertyProvider.nameDouble);
- testFilter.runOnETAllPrim("PropertyDecimal mod PropertyDecimal")
- .is("<<PropertyDecimal> mod <PropertyDecimal>>")
- .root().left()
- .isType(PropertyProvider.nameDecimal)
- .root().right()
- .isType(PropertyProvider.nameDecimal);
+ .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)
- .root().left()
- .isType(PropertyProvider.nameDecimal)
- .root().right()
- .isType(PropertyProvider.nameDecimal);
+ .left().isType(PropertyProvider.nameDecimal)
+ .root().right().isType(PropertyProvider.nameDecimal);
testFilter.runOnETAllPrim("PropertyDecimal lt PropertyDecimal")
.is("<<PropertyDecimal> lt <PropertyDecimal>>")
.isBinary(BinaryOperatorKind.LT)
- .root().left()
- .isType(PropertyProvider.nameDecimal)
- .root().right()
- .isType(PropertyProvider.nameDecimal);
+ .left().isType(PropertyProvider.nameDecimal)
+ .root().right().isType(PropertyProvider.nameDecimal);
testFilter.runOnETAllPrim("PropertyDecimal le PropertyDecimal")
.is("<<PropertyDecimal> le <PropertyDecimal>>")
.isBinary(BinaryOperatorKind.LE)
- .root().left()
- .isType(PropertyProvider.nameDecimal)
- .root().right()
- .isType(PropertyProvider.nameDecimal);
+ .left().isType(PropertyProvider.nameDecimal)
+ .root().right().isType(PropertyProvider.nameDecimal);
- // Numeric promotion: Double is considered the widest type
- testFilter.runOnETAllPrim("PropertyDecimal sub NaN")
+ // Numeric promotion: Double is considered the widest type.
+ testFilter.runOnETAllPrim("PropertyDecimal ne NaN")
.right().isLiteral("NaN").isType(PropertyProvider.nameDouble);
- testFilter.runOnETAllPrim("PropertyDecimal sub -INF")
+ testFilter.runOnETAllPrim("PropertyDecimal gt -INF")
.right().isLiteral("-INF").isType(PropertyProvider.nameDouble);
- testFilter.runOnETAllPrim("PropertyDecimal sub INF")
+ testFilter.runOnETAllPrim("PropertyDecimal lt INF")
.right().isLiteral("INF").isType(PropertyProvider.nameDouble);
}
- // TODO
@Test
- @Ignore
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().isTrue();
+ .root().right().isLiteral("true");
testFilter.runOnETAllPrim("PropertyDecimal eq 1.25")
.is("<<PropertyDecimal> eq <1.25>>")
@@ -3917,37 +3759,43 @@ public class TestFullResourcePath {
.first().isComplex("PropertyCompMixedEnumDef")
.n().isPrimitiveProperty("PropertyEnumString", EnumTypeProvider.nameENString, false);
- testFilter.runOnETAllPrim("PropertyByte mod 0")
- .is("<<PropertyByte> mod <0>>");
+ testFilter.runOnETAllPrim("PropertyByte mod 0 gt 0")
+ .is("<<<PropertyByte> mod <0>> gt <0>>");
+ }
- testFilter.runOnETAllPrim("olingo.odata.test1.UFCRTETTwoKeyNavParamCTTwoPrim(ParameterCTTwoPrim=@ParamAlias)")
- .is("<UFCRTETTwoKeyNavParamCTTwoPrim>")
- .goPath()
+ @Test
+ public void filterFunctions() throws Exception {
+ testFilter.runOnETAllPrim(
+ "olingo.odata.test1.UFCRTETTwoKeyNavParamCTTwoPrim(ParameterCTTwoPrim=@ParamAlias) eq null")
+ .is("<<UFCRTETTwoKeyNavParamCTTwoPrim> eq <null>>")
+ .left().goPath()
.first()
.isFunction("UFCRTETTwoKeyNavParamCTTwoPrim")
.isParameterAlias(0, "ParameterCTTwoPrim", "@ParamAlias");
- testFilter.runOnETTwoKeyNav("PropertyComp/olingo.odata.test1.BFCCTPrimCompRTESTwoKeyNavParam"
- + "(ParameterString=PropertyComp/PropertyComp/PropertyString)(PropertyInt16=1,PropertyString='2')"
- + "/PropertyString eq 'SomeString'")
- .is("<<PropertyComp/BFCCTPrimCompRTESTwoKeyNavParam/PropertyString> eq <'SomeString'>>")
+ 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("BFCCTPrimCompRTESTwoKeyNavParam")
- .isParameter(0, "ParameterString", "PropertyComp/PropertyComp/PropertyString")
- .goParameter(0)
- .isMember()
+ .first().isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false)
+ .n().isFunction("BFCCTPrimCompRTETTwoKeyNavParam")
+ .goParameter(0).isMember()
.goPath()
- .first().isComplex("PropertyComp")
- .n().isComplex("PropertyComp")
- .n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false).goUpFilterValidator()
- .goUpToResourceValidator()
+ .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);
+ .n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false);
testFilter.runOnETTwoKeyNav("PropertyComp/olingo.odata.test1.BFCCTPrimCompRTETTwoKeyNavParam"
+ "(ParameterString=null)/PropertyString eq 'SomeString'")
@@ -3957,9 +3805,7 @@ public class TestFullResourcePath {
.isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false)
.n()
.isFunction("BFCCTPrimCompRTETTwoKeyNavParam")
- .goParameter(0)
- .isNull()
- .goUpToResourceValidator()
+ .isParameter(0, "ParameterString", null)
.n()
.isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false);
@@ -3969,59 +3815,43 @@ public class TestFullResourcePath {
.root().left().goPath()
.first()
.isNavProperty("NavPropertyETTwoKeyNavMany", EntityTypeProvider.nameETTwoKeyNav, true)
- .n()
- .isFunction("BFCESTwoKeyNavRTString");
+ .n().isFunction("BFCESTwoKeyNavRTString");
- testFilter.runOnETTwoKeyNav("$it/olingo.odata.test1.BFESTwoKeyNavRTESTwoKeyNav()/PropertyString eq 'SomeString'")
- .is("<<$it/BFESTwoKeyNavRTESTwoKeyNav/PropertyString> eq <'SomeString'>>")
+ testFilter.runOnETKeyNav("$it/olingo.odata.test1.BFCETKeyNavRTETKeyNav()/PropertyString eq 'SomeString'")
+ .is("<<$it/BFCETKeyNavRTETKeyNav/PropertyString> eq <'SomeString'>>")
.root().left().goPath()
- .first()
- .isIt()
- .n()
- .isFunction("BFESTwoKeyNavRTESTwoKeyNav")
- .n()
- .isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false);
+ .first().isIt()
+ .n().isFunction("BFCETKeyNavRTETKeyNav")
+ .n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false);
- testFilter.runOnETTwoKeyNav("olingo.odata.test1.BFESTwoKeyNavRTESTwoKeyNav()/PropertyString eq 'SomeString'")
- .is("<<BFESTwoKeyNavRTESTwoKeyNav/PropertyString> eq <'SomeString'>>")
+ testFilter.runOnETTwoKeyNav("olingo.odata.test1.BFCESTwoKeyNavRTCTTwoPrim()/PropertyString eq 'SomeString'")
+ .is("<<BFCESTwoKeyNavRTCTTwoPrim/PropertyString> eq <'SomeString'>>")
.root().left().goPath()
- .first()
- .isFunction("BFESTwoKeyNavRTESTwoKeyNav")
- .n()
- .isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false);
+ .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);
+ .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.BFCCTPrimCompRTESTwoKeyNavParam"
- + "(ParameterString='1')"
- + "/olingo.odata.test1.ETBaseTwoKeyNav(PropertyInt16=2,PropertyString='3')"
- + "/PropertyString eq 'SomeString'")
- .is("<<PropertyComp/BFCCTPrimCompRTESTwoKeyNavParam/olingo.odata.test1.ETBaseTwoKeyNav/PropertyString> "
+ 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("BFCCTPrimCompRTESTwoKeyNavParam")
- .isTypeFilterOnCollection(EntityTypeProvider.nameETBaseTwoKeyNav)
+ .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);
+ .n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false);
testFilter.runOnETTwoKeyNavSingle("$it/olingo.odata.test1.BFCETTwoKeyNavRTCTTwoPrim()/olingo.odata.test1.CTBase"
+ "/PropertyString eq 'SomeString'")
@@ -4071,59 +3901,58 @@ public class TestFullResourcePath {
.root().left().goPath()
.first()
.isFunction("UFCRTETTwoKeyNavParam")
- .isParameter(0, "ParameterInt16", "PropertyInt16")
- .n()
- .isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false)
- .n()
- .isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTAllPrim, false)
- .n()
- .isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false);
+ .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);
}
@Test
public void methods() throws Exception {
testFilter.runOnETKeyNav("indexof(PropertyString,'47') eq 5")
.is("<<indexof(<PropertyString>,<'47'>)> eq <5>>")
- .root().left()
+ .left()
.isMethod(MethodKind.INDEXOF, 2)
.isParameterText(0, "<PropertyString>")
.isParameterText(1, "<'47'>");
testFilter.runOnETKeyNav("tolower(PropertyString) eq 'foo'")
.is("<<tolower(<PropertyString>)> eq <'foo'>>")
- .root().left()
+ .left()
.isMethod(MethodKind.TOLOWER, 1)
.isParameterText(0, "<PropertyString>");
testFilter.runOnETKeyNav("toupper(PropertyString) eq 'FOO'")
.is("<<toupper(<PropertyString>)> eq <'FOO'>>")
- .root().left()
+ .left()
.isMethod(MethodKind.TOUPPER, 1)
.isParameterText(0, "<PropertyString>");
testFilter.runOnETKeyNav("trim(PropertyString) eq 'fooba'")
.is("<<trim(<PropertyString>)> eq <'fooba'>>")
- .root().left()
+ .left()
.isMethod(MethodKind.TRIM, 1)
.isParameterText(0, "<PropertyString>");
testFilter.runOnETKeyNav("substring(PropertyString,4) eq 'foo'")
.is("<<substring(<PropertyString>,<4>)> eq <'foo'>>")
- .root().left()
+ .left()
.isMethod(MethodKind.SUBSTRING, 2)
.isParameterText(0, "<PropertyString>")
.isParameterText(1, "<4>");
testFilter.runOnETKeyNav("substring(PropertyString,4) eq 'foo'")
.is("<<substring(<PropertyString>,<4>)> eq <'foo'>>")
- .root().left()
+ .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'>>")
- .root().left()
+ .left()
.isMethod(MethodKind.SUBSTRING, 3)
.isParameterText(0, "<PropertyString>")
.isParameterText(1, "<2>")
@@ -4131,355 +3960,355 @@ public class TestFullResourcePath {
testFilter.runOnETKeyNav("concat(PropertyString,PropertyCompTwoPrim/PropertyString) eq 'foo'")
.is("<<concat(<PropertyString>,<PropertyCompTwoPrim/PropertyString>)> eq <'foo'>>")
- .root().left()
+ .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'>>")
- .root().left()
+ .left()
.isMethod(MethodKind.CONCAT, 2)
.isParameterText(0, "<PropertyString>")
.isParameterText(1, "<'bar'>");
testFilter.runOnETKeyNav("concat(PropertyString,'bar') eq 'foobar'")
.is("<<concat(<PropertyString>,<'bar'>)> eq <'foobar'>>")
- .root().left()
+ .left()
.isMethod(MethodKind.CONCAT, 2)
.isParameterText(0, "<PropertyString>")
.isParameterText(1, "<'bar'>");
testFilter.runOnETKeyNav("length(PropertyString) eq 32")
.is("<<length(<PropertyString>)> eq <32>>")
- .root().left()
+ .left()
.isMethod(MethodKind.LENGTH, 1)
.isParameterText(0, "<PropertyString>");
testFilter.runOnETAllPrim("year(PropertyDate) eq 2013")
.is("<<year(<PropertyDate>)> eq <2013>>")
- .root().left()
+ .left()
.isMethod(MethodKind.YEAR, 1)
.isParameterText(0, "<PropertyDate>");
testFilter.runOnETAllPrim("year(2013-09-25) eq 2013")
.is("<<year(<2013-09-25>)> eq <2013>>")
- .root().left()
+ .left()
.isMethod(MethodKind.YEAR, 1)
.isParameterText(0, "<2013-09-25>");
testFilter.runOnETAllPrim("year(PropertyDateTimeOffset) eq 2013")
.is("<<year(<PropertyDateTimeOffset>)> eq <2013>>")
- .root().left()
+ .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>>")
- .root().left()
+ .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>>")
- .root().left()
+ .left()
.isMethod(MethodKind.MONTH, 1)
.isParameterText(0, "<PropertyDate>");
testFilter.runOnETAllPrim("month(2013-09-25) eq 9")
.is("<<month(<2013-09-25>)> eq <9>>")
- .root().left()
+ .left()
.isMethod(MethodKind.MONTH, 1)
.isParameterText(0, "<2013-09-25>");
testFilter.runOnETAllPrim("month(PropertyDateTimeOffset) eq 9")
.is("<<month(<PropertyDateTimeOffset>)> eq <9>>")
- .root().left()
+ .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>>")
- .root().left()
+ .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>>")
- .root().left()
+ .left()
.isMethod(MethodKind.DAY, 1)
.isParameterText(0, "<PropertyDate>");
testFilter.runOnETAllPrim("day(2013-09-25) eq 25")
.is("<<day(<2013-09-25>)> eq <25>>")
- .root().left()
+ .left()
.isMethod(MethodKind.DAY, 1)
.isParameterText(0, "<2013-09-25>");
testFilter.runOnETAllPrim("day(PropertyDateTimeOffset) eq 25")
.is("<<day(<PropertyDateTimeOffset>)> eq <25>>")
- .root().left()
+ .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>>")
- .root().left()
+ .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>>")
- .root().left()
+ .left()
.isMethod(MethodKind.HOUR, 1)
.isParameterText(0, "<PropertyDateTimeOffset>");
testFilter.runOnETAllPrim("hour(PropertyDateTimeOffset) eq 2")
.is("<<hour(<PropertyDateTimeOffset>)> eq <2>>")
- .root().left()
+ .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>>")
- .root().left()
+ .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>>")
- .root().left()
+ .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>>")
- .root().left()
+ .left()
.isMethod(MethodKind.HOUR, 1)
.isParameterText(0, "<12:34:55.123456789012>");
testFilter.runOnETAllPrim("minute(PropertyDateTimeOffset) eq 34")
.is("<<minute(<PropertyDateTimeOffset>)> eq <34>>")
- .root().left()
+ .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>>")
- .root().left()
+ .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>>")
- .root().left()
+ .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>>")
- .root().left()
+ .left()
.isMethod(MethodKind.MINUTE, 1)
.isParameterText(0, "<12:34:55.123456789012>");
testFilter.runOnETAllPrim("second(PropertyDateTimeOffset) eq 56")
.is("<<second(<PropertyDateTimeOffset>)> eq <56>>")
- .root().left()
+ .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>>")
- .root().left()
+ .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>>")
- .root().left()
+ .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>>")
- .root().left()
+ .left()
.isMethod(MethodKind.SECOND, 1)
.isParameterText(0, "<12:34:55.123456789012>");
testFilter.runOnETAllPrim("fractionalseconds(PropertyDateTimeOffset) eq 123456789012")
.is("<<fractionalseconds(<PropertyDateTimeOffset>)> eq <123456789012>>")
- .root().left()
+ .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>>")
- .root().left()
+ .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>>")
- .root().left()
+ .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>>")
- .root().left()
+ .left()
.isMethod(MethodKind.FRACTIONALSECONDS, 1)
.isParameterText(0, "<12:34:55.123456789012>");
testFilter.runOnETAllPrim("totalseconds(PropertyDuration) eq 4711")
.is("<<totalseconds(<PropertyDuration>)> eq <4711>>")
- .root().left()
+ .left()
.isMethod(MethodKind.TOTALSECONDS, 1)
.isParameterText(0, "<PropertyDuration>");
testFilter.runOnETAllPrim("totalseconds(duration'P10DT5H34M21.123456789012S') eq 4711")
.is("<<totalseconds(<duration'P10DT5H34M21.123456789012S'>)> eq <4711>>")
- .root().left()
+ .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>>")
- .root().left()
+ .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>>")
- .root().left()
+ .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>>")
- .root().left()
+ .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>>")
- .root().left()
+ .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>>")
- .root().left()
+ .left()
.isMethod(MethodKind.ROUND, 1)
.isParameterText(0, "<PropertyDouble>");
testFilter.runOnETAllPrim("round(17.45e1) eq 17")
.is("<<round(<17.45e1>)> eq <17>>")
- .root().left()
+ .left()
.isMethod(MethodKind.ROUND, 1)
.isParameterText(0, "<17.45e1>");
testFilter.runOnETAllPrim("round(PropertyDecimal) eq 17")
.is("<<round(<PropertyDecimal>)> eq <17>>")
- .root().left()
+ .left()
.isMethod(MethodKind.ROUND, 1)
.isParameterText(0, "<PropertyDecimal>");
testFilter.runOnETAllPrim("round(17.45) eq 17")
.is("<<round(<17.45>)> eq <17>>")
- .root().left()
+ .left()
.isMethod(MethodKind.ROUND, 1)
.isParameterText(0, "<17.45>");
testFilter.runOnETAllPrim("floor(PropertyDouble) eq 17")
.is("<<floor(<PropertyDouble>)> eq <17>>")
- .root().left()
+ .left()
.isMethod(MethodKind.FLOOR, 1)
.isParameterText(0, "<PropertyDouble>");
testFilter.runOnETAllPrim("floor(17.45e1) eq 17")
.is("<<floor(<17.45e1>)> eq <17>>")
- .root().left()
+ .left()
.isMethod(MethodKind.FLOOR, 1)
.isParameterText(0, "<17.45e1>");
testFilter.runOnETAllPrim("floor(PropertyDecimal) eq 17")
.is("<<floor(<PropertyDecimal>)> eq <17>>")
- .root().left()
+ .left()
.isMethod(MethodKind.FLOOR, 1)
.isParameterText(0, "<PropertyDecimal>");
testFilter.runOnETAllPrim("floor(17.45) eq 17")
.is("<<floor(<17.45>)> eq <17>>")
- .root().left()
+ .left()
.isMethod(MethodKind.FLOOR, 1)
.isParameterText(0, "<17.45>");
testFilter.runOnETAllPrim("ceiling(PropertyDouble) eq 18")
.is("<<ceiling(<PropertyDouble>)> eq <18>>")
- .root().left()
+ .left()
.isMethod(MethodKind.CEILING, 1)
.isParameterText(0, "<PropertyDouble>");
testFilter.runOnETAllPrim("ceiling(17.55e1) eq 18")
.is("<<ceiling(<17.55e1>)> eq <18>>")
- .root().left()
+ .left()
.isMethod(MethodKind.CEILING, 1)
.isParameterText(0, "<17.55e1>");
testFilter.runOnETAllPrim("ceiling(PropertyDecimal) eq 18")
.is("<<ceiling(<PropertyDecimal>)> eq <18>>")
- .root().left()
+ .left()
.isMethod(MethodKind.CEILING, 1)
.isParameterText(0, "<PropertyDecimal>");
testFilter.runOnETAllPrim("ceiling(17.55) eq 18")
.is("<<ceiling(<17.55>)> eq <18>>")
- .root().left()
+ .left()
.isMethod(MethodKind.CEILING, 1)
.isParameterText(0, "<17.55>");
testFilter.runOnETAllPrim("totaloffsetminutes(PropertyDateTimeOffset) eq 4711")
.is("<<totaloffsetminutes(<PropertyDateTimeOffset>)> eq <4711>>")
- .root().left()
+ .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>>")
- .root().left()
+ .left()
.isMethod(MethodKind.TOTALOFFSETMINUTES, 1)
.isParameterText(0, "<2013-09-25T12:34:56.123456789012-10:24>");
- testFilter.runOnETAllPrim("mindatetime()")
- .is("<mindatetime()>")
- .isMethod(MethodKind.MINDATETIME, 0);
+ 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>>")
- .root().left()
+ .left()
.isMethod(MethodKind.MINDATETIME, 0);
- testFilter.runOnETAllPrim("maxdatetime()")
- .is("<maxdatetime()>")
- .isMethod(MethodKind.MAXDATETIME, 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>>")
- .root().left()
+ .left()
.isMethod(MethodKind.MAXDATETIME, 0);
- testFilter.runOnETAllPrim("now()")
- .is("<now()>")
- .isMethod(MethodKind.NOW, 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>>")
- .root().left()
+ .left()
.isMethod(MethodKind.NOW, 0);
testFilter.runOnETTwoKeyNav("$it/PropertyString eq 'SomeString'")
.is("<<$it/PropertyString> eq <'SomeString'>>")
- .root().left()
+ .left()
.goPath()
.first().isUriPathInfoKind(UriResourceKind.it)
.isType(EntityTypeProvider.nameETTwoKeyNav, false)
@@ -4487,7 +4316,7 @@ public class TestFullResourcePath {
testFilter.runOnCTTwoPrim("$it/PropertyString eq 'SomeString'")
.is("<<$it/PropertyString> eq <'SomeString'>>")
- .root().left()
+ .left()
.goPath()
.first().isUriPathInfoKind(UriResourceKind.it)
.isType(ComplexTypeProvider.nameCTTwoPrim, false)
@@ -4495,7 +4324,7 @@ public class TestFullResourcePath {
testFilter.runOnString("$it eq 'Walldorf'")
.is("<<$it> eq <'Walldorf'>>")
- .root().left()
+ .left()
.goPath()
.first().isUriPathInfoKind(UriResourceKind.it)
.isType(PropertyProvider.nameString, false);
@@ -4512,7 +4341,7 @@ public class TestFullResourcePath {
testFilter.runOnString("endswith($it,'sap.com') eq false")
.is("<<endswith(<$it>,<'sap.com'>)> eq <false>>")
- .root().left()
+ .left()
.isMethod(MethodKind.ENDSWITH, 2)
.isParameterText(0, "<$it>")
.isParameterText(1, "<'sap.com'>")
@@ -4644,44 +4473,42 @@ public class TestFullResourcePath {
.n().isPrimitiveProperty("PropertyInt16", PropertyProvider.nameInt16, false);
}
- // TODO: Implement cast method.
@Test
public void castMethod() throws Exception {
- testFilter.runOnETKeyNav("cast(olingo.odata.test1.ETBaseTwoKeyNav)")
- .is("<cast(<olingo.odata.test1.ETBaseTwoKeyNav>)>")
- .root()
+ testFilter.runOnETKeyNav("cast(olingo.odata.test1.ETBaseTwoKeyNav) ne null")
+ .is("<<cast(<olingo.odata.test1.ETBaseTwoKeyNav>)> ne <n
<TRUNCATED>
[27/30] olingo-odata4 git commit: [OLINGO-834] Delete AntLR
dependecies
Posted by ch...@apache.org.
[OLINGO-834] Delete AntLR dependecies
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/26080f42
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/26080f42
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/26080f42
Branch: refs/heads/master
Commit: 26080f420ac48ce8a3d60a6372226ee4f2f4aab8
Parents: 010642c
Author: Christian Amend <ch...@sap.com>
Authored: Thu Jan 7 15:00:17 2016 +0100
Committer: Christian Amend <ch...@sap.com>
Committed: Thu Jan 7 15:00:17 2016 +0100
----------------------------------------------------------------------
lib/server-core-ext/pom.xml | 4 -
lib/server-core/pom.xml | 40 --
.../olingo/server/core/uri/antlr/UriLexer.g4 | 424 ------------------
.../olingo/server/core/uri/antlr/UriParser.g4 | 447 -------------------
.../uri/parser/CheckFullContextListener.java | 60 ---
lib/server-test/pom.xml | 4 -
pom.xml | 14 -
7 files changed, 993 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/26080f42/lib/server-core-ext/pom.xml
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/pom.xml b/lib/server-core-ext/pom.xml
index e15dc1a..af286c0 100644
--- a/lib/server-core-ext/pom.xml
+++ b/lib/server-core-ext/pom.xml
@@ -50,10 +50,6 @@
<version>${project.version}</version>
</dependency>
<dependency>
- <groupId>org.antlr</groupId>
- <artifactId>antlr4-runtime</artifactId>
- </dependency>
- <dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/26080f42/lib/server-core/pom.xml
----------------------------------------------------------------------
diff --git a/lib/server-core/pom.xml b/lib/server-core/pom.xml
index 8b18338..6e22690 100644
--- a/lib/server-core/pom.xml
+++ b/lib/server-core/pom.xml
@@ -46,10 +46,6 @@
<version>${project.version}</version>
</dependency>
<dependency>
- <groupId>org.antlr</groupId>
- <artifactId>antlr4-runtime</artifactId>
- </dependency>
- <dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
@@ -85,42 +81,6 @@
</configuration>
</plugin>
<plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>build-helper-maven-plugin</artifactId>
- <executions>
- <execution>
- <phase>generate-sources</phase>
- <goals>
- <goal>add-source</goal>
- </goals>
- <configuration>
- <sources>
- <source>target/generated-sources/antlr4</source>
- </sources>
- </configuration>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>org.antlr</groupId>
- <artifactId>antlr4-maven-plugin</artifactId>
- <executions>
- <execution>
- <goals>
- <goal>antlr4</goal>
- </goals>
- </execution>
- </executions>
- <configuration>
- <!--<arguments><argument>-atn</argument></arguments> -->
- <listener>true</listener>
- <visitor>true</visitor>
- <!--maven antlr plugin has trouble with grammer import if the grammerfiles
- are not directly inside src/main/antlr4, hence we have to set the libDirectory -->
- <libDirectory>src/main/antlr4/org/apache/olingo/server/core/uri/antlr</libDirectory>
- </configuration>
- </plugin>
- <plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>${maven.bundle.plugin.version}</version>
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/26080f42/lib/server-core/src/main/antlr4/org/apache/olingo/server/core/uri/antlr/UriLexer.g4
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/antlr4/org/apache/olingo/server/core/uri/antlr/UriLexer.g4 b/lib/server-core/src/main/antlr4/org/apache/olingo/server/core/uri/antlr/UriLexer.g4
deleted file mode 100644
index 7a54ab1..0000000
--- a/lib/server-core/src/main/antlr4/org/apache/olingo/server/core/uri/antlr/UriLexer.g4
+++ /dev/null
@@ -1,424 +0,0 @@
-/*******************************************************************************
- * 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.
- ******************************************************************************/
-lexer grammar UriLexer;
-
-//;==============================================================================
-// Mode "DEFAULT_MODE": Processes everything before the first '?' char.
-// On '?' the next mode "MODE_QUERY" is used.
-// The percent encoding rules are defined in RFC3986; ABNF rule "path-rootless" applies.
-//;==============================================================================
-QM : '?' -> pushMode(MODE_QUERY); //first query parameter
-AMP : '&' -> pushMode(MODE_QUERY); //more query parameters
-STRING : '\'' -> more, pushMode(MODE_STRING) ; //reads up to next single '
-QUOTATION_MARK : '\u0022' -> more, pushMode(MODE_JSON_STRING); //reads up to next unescaped "
-SEARCH_INLINE : '$search' -> pushMode(MODE_SYSTEM_QUERY_SEARCH); //
-FRAGMENT : '#' -> pushMode(MODE_FRAGMENT); //
-STRING_JSON : '"' -> more, pushMode(MODE_JSON_STRING); //reads up to next unescaped "
-
-GEOGRAPHY : G E O G R A P H Y SQUOTE -> pushMode(MODE_ODATA_GEO); //TODO make case insensitive
-GEOMETRY : G E O M E T R Y SQUOTE -> pushMode(MODE_ODATA_GEO);
-
-//Letters for case insensitivity
-fragment A : 'A'|'a';
-fragment B : 'B'|'b';
-fragment D : 'D'|'d';
-fragment E : 'E'|'e';
-fragment F : 'F'|'f';
-fragment G : 'G'|'g';
-fragment H : 'H'|'h';
-fragment I : 'I'|'i';
-fragment L : 'L'|'l';
-fragment M : 'M'|'m';
-fragment N : 'N'|'n';
-fragment O : 'O'|'o';
-fragment P : 'P'|'p';
-fragment R : 'R'|'r';
-fragment S : 'S'|'s';
-fragment T : 'T'|'t';
-fragment U : 'U'|'u';
-fragment Y : 'Y'|'y';
-fragment Z : 'Z'|'z';
-
-//special chars
-OPEN : '(';
-CLOSE : ')';
-COMMA : ',';
-SLASH : '/';
-POINT : '.';
-AT : '@';
-EQ : '=' ;
-STAR : '*';
-SEMI : ';';
-COLON : ':';
-
-EQ_sq : '=' -> type(EQ);
-AMP_sq : '&' -> type(AMP), popMode;
-fragment WS : ( ' ' | '\u0009' );
-WSP : WS+;
-
-//JSON support
-BEGIN_OBJECT : WS* '{' WS*;
-END_OBJECT : WS* '}' WS*;
-
-BEGIN_ARRAY : WS* '[' WS*;
-END_ARRAY : WS* ']' WS*;
-
-
-//alpha stuff
-fragment ALPHA : 'a'..'z' | 'A'..'Z';
-fragment ALPHA_A_TO_F : 'a'..'f' | 'A'..'F';
-fragment DIGIT : '0'..'9';
-fragment DIGITS : DIGIT+;
-fragment HEXDIG : DIGIT | ALPHA_A_TO_F;
-fragment ODI_LEADINGCHARACTER : ALPHA | '_'; //TODO; add Unicode characters from the categories L or Nl
-fragment ODI_CHARACTER : ALPHA | '_' | DIGIT; //TODO; add Unicode characters from the categories L, Nl, Nd, Mn, Mc, Pc, or Cf
-
-//helper for date/time values
-fragment ONE_TO_NINE : '1'..'9';
-fragment ZERO_TO_FIFTYNINE : ('0'..'5') DIGIT;
-fragment FRACTIONALSECONDS : DIGIT+;
-fragment SECOND : ZERO_TO_FIFTYNINE;
-fragment MINUTE : ZERO_TO_FIFTYNINE;
-fragment HOUR : ('0' | '1') DIGIT | '2' ( '0'..'3');
-fragment DAY : '0' '1'..'9' | ('1'|'2') DIGIT | '3' ('0'|'1');
-fragment MONTH : '0' ONE_TO_NINE | '1' ( '0' | '1' | '2' );
-fragment YEAR : ('-')? ( '0' DIGIT DIGIT DIGIT | ONE_TO_NINE DIGIT DIGIT DIGIT );
-
-//tags starting with $
-BATCH : '$batch';
-ENTITY : '$entity';
-METADATA : '$metadata';
-
-ALL : '$all';
-CROSSJOIN : '$crossjoin';
-
-VALUE : '$value';
-REF : '$ref';
-COUNT : '$count';
-
-//inlined query parameters ( e.g. $skip)
-TOP_I : '$top' -> type(TOP);
-SKIP_QO_I : '$skip' -> type(SKIP_QO);
-FILTER_I : '$filter' -> type(FILTER);
-ORDERBY_I : '$orderby'-> type(ORDERBY);
-SELECT_I : '$select' -> type(SELECT);
-EXPAND_I : '$expand' -> type(EXPAND);
-LEVELS_I : '$levels' -> type(LEVELS);
-MAX: 'max';
-
-ROOT : '$root/';
-
-//rest
-NULLVALUE : 'null';
-
-TRUE : 'true';
-FALSE : 'false';
-BOOLEAN : T R U E | F A L S E;
-PLUS : '+';
-
-MINUS : '-';
-SIGN : PLUS | '-';
-INT : SIGN? DIGITS;
-DECIMAL : INT '.' DIGITS (('e'|'E') SIGN? DIGITS)?;
-NANINFINITY : 'NaN' | '-INF' | 'INF';
-//primary types
-BINARY : B I N A R Y SQUOTE (HEXDIG HEXDIG)* SQUOTE;
-DATE : YEAR '-' MONTH '-' DAY;
-DATETIMEOFFSET : YEAR '-' MONTH '-' DAY T HOUR ':' MINUTE ( ':' SECOND ( '.' FRACTIONALSECONDS )? )? ( Z | SIGN HOUR ':' MINUTE );
-fragment DUSECONDFRAG : DIGITS ('.' DIGITS)? 'S';
-fragment DUTIMEFRAG : 'T' (
- ( DIGITS 'H' (DIGITS 'M')? DUSECONDFRAG?)
- | (DIGITS 'M' DUSECONDFRAG?)
- | DUSECONDFRAG
- )?;
-fragment DUDAYTIMEFRAG : DIGITS 'D' DUTIMEFRAG? | DUTIMEFRAG;
-DURATION : D U R A T I O N SQUOTE '-'? 'P' DUDAYTIMEFRAG SQUOTE;
-TIMEOFDAY : HOUR ':' MINUTE ( ':' SECOND ( '.' FRACTIONALSECONDS )? )?;
-fragment GUIDVALUE : HEXDIG HEXDIG HEXDIG HEXDIG HEXDIG HEXDIG HEXDIG HEXDIG'-'
- HEXDIG HEXDIG HEXDIG HEXDIG '-'
- HEXDIG HEXDIG HEXDIG HEXDIG '-'
- HEXDIG HEXDIG HEXDIG HEXDIG '-'
- HEXDIG HEXDIG HEXDIG HEXDIG HEXDIG HEXDIG HEXDIG HEXDIG HEXDIG HEXDIG HEXDIG HEXDIG;
-GUID : GUIDVALUE;
-
-//expression tokens
-ASC : 'asc';
-DESC : 'desc';
-MUL : 'mul';
-DIV : 'div';
-MOD : 'mod';
-HAS : 'has';
-
-ADD : 'add';
-SUB : 'sub';
-
-ANY_LAMDA : 'any';
-ALL_LAMDA : 'all';
-
-GT : 'gt';
-GE : 'ge';
-LT : 'lt';
-LE : 'le';
-ISOF : 'isof';
-
-EQ_ALPHA : 'eq';
-NE : 'ne';
-
-AND : 'and';
-OR : 'or';
-
-
-NOT : 'not';
-
-
-IT : '$it';
-ITSLASH : '$it/';
-LEVELS : '$levels';
-
-CONTAINS_WORD : 'contains(';
-STARTSWITH_WORD : 'startswith(';
-ENDSWITH_WORD : 'endswith(';
-LENGTH_WORD : 'length(';
-INDEXOF_WORD : 'indexof(';
-SUBSTRING_WORD : 'substring(';
-TOLOWER_WORD : 'tolower(';
-TOUPPER_WORD : 'toupper(';
-TRIM_WORD : 'trim(';
-CONCAT_WORD : 'concat(';
-YEAR_WORD : 'year(';
-MONTH_WORD : 'month(';
-DAY_WORD : 'day(';
-HOUR_WORD : 'hour(';
-MINUTE_WORD : 'minute(';
-SECOND_WORD : 'second(';
-FRACTIONALSECONDS_WORD : 'fractionalseconds(';
-TOTALSECONDS_WORD : 'totalseconds(';
-DATE_WORD : 'date(';
-TIME_WORD : 'time(';
-TOTALOFFSETMINUTES_WORD : 'totaloffsetminutes(';
-
-MINDATETIME_WORD : 'mindatetime(';
-MAXDATETIME_WORD : 'maxdatetime(';
-NOW_WORD : 'now(';
-
-ROUND_WORD : 'round(';
-FLOOR_WORD : 'floor(';
-CEILING_WORD : 'ceiling(';
-
-GEO_DISTANCE_WORD : 'geo.distance(';
-GEO_LENGTH_WORD : 'geo.length(';
-GEO_INTERSECTS_WORD : 'geo.intersects(';
-ISOF_WORD : 'isof(';
-CAST_WORD : 'cast(';
-
-COLLECTION_REF : 'Collection($ref)';
-COLLECTION_ENTITY_TYPE : 'Collection(Edm.EntityType)';
-COLLECTION_COMPLEX_TYPE : 'Collection(Edm.ComplexType)';
-COLLECTION : 'Collection(' -> type(COLLECTION);
-
-//used in fragment only
-DELETED_ENTITY : '$deletedEntity';
-LINK : '$link';
-DELETED_LINK : '$deletedLink';
-DELTA : '$delta';
-
-ODATAIDENTIFIER : ODI_LEADINGCHARACTER (ODI_CHARACTER)*;
-
-//handle characters that failed to match any other token
-ERROR_CHARACTER : .;
-
-//;==============================================================================
-// Mode "QUERY": Processes everything between the first '?' and the '#' char.
-// On '?' the next mode "FRAGMENT" is used.
-// The percent encoding rules are defined in RFC3986; ABNF rule "query" applies.
-mode MODE_QUERY;
-//;==============================================================================
-
-FRAGMENT_q : '#' -> type(FRAGMENT);
-FILTER : '$filter' -> pushMode(DEFAULT_MODE);
-ORDERBY : '$orderby' -> pushMode(DEFAULT_MODE);
-EXPAND : '$expand' -> pushMode(DEFAULT_MODE);
-SELECT : '$select' -> pushMode(DEFAULT_MODE);
-SKIP_QO : '$skip' -> pushMode(DEFAULT_MODE);
-SKIPTOKEN : '$skiptoken' -> pushMode(MODE_SYSTEM_QUERY_REST);
-TOP : '$top' -> pushMode(DEFAULT_MODE);
-LEVELS_q : '$levels' -> type(LEVELS), pushMode(DEFAULT_MODE);
-FORMAT : '$format' -> pushMode(MODE_SYSTEM_QUERY_PCHAR);
-COUNT_q : '$count' -> type(COUNT), pushMode(DEFAULT_MODE);
-REF_q : '$ref' -> type(REF);
-VALUE_q : '$value' -> type(VALUE);
-ID : '$id' -> pushMode(MODE_SYSTEM_QUERY_REST);
-SEARCH : '$search' -> pushMode(MODE_SYSTEM_QUERY_SEARCH);
-
-EQ_q : '=' -> type(EQ);
-AMP_q : '&' -> type(AMP);
-
-AT_Q : '@' -> pushMode(DEFAULT_MODE);
-
-CUSTOMNAME : ~[&=@$] ~[&=]* -> pushMode(MODE_SYSTEM_QUERY_REST);
-
-//handle characters that failed to match any other token
-ERROR_CHARACTER_q : .;
-
-//;==============================================================================
-mode MODE_SYSTEM_QUERY_PCHAR;
-//;==============================================================================
-
-AMP_sqp : '&' -> type(AMP), popMode;
-
-fragment ALPHA_sqp : 'a'..'z'|'A'..'Z';
-fragment A_TO_F_sqp : 'a'..'f'|'A'..'F';
-fragment DIGIT_sqp : '0'..'9';
-fragment HEXDIG_sqp : DIGIT_sqp | A_TO_F_sqp;
-fragment PCT_ENCODED_sqp : '%' HEXDIG_sqp HEXDIG_sqp;
-fragment SUB_DELIMS_sqp : '$' | /*'&' |*/ '\'' | EQ_sqp | OTHER_DELIMS_sqp;
-fragment OTHER_DELIMS_sqp : '!' | '(' | ')' | '*' | '+' | ',' | ';';
-fragment UNRESERVED_sqp : ALPHA_sqp | DIGIT_sqp | '-' |'.' | '_' | '~';
-fragment PCHAR : UNRESERVED_sqp | PCT_ENCODED_sqp | SUB_DELIMS_sqp | ':' | '@';
-fragment PCHARSTART : UNRESERVED_sqp | PCT_ENCODED_sqp | '$' | /*'&' |*/ '\'' | OTHER_DELIMS_sqp | ':' | '@';
-
-ATOM : [Aa][Tt][Oo][Mm];
-JSON : [Jj][Ss][Oo][Nn];
-XML : [Xx][Mm][Ll];
-
-PCHARS : PCHARSTART PCHAR*;
-
-SLASH_sqp : '/' -> type(SLASH);
-EQ_sqp : '=' -> type(EQ);
-FRAGMENT_sqp : '#' -> type(FRAGMENT), pushMode(MODE_FRAGMENT);
-
-//handle characters that failed to match any other token
-ERROR_CHARACTER_sqp : .;
-
-//;==============================================================================
-mode MODE_FRAGMENT;
-// Read the remaining characters of a URI queryparameter up to an & or #
-// character.
-//;==============================================================================
-
-REST_F : ~('\r'|'\n')* -> type(REST), popMode;
-
-//;==============================================================================
-mode MODE_SYSTEM_QUERY_REST;
-// Read the remaining characters of a URI queryparameter up to an & or #
-// character.
-//;==============================================================================
-
-AMP_sqr : '&' -> type(AMP), popMode;
-FRAGMENT_sqr : '#' -> type(FRAGMENT), popMode;
-
-EQ_sqr : '=' -> type(EQ);
-REST : ~[&#=] ~[&#]*;
-ERROR_CHARACTER_sqmr : .;
-
-//;==============================================================================
-mode MODE_SYSTEM_QUERY_SEARCH;
-//;==============================================================================
-
-NOT_sqc : 'NOT' -> type(NOT);
-AND_sqc : 'AND' -> type(AND);
-OR_sqc : 'OR' -> type(OR);
-EQ_sqc : '=' -> type(EQ);
-
-fragment WS_sqc : ( ' ' | '\u0009');
-WSP_sqc : WS_sqc+ -> type(WSP);
-
-QUOTATION_MARK_sqc : '\u0022';
-
-SEARCHWORD : ('a'..'z'|'A'..'Z')+;
-SEARCHPHRASE : QUOTATION_MARK_sqc ~["]* QUOTATION_MARK_sqc;
-
-// Follow Set
-CLOSE_qs : ')' -> popMode, type(CLOSE);
-SEMI_qs : ';' -> popMode, type(SEMI);
-AMP_qs : '&' -> popMode, type(AMP);
-ERROR_CHARACTER_sqms : .;
-
-//;==============================================================================
-mode MODE_STRING;
-// Reads the remaining characters up to an ' character.
-// Any "'" characters inside a string are expressed as double "''".
-//;==============================================================================
-
-STRING_s : ('\'\'' | ~[\u0027] )* '\'' -> type(STRING), popMode;
-ERROR_CHARACTER_sm : EOF | .;
-
-//;==============================================================================
-mode MODE_JSON_STRING;
-// Reads the remaining characters up to an " character.
-// Any """ characters inside a string are escaped with "\".
-//;==============================================================================
-
-STRING_IN_JSON : (ESCAPED_JSON_CHAR | ~["\\])* '"' -> popMode;
-fragment ESCAPED_JSON_CHAR : '\\' (["\\/bfnrt] | UNICODE_CHAR);
-fragment UNICODE_CHAR : 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT;
-fragment HEX_DIGIT : [0-9a-fA-F];
-ERROR_CHARACTER_jsm : EOF | .;
-
-//;==============================================================================
-mode MODE_ODATA_GEO;
-//;==============================================================================
-
-fragment C_ : 'c'|'C';
-fragment D_ : 'd'|'D';
-fragment E_ : 'e'|'E';
-fragment G_ : 'g'|'G';
-fragment H_ : 'h'|'H';
-fragment I_ : 'i'|'I';
-fragment L_ : 'l'|'L';
-fragment M_ : 'm'|'M';
-fragment N_ : 'n'|'N';
-fragment O_ : 'o'|'O';
-fragment P_ : 'p'|'P';
-fragment R_ : 'r'|'R';
-fragment S_ : 's'|'S';
-fragment T_ : 't'|'T';
-fragment U_ : 'u'|'U';
-fragment Y_ : 'y'|'Y';
-
-fragment SP_g : ' '; //'\u0020'; // a simple space
-fragment WS_g : ( ' ' | '\u0009' );
-
-OPEN_g : '(' -> type(OPEN);
-CLOSE_g : ')' -> type(CLOSE);
-COMMA_g : ',' -> type(COMMA);
-WSP_g : WS_g+ -> type(WSP);
-POINT_g : '.' -> type(POINT);
-AT_g : '@' -> type(AT);
-SEMI_g : ';' -> type(SEMI);
-EQ_g : '=' -> type(EQ);
-
-fragment DIGIT_g : '0'..'9';
-fragment DIGITS_g : DIGIT_g+;
-SIGN_g : ('+' | '-') -> type(SIGN);
-INT_g : SIGN_g? DIGITS_g -> type(INT);
-DECIMAL_g : 'SS' INT_g '.' DIGITS_g (('e'|'E') SIGN_g? DIGITS_g)? -> type(DECIMAL);
-COLLECTION_g : C_ O_ L_ L_ E_ C_ T_ I_ O_ N_ -> type(COLLECTION);
-LINESTRING : L_ I_ N_ E_ S_ T_ R_ I_ N_ G_ ;
-MULTILINESTRING : M_ U_ L_ T_ I_ L_ I_ N_ E_ S_ T_ R_ I_ N_ G_;
-MULTIPOINT : M_ U_ L_ T_ I_ P_ O_ I_ N_ T_ ;
-MULTIPOLYGON : M_ U_ L_ T_ I_ P_ O_ L_ Y_ G_ O_ N_;
-GEO_POINT : P_ O_ I_ N_ T_;
-POLYGON : P_ O_ L_ Y_ G_ O_ N_ ;
-
-SRID : S_ R_ I_ D_;
-
-SQUOTE : '\'' -> popMode;
-
-ERROR_CHARACTER_g : .;
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/26080f42/lib/server-core/src/main/antlr4/org/apache/olingo/server/core/uri/antlr/UriParser.g4
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/antlr4/org/apache/olingo/server/core/uri/antlr/UriParser.g4 b/lib/server-core/src/main/antlr4/org/apache/olingo/server/core/uri/antlr/UriParser.g4
deleted file mode 100644
index 5a24b29..0000000
--- a/lib/server-core/src/main/antlr4/org/apache/olingo/server/core/uri/antlr/UriParser.g4
+++ /dev/null
@@ -1,447 +0,0 @@
-/*******************************************************************************
- * 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.
- ******************************************************************************/
-
-grammar UriParser;
-
-//------------------------------------------------------------------------------
-// This grammar refers to the "odata-abnf-construction-rules.txt" Revision 517.
-// URL: https://tools.oasis-open.org/version-control/browse/wsvn/odata/trunk/spec/ABNF/odata-abnf-construction-rules.txt?rev=517
-
-// While contructing this grammar we tried to keep it close to the ABNF.
-// However this is not really possible in order to support
-// - percent decoding
-// - operator precedence
-// - having a context free grammar ( without java snipplets to add context)
-// - generating the parser in different target languages
-// Currently not supported are
-// - $search
-// - geometry data
-// - json data in url
-//------------------------------------------------------------------------------
-
-
-options {
- language = Java;
- tokenVocab = UriLexer;
-}
-
-//;------------------------------------------------------------------------------
-//; 0. URI
-//;------------------------------------------------------------------------------
-
-batchEOF : BATCH EOF;
-
-entityEOF : vNS=namespace vODI=odataIdentifier;
-
-metadataEOF : METADATA EOF;
-
-//;------------------------------------------------------------------------------
-//; 1. Resource Path
-//;------------------------------------------------------------------------------
-
-//resourcePathEOF : vlPS=pathSegments EOF;
-
-crossjoinEOF : CROSSJOIN OPEN WSP? vlODI+=odataIdentifier WSP? ( COMMA WSP? vlODI+=odataIdentifier WSP?)* CLOSE EOF;
-
-allEOF : ALL;
-
-pathSegmentEOF : (pathSegment | constSegment) EOF;
-
-pathSegments : vlPS+=pathSegment (SLASH vlPS+=pathSegment)* (SLASH vCS=constSegment)?;
-
-pathSegment : vNS=namespace? vODI=odataIdentifier vlNVO+=nameValueOptList*;
-
-nameValueOptList : OPEN (vVO=commonExpr | vNVL=nameValueList)? CLOSE;
-nameValueList : WSP* vlNVP+=nameValuePair WSP* ( COMMA WSP* vlNVP+=nameValuePair WSP*)* ;
-nameValuePair : vODI=odataIdentifier EQ (AT vALI=odataIdentifier | vCOM=commonExpr /*TODO | val2=enumX*/);
-
-constSegment : (vV=value | vC=count | vR=ref | vAll=allExpr | vAny=anyExpr);
-
-count : COUNT;
-ref : REF;
-value : VALUE;
-
-//;------------------------------------------------------------------------------
-//; 2. Query Options
-//;------------------------------------------------------------------------------
-
-queryOptions : vlQO+=queryOption ( AMP vlQO+=queryOption )*;//TODO can this be removed
-
-queryOption : systemQueryOption;
-
-systemQueryOption : expand
- | filter
- | inlinecount
- | orderBy
- | search
- | select
- | skip
- | skiptoken
- | top
- ;
-
-skiptoken : SKIPTOKEN EQ REST;
-expand : EXPAND EQ expandItems;
-
-expandItemsEOF : expandItems EOF;
-expandItems : vlEI+=expandItem ( COMMA vlEI+=expandItem )*;
-
-
-expandItem : vS=STAR ( SLASH vR=ref | OPEN LEVELS EQ ( vL=INT | vM=MAX) CLOSE )?
- | vEP=expandPath vEPE=expandPathExtension?;
-
-
-expandPath : vlPS+=pathSegment (SLASH vlPS+=pathSegment)*;
-
-expandPathExtension : OPEN vlEO+=expandOption ( SEMI vlEO+=expandOption )* CLOSE
- | SLASH vR=ref ( OPEN vlEOR+=expandRefOption ( SEMI vlEOR+=expandRefOption )* CLOSE )?
- | SLASH vC=count ( OPEN vlEOC+=expandCountOption ( SEMI vlEOC+=expandCountOption )* CLOSE )?
- ;
-
-expandCountOption : filter
- | searchInline
- ;
-
-expandRefOption : expandCountOption
- | orderBy
- | skip
- | top
- | inlinecount
- ;
-
-expandOption : expandRefOption
- | select
- | expand
- | levels;
-
-levels : LEVELS EQ ( INT | MAX );
-
-filter : FILTER EQ commonExpr;
-
-filterExpressionEOF : commonExpr EOF;
-
-orderBy : ORDERBY EQ orderList;
-
-orderByEOF : orderList EOF;
-
-orderList : vlOI+=orderByItem ( WSP* COMMA WSP* vlOI+=orderByItem )*;
-
-orderByItem : vC=commonExpr ( WSP ( vA=ASC | vD=DESC ) )?;
-
-skip : SKIP_QO EQ INT;
-top : TOP EQ INT;
-//format : FORMAT EQ ( ATOM | JSON | XML | PCHARS SLASH PCHARS);
-
-inlinecount : COUNT EQ booleanNonCaseLiteral;
-
-search : SEARCH searchSpecialToken;
-searchInline : SEARCH_INLINE searchSpecialToken;
-
-searchSpecialToken : EQ WSP? searchExpr;
-
-searchExpr : (NOT WSP) searchExpr
- | searchExpr searchExpr
- | searchExpr WSP searchExpr
- | searchExpr ( WSP AND WSP) searchExpr
- | searchExpr ( WSP OR WSP) searchExpr
- | searchPhrase
- | searchWord
- ;
-
-searchPhrase : SEARCHPHRASE;
-searchWord : SEARCHWORD;
-
-select : SELECT EQ vlSI+=selectItem ( COMMA vlSI+=selectItem )*;
-selectEOF : vlSI+=selectItem ( COMMA vlSI+=selectItem )*;
-
-selectItem : vlSS+=selectSegment ( SLASH vlSS+=selectSegment ) *;
-selectSegment : vNS=namespace? ( vODI=odataIdentifier | vS=STAR );
-
-aliasAndValue : vODI=ODATAIDENTIFIER EQ vV=parameterValue;
-
-parameterValue : commonExpr //TODO json not supported arrayOrObject
- ;
-
-//;------------------------------------------------------------------------------
-//; 3. Context URL Fragments
-//;------------------------------------------------------------------------------
-
-contextFragment : REST; // the context fragment is only required on the client side
-
-//;------------------------------------------------------------------------------
-//; 4. Expressions
-//;------------------------------------------------------------------------------
-
-commonExpr : OPEN commonExpr CLOSE #altPharenthesis
- | vE1=commonExpr (WSP HAS WSP) vE2=commonExpr #altHas
- | methodCallExpr #altMethod
- | ( unary WSP? ) commonExpr #altUnary
- | anyExpr #altAny
- | allExpr #altAll
- | memberExpr #altMember
- | vE1=commonExpr (WSP vO=MUL WSP | WSP vO=DIV WSP | WSP vO=MOD WSP ) vE2=commonExpr #altMult
- | vE1=commonExpr (WSP vO=ADD WSP | WSP vO=SUB WSP) vE2=commonExpr #altAdd
- | vE1=commonExpr (WSP vO=GT WSP | WSP vO=GE WSP | WSP vO=LT WSP
- | WSP vO=LE WSP ) vE2=commonExpr #altComparism
- | vE1=commonExpr (WSP vO=EQ_ALPHA WSP | WSP vO=NE WSP) vE2=commonExpr #altEquality
- | vE1=commonExpr (WSP AND WSP) vE2=commonExpr #altAnd
- | vE1=commonExpr (WSP OR WSP) vE2=commonExpr #altOr
- | rootExpr #altRoot // $...
- | AT odataIdentifier #altAlias // @...
- | primitiveLiteral #altLiteral // ...
- | arrayOrObject #altJson
- ;
-
-unary : (MINUS| NOT) ;
-
-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;
-allExpr : ALL_LAMDA OPEN WSP? vLV=odataIdentifier WSP? COLON WSP? vLE=commonExpr WSP? CLOSE;
-
-methodCallExpr : indexOfMethodCallExpr
- | toLowerMethodCallExpr
- | toUpperMethodCallExpr
- | trimMethodCallExpr
- | substringMethodCallExpr
- | concatMethodCallExpr
- | lengthMethodCallExpr
- | yearMethodCallExpr
- | monthMethodCallExpr
- | dayMethodCallExpr
- | hourMethodCallExpr
- | minuteMethodCallExpr
- | secondMethodCallExpr
- | fractionalsecondsMethodCallExpr
- | totalsecondsMethodCallExpr
- | dateMethodCallExpr
- | timeMethodCallExpr
- | roundMethodCallExpr
- | floorMethodCallExpr
- | ceilingMethodCallExpr
- | geoDistanceMethodCallExpr
- | geoLengthMethodCallExpr
- | totalOffsetMinutesMethodCallExpr
- | minDateTimeMethodCallExpr
- | maxDateTimeMethodCallExpr
- | nowMethodCallExpr
- //from boolean
- | isofExpr
- | castExpr
- | endsWithMethodCallExpr
- | startsWithMethodCallExpr
- | containsMethodCallExpr
- | geoIntersectsMethodCallExpr
- ;
-
-
-containsMethodCallExpr : CONTAINS_WORD WSP? vE1=commonExpr WSP? COMMA WSP? vE2=commonExpr WSP? CLOSE;
-startsWithMethodCallExpr : STARTSWITH_WORD WSP? vE1=commonExpr WSP? COMMA WSP? vE2=commonExpr WSP? CLOSE;
-endsWithMethodCallExpr : ENDSWITH_WORD WSP? vE1=commonExpr WSP? COMMA WSP? vE2=commonExpr WSP? CLOSE;
-lengthMethodCallExpr : LENGTH_WORD WSP? vE1=commonExpr WSP? CLOSE;
-indexOfMethodCallExpr : INDEXOF_WORD WSP? vE1=commonExpr WSP? COMMA WSP? vE2=commonExpr WSP? CLOSE;
-substringMethodCallExpr : SUBSTRING_WORD WSP? vE1=commonExpr WSP? COMMA WSP? vE2=commonExpr WSP? ( COMMA WSP? vE3=commonExpr WSP? )? CLOSE;
-toLowerMethodCallExpr : TOLOWER_WORD WSP? vE1=commonExpr WSP? CLOSE;
-toUpperMethodCallExpr : TOUPPER_WORD WSP? vE1=commonExpr WSP? CLOSE;
-trimMethodCallExpr : TRIM_WORD WSP? vE1=commonExpr WSP? CLOSE;
-concatMethodCallExpr : CONCAT_WORD WSP? vE1=commonExpr WSP? COMMA WSP? vE2=commonExpr WSP? CLOSE;
-
-yearMethodCallExpr : YEAR_WORD WSP? vE1=commonExpr WSP? CLOSE;
-monthMethodCallExpr : MONTH_WORD WSP? vE1=commonExpr WSP? CLOSE;
-dayMethodCallExpr : DAY_WORD WSP? vE1=commonExpr WSP? CLOSE;
-hourMethodCallExpr : HOUR_WORD WSP? vE1=commonExpr WSP? CLOSE;
-minuteMethodCallExpr : MINUTE_WORD WSP? vE1=commonExpr WSP? CLOSE;
-secondMethodCallExpr : SECOND_WORD WSP? vE1=commonExpr WSP? CLOSE;
-fractionalsecondsMethodCallExpr : FRACTIONALSECONDS_WORD WSP? vE1=commonExpr WSP? CLOSE;
-totalsecondsMethodCallExpr : TOTALSECONDS_WORD WSP? vE1=commonExpr WSP? CLOSE;
-dateMethodCallExpr : DATE_WORD WSP? vE1=commonExpr WSP? CLOSE;
-timeMethodCallExpr : TIME_WORD WSP? vE1=commonExpr WSP? CLOSE;
-totalOffsetMinutesMethodCallExpr : TOTALOFFSETMINUTES_WORD WSP? vE1=commonExpr WSP? CLOSE;
-
-minDateTimeMethodCallExpr : MINDATETIME_WORD WSP? CLOSE;
-maxDateTimeMethodCallExpr : MAXDATETIME_WORD WSP? CLOSE;
-nowMethodCallExpr : NOW_WORD WSP? CLOSE;
-
-roundMethodCallExpr : ROUND_WORD WSP? vE1=commonExpr WSP? CLOSE;
-floorMethodCallExpr : FLOOR_WORD WSP? vE1=commonExpr WSP? CLOSE;
-ceilingMethodCallExpr : CEILING_WORD WSP? vE1=commonExpr WSP? CLOSE;
-
-geoDistanceMethodCallExpr : GEO_DISTANCE_WORD WSP? vE1=commonExpr WSP? COMMA WSP? vE2=commonExpr WSP? CLOSE;
-geoLengthMethodCallExpr : GEO_LENGTH_WORD WSP? vE1=commonExpr WSP? CLOSE;
-geoIntersectsMethodCallExpr : GEO_INTERSECTS_WORD WSP? vE1=commonExpr WSP? COMMA WSP? vE2=commonExpr WSP? CLOSE;
-
-isofExpr : ISOF_WORD WSP? ( vE1=commonExpr WSP? COMMA WSP? )? vNS=namespace vODI=odataIdentifier WSP? CLOSE;
-castExpr : CAST_WORD WSP? ( vE1=commonExpr WSP? COMMA WSP? )? vNS=namespace vODI=odataIdentifier WSP? CLOSE;
-
-//;------------------------------------------------------------------------------
-//; 5. JSON format for function parameters
-//;------------------------------------------------------------------------------
-//; Note: the query part of a URI needs to be partially percent-decoded before
-//; applying these rules, see comment at the top of this file
-//;------------------------------------------------------------------------------
-
-arrayOrObject : json_array
- | json_object;
-
-json_array : BEGIN_ARRAY (json_value (WS* COMMA WS* json_value)*)? END_ARRAY;
-
-json_value : jsonPrimitive
- | rootExpr
- | json_object
- | json_array;
-
-json_object : BEGIN_OBJECT
- (json_key_value_pair (WS* COMMA WS* json_key_value_pair)*)?
- END_OBJECT;
-
-json_key_value_pair : STRING_IN_JSON WS* COLON WS* json_value;
-
-//; JSON syntax: adapted to URI restrictions from [RFC4627]
-jsonPrimitive : STRING_IN_JSON
- | number_in_json
- | TRUE
- | FALSE
- | NULLVALUE
- ;
-
-number_in_json : INT | DECIMAL;
-
-//;------------------------------------------------------------------------------
-//; 6. Names and identifiers
-//;------------------------------------------------------------------------------
-
-qualifiedtypename : namespace odataIdentifier
- | 'collection' OPEN ( namespace odataIdentifier ) CLOSE
- ;
-
-namespace : (odataIdentifier POINT)+;
-
-odataIdentifier : ODATAIDENTIFIER;
-
-//;------------------------------------------------------------------------------
-//; 7. Literal Data Values
-//;------------------------------------------------------------------------------
-
-
-primitiveLiteral : nullruleLiteral
- | booleanNonCaseLiteral
- | decimalLiteral //includes double and single literals
- | naninfinityLiteral
- | intLiteral //includes int16/int32 and int64 literals
- | binaryLiteral
- | dateLiteral
- | datetimeoffsetLiteral
- | durationLiteral
- | guidLiteral
- | stringLiteral
- | timeofdayLiteral
- | enumLiteral
- | geographyCollection
- | geographyLineString
- | geographyMultilineString
- | geographyMultipoint
- | geographyMultipolygon
- | geographyPoint
- | geographyPolygon
- | geometryCollection
- | geometryLineString
- | geometryMultilineString
- | geometryMultipoint
- | geometryMultipolygon
- | geometryPoint
- | geometryPolygon
- ;
-
-
-nullruleLiteral : NULLVALUE;
-booleanNonCaseLiteral : BOOLEAN | TRUE | FALSE;
-decimalLiteral : DECIMAL;
-naninfinityLiteral : NANINFINITY;
-intLiteral : INT;
-binaryLiteral : BINARY;
-dateLiteral : DATE;
-datetimeoffsetLiteral : DATETIMEOFFSET;
-durationLiteral : DURATION;
-guidLiteral : GUID;
-stringLiteral : STRING;
-timeofdayLiteral : TIMEOFDAY;
-
-enumLiteral : vNS=namespace vODI=odataIdentifier vValues=STRING;
-enumValues : vlODI+=odataIdentifier ( COMMA vlODI+=odataIdentifier )*;
-
-geographyCollection : GEOGRAPHY fullCollectionLiteral SQUOTE;
-fullCollectionLiteral : sridLiteral collectionLiteral;
-
-collectionLiteral : (COLLECTION ) OPEN geoLiteral ( COMMA geoLiteral )* CLOSE;
-
-geoLiteral : collectionLiteral
- | lineStringLiteral
- | multipointLiteral
- | multilineStringLiteral
- | multipolygonLiteral
- | pointLiteral
- | polygonLiteral;
-
-geographyLineString : GEOGRAPHY fullLineStringLiteral SQUOTE;
-fullLineStringLiteral : sridLiteral lineStringLiteral;
-lineStringLiteral : LINESTRING lineStringData;
-lineStringData : OPEN positionLiteral ( COMMA positionLiteral )* CLOSE;
-
-geographyMultilineString : GEOGRAPHY fullMultilineStringLiteral SQUOTE;
-fullMultilineStringLiteral : sridLiteral multilineStringLiteral;
-multilineStringLiteral : MULTILINESTRING OPEN ( lineStringData ( COMMA lineStringData )* )? CLOSE;
-
-geographyMultipoint : GEOGRAPHY fullMultipointLiteral SQUOTE;
-fullMultipointLiteral : sridLiteral multipointLiteral;
-multipointLiteral : MULTIPOINT OPEN ( pointData ( COMMA pointData )* )? CLOSE ;
-
-geographyMultipolygon : GEOGRAPHY fullmultipolygonLiteral SQUOTE;
-fullmultipolygonLiteral : sridLiteral multipolygonLiteral;
-multipolygonLiteral : MULTIPOLYGON OPEN ( polygonData ( COMMA polygonData )* )? CLOSE;
-
-geographyPoint : GEOGRAPHY fullpointLiteral SQUOTE;
-fullpointLiteral : sridLiteral pointLiteral;
-
-pointLiteral : GEO_POINT pointData;
-pointData : OPEN positionLiteral CLOSE;
-
-positionLiteral : (DECIMAL | INT ) WSP (DECIMAL | INT ); //; longitude, then latitude
-
-
-geographyPolygon : GEOGRAPHY fullPolygonLiteral SQUOTE;
-fullPolygonLiteral : sridLiteral polygonLiteral;
-polygonLiteral : POLYGON polygonData;
-polygonData : OPEN ringLiteral ( COMMA ringLiteral )* CLOSE;
-ringLiteral : OPEN positionLiteral ( COMMA positionLiteral )* CLOSE;
-
-
-geometryCollection : GEOMETRY fullCollectionLiteral SQUOTE;
-geometryLineString : GEOMETRY fullLineStringLiteral SQUOTE;
-geometryMultilineString : GEOMETRY fullMultilineStringLiteral SQUOTE;
-geometryMultipoint : GEOMETRY fullMultipointLiteral SQUOTE;
-geometryMultipolygon : GEOMETRY fullmultipolygonLiteral SQUOTE;
-geometryPoint : GEOMETRY fullpointLiteral SQUOTE;
-geometryPolygon : GEOMETRY fullPolygonLiteral SQUOTE;
-
-sridLiteral : SRID EQ INT SEMI;
-
-
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/26080f42/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/CheckFullContextListener.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/CheckFullContextListener.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/CheckFullContextListener.java
deleted file mode 100644
index bdfdf4c..0000000
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/CheckFullContextListener.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.BitSet;
-
-import org.antlr.v4.runtime.DiagnosticErrorListener;
-import org.antlr.v4.runtime.Parser;
-import org.antlr.v4.runtime.RecognitionException;
-import org.antlr.v4.runtime.Recognizer;
-import org.antlr.v4.runtime.atn.ATNConfigSet;
-import org.antlr.v4.runtime.dfa.DFA;
-
-class CheckFullContextListener extends DiagnosticErrorListener {
-
- @Override
- public void syntaxError(final Recognizer<?, ?> recognizer, final Object offendingSymbol, final int line,
- final int charPositionInLine,
- final String msg, final RecognitionException e) {
- // System.err.println("syntaxError detected");
- }
-
- @Override
- public void reportAmbiguity(final Parser recognizer, final DFA dfa, final int startIndex, final int stopIndex,
- final boolean exact,
- final BitSet ambigAlts, final ATNConfigSet configs) {
- // System.err.println("reportAmbiguity detected");
- }
-
- @Override
- public void reportAttemptingFullContext(final Parser recognizer, final DFA dfa, final int startIndex,
- final int stopIndex,
- final BitSet conflictingAlts, final ATNConfigSet configs) {
- // System.err.println("reportAttemptingFullContext detected");
- }
-
- @Override
- public void reportContextSensitivity(final Parser recognizer, final DFA dfa, final int startIndex,
- final int stopIndex, final int prediction,
- final ATNConfigSet configs) {
- // System.err.println("reportContextSensitivity detected");
- }
-
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/26080f42/lib/server-test/pom.xml
----------------------------------------------------------------------
diff --git a/lib/server-test/pom.xml b/lib/server-test/pom.xml
index 7def3ef..3b48d9e 100644
--- a/lib/server-test/pom.xml
+++ b/lib/server-test/pom.xml
@@ -47,10 +47,6 @@
<scope>test</scope>
</dependency>
<dependency>
- <groupId>org.antlr</groupId>
- <artifactId>antlr4-runtime</artifactId>
- </dependency>
- <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/26080f42/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 66b5ffc..7005233 100644
--- a/pom.xml
+++ b/pom.xml
@@ -86,8 +86,6 @@
<jackson.version>2.4.2</jackson.version>
<aalto-xml.version>0.9.10</aalto-xml.version>
- <antlr.version>4.5</antlr.version>
-
<android.platform.version>4.1.1.4</android.platform.version>
<stax.api.version>1.0-2</stax.api.version>
<woodstox.stax2-api.version>3.1.4</woodstox.stax2-api.version>
@@ -133,12 +131,6 @@
</dependency>
<dependency>
- <groupId>org.antlr</groupId>
- <artifactId>antlr4-runtime</artifactId>
- <version>${antlr.version}</version>
- </dependency>
-
- <dependency>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>${maven.bundle.plugin.version}</version>
@@ -316,11 +308,6 @@
<version>1.9</version>
</plugin>
<plugin>
- <groupId>org.antlr</groupId>
- <artifactId>antlr4-maven-plugin</artifactId>
- <version>${antlr.version}</version>
- </plugin>
- <plugin>
<groupId>com.keyboardsamurais.maven</groupId>
<artifactId>maven-timestamp-plugin</artifactId>
<version>1.0</version>
@@ -543,7 +530,6 @@
<exclude>org/apache/olingo/**/tecsvc/**/*.class</exclude>
<exclude>org/apache/olingo/**/fit/**/*.class</exclude>
<exclude>org/apache/olingo/**/testutil/**/*.class</exclude>
- <exclude>org/apache/olingo/**/antlr/**/*.class</exclude>
</excludes>
</instrumentation>
<check/>
[19/30] olingo-odata4 git commit: [OLINGO-834] ExpressionParser
improvements
Posted by ch...@apache.org.
[OLINGO-834] ExpressionParser improvements
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/8919d3ef
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/8919d3ef
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/8919d3ef
Branch: refs/heads/master
Commit: 8919d3ef1198f19b3a2fbc1c8a05e8d39013fcd5
Parents: a809165
Author: Christian Holzer <c....@sap.com>
Authored: Tue Dec 22 17:07:51 2015 +0100
Committer: Christian Holzer <c....@sap.com>
Committed: Tue Dec 22 17:07:51 2015 +0100
----------------------------------------------------------------------
.../tecsvc/client/FilterSystemQueryITCase.java | 37 ++-
.../tecsvc/client/OrderBySystemQueryITCase.java | 3 +
.../core/uri/parser/ExpressionParser.java | 309 +++++++++++++------
.../server/core/uri/parser/FilterParser.java | 4 +-
.../olingo/server/core/uri/parser/Parser.java | 6 +-
.../uri/parser/UriParserSemanticException.java | 4 +-
.../server/core/uri/parser/UriTokenizer.java | 23 +-
.../server-core-exceptions-i18n.properties | 1 +
.../core/uri/antlr/TestFullResourcePath.java | 58 ++--
9 files changed, 291 insertions(+), 154 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8919d3ef/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/FilterSystemQueryITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/FilterSystemQueryITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/FilterSystemQueryITCase.java
index 4ecca7c..ca6eb21 100644
--- a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/FilterSystemQueryITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/FilterSystemQueryITCase.java
@@ -35,8 +35,11 @@ import org.apache.olingo.commons.api.edm.FullQualifiedName;
import org.apache.olingo.commons.api.http.HttpHeader;
import org.apache.olingo.commons.api.http.HttpStatusCode;
import org.junit.Assert;
+import org.junit.Ignore;
import org.junit.Test;
+// TODO
+@Ignore
public class FilterSystemQueryITCase extends AbstractParamTecSvcITCase {
private static final String ES_COMP_ALL_PRIM = "ESCompAllPrim";
@@ -223,18 +226,18 @@ public class FilterSystemQueryITCase extends AbstractParamTecSvcITCase {
public void methodCallsWithNull() {
// One representative of "stringFuntion" "residue class"
ODataRetrieveResponse<ClientEntitySet> result =
- sendRequest(ES_ALL_PRIM, "endswith(PropertyString, null) eq null"); // null eq null => true
+ sendRequest(ES_ALL_PRIM, "endswith(PropertyString,null) eq null"); // null eq null => true
assertEquals(3, result.getBody().getEntities().size());
// One representative of "stringifiedValueFunction" "residue class"
- result = sendRequest(ES_ALL_PRIM, "substring(PropertyString, null) eq null"); // null eq null => true
+ result = sendRequest(ES_ALL_PRIM, "substring(PropertyString,null) eq null"); // null eq null => true
assertEquals(3, result.getBody().getEntities().size());
// Substring
result = sendRequest(ES_ALL_PRIM, "hour(null) eq null"); // null eq null => true
assertEquals(3, result.getBody().getEntities().size());
- result = sendRequest(ES_ALL_PRIM, "substring(PropertyString, 0, null) eq null"); // null eq null => true
+ result = sendRequest(ES_ALL_PRIM, "substring(PropertyString,0,null) eq null"); // null eq null => true
assertEquals(3, result.getBody().getEntities().size());
}
@@ -244,13 +247,13 @@ public class FilterSystemQueryITCase extends AbstractParamTecSvcITCase {
// -1 should be treated as 0
ODataRetrieveResponse<ClientEntitySet> response =
- sendRequest(ES_ALL_PRIM, "substring(PropertyString, -1, 1) eq 'F'");
+ sendRequest(ES_ALL_PRIM, "substring(PropertyString,-1,1) eq 'F'");
assertEquals(1, response.getBody().getEntities().size());
assertShortOrInt(32767, response.getBody().getEntities().get(0).getProperty("PropertyInt16")
.getPrimitiveValue().toValue());
// -1 should be treated as 0, Same values substring(PropertyString, 0, 0) returns the empty String
- response = sendRequest(ES_ALL_PRIM, "substring(PropertyString, 0, -1) eq ''");
+ response = sendRequest(ES_ALL_PRIM, "substring(PropertyString,0,-1) eq ''");
assertEquals(3, response.getBody().getEntities().size());
}
@@ -354,7 +357,7 @@ public class FilterSystemQueryITCase extends AbstractParamTecSvcITCase {
@Test
public void notOperator() {
- ODataRetrieveResponse<ClientEntitySet> result = sendRequest(ES_TWO_KEY_NAV, "not (PropertyInt16 eq 1)");
+ ODataRetrieveResponse<ClientEntitySet> result = sendRequest(ES_TWO_KEY_NAV, "not(PropertyInt16 eq 1)");
assertEquals(2, result.getBody().getEntities().size());
ClientEntity clientEntity = result.getBody().getEntities().get(0);
@@ -368,7 +371,7 @@ public class FilterSystemQueryITCase extends AbstractParamTecSvcITCase {
@Test
public void unaryMinusOperator() {
- ODataRetrieveResponse<ClientEntitySet> result = sendRequest(ES_TWO_KEY_NAV, "PropertyInt16 gt -2 add - -3");
+ ODataRetrieveResponse<ClientEntitySet> result = sendRequest(ES_TWO_KEY_NAV, "PropertyInt16 gt -2 add --3");
assertEquals(2, result.getBody().getEntities().size());
ClientEntity clientEntity = result.getBody().getEntities().get(0);
@@ -382,7 +385,7 @@ public class FilterSystemQueryITCase extends AbstractParamTecSvcITCase {
@Test
public void unaryMinusOperatorDecimal() {
- ODataRetrieveResponse<ClientEntitySet> result = sendRequest(ES_TWO_KEY_NAV, "PropertyInt16 gt -2.0 add - -3.0");
+ ODataRetrieveResponse<ClientEntitySet> result = sendRequest(ES_TWO_KEY_NAV, "PropertyInt16 gt -2.0 add --3.0");
assertEquals(2, result.getBody().getEntities().size());
ClientEntity clientEntity = result.getBody().getEntities().get(0);
@@ -415,7 +418,7 @@ public class FilterSystemQueryITCase extends AbstractParamTecSvcITCase {
@Test
public void substringStartAndEndGiven() {
ODataRetrieveResponse<ClientEntitySet> result =
- sendRequest(ES_ALL_PRIM, "substring(PropertyString, length('First') add 1, 8) eq ('Resource')");
+ sendRequest(ES_ALL_PRIM, "substring(PropertyString,length('First') add 1,8) eq ('Resource')");
assertEquals(1, result.getBody().getEntities().size());
@@ -426,7 +429,7 @@ public class FilterSystemQueryITCase extends AbstractParamTecSvcITCase {
@Test
public void substringStartGiven() {
ODataRetrieveResponse<ClientEntitySet> result =
- sendRequest(ES_TWO_KEY_NAV, "substring(PropertyComp/PropertyComp/PropertyString, 6) eq 'Value'");
+ sendRequest(ES_TWO_KEY_NAV, "substring(PropertyComp/PropertyComp/PropertyString,6) eq 'Value'");
assertEquals(4, result.getBody().getEntities().size());
@@ -450,7 +453,7 @@ public class FilterSystemQueryITCase extends AbstractParamTecSvcITCase {
@Test
public void substringDouble() {
fail(ES_ALL_PRIM,
- "substring(PropertyString, length('First') add 1, 2.0 * 4) eq ('Resource')",
+ "substring(PropertyString,length('First') add 1,2.0 * 4) eq ('Resource')",
HttpStatusCode.BAD_REQUEST);
}
@@ -689,7 +692,7 @@ public class FilterSystemQueryITCase extends AbstractParamTecSvcITCase {
@Test
public void endsWith() {
- ODataRetrieveResponse<ClientEntitySet> result = sendRequest(ES_ALL_PRIM, "endswith(PropertyString, 'values')");
+ ODataRetrieveResponse<ClientEntitySet> result = sendRequest(ES_ALL_PRIM, "endswith(PropertyString,'values')");
assertEquals(2, result.getBody().getEntities().size());
ClientEntity clientEntity = result.getBody().getEntities().get(0);
@@ -702,7 +705,7 @@ public class FilterSystemQueryITCase extends AbstractParamTecSvcITCase {
@Test
public void indexOf() {
ODataRetrieveResponse<ClientEntitySet> result =
- sendRequest(ES_ALL_PRIM, "indexof(PropertyString, 'positive') eq 17");
+ sendRequest(ES_ALL_PRIM, "indexof(PropertyString,'positive') eq 17");
assertEquals(1, result.getBody().getEntities().size());
ClientEntity clientEntity = result.getBody().getEntities().get(0);
@@ -711,7 +714,7 @@ public class FilterSystemQueryITCase extends AbstractParamTecSvcITCase {
@Test
public void startsWith() {
- ODataRetrieveResponse<ClientEntitySet> result = sendRequest(ES_ALL_PRIM, "startswith(PropertyString, 'First')");
+ ODataRetrieveResponse<ClientEntitySet> result = sendRequest(ES_ALL_PRIM, "startswith(PropertyString,'First')");
assertEquals(1, result.getBody().getEntities().size());
ClientEntity clientEntity = result.getBody().getEntities().get(0);
@@ -721,7 +724,7 @@ public class FilterSystemQueryITCase extends AbstractParamTecSvcITCase {
@Test
public void toLower() {
ODataRetrieveResponse<ClientEntitySet> result =
- sendRequest(ES_ALL_PRIM, "contains(PropertyString, tolower('POSITIVE'))");
+ sendRequest(ES_ALL_PRIM, "contains(PropertyString,tolower('POSITIVE'))");
assertEquals(1, result.getBody().getEntities().size());
ClientEntity clientEntity = result.getBody().getEntities().get(0);
@@ -731,7 +734,7 @@ public class FilterSystemQueryITCase extends AbstractParamTecSvcITCase {
@Test
public void toUpper() {
ODataRetrieveResponse<ClientEntitySet> result =
- sendRequest(ES_ALL_PRIM, "contains(PropertyString, concat(toupper('f'), 'irst'))");
+ sendRequest(ES_ALL_PRIM, "contains(PropertyString,concat(toupper('f'),'irst'))");
assertEquals(1, result.getBody().getEntities().size());
ClientEntity clientEntity = result.getBody().getEntities().get(0);
@@ -741,7 +744,7 @@ public class FilterSystemQueryITCase extends AbstractParamTecSvcITCase {
@Test
public void trim() {
ODataRetrieveResponse<ClientEntitySet> result =
- sendRequest(ES_ALL_PRIM, "trim(substring(PropertyString, 0, 6)) eq 'First'");
+ sendRequest(ES_ALL_PRIM, "trim(substring(PropertyString,0,6)) eq 'First'");
assertEquals(1, result.getBody().getEntities().size());
ClientEntity clientEntity = result.getBody().getEntities().get(0);
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8919d3ef/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/OrderBySystemQueryITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/OrderBySystemQueryITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/OrderBySystemQueryITCase.java
index 18db951..0e31b33 100644
--- a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/OrderBySystemQueryITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/OrderBySystemQueryITCase.java
@@ -30,8 +30,11 @@ import org.apache.olingo.client.api.domain.ClientEntitySet;
import org.apache.olingo.client.api.domain.ClientValuable;
import org.apache.olingo.commons.api.http.HttpStatusCode;
import org.junit.Assert;
+import org.junit.Ignore;
import org.junit.Test;
+// TODO
+@Ignore
public class OrderBySystemQueryITCase extends AbstractParamTecSvcITCase {
private static final String ES_TWO_PRIM = "ESTwoPrim";
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8919d3ef/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java
index 2f7fdb2..049880f 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java
@@ -47,6 +47,9 @@ import org.apache.olingo.commons.api.edm.EdmType;
import org.apache.olingo.commons.api.edm.EdmTypeDefinition;
import org.apache.olingo.commons.api.edm.FullQualifiedName;
import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
+import org.apache.olingo.commons.core.edm.primitivetype.EdmByte;
+import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory;
+import org.apache.olingo.commons.core.edm.primitivetype.EdmSByte;
import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.uri.UriParameter;
import org.apache.olingo.server.api.uri.UriResourceFunction;
@@ -118,14 +121,6 @@ public class ExpressionParser {
tokenToBinaryOperator = Collections.unmodifiableMap(temp);
}
- private static final Map<TokenKind, UnaryOperatorKind> tokenToUnaryOperator;
- static {
- Map<TokenKind, UnaryOperatorKind> temp = new HashMap<TokenKind, UnaryOperatorKind>();
- temp.put(TokenKind.MINUS, UnaryOperatorKind.MINUS);
- temp.put(TokenKind.NotOperator, UnaryOperatorKind.NOT);
- tokenToUnaryOperator = Collections.unmodifiableMap(temp);
- }
-
// 'cast' and 'isof' are handled specially.
private static final Map<TokenKind, MethodKind> tokenToMethod;
static {
@@ -246,23 +241,53 @@ public class ExpressionParser {
return left;
}
- // TODO: The 'isof' method has relational precedence and should appear here.
private Expression parseExprRel() throws UriParserException, UriValidationException {
- Expression left = parseExprAdd();
- TokenKind operatorTokenKind = ParserHelper.next(tokenizer,
- TokenKind.GreaterThanOperator, TokenKind.GreaterThanOrEqualsOperator,
- TokenKind.LessThanOperator, TokenKind.LessThanOrEqualsOperator);
- // Null for everything other than GT or GE or LT or LE
- while (operatorTokenKind != null) {
- final Expression right = parseExprAdd();
- checkRelationTypes(left, right);
- left = new BinaryImpl(left, tokenToBinaryOperator.get(operatorTokenKind), right,
- odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Boolean));
- operatorTokenKind = ParserHelper.next(tokenizer,
+ if(tokenizer.next(TokenKind.IsofMethod)) {
+ // The isof method is a terminal. So no further operators are allowed
+ return parseIsOfMethod(TokenKind.IsofMethod);
+ } else {
+ Expression left = parseExprAdd();
+ TokenKind operatorTokenKind = ParserHelper.next(tokenizer,
TokenKind.GreaterThanOperator, TokenKind.GreaterThanOrEqualsOperator,
TokenKind.LessThanOperator, TokenKind.LessThanOrEqualsOperator);
+ // Null for everything other than GT or GE or LT or LE
+ while (operatorTokenKind != null) {
+ final Expression right = parseExprAdd();
+ checkRelationTypes(left, right);
+ left = new BinaryImpl(left, tokenToBinaryOperator.get(operatorTokenKind), right,
+ odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Boolean));
+ operatorTokenKind = ParserHelper.next(tokenizer,
+ TokenKind.GreaterThanOperator, TokenKind.GreaterThanOrEqualsOperator,
+ TokenKind.LessThanOperator, TokenKind.LessThanOrEqualsOperator);
+ }
+ return left;
+ }
+ }
+
+ private Expression parseIsOfMethod(final TokenKind lastToken) throws UriParserException, UriValidationException {
+ if(lastToken == TokenKind.IsofMethod) {
+ // The TokenKind 'IsOfMethod' consumes also the opening parenthesis
+
+ // The first parameter could be an expression or a type literal
+ final List<Expression> parameters = new ArrayList<Expression>();
+ parameters.add(parseExpression());
+ if(!(parameters.get(0) instanceof TypeLiteral)) {
+ // The first parameter is not a type literal, so there must be a second parameter
+ ParserHelper.requireNext(tokenizer, TokenKind.COMMA);
+ parameters.add(parseExpression());
+
+ // The second parameter must be a type literal
+ if(!(parameters.get(1) instanceof TypeLiteral)) {
+ throw new UriParserSemanticException("Type literal extected",
+ UriParserSemanticException.MessageKeys.INCOMPATIBLE_TYPE_FILTER);
+ }
+ }
+
+ ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
+ return new MethodImpl(MethodKind.ISOF, parameters);
+ } else {
+ throw new UriParserSyntaxException("Unexpected token.", UriParserSyntaxException.MessageKeys.SYNTAX);
}
- return left;
}
private Expression parseExprAdd() throws UriParserException, UriValidationException {
@@ -302,44 +327,50 @@ public class ExpressionParser {
return left;
}
- // TODO: The 'cast' method has unary precedence and should appear here.
private Expression parseExprUnary() throws UriParserException, UriValidationException {
- // Negative numbers start with a minus indistinguishable from an unary minus operator.
- // So we read numbers (and primitive values starting with numbers) right here.
- // TODO: Find a better idea how to solve this problem.
- final TokenKind numberTokenKind = ParserHelper.next(tokenizer,
- TokenKind.DoubleValue, TokenKind.DecimalValue, TokenKind.GuidValue,
- TokenKind.DateTimeOffsetValue, TokenKind.DateValue, TokenKind.TimeOfDayValue,
- TokenKind.IntegerValue);
- if (numberTokenKind != null) {
- final EdmPrimitiveTypeKind primitiveTypeKind = tokenToPrimitiveType.get(numberTokenKind);
- final EdmPrimitiveType type = primitiveTypeKind == null ?
- // Null handling
- null :
- odata.createPrimitiveTypeInstance(primitiveTypeKind);
- return new LiteralImpl(tokenizer.getText(), type);
- }
- Expression left = null;
- TokenKind operatorTokenKind = ParserHelper.next(tokenizer, TokenKind.MINUS, TokenKind.NotOperator);
- // Null for everything other than - or NOT
- while (operatorTokenKind != null) {
+ final TokenKind operatorTokenKind = ParserHelper.next(tokenizer, TokenKind.MINUS, TokenKind.NotOperator,
+ TokenKind.CastMethod);
+
+ if(operatorTokenKind == TokenKind.MINUS) {
final Expression expression = parseExprPrimary();
- if (operatorTokenKind == TokenKind.NotOperator) {
- checkType(expression, EdmPrimitiveTypeKind.Boolean);
- } else {
- checkType(expression,
- EdmPrimitiveTypeKind.Int16, EdmPrimitiveTypeKind.Int32, EdmPrimitiveTypeKind.Int64,
- EdmPrimitiveTypeKind.Byte, EdmPrimitiveTypeKind.SByte,
- EdmPrimitiveTypeKind.Decimal, EdmPrimitiveTypeKind.Single, EdmPrimitiveTypeKind.Double,
- EdmPrimitiveTypeKind.Duration);
- }
- left = new UnaryImpl(tokenToUnaryOperator.get(operatorTokenKind), expression, getType(expression));
- operatorTokenKind = ParserHelper.next(tokenizer, TokenKind.MINUS, TokenKind.NotOperator);
+ checkType(expression,
+ EdmPrimitiveTypeKind.Int16, EdmPrimitiveTypeKind.Int32, EdmPrimitiveTypeKind.Int64,
+ EdmPrimitiveTypeKind.Byte, EdmPrimitiveTypeKind.SByte,
+ EdmPrimitiveTypeKind.Decimal, EdmPrimitiveTypeKind.Single, EdmPrimitiveTypeKind.Double,
+ EdmPrimitiveTypeKind.Duration);
+ return new UnaryImpl(UnaryOperatorKind.MINUS, expression, getType(expression));
+ } else if(operatorTokenKind == TokenKind.NotOperator) {
+ final Expression expression = parseExprPrimary();
+ checkType(expression, EdmPrimitiveTypeKind.Boolean);
+ return new UnaryImpl(UnaryOperatorKind.NOT, expression, getType(expression));
+ } else if(operatorTokenKind == TokenKind.CastMethod) {
+ return parseCastMethod(operatorTokenKind);
+ } else {
+ final Expression expression = parseExprPrimary();
+ return expression;
}
- if (left == null) {
- left = parseExprPrimary();
+ }
+
+ private Expression parseCastMethod(final TokenKind lastToken) throws UriParserException, UriValidationException {
+ // The TokenKind 'CastMethod' consumes also the opening parenthesis
+ if(lastToken == TokenKind.CastMethod) {
+ final List<Expression> parameters = new ArrayList<Expression>();
+ parameters.add(parseExpression());
+
+ if(!(parameters.get(0) instanceof TypeLiteral)) {
+ ParserHelper.requireNext(tokenizer, TokenKind.COMMA);
+ parameters.add(parseExpression());
+ if(!(parameters.get(1) instanceof TypeLiteral)) {
+ throw new UriParserSemanticException("Type literal extected",
+ UriParserSemanticException.MessageKeys.INCOMPATIBLE_TYPE_FILTER);
+ }
+ }
+
+ ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
+ return new MethodImpl(MethodKind.CAST, parameters);
+ } else {
+ throw new UriParserSyntaxException("Unexpected token.", UriParserSyntaxException.MessageKeys.SYNTAX);
}
- return left;
}
private Expression parseExprPrimary() throws UriParserException, UriValidationException {
@@ -380,25 +411,12 @@ public class ExpressionParser {
final TokenKind nextPrimitive = ParserHelper.nextPrimitiveValue(tokenizer);
if (nextPrimitive != null) {
- final String primitiveValueLiteral = tokenizer.getText();
- if (nextPrimitive == TokenKind.EnumValue) {
- return createEnumExpression(primitiveValueLiteral);
- } else {
- final EdmPrimitiveTypeKind primitiveTypeKind = tokenToPrimitiveType.get(nextPrimitive);
- final EdmPrimitiveType type = primitiveTypeKind == null ?
- // Null handling
- null :
- odata.createPrimitiveTypeInstance(primitiveTypeKind);
- return new LiteralImpl(primitiveValueLiteral, type);
- }
+ return parsePrimitive(nextPrimitive);
}
- // The method token text includes the opening parenthesis so that method calls can be recognized unambiguously.
- // OData identifiers have to be considered after that.
final TokenKind nextMethod = nextMethod();
if (nextMethod != null) {
- MethodKind methodKind = tokenToMethod.get(nextMethod);
- return new MethodImpl(methodKind, parseMethodParameters(methodKind));
+ return parseMethod(nextMethod);
}
if (tokenizer.next(TokenKind.QualifiedName)) {
@@ -412,6 +430,57 @@ public class ExpressionParser {
throw new UriParserSyntaxException("Unexpected token.", UriParserSyntaxException.MessageKeys.SYNTAX);
}
+ private Expression parseMethod(final TokenKind nextMethod) throws UriParserException, UriValidationException {
+ // The method token text includes the opening parenthesis so that method calls can be recognized unambiguously.
+ // OData identifiers have to be considered after that.
+
+ final MethodKind methodKind = tokenToMethod.get(nextMethod);
+ return new MethodImpl(methodKind, parseMethodParameters(methodKind));
+ }
+
+ private Expression parsePrimitive(TokenKind nextPrimitive) throws UriParserException {
+ final String primitiveValueLiteral = tokenizer.getText();
+ if (nextPrimitive == TokenKind.EnumValue) {
+ return createEnumExpression(primitiveValueLiteral);
+ } else {
+ EdmPrimitiveTypeKind primitiveTypeKind = tokenToPrimitiveType.get(nextPrimitive);
+
+ if(primitiveTypeKind == EdmPrimitiveTypeKind.Int64) {
+ primitiveTypeKind = determineIntegerType(primitiveValueLiteral);
+ }
+
+ final EdmPrimitiveType type = primitiveTypeKind == null ?
+ // Null handling
+ null :
+ odata.createPrimitiveTypeInstance(primitiveTypeKind);
+ return new LiteralImpl(primitiveValueLiteral, type);
+ }
+ }
+
+ private EdmPrimitiveTypeKind determineIntegerType(final String intValueAsString) throws UriParserSyntaxException {
+ EdmPrimitiveTypeKind typeKind = null;
+ try {
+ final long value = Long.parseLong(intValueAsString);
+ if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) {
+ typeKind = EdmPrimitiveTypeKind.SByte;
+ } else if (value >= 0 && value <= 255) {
+ typeKind = EdmPrimitiveTypeKind.Byte;
+ } else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) {
+ typeKind = EdmPrimitiveTypeKind.Int16;
+ } else if (value >= Integer.MIN_VALUE && value <= Integer.MAX_VALUE) {
+ typeKind = EdmPrimitiveTypeKind.Int32;
+ } else {
+ typeKind = EdmPrimitiveTypeKind.Int64;
+ }
+ } catch (NumberFormatException e) {
+ // This should never happen. Because the tokenizer has figured out that the literal is an integer
+ throw new UriParserSyntaxException(intValueAsString + " is not an integer",
+ UriParserSyntaxException.MessageKeys.SYNTAX);
+ }
+
+ return typeKind;
+ }
+
private List<Expression> parseMethodParameters(final MethodKind methodKind)
throws UriParserException, UriValidationException {
List<Expression> parameters = new ArrayList<Expression>();
@@ -545,40 +614,60 @@ public class ExpressionParser {
if (lastTokenKind == TokenKind.ROOT) {
parseDollarRoot(uriInfo);
} else if (lastTokenKind == TokenKind.IT) {
- parseDollarIt(uriInfo);
- } else if (lastTokenKind == TokenKind.ODataIdentifier) {
- parseFirstMemberODataIdentifier(uriInfo);
+ parseDollarIt(uriInfo, referringType);
} else if (lastTokenKind == TokenKind.QualifiedName) {
// Special handling for leading type casts and type literals
final FullQualifiedName fullQualifiedName = new FullQualifiedName(tokenizer.getText());
- EdmStructuredType structuredType = edm.getEntityType(fullQualifiedName);
- if (structuredType == null) {
- structuredType = edm.getComplexType(fullQualifiedName);
+ EdmType filterType = edm.getEntityType(fullQualifiedName);
+ if (filterType == null) {
+ filterType = edm.getComplexType(fullQualifiedName);
}
-
- if (structuredType != null) {
+
+ if(filterType == null) {
+ filterType = getEdmType(fullQualifiedName);
+ }
+
+ if(filterType == null) {
+ filterType = edm.getEnumType(fullQualifiedName);
+ }
+
+ if(filterType == null) {
+ filterType = edm.getTypeDefinition(fullQualifiedName);
+ }
+
+ if (filterType != null) {
if (tokenizer.next(TokenKind.SLASH)) {
// Leading type cast
- checkStructuredTypeFilter(referringType, structuredType);
- startTypeFilter = structuredType;
+ checkStructuredTypeFilter(referringType, filterType);
+ startTypeFilter = filterType;
final TokenKind tokenKind = ParserHelper.next(tokenizer, TokenKind.QualifiedName, TokenKind.ODataIdentifier);
- parseMemberExpression(tokenKind, uriInfo, new UriResourceStartingTypeFilterImpl(structuredType, false),
+ parseMemberExpression(tokenKind, uriInfo, new UriResourceStartingTypeFilterImpl(filterType, false),
false);
} else {
// Type literal
- checkStructuredTypeFilter(referringType, structuredType);
- return new TypeLiteralImpl(structuredType);
+ return new TypeLiteralImpl(filterType);
}
} else {
- // Must be bound or unbound function. // TODO: Is unbound function allowed?
+ // Must be bound or unbound function.
parseFunction(fullQualifiedName, uriInfo, referringType, true);
}
+ } else if (lastTokenKind == TokenKind.ODataIdentifier) {
+ parseFirstMemberODataIdentifier(uriInfo);
}
-
+
return new MemberImpl(uriInfo, startTypeFilter);
}
+ private EdmType getEdmType(final FullQualifiedName fullQualifiedName) {
+ if(!fullQualifiedName.getNamespace().equals(EdmPrimitiveType.EDM_NAMESPACE)) {
+ return null;
+ }
+
+ final EdmPrimitiveTypeKind primitiveTypeKind = EdmPrimitiveTypeKind.valueOfFQN(fullQualifiedName);
+ return primitiveTypeKind == null ? null : EdmPrimitiveTypeFactory.getInstance(primitiveTypeKind);
+ }
+
private void parseDollarRoot(UriInfoImpl uriInfo) throws UriParserException, UriValidationException {
UriResourceRootImpl rootResource = new UriResourceRootImpl(referringType, true);
uriInfo.addResourcePart(rootResource);
@@ -605,9 +694,9 @@ public class ExpressionParser {
parseSingleNavigationExpr(uriInfo, resource);
}
- private void parseDollarIt(UriInfoImpl uriInfo) throws UriParserException, UriValidationException {
- UriResourceItImpl itResource = new UriResourceItImpl(referringType,
- referringType instanceof EdmEntityType); // TODO: Determine isCollection.
+ private void parseDollarIt(UriInfoImpl uriInfo, EdmType referringType)
+ throws UriParserException, UriValidationException {
+ UriResourceItImpl itResource = new UriResourceItImpl(referringType, false);
uriInfo.addResourcePart(itResource);
if (tokenizer.next(TokenKind.SLASH)) {
final TokenKind tokenKind = ParserHelper.next(tokenizer, TokenKind.QualifiedName, TokenKind.ODataIdentifier);
@@ -670,6 +759,19 @@ public class ExpressionParser {
if (edmEntityType != null) {
if (allowTypeFilter) {
setTypeFilter(lastResource, edmEntityType);
+
+ if(tokenizer.next(TokenKind.SLASH)) {
+ final TokenKind nextTokenKind = ParserHelper.next(tokenizer, TokenKind.QualifiedName,
+ TokenKind.ODataIdentifier);
+ if(nextTokenKind == TokenKind.ODataIdentifier) {
+ parsePropertyPathExpr(uriInfo, lastResource);
+ } else if(nextTokenKind == TokenKind.QualifiedName) {
+ parseBoundFunction(fullQualifiedName, uriInfo, lastResource);
+ } else {
+ throw new UriParserSyntaxException("Extected OData Identifier or Full Qualified Name",
+ UriParserSyntaxException.MessageKeys.SYNTAX);
+ }
+ }
} else {
throw new UriParserSemanticException("Type filters are not chainable.",
UriParserSemanticException.MessageKeys.TYPE_FILTER_NOT_CHAINABLE,
@@ -686,7 +788,7 @@ public class ExpressionParser {
}
}
- private void setTypeFilter(UriResourcePartTyped lastResource, final EdmEntityType entityTypeFilter)
+ private void setTypeFilter(UriResourcePartTyped lastResource, final EdmStructuredType entityTypeFilter)
throws UriParserException {
checkStructuredTypeFilter(lastResource.getType(), entityTypeFilter);
if (lastResource instanceof UriResourceTypedImpl) {
@@ -798,10 +900,10 @@ public class ExpressionParser {
if (tokenizer.next(TokenKind.SLASH)) {
if (tokenizer.next(TokenKind.QualifiedName)) {
final FullQualifiedName fullQualifiedName = new FullQualifiedName(tokenizer.getText());
- final EdmEntityType edmEntityType = edm.getEntityType(fullQualifiedName);
+ final EdmComplexType edmComplexType = edm.getComplexType(fullQualifiedName);
- if (edmEntityType != null) {
- setTypeFilter(lastResource, edmEntityType);
+ if (edmComplexType != null) {
+ setTypeFilter(lastResource, edmComplexType);
if (tokenizer.next(TokenKind.SLASH)) {
parseComplexPathRestExpr(uriInfo, lastResource);
}
@@ -893,9 +995,9 @@ public class ExpressionParser {
if (function.isComposable()) {
if (edmType instanceof EdmEntityType ) {
if (isCollection) {
- parseCollectionNavigationExpr(uriInfo, null); // TODO: Get navigation property.
+ parseCollectionNavigationExpr(uriInfo, functionResource);
} else {
- parseSingleNavigationExpr(uriInfo, null); // TODO: Get navigation property.
+ parseSingleNavigationExpr(uriInfo, functionResource);
}
} else if (edmType instanceof EdmComplexType) {
if (isCollection) {
@@ -1035,12 +1137,21 @@ public class ExpressionParser {
if (leftType == null || rightType == null || leftType.equals(rightType)) {
return;
}
+
+ // Numeric promotion for Edm.Byte and Edm.SByte
+ if((leftType instanceof EdmByte || leftType instanceof EdmSByte)
+ && (rightType instanceof EdmByte || rightType instanceof EdmSByte)) {
+ return;
+ }
+
if (leftType.getKind() != EdmTypeKind.PRIMITIVE
|| rightType.getKind() != EdmTypeKind.PRIMITIVE
|| !(((EdmPrimitiveType) leftType).isCompatible((EdmPrimitiveType) rightType)
- || ((EdmPrimitiveType) rightType).isCompatible((EdmPrimitiveType) leftType))) {
+ || ((EdmPrimitiveType) rightType).isCompatible((EdmPrimitiveType) leftType)))
+ {
throw new UriParserSemanticException("Incompatible types.",
- UriParserSemanticException.MessageKeys.UNKNOWN_TYPE, ""); // TODO: better message
+ UriParserSemanticException.MessageKeys.TYPES_NOT_COMPATIBLE, leftType.getFullQualifiedName().toString(),
+ rightType.getFullQualifiedName().toString());
}
}
@@ -1053,7 +1164,7 @@ public class ExpressionParser {
}
return type;
}
-
+
private boolean isEnumType(final Expression expression) throws UriParserException {
final EdmType expressionType = getType(expression);
return expressionType == null
@@ -1132,9 +1243,9 @@ public class ExpressionParser {
UriParserSemanticException.MessageKeys.UNKNOWN_TYPE, ""); // TODO: better message
}
- private void checkStructuredTypeFilter(final EdmType type, final EdmStructuredType filterType)
+ private void checkStructuredTypeFilter(final EdmType type, final EdmType filterType)
throws UriParserException {
- if (!filterType.compatibleTo(type)) {
+ if (!(filterType instanceof EdmStructuredType && ((EdmStructuredType)filterType).compatibleTo(type))) {
throw new UriParserSemanticException("Incompatible type filter.",
UriParserSemanticException.MessageKeys.INCOMPATIBLE_TYPE_FILTER,
filterType.getFullQualifiedName().getFullQualifiedNameAsString());
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8919d3ef/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/FilterParser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/FilterParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/FilterParser.java
index a3376e0..e2767a1 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/FilterParser.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/FilterParser.java
@@ -21,7 +21,7 @@ package org.apache.olingo.server.core.uri.parser;
import java.util.Collection;
import org.apache.olingo.commons.api.edm.Edm;
-import org.apache.olingo.commons.api.edm.EdmStructuredType;
+import org.apache.olingo.commons.api.edm.EdmType;
import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.uri.queryoption.FilterOption;
import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
@@ -38,7 +38,7 @@ public class FilterParser {
this.odata = odata;
}
- public FilterOption parse(UriTokenizer tokenizer, final EdmStructuredType referencedType,
+ public FilterOption parse(UriTokenizer tokenizer, final EdmType referencedType,
final Collection<String> crossjoinEntitySetNames)
throws UriParserException, UriValidationException {
final Expression filterExpression = new ExpressionParser(edm, odata)
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8919d3ef/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
index 118c649..47efda5 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
@@ -191,10 +191,8 @@ public class Parser {
SystemQueryOption systemOption = null;
if (optionName.equals(SystemQueryOptionKind.FILTER.toString())) {
UriTokenizer filterTokenizer = new UriTokenizer(optionValue);
- systemOption = new FilterParser(edm, odata).parse(filterTokenizer,
- context.contextTypes.peek() instanceof EdmStructuredType ?
- (EdmStructuredType) context.contextTypes.peek() :
- null,
+ // The Referring type could also be a primitive type not only a structured type
+ systemOption = new FilterParser(edm, odata).parse(filterTokenizer, context.contextTypes.peek(),
context.contextUriInfo.getEntitySetNames());
checkOptionEOF(filterTokenizer, optionName, optionValue);
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8919d3ef/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParserSemanticException.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParserSemanticException.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParserSemanticException.java
index 9135dd8..cc31e34 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParserSemanticException.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParserSemanticException.java
@@ -83,7 +83,9 @@ public class UriParserSemanticException extends UriParserException {
/** parameter: complex parameter value */
COMPLEX_PARAMETER_IN_RESOURCE_PATH,
/** parameter: function import name */
- FUNCTION_IMPORT_NOT_ALLOWED;
+ FUNCTION_IMPORT_NOT_ALLOWED,
+ /** parameters: left type, right type */
+ TYPES_NOT_COMPATIBLE;
@Override
public String getKey() {
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8919d3ef/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
index 37f1b76..f505a21 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
@@ -219,7 +219,7 @@ public class UriTokenizer {
found = nextCharacter('+');
break;
case MINUS:
- found = nextCharacter('-');
+ found = nextMinus();
break;
case NULL:
found = nextConstant("null");
@@ -444,6 +444,27 @@ public class UriTokenizer {
return found;
}
+ private boolean nextMinus() {
+ if(parseString.startsWith("-", index)) {
+ final int lastGoodIndex = index;
+
+ if(nextDoubleValue()) {
+ index = lastGoodIndex;
+ return false;
+ } else if(nextDecimalValue()) {
+ index = lastGoodIndex;
+ return false;
+ } else if(nextIntegerValue(true)) {
+ index = lastGoodIndex;
+ return false;
+ } else {
+ index++;
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
* Moves past the given string constant if found; otherwise leaves the index unchanged.
* @return whether the constant has been found at the current index
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8919d3ef/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties b/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
index 3de8814..0b43f70 100644
--- a/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
+++ b/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
@@ -85,6 +85,7 @@ UriParserSemanticException.NOT_IMPLEMENTED=%1$s is not implemented!
UriParserSemanticException.NAMESPACE_NOT_ALLOWED_AT_FIRST_ELEMENT=Namespace is not allowed for Entity Sets, Singeltons, Action Imports and Function Imports. Found '%1$s'.
UriParserSemanticException.COMPLEX_PARAMETER_IN_RESOURCE_PATH=Complex parameters must not appear in resource path segments. Found: '%1$s'.
UriParserSemanticException.FUNCTION_IMPORT_NOT_ALLOWED=Function Imports are not allowed in $filter or $orderby. Found: '%1$s'.
+UriParserSemanticException.TYPES_NOT_COMPATIBLE=Types are not compatible. Left type: '%1$s', right type: '%1$s'.
UriValidationException.UNSUPPORTED_QUERY_OPTION=The query option '%1$s' is not supported.
UriValidationException.UNSUPPORTED_URI_KIND=The URI kind '%1$s' is not supported.
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8919d3ef/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java
index ec9cc22..c27c960 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java
@@ -33,6 +33,7 @@ import org.apache.olingo.commons.api.edm.EdmProperty;
import org.apache.olingo.commons.api.edm.FullQualifiedName;
import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.commons.core.Encoder;
+import org.apache.olingo.commons.core.edm.primitivetype.EdmString;
import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.edmx.EdmxReference;
import org.apache.olingo.server.api.uri.UriInfoKind;
@@ -3231,7 +3232,6 @@ public class TestFullResourcePath {
// TODO
@Test
- @Ignore
public void filter() throws Exception {
testFilter.runOnETTwoKeyNav("PropertyString")
@@ -3334,21 +3334,22 @@ public class TestFullResourcePath {
// .isExSemantic(MessageKeys.UNKNOWN_TYPE);
testFilter.runOnETTwoKeyNavEx("PropertyComp/invalid")
.isExSemantic(MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE);
- testFilter.runOnETTwoKeyNavEx("concat('a','b')/invalid").isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
+ testFilter.runOnETTwoKeyNavEx("concat('a','b')/invalid")
+ .isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
testFilter.runOnETTwoKeyNavEx("PropertyComp/concat('a','b')")
- .isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
+ .isExSemantic(MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE);
testFilter.runOnETTwoKeyNavEx("PropertyComp/PropertyInt16 eq '1'")
- .isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
+ .isExSemantic(MessageKeys.TYPES_NOT_COMPATIBLE);
testFilter.runOnETTwoKeyNavEx("PropertyComp/PropertyComp/PropertyDate eq 1")
- .isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
+ .isExSemantic(MessageKeys.TYPES_NOT_COMPATIBLE);
testFilter.runOnETTwoKeyNavEx("PropertyComp/PropertyComp/PropertyString eq 1")
- .isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
+ .isExSemantic(MessageKeys.TYPES_NOT_COMPATIBLE);
testFilter.runOnETTwoKeyNavEx("PropertyComp/PropertyInt64 eq 1")
.isExSemantic(MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE);
testFilter.runOnETTwoKeyNavEx("NavPropertyETKeyNavMany/PropertyInt16 gt 42")
- .isExSemantic(MessageKeys.PROPERTY_AFTER_COLLECTION);
+ .isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
testFilter.runOnETTwoKeyNavEx("NavPropertyETKeyNavMany/NavPropertyETTwoKeyNavOne eq null")
- .isExSemantic(MessageKeys.PROPERTY_AFTER_COLLECTION);
+ .isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
testFilter.runOnETAllPrim("PropertySByte eq PropertySByte")
.is("<<PropertySByte> eq <PropertySByte>>")
@@ -3758,12 +3759,13 @@ public class TestFullResourcePath {
.root().right()
.isType(PropertyProvider.nameDecimal);
+ // Numeric promotion: Double is considered the widest type
testFilter.runOnETAllPrim("PropertyDecimal sub NaN")
- .right().isLiteral("NaN").isType(PropertyProvider.nameDecimal);
+ .right().isLiteral("NaN").isType(PropertyProvider.nameDouble);
testFilter.runOnETAllPrim("PropertyDecimal sub -INF")
- .right().isLiteral("-INF").isType(PropertyProvider.nameDecimal);
+ .right().isLiteral("-INF").isType(PropertyProvider.nameDouble);
testFilter.runOnETAllPrim("PropertyDecimal sub INF")
- .right().isLiteral("INF").isType(PropertyProvider.nameDecimal);
+ .right().isLiteral("INF").isType(PropertyProvider.nameDouble);
}
// TODO
@@ -4078,9 +4080,7 @@ public class TestFullResourcePath {
.isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false);
}
- // TODO: $it on primitive types?
@Test
- @Ignore
public void methods() throws Exception {
testFilter.runOnETKeyNav("indexof(PropertyString,'47') eq 5")
.is("<<indexof(<PropertyString>,<'47'>)> eq <5>>")
@@ -4482,7 +4482,7 @@ public class TestFullResourcePath {
.root().left()
.goPath()
.first().isUriPathInfoKind(UriResourceKind.it)
- .isType(EntityTypeProvider.nameETTwoKeyNav, true)
+ .isType(EntityTypeProvider.nameETTwoKeyNav, false)
.n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false);
testFilter.runOnCTTwoPrim("$it/PropertyString eq 'SomeString'")
@@ -4529,7 +4529,7 @@ public class TestFullResourcePath {
.goParameter(0)
.goPath()
.first().isUriPathInfoKind(UriResourceKind.it)
- .isType(EntityTypeProvider.nameETTwoKeyNav, true)
+ .isType(EntityTypeProvider.nameETTwoKeyNav, false)
.n().isPrimitiveProperty("CollPropertyString", PropertyProvider.nameString, true);
testFilter.runOnETTwoKeyNav("endswith(PropertyComp/PropertyComp/PropertyString,'dorf')")
@@ -4646,7 +4646,6 @@ public class TestFullResourcePath {
// TODO: Implement cast method.
@Test
- @Ignore
public void castMethod() throws Exception {
testFilter.runOnETKeyNav("cast(olingo.odata.test1.ETBaseTwoKeyNav)")
.is("<cast(<olingo.odata.test1.ETBaseTwoKeyNav>)>")
@@ -4795,13 +4794,14 @@ public class TestFullResourcePath {
testFilter.runOnETKeyNavEx("cast(NavPropertyETKeyPrimNavOne,olingo.odata.test1.ETKeyNav)")
.isExSemantic(MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE);
- testFilter.runOnETKeyNav("any()")
- .isMember().goPath().first().isUriPathInfoKind(UriResourceKind.lambdaAny);
+ // TODO Is that case makes not really sense, each any / all lambda expr must
+ // containing at least one lambdaVariableExpr
+// testFilter.runOnETKeyNav("any()")
+// .isMember().goPath().first().isUriPathInfoKind(UriResourceKind.lambdaAny);
}
// TODO: Check whether lambda expressions really are allowed on complex collections.
@Test
- @Ignore
public void lambdaFunctions() throws Exception {
testFilter.runOnETKeyNav("NavPropertyETTwoKeyNavMany/any(d:d/PropertyString eq 'SomeString')")
.is("<NavPropertyETTwoKeyNavMany/<ANY;<<d/PropertyString> eq <'SomeString'>>>>")
@@ -4846,9 +4846,9 @@ public class TestFullResourcePath {
.n().isPrimitiveProperty("PropertyInt16", PropertyProvider.nameInt16, false);
testFilter.runOnETKeyNav("NavPropertyETTwoKeyNavMany/any(d:d/PropertyInt16 eq 1 or "
- + "d/any(e:e/CollPropertyString eq 'SomeString'))")
- .is("<NavPropertyETTwoKeyNavMany/<ANY;<<<d/PropertyInt16> eq <1>> or "
- + "<d/<ANY;<<e/CollPropertyString> eq <'SomeString'>>>>>>>")
+ + "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)
@@ -4866,12 +4866,13 @@ public class TestFullResourcePath {
.goPath()
.first().isUriPathInfoKind(UriResourceKind.lambdaVariable)
.isType(EntityTypeProvider.nameETTwoKeyNav, false)
- .n().isUriPathInfoKind(UriResourceKind.lambdaAny)
+ .n().isUriPathInfoKind(UriResourceKind.primitiveProperty)
+ .isPrimitiveProperty("CollPropertyString", PropertyProvider.nameString, true)
+ .at(2).isUriPathInfoKind(UriResourceKind.lambdaAny)
.goLambdaExpression()
.root().left().goPath()
.first().isUriPathInfoKind(UriResourceKind.lambdaVariable)
- .isType(EntityTypeProvider.nameETTwoKeyNav, false)
- .n().isPrimitiveProperty("CollPropertyString", PropertyProvider.nameString, true);
+ .isType(EdmString.getInstance().getFullQualifiedName(), false);
testFilter.runOnETKeyNav("NavPropertyETTwoKeyNavMany/any(d:d/PropertyInt16 eq 1 or "
+ "d/CollPropertyString/any(e:e eq 'SomeString'))")
@@ -4934,12 +4935,10 @@ public class TestFullResourcePath {
.n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false);
testFilter.runOnETKeyNavEx("any(d:d/PropertyInt16 eq 1)")
- .isExSemantic(MessageKeys.PROPERTY_NOT_IN_TYPE);
+ .isExSemantic(MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE);
}
- // TODO: Implement isof method.
@Test
- @Ignore
public void isOfMethod() throws Exception {
testFilter.runOnETKeyNav("isof(olingo.odata.test1.ETTwoKeyNav)")
.is("<isof(<olingo.odata.test1.ETTwoKeyNav>)>")
@@ -4962,7 +4961,7 @@ public class TestFullResourcePath {
.left().isMethod(MethodKind.ISOF, 1)
.goParameter(0).isTypedLiteral(EntityTypeProvider.nameETBaseTwoKeyNav);
- testFilter.runOnETKeyNav("isof(NavPropertyETKeyNavOne, olingo.odata.test1.ETKeyNav) eq true")
+ 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)
@@ -5865,7 +5864,6 @@ public class TestFullResourcePath {
// TODO: Better type determination for literal numbers.
@Test
- @Ignore
public void filterLiteralTypes() throws Exception {
testFilter.runOnETAllPrim("-1000 eq 42")
.isBinary(BinaryOperatorKind.EQ)
[05/30] olingo-odata4 git commit: [OLINGO-834] Filter parser
refactoring first draft
Posted by ch...@apache.org.
[OLINGO-834] Filter parser refactoring first draft
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/7b23ad71
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/7b23ad71
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/7b23ad71
Branch: refs/heads/master
Commit: 7b23ad71a7faab152841a3776b4db3ac9dffccf2
Parents: a47e9f6
Author: Christian Amend <ch...@sap.com>
Authored: Wed Dec 9 14:00:48 2015 +0100
Committer: Christian Amend <ch...@sap.com>
Committed: Wed Dec 9 14:11:46 2015 +0100
----------------------------------------------------------------------
.../core/uri/expression/FilterParser.java | 562 +++++++++++++++++++
.../uri/queryoption/expression/AliasImpl.java | 8 +
.../uri/queryoption/expression/BinaryImpl.java | 16 +
.../uri/queryoption/expression/LiteralImpl.java | 14 +
.../uri/queryoption/expression/MethodImpl.java | 24 +
.../uri/queryoption/expression/UnaryImpl.java | 14 +
.../core/uri/expression/FilterParserTest.java | 210 +++++++
7 files changed, 848 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7b23ad71/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/expression/FilterParser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/expression/FilterParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/expression/FilterParser.java
new file mode 100644
index 0000000..32cbc1a
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/expression/FilterParser.java
@@ -0,0 +1,562 @@
+/*
+ * 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.expression;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
+import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory;
+import org.apache.olingo.server.api.uri.queryoption.expression.BinaryOperatorKind;
+import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
+import org.apache.olingo.server.api.uri.queryoption.expression.MethodKind;
+import org.apache.olingo.server.api.uri.queryoption.expression.UnaryOperatorKind;
+import org.apache.olingo.server.core.uri.queryoption.expression.AliasImpl;
+import org.apache.olingo.server.core.uri.queryoption.expression.BinaryImpl;
+import org.apache.olingo.server.core.uri.queryoption.expression.ExpressionImpl;
+import org.apache.olingo.server.core.uri.queryoption.expression.LiteralImpl;
+import org.apache.olingo.server.core.uri.queryoption.expression.MethodImpl;
+import org.apache.olingo.server.core.uri.queryoption.expression.UnaryImpl;
+
+public class FilterParser {
+ private Tokenizer tokenizer;
+
+ private static final Map<TokenKind, BinaryOperatorKind> tokenToBinaryOperator;
+ static {
+ HashMap<TokenKind, BinaryOperatorKind> temp = new HashMap<FilterParser.TokenKind, BinaryOperatorKind>();
+ temp.put(TokenKind.OR_OP, BinaryOperatorKind.OR);
+ temp.put(TokenKind.AND_OP, BinaryOperatorKind.AND);
+
+ temp.put(TokenKind.EQ_OP, BinaryOperatorKind.EQ);
+ temp.put(TokenKind.NE_OP, BinaryOperatorKind.NE);
+
+ temp.put(TokenKind.GT_OP, BinaryOperatorKind.GT);
+ temp.put(TokenKind.GE_OP, BinaryOperatorKind.GE);
+ temp.put(TokenKind.LT_OP, BinaryOperatorKind.LT);
+ temp.put(TokenKind.LE_OP, BinaryOperatorKind.LE);
+
+ temp.put(TokenKind.ADD_OP, BinaryOperatorKind.ADD);
+ temp.put(TokenKind.SUB_OP, BinaryOperatorKind.SUB);
+
+ temp.put(TokenKind.MUL_OP, BinaryOperatorKind.MUL);
+ temp.put(TokenKind.DIV_OP, BinaryOperatorKind.DIV);
+ temp.put(TokenKind.MOD_OP, BinaryOperatorKind.MOD);
+
+ tokenToBinaryOperator = Collections.unmodifiableMap(temp);
+ }
+
+ private static final Map<TokenKind, UnaryOperatorKind> tokenToUnaryOperator;
+ static {
+ HashMap<TokenKind, UnaryOperatorKind> temp = new HashMap<FilterParser.TokenKind, UnaryOperatorKind>();
+ temp.put(TokenKind.MINUS, UnaryOperatorKind.MINUS);
+ temp.put(TokenKind.NOT, UnaryOperatorKind.NOT);
+ tokenToUnaryOperator = Collections.unmodifiableMap(temp);
+ }
+
+ private static final Map<TokenKind, MethodKind> tokenToMethod;
+ static {
+ HashMap<TokenKind, MethodKind> temp = new HashMap<FilterParser.TokenKind, MethodKind>();
+ temp.put(TokenKind.Cast, MethodKind.CAST);
+ temp.put(TokenKind.Ceiling, MethodKind.CEILING);
+ temp.put(TokenKind.Concat, MethodKind.CONCAT);
+ temp.put(TokenKind.Contains, MethodKind.CONTAINS);
+ temp.put(TokenKind.Date, MethodKind.DATE);
+ temp.put(TokenKind.Day, MethodKind.DAY);
+ temp.put(TokenKind.Endswith, MethodKind.ENDSWITH);
+ temp.put(TokenKind.Floor, MethodKind.FLOOR);
+ temp.put(TokenKind.Fractionalseconds, MethodKind.FRACTIONALSECONDS);
+ temp.put(TokenKind.GeoDistance, MethodKind.GEODISTANCE);
+ temp.put(TokenKind.GeoIntersects, MethodKind.GEOINTERSECTS);
+ temp.put(TokenKind.GeoLength, MethodKind.GEOLENGTH);
+ temp.put(TokenKind.Hour, MethodKind.HOUR);
+ temp.put(TokenKind.Indexof, MethodKind.INDEXOF);
+ temp.put(TokenKind.Isof, MethodKind.ISOF);
+ temp.put(TokenKind.Length, MethodKind.LENGTH);
+ temp.put(TokenKind.Maxdatetime, MethodKind.MAXDATETIME);
+ temp.put(TokenKind.Mindatetime, MethodKind.MINDATETIME);
+ temp.put(TokenKind.Minute, MethodKind.MINUTE);
+ temp.put(TokenKind.Month, MethodKind.MONTH);
+ temp.put(TokenKind.Now, MethodKind.NOW);
+ temp.put(TokenKind.Round, MethodKind.ROUND);
+ temp.put(TokenKind.Second, MethodKind.SECOND);
+ temp.put(TokenKind.Startswith, MethodKind.STARTSWITH);
+ temp.put(TokenKind.Substring, MethodKind.SUBSTRING);
+ temp.put(TokenKind.Time, MethodKind.TIME);
+ temp.put(TokenKind.Tolower, MethodKind.TOLOWER);
+ temp.put(TokenKind.Totaloffsetminutes, MethodKind.TOTALOFFSETMINUTES);
+ temp.put(TokenKind.Totalseconds, MethodKind.TOTALSECONDS);
+ temp.put(TokenKind.Toupper, MethodKind.TOUPPER);
+ temp.put(TokenKind.Trim, MethodKind.TRIM);
+ temp.put(TokenKind.Year, MethodKind.YEAR);
+
+ tokenToMethod = Collections.unmodifiableMap(temp);
+ }
+
+ private static final Map<TokenKind, EdmPrimitiveTypeKind> tokenToPrimitiveType;
+ static {
+ /* Enum and null are not present in the map. These have to be handled differently */
+ HashMap<TokenKind, EdmPrimitiveTypeKind> temp = new HashMap<FilterParser.TokenKind, EdmPrimitiveTypeKind>();
+ temp.put(TokenKind.PrimitiveBooleanValue, EdmPrimitiveTypeKind.Boolean);
+ temp.put(TokenKind.PrimitiveStringValue, EdmPrimitiveTypeKind.String);
+ // TODO:Check if int64 is correct here or if it has to be single instead
+ temp.put(TokenKind.PrimitiveIntegerValue, EdmPrimitiveTypeKind.Int64);
+ temp.put(TokenKind.PrimitiveGuidValue, EdmPrimitiveTypeKind.Guid);
+ temp.put(TokenKind.PrimitiveDateValue, EdmPrimitiveTypeKind.Date);
+ temp.put(TokenKind.PrimitiveDateTimeOffsetValue, EdmPrimitiveTypeKind.DateTimeOffset);
+ temp.put(TokenKind.PrimitiveTimeOfDayValue, EdmPrimitiveTypeKind.TimeOfDay);
+ temp.put(TokenKind.PrimitiveDecimalValue, EdmPrimitiveTypeKind.Decimal);
+ temp.put(TokenKind.PrimitiveDoubleValue, EdmPrimitiveTypeKind.Double);
+ temp.put(TokenKind.PrimitiveDurationValue, EdmPrimitiveTypeKind.Duration);
+ temp.put(TokenKind.PrimitiveBinaryValue, EdmPrimitiveTypeKind.Binary);
+
+ tokenToPrimitiveType = Collections.unmodifiableMap(temp);
+ }
+
+ public Expression parse(Tokenizer tokenizer) {
+ // Initialize tokenizer
+ this.tokenizer = tokenizer;
+
+ Expression exp = parseExpression();
+ return exp;
+ }
+
+ private Expression parseExpression() {
+ Expression left = parseAnd();
+
+ while (is(TokenKind.OR_OP) != null) {
+ tokenizer.getText();
+
+ Expression right = parseAnd();
+ left = new BinaryImpl(left, BinaryOperatorKind.OR, right);
+ }
+
+ return left;
+ }
+
+ private Expression parseAnd() {
+ Expression left = parseExprEquality();
+ while (is(TokenKind.AND_OP) != null) {
+ tokenizer.getText();
+
+ Expression right = parseExprEquality();
+ left = new BinaryImpl(left, BinaryOperatorKind.AND, right);
+ }
+ return left;
+ }
+
+ private Expression parseExprEquality() {
+ Expression left = parseExprRel();
+
+ TokenKind nextTokenKind = is(TokenKind.EQ_OP, TokenKind.NE_OP);
+ // Null for everything other than EQ or NE
+ while (nextTokenKind != null) {
+ tokenizer.getText();
+
+ Expression right = parseExprEquality();
+ left = new BinaryImpl(left, tokenToBinaryOperator.get(nextTokenKind), right);
+ nextTokenKind = is(TokenKind.EQ_OP, TokenKind.NE_OP);
+ }
+
+ return left;
+ }
+
+ private Expression parseExprRel() {
+ Expression left = parseExprAdd();
+
+ TokenKind nextTokenKind = is(TokenKind.GT_OP, TokenKind.GE_OP, TokenKind.LT_OP, TokenKind.LE_OP);
+ // Null for everything other than GT or GE or LT or LE
+ while (nextTokenKind != null) {
+ tokenizer.getText();
+
+ Expression right = parseExprAdd();
+ left = new BinaryImpl(left, tokenToBinaryOperator.get(nextTokenKind), right);
+ nextTokenKind = is(TokenKind.GT_OP, TokenKind.GE_OP, TokenKind.LT_OP, TokenKind.LE_OP);
+ }
+
+ return left;
+ }
+
+ private Expression parseExprAdd() {
+ Expression left = parseExprMul();
+
+ TokenKind nextTokenKind = is(TokenKind.ADD_OP, TokenKind.SUB_OP);
+ // Null for everything other than ADD or SUB
+ while (nextTokenKind != null) {
+ tokenizer.getText();
+
+ Expression right = parseExprMul();
+ left = new BinaryImpl(left, tokenToBinaryOperator.get(nextTokenKind), right);
+ nextTokenKind = is(TokenKind.ADD_OP, TokenKind.SUB_OP);
+ }
+
+ return left;
+ }
+
+ private Expression parseExprMul() {
+ Expression left = parseExprUnary();
+
+ TokenKind nextTokenKind = is(TokenKind.MUL_OP, TokenKind.DIV_OP, TokenKind.MOD_OP);
+ // Null for everything other than MUL or DIV or MOD
+ while (nextTokenKind != null) {
+ tokenizer.getText();
+
+ Expression right = parseExprUnary();
+ left = new BinaryImpl(left, tokenToBinaryOperator.get(nextTokenKind), right);
+ nextTokenKind = is(TokenKind.MUL_OP, TokenKind.DIV_OP, TokenKind.MOD_OP);
+ }
+
+ return left;
+ }
+
+ private Expression parseExprUnary() {
+ Expression left = null;
+ TokenKind nextTokenKind = is(TokenKind.MINUS, TokenKind.NOT);
+ // Null for everything other than - or NOT
+ while (nextTokenKind != null) {
+ tokenizer.getText();
+
+ Expression exp = parseExprValue();
+ left = new UnaryImpl(tokenToUnaryOperator.get(nextTokenKind), exp);
+ nextTokenKind = is(TokenKind.MINUS, TokenKind.NOT);
+ }
+
+ if (left == null) {
+ left = parseExprValue();
+ }
+
+ return left;
+ }
+
+ private Expression parseExprValue() {
+ if (is(TokenKind.OPEN) != null) {
+ tokenizer.getText();
+ Expression exp = parseExpression();
+ require(TokenKind.CLOSE);
+ return exp;
+ }
+
+ if (is(TokenKind.ParameterAlias) != null) {
+ return new AliasImpl(tokenizer.getText());
+ }
+
+ if (is(TokenKind.RootExpr) != null) {
+ tokenizer.getText();
+ // TODO: ConsumeRootExpression
+ }
+
+ TokenKind nextPrimitive = isPrimitive();
+ if (nextPrimitive != null) {
+ EdmPrimitiveTypeKind primitiveTypeKind = tokenToPrimitiveType.get(nextPrimitive);
+ EdmPrimitiveType type;
+ if (primitiveTypeKind == null) {
+ if (nextPrimitive == TokenKind.PrimitiveEnumValue) {
+ // TODO: Get enum type
+ type = null;
+ } else {
+ // Null handling
+ type = null;
+ }
+ } else {
+ type = EdmPrimitiveTypeFactory.getInstance(primitiveTypeKind);
+ }
+ return new LiteralImpl(tokenizer.getText(), type);
+ }
+
+ TokenKind nextMethod = isMethod();
+ if (nextMethod != null) {
+ MethodImpl methodImpl = new MethodImpl(tokenToMethod.get(nextMethod));
+ // Consume Method
+ tokenizer.getText();
+ if (is(TokenKind.CLOSE) != null) {
+ // Consume closing bracket
+ tokenizer.getText();
+ } else {
+ // TODO: Remove Cast
+ methodImpl.addParameter((ExpressionImpl) parseExpression());
+ while (is(TokenKind.COMMA) != null) {
+ tokenizer.getText();
+ methodImpl.addParameter((ExpressionImpl) parseExpression());
+ }
+ require(TokenKind.CLOSE);
+ }
+
+ validateMethodParameters(methodImpl);
+
+ return methodImpl;
+ }
+
+ throw new RuntimeException("Unexpected token");
+ }
+
+ private void validateMethodParameters(MethodImpl methodImpl) {
+ // We might validate parameter types in the future
+ int size = methodImpl.getParameters().size();
+ switch (methodImpl.getMethod()) {
+ // Must have two Parameters
+ case CONTAINS:
+ case ENDSWITH:
+ case STARTSWITH:
+ case INDEXOF:
+ case CONCAT:
+ case GEODISTANCE:
+ case GEOINTERSECTS:
+ if (size != 2) {
+ throw new RuntimeException("The method " + methodImpl.getMethod() + " needs exactly two parameters.");
+ }
+ break;
+ // Must have one parameter
+ case LENGTH:
+ case TOLOWER:
+ case TOUPPER:
+ case TRIM:
+ case YEAR:
+ case MONTH:
+ case DAY:
+ case HOUR:
+ case MINUTE:
+ case SECOND:
+ case FRACTIONALSECONDS:
+ case DATE:
+ case TIME:
+ case TOTALOFFSETMINUTES:
+ case TOTALSECONDS:
+ case ROUND:
+ case FLOOR:
+ case CEILING:
+ case GEOLENGTH:
+ if (size != 1) {
+ throw new RuntimeException("The method: '" + methodImpl.getMethod() + "' needs exactly one parameter.");
+ }
+ break;
+ // Must have no parameter
+ case NOW:
+ case MAXDATETIME:
+ case MINDATETIME:
+ if (size != 0) {
+ throw new RuntimeException("The method: '" + methodImpl.getMethod() + "' must have no parameters.");
+ }
+ break;
+ // Variable parameter number
+ case CAST:
+ case ISOF:
+ if (size == 1 || size == 2) {
+ throw new RuntimeException("The method: '" + methodImpl.getMethod() + "' must have one or two parameters.");
+ }
+ break;
+ case SUBSTRING:
+ if (size == 2 || size == 3) {
+ throw new RuntimeException("The method: '" + methodImpl.getMethod() + "' must have two or three parameters.");
+ }
+ break;
+ default:
+ throw new RuntimeException("Unkown method: '" + methodImpl.getMethod() + "'");
+ }
+ }
+
+ private String require(TokenKind required) {
+ if (is(required) == null) {
+ throw new RuntimeException("Requred token: " + required);
+ }
+ return tokenizer.getText();
+ }
+
+ private TokenKind is(TokenKind... kind) {
+ for (int i = 0; i < kind.length; i++) {
+ if (tokenizer.next(kind[i])) {
+ return kind[i];
+ }
+ }
+ return null;
+ }
+
+ private TokenKind isMethod() {
+ return is(TokenKind.Cast,
+ TokenKind.Ceiling,
+ TokenKind.Concat,
+ TokenKind.Contains,
+ TokenKind.Date,
+ TokenKind.Day,
+ TokenKind.Endswith,
+ TokenKind.Floor,
+ TokenKind.Fractionalseconds,
+ TokenKind.GeoDistance,
+ TokenKind.GeoIntersects,
+ TokenKind.GeoLength,
+ TokenKind.Hour,
+ TokenKind.Indexof,
+ TokenKind.Isof,
+ TokenKind.Length,
+ TokenKind.Maxdatetime,
+ TokenKind.Mindatetime,
+ TokenKind.Minute,
+ TokenKind.Month,
+ TokenKind.Now,
+ TokenKind.Round,
+ TokenKind.Second,
+ TokenKind.Startswith,
+ TokenKind.Substring,
+ TokenKind.Time,
+ TokenKind.Tolower,
+ TokenKind.Totaloffsetminutes,
+ TokenKind.Totalseconds,
+ TokenKind.Toupper,
+ TokenKind.Trim,
+ TokenKind.Year);
+ }
+
+ private TokenKind isPrimitive() {
+ return is(TokenKind.PrimitiveNullValue,
+ TokenKind.PrimitiveBooleanValue,
+ TokenKind.PrimitiveStringValue,
+
+ // The order of the next seven expressions is important in order to avoid
+ // finding partly parsed tokens (counter-intuitive as it may be, even a GUID may start with digits ...).
+ TokenKind.PrimitiveDoubleValue,
+ TokenKind.PrimitiveDecimalValue,
+ TokenKind.PrimitiveGuidValue,
+ TokenKind.PrimitiveDateTimeOffsetValue,
+ TokenKind.PrimitiveDateValue,
+ TokenKind.PrimitiveTimeOfDayValue,
+ TokenKind.PrimitiveIntegerValue,
+ TokenKind.PrimitiveDurationValue,
+ TokenKind.PrimitiveBinaryValue,
+ TokenKind.PrimitiveEnumValue);
+ }
+
+ public enum TokenKind {
+ // BINARY
+ OR_OP,
+ AND_OP,
+
+ EQ_OP,
+ NE_OP,
+
+ GT_OP,
+ GE_OP,
+ LT_OP,
+ LE_OP,
+
+ ADD_OP,
+ SUB_OP,
+
+ MUL_OP,
+ DIV_OP,
+ MOD_OP,
+
+ MINUS,
+ NOT,
+
+ // Grouping
+ OPEN,
+ CLOSE,
+
+ // PrimitiveValues
+ PrimitiveNullValue,
+ PrimitiveBooleanValue,
+
+ PrimitiveStringValue,
+ PrimitiveIntegerValue,
+ PrimitiveGuidValue,
+ PrimitiveDateValue,
+ PrimitiveDateTimeOffsetValue,
+ PrimitiveTimeOfDayValue,
+ PrimitiveDecimalValue,
+ PrimitiveDoubleValue,
+ PrimitiveDurationValue,
+ PrimitiveBinaryValue,
+ PrimitiveEnumValue,
+
+ // ExpressionValues
+ ParameterAlias,
+ ArrayOrObject,
+ RootExpr,
+ IT,
+
+ // BuiltInMethods
+ Cast,
+ Ceiling,
+ Concat,
+ Contains,
+ Date,
+ Day,
+ Endswith,
+ Floor,
+ Fractionalseconds,
+ GeoDistance,
+ GeoIntersects,
+ GeoLength,
+ Hour,
+ Indexof,
+ Isof,
+ Length,
+ Maxdatetime,
+ Mindatetime,
+ Minute,
+ Month,
+ Now,
+ Round,
+ Second,
+ Startswith,
+ Substring,
+ Time,
+ Tolower,
+ Totaloffsetminutes,
+ Totalseconds,
+ Toupper,
+ Trim,
+ Year,
+ COMMA
+ }
+
+ public static class Token {
+ TokenKind kind;
+ String text;
+
+ public Token(TokenKind kind, String text) {
+ this.kind = kind;
+ this.text = text;
+ }
+ }
+
+ public static class Tokenizer {
+ private List<Token> tokens;
+ int counter = 0;
+
+ public Tokenizer(List<Token> tokens) {
+ this.tokens = tokens;
+ }
+
+ public boolean next(TokenKind expectedKind) {
+ if (counter < tokens.size() && expectedKind == tokens.get(counter).kind) {
+ return true;
+ }
+ return false;
+ }
+
+ public String getText() {
+ String text = tokens.get(counter).text;
+ counter++;
+ return text;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7b23ad71/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/AliasImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/AliasImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/AliasImpl.java
index 09af93f..5309d73 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/AliasImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/AliasImpl.java
@@ -27,6 +27,14 @@ public class AliasImpl extends ExpressionImpl implements Alias {
private String parameterName;
+ public AliasImpl() {
+ //TODO: Delete Constructor
+ }
+
+ public AliasImpl(String parameterName) {
+ this.parameterName = parameterName;
+ }
+
@Override
public String getParameterName() {
return parameterName;
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7b23ad71/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/BinaryImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/BinaryImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/BinaryImpl.java
index a28f92c..c3530c0 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/BinaryImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/BinaryImpl.java
@@ -31,6 +31,17 @@ public class BinaryImpl extends ExpressionImpl implements Binary {
private ExpressionImpl left;
private ExpressionImpl right;
+ public BinaryImpl() {
+ // TODO: Delete
+ }
+
+ public BinaryImpl(Expression left, BinaryOperatorKind operator, Expression right) {
+ // TODO:DeleteCast
+ this.left = (ExpressionImpl) left;
+ this.operator = operator;
+ this.right = (ExpressionImpl) right;
+ }
+
@Override
public BinaryOperatorKind getOperator() {
return operator;
@@ -67,4 +78,9 @@ public class BinaryImpl extends ExpressionImpl implements Binary {
return visitor.visitBinaryOperator(operator, left, right);
}
+ @Override
+ public String toString() {
+ return "{" + left + " " + operator.name() + " " + right + '}';
+ }
+
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7b23ad71/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/LiteralImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/LiteralImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/LiteralImpl.java
index 1dd9fa7..e275fdd 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/LiteralImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/LiteralImpl.java
@@ -29,6 +29,15 @@ public class LiteralImpl extends ExpressionImpl implements Literal {
private String text;
private EdmType type;
+ public LiteralImpl() {
+
+ }
+
+ public LiteralImpl(String text, EdmType type) {
+ this.text = text;
+ this.type = type;
+ }
+
@Override
public String getText() {
return text;
@@ -54,4 +63,9 @@ public class LiteralImpl extends ExpressionImpl implements Literal {
return visitor.visitLiteral(this);
}
+ @Override
+ public String toString() {
+ return "" + text;
+ }
+
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7b23ad71/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/MethodImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/MethodImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/MethodImpl.java
index 7104a9f..8175c85 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/MethodImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/MethodImpl.java
@@ -33,6 +33,14 @@ public class MethodImpl extends ExpressionImpl implements Method {
private MethodKind method;
private List<ExpressionImpl> parameters = new ArrayList<ExpressionImpl>();
+ public MethodImpl() {
+ // TODO: Delete constructor
+ }
+
+ public MethodImpl(MethodKind method) {
+ this.method = method;
+ }
+
@Override
public MethodKind getMethod() {
return method;
@@ -66,4 +74,20 @@ public class MethodImpl extends ExpressionImpl implements Method {
return visitor.visitMethodCall(method, userParameters);
}
+ @Override
+ public String toString() {
+ String parametersString = "[";
+ boolean first = true;
+ for (Expression exp : parameters) {
+ if(first){
+ first = false;
+ parametersString = parametersString + exp.toString();
+ }else {
+ parametersString = parametersString + ", " + exp.toString();
+ }
+ }
+ parametersString = parametersString + "]";
+ return "{" + method + " " + parametersString + "}";
+ }
+
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7b23ad71/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/UnaryImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/UnaryImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/UnaryImpl.java
index 796191f..f1edf91 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/UnaryImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/UnaryImpl.java
@@ -30,6 +30,15 @@ public class UnaryImpl extends ExpressionImpl implements Unary {
private UnaryOperatorKind operator;
private ExpressionImpl expression;
+ public UnaryImpl() {
+
+ }
+
+ public UnaryImpl(UnaryOperatorKind operator, Expression expression) {
+ this.operator = operator;
+ this.expression = (ExpressionImpl) expression;
+ }
+
@Override
public UnaryOperatorKind getOperator() {
return operator;
@@ -54,4 +63,9 @@ public class UnaryImpl extends ExpressionImpl implements Unary {
return visitor.visitUnaryOperator(operator, operand);
}
+ @Override
+ public String toString() {
+ return "{" + operator + " " + expression + '}';
+ }
+
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7b23ad71/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/expression/FilterParserTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/expression/FilterParserTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/expression/FilterParserTest.java
new file mode 100644
index 0000000..7bfc369
--- /dev/null
+++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/expression/FilterParserTest.java
@@ -0,0 +1,210 @@
+/*
+ * 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.expression;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.ArrayList;
+
+import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
+import org.apache.olingo.server.core.uri.expression.FilterParser.TokenKind;
+import org.apache.olingo.server.core.uri.expression.FilterParser.Tokenizer;
+import org.apache.olingo.server.core.uri.expression.FilterParser.Token;
+import org.junit.Test;
+
+public class FilterParserTest {
+
+ @Test
+ public void equality() {
+ Expression expression = parseExpression(TokenKind.EQ_OP);
+ assertEquals("{5 EQ 5}", expression.toString());
+
+ expression = parseExpression(TokenKind.NE_OP);
+ assertEquals("{5 NE 5}", expression.toString());
+ }
+
+ @Test
+ public void relational() {
+ Expression expression = parseExpression(TokenKind.GT_OP);
+ assertEquals("{5 GT 5}", expression.toString());
+
+ expression = parseExpression(TokenKind.GE_OP);
+ assertEquals("{5 GE 5}", expression.toString());
+
+ expression = parseExpression(TokenKind.LT_OP);
+ assertEquals("{5 LT 5}", expression.toString());
+
+ expression = parseExpression(TokenKind.LE_OP);
+ assertEquals("{5 LE 5}", expression.toString());
+ }
+
+ @Test
+ public void additive() {
+ Expression expression = parseExpression(TokenKind.ADD_OP);
+ assertEquals("{5 ADD 5}", expression.toString());
+
+ expression = parseExpression(TokenKind.SUB_OP);
+ assertEquals("{5 SUB 5}", expression.toString());
+ }
+
+ @Test
+ public void multiplicative() {
+ Expression expression = parseExpression(TokenKind.MUL_OP);
+ assertEquals("{5 MUL 5}", expression.toString());
+
+ expression = parseExpression(TokenKind.DIV_OP);
+ assertEquals("{5 DIV 5}", expression.toString());
+
+ expression = parseExpression(TokenKind.MOD_OP);
+ assertEquals("{5 MOD 5}", expression.toString());
+ }
+
+ @Test
+ public void unary() {
+ ArrayList<Token> tokens = new ArrayList<Token>();
+ tokens.add(new Token(TokenKind.MINUS, ""));
+ tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
+ Tokenizer tokenizer = new Tokenizer(tokens);
+ Expression expression = new FilterParser().parse(tokenizer);
+ assertEquals("{- 5}", expression.toString());
+
+ tokens = new ArrayList<Token>();
+ tokens.add(new Token(TokenKind.NOT, ""));
+ tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
+ tokenizer = new Tokenizer(tokens);
+ expression = new FilterParser().parse(tokenizer);
+ assertEquals("{not 5}", expression.toString());
+ }
+
+ @Test
+ public void grouping() {
+ ArrayList<Token> tokens = new ArrayList<Token>();
+ tokens.add(new Token(TokenKind.MINUS, ""));
+ tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
+ tokens.add(new Token(TokenKind.ADD_OP, ""));
+ tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
+ Tokenizer tokenizer = new Tokenizer(tokens);
+ Expression expression = new FilterParser().parse(tokenizer);
+ assertEquals("{{- 5} ADD 5}", expression.toString());
+
+ tokens = new ArrayList<Token>();
+ tokens.add(new Token(TokenKind.MINUS, ""));
+ tokens.add(new Token(TokenKind.OPEN, ""));
+ tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
+ tokens.add(new Token(TokenKind.ADD_OP, ""));
+ tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
+ tokens.add(new Token(TokenKind.CLOSE, ""));
+ tokenizer = new Tokenizer(tokens);
+ expression = new FilterParser().parse(tokenizer);
+ assertEquals("{- {5 ADD 5}}", expression.toString());
+ }
+
+ @Test
+ public void noParameterMethods() {
+ Expression expression = parseMethod(TokenKind.Now);
+ assertEquals("{now []}", expression.toString());
+
+ expression = parseMethod(TokenKind.Maxdatetime);
+ assertEquals("{maxdatetime []}", expression.toString());
+
+ expression = parseMethod(TokenKind.Mindatetime);
+ assertEquals("{mindatetime []}", expression.toString());
+ }
+
+ @Test
+ public void oneParameterMethods() {
+ Expression expression = parseMethod(TokenKind.Length, TokenKind.PrimitiveStringValue);
+ assertEquals("{length [String1]}", expression.toString());
+
+ expression = parseMethod(TokenKind.Tolower, TokenKind.PrimitiveStringValue);
+ assertEquals("{tolower [String1]}", expression.toString());
+
+ expression = parseMethod(TokenKind.Toupper, TokenKind.PrimitiveStringValue);
+ assertEquals("{toupper [String1]}", expression.toString());
+
+ expression = parseMethod(TokenKind.Trim, TokenKind.PrimitiveStringValue);
+ assertEquals("{trim [String1]}", expression.toString());
+
+ expression = parseMethod(TokenKind.Year, TokenKind.PrimitiveDateValue);
+ assertEquals("{year [Date1]}", expression.toString());
+
+ expression = parseMethod(TokenKind.Month, TokenKind.PrimitiveDateValue);
+ assertEquals("{month [Date1]}", expression.toString());
+
+ expression = parseMethod(TokenKind.Day, TokenKind.PrimitiveDateValue);
+ assertEquals("{day [Date1]}", expression.toString());
+
+ expression = parseMethod(TokenKind.Hour, TokenKind.PrimitiveDateTimeOffsetValue);
+ assertEquals("{hour [DateTimeOffset1]}", expression.toString());
+
+ expression = parseMethod(TokenKind.Minute, TokenKind.PrimitiveDateTimeOffsetValue);
+ assertEquals("{minute [DateTimeOffset1]}", expression.toString());
+
+ expression = parseMethod(TokenKind.Second, TokenKind.PrimitiveDateTimeOffsetValue);
+ assertEquals("{second [DateTimeOffset1]}", expression.toString());
+ }
+
+ @Test
+ public void twoParameterMethods() {
+
+ }
+
+ private Expression parseMethod(TokenKind... kind) {
+ ArrayList<Token> tokens = new ArrayList<Token>();
+ tokens.add(new Token(kind[0], ""));
+
+ for (int i = 1; i < kind.length; i++) {
+ String text = null;
+ switch (kind[i]) {
+ case PrimitiveStringValue:
+ text = "String" + i;
+ break;
+ case PrimitiveDateValue:
+ text = "Date" + i;
+ break;
+ case PrimitiveDateTimeOffsetValue:
+ text = "DateTimeOffset" + i;
+ break;
+ default:
+ text = "" + i;
+ break;
+ }
+ tokens.add(new Token(kind[i], text));
+ }
+
+ tokens.add(new Token(TokenKind.CLOSE, ""));
+ Tokenizer tokenizer = new Tokenizer(tokens);
+ Expression expression = new FilterParser().parse(tokenizer);
+ assertNotNull(expression);
+ return expression;
+ }
+
+ private Expression parseExpression(TokenKind operator) {
+ ArrayList<Token> tokens = new ArrayList<Token>();
+ tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
+ tokens.add(new Token(operator, ""));
+ tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
+ Tokenizer tokenizer = new Tokenizer(tokens);
+
+ Expression expression = new FilterParser().parse(tokenizer);
+ assertNotNull(expression);
+ return expression;
+ }
+}
[12/30] olingo-odata4 git commit: [OLINGO-834] ExpressionParser uses
UriTokenizer
Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2f3bc286/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java
index 177a396..b5614ad 100644
--- a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java
+++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java
@@ -22,6 +22,8 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import java.util.Locale;
+
import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind;
import org.junit.Test;
@@ -44,6 +46,8 @@ public class UriTokenizerTest {
assertTrue(new UriTokenizer("$value").next(TokenKind.VALUE));
assertTrue(new UriTokenizer("$count").next(TokenKind.COUNT));
assertTrue(new UriTokenizer("$crossjoin").next(TokenKind.CROSSJOIN));
+ assertTrue(new UriTokenizer("$root").next(TokenKind.ROOT));
+ assertTrue(new UriTokenizer("$it").next(TokenKind.IT));
assertTrue(new UriTokenizer("null").next(TokenKind.NULL));
wrongToken(TokenKind.REF, "$ref", 'x');
@@ -51,19 +55,19 @@ public class UriTokenizerTest {
@Test
public void sequence() {
- final UriTokenizer tokenizer = new UriTokenizer("(A=1,B=2);.*/+");
+ final UriTokenizer tokenizer = new UriTokenizer("(A=1,B=2);.*/+-");
assertTrue(tokenizer.next(TokenKind.OPEN));
assertFalse(tokenizer.next(TokenKind.OPEN));
assertTrue(tokenizer.next(TokenKind.ODataIdentifier));
assertEquals("A", tokenizer.getText());
assertTrue(tokenizer.next(TokenKind.EQ));
- assertTrue(tokenizer.next(TokenKind.PrimitiveIntegerValue));
+ assertTrue(tokenizer.next(TokenKind.IntegerValue));
assertEquals("1", tokenizer.getText());
assertTrue(tokenizer.next(TokenKind.COMMA));
assertTrue(tokenizer.next(TokenKind.ODataIdentifier));
assertEquals("B", tokenizer.getText());
assertTrue(tokenizer.next(TokenKind.EQ));
- assertTrue(tokenizer.next(TokenKind.PrimitiveIntegerValue));
+ assertTrue(tokenizer.next(TokenKind.IntegerValue));
assertEquals("2", tokenizer.getText());
assertFalse(tokenizer.next(TokenKind.EOF));
assertTrue(tokenizer.next(TokenKind.CLOSE));
@@ -72,6 +76,7 @@ public class UriTokenizerTest {
assertTrue(tokenizer.next(TokenKind.STAR));
assertTrue(tokenizer.next(TokenKind.SLASH));
assertTrue(tokenizer.next(TokenKind.PLUS));
+ assertTrue(tokenizer.next(TokenKind.MINUS));
assertTrue(tokenizer.next(TokenKind.EOF));
}
@@ -107,7 +112,7 @@ public class UriTokenizerTest {
final UriTokenizer tokenizer = new UriTokenizer("multi.part.namespace.name.1");
assertTrue(tokenizer.next(TokenKind.QualifiedName));
assertTrue(tokenizer.next(TokenKind.DOT));
- assertTrue(tokenizer.next(TokenKind.PrimitiveIntegerValue));
+ assertTrue(tokenizer.next(TokenKind.IntegerValue));
assertTrue(tokenizer.next(TokenKind.EOF));
assertFalse(new UriTokenizer("name").next(TokenKind.QualifiedName));
@@ -127,174 +132,174 @@ public class UriTokenizerTest {
@Test
public void booleanValue() {
- assertTrue(new UriTokenizer("true").next(TokenKind.PrimitiveBooleanValue));
- assertTrue(new UriTokenizer("tRuE").next(TokenKind.PrimitiveBooleanValue));
- assertTrue(new UriTokenizer("false").next(TokenKind.PrimitiveBooleanValue));
- assertTrue(new UriTokenizer("False").next(TokenKind.PrimitiveBooleanValue));
+ assertTrue(new UriTokenizer("true").next(TokenKind.BooleanValue));
+ assertTrue(new UriTokenizer("tRuE").next(TokenKind.BooleanValue));
+ assertTrue(new UriTokenizer("false").next(TokenKind.BooleanValue));
+ assertTrue(new UriTokenizer("False").next(TokenKind.BooleanValue));
- wrongToken(TokenKind.PrimitiveBooleanValue, "true", 'x');
+ wrongToken(TokenKind.BooleanValue, "true", 'x');
}
@Test
public void string() {
- assertTrue(new UriTokenizer("'ABC'").next(TokenKind.PrimitiveStringValue));
- assertTrue(new UriTokenizer("'€\uFDFC'").next(TokenKind.PrimitiveStringValue));
+ assertTrue(new UriTokenizer("'ABC'").next(TokenKind.StringValue));
+ assertTrue(new UriTokenizer("'€\uFDFC'").next(TokenKind.StringValue));
assertTrue(new UriTokenizer('\'' + String.valueOf(Character.toChars(0x1F603)) + '\'')
- .next(TokenKind.PrimitiveStringValue));
+ .next(TokenKind.StringValue));
final UriTokenizer tokenizer = new UriTokenizer("'AB''''C'''D");
- assertTrue(tokenizer.next(TokenKind.PrimitiveStringValue));
+ assertTrue(tokenizer.next(TokenKind.StringValue));
assertEquals("'AB''''C'''", tokenizer.getText());
assertTrue(tokenizer.next(TokenKind.ODataIdentifier));
assertEquals("D", tokenizer.getText());
- assertFalse(new UriTokenizer("A").next(TokenKind.PrimitiveStringValue));
- assertFalse(new UriTokenizer("'A").next(TokenKind.PrimitiveStringValue));
+ assertFalse(new UriTokenizer("A").next(TokenKind.StringValue));
+ assertFalse(new UriTokenizer("'A").next(TokenKind.StringValue));
}
@Test
public void integer() {
- assertTrue(new UriTokenizer("1").next(TokenKind.PrimitiveIntegerValue));
- assertTrue(new UriTokenizer("1.").next(TokenKind.PrimitiveIntegerValue));
- assertFalse(new UriTokenizer(".1").next(TokenKind.PrimitiveIntegerValue));
- assertTrue(new UriTokenizer("-1").next(TokenKind.PrimitiveIntegerValue));
- assertTrue(new UriTokenizer("1234567890").next(TokenKind.PrimitiveIntegerValue));
+ assertTrue(new UriTokenizer("1").next(TokenKind.IntegerValue));
+ assertTrue(new UriTokenizer("1.").next(TokenKind.IntegerValue));
+ assertFalse(new UriTokenizer(".1").next(TokenKind.IntegerValue));
+ assertTrue(new UriTokenizer("-1").next(TokenKind.IntegerValue));
+ assertTrue(new UriTokenizer("1234567890").next(TokenKind.IntegerValue));
}
@Test
public void guid() {
- assertTrue(new UriTokenizer("12345678-abcd-ef12-1234-567890ABCDEF").next(TokenKind.PrimitiveGuidValue));
- wrongToken(TokenKind.PrimitiveGuidValue, "12345678-1234-1234-1234-123456789ABC", 'G');
+ assertTrue(new UriTokenizer("12345678-abcd-ef12-1234-567890ABCDEF").next(TokenKind.GuidValue));
+ wrongToken(TokenKind.GuidValue, "12345678-1234-1234-1234-123456789ABC", 'G');
}
@Test
public void date() {
- assertTrue(new UriTokenizer("12345-12-25").next(TokenKind.PrimitiveDateValue));
- assertTrue(new UriTokenizer("-0001-12-24").next(TokenKind.PrimitiveDateValue));
- assertFalse(new UriTokenizer("1234-13-01").next(TokenKind.PrimitiveDateValue));
- assertFalse(new UriTokenizer("1234-12-32").next(TokenKind.PrimitiveDateValue));
- assertFalse(new UriTokenizer("123-01-01").next(TokenKind.PrimitiveDateValue));
- assertFalse(new UriTokenizer("1234-00-01").next(TokenKind.PrimitiveDateValue));
- assertFalse(new UriTokenizer("1234-01-00").next(TokenKind.PrimitiveDateValue));
- wrongToken(TokenKind.PrimitiveDateValue, "2000-12-29", 'A');
- wrongToken(TokenKind.PrimitiveDateValue, "0001-01-01", 'A');
- wrongToken(TokenKind.PrimitiveDateValue, "-12345-01-31", 'A');
+ assertTrue(new UriTokenizer("12345-12-25").next(TokenKind.DateValue));
+ assertTrue(new UriTokenizer("-0001-12-24").next(TokenKind.DateValue));
+ assertFalse(new UriTokenizer("1234-13-01").next(TokenKind.DateValue));
+ assertFalse(new UriTokenizer("1234-12-32").next(TokenKind.DateValue));
+ assertFalse(new UriTokenizer("123-01-01").next(TokenKind.DateValue));
+ assertFalse(new UriTokenizer("1234-00-01").next(TokenKind.DateValue));
+ assertFalse(new UriTokenizer("1234-01-00").next(TokenKind.DateValue));
+ wrongToken(TokenKind.DateValue, "2000-12-29", 'A');
+ wrongToken(TokenKind.DateValue, "0001-01-01", 'A');
+ wrongToken(TokenKind.DateValue, "-12345-01-31", 'A');
}
@Test
public void dateTimeOffset() {
- assertTrue(new UriTokenizer("1234-12-25T11:12:13.456Z").next(TokenKind.PrimitiveDateTimeOffsetValue));
- assertTrue(new UriTokenizer("-1234-12-25t01:12z").next(TokenKind.PrimitiveDateTimeOffsetValue));
- assertTrue(new UriTokenizer("-1234-12-25T21:22:23+01:00").next(TokenKind.PrimitiveDateTimeOffsetValue));
- assertTrue(new UriTokenizer("1234-12-25T11:12:13-00:30").next(TokenKind.PrimitiveDateTimeOffsetValue));
- assertFalse(new UriTokenizer("1234-10-01").next(TokenKind.PrimitiveDateTimeOffsetValue));
- wrongToken(TokenKind.PrimitiveDateTimeOffsetValue, "-1234-12-25T11:12:13.456+01:00", 'P');
+ assertTrue(new UriTokenizer("1234-12-25T11:12:13.456Z").next(TokenKind.DateTimeOffsetValue));
+ assertTrue(new UriTokenizer("-1234-12-25t01:12z").next(TokenKind.DateTimeOffsetValue));
+ assertTrue(new UriTokenizer("-1234-12-25T21:22:23+01:00").next(TokenKind.DateTimeOffsetValue));
+ assertTrue(new UriTokenizer("1234-12-25T11:12:13-00:30").next(TokenKind.DateTimeOffsetValue));
+ assertFalse(new UriTokenizer("1234-10-01").next(TokenKind.DateTimeOffsetValue));
+ wrongToken(TokenKind.DateTimeOffsetValue, "-1234-12-25T11:12:13.456+01:00", 'P');
}
@Test
public void timeOfDay() {
- assertTrue(new UriTokenizer("11:12:13").next(TokenKind.PrimitiveTimeOfDayValue));
- assertTrue(new UriTokenizer("11:12:13.456").next(TokenKind.PrimitiveTimeOfDayValue));
- assertFalse(new UriTokenizer("24:00:00").next(TokenKind.PrimitiveTimeOfDayValue));
- assertFalse(new UriTokenizer("01:60:00").next(TokenKind.PrimitiveTimeOfDayValue));
- assertFalse(new UriTokenizer("01:00:60").next(TokenKind.PrimitiveTimeOfDayValue));
- assertFalse(new UriTokenizer("01:00:00.").next(TokenKind.PrimitiveTimeOfDayValue));
- assertFalse(new UriTokenizer("0:02:03").next(TokenKind.PrimitiveTimeOfDayValue));
- assertFalse(new UriTokenizer("01:0:03").next(TokenKind.PrimitiveTimeOfDayValue));
- assertFalse(new UriTokenizer("01:02:0").next(TokenKind.PrimitiveTimeOfDayValue));
- wrongToken(TokenKind.PrimitiveTimeOfDayValue, "11:12", '-');
+ assertTrue(new UriTokenizer("11:12:13").next(TokenKind.TimeOfDayValue));
+ assertTrue(new UriTokenizer("11:12:13.456").next(TokenKind.TimeOfDayValue));
+ assertFalse(new UriTokenizer("24:00:00").next(TokenKind.TimeOfDayValue));
+ assertFalse(new UriTokenizer("01:60:00").next(TokenKind.TimeOfDayValue));
+ assertFalse(new UriTokenizer("01:00:60").next(TokenKind.TimeOfDayValue));
+ assertFalse(new UriTokenizer("01:00:00.").next(TokenKind.TimeOfDayValue));
+ assertFalse(new UriTokenizer("0:02:03").next(TokenKind.TimeOfDayValue));
+ assertFalse(new UriTokenizer("01:0:03").next(TokenKind.TimeOfDayValue));
+ assertFalse(new UriTokenizer("01:02:0").next(TokenKind.TimeOfDayValue));
+ wrongToken(TokenKind.TimeOfDayValue, "11:12", '-');
}
@Test
public void decimal() {
- assertTrue(new UriTokenizer("1.2").next(TokenKind.PrimitiveDecimalValue));
- assertFalse(new UriTokenizer(".1").next(TokenKind.PrimitiveDecimalValue));
- assertTrue(new UriTokenizer("-12.34").next(TokenKind.PrimitiveDecimalValue));
- assertTrue(new UriTokenizer("1234567890.0123456789").next(TokenKind.PrimitiveDecimalValue));
- assertFalse(new UriTokenizer("0,1").next(TokenKind.PrimitiveDecimalValue));
- assertFalse(new UriTokenizer("0..1").next(TokenKind.PrimitiveDecimalValue));
+ assertTrue(new UriTokenizer("1.2").next(TokenKind.DecimalValue));
+ assertFalse(new UriTokenizer(".1").next(TokenKind.DecimalValue));
+ assertTrue(new UriTokenizer("-12.34").next(TokenKind.DecimalValue));
+ assertTrue(new UriTokenizer("1234567890.0123456789").next(TokenKind.DecimalValue));
+ assertFalse(new UriTokenizer("0,1").next(TokenKind.DecimalValue));
+ assertFalse(new UriTokenizer("0..1").next(TokenKind.DecimalValue));
}
@Test
public void doubleValue() {
- assertTrue(new UriTokenizer("NaN").next(TokenKind.PrimitiveDoubleValue));
- assertTrue(new UriTokenizer("-INF").next(TokenKind.PrimitiveDoubleValue));
- assertTrue(new UriTokenizer("INF").next(TokenKind.PrimitiveDoubleValue));
- assertFalse(new UriTokenizer("inf").next(TokenKind.PrimitiveDoubleValue));
- assertTrue(new UriTokenizer("1.2E3").next(TokenKind.PrimitiveDoubleValue));
- assertTrue(new UriTokenizer("-12.34e-05").next(TokenKind.PrimitiveDoubleValue));
- assertTrue(new UriTokenizer("1E2").next(TokenKind.PrimitiveDoubleValue));
- assertFalse(new UriTokenizer("1.E2").next(TokenKind.PrimitiveDoubleValue));
- wrongToken(TokenKind.PrimitiveDoubleValue, "-12.34E+5", 'i');
+ assertTrue(new UriTokenizer("NaN").next(TokenKind.DoubleValue));
+ assertTrue(new UriTokenizer("-INF").next(TokenKind.DoubleValue));
+ assertTrue(new UriTokenizer("INF").next(TokenKind.DoubleValue));
+ assertFalse(new UriTokenizer("inf").next(TokenKind.DoubleValue));
+ assertTrue(new UriTokenizer("1.2E3").next(TokenKind.DoubleValue));
+ assertTrue(new UriTokenizer("-12.34e-05").next(TokenKind.DoubleValue));
+ assertTrue(new UriTokenizer("1E2").next(TokenKind.DoubleValue));
+ assertFalse(new UriTokenizer("1.E2").next(TokenKind.DoubleValue));
+ wrongToken(TokenKind.DoubleValue, "-12.34E+5", 'i');
}
@Test
public void duration() {
- assertTrue(new UriTokenizer("duration'P'").next(TokenKind.PrimitiveDurationValue));
- assertTrue(new UriTokenizer("DURATION'P1D'").next(TokenKind.PrimitiveDurationValue));
- assertTrue(new UriTokenizer("duration'PT'").next(TokenKind.PrimitiveDurationValue));
- assertTrue(new UriTokenizer("duration'PT1H'").next(TokenKind.PrimitiveDurationValue));
- assertTrue(new UriTokenizer("duration'pt1M'").next(TokenKind.PrimitiveDurationValue));
- assertTrue(new UriTokenizer("duration'PT1S'").next(TokenKind.PrimitiveDurationValue));
- assertTrue(new UriTokenizer("duration'PT1.2s'").next(TokenKind.PrimitiveDurationValue));
- assertTrue(new UriTokenizer("duration'-p1dt2h3m4.5s'").next(TokenKind.PrimitiveDurationValue));
- assertFalse(new UriTokenizer("-p1dt2h3m4.5s").next(TokenKind.PrimitiveDurationValue));
- assertFalse(new UriTokenizer("duration'-p1dt2h3m4.5s").next(TokenKind.PrimitiveDurationValue));
- assertFalse(new UriTokenizer("duration'2h3m4s'").next(TokenKind.PrimitiveDurationValue));
- wrongToken(TokenKind.PrimitiveDurationValue, "duration'P1DT2H3M4.5S'", ':');
+ assertTrue(new UriTokenizer("duration'P'").next(TokenKind.DurationValue));
+ assertTrue(new UriTokenizer("DURATION'P1D'").next(TokenKind.DurationValue));
+ assertTrue(new UriTokenizer("duration'PT'").next(TokenKind.DurationValue));
+ assertTrue(new UriTokenizer("duration'PT1H'").next(TokenKind.DurationValue));
+ assertTrue(new UriTokenizer("duration'pt1M'").next(TokenKind.DurationValue));
+ assertTrue(new UriTokenizer("duration'PT1S'").next(TokenKind.DurationValue));
+ assertTrue(new UriTokenizer("duration'PT1.2s'").next(TokenKind.DurationValue));
+ assertTrue(new UriTokenizer("duration'-p1dt2h3m4.5s'").next(TokenKind.DurationValue));
+ assertFalse(new UriTokenizer("-p1dt2h3m4.5s").next(TokenKind.DurationValue));
+ assertFalse(new UriTokenizer("duration'-p1dt2h3m4.5s").next(TokenKind.DurationValue));
+ assertFalse(new UriTokenizer("duration'2h3m4s'").next(TokenKind.DurationValue));
+ wrongToken(TokenKind.DurationValue, "duration'P1DT2H3M4.5S'", ':');
}
@Test
public void binary() {
- assertTrue(new UriTokenizer("binary''").next(TokenKind.PrimitiveBinaryValue));
- assertTrue(new UriTokenizer("Binary'bm93'").next(TokenKind.PrimitiveBinaryValue));
+ assertTrue(new UriTokenizer("binary''").next(TokenKind.BinaryValue));
+ assertTrue(new UriTokenizer("Binary'bm93'").next(TokenKind.BinaryValue));
// all cases with three base64 characters (and one fill character) at the end
- assertTrue(new UriTokenizer("binary'QUA='").next(TokenKind.PrimitiveBinaryValue));
- assertTrue(new UriTokenizer("binary'QUE='").next(TokenKind.PrimitiveBinaryValue));
- assertTrue(new UriTokenizer("binary'QUI='").next(TokenKind.PrimitiveBinaryValue));
- assertTrue(new UriTokenizer("binary'QUM='").next(TokenKind.PrimitiveBinaryValue));
- assertTrue(new UriTokenizer("binary'QUQ='").next(TokenKind.PrimitiveBinaryValue));
- assertTrue(new UriTokenizer("binary'QUU='").next(TokenKind.PrimitiveBinaryValue));
- assertTrue(new UriTokenizer("binary'QUY='").next(TokenKind.PrimitiveBinaryValue));
- assertTrue(new UriTokenizer("binary'QUc='").next(TokenKind.PrimitiveBinaryValue));
- assertTrue(new UriTokenizer("binary'QUg='").next(TokenKind.PrimitiveBinaryValue));
- assertTrue(new UriTokenizer("binary'QUk='").next(TokenKind.PrimitiveBinaryValue));
- assertTrue(new UriTokenizer("binary'QUo='").next(TokenKind.PrimitiveBinaryValue));
- assertTrue(new UriTokenizer("binary'QUs='").next(TokenKind.PrimitiveBinaryValue));
- assertTrue(new UriTokenizer("binary'QUw='").next(TokenKind.PrimitiveBinaryValue));
- assertTrue(new UriTokenizer("binary'QU0='").next(TokenKind.PrimitiveBinaryValue));
- assertTrue(new UriTokenizer("binary'QU4='").next(TokenKind.PrimitiveBinaryValue));
- assertTrue(new UriTokenizer("binary'QU8='").next(TokenKind.PrimitiveBinaryValue));
- assertFalse(new UriTokenizer("binary'QUB='").next(TokenKind.PrimitiveBinaryValue));
+ assertTrue(new UriTokenizer("binary'QUA='").next(TokenKind.BinaryValue));
+ assertTrue(new UriTokenizer("binary'QUE='").next(TokenKind.BinaryValue));
+ assertTrue(new UriTokenizer("binary'QUI='").next(TokenKind.BinaryValue));
+ assertTrue(new UriTokenizer("binary'QUM='").next(TokenKind.BinaryValue));
+ assertTrue(new UriTokenizer("binary'QUQ='").next(TokenKind.BinaryValue));
+ assertTrue(new UriTokenizer("binary'QUU='").next(TokenKind.BinaryValue));
+ assertTrue(new UriTokenizer("binary'QUY='").next(TokenKind.BinaryValue));
+ assertTrue(new UriTokenizer("binary'QUc='").next(TokenKind.BinaryValue));
+ assertTrue(new UriTokenizer("binary'QUg='").next(TokenKind.BinaryValue));
+ assertTrue(new UriTokenizer("binary'QUk='").next(TokenKind.BinaryValue));
+ assertTrue(new UriTokenizer("binary'QUo='").next(TokenKind.BinaryValue));
+ assertTrue(new UriTokenizer("binary'QUs='").next(TokenKind.BinaryValue));
+ assertTrue(new UriTokenizer("binary'QUw='").next(TokenKind.BinaryValue));
+ assertTrue(new UriTokenizer("binary'QU0='").next(TokenKind.BinaryValue));
+ assertTrue(new UriTokenizer("binary'QU4='").next(TokenKind.BinaryValue));
+ assertTrue(new UriTokenizer("binary'QU8='").next(TokenKind.BinaryValue));
+ assertFalse(new UriTokenizer("binary'QUB='").next(TokenKind.BinaryValue));
// all cases with two base64 characters (and two fill characters) at the end
- assertTrue(new UriTokenizer("BINARY'VGVzdA=='").next(TokenKind.PrimitiveBinaryValue));
- assertTrue(new UriTokenizer("binary'U-RnZQ=='").next(TokenKind.PrimitiveBinaryValue));
- assertTrue(new UriTokenizer("binary'Yg=='").next(TokenKind.PrimitiveBinaryValue));
- assertTrue(new UriTokenizer("binary'Yw=='").next(TokenKind.PrimitiveBinaryValue));
+ assertTrue(new UriTokenizer("BINARY'VGVzdA=='").next(TokenKind.BinaryValue));
+ assertTrue(new UriTokenizer("binary'U-RnZQ=='").next(TokenKind.BinaryValue));
+ assertTrue(new UriTokenizer("binary'Yg=='").next(TokenKind.BinaryValue));
+ assertTrue(new UriTokenizer("binary'Yw=='").next(TokenKind.BinaryValue));
// without optional fill character
- assertTrue(new UriTokenizer("binary'T0RhdGE'").next(TokenKind.PrimitiveBinaryValue));
+ assertTrue(new UriTokenizer("binary'T0RhdGE'").next(TokenKind.BinaryValue));
// special character '_' (the other, '-', already has been used above)
- assertTrue(new UriTokenizer("binary'V_ZydGVy'").next(TokenKind.PrimitiveBinaryValue));
+ assertTrue(new UriTokenizer("binary'V_ZydGVy'").next(TokenKind.BinaryValue));
- wrongToken(TokenKind.PrimitiveBinaryValue, "binary'VGVzdA=='", '+');
+ wrongToken(TokenKind.BinaryValue, "binary'VGVzdA=='", '+');
}
@Test
public void enumValue() {
- assertTrue(new UriTokenizer("namespace.name'value'").next(TokenKind.PrimitiveEnumValue));
- assertTrue(new UriTokenizer("namespace.name'flag1,flag2,-3'").next(TokenKind.PrimitiveEnumValue));
- assertFalse(new UriTokenizer("namespace.name'1flag'").next(TokenKind.PrimitiveEnumValue));
- assertFalse(new UriTokenizer("namespace.name'flag1,,flag2'").next(TokenKind.PrimitiveEnumValue));
- assertFalse(new UriTokenizer("namespace.name',value'").next(TokenKind.PrimitiveEnumValue));
- assertFalse(new UriTokenizer("namespace.name'value,'").next(TokenKind.PrimitiveEnumValue));
- assertFalse(new UriTokenizer("namespace.name''").next(TokenKind.PrimitiveEnumValue));
- assertFalse(new UriTokenizer("'1'").next(TokenKind.PrimitiveEnumValue));
- assertFalse(new UriTokenizer("1").next(TokenKind.PrimitiveEnumValue));
- wrongToken(TokenKind.PrimitiveEnumValue, "namespace.name'_1,_2,3'", ';');
+ assertTrue(new UriTokenizer("namespace.name'value'").next(TokenKind.EnumValue));
+ assertTrue(new UriTokenizer("namespace.name'flag1,flag2,-3'").next(TokenKind.EnumValue));
+ assertFalse(new UriTokenizer("namespace.name'1flag'").next(TokenKind.EnumValue));
+ assertFalse(new UriTokenizer("namespace.name'flag1,,flag2'").next(TokenKind.EnumValue));
+ assertFalse(new UriTokenizer("namespace.name',value'").next(TokenKind.EnumValue));
+ assertFalse(new UriTokenizer("namespace.name'value,'").next(TokenKind.EnumValue));
+ assertFalse(new UriTokenizer("namespace.name''").next(TokenKind.EnumValue));
+ assertFalse(new UriTokenizer("'1'").next(TokenKind.EnumValue));
+ assertFalse(new UriTokenizer("1").next(TokenKind.EnumValue));
+ wrongToken(TokenKind.EnumValue, "namespace.name'_1,_2,3'", ';');
}
@Test
@@ -360,6 +365,92 @@ public class UriTokenizerTest {
wrongToken(TokenKind.jsonArrayOrObject, "[{\"name\":+123.456},null]", '\\');
}
+ @Test
+ public void operators() {
+ UriTokenizer tokenizer = new UriTokenizer("1 ne 2");
+ assertTrue(tokenizer.next(TokenKind.IntegerValue));
+ assertFalse(tokenizer.next(TokenKind.EqualsOperator));
+ assertTrue(tokenizer.next(TokenKind.NotEqualsOperator));
+ assertTrue(tokenizer.next(TokenKind.IntegerValue));
+ assertTrue(tokenizer.next(TokenKind.EOF));
+
+ tokenizer = new UriTokenizer("1ne 2");
+ assertTrue(tokenizer.next(TokenKind.IntegerValue));
+ assertFalse(tokenizer.next(TokenKind.NotEqualsOperator));
+
+ tokenizer = new UriTokenizer("1 ne2");
+ assertTrue(tokenizer.next(TokenKind.IntegerValue));
+ assertFalse(tokenizer.next(TokenKind.NotEqualsOperator));
+
+ tokenizer = new UriTokenizer("1 \tle\t\t\t2");
+ assertTrue(tokenizer.next(TokenKind.IntegerValue));
+ assertTrue(tokenizer.next(TokenKind.LessThanOrEqualsOperator));
+ assertTrue(tokenizer.next(TokenKind.IntegerValue));
+ assertTrue(tokenizer.next(TokenKind.EOF));
+
+ assertFalse(new UriTokenizer("nottrue").next(TokenKind.NotOperator));
+ assertFalse(new UriTokenizer("no true").next(TokenKind.NotOperator));
+
+ tokenizer = new UriTokenizer("true or not false and 1 eq 2 add 3 sub 4 mul 5 div 6 mod 7");
+ assertTrue(tokenizer.next(TokenKind.BooleanValue));
+ assertTrue(tokenizer.next(TokenKind.OrOperator));
+ assertTrue(tokenizer.next(TokenKind.NotOperator));
+ assertTrue(tokenizer.next(TokenKind.BooleanValue));
+ assertTrue(tokenizer.next(TokenKind.AndOperator));
+ assertTrue(tokenizer.next(TokenKind.IntegerValue));
+ assertTrue(tokenizer.next(TokenKind.EqualsOperator));
+ assertTrue(tokenizer.next(TokenKind.IntegerValue));
+ assertTrue(tokenizer.next(TokenKind.AddOperator));
+ assertTrue(tokenizer.next(TokenKind.IntegerValue));
+ assertTrue(tokenizer.next(TokenKind.SubOperator));
+ assertTrue(tokenizer.next(TokenKind.IntegerValue));
+ assertTrue(tokenizer.next(TokenKind.MulOperator));
+ assertTrue(tokenizer.next(TokenKind.IntegerValue));
+ assertTrue(tokenizer.next(TokenKind.DivOperator));
+ assertTrue(tokenizer.next(TokenKind.IntegerValue));
+ assertTrue(tokenizer.next(TokenKind.ModOperator));
+ assertTrue(tokenizer.next(TokenKind.IntegerValue));
+ assertTrue(tokenizer.next(TokenKind.EOF));
+
+ tokenizer = new UriTokenizer("1 gt 2 or 3 ge 4 or 5 lt 6");
+ assertTrue(tokenizer.next(TokenKind.IntegerValue));
+ assertTrue(tokenizer.next(TokenKind.GreaterThanOperator));
+ assertTrue(tokenizer.next(TokenKind.IntegerValue));
+ assertTrue(tokenizer.next(TokenKind.OrOperator));
+ assertTrue(tokenizer.next(TokenKind.IntegerValue));
+ assertTrue(tokenizer.next(TokenKind.GreaterThanOrEqualsOperator));
+ assertTrue(tokenizer.next(TokenKind.IntegerValue));
+ assertTrue(tokenizer.next(TokenKind.OrOperator));
+ assertTrue(tokenizer.next(TokenKind.IntegerValue));
+ assertTrue(tokenizer.next(TokenKind.LessThanOperator));
+ assertTrue(tokenizer.next(TokenKind.IntegerValue));
+ assertTrue(tokenizer.next(TokenKind.EOF));
+ }
+
+ @Test
+ public void methods() {
+ UriTokenizer tokenizer = new UriTokenizer("now()");
+ assertTrue(tokenizer.next(TokenKind.NowMethod));
+ assertTrue(tokenizer.next(TokenKind.CLOSE));
+ assertTrue(tokenizer.next(TokenKind.EOF));
+
+ assertFalse(new UriTokenizer("no w()").next(TokenKind.NowMethod));
+ assertFalse(new UriTokenizer("now ()").next(TokenKind.NowMethod));
+
+ assertTrue(new UriTokenizer("maxdatetime()").next(TokenKind.MaxdatetimeMethod));
+ assertTrue(new UriTokenizer("mindatetime()").next(TokenKind.MindatetimeMethod));
+
+ for (final TokenKind tokenKind : TokenKind.values()) {
+ if (tokenKind.name().endsWith("Method")) {
+ assertTrue(tokenKind.name(),
+ new UriTokenizer(
+ tokenKind.name().substring(0, tokenKind.name().indexOf("Method"))
+ .toLowerCase(Locale.ROOT).replace("geo", "geo.") + '(')
+ .next(tokenKind));
+ }
+ }
+ }
+
private void wrongToken(final TokenKind kind, final String value, final char disturbCharacter) {
assertFalse(new UriTokenizer(disturbCharacter + value).next(kind));
[11/30] olingo-odata4 git commit: [OLINGO-834] clean-up Expression
implementations
Posted by ch...@apache.org.
[OLINGO-834] clean-up Expression implementations
Signed-off-by: Christian Amend <ch...@sap.com>
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/208f26c7
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/208f26c7
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/208f26c7
Branch: refs/heads/master
Commit: 208f26c746263c2d5b9a14e48bae9a7091e1f839
Parents: d7e23bf
Author: Klaus Straubinger <kl...@sap.com>
Authored: Fri Dec 11 10:10:03 2015 +0100
Committer: Christian Amend <ch...@sap.com>
Committed: Fri Dec 11 12:30:10 2015 +0100
----------------------------------------------------------------------
.../core/uri/UriResourceLambdaAllImpl.java | 11 +-
.../core/uri/UriResourceLambdaAnyImpl.java | 11 +-
.../core/uri/UriResourceLambdaVarImpl.java | 4 +-
.../core/uri/expression/FilterParser.java | 562 ------------------
.../core/uri/parser/ExpressionParser.java | 575 +++++++++++++++++++
.../core/uri/parser/UriParseTreeVisitor.java | 498 ++++++----------
.../core/uri/queryoption/OrderByItemImpl.java | 8 +-
.../uri/queryoption/expression/AliasImpl.java | 14 +-
.../uri/queryoption/expression/BinaryImpl.java | 34 +-
.../queryoption/expression/EnumerationImpl.java | 28 +-
.../queryoption/expression/ExpressionImpl.java | 25 -
.../queryoption/expression/LambdaRefImpl.java | 14 +-
.../uri/queryoption/expression/LiteralImpl.java | 25 +-
.../uri/queryoption/expression/MemberImpl.java | 28 +-
.../uri/queryoption/expression/MethodImpl.java | 52 +-
.../queryoption/expression/TypeLiteralImpl.java | 14 +-
.../uri/queryoption/expression/UnaryImpl.java | 23 +-
.../core/uri/expression/FilterParserTest.java | 210 -------
.../core/uri/parser/ExpressionParserTest.java | 210 +++++++
.../server/core/uri/UriResourceImplTest.java | 8 +-
.../core/uri/queryoption/QueryOptionTest.java | 6 +-
.../queryoption/expression/ExpressionTest.java | 103 ++--
22 files changed, 1095 insertions(+), 1368 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/208f26c7/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceLambdaAllImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceLambdaAllImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceLambdaAllImpl.java
index b57d12c..d980777 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceLambdaAllImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceLambdaAllImpl.java
@@ -25,15 +25,12 @@ import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory;
import org.apache.olingo.server.api.uri.UriResourceKind;
import org.apache.olingo.server.api.uri.UriResourceLambdaAll;
import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
-import org.apache.olingo.server.core.uri.queryoption.expression.ExpressionImpl;
public class UriResourceLambdaAllImpl extends UriResourceTypedImpl implements UriResourceLambdaAll {
protected EdmProperty property;
-
private String lambdaVariable;
-
- private ExpressionImpl expression;
+ private Expression expression;
public UriResourceLambdaAllImpl() {
super(UriResourceKind.lambdaAll);
@@ -64,13 +61,13 @@ public class UriResourceLambdaAllImpl extends UriResourceTypedImpl implements Ur
return expression;
}
- public UriResourceLambdaAllImpl setExpression(final ExpressionImpl expression) {
+ public UriResourceLambdaAllImpl setExpression(final Expression expression) {
this.expression = expression;
return this;
}
-
+
@Override
- public String getSegmentValue(){
+ public String getSegmentValue() {
return "all";
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/208f26c7/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceLambdaAnyImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceLambdaAnyImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceLambdaAnyImpl.java
index 49be2fe..fe5dfee 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceLambdaAnyImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceLambdaAnyImpl.java
@@ -25,15 +25,12 @@ import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory;
import org.apache.olingo.server.api.uri.UriResourceKind;
import org.apache.olingo.server.api.uri.UriResourceLambdaAny;
import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
-import org.apache.olingo.server.core.uri.queryoption.expression.ExpressionImpl;
public class UriResourceLambdaAnyImpl extends UriResourceTypedImpl implements UriResourceLambdaAny {
protected EdmProperty property;
-
private String lambdaVariable;
-
- private ExpressionImpl expression;
+ private Expression expression;
public UriResourceLambdaAnyImpl() {
super(UriResourceKind.lambdaAny);
@@ -64,13 +61,13 @@ public class UriResourceLambdaAnyImpl extends UriResourceTypedImpl implements Ur
return expression;
}
- public UriResourceLambdaAnyImpl setExpression(final ExpressionImpl expression) {
+ public UriResourceLambdaAnyImpl setExpression(final Expression expression) {
this.expression = expression;
return this;
}
-
+
@Override
- public String getSegmentValue(){
+ public String getSegmentValue() {
return "any";
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/208f26c7/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceLambdaVarImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceLambdaVarImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceLambdaVarImpl.java
index f7fa6fc..2eb7607 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceLambdaVarImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceLambdaVarImpl.java
@@ -64,10 +64,10 @@ public class UriResourceLambdaVarImpl extends UriResourceTypedImpl implements Ur
}
@Override
- public String getSegmentValue(){
+ public String getSegmentValue() {
return variableText;
}
-
+
@Override
public String toString() {
return getSegmentValue();
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/208f26c7/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/expression/FilterParser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/expression/FilterParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/expression/FilterParser.java
deleted file mode 100644
index 32cbc1a..0000000
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/expression/FilterParser.java
+++ /dev/null
@@ -1,562 +0,0 @@
-/*
- * 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.expression;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
-import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory;
-import org.apache.olingo.server.api.uri.queryoption.expression.BinaryOperatorKind;
-import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
-import org.apache.olingo.server.api.uri.queryoption.expression.MethodKind;
-import org.apache.olingo.server.api.uri.queryoption.expression.UnaryOperatorKind;
-import org.apache.olingo.server.core.uri.queryoption.expression.AliasImpl;
-import org.apache.olingo.server.core.uri.queryoption.expression.BinaryImpl;
-import org.apache.olingo.server.core.uri.queryoption.expression.ExpressionImpl;
-import org.apache.olingo.server.core.uri.queryoption.expression.LiteralImpl;
-import org.apache.olingo.server.core.uri.queryoption.expression.MethodImpl;
-import org.apache.olingo.server.core.uri.queryoption.expression.UnaryImpl;
-
-public class FilterParser {
- private Tokenizer tokenizer;
-
- private static final Map<TokenKind, BinaryOperatorKind> tokenToBinaryOperator;
- static {
- HashMap<TokenKind, BinaryOperatorKind> temp = new HashMap<FilterParser.TokenKind, BinaryOperatorKind>();
- temp.put(TokenKind.OR_OP, BinaryOperatorKind.OR);
- temp.put(TokenKind.AND_OP, BinaryOperatorKind.AND);
-
- temp.put(TokenKind.EQ_OP, BinaryOperatorKind.EQ);
- temp.put(TokenKind.NE_OP, BinaryOperatorKind.NE);
-
- temp.put(TokenKind.GT_OP, BinaryOperatorKind.GT);
- temp.put(TokenKind.GE_OP, BinaryOperatorKind.GE);
- temp.put(TokenKind.LT_OP, BinaryOperatorKind.LT);
- temp.put(TokenKind.LE_OP, BinaryOperatorKind.LE);
-
- temp.put(TokenKind.ADD_OP, BinaryOperatorKind.ADD);
- temp.put(TokenKind.SUB_OP, BinaryOperatorKind.SUB);
-
- temp.put(TokenKind.MUL_OP, BinaryOperatorKind.MUL);
- temp.put(TokenKind.DIV_OP, BinaryOperatorKind.DIV);
- temp.put(TokenKind.MOD_OP, BinaryOperatorKind.MOD);
-
- tokenToBinaryOperator = Collections.unmodifiableMap(temp);
- }
-
- private static final Map<TokenKind, UnaryOperatorKind> tokenToUnaryOperator;
- static {
- HashMap<TokenKind, UnaryOperatorKind> temp = new HashMap<FilterParser.TokenKind, UnaryOperatorKind>();
- temp.put(TokenKind.MINUS, UnaryOperatorKind.MINUS);
- temp.put(TokenKind.NOT, UnaryOperatorKind.NOT);
- tokenToUnaryOperator = Collections.unmodifiableMap(temp);
- }
-
- private static final Map<TokenKind, MethodKind> tokenToMethod;
- static {
- HashMap<TokenKind, MethodKind> temp = new HashMap<FilterParser.TokenKind, MethodKind>();
- temp.put(TokenKind.Cast, MethodKind.CAST);
- temp.put(TokenKind.Ceiling, MethodKind.CEILING);
- temp.put(TokenKind.Concat, MethodKind.CONCAT);
- temp.put(TokenKind.Contains, MethodKind.CONTAINS);
- temp.put(TokenKind.Date, MethodKind.DATE);
- temp.put(TokenKind.Day, MethodKind.DAY);
- temp.put(TokenKind.Endswith, MethodKind.ENDSWITH);
- temp.put(TokenKind.Floor, MethodKind.FLOOR);
- temp.put(TokenKind.Fractionalseconds, MethodKind.FRACTIONALSECONDS);
- temp.put(TokenKind.GeoDistance, MethodKind.GEODISTANCE);
- temp.put(TokenKind.GeoIntersects, MethodKind.GEOINTERSECTS);
- temp.put(TokenKind.GeoLength, MethodKind.GEOLENGTH);
- temp.put(TokenKind.Hour, MethodKind.HOUR);
- temp.put(TokenKind.Indexof, MethodKind.INDEXOF);
- temp.put(TokenKind.Isof, MethodKind.ISOF);
- temp.put(TokenKind.Length, MethodKind.LENGTH);
- temp.put(TokenKind.Maxdatetime, MethodKind.MAXDATETIME);
- temp.put(TokenKind.Mindatetime, MethodKind.MINDATETIME);
- temp.put(TokenKind.Minute, MethodKind.MINUTE);
- temp.put(TokenKind.Month, MethodKind.MONTH);
- temp.put(TokenKind.Now, MethodKind.NOW);
- temp.put(TokenKind.Round, MethodKind.ROUND);
- temp.put(TokenKind.Second, MethodKind.SECOND);
- temp.put(TokenKind.Startswith, MethodKind.STARTSWITH);
- temp.put(TokenKind.Substring, MethodKind.SUBSTRING);
- temp.put(TokenKind.Time, MethodKind.TIME);
- temp.put(TokenKind.Tolower, MethodKind.TOLOWER);
- temp.put(TokenKind.Totaloffsetminutes, MethodKind.TOTALOFFSETMINUTES);
- temp.put(TokenKind.Totalseconds, MethodKind.TOTALSECONDS);
- temp.put(TokenKind.Toupper, MethodKind.TOUPPER);
- temp.put(TokenKind.Trim, MethodKind.TRIM);
- temp.put(TokenKind.Year, MethodKind.YEAR);
-
- tokenToMethod = Collections.unmodifiableMap(temp);
- }
-
- private static final Map<TokenKind, EdmPrimitiveTypeKind> tokenToPrimitiveType;
- static {
- /* Enum and null are not present in the map. These have to be handled differently */
- HashMap<TokenKind, EdmPrimitiveTypeKind> temp = new HashMap<FilterParser.TokenKind, EdmPrimitiveTypeKind>();
- temp.put(TokenKind.PrimitiveBooleanValue, EdmPrimitiveTypeKind.Boolean);
- temp.put(TokenKind.PrimitiveStringValue, EdmPrimitiveTypeKind.String);
- // TODO:Check if int64 is correct here or if it has to be single instead
- temp.put(TokenKind.PrimitiveIntegerValue, EdmPrimitiveTypeKind.Int64);
- temp.put(TokenKind.PrimitiveGuidValue, EdmPrimitiveTypeKind.Guid);
- temp.put(TokenKind.PrimitiveDateValue, EdmPrimitiveTypeKind.Date);
- temp.put(TokenKind.PrimitiveDateTimeOffsetValue, EdmPrimitiveTypeKind.DateTimeOffset);
- temp.put(TokenKind.PrimitiveTimeOfDayValue, EdmPrimitiveTypeKind.TimeOfDay);
- temp.put(TokenKind.PrimitiveDecimalValue, EdmPrimitiveTypeKind.Decimal);
- temp.put(TokenKind.PrimitiveDoubleValue, EdmPrimitiveTypeKind.Double);
- temp.put(TokenKind.PrimitiveDurationValue, EdmPrimitiveTypeKind.Duration);
- temp.put(TokenKind.PrimitiveBinaryValue, EdmPrimitiveTypeKind.Binary);
-
- tokenToPrimitiveType = Collections.unmodifiableMap(temp);
- }
-
- public Expression parse(Tokenizer tokenizer) {
- // Initialize tokenizer
- this.tokenizer = tokenizer;
-
- Expression exp = parseExpression();
- return exp;
- }
-
- private Expression parseExpression() {
- Expression left = parseAnd();
-
- while (is(TokenKind.OR_OP) != null) {
- tokenizer.getText();
-
- Expression right = parseAnd();
- left = new BinaryImpl(left, BinaryOperatorKind.OR, right);
- }
-
- return left;
- }
-
- private Expression parseAnd() {
- Expression left = parseExprEquality();
- while (is(TokenKind.AND_OP) != null) {
- tokenizer.getText();
-
- Expression right = parseExprEquality();
- left = new BinaryImpl(left, BinaryOperatorKind.AND, right);
- }
- return left;
- }
-
- private Expression parseExprEquality() {
- Expression left = parseExprRel();
-
- TokenKind nextTokenKind = is(TokenKind.EQ_OP, TokenKind.NE_OP);
- // Null for everything other than EQ or NE
- while (nextTokenKind != null) {
- tokenizer.getText();
-
- Expression right = parseExprEquality();
- left = new BinaryImpl(left, tokenToBinaryOperator.get(nextTokenKind), right);
- nextTokenKind = is(TokenKind.EQ_OP, TokenKind.NE_OP);
- }
-
- return left;
- }
-
- private Expression parseExprRel() {
- Expression left = parseExprAdd();
-
- TokenKind nextTokenKind = is(TokenKind.GT_OP, TokenKind.GE_OP, TokenKind.LT_OP, TokenKind.LE_OP);
- // Null for everything other than GT or GE or LT or LE
- while (nextTokenKind != null) {
- tokenizer.getText();
-
- Expression right = parseExprAdd();
- left = new BinaryImpl(left, tokenToBinaryOperator.get(nextTokenKind), right);
- nextTokenKind = is(TokenKind.GT_OP, TokenKind.GE_OP, TokenKind.LT_OP, TokenKind.LE_OP);
- }
-
- return left;
- }
-
- private Expression parseExprAdd() {
- Expression left = parseExprMul();
-
- TokenKind nextTokenKind = is(TokenKind.ADD_OP, TokenKind.SUB_OP);
- // Null for everything other than ADD or SUB
- while (nextTokenKind != null) {
- tokenizer.getText();
-
- Expression right = parseExprMul();
- left = new BinaryImpl(left, tokenToBinaryOperator.get(nextTokenKind), right);
- nextTokenKind = is(TokenKind.ADD_OP, TokenKind.SUB_OP);
- }
-
- return left;
- }
-
- private Expression parseExprMul() {
- Expression left = parseExprUnary();
-
- TokenKind nextTokenKind = is(TokenKind.MUL_OP, TokenKind.DIV_OP, TokenKind.MOD_OP);
- // Null for everything other than MUL or DIV or MOD
- while (nextTokenKind != null) {
- tokenizer.getText();
-
- Expression right = parseExprUnary();
- left = new BinaryImpl(left, tokenToBinaryOperator.get(nextTokenKind), right);
- nextTokenKind = is(TokenKind.MUL_OP, TokenKind.DIV_OP, TokenKind.MOD_OP);
- }
-
- return left;
- }
-
- private Expression parseExprUnary() {
- Expression left = null;
- TokenKind nextTokenKind = is(TokenKind.MINUS, TokenKind.NOT);
- // Null for everything other than - or NOT
- while (nextTokenKind != null) {
- tokenizer.getText();
-
- Expression exp = parseExprValue();
- left = new UnaryImpl(tokenToUnaryOperator.get(nextTokenKind), exp);
- nextTokenKind = is(TokenKind.MINUS, TokenKind.NOT);
- }
-
- if (left == null) {
- left = parseExprValue();
- }
-
- return left;
- }
-
- private Expression parseExprValue() {
- if (is(TokenKind.OPEN) != null) {
- tokenizer.getText();
- Expression exp = parseExpression();
- require(TokenKind.CLOSE);
- return exp;
- }
-
- if (is(TokenKind.ParameterAlias) != null) {
- return new AliasImpl(tokenizer.getText());
- }
-
- if (is(TokenKind.RootExpr) != null) {
- tokenizer.getText();
- // TODO: ConsumeRootExpression
- }
-
- TokenKind nextPrimitive = isPrimitive();
- if (nextPrimitive != null) {
- EdmPrimitiveTypeKind primitiveTypeKind = tokenToPrimitiveType.get(nextPrimitive);
- EdmPrimitiveType type;
- if (primitiveTypeKind == null) {
- if (nextPrimitive == TokenKind.PrimitiveEnumValue) {
- // TODO: Get enum type
- type = null;
- } else {
- // Null handling
- type = null;
- }
- } else {
- type = EdmPrimitiveTypeFactory.getInstance(primitiveTypeKind);
- }
- return new LiteralImpl(tokenizer.getText(), type);
- }
-
- TokenKind nextMethod = isMethod();
- if (nextMethod != null) {
- MethodImpl methodImpl = new MethodImpl(tokenToMethod.get(nextMethod));
- // Consume Method
- tokenizer.getText();
- if (is(TokenKind.CLOSE) != null) {
- // Consume closing bracket
- tokenizer.getText();
- } else {
- // TODO: Remove Cast
- methodImpl.addParameter((ExpressionImpl) parseExpression());
- while (is(TokenKind.COMMA) != null) {
- tokenizer.getText();
- methodImpl.addParameter((ExpressionImpl) parseExpression());
- }
- require(TokenKind.CLOSE);
- }
-
- validateMethodParameters(methodImpl);
-
- return methodImpl;
- }
-
- throw new RuntimeException("Unexpected token");
- }
-
- private void validateMethodParameters(MethodImpl methodImpl) {
- // We might validate parameter types in the future
- int size = methodImpl.getParameters().size();
- switch (methodImpl.getMethod()) {
- // Must have two Parameters
- case CONTAINS:
- case ENDSWITH:
- case STARTSWITH:
- case INDEXOF:
- case CONCAT:
- case GEODISTANCE:
- case GEOINTERSECTS:
- if (size != 2) {
- throw new RuntimeException("The method " + methodImpl.getMethod() + " needs exactly two parameters.");
- }
- break;
- // Must have one parameter
- case LENGTH:
- case TOLOWER:
- case TOUPPER:
- case TRIM:
- case YEAR:
- case MONTH:
- case DAY:
- case HOUR:
- case MINUTE:
- case SECOND:
- case FRACTIONALSECONDS:
- case DATE:
- case TIME:
- case TOTALOFFSETMINUTES:
- case TOTALSECONDS:
- case ROUND:
- case FLOOR:
- case CEILING:
- case GEOLENGTH:
- if (size != 1) {
- throw new RuntimeException("The method: '" + methodImpl.getMethod() + "' needs exactly one parameter.");
- }
- break;
- // Must have no parameter
- case NOW:
- case MAXDATETIME:
- case MINDATETIME:
- if (size != 0) {
- throw new RuntimeException("The method: '" + methodImpl.getMethod() + "' must have no parameters.");
- }
- break;
- // Variable parameter number
- case CAST:
- case ISOF:
- if (size == 1 || size == 2) {
- throw new RuntimeException("The method: '" + methodImpl.getMethod() + "' must have one or two parameters.");
- }
- break;
- case SUBSTRING:
- if (size == 2 || size == 3) {
- throw new RuntimeException("The method: '" + methodImpl.getMethod() + "' must have two or three parameters.");
- }
- break;
- default:
- throw new RuntimeException("Unkown method: '" + methodImpl.getMethod() + "'");
- }
- }
-
- private String require(TokenKind required) {
- if (is(required) == null) {
- throw new RuntimeException("Requred token: " + required);
- }
- return tokenizer.getText();
- }
-
- private TokenKind is(TokenKind... kind) {
- for (int i = 0; i < kind.length; i++) {
- if (tokenizer.next(kind[i])) {
- return kind[i];
- }
- }
- return null;
- }
-
- private TokenKind isMethod() {
- return is(TokenKind.Cast,
- TokenKind.Ceiling,
- TokenKind.Concat,
- TokenKind.Contains,
- TokenKind.Date,
- TokenKind.Day,
- TokenKind.Endswith,
- TokenKind.Floor,
- TokenKind.Fractionalseconds,
- TokenKind.GeoDistance,
- TokenKind.GeoIntersects,
- TokenKind.GeoLength,
- TokenKind.Hour,
- TokenKind.Indexof,
- TokenKind.Isof,
- TokenKind.Length,
- TokenKind.Maxdatetime,
- TokenKind.Mindatetime,
- TokenKind.Minute,
- TokenKind.Month,
- TokenKind.Now,
- TokenKind.Round,
- TokenKind.Second,
- TokenKind.Startswith,
- TokenKind.Substring,
- TokenKind.Time,
- TokenKind.Tolower,
- TokenKind.Totaloffsetminutes,
- TokenKind.Totalseconds,
- TokenKind.Toupper,
- TokenKind.Trim,
- TokenKind.Year);
- }
-
- private TokenKind isPrimitive() {
- return is(TokenKind.PrimitiveNullValue,
- TokenKind.PrimitiveBooleanValue,
- TokenKind.PrimitiveStringValue,
-
- // The order of the next seven expressions is important in order to avoid
- // finding partly parsed tokens (counter-intuitive as it may be, even a GUID may start with digits ...).
- TokenKind.PrimitiveDoubleValue,
- TokenKind.PrimitiveDecimalValue,
- TokenKind.PrimitiveGuidValue,
- TokenKind.PrimitiveDateTimeOffsetValue,
- TokenKind.PrimitiveDateValue,
- TokenKind.PrimitiveTimeOfDayValue,
- TokenKind.PrimitiveIntegerValue,
- TokenKind.PrimitiveDurationValue,
- TokenKind.PrimitiveBinaryValue,
- TokenKind.PrimitiveEnumValue);
- }
-
- public enum TokenKind {
- // BINARY
- OR_OP,
- AND_OP,
-
- EQ_OP,
- NE_OP,
-
- GT_OP,
- GE_OP,
- LT_OP,
- LE_OP,
-
- ADD_OP,
- SUB_OP,
-
- MUL_OP,
- DIV_OP,
- MOD_OP,
-
- MINUS,
- NOT,
-
- // Grouping
- OPEN,
- CLOSE,
-
- // PrimitiveValues
- PrimitiveNullValue,
- PrimitiveBooleanValue,
-
- PrimitiveStringValue,
- PrimitiveIntegerValue,
- PrimitiveGuidValue,
- PrimitiveDateValue,
- PrimitiveDateTimeOffsetValue,
- PrimitiveTimeOfDayValue,
- PrimitiveDecimalValue,
- PrimitiveDoubleValue,
- PrimitiveDurationValue,
- PrimitiveBinaryValue,
- PrimitiveEnumValue,
-
- // ExpressionValues
- ParameterAlias,
- ArrayOrObject,
- RootExpr,
- IT,
-
- // BuiltInMethods
- Cast,
- Ceiling,
- Concat,
- Contains,
- Date,
- Day,
- Endswith,
- Floor,
- Fractionalseconds,
- GeoDistance,
- GeoIntersects,
- GeoLength,
- Hour,
- Indexof,
- Isof,
- Length,
- Maxdatetime,
- Mindatetime,
- Minute,
- Month,
- Now,
- Round,
- Second,
- Startswith,
- Substring,
- Time,
- Tolower,
- Totaloffsetminutes,
- Totalseconds,
- Toupper,
- Trim,
- Year,
- COMMA
- }
-
- public static class Token {
- TokenKind kind;
- String text;
-
- public Token(TokenKind kind, String text) {
- this.kind = kind;
- this.text = text;
- }
- }
-
- public static class Tokenizer {
- private List<Token> tokens;
- int counter = 0;
-
- public Tokenizer(List<Token> tokens) {
- this.tokens = tokens;
- }
-
- public boolean next(TokenKind expectedKind) {
- if (counter < tokens.size() && expectedKind == tokens.get(counter).kind) {
- return true;
- }
- return false;
- }
-
- public String getText() {
- String text = tokens.get(counter).text;
- counter++;
- return text;
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/208f26c7/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java
new file mode 100644
index 0000000..854536d
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java
@@ -0,0 +1,575 @@
+/*
+ * 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.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
+import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory;
+import org.apache.olingo.server.api.uri.queryoption.expression.BinaryOperatorKind;
+import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
+import org.apache.olingo.server.api.uri.queryoption.expression.Method;
+import org.apache.olingo.server.api.uri.queryoption.expression.MethodKind;
+import org.apache.olingo.server.api.uri.queryoption.expression.UnaryOperatorKind;
+import org.apache.olingo.server.core.uri.queryoption.expression.AliasImpl;
+import org.apache.olingo.server.core.uri.queryoption.expression.BinaryImpl;
+import org.apache.olingo.server.core.uri.queryoption.expression.LiteralImpl;
+import org.apache.olingo.server.core.uri.queryoption.expression.MethodImpl;
+import org.apache.olingo.server.core.uri.queryoption.expression.UnaryImpl;
+
+public class ExpressionParser {
+ private Tokenizer tokenizer;
+
+ private static final Map<TokenKind, BinaryOperatorKind> tokenToBinaryOperator;
+ static {
+ Map<TokenKind, BinaryOperatorKind> temp = new HashMap<ExpressionParser.TokenKind, BinaryOperatorKind>();
+ temp.put(TokenKind.OR_OP, BinaryOperatorKind.OR);
+ temp.put(TokenKind.AND_OP, BinaryOperatorKind.AND);
+
+ temp.put(TokenKind.EQ_OP, BinaryOperatorKind.EQ);
+ temp.put(TokenKind.NE_OP, BinaryOperatorKind.NE);
+
+ temp.put(TokenKind.GT_OP, BinaryOperatorKind.GT);
+ temp.put(TokenKind.GE_OP, BinaryOperatorKind.GE);
+ temp.put(TokenKind.LT_OP, BinaryOperatorKind.LT);
+ temp.put(TokenKind.LE_OP, BinaryOperatorKind.LE);
+
+ temp.put(TokenKind.ADD_OP, BinaryOperatorKind.ADD);
+ temp.put(TokenKind.SUB_OP, BinaryOperatorKind.SUB);
+
+ temp.put(TokenKind.MUL_OP, BinaryOperatorKind.MUL);
+ temp.put(TokenKind.DIV_OP, BinaryOperatorKind.DIV);
+ temp.put(TokenKind.MOD_OP, BinaryOperatorKind.MOD);
+
+ tokenToBinaryOperator = Collections.unmodifiableMap(temp);
+ }
+
+ private static final Map<TokenKind, UnaryOperatorKind> tokenToUnaryOperator;
+ static {
+ Map<TokenKind, UnaryOperatorKind> temp = new HashMap<ExpressionParser.TokenKind, UnaryOperatorKind>();
+ temp.put(TokenKind.MINUS, UnaryOperatorKind.MINUS);
+ temp.put(TokenKind.NOT, UnaryOperatorKind.NOT);
+ tokenToUnaryOperator = Collections.unmodifiableMap(temp);
+ }
+
+ private static final Map<TokenKind, MethodKind> tokenToMethod;
+ static {
+ Map<TokenKind, MethodKind> temp = new HashMap<ExpressionParser.TokenKind, MethodKind>();
+ temp.put(TokenKind.Cast, MethodKind.CAST);
+ temp.put(TokenKind.Ceiling, MethodKind.CEILING);
+ temp.put(TokenKind.Concat, MethodKind.CONCAT);
+ temp.put(TokenKind.Contains, MethodKind.CONTAINS);
+ temp.put(TokenKind.Date, MethodKind.DATE);
+ temp.put(TokenKind.Day, MethodKind.DAY);
+ temp.put(TokenKind.Endswith, MethodKind.ENDSWITH);
+ temp.put(TokenKind.Floor, MethodKind.FLOOR);
+ temp.put(TokenKind.Fractionalseconds, MethodKind.FRACTIONALSECONDS);
+ temp.put(TokenKind.GeoDistance, MethodKind.GEODISTANCE);
+ temp.put(TokenKind.GeoIntersects, MethodKind.GEOINTERSECTS);
+ temp.put(TokenKind.GeoLength, MethodKind.GEOLENGTH);
+ temp.put(TokenKind.Hour, MethodKind.HOUR);
+ temp.put(TokenKind.Indexof, MethodKind.INDEXOF);
+ temp.put(TokenKind.Isof, MethodKind.ISOF);
+ temp.put(TokenKind.Length, MethodKind.LENGTH);
+ temp.put(TokenKind.Maxdatetime, MethodKind.MAXDATETIME);
+ temp.put(TokenKind.Mindatetime, MethodKind.MINDATETIME);
+ temp.put(TokenKind.Minute, MethodKind.MINUTE);
+ temp.put(TokenKind.Month, MethodKind.MONTH);
+ temp.put(TokenKind.Now, MethodKind.NOW);
+ temp.put(TokenKind.Round, MethodKind.ROUND);
+ temp.put(TokenKind.Second, MethodKind.SECOND);
+ temp.put(TokenKind.Startswith, MethodKind.STARTSWITH);
+ temp.put(TokenKind.Substring, MethodKind.SUBSTRING);
+ temp.put(TokenKind.Time, MethodKind.TIME);
+ temp.put(TokenKind.Tolower, MethodKind.TOLOWER);
+ temp.put(TokenKind.Totaloffsetminutes, MethodKind.TOTALOFFSETMINUTES);
+ temp.put(TokenKind.Totalseconds, MethodKind.TOTALSECONDS);
+ temp.put(TokenKind.Toupper, MethodKind.TOUPPER);
+ temp.put(TokenKind.Trim, MethodKind.TRIM);
+ temp.put(TokenKind.Year, MethodKind.YEAR);
+
+ tokenToMethod = Collections.unmodifiableMap(temp);
+ }
+
+ private static final Map<TokenKind, EdmPrimitiveTypeKind> tokenToPrimitiveType;
+ static {
+ /* Enum and null are not present in the map. These have to be handled differently */
+ Map<TokenKind, EdmPrimitiveTypeKind> temp = new HashMap<ExpressionParser.TokenKind, EdmPrimitiveTypeKind>();
+ temp.put(TokenKind.PrimitiveBooleanValue, EdmPrimitiveTypeKind.Boolean);
+ temp.put(TokenKind.PrimitiveStringValue, EdmPrimitiveTypeKind.String);
+ // TODO:Check if int64 is correct here or if it has to be single instead
+ temp.put(TokenKind.PrimitiveIntegerValue, EdmPrimitiveTypeKind.Int64);
+ temp.put(TokenKind.PrimitiveGuidValue, EdmPrimitiveTypeKind.Guid);
+ temp.put(TokenKind.PrimitiveDateValue, EdmPrimitiveTypeKind.Date);
+ temp.put(TokenKind.PrimitiveDateTimeOffsetValue, EdmPrimitiveTypeKind.DateTimeOffset);
+ temp.put(TokenKind.PrimitiveTimeOfDayValue, EdmPrimitiveTypeKind.TimeOfDay);
+ temp.put(TokenKind.PrimitiveDecimalValue, EdmPrimitiveTypeKind.Decimal);
+ temp.put(TokenKind.PrimitiveDoubleValue, EdmPrimitiveTypeKind.Double);
+ temp.put(TokenKind.PrimitiveDurationValue, EdmPrimitiveTypeKind.Duration);
+ temp.put(TokenKind.PrimitiveBinaryValue, EdmPrimitiveTypeKind.Binary);
+
+ tokenToPrimitiveType = Collections.unmodifiableMap(temp);
+ }
+
+ public Expression parse(Tokenizer tokenizer) throws UriParserException {
+ // Initialize tokenizer.
+ this.tokenizer = tokenizer;
+
+ return parseExpression();
+ }
+
+ private Expression parseExpression() throws UriParserException {
+ Expression left = parseAnd();
+
+ while (is(TokenKind.OR_OP) != null) {
+ tokenizer.getText();
+
+ Expression right = parseAnd();
+ left = new BinaryImpl(left, BinaryOperatorKind.OR, right);
+ }
+
+ return left;
+ }
+
+ private Expression parseAnd() throws UriParserException {
+ Expression left = parseExprEquality();
+ while (is(TokenKind.AND_OP) != null) {
+ tokenizer.getText();
+
+ Expression right = parseExprEquality();
+ left = new BinaryImpl(left, BinaryOperatorKind.AND, right);
+ }
+ return left;
+ }
+
+ private Expression parseExprEquality() throws UriParserException {
+ Expression left = parseExprRel();
+
+ TokenKind nextTokenKind = is(TokenKind.EQ_OP, TokenKind.NE_OP);
+ // Null for everything other than EQ or NE
+ while (nextTokenKind != null) {
+ tokenizer.getText();
+
+ Expression right = parseExprEquality();
+ left = new BinaryImpl(left, tokenToBinaryOperator.get(nextTokenKind), right);
+ nextTokenKind = is(TokenKind.EQ_OP, TokenKind.NE_OP);
+ }
+
+ return left;
+ }
+
+ private Expression parseExprRel() throws UriParserException {
+ Expression left = parseExprAdd();
+
+ TokenKind nextTokenKind = is(TokenKind.GT_OP, TokenKind.GE_OP, TokenKind.LT_OP, TokenKind.LE_OP);
+ // Null for everything other than GT or GE or LT or LE
+ while (nextTokenKind != null) {
+ tokenizer.getText();
+
+ Expression right = parseExprAdd();
+ left = new BinaryImpl(left, tokenToBinaryOperator.get(nextTokenKind), right);
+ nextTokenKind = is(TokenKind.GT_OP, TokenKind.GE_OP, TokenKind.LT_OP, TokenKind.LE_OP);
+ }
+
+ return left;
+ }
+
+ private Expression parseExprAdd() throws UriParserException {
+ Expression left = parseExprMul();
+
+ TokenKind nextTokenKind = is(TokenKind.ADD_OP, TokenKind.SUB_OP);
+ // Null for everything other than ADD or SUB
+ while (nextTokenKind != null) {
+ tokenizer.getText();
+
+ Expression right = parseExprMul();
+ left = new BinaryImpl(left, tokenToBinaryOperator.get(nextTokenKind), right);
+ nextTokenKind = is(TokenKind.ADD_OP, TokenKind.SUB_OP);
+ }
+
+ return left;
+ }
+
+ private Expression parseExprMul() throws UriParserException {
+ Expression left = parseExprUnary();
+
+ TokenKind nextTokenKind = is(TokenKind.MUL_OP, TokenKind.DIV_OP, TokenKind.MOD_OP);
+ // Null for everything other than MUL or DIV or MOD
+ while (nextTokenKind != null) {
+ tokenizer.getText();
+
+ Expression right = parseExprUnary();
+ left = new BinaryImpl(left, tokenToBinaryOperator.get(nextTokenKind), right);
+ nextTokenKind = is(TokenKind.MUL_OP, TokenKind.DIV_OP, TokenKind.MOD_OP);
+ }
+
+ return left;
+ }
+
+ private Expression parseExprUnary() throws UriParserException {
+ Expression left = null;
+ TokenKind nextTokenKind = is(TokenKind.MINUS, TokenKind.NOT);
+ // Null for everything other than - or NOT
+ while (nextTokenKind != null) {
+ tokenizer.getText();
+
+ Expression exp = parseExprValue();
+ left = new UnaryImpl(tokenToUnaryOperator.get(nextTokenKind), exp);
+ nextTokenKind = is(TokenKind.MINUS, TokenKind.NOT);
+ }
+
+ if (left == null) {
+ left = parseExprValue();
+ }
+
+ return left;
+ }
+
+ private Expression parseExprValue() throws UriParserException {
+ if (is(TokenKind.OPEN) != null) {
+ tokenizer.getText();
+ Expression exp = parseExpression();
+ require(TokenKind.CLOSE);
+ return exp;
+ }
+
+ if (is(TokenKind.ParameterAlias) != null) {
+ return new AliasImpl(tokenizer.getText());
+ }
+
+ if (is(TokenKind.RootExpr) != null) {
+ tokenizer.getText();
+ // TODO: Consume $root Expression.
+ }
+
+ TokenKind nextPrimitive = isPrimitive();
+ if (nextPrimitive != null) {
+ EdmPrimitiveTypeKind primitiveTypeKind = tokenToPrimitiveType.get(nextPrimitive);
+ EdmPrimitiveType type;
+ if (primitiveTypeKind == null) {
+ if (nextPrimitive == TokenKind.PrimitiveEnumValue) {
+ // TODO: Get enum type.
+ type = null;
+ } else {
+ // Null handling
+ type = null;
+ }
+ } else {
+ type = EdmPrimitiveTypeFactory.getInstance(primitiveTypeKind);
+ }
+ return new LiteralImpl(tokenizer.getText(), type);
+ }
+
+ TokenKind nextMethod = isMethod();
+ if (nextMethod != null) {
+ MethodKind methodKind = tokenToMethod.get(nextMethod);
+ List<Expression> parameters = new ArrayList<Expression>();
+ // Consume Method name.
+ tokenizer.getText();
+ if (is(TokenKind.CLOSE) != null) {
+ // Consume closing parenthesis.
+ tokenizer.getText();
+ } else {
+ parameters.add(parseExpression());
+ while (is(TokenKind.COMMA) != null) {
+ tokenizer.getText();
+ parameters.add(parseExpression());
+ }
+ require(TokenKind.CLOSE);
+ }
+
+ MethodImpl methodImpl = new MethodImpl(methodKind, parameters);
+ validateMethodParameters(methodImpl);
+
+ return methodImpl;
+ }
+
+ throw new UriParserSyntaxException("Unexpected token", UriParserSyntaxException.MessageKeys.SYNTAX);
+ }
+
+ private void validateMethodParameters(final Method method) throws UriParserException {
+ // We might validate parameter types in the future.
+ int size = method.getParameters().size();
+ switch (method.getMethod()) {
+ // Must have two Parameters.
+ case CONTAINS:
+ case ENDSWITH:
+ case STARTSWITH:
+ case INDEXOF:
+ case CONCAT:
+ case GEODISTANCE:
+ case GEOINTERSECTS:
+ if (size != 2) {
+ throw new UriParserSemanticException(
+ "The method " + method.getMethod() + " needs exactly two parameters.",
+ null); // TODO: message key
+ }
+ break;
+ // Must have one parameter.
+ case LENGTH:
+ case TOLOWER:
+ case TOUPPER:
+ case TRIM:
+ case YEAR:
+ case MONTH:
+ case DAY:
+ case HOUR:
+ case MINUTE:
+ case SECOND:
+ case FRACTIONALSECONDS:
+ case DATE:
+ case TIME:
+ case TOTALOFFSETMINUTES:
+ case TOTALSECONDS:
+ case ROUND:
+ case FLOOR:
+ case CEILING:
+ case GEOLENGTH:
+ if (size != 1) {
+ throw new UriParserSemanticException(
+ "The method '" + method.getMethod() + "' needs exactly one parameter.",
+ null); // TODO: message key
+ }
+ break;
+ // Must have no parameter.
+ case NOW:
+ case MAXDATETIME:
+ case MINDATETIME:
+ if (size != 0) {
+ throw new UriParserSemanticException("The method '" + method.getMethod() + "' must have no parameters.",
+ null); // TODO: message key
+ }
+ break;
+ // Variable parameter number
+ case CAST:
+ case ISOF:
+ if (size < 1 || size > 2) {
+ throw new UriParserSemanticException(
+ "The method '" + method.getMethod() + "' must have one or two parameters.",
+ null); // TODO: message key
+ }
+ break;
+ case SUBSTRING:
+ if (size < 2 || size > 3) {
+ throw new UriParserSemanticException(
+ "The method '" + method.getMethod() + "' must have two or three parameters.",
+ null); // TODO: message key
+ }
+ break;
+ default:
+ throw new UriParserSemanticException(
+ "Unkown method '" + method.getMethod() + "'",
+ null); // TODO: message key
+ }
+ }
+
+ private String require(TokenKind required) throws UriParserException {
+ if (is(required) == null) {
+ throw new UriParserSyntaxException("Required token: " + required,
+ UriParserSyntaxException.MessageKeys.SYNTAX);
+ }
+ return tokenizer.getText();
+ }
+
+ private TokenKind is(TokenKind... kind) {
+ for (int i = 0; i < kind.length; i++) {
+ if (tokenizer.next(kind[i])) {
+ return kind[i];
+ }
+ }
+ return null;
+ }
+
+ private TokenKind isMethod() {
+ return is(TokenKind.Cast,
+ TokenKind.Ceiling,
+ TokenKind.Concat,
+ TokenKind.Contains,
+ TokenKind.Date,
+ TokenKind.Day,
+ TokenKind.Endswith,
+ TokenKind.Floor,
+ TokenKind.Fractionalseconds,
+ TokenKind.GeoDistance,
+ TokenKind.GeoIntersects,
+ TokenKind.GeoLength,
+ TokenKind.Hour,
+ TokenKind.Indexof,
+ TokenKind.Isof,
+ TokenKind.Length,
+ TokenKind.Maxdatetime,
+ TokenKind.Mindatetime,
+ TokenKind.Minute,
+ TokenKind.Month,
+ TokenKind.Now,
+ TokenKind.Round,
+ TokenKind.Second,
+ TokenKind.Startswith,
+ TokenKind.Substring,
+ TokenKind.Time,
+ TokenKind.Tolower,
+ TokenKind.Totaloffsetminutes,
+ TokenKind.Totalseconds,
+ TokenKind.Toupper,
+ TokenKind.Trim,
+ TokenKind.Year);
+ }
+
+ private TokenKind isPrimitive() {
+ return is(TokenKind.PrimitiveNullValue,
+ TokenKind.PrimitiveBooleanValue,
+ TokenKind.PrimitiveStringValue,
+
+ // The order of the next seven expressions is important in order to avoid
+ // finding partly parsed tokens (counter-intuitive as it may be, even a GUID may start with digits ...).
+ TokenKind.PrimitiveDoubleValue,
+ TokenKind.PrimitiveDecimalValue,
+ TokenKind.PrimitiveGuidValue,
+ TokenKind.PrimitiveDateTimeOffsetValue,
+ TokenKind.PrimitiveDateValue,
+ TokenKind.PrimitiveTimeOfDayValue,
+ TokenKind.PrimitiveIntegerValue,
+ TokenKind.PrimitiveDurationValue,
+ TokenKind.PrimitiveBinaryValue,
+ TokenKind.PrimitiveEnumValue);
+ }
+
+ public enum TokenKind {
+ // BINARY
+ OR_OP,
+ AND_OP,
+
+ EQ_OP,
+ NE_OP,
+
+ GT_OP,
+ GE_OP,
+ LT_OP,
+ LE_OP,
+
+ ADD_OP,
+ SUB_OP,
+
+ MUL_OP,
+ DIV_OP,
+ MOD_OP,
+
+ MINUS,
+ NOT,
+
+ // Grouping
+ OPEN,
+ CLOSE,
+
+ // PrimitiveValues
+ PrimitiveNullValue,
+ PrimitiveBooleanValue,
+
+ PrimitiveStringValue,
+ PrimitiveIntegerValue,
+ PrimitiveGuidValue,
+ PrimitiveDateValue,
+ PrimitiveDateTimeOffsetValue,
+ PrimitiveTimeOfDayValue,
+ PrimitiveDecimalValue,
+ PrimitiveDoubleValue,
+ PrimitiveDurationValue,
+ PrimitiveBinaryValue,
+ PrimitiveEnumValue,
+
+ // ExpressionValues
+ ParameterAlias,
+ ArrayOrObject,
+ RootExpr,
+ IT,
+
+ // BuiltInMethods
+ Cast,
+ Ceiling,
+ Concat,
+ Contains,
+ Date,
+ Day,
+ Endswith,
+ Floor,
+ Fractionalseconds,
+ GeoDistance,
+ GeoIntersects,
+ GeoLength,
+ Hour,
+ Indexof,
+ Isof,
+ Length,
+ Maxdatetime,
+ Mindatetime,
+ Minute,
+ Month,
+ Now,
+ Round,
+ Second,
+ Startswith,
+ Substring,
+ Time,
+ Tolower,
+ Totaloffsetminutes,
+ Totalseconds,
+ Toupper,
+ Trim,
+ Year,
+ COMMA
+ }
+
+ public static class Token {
+ TokenKind kind;
+ String text;
+
+ public Token(TokenKind kind, String text) {
+ this.kind = kind;
+ this.text = text;
+ }
+ }
+
+ public static class Tokenizer {
+ private List<Token> tokens;
+ int counter = 0;
+
+ public Tokenizer(List<Token> tokens) {
+ this.tokens = tokens;
+ }
+
+ public boolean next(TokenKind expectedKind) {
+ if (counter < tokens.size() && expectedKind == tokens.get(counter).kind) {
+ return true;
+ }
+ return false;
+ }
+
+ public String getText() {
+ String text = tokens.get(counter).text;
+ counter++;
+ return text;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/208f26c7/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
index c58327b..3f7f70c 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
@@ -19,6 +19,7 @@
package org.apache.olingo.server.core.uri.parser;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -59,6 +60,7 @@ import org.apache.olingo.server.api.uri.UriResourcePartTyped;
import org.apache.olingo.server.api.uri.UriResourceRoot;
import org.apache.olingo.server.api.uri.queryoption.SelectItem;
import org.apache.olingo.server.api.uri.queryoption.expression.BinaryOperatorKind;
+import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
import org.apache.olingo.server.api.uri.queryoption.expression.MethodKind;
import org.apache.olingo.server.api.uri.queryoption.expression.UnaryOperatorKind;
import org.apache.olingo.server.core.uri.UriInfoImpl;
@@ -82,7 +84,9 @@ import org.apache.olingo.server.core.uri.UriResourceStartingTypeFilterImpl;
import org.apache.olingo.server.core.uri.UriResourceTypedImpl;
import org.apache.olingo.server.core.uri.UriResourceValueImpl;
import org.apache.olingo.server.core.uri.UriResourceWithKeysImpl;
-import org.apache.olingo.server.core.uri.antlr.*;
+import org.apache.olingo.server.core.uri.antlr.UriLexer;
+import org.apache.olingo.server.core.uri.antlr.UriParserBaseVisitor;
+import org.apache.olingo.server.core.uri.antlr.UriParserParser;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.AllEOFContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.AllExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltAddContext;
@@ -96,7 +100,6 @@ import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltMultContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltOrContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.AnyExprContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.ArrayOrObjectContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.BatchEOFContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.BinaryLiteralContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.BooleanNonCaseLiteralContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.CastExprContext;
@@ -197,7 +200,6 @@ import org.apache.olingo.server.core.uri.queryoption.TopOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.expression.AliasImpl;
import org.apache.olingo.server.core.uri.queryoption.expression.BinaryImpl;
import org.apache.olingo.server.core.uri.queryoption.expression.EnumerationImpl;
-import org.apache.olingo.server.core.uri.queryoption.expression.ExpressionImpl;
import org.apache.olingo.server.core.uri.queryoption.expression.LiteralImpl;
import org.apache.olingo.server.core.uri.queryoption.expression.MemberImpl;
import org.apache.olingo.server.core.uri.queryoption.expression.MethodImpl;
@@ -725,26 +727,18 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
all.setLamdaVariable(ctx.vLV.getText());
context.allowedLambdaVariables.push(var);
- all.setExpression((ExpressionImpl) ctx.vLE.accept(this));
+ all.setExpression((Expression) ctx.vLE.accept(this));
context.allowedLambdaVariables.pop();
return all;
}
@Override
- public ExpressionImpl visitAltAdd(final AltAddContext ctx) {
- BinaryImpl binary = new BinaryImpl();
-
+ public Expression visitAltAdd(final AltAddContext ctx) {
int tokenIndex = ctx.vO.getType();
-
- if (tokenIndex == UriLexer.ADD) {
- binary.setOperator(BinaryOperatorKind.ADD);
- } else if (tokenIndex == UriLexer.SUB) {
- binary.setOperator(BinaryOperatorKind.SUB);
- }
-
- binary.setLeftOperand((ExpressionImpl) ctx.vE1.accept(this));
- binary.setRightOperand((ExpressionImpl) ctx.vE2.accept(this));
- return binary;
+ return new BinaryImpl(
+ (Expression) ctx.vE1.accept(this),
+ tokenIndex == UriLexer.ADD ? BinaryOperatorKind.ADD : BinaryOperatorKind.SUB,
+ (Expression) ctx.vE2.accept(this));
}
@Override
@@ -756,14 +750,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
EdmType startType = removeUriResourceStartingTypeFilterImpl(uriInfoImplpath);
- MemberImpl ret = new MemberImpl();
-
- ret.setResourcePath(uriInfoImplpath);
- if (startType != null) {
- ret.setTypeFilter(startType);
- }
-
- return ret;
+ return new MemberImpl(uriInfoImplpath, startType);
}
private EdmType removeUriResourceStartingTypeFilterImpl(final UriInfoImpl uriInfoImplpath) {
@@ -794,14 +781,11 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
}
@Override
- public ExpressionImpl visitAltAnd(final AltAndContext ctx) {
- BinaryImpl binary = new BinaryImpl();
-
- binary.setOperator(BinaryOperatorKind.AND);
- binary.setLeftOperand((ExpressionImpl) ctx.vE1.accept(this));
- binary.setRightOperand((ExpressionImpl) ctx.vE2.accept(this));
-
- return binary;
+ public Expression visitAltAnd(final AltAndContext ctx) {
+ return new BinaryImpl(
+ (Expression) ctx.vE1.accept(this),
+ BinaryOperatorKind.AND,
+ (Expression) ctx.vE2.accept(this));
}
@Override
@@ -812,39 +796,26 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
EdmType startType = removeUriResourceStartingTypeFilterImpl(uriInfoImplpath);
- MemberImpl ret = new MemberImpl();
- ret.setResourcePath(uriInfoImplpath);
- if (startType != null) {
- ret.setTypeFilter(startType);
- }
- return ret;
- }
-
- @Override
- public Object visitBatchEOF(final BatchEOFContext ctx) {
- context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.batch);
- return null;
+ return new MemberImpl(uriInfoImplpath, startType);
}
@Override
- public ExpressionImpl visitAltComparism(final AltComparismContext ctx) {
- BinaryImpl binary = new BinaryImpl();
-
+ public Expression visitAltComparism(final AltComparismContext ctx) {
int tokenIndex = ctx.vO.getType();
-
+ BinaryOperatorKind kind = null;
if (tokenIndex == UriLexer.GT) {
- binary.setOperator(BinaryOperatorKind.GT);
+ kind = BinaryOperatorKind.GT;
} else if (tokenIndex == UriLexer.GE) {
- binary.setOperator(BinaryOperatorKind.GE);
+ kind = BinaryOperatorKind.GE;
} else if (tokenIndex == UriLexer.LT) {
- binary.setOperator(BinaryOperatorKind.LT);
+ kind = BinaryOperatorKind.LT;
} else if (tokenIndex == UriLexer.LE) {
- binary.setOperator(BinaryOperatorKind.LE);
+ kind = BinaryOperatorKind.LE;
}
-
- binary.setLeftOperand((ExpressionImpl) ctx.vE1.accept(this));
- binary.setRightOperand((ExpressionImpl) ctx.vE2.accept(this));
- return binary;
+ return new BinaryImpl(
+ (Expression) ctx.vE1.accept(this),
+ kind,
+ (Expression) ctx.vE2.accept(this));
}
@Override
@@ -867,31 +838,20 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
}
@Override
- public ExpressionImpl visitAltEquality(final AltEqualityContext ctx) {
- BinaryImpl binary = new BinaryImpl();
-
+ public Expression visitAltEquality(final AltEqualityContext ctx) {
int tokenIndex = ctx.vO.getType();
-
- if (tokenIndex == UriLexer.EQ_ALPHA) {
- binary.setOperator(BinaryOperatorKind.EQ);
- } else {
- binary.setOperator(BinaryOperatorKind.NE);
- }
- binary.setLeftOperand((ExpressionImpl) ctx.vE1.accept(this));
- binary.setRightOperand((ExpressionImpl) ctx.vE2.accept(this));
-
- return binary;
+ return new BinaryImpl(
+ (Expression) ctx.vE1.accept(this),
+ tokenIndex == UriLexer.EQ_ALPHA ? BinaryOperatorKind.EQ : BinaryOperatorKind.NE,
+ (Expression) ctx.vE2.accept(this));
}
@Override
public Object visitAltHas(final AltHasContext ctx) {
- BinaryImpl binary = new BinaryImpl();
-
- binary.setOperator(BinaryOperatorKind.HAS);
- binary.setLeftOperand((ExpressionImpl) ctx.vE1.accept(this));
- binary.setRightOperand((ExpressionImpl) ctx.vE2.accept(this));
-
- return binary;
+ return new BinaryImpl(
+ (Expression) ctx.vE1.accept(this),
+ BinaryOperatorKind.HAS,
+ (Expression) ctx.vE2.accept(this));
}
@Override
@@ -902,33 +862,28 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
}
@Override
- public ExpressionImpl visitAltMult(final AltMultContext ctx) {
- BinaryImpl binary = new BinaryImpl();
-
+ public Expression visitAltMult(final AltMultContext ctx) {
int tokenIndex = ctx.vO.getType();
-
+ BinaryOperatorKind kind;
if (tokenIndex == UriLexer.MUL) {
- binary.setOperator(BinaryOperatorKind.MUL);
+ kind = BinaryOperatorKind.MUL;
} else if (tokenIndex == UriLexer.DIV) {
- binary.setOperator(BinaryOperatorKind.DIV);
+ kind = BinaryOperatorKind.DIV;
} else {
- binary.setOperator(BinaryOperatorKind.MOD);
+ kind = BinaryOperatorKind.MOD;
}
- binary.setLeftOperand((ExpressionImpl) ctx.vE1.accept(this));
- binary.setRightOperand((ExpressionImpl) ctx.vE2.accept(this));
-
- return binary;
+ return new BinaryImpl(
+ (Expression) ctx.vE1.accept(this),
+ kind,
+ (Expression) ctx.vE2.accept(this));
}
@Override
- public ExpressionImpl visitAltOr(final AltOrContext ctx) {
- BinaryImpl binary = new BinaryImpl();
-
- binary.setOperator(BinaryOperatorKind.OR);
- binary.setLeftOperand((ExpressionImpl) ctx.vE1.accept(this));
- binary.setRightOperand((ExpressionImpl) ctx.vE2.accept(this));
-
- return binary;
+ public Expression visitAltOr(final AltOrContext ctx) {
+ return new BinaryImpl(
+ (Expression) ctx.vE1.accept(this),
+ BinaryOperatorKind.OR,
+ (Expression) ctx.vE2.accept(this));
}
@Override
@@ -954,7 +909,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
any.setLamdaVariable(ctx.vLV.getText());
context.allowedLambdaVariables.push(var);
- any.setExpression((ExpressionImpl) ctx.vLE.accept(this));
+ any.setExpression((Expression) ctx.vLE.accept(this));
context.allowedLambdaVariables.pop();
}
return any;
@@ -963,17 +918,16 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
@Override
public Object visitBooleanNonCaseLiteral(final BooleanNonCaseLiteralContext ctx) {
final String text = ctx.getText().toLowerCase();
- return new LiteralImpl().setText(text.equals("false") ? "false" : "true")
- .setType(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Boolean));
+ return new LiteralImpl(text.equals("false") ? "false" : "true",
+ EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Boolean));
}
@Override
- public ExpressionImpl visitCastExpr(final CastExprContext ctx) {
- MethodImpl method = new MethodImpl();
+ public Expression visitCastExpr(final CastExprContext ctx) {
+ List<Expression> parameters = new ArrayList<Expression>();
if (ctx.vE1 != null) {
// is optional parameter
- ExpressionImpl onExpression = (ExpressionImpl) ctx.vE1.accept(this);
- method.addParameter(onExpression);
+ parameters.add((Expression) ctx.vE1.accept(this));
}
String namespace = ctx.vNS.getText();
@@ -981,9 +935,8 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
FullQualifiedName fullName = new FullQualifiedName(namespace, ctx.vODI.getText());
EdmType type = getType(fullName);
- method.setMethod(MethodKind.CAST);
- method.addParameter(new TypeLiteralImpl().setType(type));
- return method;
+ parameters.add(new TypeLiteralImpl(type));
+ return new MethodImpl(MethodKind.CAST, parameters);
}
private EdmType getType(final FullQualifiedName fullName) {
@@ -1022,18 +975,15 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
}
@Override
- public ExpressionImpl visitCeilingMethodCallExpr(final CeilingMethodCallExprContext ctx) {
- return new MethodImpl()
- .setMethod(MethodKind.CEILING)
- .addParameter((ExpressionImpl) ctx.vE1.accept(this));
+ public Expression visitCeilingMethodCallExpr(final CeilingMethodCallExprContext ctx) {
+ return new MethodImpl(MethodKind.CEILING, Collections.singletonList((Expression) ctx.vE1.accept(this)));
}
@Override
- public ExpressionImpl visitConcatMethodCallExpr(final ConcatMethodCallExprContext ctx) {
- return new MethodImpl()
- .setMethod(MethodKind.CONCAT)
- .addParameter((ExpressionImpl) ctx.vE1.accept(this))
- .addParameter((ExpressionImpl) ctx.vE2.accept(this));
+ public Expression visitConcatMethodCallExpr(final ConcatMethodCallExprContext ctx) {
+ return new MethodImpl(MethodKind.CONCAT, Arrays.asList(
+ (Expression) ctx.vE1.accept(this),
+ (Expression) ctx.vE2.accept(this)));
}
@Override
@@ -1090,47 +1040,38 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
}
@Override
- public ExpressionImpl visitContainsMethodCallExpr(final ContainsMethodCallExprContext ctx) {
- return new MethodImpl()
- .setMethod(MethodKind.CONTAINS)
- .addParameter((ExpressionImpl) ctx.vE1.accept(this))
- .addParameter((ExpressionImpl) ctx.vE2.accept(this));
+ public Expression visitContainsMethodCallExpr(final ContainsMethodCallExprContext ctx) {
+ return new MethodImpl(MethodKind.CONTAINS, Arrays.asList(
+ (Expression) ctx.vE1.accept(this),
+ (Expression) ctx.vE2.accept(this)));
}
@Override
public Object visitDateMethodCallExpr(final DateMethodCallExprContext ctx) {
- return new MethodImpl()
- .setMethod(MethodKind.DATE)
- .addParameter((ExpressionImpl) ctx.vE1.accept(this));
+ return new MethodImpl(MethodKind.DATE, Collections.singletonList((Expression) ctx.vE1.accept(this)));
}
@Override
- public ExpressionImpl visitDayMethodCallExpr(final DayMethodCallExprContext ctx) {
- return new MethodImpl()
- .setMethod(MethodKind.DAY)
- .addParameter((ExpressionImpl) ctx.vE1.accept(this));
+ public Expression visitDayMethodCallExpr(final DayMethodCallExprContext ctx) {
+ return new MethodImpl(MethodKind.DAY, Collections.singletonList((Expression) ctx.vE1.accept(this)));
}
@Override
- public ExpressionImpl visitGeoDistanceMethodCallExpr(final GeoDistanceMethodCallExprContext ctx) {
- return new MethodImpl()
- .setMethod(MethodKind.GEODISTANCE)
- .addParameter((ExpressionImpl) ctx.vE1.accept(this))
- .addParameter((ExpressionImpl) ctx.vE2.accept(this));
+ public Expression visitGeoDistanceMethodCallExpr(final GeoDistanceMethodCallExprContext ctx) {
+ return new MethodImpl(MethodKind.GEODISTANCE, Arrays.asList(
+ (Expression) ctx.vE1.accept(this),
+ (Expression) ctx.vE2.accept(this)));
}
@Override
public Object visitEndsWithMethodCallExpr(final EndsWithMethodCallExprContext ctx) {
- return new MethodImpl()
- .setMethod(MethodKind.ENDSWITH)
- .addParameter((ExpressionImpl) ctx.vE1.accept(this))
- .addParameter((ExpressionImpl) ctx.vE2.accept(this));
+ return new MethodImpl(MethodKind.ENDSWITH, Arrays.asList(
+ (Expression) ctx.vE1.accept(this),
+ (Expression) ctx.vE2.accept(this)));
}
@Override
public Object visitEnumLiteral(final EnumLiteralContext ctx) {
- EnumerationImpl enum1 = new EnumerationImpl();
-
// get type
final String odi = ctx.vODI.getText();
@@ -1141,17 +1082,11 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
"Enum type '" + fullName.getFullQualifiedNameAsString() + "' not found!",
UriParserSemanticException.MessageKeys.UNKNOWN_TYPE, fullName.getFullQualifiedNameAsString()));
}
- enum1.setType(edmEnumType);
String valueString = ctx.vValues.getText();
valueString = valueString.substring(1, valueString.length() - 1);
-
String[] values = valueString.split(",");
- for (String item : values) {
- enum1.addValue(item);
- }
-
- return enum1;
+ return new EnumerationImpl(edmEnumType, Arrays.asList(values));
}
@Override
@@ -1343,7 +1278,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
@Override
public Object visitFilter(final FilterContext ctx) {
context.contextReadingQueryPart = true;
- final FilterOptionImpl result = new FilterOptionImpl().setExpression((ExpressionImpl) ctx.children.get(2)
+ final FilterOptionImpl result = new FilterOptionImpl().setExpression((Expression) ctx.children.get(2)
.accept(this));
context.contextReadingQueryPart = false;
@@ -1353,7 +1288,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
@Override
public Object visitFilterExpressionEOF(final FilterExpressionEOFContext ctx) {
context.contextReadingQueryPart = true;
- final FilterOptionImpl result = new FilterOptionImpl().setExpression((ExpressionImpl) ctx.children.get(0)
+ final FilterOptionImpl result = new FilterOptionImpl().setExpression((Expression) ctx.children.get(0)
.accept(this));
context.contextReadingQueryPart = false;
@@ -1361,39 +1296,30 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
}
@Override
- public ExpressionImpl visitFloorMethodCallExpr(final FloorMethodCallExprContext ctx) {
- return new MethodImpl()
- .setMethod(MethodKind.FLOOR)
- .addParameter((ExpressionImpl) ctx.vE1.accept(this));
+ public Expression visitFloorMethodCallExpr(final FloorMethodCallExprContext ctx) {
+ return new MethodImpl(MethodKind.FLOOR, Collections.singletonList((Expression) ctx.vE1.accept(this)));
}
@Override
- public ExpressionImpl visitFractionalsecondsMethodCallExpr(final FractionalsecondsMethodCallExprContext ctx) {
- return new MethodImpl()
- .setMethod(MethodKind.FRACTIONALSECONDS)
- .addParameter((ExpressionImpl) ctx.vE1.accept(this));
+ public Expression visitFractionalsecondsMethodCallExpr(final FractionalsecondsMethodCallExprContext ctx) {
+ return new MethodImpl(MethodKind.FRACTIONALSECONDS, Collections.singletonList((Expression) ctx.vE1.accept(this)));
}
@Override
- public ExpressionImpl visitGeoLengthMethodCallExpr(final GeoLengthMethodCallExprContext ctx) {
- return new MethodImpl()
- .setMethod(MethodKind.GEOLENGTH)
- .addParameter((ExpressionImpl) ctx.vE1.accept(this));
+ public Expression visitGeoLengthMethodCallExpr(final GeoLengthMethodCallExprContext ctx) {
+ return new MethodImpl(MethodKind.GEOLENGTH, Collections.singletonList((Expression) ctx.vE1.accept(this)));
}
@Override
- public ExpressionImpl visitHourMethodCallExpr(final HourMethodCallExprContext ctx) {
- return new MethodImpl()
- .setMethod(MethodKind.HOUR)
- .addParameter((ExpressionImpl) ctx.vE1.accept(this));
+ public Expression visitHourMethodCallExpr(final HourMethodCallExprContext ctx) {
+ return new MethodImpl(MethodKind.HOUR, Collections.singletonList((Expression) ctx.vE1.accept(this)));
}
@Override
- public ExpressionImpl visitIndexOfMethodCallExpr(final IndexOfMethodCallExprContext ctx) {
- return new MethodImpl()
- .setMethod(MethodKind.INDEXOF)
- .addParameter((ExpressionImpl) ctx.vE1.accept(this))
- .addParameter((ExpressionImpl) ctx.vE2.accept(this));
+ public Expression visitIndexOfMethodCallExpr(final IndexOfMethodCallExprContext ctx) {
+ return new MethodImpl(MethodKind.INDEXOF, Arrays.asList(
+ (Expression) ctx.vE1.accept(this),
+ (Expression) ctx.vE2.accept(this)));
}
@Override
@@ -1405,19 +1331,17 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
}
@Override
- public ExpressionImpl visitGeoIntersectsMethodCallExpr(final GeoIntersectsMethodCallExprContext ctx) {
- return new MethodImpl()
- .setMethod(MethodKind.GEOINTERSECTS)
- .addParameter((ExpressionImpl) ctx.vE1.accept(this))
- .addParameter((ExpressionImpl) ctx.vE2.accept(this));
+ public Expression visitGeoIntersectsMethodCallExpr(final GeoIntersectsMethodCallExprContext ctx) {
+ return new MethodImpl(MethodKind.GEOINTERSECTS, Arrays.asList(
+ (Expression) ctx.vE1.accept(this),
+ (Expression) ctx.vE2.accept(this)));
}
@Override
- public ExpressionImpl visitIsofExpr(final IsofExprContext ctx) {
- MethodImpl method = new MethodImpl();
+ public Expression visitIsofExpr(final IsofExprContext ctx) {
+ List<Expression> parameters = new ArrayList<Expression>();
if (ctx.vE1 != null) {
- ExpressionImpl onExpression = (ExpressionImpl) ctx.vE1.accept(this);
- method.addParameter(onExpression);
+ parameters.add((Expression) ctx.vE1.accept(this));
}
String namespace = ctx.vNS.getText();
@@ -1425,17 +1349,14 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
FullQualifiedName fullName = new FullQualifiedName(namespace, ctx.vODI.getText());
EdmType type = getType(fullName);
- method.setMethod(MethodKind.ISOF);
- method.addParameter(new TypeLiteralImpl().setType(type));
+ parameters.add(new TypeLiteralImpl(type));
- return method;
+ return new MethodImpl(MethodKind.ISOF, parameters);
}
@Override
- public ExpressionImpl visitLengthMethodCallExpr(final LengthMethodCallExprContext ctx) {
- return new MethodImpl()
- .setMethod(MethodKind.LENGTH)
- .addParameter((ExpressionImpl) ctx.vE1.accept(this));
+ public Expression visitLengthMethodCallExpr(final LengthMethodCallExprContext ctx) {
+ return new MethodImpl(MethodKind.LENGTH, Collections.singletonList((Expression) ctx.vE1.accept(this)));
}
@Override
@@ -1457,9 +1378,8 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
}
@Override
- public ExpressionImpl visitMaxDateTimeMethodCallExpr(final MaxDateTimeMethodCallExprContext ctx) {
- return new MethodImpl()
- .setMethod(MethodKind.MAXDATETIME);
+ public Expression visitMaxDateTimeMethodCallExpr(final MaxDateTimeMethodCallExprContext ctx) {
+ return new MethodImpl(MethodKind.MAXDATETIME, null);
}
@Override
@@ -1501,33 +1421,22 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
EdmType startType = removeUriResourceStartingTypeFilterImpl(uriInfoImplpath);
- MemberImpl ret = new MemberImpl();
- ret.setResourcePath(uriInfoImplpath);
- if (startType != null) {
- ret.setTypeFilter(startType);
- }
-
- return ret;
+ return new MemberImpl(uriInfoImplpath, startType);
}
@Override
- public ExpressionImpl visitMinDateTimeMethodCallExpr(final MinDateTimeMethodCallExprContext ctx) {
- return new MethodImpl()
- .setMethod(MethodKind.MINDATETIME);
+ public Expression visitMinDateTimeMethodCallExpr(final MinDateTimeMethodCallExprContext ctx) {
+ return new MethodImpl(MethodKind.MINDATETIME, null);
}
@Override
- public ExpressionImpl visitMinuteMethodCallExpr(final MinuteMethodCallExprContext ctx) {
- return new MethodImpl()
- .setMethod(MethodKind.MINUTE)
- .addParameter((ExpressionImpl) ctx.vE1.accept(this));
+ public Expression visitMinuteMethodCallExpr(final MinuteMethodCallExprContext ctx) {
+ return new MethodImpl(MethodKind.MINUTE, Collections.singletonList((Expression) ctx.vE1.accept(this)));
}
@Override
- public ExpressionImpl visitMonthMethodCallExpr(final MonthMethodCallExprContext ctx) {
- return new MethodImpl()
- .setMethod(MethodKind.MONTH)
- .addParameter((ExpressionImpl) ctx.vE1.accept(this));
+ public Expression visitMonthMethodCallExpr(final MonthMethodCallExprContext ctx) {
+ return new MethodImpl(MethodKind.MONTH, Collections.singletonList((Expression) ctx.vE1.accept(this)));
}
@Override
@@ -1537,9 +1446,9 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
// is single key predicate without a name
String valueText = ctx.vVO.getText();
- ExpressionImpl expression = null;
+ Expression expression = null;
try {
- expression = (ExpressionImpl) ctx.vVO.accept(this);
+ expression = (Expression) ctx.vVO.accept(this);
} catch (final RuntimeException e) {
throw wrap(new UriParserSemanticException("Invalid key value: " + valueText, e,
UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, valueText));
@@ -1763,7 +1672,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
if (ctx.vCOM != null) {
final String text = ctx.vCOM.getText();
uriParameter.setText("null".equals(text) ? null : text);
- uriParameter.setExpression((ExpressionImpl) ctx.vCOM.accept(this));
+ uriParameter.setExpression((Expression) ctx.vCOM.accept(this));
} else {
uriParameter.setAlias("@" + ctx.vALI.getText());
}
@@ -1773,29 +1682,20 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
@Override
public Object visitNaninfinityLiteral(final NaninfinityLiteralContext ctx) {
- return new LiteralImpl().setType(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal)).setText(ctx
- .getText());
+ return new LiteralImpl(ctx.getText(),
+ EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal));
}
@Override
- public ExpressionImpl visitNowMethodCallExpr(final NowMethodCallExprContext ctx) {
- return new MethodImpl()
- .setMethod(MethodKind.NOW);
+ public Expression visitNowMethodCallExpr(final NowMethodCallExprContext ctx) {
+ return new MethodImpl(MethodKind.NOW, null);
}
@Override
public Object visitNullruleLiteral(final NullruleLiteralContext ctx) {
- return new LiteralImpl().setText("null");
+ return new LiteralImpl("null", null);
}
- /*
- * @Override
- * public Object visitOdataRelativeUriEOF(final OdataRelativeUriEOFContext ctx) {
- * contextUriInfo = null;
- * super.visitOdataRelativeUriEOF(ctx);
- * return contextUriInfo;
- * }
- */
@Override
public Object visitOrderBy(final OrderByContext ctx) {
@@ -1831,7 +1731,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
oItem.setDescending(true);
}
- oItem.setExpression((ExpressionImpl) ctx.vC.accept(this));
+ oItem.setExpression((Expression) ctx.vC.accept(this));
return oItem;
}
@@ -1906,19 +1806,19 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
}
// TODO Implement geography types and set a proper type
- return new LiteralImpl().setText(ctx.getText());
+ return new LiteralImpl(ctx.getText(), null);
}
@Override
public Object visitBinaryLiteral(BinaryLiteralContext ctx) {
- return new LiteralImpl().setText(ctx.getText())
- .setType(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Binary));
+ return new LiteralImpl(ctx.getText(),
+ EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Binary));
}
@Override
public Object visitStringLiteral(final StringLiteralContext ctx) {
- return new LiteralImpl().setText(ctx.getText())
- .setType(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.String));
+ return new LiteralImpl(ctx.getText(),
+ EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.String));
}
@Override
@@ -1928,7 +1828,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
EdmPrimitiveTypeKind.Double :
EdmPrimitiveTypeKind.Decimal);
- return new LiteralImpl().setText(ctx.getText()).setType(type);
+ return new LiteralImpl(ctx.getText(), type);
}
@Override
@@ -1948,41 +1848,41 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
typeKind = EdmPrimitiveTypeKind.Int64;
}
} catch (NumberFormatException e) {
- return new LiteralImpl().setText(ctx.getText())
- .setType(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal));
+ return new LiteralImpl(ctx.getText(),
+ EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal));
}
- return new LiteralImpl().setText(ctx.getText())
- .setType(EdmPrimitiveTypeFactory.getInstance(typeKind));
+ return new LiteralImpl(ctx.getText(),
+ EdmPrimitiveTypeFactory.getInstance(typeKind));
}
@Override
public Object visitDateLiteral(final DateLiteralContext ctx) {
- return new LiteralImpl().setText(ctx.getText())
- .setType(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Date));
+ return new LiteralImpl(ctx.getText(),
+ EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Date));
}
@Override
public Object visitDatetimeoffsetLiteral(final DatetimeoffsetLiteralContext ctx) {
- return new LiteralImpl().setText(ctx.getText())
- .setType(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.DateTimeOffset));
+ return new LiteralImpl(ctx.getText(),
+ EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.DateTimeOffset));
}
@Override
public Object visitDurationLiteral(final DurationLiteralContext ctx) {
- return new LiteralImpl().setText(ctx.getText())
- .setType(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Duration));
+ return new LiteralImpl(ctx.getText(),
+ EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Duration));
}
@Override
public Object visitGuidLiteral(final GuidLiteralContext ctx) {
- return new LiteralImpl().setText(ctx.getText())
- .setType(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Guid));
+ return new LiteralImpl(ctx.getText(),
+ EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Guid));
}
@Override
public Object visitTimeofdayLiteral(final TimeofdayLiteralContext ctx) {
- return new LiteralImpl().setText(ctx.getText())
- .setType(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.TimeOfDay));
+ return new LiteralImpl(ctx.getText(),
+ EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.TimeOfDay));
}
@Override
@@ -1996,21 +1896,6 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
return qpList;
}
- /*
- * @Override
- * public Object visitResourcePath(final ResourcePathContext ctx) {
- * if (ctx.vAll != null) {
- * contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.all);
- * } else if (ctx.vCJ != null) {
- * ctx.vCJ.accept(this);
- * } else if (ctx.vlPS != null) {
- * UriInfoImpl uriInfoPath = new UriInfoImpl().setKind(UriInfoKind.resource);
- * contextUriInfo = uriInfoPath;
- * super.visitResourcePath(ctx); // visit all children of ctx
- * }
- * return contextUriInfo;
- * }
- */
@Override
public Object visitRootExpr(final RootExprContext ctx) {
@@ -2042,23 +1927,18 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
context.contextUriInfo = backupUriInfoPath;
}
- return new MemberImpl()
- .setResourcePath(uriInfoImplpath);
+ return new MemberImpl(uriInfoImplpath, null);
}
@Override
- public ExpressionImpl visitRoundMethodCallExpr(final RoundMethodCallExprContext ctx) {
- return new MethodImpl()
- .setMethod(MethodKind.ROUND)
- .addParameter((ExpressionImpl) ctx.vE1.accept(this));
+ public Expression visitRoundMethodCallExpr(final RoundMethodCallExprContext ctx) {
+ return new MethodImpl(MethodKind.ROUND, Collections.singletonList((Expression) ctx.vE1.accept(this)));
}
@Override
- public ExpressionImpl visitSecondMethodCallExpr(final SecondMethodCallExprContext ctx) {
- return new MethodImpl()
- .setMethod(MethodKind.SECOND)
- .addParameter((ExpressionImpl) ctx.vE1.accept(this));
+ public Expression visitSecondMethodCallExpr(final SecondMethodCallExprContext ctx) {
+ return new MethodImpl(MethodKind.SECOND, Collections.singletonList((Expression) ctx.vE1.accept(this)));
}
@Override
@@ -2344,33 +2224,28 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
}
@Override
- public ExpressionImpl visitStartsWithMethodCallExpr(final StartsWithMethodCallExprContext ctx) {
- return new MethodImpl()
- .setMethod(MethodKind.STARTSWITH)
- .addParameter((ExpressionImpl) ctx.vE1.accept(this))
- .addParameter((ExpressionImpl) ctx.vE2.accept(this));
+ public Expression visitStartsWithMethodCallExpr(final StartsWithMethodCallExprContext ctx) {
+ return new MethodImpl(MethodKind.STARTSWITH, Arrays.asList(
+ (Expression) ctx.vE1.accept(this),
+ (Expression) ctx.vE2.accept(this)));
}
@Override
- public ExpressionImpl visitSubstringMethodCallExpr(final SubstringMethodCallExprContext ctx) {
- MethodImpl ret = new MethodImpl();
- ret.setMethod(MethodKind.SUBSTRING);
- ret.addParameter((ExpressionImpl) ctx.vE1.accept(this));
- ret.addParameter((ExpressionImpl) ctx.vE2.accept(this));
+ public Expression visitSubstringMethodCallExpr(final SubstringMethodCallExprContext ctx) {
+ List<Expression> parameters = new ArrayList<Expression>();
+ parameters.add((Expression) ctx.vE1.accept(this));
+ parameters.add((Expression) ctx.vE2.accept(this));
if (ctx.vE3 != null) {
- ret.addParameter((ExpressionImpl) ctx.vE3.accept(this));
+ parameters.add((Expression) ctx.vE3.accept(this));
}
- return ret;
-
+ return new MethodImpl(MethodKind.SUBSTRING, parameters);
}
@Override
- public ExpressionImpl visitTimeMethodCallExpr(final TimeMethodCallExprContext ctx) {
- return new MethodImpl()
- .setMethod(MethodKind.TIME)
- .addParameter((ExpressionImpl) ctx.vE1.accept(this));
+ public Expression visitTimeMethodCallExpr(final TimeMethodCallExprContext ctx) {
+ return new MethodImpl(MethodKind.TIME, Collections.singletonList((Expression) ctx.vE1.accept(this)));
}
@Override
@@ -2382,45 +2257,33 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
}
@Override
- public ExpressionImpl visitToLowerMethodCallExpr(final ToLowerMethodCallExprContext ctx) {
- return new MethodImpl()
- .setMethod(MethodKind.TOLOWER)
- .addParameter((ExpressionImpl) ctx.vE1.accept(this));
+ public Expression visitToLowerMethodCallExpr(final ToLowerMethodCallExprContext ctx) {
+ return new MethodImpl(MethodKind.TOLOWER, Collections.singletonList((Expression) ctx.vE1.accept(this)));
}
@Override
- public ExpressionImpl visitTotalOffsetMinutesMethodCallExpr(final TotalOffsetMinutesMethodCallExprContext ctx) {
- return new MethodImpl()
- .setMethod(MethodKind.TOTALOFFSETMINUTES)
- .addParameter((ExpressionImpl) ctx.vE1.accept(this));
+ public Expression visitTotalOffsetMinutesMethodCallExpr(final TotalOffsetMinutesMethodCallExprContext ctx) {
+ return new MethodImpl(MethodKind.TOTALOFFSETMINUTES, Collections.singletonList((Expression) ctx.vE1.accept(this)));
}
@Override
- public ExpressionImpl visitTotalsecondsMethodCallExpr(final TotalsecondsMethodCallExprContext ctx) {
- return new MethodImpl()
- .setMethod(MethodKind.TOTALSECONDS)
- .addParameter((ExpressionImpl) ctx.vE1.accept(this));
+ public Expression visitTotalsecondsMethodCallExpr(final TotalsecondsMethodCallExprContext ctx) {
+ return new MethodImpl(MethodKind.TOTALSECONDS, Collections.singletonList((Expression) ctx.vE1.accept(this)));
}
@Override
- public ExpressionImpl visitToUpperMethodCallExpr(final ToUpperMethodCallExprContext ctx) {
- return new MethodImpl()
- .setMethod(MethodKind.TOUPPER)
- .addParameter((ExpressionImpl) ctx.vE1.accept(this));
+ public Expression visitToUpperMethodCallExpr(final ToUpperMethodCallExprContext ctx) {
+ return new MethodImpl(MethodKind.TOUPPER, Collections.singletonList((Expression) ctx.vE1.accept(this)));
}
@Override
- public ExpressionImpl visitTrimMethodCallExpr(final TrimMethodCallExprContext ctx) {
- return new MethodImpl()
- .setMethod(MethodKind.TRIM)
- .addParameter((ExpressionImpl) ctx.vE1.accept(this));
+ public Expression visitTrimMethodCallExpr(final TrimMethodCallExprContext ctx) {
+ return new MethodImpl(MethodKind.TRIM, Collections.singletonList((Expression) ctx.vE1.accept(this)));
}
@Override
- public ExpressionImpl visitYearMethodCallExpr(final YearMethodCallExprContext ctx) {
- return new MethodImpl()
- .setMethod(MethodKind.YEAR)
- .addParameter((ExpressionImpl) ctx.vE1.accept(this));
+ public Expression visitYearMethodCallExpr(final YearMethodCallExprContext ctx) {
+ return new MethodImpl(MethodKind.YEAR, Collections.singletonList((Expression) ctx.vE1.accept(this)));
}
private ParseCancellationException wrap(final UriParserException uriParserException) {
@@ -2428,18 +2291,15 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
}
@Override
- public ExpressionImpl visitAltUnary(@NotNull final UriParserParser.AltUnaryContext ctx) {
- UnaryImpl unary = new UnaryImpl();
- unary.setOperator(ctx.unary().NOT() == null ? UnaryOperatorKind.MINUS : UnaryOperatorKind.NOT);
- unary.setOperand((ExpressionImpl) ctx.commonExpr().accept(this));
- return unary;
+ public Expression visitAltUnary(@NotNull final UriParserParser.AltUnaryContext ctx) {
+ return new UnaryImpl(
+ ctx.unary().NOT() == null ? UnaryOperatorKind.MINUS : UnaryOperatorKind.NOT,
+ (Expression) ctx.commonExpr().accept(this));
}
@Override
- public ExpressionImpl visitAltAlias(@NotNull final UriParserParser.AltAliasContext ctx) {
- AliasImpl alias = new AliasImpl();
- alias.setParameter("@" + ctx.odataIdentifier().getChild(0).getText());
- return alias;
+ public Expression visitAltAlias(@NotNull final UriParserParser.AltAliasContext ctx) {
+ return new AliasImpl("@" + ctx.odataIdentifier().getChild(0).getText());
}
@Override
@@ -2455,7 +2315,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
MessageKeys.COMPLEX_PARAMETER_IN_RESOURCE_PATH, ctx.getText()));
}
- return new LiteralImpl().setText(ctx.getText()).setType(null);
+ return new LiteralImpl(ctx.getText(), null);
}
@Override
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/208f26c7/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/OrderByItemImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/OrderByItemImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/OrderByItemImpl.java
index aac33f0..71c728c 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/OrderByItemImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/OrderByItemImpl.java
@@ -19,11 +19,11 @@
package org.apache.olingo.server.core.uri.queryoption;
import org.apache.olingo.server.api.uri.queryoption.OrderByItem;
-import org.apache.olingo.server.core.uri.queryoption.expression.ExpressionImpl;
+import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
public class OrderByItemImpl implements OrderByItem {
- private ExpressionImpl expression;
+ private Expression expression;
private boolean descending = false; // default sort order is ascending
@Override
@@ -37,11 +37,11 @@ public class OrderByItemImpl implements OrderByItem {
}
@Override
- public ExpressionImpl getExpression() {
+ public Expression getExpression() {
return expression;
}
- public OrderByItem setExpression(final ExpressionImpl expression) {
+ public OrderByItem setExpression(final Expression expression) {
this.expression = expression;
return this;
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/208f26c7/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/AliasImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/AliasImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/AliasImpl.java
index 5309d73..c7d7c20 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/AliasImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/AliasImpl.java
@@ -23,15 +23,11 @@ import org.apache.olingo.server.api.uri.queryoption.expression.Alias;
import org.apache.olingo.server.api.uri.queryoption.expression.ExpressionVisitException;
import org.apache.olingo.server.api.uri.queryoption.expression.ExpressionVisitor;
-public class AliasImpl extends ExpressionImpl implements Alias {
+public class AliasImpl implements Alias {
- private String parameterName;
+ private final String parameterName;
- public AliasImpl() {
- //TODO: Delete Constructor
- }
-
- public AliasImpl(String parameterName) {
+ public AliasImpl(final String parameterName) {
this.parameterName = parameterName;
}
@@ -40,10 +36,6 @@ public class AliasImpl extends ExpressionImpl implements Alias {
return parameterName;
}
- public void setParameter(final String ParameterName) {
- parameterName = ParameterName;
- }
-
@Override
public <T> T accept(final ExpressionVisitor<T> visitor) throws ExpressionVisitException, ODataApplicationException {
return visitor.visitAlias(parameterName);
[08/30] olingo-odata4 git commit: [OLINGO-834] $select parser in Java
+ clean-up
Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/d7e23bf8/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
index 87e09ad..8051573 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
@@ -39,7 +39,11 @@ public class UriTokenizer {
CLOSE,
COMMA,
SEMI,
+ DOT,
+ SLASH,
EQ,
+ STAR,
+ PLUS,
NULL,
// variable-value tokens (convention: mixed case)
@@ -63,18 +67,18 @@ public class UriTokenizer {
jsonArrayOrObject
}
- private final String pathSegment;
+ private final String parseString;
private int startIndex = 0;
private int index = 0;
- public UriTokenizer(final String pathSegment) {
- this.pathSegment = pathSegment == null ? "" : pathSegment;
+ public UriTokenizer(final String parseString) {
+ this.parseString = parseString == null ? "" : parseString;
}
/** Returns the string value corresponding to the last successful {@link #next(TokenKind)} call. */
public String getText() {
- return pathSegment.substring(startIndex, index);
+ return parseString.substring(startIndex, index);
}
/**
@@ -119,14 +123,26 @@ public class UriTokenizer {
case SEMI:
found = nextCharacter(';');
break;
+ case DOT:
+ found = nextCharacter('.');
+ break;
+ case SLASH:
+ found = nextCharacter('/');
+ break;
case EQ:
found = nextCharacter('=');
break;
+ case STAR:
+ found = nextCharacter('*');
+ break;
+ case PLUS:
+ found = nextCharacter('+');
+ break;
case NULL:
found = nextConstant("null");
break;
case EOF:
- found = index >= pathSegment.length();
+ found = index >= parseString.length();
break;
// Identifiers
@@ -192,8 +208,12 @@ public class UriTokenizer {
return found;
}
+ /**
+ * Moves past the given string constant if found; otherwise leaves the index unchanged.
+ * @return whether the constant has been found at the current index
+ */
private boolean nextConstant(final String constant) {
- if (pathSegment.startsWith(constant, index)) {
+ if (parseString.startsWith(constant, index)) {
index += constant.length();
return true;
} else {
@@ -201,10 +221,14 @@ public class UriTokenizer {
}
}
+ /**
+ * Moves past the given string constant, ignoring case, if found; otherwise leaves the index unchanged.
+ * @return whether the constant has been found at the current index
+ */
private boolean nextConstantIgnoreCase(final String constant) {
final int length = constant.length();
- if (index + length <= pathSegment.length()
- && constant.equalsIgnoreCase(pathSegment.substring(index, index + length))) {
+ if (index + length <= parseString.length()
+ && constant.equalsIgnoreCase(parseString.substring(index, index + length))) {
index += length;
return true;
} else {
@@ -217,7 +241,7 @@ public class UriTokenizer {
* @return whether the given character has been found at the current index
*/
private boolean nextCharacter(final char character) {
- if (index < pathSegment.length() && pathSegment.charAt(index) == character) {
+ if (index < parseString.length() && parseString.charAt(index) == character) {
index++;
return true;
} else {
@@ -231,8 +255,8 @@ public class UriTokenizer {
* @return whether the given character has been found at the current index
*/
private boolean nextCharacterRange(final char from, final char to) {
- if (index < pathSegment.length()) {
- final char code = pathSegment.charAt(index);
+ if (index < parseString.length()) {
+ final char code = parseString.charAt(index);
if (code >= from && code <= to) {
index++;
return true;
@@ -276,16 +300,20 @@ public class UriTokenizer {
return nextCharacter('+') || nextCharacter('-');
}
+ /**
+ * Moves past an OData identifier if found; otherwise leaves the index unchanged.
+ * @return whether an OData identifier has been found at the current index
+ */
private boolean nextODataIdentifier() {
int count = 0;
- if (index < pathSegment.length()) {
- int code = pathSegment.codePointAt(index);
+ if (index < parseString.length()) {
+ int code = parseString.codePointAt(index);
if (Character.isUnicodeIdentifierStart(code) || code == '_') {
count++;
// Unicode characters outside of the Basic Multilingual Plane are represented as two Java characters.
index += Character.isSupplementaryCodePoint(code) ? 2 : 1;
- while (index < pathSegment.length() && count < 128) {
- code = pathSegment.codePointAt(index);
+ while (index < parseString.length() && count < 128) {
+ code = parseString.codePointAt(index);
if (Character.isUnicodeIdentifierPart(code) && !Character.isISOControl(code)) {
count++;
// Unicode characters outside of the Basic Multilingual Plane are represented as two Java characters.
@@ -299,16 +327,30 @@ public class UriTokenizer {
return count > 0;
}
+ /**
+ * Moves past a qualified name if found; otherwise leaves the index unchanged.
+ * @return whether a qualified name has been found at the current index
+ */
private boolean nextQualifiedName() {
- int count = 0;
- do {
+ final int lastGoodIndex = index;
+ if (!nextODataIdentifier()) {
+ return false;
+ }
+ int count = 1;
+ while (nextCharacter('.')) {
if (nextODataIdentifier()) {
count++;
} else {
- return false;
+ index--;
+ break;
}
- } while (nextCharacter('.'));
- return count >= 2;
+ }
+ if (count >= 2) {
+ return true;
+ } else {
+ index = lastGoodIndex;
+ return false;
+ }
}
private boolean nextParameterAliasName() {
@@ -323,12 +365,12 @@ public class UriTokenizer {
if (!nextCharacter('\'')) {
return false;
}
- while (index < pathSegment.length()) {
- if (pathSegment.charAt(index) == '\'') {
+ while (index < parseString.length()) {
+ if (parseString.charAt(index) == '\'') {
// If a single quote is followed by another single quote,
// it represents one single quote within the string literal,
// otherwise it marks the end of the string literal.
- if (index + 1 < pathSegment.length() && pathSegment.charAt(index + 1) == '\'') {
+ if (index + 1 < parseString.length() && parseString.charAt(index + 1) == '\'') {
index++;
} else {
break;
@@ -339,7 +381,13 @@ public class UriTokenizer {
return nextCharacter('\'');
}
+ /**
+ * Moves past an integer value if found; otherwise leaves the index unchanged.
+ * @param signed whether a sign character ('+' or '-') at the beginning is allowed
+ * @return whether an integer value has been found at the current index
+ */
private boolean nextIntegerValue(final boolean signed) {
+ final int lastGoodIndex = index;
if (signed) {
nextSign();
}
@@ -347,33 +395,53 @@ public class UriTokenizer {
while (nextDigit()) {
hasDigits = true;
}
- return hasDigits;
+ if (hasDigits) {
+ return true;
+ } else {
+ index = lastGoodIndex;
+ return false;
+ }
}
- /** Finds and returns only decimal-number tokens with a fractional part.
- * Whole numbers must be found with {@link #nextIntegerValue()}.
+ /**
+ * Moves past a decimal value with a fractional part if found; otherwise leaves the index unchanged.
+ * Whole numbers must be found with {@link #nextIntegerValue()}.
*/
private boolean nextDecimalValue() {
- return nextIntegerValue(true) && nextCharacter('.') && nextIntegerValue(false);
+ final int lastGoodIndex = index;
+ if (nextIntegerValue(true) && nextCharacter('.') && nextIntegerValue(false)) {
+ return true;
+ } else {
+ index = lastGoodIndex;
+ return false;
+ }
}
/**
- * Finds and returns only floating-point-number tokens with an exponential part
- * and the special three constants "NaN", "-INF", and "INF".
- * Whole numbers must be found with {@link #nextIntegerValue()}.
- * Decimal numbers must be found with {@link #nextDecimalValue()}.
+ * Moves past a floating-point-number value with an exponential part
+ * or one of the special constants "NaN", "-INF", and "INF"
+ * if found; otherwise leaves the index unchanged.
+ * Whole numbers must be found with {@link #nextIntegerValue()}.
+ * Decimal numbers must be found with {@link #nextDecimalValue()}.
*/
private boolean nextDoubleValue() {
if (nextConstant("NaN") || nextConstant("-INF") || nextConstant("INF")) {
return true;
} else {
+ final int lastGoodIndex = index;
if (!nextIntegerValue(true)) {
return false;
}
if (nextCharacter('.') && !nextIntegerValue(false)) {
+ index = lastGoodIndex;
+ return false;
+ }
+ if ((nextCharacter('E') || nextCharacter('e')) && nextIntegerValue(true)) {
+ return true;
+ } else {
+ index = lastGoodIndex;
return false;
}
- return (nextCharacter('E') || nextCharacter('e')) && nextIntegerValue(true);
}
}
@@ -533,7 +601,12 @@ public class UriTokenizer {
return false;
}
+ /**
+ * Moves past a JSON string if found; otherwise leaves the index unchanged.
+ * @return whether a JSON string has been found at the current index
+ */
private boolean nextJsonString() {
+ final int lastGoodIndex = index;
if (nextCharacter('"')) {
do {
if (nextCharacter('\\')) {
@@ -541,6 +614,7 @@ public class UriTokenizer {
|| nextCharacter('n') || nextCharacter('f') || nextCharacter('r')
|| nextCharacter('"') || nextCharacter('/') || nextCharacter('\\')
|| nextCharacter('u') && nextHexDigit() && nextHexDigit() && nextHexDigit() && nextHexDigit())) {
+ index = lastGoodIndex;
return false;
}
} else if (nextCharacter('"')) {
@@ -548,16 +622,17 @@ public class UriTokenizer {
} else {
index++;
}
- } while (index < pathSegment.length());
+ } while (index < parseString.length());
+ index = lastGoodIndex;
return false;
}
+ index = lastGoodIndex;
return false;
}
private boolean nextJsonValue() {
return nextConstant("null") || nextConstant("true") || nextConstant("false")
- // If a double or decimal number is not found, the index must be reset; the internal methods don't do that.
- || next(TokenKind.PrimitiveDoubleValue) || next(TokenKind.PrimitiveDecimalValue) || nextIntegerValue(true)
+ || nextDoubleValue() || nextDecimalValue() || nextIntegerValue(true)
|| nextJsonString()
|| nextJsonArrayOrObject();
}
@@ -566,25 +641,42 @@ public class UriTokenizer {
return nextJsonString() && nextCharacter(':') && nextJsonValue();
}
+ /**
+ * Moves past a JSON array or object if found; otherwise leaves the index unchanged.
+ * @return whether a JSON array or object has been found at the current index
+ */
private boolean nextJsonArrayOrObject() {
+ final int lastGoodIndex = index;
if (nextCharacter('[')) {
if (nextJsonValue()) {
while (nextCharacter(',')) {
if (!nextJsonValue()) {
+ index = lastGoodIndex;
return false;
}
}
}
- return nextCharacter(']');
+ if (nextCharacter(']')) {
+ return true;
+ } else {
+ index = lastGoodIndex;
+ return false;
+ }
} else if (nextCharacter('{')) {
if (nextJsonMember()) {
while (nextCharacter(',')) {
if (!nextJsonMember()) {
+ index = lastGoodIndex;
return false;
}
}
}
- return nextCharacter('}');
+ if (nextCharacter('}')) {
+ return true;
+ } else {
+ index = lastGoodIndex;
+ return false;
+ }
} else {
return false;
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/d7e23bf8/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/UriInfoImplTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/UriInfoImplTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/UriInfoImplTest.java
new file mode 100644
index 0000000..4c76e96
--- /dev/null
+++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/UriInfoImplTest.java
@@ -0,0 +1,204 @@
+/*
+ * 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;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+
+import org.apache.olingo.commons.api.edm.EdmEntityType;
+import org.apache.olingo.commons.api.ex.ODataRuntimeException;
+import org.apache.olingo.server.api.uri.UriInfo;
+import org.apache.olingo.server.api.uri.UriInfoKind;
+import org.apache.olingo.server.api.uri.UriResourceAction;
+import org.apache.olingo.server.api.uri.UriResourceEntitySet;
+import org.apache.olingo.server.api.uri.queryoption.AliasQueryOption;
+import org.apache.olingo.server.api.uri.queryoption.QueryOption;
+import org.apache.olingo.server.core.uri.UriInfoImpl;
+import org.apache.olingo.server.core.uri.UriResourceActionImpl;
+import org.apache.olingo.server.core.uri.UriResourceEntitySetImpl;
+import org.apache.olingo.server.core.uri.queryoption.AliasQueryOptionImpl;
+import org.apache.olingo.server.core.uri.queryoption.CountOptionImpl;
+import org.apache.olingo.server.core.uri.queryoption.CustomQueryOptionImpl;
+import org.apache.olingo.server.core.uri.queryoption.ExpandOptionImpl;
+import org.apache.olingo.server.core.uri.queryoption.FilterOptionImpl;
+import org.apache.olingo.server.core.uri.queryoption.FormatOptionImpl;
+import org.apache.olingo.server.core.uri.queryoption.IdOptionImpl;
+import org.apache.olingo.server.core.uri.queryoption.LevelsOptionImpl;
+import org.apache.olingo.server.core.uri.queryoption.OrderByOptionImpl;
+import org.apache.olingo.server.core.uri.queryoption.SearchOptionImpl;
+import org.apache.olingo.server.core.uri.queryoption.SelectOptionImpl;
+import org.apache.olingo.server.core.uri.queryoption.SkipOptionImpl;
+import org.apache.olingo.server.core.uri.queryoption.SkipTokenOptionImpl;
+import org.apache.olingo.server.core.uri.queryoption.TopOptionImpl;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class UriInfoImplTest {
+
+ @Test
+ public void kind() {
+ final UriInfo uriInfo = new UriInfoImpl().setKind(UriInfoKind.all);
+ assertEquals(UriInfoKind.all, uriInfo.getKind());
+ }
+
+ @Test
+ public void casts() {
+ final UriInfo uriInfo = new UriInfoImpl();
+
+ assertEquals(uriInfo, uriInfo.asUriInfoAll());
+ assertEquals(uriInfo, uriInfo.asUriInfoBatch());
+ assertEquals(uriInfo, uriInfo.asUriInfoCrossjoin());
+ assertEquals(uriInfo, uriInfo.asUriInfoEntityId());
+ assertEquals(uriInfo, uriInfo.asUriInfoMetadata());
+ assertEquals(uriInfo, uriInfo.asUriInfoResource());
+ assertEquals(uriInfo, uriInfo.asUriInfoService());
+ }
+
+ @Test
+ public void entityNames() {
+ final UriInfo uriInfo = new UriInfoImpl()
+ .addEntitySetName("A")
+ .addEntitySetName("B");
+ assertArrayEquals(new String[] { "A", "B" }, uriInfo.getEntitySetNames().toArray());
+ }
+
+ @Test
+ public void resourceParts() {
+ UriInfoImpl uriInfo = new UriInfoImpl();
+
+ final UriResourceAction action = new UriResourceActionImpl();
+ final UriResourceEntitySet entitySet0 = new UriResourceEntitySetImpl();
+ final UriResourceEntitySet entitySet1 = new UriResourceEntitySetImpl();
+
+ uriInfo.addResourcePart(action);
+ uriInfo.addResourcePart(entitySet0);
+
+ assertEquals(action, uriInfo.getUriResourceParts().get(0));
+ assertEquals(entitySet0, uriInfo.getUriResourceParts().get(1));
+
+ assertEquals(entitySet0, uriInfo.getLastResourcePart());
+
+ uriInfo.addResourcePart(entitySet1);
+ assertEquals(entitySet1, uriInfo.getLastResourcePart());
+ }
+
+ @Test(expected = ODataRuntimeException.class)
+ public void doubleSystemQueryOptions() {
+ new UriInfoImpl()
+ .setSystemQueryOption(new FormatOptionImpl())
+ .setSystemQueryOption(new FormatOptionImpl());
+ }
+
+ @Test
+ public void customQueryOption() {
+ final QueryOption expand = new ExpandOptionImpl().setName("");
+ final QueryOption filter = new FilterOptionImpl().setName("");
+ final QueryOption format = new FormatOptionImpl().setName("");
+ final QueryOption id = new IdOptionImpl().setName("");
+ final QueryOption inlinecount = new CountOptionImpl().setName("");
+ final QueryOption orderby = new OrderByOptionImpl().setName("");
+ final QueryOption search = new SearchOptionImpl().setName("");
+ final QueryOption select = new SelectOptionImpl().setName("");
+ final QueryOption skip = new SkipOptionImpl().setName("");
+ final QueryOption skipToken = new SkipTokenOptionImpl().setName("");
+ final QueryOption top = new TopOptionImpl().setName("");
+ final QueryOption levels = new LevelsOptionImpl().setName("");
+
+ final QueryOption customOption0 = new CustomQueryOptionImpl().setName("").setText("A");
+ final QueryOption customOption1 = new CustomQueryOptionImpl().setName("").setText("B");
+
+ final QueryOption initialQueryOption = new CustomQueryOptionImpl();
+
+ final QueryOption alias = new AliasQueryOptionImpl().setName("alias").setText("C");
+
+ final UriInfo uriInfo = new UriInfoImpl()
+ .setQueryOptions(Arrays.asList(
+ expand,
+ filter,
+ format,
+ id,
+ inlinecount,
+ orderby,
+ search,
+ select,
+ skip,
+ skipToken,
+ top,
+ customOption0,
+ customOption1,
+ levels,
+ initialQueryOption,
+ alias));
+
+ assertEquals(12, uriInfo.getSystemQueryOptions().size());
+ assertEquals(expand, uriInfo.getExpandOption());
+ assertEquals(filter, uriInfo.getFilterOption());
+ assertEquals(format, uriInfo.getFormatOption());
+ assertEquals(id, uriInfo.getIdOption());
+ assertEquals(inlinecount, uriInfo.getCountOption());
+ assertEquals(orderby, uriInfo.getOrderByOption());
+ assertEquals(search, uriInfo.getSearchOption());
+ assertEquals(select, uriInfo.getSelectOption());
+ assertEquals(skip, uriInfo.getSkipOption());
+ assertEquals(skipToken, uriInfo.getSkipTokenOption());
+ assertEquals(top, uriInfo.getTopOption());
+
+ assertArrayEquals(new QueryOption[] { alias }, uriInfo.getAliases().toArray());
+ assertEquals("C", uriInfo.getValueForAlias("alias"));
+
+ assertArrayEquals(new QueryOption[] { customOption0, customOption1, initialQueryOption },
+ uriInfo.getCustomQueryOptions().toArray());
+ }
+
+ @Test
+ public void fragment() {
+ final UriInfo uriInfo = new UriInfoImpl().setFragment("F");
+ assertEquals("F", uriInfo.getFragment());
+ }
+
+ @Test
+ public void entityTypeCast() {
+ final EdmEntityType entityType = Mockito.mock(EdmEntityType.class);
+ final UriInfo uriInfo = new UriInfoImpl()
+ .setEntityTypeCast(entityType);
+ assertEquals(entityType, uriInfo.getEntityTypeCast());
+ }
+
+ @Test
+ public void alias() {
+ final UriInfo uriInfo = new UriInfoImpl()
+ .addAlias((AliasQueryOption) new AliasQueryOptionImpl().setName("A").setText("notUsed"))
+ .addAlias((AliasQueryOption) new AliasQueryOptionImpl().setName("A").setText("X"))
+ .addAlias((AliasQueryOption) new AliasQueryOptionImpl().setName("B").setText("Y"))
+ .addAlias((AliasQueryOption) new AliasQueryOptionImpl().setName("C").setText("Z"));
+
+ assertEquals(3, uriInfo.getAliases().size());
+ assertEquals("X", uriInfo.getValueForAlias("A"));
+ assertEquals("Y", uriInfo.getValueForAlias("B"));
+ assertEquals("Z", uriInfo.getValueForAlias("C"));
+ assertNull(uriInfo.getValueForAlias("D"));
+
+ assertTrue(uriInfo.getSystemQueryOptions().isEmpty());
+ assertTrue(uriInfo.getCustomQueryOptions().isEmpty());
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/d7e23bf8/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriDecoderTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriDecoderTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriDecoderTest.java
new file mode 100644
index 0000000..20ab94f
--- /dev/null
+++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriDecoderTest.java
@@ -0,0 +1,94 @@
+/*
+ * 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.olingo.server.api.uri.queryoption.QueryOption;
+import org.junit.Test;
+
+public class UriDecoderTest {
+
+ @Test
+ public void split() throws Exception {
+ assertTrue(UriDecoder.splitAndDecodePath("").isEmpty());
+ assertTrue(UriDecoder.splitAndDecodePath("/").isEmpty());
+ assertEquals(Arrays.asList("a"), UriDecoder.splitAndDecodePath("a"));
+ assertEquals(Arrays.asList("a"), UriDecoder.splitAndDecodePath("a/"));
+ assertEquals(Arrays.asList("a"), UriDecoder.splitAndDecodePath("/a"));
+ assertEquals(Arrays.asList("a", "a"), UriDecoder.splitAndDecodePath("a/a"));
+ assertEquals(Arrays.asList("a", "a"), UriDecoder.splitAndDecodePath("/a/a"));
+ }
+
+ @Test
+ public void path() throws Exception {
+ assertEquals(Arrays.asList("a", "entitySet('/')", "bcd"),
+ UriDecoder.splitAndDecodePath("a/entitySet('%2F')/b%63d"));
+ }
+
+ @Test
+ public void options() throws Exception {
+ assertTrue(UriDecoder.splitAndDecodeOptions("").isEmpty());
+
+ checkOption("a", "a", "");
+ checkOption("a=b", "a", "b");
+ checkOption("=", "", "");
+ checkOption("=b", "", "b");
+
+ checkOption("a&c", "a", "");
+ checkOption("a&c", "c", "");
+
+ checkOption("a=b&c", "a", "b");
+ checkOption("a=b&c", "c", "");
+
+ checkOption("a=b&c=d", "a", "b");
+ checkOption("a=b&c=d", "c", "d");
+
+ checkOption("=&=", "", "");
+ assertEquals(2, UriDecoder.splitAndDecodeOptions("=&=").size());
+
+ checkOption("=&c=d", "", "");
+ checkOption("=&c=d", "c", "d");
+
+ checkOption("a%62c=d%65f", "abc", "def");
+ checkOption("a='%26%3D'", "a", "'&='");
+ }
+
+ @Test(expected = UriParserSyntaxException.class)
+ public void wrongPercentEncoding() throws Exception {
+ UriDecoder.splitAndDecodePath("%wrong");
+ }
+
+ private void checkOption(final String query, final String name, final String value)
+ throws UriParserSyntaxException {
+ final List<QueryOption> options = UriDecoder.splitAndDecodeOptions(query);
+ for (final QueryOption option : options) {
+ if (option.getName().equals(name)) {
+ assertEquals(value, option.getText());
+ return;
+ }
+ }
+ fail("Option " + name + " not found!");
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/d7e23bf8/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java
index a9e97ce..177a396 100644
--- a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java
+++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java
@@ -51,7 +51,7 @@ public class UriTokenizerTest {
@Test
public void sequence() {
- final UriTokenizer tokenizer = new UriTokenizer("(A=1,B=2);");
+ final UriTokenizer tokenizer = new UriTokenizer("(A=1,B=2);.*/+");
assertTrue(tokenizer.next(TokenKind.OPEN));
assertFalse(tokenizer.next(TokenKind.OPEN));
assertTrue(tokenizer.next(TokenKind.ODataIdentifier));
@@ -68,6 +68,10 @@ public class UriTokenizerTest {
assertFalse(tokenizer.next(TokenKind.EOF));
assertTrue(tokenizer.next(TokenKind.CLOSE));
assertTrue(tokenizer.next(TokenKind.SEMI));
+ assertTrue(tokenizer.next(TokenKind.DOT));
+ assertTrue(tokenizer.next(TokenKind.STAR));
+ assertTrue(tokenizer.next(TokenKind.SLASH));
+ assertTrue(tokenizer.next(TokenKind.PLUS));
assertTrue(tokenizer.next(TokenKind.EOF));
}
@@ -100,8 +104,10 @@ public class UriTokenizerTest {
public void qualifiedName() {
assertTrue(new UriTokenizer("namespace.name").next(TokenKind.QualifiedName));
- final UriTokenizer tokenizer = new UriTokenizer("multi.part.namespace.name");
+ final UriTokenizer tokenizer = new UriTokenizer("multi.part.namespace.name.1");
assertTrue(tokenizer.next(TokenKind.QualifiedName));
+ assertTrue(tokenizer.next(TokenKind.DOT));
+ assertTrue(tokenizer.next(TokenKind.PrimitiveIntegerValue));
assertTrue(tokenizer.next(TokenKind.EOF));
assertFalse(new UriTokenizer("name").next(TokenKind.QualifiedName));
@@ -334,6 +340,7 @@ public class UriTokenizerTest {
assertFalse(new UriTokenizer("[,1]").next(TokenKind.jsonArrayOrObject));
assertFalse(new UriTokenizer("[1,,2]").next(TokenKind.jsonArrayOrObject));
assertFalse(new UriTokenizer("[1,x]").next(TokenKind.jsonArrayOrObject));
+ assertFalse(new UriTokenizer("[+\"x\"]").next(TokenKind.jsonArrayOrObject));
assertFalse(new UriTokenizer("{\"name\":1,}").next(TokenKind.jsonArrayOrObject));
assertFalse(new UriTokenizer("{,\"name\":1}").next(TokenKind.jsonArrayOrObject));
assertFalse(new UriTokenizer("{\"name\":1,,\"name2\":2}").next(TokenKind.jsonArrayOrObject));
@@ -350,6 +357,7 @@ public class UriTokenizerTest {
assertFalse(new UriTokenizer("[\"\\u1\"]").next(TokenKind.jsonArrayOrObject));
assertFalse(new UriTokenizer("[\"\\u12x\"]").next(TokenKind.jsonArrayOrObject));
assertFalse(new UriTokenizer("[\"\\u123x\"]").next(TokenKind.jsonArrayOrObject));
+ wrongToken(TokenKind.jsonArrayOrObject, "[{\"name\":+123.456},null]", '\\');
}
private void wrongToken(final TokenKind kind, final String value, final char disturbCharacter) {
@@ -358,6 +366,7 @@ public class UriTokenizerTest {
final UriTokenizer tokenizer = new UriTokenizer(value + disturbCharacter);
assertTrue(tokenizer.next(kind));
assertEquals(value, tokenizer.getText());
+ assertFalse(tokenizer.next(TokenKind.EOF));
// Place the disturbing character at every position in the value string
// and check that this leads to a failed token recognition.
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/d7e23bf8/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/UriInfoImplTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/UriInfoImplTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/UriInfoImplTest.java
deleted file mode 100644
index 20bdade..0000000
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/UriInfoImplTest.java
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * 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;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import java.util.Arrays;
-import java.util.Collections;
-
-import org.apache.olingo.commons.api.edm.Edm;
-import org.apache.olingo.commons.api.edm.EdmEntityType;
-import org.apache.olingo.commons.api.ex.ODataRuntimeException;
-import org.apache.olingo.server.api.OData;
-import org.apache.olingo.server.api.edmx.EdmxReference;
-import org.apache.olingo.server.api.uri.UriInfo;
-import org.apache.olingo.server.api.uri.UriInfoKind;
-import org.apache.olingo.server.api.uri.UriResourceAction;
-import org.apache.olingo.server.api.uri.UriResourceEntitySet;
-import org.apache.olingo.server.api.uri.queryoption.AliasQueryOption;
-import org.apache.olingo.server.api.uri.queryoption.QueryOption;
-import org.apache.olingo.server.core.uri.queryoption.AliasQueryOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.CountOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.CustomQueryOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.ExpandOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.FilterOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.FormatOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.IdOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.LevelsOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.OrderByOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.SearchOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.SelectOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.SkipOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.SkipTokenOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.TopOptionImpl;
-import org.apache.olingo.server.tecsvc.provider.EdmTechProvider;
-import org.apache.olingo.server.tecsvc.provider.EntityTypeProvider;
-import org.junit.Test;
-
-public class UriInfoImplTest {
-
- private static final Edm edm = OData.newInstance().createServiceMetadata(
- new EdmTechProvider(), Collections.<EdmxReference> emptyList()).getEdm();
-
- @Test
- public void kind() {
- final UriInfo uriInfo = new UriInfoImpl().setKind(UriInfoKind.all);
- assertEquals(UriInfoKind.all, uriInfo.getKind());
- }
-
- @Test
- public void casts() {
- final UriInfo uriInfo = new UriInfoImpl();
-
- assertEquals(uriInfo, uriInfo.asUriInfoAll());
- assertEquals(uriInfo, uriInfo.asUriInfoBatch());
- assertEquals(uriInfo, uriInfo.asUriInfoCrossjoin());
- assertEquals(uriInfo, uriInfo.asUriInfoEntityId());
- assertEquals(uriInfo, uriInfo.asUriInfoMetadata());
- assertEquals(uriInfo, uriInfo.asUriInfoResource());
- assertEquals(uriInfo, uriInfo.asUriInfoService());
- }
-
- @Test
- public void entityNames() {
- final UriInfo uriInfo = new UriInfoImpl()
- .addEntitySetName("A")
- .addEntitySetName("B");
- assertArrayEquals(new String[] { "A", "B" }, uriInfo.getEntitySetNames().toArray());
- }
-
- @Test
- public void resourceParts() {
- UriInfoImpl uriInfo = new UriInfoImpl();
-
- final UriResourceAction action = new UriResourceActionImpl();
- final UriResourceEntitySet entitySet0 = new UriResourceEntitySetImpl();
- final UriResourceEntitySet entitySet1 = new UriResourceEntitySetImpl();
-
- uriInfo.addResourcePart(action);
- uriInfo.addResourcePart(entitySet0);
-
- assertEquals(action, uriInfo.getUriResourceParts().get(0));
- assertEquals(entitySet0, uriInfo.getUriResourceParts().get(1));
-
- assertEquals(entitySet0, uriInfo.getLastResourcePart());
-
- uriInfo.addResourcePart(entitySet1);
- assertEquals(entitySet1, uriInfo.getLastResourcePart());
- }
-
- @Test(expected = ODataRuntimeException.class)
- public void doubleSystemQueryOptions() {
- new UriInfoImpl()
- .setSystemQueryOption(new FormatOptionImpl())
- .setSystemQueryOption(new FormatOptionImpl());
- }
-
- @Test
- public void customQueryOption() {
- final QueryOption expand = new ExpandOptionImpl().setName("");
- final QueryOption filter = new FilterOptionImpl().setName("");
- final QueryOption format = new FormatOptionImpl().setName("");
- final QueryOption id = new IdOptionImpl().setName("");
- final QueryOption inlinecount = new CountOptionImpl().setName("");
- final QueryOption orderby = new OrderByOptionImpl().setName("");
- final QueryOption search = new SearchOptionImpl().setName("");
- final QueryOption select = new SelectOptionImpl().setName("");
- final QueryOption skip = new SkipOptionImpl().setName("");
- final QueryOption skipToken = new SkipTokenOptionImpl().setName("");
- final QueryOption top = new TopOptionImpl().setName("");
- final QueryOption levels = new LevelsOptionImpl().setName("");
-
- final QueryOption customOption0 = new CustomQueryOptionImpl().setName("").setText("A");
- final QueryOption customOption1 = new CustomQueryOptionImpl().setName("").setText("B");
-
- final QueryOption initialQueryOption = new CustomQueryOptionImpl();
-
- final QueryOption alias = new AliasQueryOptionImpl().setName("alias").setText("C");
-
- final UriInfo uriInfo = new UriInfoImpl()
- .setQueryOptions(Arrays.asList(
- expand,
- filter,
- format,
- id,
- inlinecount,
- orderby,
- search,
- select,
- skip,
- skipToken,
- top,
- customOption0,
- customOption1,
- levels,
- initialQueryOption,
- alias));
-
- assertEquals(12, uriInfo.getSystemQueryOptions().size());
- assertEquals(expand, uriInfo.getExpandOption());
- assertEquals(filter, uriInfo.getFilterOption());
- assertEquals(format, uriInfo.getFormatOption());
- assertEquals(id, uriInfo.getIdOption());
- assertEquals(inlinecount, uriInfo.getCountOption());
- assertEquals(orderby, uriInfo.getOrderByOption());
- assertEquals(search, uriInfo.getSearchOption());
- assertEquals(select, uriInfo.getSelectOption());
- assertEquals(skip, uriInfo.getSkipOption());
- assertEquals(skipToken, uriInfo.getSkipTokenOption());
- assertEquals(top, uriInfo.getTopOption());
-
- assertArrayEquals(new QueryOption[] { alias }, uriInfo.getAliases().toArray());
- assertEquals("C", uriInfo.getValueForAlias("alias"));
-
- assertArrayEquals(new QueryOption[] { customOption0, customOption1, initialQueryOption },
- uriInfo.getCustomQueryOptions().toArray());
- }
-
- @Test
- public void fragment() {
- final UriInfo uriInfo = new UriInfoImpl().setFragment("F");
- assertEquals("F", uriInfo.getFragment());
- }
-
- @Test
- public void entityTypeCast() {
- final EdmEntityType entityType = edm.getEntityType(EntityTypeProvider.nameETKeyNav);
- assertNotNull(entityType);
-
- final UriInfo uriInfo = new UriInfoImpl()
- .setEntityTypeCast(entityType);
- assertEquals(entityType, uriInfo.getEntityTypeCast());
- }
-
- @Test
- public void alias() {
- final UriInfo uriInfo = new UriInfoImpl()
- .addAlias((AliasQueryOption) new AliasQueryOptionImpl().setName("A").setText("notUsed"))
- .addAlias((AliasQueryOption) new AliasQueryOptionImpl().setName("A").setText("X"))
- .addAlias((AliasQueryOption) new AliasQueryOptionImpl().setName("B").setText("Y"))
- .addAlias((AliasQueryOption) new AliasQueryOptionImpl().setName("C").setText("Z"));
-
- assertEquals(3, uriInfo.getAliases().size());
- assertEquals("X", uriInfo.getValueForAlias("A"));
- assertEquals("Y", uriInfo.getValueForAlias("B"));
- assertEquals("Z", uriInfo.getValueForAlias("C"));
- assertNull(uriInfo.getValueForAlias("D"));
-
- assertTrue(uriInfo.getSystemQueryOptions().isEmpty());
- assertTrue(uriInfo.getCustomQueryOptions().isEmpty());
- }
-}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/d7e23bf8/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java
index 11acede..e9f1c07 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java
@@ -40,18 +40,19 @@ 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.UriParserException;
-import org.apache.olingo.server.core.uri.parser.UriParserSemanticException;
import org.apache.olingo.server.core.uri.parser.UriParserSemanticException.MessageKeys;
import org.apache.olingo.server.core.uri.parser.UriParserSyntaxException;
import org.apache.olingo.server.core.uri.parser.search.SearchParserException;
import org.apache.olingo.server.core.uri.testutil.FilterValidator;
import org.apache.olingo.server.core.uri.testutil.TestUriValidator;
import org.apache.olingo.server.core.uri.validator.UriValidationException;
+import org.apache.olingo.server.tecsvc.provider.ActionProvider;
import org.apache.olingo.server.tecsvc.provider.ComplexTypeProvider;
import org.apache.olingo.server.tecsvc.provider.ContainerProvider;
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.FunctionProvider;
import org.apache.olingo.server.tecsvc.provider.PropertyProvider;
import org.apache.olingo.server.tecsvc.provider.TypeDefinitionProvider;
import org.junit.Ignore;
@@ -2731,17 +2732,6 @@ public class TestFullResourcePath {
.isNavProperty("NavPropertyETKeyNavOne", EntityTypeProvider.nameETKeyNav, false)
.isType(EntityTypeProvider.nameETKeyNav);
- testUri.run("ESTwoKeyNav(PropertyInt16=1,PropertyString='2')", "$select=olingo.odata.test1.ETBaseTwoKeyNav"
- + "/PropertyInt16")
- .isKind(UriInfoKind.resource).goPath()
- .first()
- .isKeyPredicate(0, "PropertyInt16", "1")
- .isKeyPredicate(1, "PropertyString", "'2'")
- .isSelectStartType(0, EntityTypeProvider.nameETBaseTwoKeyNav)
- .goSelectItem(0)
- .first()
- .isPrimitiveProperty("PropertyInt16", PropertyProvider.nameInt16, false);
-
testUri.run("ESKeyNav", "$expand=NavPropertyETKeyNavOne($select=PropertyInt16)")
.isKind(UriInfoKind.resource)
.goPath().first()
@@ -2763,17 +2753,6 @@ public class TestFullResourcePath {
.goUpExpandValidator()
.isSelectText("PropertyCompNav/PropertyInt16");
- testUri.run("ESMixEnumDefCollComp",
- "$select=PropertyEnumString,PropertyDefString,CollPropertyEnumString,CollPropertyDefString")
- .isKind(UriInfoKind.resource)
- .goSelectItemPath(0).isPrimitiveProperty("PropertyEnumString", EnumTypeProvider.nameENString, false)
- .goUpUriValidator()
- .goSelectItemPath(1).isPrimitiveProperty("PropertyDefString", TypeDefinitionProvider.nameTDString, false)
- .goUpUriValidator()
- .goSelectItemPath(2).isPrimitiveProperty("CollPropertyEnumString", EnumTypeProvider.nameENString, true)
- .goUpUriValidator()
- .goSelectItemPath(3).isPrimitiveProperty("CollPropertyDefString", TypeDefinitionProvider.nameTDString, true);
-
testUri.runEx("ESKeyNav", "$expand=undefined")
.isExSemantic(MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE);
testUri.runEx("ESTwoKeyNav", "$expand=PropertyCompNav/undefined")
@@ -2815,6 +2794,134 @@ public class TestFullResourcePath {
}
@Test
+ public void select() throws Exception {
+ testUri.run("ESTwoKeyNav", "$select=*")
+ .isSelectItemStar(0);
+
+ testUri.run("ESTwoKeyNav", "$select=olingo.odata.test1.*")
+ .isSelectItemAllOp(0, new FullQualifiedName("olingo.odata.test1", "*"));
+ testUri.run("ESTwoKeyNav", "$select=Namespace1_Alias.*")
+ .isSelectItemAllOp(0, new FullQualifiedName("Namespace1_Alias", "*"));
+
+ testUri.run("ESTwoKeyNav", "$select=PropertyString")
+ .goSelectItemPath(0).isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false);
+
+ testUri.run("ESTwoKeyNav", "$select=PropertyComp")
+ .goSelectItemPath(0).isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false);
+
+ testUri.run("ESAllPrim", "$select=PropertyTimeOfDay,PropertyDate,NavPropertyETTwoPrimOne")
+ .isKind(UriInfoKind.resource)
+ .goSelectItemPath(0).first().isPrimitiveProperty("PropertyTimeOfDay", PropertyProvider.nameTimeOfDay, false)
+ .goUpUriValidator()
+ .goSelectItemPath(1).first().isPrimitiveProperty("PropertyDate", PropertyProvider.nameDate, false)
+ .goUpUriValidator()
+ .goSelectItemPath(2).first().isNavProperty("NavPropertyETTwoPrimOne", EntityTypeProvider.nameETTwoPrim, false);
+
+ testUri.run("ESMixEnumDefCollComp",
+ "$select=PropertyEnumString,PropertyDefString,CollPropertyEnumString,CollPropertyDefString")
+ .isKind(UriInfoKind.resource)
+ .goSelectItemPath(0).isPrimitiveProperty("PropertyEnumString", EnumTypeProvider.nameENString, false)
+ .goUpUriValidator()
+ .goSelectItemPath(1).isPrimitiveProperty("PropertyDefString", TypeDefinitionProvider.nameTDString, false)
+ .goUpUriValidator()
+ .goSelectItemPath(2).isPrimitiveProperty("CollPropertyEnumString", EnumTypeProvider.nameENString, true)
+ .goUpUriValidator()
+ .goSelectItemPath(3).isPrimitiveProperty("CollPropertyDefString", TypeDefinitionProvider.nameTDString, true);
+
+ testUri.run("ESTwoKeyNav", "$select=PropertyComp/PropertyInt16")
+ .goSelectItemPath(0)
+ .first()
+ .isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false)
+ .n()
+ .isPrimitiveProperty("PropertyInt16", PropertyProvider.nameInt16, false);
+
+ testUri.run("ESTwoKeyNav", "$select=PropertyComp/PropertyComp")
+ .goSelectItemPath(0)
+ .first()
+ .isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false)
+ .n()
+ .isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTAllPrim, false);
+
+ testUri.run("ESTwoKeyNav", "$select=olingo.odata.test1.ETBaseTwoKeyNav")
+ .isSelectStartType(0, EntityTypeProvider.nameETBaseTwoKeyNav);
+
+ testUri.run("ESTwoKeyNav(PropertyInt16=1,PropertyString='2')",
+ "$select=olingo.odata.test1.ETBaseTwoKeyNav/PropertyInt16")
+ .isKind(UriInfoKind.resource).goPath()
+ .first()
+ .isKeyPredicate(0, "PropertyInt16", "1")
+ .isKeyPredicate(1, "PropertyString", "'2'")
+ .isSelectStartType(0, EntityTypeProvider.nameETBaseTwoKeyNav)
+ .goSelectItem(0)
+ .first()
+ .isPrimitiveProperty("PropertyInt16", PropertyProvider.nameInt16, false);
+
+ testUri.run("ESTwoKeyNav(PropertyInt16=1,PropertyString='1')/PropertyCompNav",
+ "$select=olingo.odata.test1.CTTwoBasePrimCompNav")
+ .isSelectStartType(0, ComplexTypeProvider.nameCTTwoBasePrimCompNav);
+
+ testUri.run("ESTwoKeyNav", "$select=PropertyCompNav/olingo.odata.test1.CTTwoBasePrimCompNav")
+ .goSelectItemPath(0)
+ .first()
+ .isComplexProperty("PropertyCompNav", ComplexTypeProvider.nameCTBasePrimCompNav, false)
+ .isTypeFilter(ComplexTypeProvider.nameCTTwoBasePrimCompNav);
+
+ testUri.run("ESTwoKeyNav", "$select=PropertyCompNav/Namespace1_Alias.CTTwoBasePrimCompNav/PropertyInt16")
+ .goSelectItemPath(0)
+ .first()
+ .isComplexProperty("PropertyCompNav", ComplexTypeProvider.nameCTBasePrimCompNav, false)
+ .isTypeFilter(ComplexTypeProvider.nameCTTwoBasePrimCompNav)
+ .n()
+ .isPrimitiveProperty("PropertyInt16", PropertyProvider.nameInt16, false);
+
+ testUri.run("ESAllPrim", "$select=olingo.odata.test1.BAESAllPrimRTETAllPrim")
+ .goSelectItemPath(0)
+ .first()
+ .isAction(ActionProvider.nameBAESAllPrimRTETAllPrim.getName());
+ testUri.run("ESTwoKeyNav", "$select=Namespace1_Alias.BFCESTwoKeyNavRTString")
+ .goSelectItemPath(0)
+ .first()
+ .isFunction(FunctionProvider.nameBFCESTwoKeyNavRTString.getName());
+ testUri.run("ESTwoKeyNav", "$select=olingo.odata.test1.BFCESTwoKeyNavRTStringParam(ParameterComp)")
+ .goSelectItemPath(0)
+ .first()
+ .isFunction(FunctionProvider.nameBFCESTwoKeyNavRTStringParam.getName());
+
+ testUri.runEx("ESMixPrimCollComp", "$select=wrong")
+ .isExSemantic(MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE);
+ testUri.runEx("ESMixPrimCollComp", "$select=PropertyComp/wrong")
+ .isExSemantic(MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE);
+ testUri.runEx("ESMixPrimCollComp", "$select=PropertyComp///PropertyInt16")
+ .isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
+ testUri.runEx("ESMixPrimCollComp", "$select=/PropertyInt16")
+ .isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
+ testUri.runEx("ESMixPrimCollComp", "$select=PropertyInt16+")
+ .isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
+ testUri.runEx("ESTwoKeyNav", "$select=olingo.odata.test1.1")
+ .isExSemantic(MessageKeys.UNKNOWN_PART);
+ testUri.runEx("ESTwoKeyNav", "$select=olingo.odata.test1.ETKeyNav")
+ .isExSemantic(MessageKeys.INCOMPATIBLE_TYPE_FILTER);
+ testUri.runEx("ESTwoKeyNav", "$select=PropertyCompNav/olingo.odata.test1.CTTwoPrim")
+ .isExSemantic(MessageKeys.INCOMPATIBLE_TYPE_FILTER);
+ testUri.runEx("ESTwoKeyNav", "$select=PropertyCompNav/olingo.odata.test1.CTwrong")
+ .isExSemantic(MessageKeys.UNKNOWN_TYPE);
+ testUri.runEx("ESTwoKeyNav", "$select=PropertyCompNav/.")
+ .isExSemantic(MessageKeys.UNKNOWN_PART);
+ testUri.runEx("ESTwoKeyNav", "$select=PropertyCompNav/olingo.odata.test1.CTTwoBasePrimCompNav/.")
+ .isExSemantic(MessageKeys.UNKNOWN_PART);
+ testUri.runEx("AIRT", "$select=wrong")
+ .isExSemantic(MessageKeys.ONLY_FOR_TYPED_PARTS);
+ testUri.runEx("AIRT", "$select=olingo.odata.test1.BAESAllPrimRT")
+ .isExSemantic(MessageKeys.ONLY_FOR_TYPED_PARTS);
+ testUri.runEx("ESTwoKeyNav", "$select=olingo.odata.test1.BFwrong")
+ .isExSemantic(MessageKeys.UNKNOWN_PART);
+ testUri.runEx("ESTwoKeyNav", "$select=olingo.odata.test1.BFCESTwoKeyNavRTStringParam()")
+ .isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
+ testUri.runEx("ESTwoKeyNav", "$select=Namespace1_Alias.BFCESTwoKeyNavRTStringParam(ParameterComp,...)")
+ .isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
+ }
+
+ @Test
public void runTop() throws Exception {
// top
testUri.run("ESKeyNav", "$top=1")
@@ -5950,7 +6057,7 @@ public class TestFullResourcePath {
testUri.runEx("ESTwoKeyNav/olingo.odata.test1.BFCESTwoKeyNavRTStringParam"
+ "(ParameterComp={\"PropertyInt16\":1,\"PropertyString\":\"Test\"})")
- .isExSemantic(UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE);
+ .isExSemantic(MessageKeys.INVALID_KEY_VALUE);
testUri.runEx("FICRTCTTwoPrimTwoParam(ParameterInt16=1,ParameterString=null)")
.isExValidation(UriValidationException.MessageKeys.MISSING_PARAMETER);
@@ -5964,7 +6071,7 @@ public class TestFullResourcePath {
testUri.run("FICRTCTTwoPrimTwoParam(ParameterInt16=1,ParameterString=@test)", "@test='null'");
testUri.runEx("FICRTCTTwoPrimTwoParam(ParameterInt16=1,ParameterString=@test,UnknownParam=1)", "@test='null'")
- .isExSemantic(UriParserSemanticException.MessageKeys.FUNCTION_NOT_FOUND);
+ .isExSemantic(MessageKeys.FUNCTION_NOT_FOUND);
testUri.run("FICRTCollCTTwoPrimTwoParam(ParameterInt16=1,ParameterString=@test)", "@test='null'");
testUri.run("FICRTCollCTTwoPrimTwoParam(ParameterInt16=1,ParameterString=@test)", "@test=null");
@@ -5975,7 +6082,7 @@ public class TestFullResourcePath {
.isExSyntax(UriParserSyntaxException.MessageKeys.DUPLICATED_ALIAS);
testUri.runEx("ESAllPrim", "$filter=FINRTInt16() eq 0")
- .isExSemantic(UriParserSemanticException.MessageKeys.FUNCTION_IMPORT_NOT_ALLOWED);
+ .isExSemantic(MessageKeys.FUNCTION_IMPORT_NOT_ALLOWED);
testUri.runEx("ESTwoKeyNav", "$filter=olingo.odata.test1.BFCESTwoKeyNavRTStringParam"
+ "(ParameterComp=@p1) eq 0&@p1={\"PropertyInt16\":1,\"PropertyString\":\"1\"")
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/d7e23bf8/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestUriParserImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestUriParserImpl.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestUriParserImpl.java
index e6612ff..19f5946 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestUriParserImpl.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestUriParserImpl.java
@@ -22,13 +22,11 @@ import java.util.Arrays;
import java.util.Collections;
import org.apache.olingo.commons.api.edm.Edm;
-import org.apache.olingo.commons.api.edm.FullQualifiedName;
import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.edmx.EdmxReference;
import org.apache.olingo.server.api.uri.UriInfoKind;
import org.apache.olingo.server.api.uri.UriResourceKind;
import org.apache.olingo.server.api.uri.queryoption.expression.MethodKind;
-import org.apache.olingo.server.core.uri.parser.UriParserSemanticException;
import org.apache.olingo.server.core.uri.parser.UriParserSyntaxException;
import org.apache.olingo.server.core.uri.testutil.FilterValidator;
import org.apache.olingo.server.core.uri.testutil.ResourceValidator;
@@ -1112,64 +1110,6 @@ public class TestUriParserImpl {
.isMethod(MethodKind.GEOINTERSECTS, 2);
}
- @Test
- public void testSelect() throws Exception {
- testUri.run("ESTwoKeyNav", "$select=*")
- .isSelectItemStar(0);
-
- testUri.run("ESTwoKeyNav", "$select=olingo.odata.test1.*")
- .isSelectItemAllOp(0, new FullQualifiedName("olingo.odata.test1", "*"));
-
- testUri.run("ESTwoKeyNav", "$select=PropertyString")
- .goSelectItemPath(0).isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false);
-
- testUri.run("ESTwoKeyNav", "$select=PropertyComp")
- .goSelectItemPath(0).isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false);
-
- testUri.run("ESTwoKeyNav", "$select=PropertyComp/PropertyInt16")
- .goSelectItemPath(0)
- .first()
- .isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false)
- .n()
- .isPrimitiveProperty("PropertyInt16", PropertyProvider.nameInt16, false);
-
- testUri.run("ESTwoKeyNav", "$select=PropertyComp/PropertyComp")
- .goSelectItemPath(0)
- .first()
- .isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false)
- .n()
- .isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTAllPrim, false);
-
- testUri.run("ESTwoKeyNav", "$select=olingo.odata.test1.ETBaseTwoKeyNav")
- .isSelectStartType(0, EntityTypeProvider.nameETBaseTwoKeyNav);
-
- testUri.run("ESTwoKeyNav(PropertyInt16=1,PropertyString='1')/PropertyCompNav",
- "$select=olingo.odata.test1.CTTwoBasePrimCompNav")
- .isSelectStartType(0, ComplexTypeProvider.nameCTTwoBasePrimCompNav);
-
- testUri.run("ESTwoKeyNav", "$select=PropertyCompNav/olingo.odata.test1.CTTwoBasePrimCompNav")
- .goSelectItemPath(0)
- .first()
- .isComplexProperty("PropertyCompNav", ComplexTypeProvider.nameCTBasePrimCompNav, false)
- .n()
- .isTypeFilterOnCollection(ComplexTypeProvider.nameCTTwoBasePrimCompNav);
-
- testUri.run("ESAllPrim", "$select=PropertyTimeOfDay,PropertyDate,PropertyTimeOfDay")
- .isKind(UriInfoKind.resource)
- .goSelectItemPath(0).first().isPrimitiveProperty("PropertyTimeOfDay", PropertyProvider.nameTimeOfDay, false)
- .goUpUriValidator()
- .goSelectItemPath(1).first().isPrimitiveProperty("PropertyDate", PropertyProvider.nameDate, false);
-
- testUri.runEx("ESMixPrimCollComp", "$select=wrong")
- .isExSemantic(UriParserSemanticException.MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE);
- testUri.runEx("ESMixPrimCollComp", "$select=PropertyComp/wrong")
- .isExSemantic(UriParserSemanticException.MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE);
- testUri.runEx("ESMixPrimCollComp", "$select=PropertyComp///PropertyInt16")
- .isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
- testUri.runEx("ESMixPrimCollComp", "$select=/PropertyInt16")
- .isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
- }
-
private final String encode(final String uriPart) {
return uriPart.replaceAll(":", "%3A");
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/d7e23bf8/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/parser/RawUriTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/parser/RawUriTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/parser/RawUriTest.java
deleted file mode 100644
index c897400..0000000
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/parser/RawUriTest.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * 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 static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import org.junit.Test;
-
-public class RawUriTest {
-
- private RawUri runRawParser(final String path, final String query, final int skipSegments)
- throws UriParserSyntaxException {
- return UriDecoder.decodeUri(path, query, null, skipSegments);
- }
-
- @Test
- public void testOption() throws Exception {
- RawUri rawUri;
- rawUri = runRawParser("", "", 0);
- checkOptionCount(rawUri, 0);
-
- rawUri = runRawParser("", "a", 0);
- checkOption(rawUri, 0, "a", "");
-
- rawUri = runRawParser("", "a=b", 0);
- checkOption(rawUri, 0, "a", "b");
-
- rawUri = runRawParser("", "=", 0);
- checkOption(rawUri, 0, "", "");
-
- rawUri = runRawParser("", "=b", 0);
- checkOption(rawUri, 0, "", "b");
-
- rawUri = runRawParser("", "a&c", 0);
- checkOption(rawUri, 0, "a", "");
- checkOption(rawUri, 1, "c", "");
-
- rawUri = runRawParser("", "a=b&c", 0);
- checkOption(rawUri, 0, "a", "b");
- checkOption(rawUri, 1, "c", "");
-
- rawUri = runRawParser("", "a=b&c=d", 0);
- checkOption(rawUri, 0, "a", "b");
- checkOption(rawUri, 1, "c", "d");
-
- rawUri = runRawParser("", "=&=", 0);
- checkOption(rawUri, 0, "", "");
- checkOption(rawUri, 1, "", "");
-
- rawUri = runRawParser("", "=&c=d", 0);
- checkOption(rawUri, 0, "", "");
- checkOption(rawUri, 1, "c", "d");
- }
-
- private void checkOption(final RawUri rawUri, final int index, final String name, final String value) {
- RawUri.QueryOption option = rawUri.queryOptionListDecoded.get(index);
-
- assertEquals(name, option.name);
- assertEquals(value, option.value);
- }
-
- private void checkOptionCount(final RawUri rawUri, final int count) {
- assertEquals(count, rawUri.queryOptionListDecoded.size());
- }
-
- @Test
- public void testPath() throws Exception {
- RawUri rawUri;
-
- rawUri = runRawParser("", null, 0);
- checkPath(rawUri, "", Collections.<String> emptyList());
-
- rawUri = runRawParser("/", null, 0);
- checkPath(rawUri, "/", Collections.<String> emptyList());
-
- rawUri = runRawParser("/entitySet", null, 0);
- checkPath(rawUri, "/entitySet", Arrays.asList("entitySet"));
-
- rawUri = runRawParser("//entitySet", null, 0);
- checkPath(rawUri, "//entitySet", Arrays.asList("entitySet"));
-
- rawUri = runRawParser("entitySet", null, 0);
- checkPath(rawUri, "entitySet", Arrays.asList("entitySet"));
-
- rawUri = runRawParser("/nonServiceSegment/entitySet", null, 0);
- checkPath(rawUri, "/nonServiceSegment/entitySet", Arrays.asList("nonServiceSegment", "entitySet"));
-
- rawUri = runRawParser("/nonServiceSegment/entitySet", null, 1);
- checkPath(rawUri, "/nonServiceSegment/entitySet", Arrays.asList("entitySet"));
-
- rawUri = runRawParser("nonServiceSegment/entitySet", null, 0);
- checkPath(rawUri, "nonServiceSegment/entitySet", Arrays.asList("nonServiceSegment", "entitySet"));
-
- rawUri = runRawParser("nonServiceSegment/entitySet", null, 1);
- checkPath(rawUri, "nonServiceSegment/entitySet", Arrays.asList("entitySet"));
-
- rawUri = runRawParser("non//Service/Segment///entitySet/", null, 3);
- checkPath(rawUri, "non//Service/Segment///entitySet/", Arrays.asList("entitySet"));
-
- rawUri = runRawParser("/a", "abc=xx+yz", 0);
- checkPath(rawUri, "/a", Arrays.asList("a"));
- }
-
- @Test
- public void testSplit() {
- assertTrue(UriDecoder.splitSkipEmpty("", '/').isEmpty());
- assertTrue(UriDecoder.splitSkipEmpty("/", '/').isEmpty());
- assertEquals(Arrays.asList("a"), UriDecoder.splitSkipEmpty("a", '/'));
- assertEquals(Arrays.asList("a"), UriDecoder.splitSkipEmpty("a/", '/'));
- assertEquals(Arrays.asList("a"), UriDecoder.splitSkipEmpty("/a", '/'));
- assertEquals(Arrays.asList("a", "a"), UriDecoder.splitSkipEmpty("a/a", '/'));
- assertEquals(Arrays.asList("a", "a"), UriDecoder.splitSkipEmpty("/a/a", '/'));
- }
-
- private void checkPath(final RawUri rawUri, final String path, final List<String> list) {
- assertEquals(path, rawUri.path);
-
- assertEquals(list.size(), rawUri.pathSegmentListDecoded.size());
-
- for (int i = 0; i < list.size(); i++) {
- assertEquals(list.get(i), rawUri.pathSegmentListDecoded.get(i));
- }
- }
-
- @Test(expected = UriParserSyntaxException.class)
- public void wrongPercentEncoding() throws Exception {
- runRawParser("%wrong", null, 0);
- }
-}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/d7e23bf8/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/ParserWithLogging.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/ParserWithLogging.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/ParserWithLogging.java
deleted file mode 100644
index 5ebc57e..0000000
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/ParserWithLogging.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.testutil;
-
-import org.antlr.v4.runtime.DefaultErrorStrategy;
-import org.antlr.v4.runtime.DiagnosticErrorListener;
-import org.apache.olingo.commons.api.edm.Edm;
-import org.apache.olingo.server.api.OData;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser;
-import org.apache.olingo.server.core.uri.parser.Parser;
-
-public class ParserWithLogging extends Parser {
- TestErrorLogger errorCollector1;
- TestErrorLogger errorCollector2;
-
- public ParserWithLogging(final Edm edm, final OData odata) {
- super(edm, odata);
- errorCollector1 = new TestErrorLogger("Stage 1", 1);
- errorCollector2 = new TestErrorLogger("Stage 2", 1);
- }
-
- @Override
- protected void addStage2ErrorStategy(final UriParserParser parser) {
- // Don't throw an at first syntax error, so the error listener will be called
- parser.setErrorHandler(new DefaultErrorStrategy());
- }
-
- @Override
- protected void addStage1ErrorListener(final UriParserParser parser) {
- // Log error to console
- parser.removeErrorListeners();
- parser.addErrorListener(errorCollector1);
- parser.addErrorListener(new DiagnosticErrorListener());
- }
-
- @Override
- protected void addStage2ErrorListener(final UriParserParser parser) {
- // Log error to console
- parser.removeErrorListeners();
- parser.addErrorListener(errorCollector2);
- parser.addErrorListener(new DiagnosticErrorListener());
- }
-}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/d7e23bf8/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/ResourceValidator.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/ResourceValidator.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/ResourceValidator.java
index d70b204..a9d25be 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/ResourceValidator.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/ResourceValidator.java
@@ -52,6 +52,7 @@ import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
import org.apache.olingo.server.api.uri.queryoption.SelectItem;
import org.apache.olingo.server.api.uri.queryoption.SelectOption;
import org.apache.olingo.server.core.uri.UriResourceWithKeysImpl;
+import org.apache.olingo.server.core.uri.parser.Parser;
import org.apache.olingo.server.core.uri.validator.UriValidationException;
import org.apache.olingo.server.core.uri.validator.UriValidator;
@@ -85,7 +86,7 @@ public class ResourceValidator implements TestValidator {
// --- Execution ---
public ResourceValidator run(final String path) {
- ParserWithLogging testParser = new ParserWithLogging(edm, odata);
+ Parser testParser = new Parser(edm, odata);
UriInfo uriInfoTmp = null;
uriPathInfo = null;
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/d7e23bf8/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/TestErrorLogger.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/TestErrorLogger.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/TestErrorLogger.java
deleted file mode 100644
index 76b0d38..0000000
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/TestErrorLogger.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * 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.testutil;
-
-import java.util.BitSet;
-import java.util.Collections;
-import java.util.List;
-
-import org.antlr.v4.runtime.ANTLRErrorListener;
-import org.antlr.v4.runtime.Parser;
-import org.antlr.v4.runtime.RecognitionException;
-import org.antlr.v4.runtime.Recognizer;
-import org.antlr.v4.runtime.atn.ATNConfigSet;
-import org.antlr.v4.runtime.dfa.DFA;
-import org.apache.olingo.server.core.uri.antlr.UriLexer;
-
-class TestErrorLogger implements ANTLRErrorListener {
-
- private String prefix;
- private int logLevel = 0;
-
- public TestErrorLogger(final String prefix, final int logLevel) {
- this.prefix = prefix;
- this.logLevel = logLevel;
- }
-
- @Override
- public void syntaxError(final Recognizer<?, ?> recognizer, final Object offendingSymbol, final int line,
- final int charPositionInLine,
- final String msg, final RecognitionException e) {
-
- if (logLevel > 0) {
- System.out.println("\n" + prefix + " -- SyntaxError");
- trace(recognizer, offendingSymbol, line, charPositionInLine, msg, e);
- }
-
- }
-
- @Override
- public void reportAmbiguity(final Parser recognizer, final DFA dfa, final int startIndex, final int stopIndex,
- final boolean exact,
- final BitSet ambigAlts, final ATNConfigSet configs) {
- // Test
- }
-
- @Override
- public void reportAttemptingFullContext(final Parser recognizer, final DFA dfa, final int startIndex,
- final int stopIndex,
- final BitSet conflictingAlts, final ATNConfigSet configs) {
- // Test
- }
-
- @Override
- public void reportContextSensitivity(final Parser recognizer, final DFA dfa, final int startIndex,
- final int stopIndex, final int prediction,
- final ATNConfigSet configs) {
- // Test
- }
-
- private void printStack(final Recognizer<?, ?> recognizer) {
- List<String> stack = ((Parser) recognizer).getRuleInvocationStack();
- Collections.reverse(stack);
- System.out.println(" rule stack: " + stack);
- }
-
- public void trace(final Recognizer<?, ?> recognizer, final Object offendingSymbol,
- final int line, final int charPositionInLine, final String msg, final RecognitionException e) {
-
- System.out.println("Error message: " + msg);
-
- printStack(recognizer);
-
- System.out.println(" line/char :" + line + " / " + charPositionInLine);
- System.out.println(" sym :" + offendingSymbol);
- if (e != null && e.getOffendingToken() != null) {
-
- String lexerTokenName = "";
- try {
- lexerTokenName = UriLexer.VOCABULARY.getDisplayName(e.getOffendingToken().getType());
- } catch (ArrayIndexOutOfBoundsException es) {
- lexerTokenName = "token error";
- }
-
- System.out.println(" tokenname:" + lexerTokenName);
- }
-
- }
-
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/d7e23bf8/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/TokenValidator.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/TokenValidator.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/TokenValidator.java
index 3ec6229..547c2ea 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/TokenValidator.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/TokenValidator.java
@@ -29,35 +29,18 @@ import org.apache.olingo.server.core.uri.antlr.UriLexer;
public class TokenValidator {
private String input = null;
-
private List<? extends Token> tokens = null;
private Token curToken = null;
private Exception curException = null;
private int startMode;
- private int logLevel = 0;
-
- // --- Setup ---
-
- public TokenValidator log(final int logLevel) {
- this.logLevel = logLevel;
- return this;
- }
// --- Execution ---
public TokenValidator run(final String uri) {
input = uri;
-
tokens = parseInput(uri);
- if (logLevel > 0) {
- showTokens();
- }
-
first();
- exFirst();
- logLevel = 0;
-
return this;
}
@@ -87,31 +70,6 @@ public class TokenValidator {
return this;
}
- public TokenValidator exLast() {
- // curException = exceptions.get(exceptions.size() - 1);
- return this;
- }
-
- // navigate within the exception list
- public TokenValidator exFirst() {
- try {
- // curException = exceptions.get(0);
- } catch (IndexOutOfBoundsException ex) {
- curException = null;
- }
- return this;
-
- }
-
- public TokenValidator exAt(final int index) {
- try {
- // curException = exceptions.get(index);
- } catch (IndexOutOfBoundsException ex) {
- curException = null;
- }
- return this;
- }
-
// --- Validation ---
public TokenValidator isText(final String expected) {
@@ -162,32 +120,8 @@ public class TokenValidator {
private List<? extends Token> parseInput(final String input) {
ANTLRInputStream inputStream = new ANTLRInputStream(input);
-
- UriLexer lexer = new UriLexerWithTrace(inputStream, logLevel, startMode);
- // lexer.addErrorListener(new ErrorCollector(this));
+ UriLexer lexer = new UriLexer(inputStream);
+ lexer.mode(startMode);
return lexer.getAllTokens();
}
-
- public TokenValidator showTokens() {
- boolean first = true;
- System.out.println("input: " + input);
- String nL = "\n";
- String out = "[" + nL;
- for (Token token : tokens) {
- if (!first) {
- out += ",";
- first = false;
- }
- int index = token.getType();
- if (index != -1) {
- out += "\"" + token.getText() + "\"" + " " + UriLexer.VOCABULARY.getDisplayName(index) + nL;
- } else {
- out += "\"" + token.getText() + "\"" + " " + index + nL;
- }
- }
- out += ']';
- System.out.println("tokens: " + out);
- return this;
- }
-
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/d7e23bf8/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/UriLexerWithTrace.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/UriLexerWithTrace.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/UriLexerWithTrace.java
deleted file mode 100644
index c067394..0000000
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/UriLexerWithTrace.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * 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.testutil;
-
-import org.antlr.v4.runtime.ANTLRInputStream;
-import org.antlr.v4.runtime.Token;
-import org.apache.olingo.server.core.uri.antlr.UriLexer;
-
-public class UriLexerWithTrace extends UriLexer {
- int logLevel = 0;
-
- public UriLexerWithTrace(final ANTLRInputStream antlrInputStream, final int logLevel) {
- super(antlrInputStream);
- this.logLevel = logLevel;
- }
-
- public UriLexerWithTrace(final ANTLRInputStream antlrInputStream, final int logLevel, final int mode) {
- super(antlrInputStream);
- super.mode(mode);
- this.logLevel = logLevel;
- }
-
- @Override
- public void emit(final Token token) {
- if (logLevel > 1) {
- String out = String.format("%1$-" + 20 + "s", token.getText());
-
- int tokenType = token.getType();
- if (tokenType == -1) {
- out += "-1/EOF";
- } else {
- out += UriLexer.VOCABULARY.getDisplayName(tokenType);
- }
- System.out.println("Lexer.emit(...):" + out);
- }
-
- super.emit(token);
- }
-
- @Override
- public void pushMode(final int m) {
-
- String out = UriLexer.modeNames[_mode] + "-->";
-
- super.pushMode(m);
-
- out += UriLexer.modeNames[_mode];
-
- if (logLevel > 1) {
- System.out.println(out + " ");
- }
- }
-
- @Override
- public int popMode() {
-
- String out = UriLexer.modeNames[_mode] + "-->";
-
- int m = super.popMode();
-
- out += UriLexer.modeNames[_mode];
-
- if (logLevel > 1) {
- System.out.println(out + " ");
- }
-
- return m;
- }
-}
[04/30] olingo-odata4 git commit: [OLINGO-833] Replace unicode 6.x
characters in fit-test
Posted by ch...@apache.org.
[OLINGO-833] Replace unicode 6.x characters in fit-test
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/83f11b92
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/83f11b92
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/83f11b92
Branch: refs/heads/master
Commit: 83f11b926da1e52c09b0bc8320eec251946f4952
Parents: 927ecb9
Author: Christian Holzer <c....@sap.com>
Authored: Tue Dec 8 10:20:59 2015 +0100
Committer: Christian Holzer <c....@sap.com>
Committed: Tue Dec 8 10:20:59 2015 +0100
----------------------------------------------------------------------
.../apache/olingo/fit/tecsvc/client/SystemQueryOptionITCase.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/83f11b92/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/SystemQueryOptionITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/SystemQueryOptionITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/SystemQueryOptionITCase.java
index 3d0df10..bb7fd31 100644
--- a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/SystemQueryOptionITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/SystemQueryOptionITCase.java
@@ -320,7 +320,7 @@ public class SystemQueryOptionITCase extends AbstractParamTecSvcITCase {
.getEntitySetRequest(getClient().newURIBuilder(SERVICE_URI)
.appendEntitySetSegment(ES_ALL_PRIM)
.search("\"This is a \\\"$imple\\\"\\\\Phras~\" AND "
- + "AnUnicodeWordLl\u01E3Lm\u02B5Lo\u1BE4Lt\u01F2Lu\u03D3Nl\u216F")
+ + "AnUnicodeWordLl\u01E3Lm\u02B5Lo\u00AALt\u01F2Lu\u03D3Nl\u216F")
.build());
setCookieHeader(request);
final ODataRetrieveResponse<ClientEntitySet> response = request.execute();
[16/30] olingo-odata4 git commit: [OLINGO-834] ExpressionParser
parses path expressions
Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java
index 1b2d508..af45e80 100644
--- a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java
+++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java
@@ -55,7 +55,7 @@ public class UriTokenizerTest {
@Test
public void sequence() {
- final UriTokenizer tokenizer = new UriTokenizer("(A=1,B=2);.*/+-");
+ UriTokenizer tokenizer = new UriTokenizer("(A=1,B=2);.*/+-");
assertTrue(tokenizer.next(TokenKind.OPEN));
assertFalse(tokenizer.next(TokenKind.OPEN));
assertTrue(tokenizer.next(TokenKind.ODataIdentifier));
@@ -78,6 +78,22 @@ public class UriTokenizerTest {
assertTrue(tokenizer.next(TokenKind.PLUS));
assertTrue(tokenizer.next(TokenKind.MINUS));
assertTrue(tokenizer.next(TokenKind.EOF));
+
+ tokenizer = new UriTokenizer("any(a:true) or all(b:false)");
+ assertTrue(tokenizer.next(TokenKind.ANY));
+ assertTrue(tokenizer.next(TokenKind.OPEN));
+ assertTrue(tokenizer.next(TokenKind.ODataIdentifier));
+ assertTrue(tokenizer.next(TokenKind.COLON));
+ assertTrue(tokenizer.next(TokenKind.BooleanValue));
+ assertTrue(tokenizer.next(TokenKind.CLOSE));
+ assertTrue(tokenizer.next(TokenKind.OrOperator));
+ assertTrue(tokenizer.next(TokenKind.ALL));
+ assertTrue(tokenizer.next(TokenKind.OPEN));
+ assertTrue(tokenizer.next(TokenKind.ODataIdentifier));
+ assertTrue(tokenizer.next(TokenKind.COLON));
+ assertTrue(tokenizer.next(TokenKind.BooleanValue));
+ assertTrue(tokenizer.next(TokenKind.CLOSE));
+ assertTrue(tokenizer.next(TokenKind.EOF));
}
@Test
@@ -455,6 +471,19 @@ public class UriTokenizerTest {
}
}
+ @Test
+ public void suffixes() {
+ UriTokenizer tokenizer = new UriTokenizer("p1 asc,p2 desc");
+ assertTrue(tokenizer.next(TokenKind.ODataIdentifier));
+ assertTrue(tokenizer.next(TokenKind.AscSuffix));
+ assertTrue(tokenizer.next(TokenKind.COMMA));
+ assertTrue(tokenizer.next(TokenKind.ODataIdentifier));
+ assertTrue(tokenizer.next(TokenKind.DescSuffix));
+ assertTrue(tokenizer.next(TokenKind.EOF));
+
+ wrongToken(TokenKind.DescSuffix, " desc", 'D');
+ }
+
private void wrongToken(final TokenKind kind, final String value, final char disturbCharacter) {
assertFalse(new UriTokenizer(disturbCharacter + value).next(kind));
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/UriResourceImplTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/UriResourceImplTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/UriResourceImplTest.java
index a945d11..72f3eb9 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/UriResourceImplTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/UriResourceImplTest.java
@@ -57,7 +57,7 @@ public class UriResourceImplTest {
new EdmTechProvider(), Collections.<EdmxReference> emptyList()).getEdm();
@Test
- public void testUriParameterImpl() {
+ public void uriParameterImpl() {
UriParameterImpl impl = new UriParameterImpl();
Expression expression = new LiteralImpl("Expression", null);
@@ -73,21 +73,20 @@ public class UriResourceImplTest {
}
@Test
- public void testUriResourceActionImpl() {
- UriResourceActionImpl impl = new UriResourceActionImpl();
+ public void uriResourceActionImpl() {
+ UriResourceActionImpl impl = new UriResourceActionImpl((EdmAction) null);
assertEquals(UriResourceKind.action, impl.getKind());
assertEquals("", impl.toString());
// action
EdmAction action = edm.getUnboundAction(ActionProvider.nameUARTETTwoKeyTwoPrimParam);
- impl.setAction(action);
+ impl = new UriResourceActionImpl(action);
assertEquals(action, impl.getAction());
assertEquals(ActionProvider.nameUARTETTwoKeyTwoPrimParam.getName(), impl.toString());
// action import
- impl = new UriResourceActionImpl();
EdmActionImport actionImport = edm.getEntityContainer().getActionImport("AIRTCTTwoPrimParam");
- impl.setActionImport(actionImport);
+ impl = new UriResourceActionImpl(actionImport);
assertEquals(actionImport, impl.getActionImport());
assertEquals(actionImport.getUnboundAction(), impl.getAction());
assertFalse(impl.isCollection());
@@ -95,20 +94,16 @@ public class UriResourceImplTest {
assertEquals(actionImport.getUnboundAction().getReturnType().getType(), impl.getType());
actionImport = edm.getEntityContainer().getActionImport("AIRT");
- impl.setActionImport(actionImport);
+ impl = new UriResourceActionImpl(actionImport);
assertFalse(impl.isCollection());
assertNull(impl.getType());
}
@Test
- public void testUriResourceLambdaAllImpl() {
- UriResourceLambdaAllImpl impl = new UriResourceLambdaAllImpl();
- assertEquals(UriResourceKind.lambdaAll, impl.getKind());
-
+ public void uriResourceLambdaAllImpl() {
Expression expression = new LiteralImpl("Expression", null);
- impl.setExpression(expression);
- impl.setLamdaVariable("A");
-
+ UriResourceLambdaAllImpl impl = new UriResourceLambdaAllImpl("A", expression);
+ assertEquals(UriResourceKind.lambdaAll, impl.getKind());
assertFalse(impl.isCollection());
assertEquals(expression, impl.getExpression());
assertEquals("A", impl.getLambdaVariable());
@@ -117,14 +112,10 @@ public class UriResourceImplTest {
}
@Test
- public void testUriResourceLambdaAnyImpl() {
- UriResourceLambdaAnyImpl impl = new UriResourceLambdaAnyImpl();
- assertEquals(UriResourceKind.lambdaAny, impl.getKind());
-
+ public void uriResourceLambdaAnyImpl() {
Expression expression = new LiteralImpl("Expression", null);
- impl.setExpression(expression);
- impl.setLamdaVariable("A");
-
+ UriResourceLambdaAnyImpl impl = new UriResourceLambdaAnyImpl("A", expression);
+ assertEquals(UriResourceKind.lambdaAny, impl.getKind());
assertFalse(impl.isCollection());
assertEquals(expression, impl.getExpression());
assertEquals("A", impl.getLambdaVariable());
@@ -133,14 +124,11 @@ public class UriResourceImplTest {
}
@Test
- public void testUriResourceComplexPropertyImpl() {
- UriResourceComplexPropertyImpl impl = new UriResourceComplexPropertyImpl();
- assertEquals(UriResourceKind.complexProperty, impl.getKind());
-
+ public void uriResourceComplexPropertyImpl() {
EdmEntityType entityType = edm.getEntityType(EntityTypeProvider.nameETKeyNav);
EdmProperty property = (EdmProperty) entityType.getProperty("PropertyCompNav");
- impl.setProperty(property);
-
+ UriResourceComplexPropertyImpl impl = new UriResourceComplexPropertyImpl(property);
+ assertEquals(UriResourceKind.complexProperty, impl.getKind());
assertEquals(property, impl.getProperty());
assertEquals(property.getName(), impl.toString());
assertFalse(impl.isCollection());
@@ -158,14 +146,11 @@ public class UriResourceImplTest {
}
@Test
- public void testUriResourcePrimitivePropertyImpl() {
- UriResourcePrimitivePropertyImpl impl = new UriResourcePrimitivePropertyImpl();
- assertEquals(UriResourceKind.primitiveProperty, impl.getKind());
-
+ public void uriResourcePrimitivePropertyImpl() {
EdmEntityType entityType = edm.getEntityType(EntityTypeProvider.nameETKeyNav);
EdmProperty property = (EdmProperty) entityType.getProperty("PropertyInt16");
- impl.setProperty(property);
-
+ UriResourcePrimitivePropertyImpl impl = new UriResourcePrimitivePropertyImpl(property);
+ assertEquals(UriResourceKind.primitiveProperty, impl.getKind());
assertEquals(property, impl.getProperty());
assertEquals(property.getName(), impl.toString());
assertFalse(impl.isCollection());
@@ -173,20 +158,17 @@ public class UriResourceImplTest {
}
@Test
- public void testUriResourceCountImpl() {
+ public void uriResourceCountImpl() {
UriResourceCountImpl impl = new UriResourceCountImpl();
assertEquals(UriResourceKind.count, impl.getKind());
assertEquals("$count", impl.toString());
}
@Test
- public void testUriResourceEntitySetImpl() {
- UriResourceEntitySetImpl impl = new UriResourceEntitySetImpl();
- assertEquals(UriResourceKind.entitySet, impl.getKind());
-
+ public void uriResourceEntitySetImpl() {
EdmEntitySet entitySet = edm.getEntityContainer().getEntitySet("ESAllPrim");
- impl.setEntitSet(entitySet);
-
+ UriResourceEntitySetImpl impl = new UriResourceEntitySetImpl(entitySet);
+ assertEquals(UriResourceKind.entitySet, impl.getKind());
assertEquals("ESAllPrim", impl.toString());
assertEquals(entitySet, impl.getEntitySet());
@@ -201,8 +183,8 @@ public class UriResourceImplTest {
}
@Test
- public void testUriResourceFunctionImpl() {
- UriResourceFunctionImpl impl = new UriResourceFunctionImpl();
+ public void uriResourceFunctionImpl() {
+ UriResourceFunctionImpl impl = new UriResourceFunctionImpl(null, null, null);
assertEquals(UriResourceKind.function, impl.getKind());
assertEquals("", impl.toString());
@@ -210,39 +192,38 @@ public class UriResourceImplTest {
EdmFunction function = edm.getEntityContainer().getFunctionImport("FINRTInt16")
.getUnboundFunction(Collections.<String> emptyList());
assertNotNull(function);
- impl.setFunction(function);
+ impl = new UriResourceFunctionImpl(null, function, null);
assertEquals(function, impl.getFunction());
assertEquals("UFNRTInt16", impl.toString());
assertEquals(function.getReturnType().getType(), impl.getType());
- assertFalse(impl.isParameterListFilled());
+ assertTrue(impl.getParameters().isEmpty());
// function import
- impl = new UriResourceFunctionImpl();
EdmFunctionImport functionImport = edm.getEntityContainer().getFunctionImport("FINRTInt16");
- impl.setFunctionImport(functionImport, Collections.<UriParameter> emptyList());
+ impl = new UriResourceFunctionImpl(functionImport, functionImport.getUnboundFunctions().get(0),
+ Collections.<UriParameter> emptyList());
assertEquals(functionImport, impl.getFunctionImport());
assertEquals("FINRTInt16", impl.toString());
// function collection
- impl = new UriResourceFunctionImpl();
functionImport = edm.getEntityContainer().getFunctionImport("FICRTCollESTwoKeyNavParam");
- assertNotNull(function);
UriParameter parameter = new UriParameterImpl().setName("ParameterInt16");
- impl.setFunctionImport(functionImport, Collections.singletonList(parameter));
+ impl = new UriResourceFunctionImpl(functionImport,
+ functionImport.getUnboundFunction(Collections.singletonList("ParameterInt16")),
+ Collections.singletonList(parameter));
assertEquals("FICRTCollESTwoKeyNavParam", impl.toString());
- impl.setFunction(functionImport.getUnboundFunction(Collections.singletonList("ParameterInt16")));
assertTrue(impl.isCollection());
impl.setKeyPredicates(Collections.<UriParameter> emptyList());
assertFalse(impl.isCollection());
+ assertFalse(impl.getParameters().isEmpty());
assertEquals(parameter, impl.getParameters().get(0));
- assertTrue(impl.isParameterListFilled());
}
@Test
- public void testUriResourceImplKeyPred() {
+ public void uriResourceImplKeyPred() {
final EdmEntityType entityType = edm.getEntityType(EntityTypeProvider.nameETTwoKeyNav);
class Mock extends UriResourceWithKeysImpl {
@@ -306,7 +287,7 @@ public class UriResourceImplTest {
}
@Test
- public void testUriResourceImplTyped() {
+ public void uriResourceImplTyped() {
final EdmEntityType entityType = edm.getEntityType(EntityTypeProvider.nameETTwoKeyNav);
class Mock extends UriResourceTypedImpl {
@@ -344,18 +325,15 @@ public class UriResourceImplTest {
}
@Test
- public void testUriResourceItImpl() {
- UriResourceItImpl impl = new UriResourceItImpl();
- assertEquals(UriResourceKind.it, impl.getKind());
-
+ public void uriResourceItImpl() {
EdmEntityType entityType = edm.getEntityType(EntityTypeProvider.nameETTwoKeyNav);
+ UriResourceItImpl impl = new UriResourceItImpl(entityType, false);
+ assertEquals(UriResourceKind.it, impl.getKind());
assertEquals("$it", impl.toString());
-
- impl.setType(entityType);
assertEquals(entityType, impl.getType());
-
assertFalse(impl.isCollection());
- impl.setCollection(true);
+
+ impl = new UriResourceItImpl(entityType, true);
assertTrue(impl.isCollection());
impl.setKeyPredicates(Collections.singletonList(
(UriParameter) new UriParameterImpl().setName("ParameterInt16")));
@@ -363,15 +341,13 @@ public class UriResourceImplTest {
}
@Test
- public void testUriResourceNavigationPropertyImpl() {
- UriResourceNavigationPropertyImpl impl = new UriResourceNavigationPropertyImpl();
- assertEquals(UriResourceKind.navigationProperty, impl.getKind());
-
+ public void uriResourceNavigationPropertyImpl() {
EdmEntityType entityType = edm.getEntityType(EntityTypeProvider.nameETTwoKeyNav);
EdmNavigationProperty property = (EdmNavigationProperty) entityType.getProperty("NavPropertyETKeyNavMany");
assertNotNull(property);
- impl.setNavigationProperty(property);
+ UriResourceNavigationPropertyImpl impl = new UriResourceNavigationPropertyImpl(property);
+ assertEquals(UriResourceKind.navigationProperty, impl.getKind());
assertEquals(property, impl.getProperty());
assertEquals("NavPropertyETKeyNavMany", impl.toString());
@@ -384,25 +360,22 @@ public class UriResourceImplTest {
}
@Test
- public void testUriResourceRefImpl() {
+ public void uriResourceRefImpl() {
UriResourceRefImpl impl = new UriResourceRefImpl();
assertEquals(UriResourceKind.ref, impl.getKind());
assertEquals("$ref", impl.toString());
}
@Test
- public void testUriResourceRootImpl() {
- UriResourceRootImpl impl = new UriResourceRootImpl();
- assertEquals(UriResourceKind.root, impl.getKind());
-
+ public void uriResourceRootImpl() {
EdmEntityType entityType = edm.getEntityType(EntityTypeProvider.nameETTwoKeyNav);
+ UriResourceRootImpl impl = new UriResourceRootImpl(entityType, false);
+ assertEquals(UriResourceKind.root, impl.getKind());
assertEquals("$root", impl.toString());
-
- impl.setType(entityType);
assertEquals(entityType, impl.getType());
-
assertFalse(impl.isCollection());
- impl.setCollection(true);
+
+ impl = new UriResourceRootImpl(entityType, true);
assertTrue(impl.isCollection());
impl.setKeyPredicates(Collections.singletonList(
(UriParameter) new UriParameterImpl().setName("ParameterInt16")));
@@ -410,14 +383,11 @@ public class UriResourceImplTest {
}
@Test
- public void testUriResourceSingletonImpl() {
- UriResourceSingletonImpl impl = new UriResourceSingletonImpl();
- assertEquals(UriResourceKind.singleton, impl.getKind());
-
+ public void uriResourceSingletonImpl() {
EdmSingleton singleton = edm.getEntityContainer().getSingleton("SINav");
EdmEntityType entityTypeBaseColl = edm.getEntityType(EntityTypeProvider.nameETBaseTwoKeyNav);
- impl.setSingleton(singleton);
-
+ UriResourceSingletonImpl impl = new UriResourceSingletonImpl(singleton);
+ assertEquals(UriResourceKind.singleton, impl.getKind());
assertEquals("SINav", impl.toString());
assertEquals(singleton, impl.getSingleton());
@@ -433,41 +403,33 @@ public class UriResourceImplTest {
}
@Test
- public void testUriResourceValueImpl() {
+ public void uriResourceValueImpl() {
UriResourceValueImpl impl = new UriResourceValueImpl();
assertEquals(UriResourceKind.value, impl.getKind());
assertEquals("$value", impl.toString());
}
@Test
- public void testUriResourceLambdaVarImpl() {
- UriResourceLambdaVarImpl impl = new UriResourceLambdaVarImpl();
- assertEquals(UriResourceKind.lambdaVariable, impl.getKind());
-
+ public void uriResourceLambdaVarImpl() {
EdmEntityType entityType = edm.getEntityType(EntityTypeProvider.nameETTwoKeyNav);
- impl.setType(entityType);
- impl.setVariableText("A");
-
+ UriResourceLambdaVarImpl impl = new UriResourceLambdaVarImpl("A", entityType);
+ assertEquals(UriResourceKind.lambdaVariable, impl.getKind());
assertEquals("A", impl.toString());
assertEquals(entityType, impl.getType());
assertEquals("A", impl.getVariableName());
assertFalse(impl.isCollection());
- impl.setCollection(true);
- assertTrue(impl.isCollection());
}
@Test
- public void testUriResourceStartingTypeFilterImpl() {
- UriResourceStartingTypeFilterImpl impl = new UriResourceStartingTypeFilterImpl();
-
+ public void uriResourceStartingTypeFilterImpl() {
EdmEntityType entityType = edm.getEntityType(EntityTypeProvider.nameETTwoKeyNav);
- impl.setType(entityType);
+ UriResourceStartingTypeFilterImpl impl = new UriResourceStartingTypeFilterImpl(entityType, false);
assertEquals("olingo.odata.test1.ETTwoKeyNav", impl.toString());
assertEquals(entityType, impl.getType());
-
assertFalse(impl.isCollection());
- impl.setCollection(true);
+
+ impl = new UriResourceStartingTypeFilterImpl(entityType, true);
assertTrue(impl.isCollection());
impl.setKeyPredicates(Collections.singletonList(
(UriParameter) new UriParameterImpl().setName("ParameterInt16")));
[14/30] olingo-odata4 git commit: [OLINGO-834] Type checks in
ExpressionParser
Posted by ch...@apache.org.
[OLINGO-834] Type checks in ExpressionParser
Signed-off-by: Christian Amend <ch...@sap.com>
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/104ecf43
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/104ecf43
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/104ecf43
Branch: refs/heads/master
Commit: 104ecf43d255722e99e18641a1444e33a0ff11b1
Parents: 2f3bc28
Author: Klaus Straubinger <kl...@sap.com>
Authored: Wed Dec 16 16:14:12 2015 +0100
Committer: Christian Amend <ch...@sap.com>
Committed: Wed Dec 16 16:26:51 2015 +0100
----------------------------------------------------------------------
.../core/uri/parser/ExpressionParser.java | 413 +++++++++++++++----
.../core/uri/parser/UriParseTreeVisitor.java | 24 +-
.../server/core/uri/parser/UriTokenizer.java | 5 +
.../uri/queryoption/expression/BinaryImpl.java | 10 +-
.../uri/queryoption/expression/MethodImpl.java | 70 ++++
.../uri/queryoption/expression/UnaryImpl.java | 9 +-
.../core/uri/parser/ExpressionParserTest.java | 142 ++++++-
.../core/uri/parser/UriTokenizerTest.java | 6 +-
.../queryoption/expression/ExpressionTest.java | 64 +--
9 files changed, 616 insertions(+), 127 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/104ecf43/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java
index 3b04089..61c023d 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java
@@ -24,13 +24,26 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import org.apache.olingo.commons.api.edm.Edm;
import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory;
+import org.apache.olingo.commons.api.edm.EdmType;
+import org.apache.olingo.commons.api.edm.EdmTypeDefinition;
+import org.apache.olingo.commons.api.edm.FullQualifiedName;
+import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
+import org.apache.olingo.server.api.OData;
+import org.apache.olingo.server.api.uri.queryoption.expression.Alias;
+import org.apache.olingo.server.api.uri.queryoption.expression.Binary;
import org.apache.olingo.server.api.uri.queryoption.expression.BinaryOperatorKind;
+import org.apache.olingo.server.api.uri.queryoption.expression.Enumeration;
import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
+import org.apache.olingo.server.api.uri.queryoption.expression.LambdaRef;
+import org.apache.olingo.server.api.uri.queryoption.expression.Literal;
+import org.apache.olingo.server.api.uri.queryoption.expression.Member;
import org.apache.olingo.server.api.uri.queryoption.expression.Method;
import org.apache.olingo.server.api.uri.queryoption.expression.MethodKind;
+import org.apache.olingo.server.api.uri.queryoption.expression.TypeLiteral;
+import org.apache.olingo.server.api.uri.queryoption.expression.Unary;
import org.apache.olingo.server.api.uri.queryoption.expression.UnaryOperatorKind;
import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind;
import org.apache.olingo.server.core.uri.queryoption.expression.AliasImpl;
@@ -72,10 +85,10 @@ public class ExpressionParser {
tokenToUnaryOperator = Collections.unmodifiableMap(temp);
}
+ // 'cast' and 'isof' are handled specially.
private static final Map<TokenKind, MethodKind> tokenToMethod;
static {
Map<TokenKind, MethodKind> temp = new HashMap<TokenKind, MethodKind>();
- temp.put(TokenKind.CastMethod, MethodKind.CAST);
temp.put(TokenKind.CeilingMethod, MethodKind.CEILING);
temp.put(TokenKind.ConcatMethod, MethodKind.CONCAT);
temp.put(TokenKind.ContainsMethod, MethodKind.CONTAINS);
@@ -89,7 +102,6 @@ public class ExpressionParser {
temp.put(TokenKind.GeoLengthMethod, MethodKind.GEOLENGTH);
temp.put(TokenKind.HourMethod, MethodKind.HOUR);
temp.put(TokenKind.IndexofMethod, MethodKind.INDEXOF);
- temp.put(TokenKind.IsofMethod, MethodKind.ISOF);
temp.put(TokenKind.LengthMethod, MethodKind.LENGTH);
temp.put(TokenKind.MaxdatetimeMethod, MethodKind.MAXDATETIME);
temp.put(TokenKind.MindatetimeMethod, MethodKind.MINDATETIME);
@@ -131,8 +143,16 @@ public class ExpressionParser {
tokenToPrimitiveType = Collections.unmodifiableMap(temp);
}
+ private final Edm edm;
+ private final OData odata;
+
private UriTokenizer tokenizer;
+ public ExpressionParser(final Edm edm, final OData odata) {
+ this.edm = edm;
+ this.odata = odata;
+ }
+
public Expression parse(UriTokenizer tokenizer) throws UriParserException {
// Initialize tokenizer.
this.tokenizer = tokenizer;
@@ -144,7 +164,10 @@ public class ExpressionParser {
Expression left = parseAnd();
while (tokenizer.next(TokenKind.OrOperator)) {
final Expression right = parseAnd();
- left = new BinaryImpl(left, BinaryOperatorKind.OR, right);
+ checkType(left, EdmPrimitiveTypeKind.Boolean);
+ checkType(right, EdmPrimitiveTypeKind.Boolean);
+ left = new BinaryImpl(left, BinaryOperatorKind.OR, right,
+ odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Boolean));
}
return left;
}
@@ -153,7 +176,10 @@ public class ExpressionParser {
Expression left = parseExprEquality();
while (tokenizer.next(TokenKind.AndOperator)) {
final Expression right = parseExprEquality();
- left = new BinaryImpl(left, BinaryOperatorKind.AND, right);
+ checkType(left, EdmPrimitiveTypeKind.Boolean);
+ checkType(right, EdmPrimitiveTypeKind.Boolean);
+ left = new BinaryImpl(left, BinaryOperatorKind.AND, right,
+ odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Boolean));
}
return left;
}
@@ -164,12 +190,15 @@ public class ExpressionParser {
// Null for everything other than EQ or NE
while (operatorTokenKind != null) {
final Expression right = parseExprEquality();
- left = new BinaryImpl(left, tokenToBinaryOperator.get(operatorTokenKind), right);
+ checkEqualityTypes(left, right);
+ left = new BinaryImpl(left, tokenToBinaryOperator.get(operatorTokenKind), right,
+ odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Boolean));
operatorTokenKind = ParserHelper.next(tokenizer, TokenKind.EqualsOperator, TokenKind.NotEqualsOperator);
}
return left;
}
+ // TODO: The 'isof' method has relational precedence and should appear here.
private Expression parseExprRel() throws UriParserException {
Expression left = parseExprAdd();
TokenKind operatorTokenKind = ParserHelper.next(tokenizer,
@@ -178,7 +207,9 @@ public class ExpressionParser {
// Null for everything other than GT or GE or LT or LE
while (operatorTokenKind != null) {
final Expression right = parseExprAdd();
- left = new BinaryImpl(left, tokenToBinaryOperator.get(operatorTokenKind), right);
+ checkRelationTypes(left, right);
+ left = new BinaryImpl(left, tokenToBinaryOperator.get(operatorTokenKind), right,
+ odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Boolean));
operatorTokenKind = ParserHelper.next(tokenizer,
TokenKind.GreaterThanOperator, TokenKind.GreaterThanOrEqualsOperator,
TokenKind.LessThanOperator, TokenKind.LessThanOrEqualsOperator);
@@ -192,7 +223,9 @@ public class ExpressionParser {
// Null for everything other than ADD or SUB
while (operatorTokenKind != null) {
final Expression right = parseExprMul();
- left = new BinaryImpl(left, tokenToBinaryOperator.get(operatorTokenKind), right);
+ checkAddSubTypes(left, right, operatorTokenKind == TokenKind.AddOperator);
+ left = new BinaryImpl(left, tokenToBinaryOperator.get(operatorTokenKind), right,
+ odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Double));
operatorTokenKind = ParserHelper.next(tokenizer, TokenKind.AddOperator, TokenKind.SubOperator);
}
return left;
@@ -205,28 +238,61 @@ public class ExpressionParser {
// Null for everything other than MUL or DIV or MOD
while (operatorTokenKind != null) {
final Expression right = parseExprUnary();
- left = new BinaryImpl(left, tokenToBinaryOperator.get(operatorTokenKind), right);
+ checkType(left,
+ EdmPrimitiveTypeKind.Int16, EdmPrimitiveTypeKind.Int32, EdmPrimitiveTypeKind.Int64,
+ EdmPrimitiveTypeKind.Byte, EdmPrimitiveTypeKind.SByte,
+ EdmPrimitiveTypeKind.Decimal, EdmPrimitiveTypeKind.Single, EdmPrimitiveTypeKind.Double);
+ checkType(right,
+ EdmPrimitiveTypeKind.Int16, EdmPrimitiveTypeKind.Int32, EdmPrimitiveTypeKind.Int64,
+ EdmPrimitiveTypeKind.Byte, EdmPrimitiveTypeKind.SByte,
+ EdmPrimitiveTypeKind.Decimal, EdmPrimitiveTypeKind.Single, EdmPrimitiveTypeKind.Double);
+ left = new BinaryImpl(left, tokenToBinaryOperator.get(operatorTokenKind), right,
+ odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Double));
operatorTokenKind = ParserHelper.next(tokenizer,
TokenKind.MulOperator, TokenKind.DivOperator, TokenKind.ModOperator);
}
return left;
}
+ // TODO: The 'cast' method has unary precedence and should appear here.
private Expression parseExprUnary() throws UriParserException {
Expression left = null;
TokenKind operatorTokenKind = ParserHelper.next(tokenizer, TokenKind.MINUS, TokenKind.NotOperator);
// Null for everything other than - or NOT
while (operatorTokenKind != null) {
- final Expression expression = parseExprValue();
- left = new UnaryImpl(tokenToUnaryOperator.get(operatorTokenKind), expression);
+ final Expression expression = parseExprPrimary();
+ if (operatorTokenKind == TokenKind.NotOperator) {
+ checkType(expression, EdmPrimitiveTypeKind.Boolean);
+ } else {
+ checkType(expression,
+ EdmPrimitiveTypeKind.Int16, EdmPrimitiveTypeKind.Int32, EdmPrimitiveTypeKind.Int64,
+ EdmPrimitiveTypeKind.Byte, EdmPrimitiveTypeKind.SByte,
+ EdmPrimitiveTypeKind.Decimal, EdmPrimitiveTypeKind.Single, EdmPrimitiveTypeKind.Double,
+ EdmPrimitiveTypeKind.Duration);
+ }
+ left = new UnaryImpl(tokenToUnaryOperator.get(operatorTokenKind), expression, getType(expression));
operatorTokenKind = ParserHelper.next(tokenizer, TokenKind.MINUS, TokenKind.NotOperator);
}
if (left == null) {
- left = parseExprValue();
+ left = parseExprPrimary();
}
return left;
}
+ private Expression parseExprPrimary() throws UriParserException {
+ final Expression left = parseExprValue();
+ if (isEnumType(left) && tokenizer.next(TokenKind.HasOperator)) {
+ ParserHelper.requireNext(tokenizer, TokenKind.EnumValue);
+ final String primitiveValueLiteral = tokenizer.getText();
+ final Expression right = new LiteralImpl(primitiveValueLiteral, getEnumType(primitiveValueLiteral));
+ checkEnumLiteral(right);
+ return new BinaryImpl(left, BinaryOperatorKind.HAS, right,
+ odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Boolean));
+ } else {
+ return left;
+ }
+ }
+
private Expression parseExprValue() throws UriParserException {
if (tokenizer.next(TokenKind.OPEN)) {
final Expression expression = parseExpression();
@@ -251,44 +317,34 @@ public class ExpressionParser {
// TODO: Consume $it expression.
}
- if (tokenizer.next(TokenKind.QualifiedName)) {
- // TODO: Consume typecast or bound-function expression.
- }
-
TokenKind nextPrimitive = ParserHelper.nextPrimitive(tokenizer);
if (nextPrimitive != null) {
+ final String primitiveValueLiteral = tokenizer.getText();
final EdmPrimitiveTypeKind primitiveTypeKind = tokenToPrimitiveType.get(nextPrimitive);
EdmPrimitiveType type;
if (primitiveTypeKind == null) {
if (nextPrimitive == TokenKind.EnumValue) {
- // TODO: Get enum type.
- type = null;
+ type = getEnumType(primitiveValueLiteral);
} else {
// Null handling
type = null;
}
} else {
- type = EdmPrimitiveTypeFactory.getInstance(primitiveTypeKind);
+ type = odata.createPrimitiveTypeInstance(primitiveTypeKind);
}
- return new LiteralImpl(tokenizer.getText(), type);
+ return new LiteralImpl(primitiveValueLiteral, type);
}
+ // The method token text includes the opening parenthesis so that method calls can be recognized unambiguously.
+ // OData identifiers have to be considered after that.
TokenKind nextMethod = nextMethod();
if (nextMethod != null) {
MethodKind methodKind = tokenToMethod.get(nextMethod);
- List<Expression> parameters = new ArrayList<Expression>();
- // The method token text includes the opening parenthesis!
- if (!tokenizer.next(TokenKind.CLOSE)) {
- do {
- parameters.add(parseExpression());
- } while (tokenizer.next(TokenKind.COMMA));
- ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
- }
-
- MethodImpl methodImpl = new MethodImpl(methodKind, parameters);
- validateMethodParameters(methodImpl);
+ return new MethodImpl(methodKind, parseMethodParameters(methodKind));
+ }
- return methodImpl;
+ if (tokenizer.next(TokenKind.QualifiedName)) {
+ // TODO: Consume typecast or bound-function expression.
}
if (tokenizer.next(TokenKind.ODataIdentifier)) {
@@ -298,85 +354,131 @@ public class ExpressionParser {
throw new UriParserSyntaxException("Unexpected token", UriParserSyntaxException.MessageKeys.SYNTAX);
}
- private void validateMethodParameters(final Method method) throws UriParserException {
- // We might validate parameter types in the future.
- int size = method.getParameters().size();
- switch (method.getMethod()) {
- // Must have two Parameters.
- case CONTAINS:
- case ENDSWITH:
- case STARTSWITH:
- case INDEXOF:
- case CONCAT:
- case GEODISTANCE:
- case GEOINTERSECTS:
- if (size != 2) {
- throw new UriParserSemanticException(
- "The method " + method.getMethod() + " needs exactly two parameters.",
- null); // TODO: message key
- }
+ private List<Expression> parseMethodParameters(final MethodKind methodKind) throws UriParserException {
+ List<Expression> parameters = new ArrayList<Expression>();
+ switch (methodKind) {
+ // Must have no parameter.
+ case NOW:
+ case MAXDATETIME:
+ case MINDATETIME:
break;
+
// Must have one parameter.
case LENGTH:
case TOLOWER:
case TOUPPER:
case TRIM:
+ final Expression stringParameter = parseExpression();
+ checkType(stringParameter, EdmPrimitiveTypeKind.String);
+ parameters.add(stringParameter);
+ break;
case YEAR:
case MONTH:
case DAY:
+ final Expression dateParameter = parseExpression();
+ checkType(dateParameter, EdmPrimitiveTypeKind.Date, EdmPrimitiveTypeKind.DateTimeOffset);
+ parameters.add(dateParameter);
+ break;
case HOUR:
case MINUTE:
case SECOND:
case FRACTIONALSECONDS:
+ final Expression timeParameter = parseExpression();
+ checkType(timeParameter, EdmPrimitiveTypeKind.TimeOfDay, EdmPrimitiveTypeKind.DateTimeOffset);
+ parameters.add(timeParameter);
+ break;
case DATE:
case TIME:
case TOTALOFFSETMINUTES:
+ final Expression dateTimeParameter = parseExpression();
+ checkType(dateTimeParameter, EdmPrimitiveTypeKind.DateTimeOffset);
+ parameters.add(dateTimeParameter);
+ break;
case TOTALSECONDS:
+ final Expression durationParameter = parseExpression();
+ checkType(durationParameter, EdmPrimitiveTypeKind.Duration);
+ parameters.add(durationParameter);
+ break;
case ROUND:
case FLOOR:
case CEILING:
+ final Expression decimalParameter = parseExpression();
+ checkType(decimalParameter,
+ EdmPrimitiveTypeKind.Decimal, EdmPrimitiveTypeKind.Single, EdmPrimitiveTypeKind.Double);
+ parameters.add(decimalParameter);
+ break;
case GEOLENGTH:
- if (size != 1) {
- throw new UriParserSemanticException(
- "The method '" + method.getMethod() + "' needs exactly one parameter.",
- null); // TODO: message key
- }
+ final Expression geoParameter = parseExpression();
+ checkType(geoParameter,
+ EdmPrimitiveTypeKind.GeographyLineString, EdmPrimitiveTypeKind.GeometryLineString);
+ parameters.add(geoParameter);
break;
- // Must have no parameter.
- case NOW:
- case MAXDATETIME:
- case MINDATETIME:
- if (size > 0) {
- throw new UriParserSemanticException("The method '" + method.getMethod() + "' must have no parameters.",
- null); // TODO: message key
- }
+
+ // Must have two parameters.
+ case CONTAINS:
+ case ENDSWITH:
+ case STARTSWITH:
+ case INDEXOF:
+ case CONCAT:
+ final Expression stringParameter1 = parseExpression();
+ checkType(stringParameter1, EdmPrimitiveTypeKind.String);
+ parameters.add(stringParameter1);
+ ParserHelper.requireNext(tokenizer, TokenKind.COMMA);
+ final Expression stringParameter2 = parseExpression();
+ checkType(stringParameter2, EdmPrimitiveTypeKind.String);
+ parameters.add(stringParameter2);
break;
- // Variable parameter number
- case CAST:
- case ISOF:
- if (size < 1 || size > 2) {
- throw new UriParserSemanticException(
- "The method '" + method.getMethod() + "' must have one or two parameters.",
- null); // TODO: message key
- }
+ case GEODISTANCE:
+ final Expression geoParameter1 = parseExpression();
+ checkType(geoParameter1, EdmPrimitiveTypeKind.GeographyPoint, EdmPrimitiveTypeKind.GeometryPoint);
+ parameters.add(geoParameter1);
+ ParserHelper.requireNext(tokenizer, TokenKind.COMMA);
+ final Expression geoParameter2 = parseExpression();
+ checkType(geoParameter2, EdmPrimitiveTypeKind.GeographyPoint, EdmPrimitiveTypeKind.GeometryPoint);
+ parameters.add(geoParameter2);
+ break;
+ case GEOINTERSECTS:
+ final Expression geoPointParameter = parseExpression();
+ checkType(geoPointParameter,
+ EdmPrimitiveTypeKind.GeographyPoint, EdmPrimitiveTypeKind.GeometryPoint);
+ parameters.add(geoPointParameter);
+ ParserHelper.requireNext(tokenizer, TokenKind.COMMA);
+ final Expression geoPolygonParameter = parseExpression();
+ checkType(geoPolygonParameter,
+ EdmPrimitiveTypeKind.GeographyPolygon, EdmPrimitiveTypeKind.GeometryPolygon);
+ parameters.add(geoPolygonParameter);
break;
+
+ // Can have two or three parameters.
case SUBSTRING:
- if (size < 2 || size > 3) {
- throw new UriParserSemanticException(
- "The method '" + method.getMethod() + "' must have two or three parameters.",
- null); // TODO: message key
+ final Expression parameterFirst = parseExpression();
+ checkType(parameterFirst, EdmPrimitiveTypeKind.String);
+ parameters.add(parameterFirst);
+ ParserHelper.requireNext(tokenizer, TokenKind.COMMA);
+ final Expression parameterSecond = parseExpression();
+ checkType(parameterSecond,
+ EdmPrimitiveTypeKind.Int64, EdmPrimitiveTypeKind.Int32, EdmPrimitiveTypeKind.Int16,
+ EdmPrimitiveTypeKind.Byte, EdmPrimitiveTypeKind.SByte);
+ parameters.add(parameterSecond);
+ if (tokenizer.next(TokenKind.COMMA)) {
+ final Expression parameterThird = parseExpression();
+ checkType(parameterThird,
+ EdmPrimitiveTypeKind.Int64, EdmPrimitiveTypeKind.Int32, EdmPrimitiveTypeKind.Int16,
+ EdmPrimitiveTypeKind.Byte, EdmPrimitiveTypeKind.SByte);
+ parameters.add(parameterThird);
}
break;
+
default:
- throw new UriParserSemanticException(
- "Unkown method '" + method.getMethod() + "'",
- null); // TODO: message key
+ throw new UriParserSemanticException("Unkown method '" + methodKind.name() + "'",
+ UriParserSemanticException.MessageKeys.NOT_IMPLEMENTED, methodKind.name()); // TODO: better message
}
+ ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
+ return parameters;
}
private TokenKind nextMethod() {
return ParserHelper.next(tokenizer,
- TokenKind.CastMethod,
TokenKind.CeilingMethod,
TokenKind.ConcatMethod,
TokenKind.ContainsMethod,
@@ -390,7 +492,6 @@ public class ExpressionParser {
TokenKind.GeoLengthMethod,
TokenKind.HourMethod,
TokenKind.IndexofMethod,
- TokenKind.IsofMethod,
TokenKind.LengthMethod,
TokenKind.MaxdatetimeMethod,
TokenKind.MindatetimeMethod,
@@ -409,4 +510,158 @@ public class ExpressionParser {
TokenKind.TrimMethod,
TokenKind.YearMethod);
}
+
+ private EdmType getType(final Expression expression) throws UriParserException {
+ EdmType type;
+ if (expression instanceof Literal) {
+ type = ((Literal) expression).getType();
+ } else if (expression instanceof TypeLiteral) {
+ type = ((TypeLiteral) expression).getType();
+ } else if (expression instanceof Enumeration) {
+ type = ((Enumeration) expression).getType();
+ } else if (expression instanceof Member) {
+ type = ((Member) expression).getType();
+ } else if (expression instanceof Unary) {
+ type = ((UnaryImpl) expression).getType();
+ } else if (expression instanceof Binary) {
+ type = ((BinaryImpl) expression).getType();
+ } else if (expression instanceof Method) {
+ type = ((MethodImpl) expression).getType();
+ } else if (expression instanceof LambdaRef) {
+ throw new UriParserSemanticException("Type determination not implemented.",
+ UriParserSemanticException.MessageKeys.NOT_IMPLEMENTED, expression.toString());
+ } else if (expression instanceof Alias) {
+ type = null; // The alias would have to be available already parsed.
+ } else {
+ throw new UriParserSemanticException("Unknown expression type.",
+ UriParserSemanticException.MessageKeys.NOT_IMPLEMENTED, expression.toString());
+ }
+ if (type != null && type.getKind() == EdmTypeKind.DEFINITION) {
+ type = ((EdmTypeDefinition) type).getUnderlyingType();
+ }
+ return type;
+ }
+
+ private boolean isType(final Expression expression, final EdmPrimitiveTypeKind... kinds) throws UriParserException {
+ final EdmType expressionType = getType(expression);
+ if (expressionType == null) {
+ return true;
+ }
+ for (final EdmPrimitiveTypeKind kind : kinds) {
+ if (expressionType.equals(odata.createPrimitiveTypeInstance(kind))) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void checkType(final Expression expression, final EdmPrimitiveTypeKind... kinds) throws UriParserException {
+ if (!isType(expression, kinds)) {
+ throw new UriParserSemanticException("Incompatible type.",
+ UriParserSemanticException.MessageKeys.UNKNOWN_TYPE, // TODO: better message
+ getType(expression) == null ?
+ "" :
+ getType(expression).getFullQualifiedName().getFullQualifiedNameAsString());
+ }
+ }
+
+ private void checkEqualityTypes(final Expression left, final Expression right) throws UriParserException {
+ final EdmType leftType = getType(left);
+ final EdmType rightType = getType(right);
+ if (leftType == null || rightType == null || leftType.equals(rightType)) {
+ return;
+ }
+ if (leftType.getKind() != EdmTypeKind.PRIMITIVE
+ || rightType.getKind() != EdmTypeKind.PRIMITIVE
+ || !(((EdmPrimitiveType) leftType).isCompatible((EdmPrimitiveType) rightType)
+ || ((EdmPrimitiveType) rightType).isCompatible((EdmPrimitiveType) leftType))) {
+ throw new UriParserSemanticException("Incompatible types.",
+ UriParserSemanticException.MessageKeys.UNKNOWN_TYPE, ""); // TODO: better message
+ }
+ }
+
+ private EdmPrimitiveType getEnumType(final String primitiveValueLiteral) throws UriParserException {
+ final String enumTypeName = primitiveValueLiteral.substring(0, primitiveValueLiteral.indexOf('\''));
+ final EdmPrimitiveType type = edm.getEnumType(new FullQualifiedName(enumTypeName));
+ if (type == null) {
+ throw new UriParserSemanticException("Unknown Enum type '" + enumTypeName + "'.",
+ UriParserSemanticException.MessageKeys.UNKNOWN_TYPE, enumTypeName);
+ }
+ return type;
+ }
+
+ private boolean isEnumType(final Expression expression) throws UriParserException {
+ final EdmType expressionType = getType(expression);
+ return expressionType == null
+ || expressionType.getKind() == EdmTypeKind.ENUM
+ || isType(expression,
+ EdmPrimitiveTypeKind.Int16, EdmPrimitiveTypeKind.Int32, EdmPrimitiveTypeKind.Int64,
+ EdmPrimitiveTypeKind.Byte, EdmPrimitiveTypeKind.SByte);
+ }
+
+ private void checkEnumLiteral(final Expression expression) throws UriParserException {
+ if (expression == null
+ || !(expression instanceof Literal)
+ || ((Literal) expression).getType() == null
+ || ((Literal) expression).getType().getKind() != EdmTypeKind.ENUM) {
+ throw new UriParserSemanticException("Enum literal expected.",
+ UriParserSemanticException.MessageKeys.UNKNOWN_TYPE, ""); // TODO: better message
+ }
+ }
+
+ private void checkRelationTypes(final Expression left, final Expression right) throws UriParserException {
+ final EdmType leftType = getType(left);
+ final EdmType rightType = getType(right);
+ if (leftType == null || rightType == null) {
+ return;
+ }
+ checkType(left,
+ EdmPrimitiveTypeKind.Int16, EdmPrimitiveTypeKind.Int32, EdmPrimitiveTypeKind.Int64,
+ EdmPrimitiveTypeKind.Byte, EdmPrimitiveTypeKind.SByte,
+ EdmPrimitiveTypeKind.Decimal, EdmPrimitiveTypeKind.Single, EdmPrimitiveTypeKind.Double,
+ EdmPrimitiveTypeKind.Boolean, EdmPrimitiveTypeKind.Guid, EdmPrimitiveTypeKind.String,
+ EdmPrimitiveTypeKind.Date, EdmPrimitiveTypeKind.TimeOfDay,
+ EdmPrimitiveTypeKind.DateTimeOffset, EdmPrimitiveTypeKind.Duration);
+ checkType(right,
+ EdmPrimitiveTypeKind.Int16, EdmPrimitiveTypeKind.Int32, EdmPrimitiveTypeKind.Int64,
+ EdmPrimitiveTypeKind.Byte, EdmPrimitiveTypeKind.SByte,
+ EdmPrimitiveTypeKind.Decimal, EdmPrimitiveTypeKind.Single, EdmPrimitiveTypeKind.Double,
+ EdmPrimitiveTypeKind.Boolean, EdmPrimitiveTypeKind.Guid, EdmPrimitiveTypeKind.String,
+ EdmPrimitiveTypeKind.Date, EdmPrimitiveTypeKind.TimeOfDay,
+ EdmPrimitiveTypeKind.DateTimeOffset, EdmPrimitiveTypeKind.Duration);
+ if (!(((EdmPrimitiveType) leftType).isCompatible((EdmPrimitiveType) rightType)
+ || ((EdmPrimitiveType) rightType).isCompatible((EdmPrimitiveType) leftType))) {
+ throw new UriParserSemanticException("Incompatible types.",
+ UriParserSemanticException.MessageKeys.UNKNOWN_TYPE, ""); // TODO: better message
+ }
+ }
+
+ private void checkAddSubTypes(final Expression left, final Expression right, final boolean isAdd)
+ throws UriParserException {
+ final EdmType leftType = getType(left);
+ final EdmType rightType = getType(right);
+ if (leftType == null || rightType == null
+ || isType(left,
+ EdmPrimitiveTypeKind.Int16, EdmPrimitiveTypeKind.Int32, EdmPrimitiveTypeKind.Int64,
+ EdmPrimitiveTypeKind.Byte, EdmPrimitiveTypeKind.SByte,
+ EdmPrimitiveTypeKind.Decimal, EdmPrimitiveTypeKind.Single, EdmPrimitiveTypeKind.Double)
+ && isType(right,
+ EdmPrimitiveTypeKind.Int16, EdmPrimitiveTypeKind.Int32, EdmPrimitiveTypeKind.Int64,
+ EdmPrimitiveTypeKind.Byte, EdmPrimitiveTypeKind.SByte,
+ EdmPrimitiveTypeKind.Decimal, EdmPrimitiveTypeKind.Single, EdmPrimitiveTypeKind.Double)) {
+ return;
+ }
+ if (isType(left, EdmPrimitiveTypeKind.DateTimeOffset)
+ && (isType(right, EdmPrimitiveTypeKind.Duration)
+ || isType(right, EdmPrimitiveTypeKind.DateTimeOffset) && !isAdd)) {
+ return;
+ }
+ if (isType(left, EdmPrimitiveTypeKind.Duration) && isType(right, EdmPrimitiveTypeKind.Duration)
+ || isType(left, EdmPrimitiveTypeKind.Date)
+ && (isType(right, EdmPrimitiveTypeKind.Duration) || isType(right, EdmPrimitiveTypeKind.Date) && !isAdd)) {
+ return;
+ }
+ throw new UriParserSemanticException("Incompatible types.",
+ UriParserSemanticException.MessageKeys.UNKNOWN_TYPE, ""); // TODO: better message
+ }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/104ecf43/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
index 3f7f70c..9d29ab2 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
@@ -738,7 +738,8 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
return new BinaryImpl(
(Expression) ctx.vE1.accept(this),
tokenIndex == UriLexer.ADD ? BinaryOperatorKind.ADD : BinaryOperatorKind.SUB,
- (Expression) ctx.vE2.accept(this));
+ (Expression) ctx.vE2.accept(this),
+ null);
}
@Override
@@ -785,7 +786,8 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
return new BinaryImpl(
(Expression) ctx.vE1.accept(this),
BinaryOperatorKind.AND,
- (Expression) ctx.vE2.accept(this));
+ (Expression) ctx.vE2.accept(this),
+ EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Boolean));
}
@Override
@@ -815,7 +817,8 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
return new BinaryImpl(
(Expression) ctx.vE1.accept(this),
kind,
- (Expression) ctx.vE2.accept(this));
+ (Expression) ctx.vE2.accept(this),
+ EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Boolean));
}
@Override
@@ -843,7 +846,8 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
return new BinaryImpl(
(Expression) ctx.vE1.accept(this),
tokenIndex == UriLexer.EQ_ALPHA ? BinaryOperatorKind.EQ : BinaryOperatorKind.NE,
- (Expression) ctx.vE2.accept(this));
+ (Expression) ctx.vE2.accept(this),
+ EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Boolean));
}
@Override
@@ -851,7 +855,8 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
return new BinaryImpl(
(Expression) ctx.vE1.accept(this),
BinaryOperatorKind.HAS,
- (Expression) ctx.vE2.accept(this));
+ (Expression) ctx.vE2.accept(this),
+ EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Boolean));
}
@Override
@@ -875,7 +880,8 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
return new BinaryImpl(
(Expression) ctx.vE1.accept(this),
kind,
- (Expression) ctx.vE2.accept(this));
+ (Expression) ctx.vE2.accept(this),
+ null);
}
@Override
@@ -883,7 +889,8 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
return new BinaryImpl(
(Expression) ctx.vE1.accept(this),
BinaryOperatorKind.OR,
- (Expression) ctx.vE2.accept(this));
+ (Expression) ctx.vE2.accept(this),
+ EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Boolean));
}
@Override
@@ -2294,7 +2301,8 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
public Expression visitAltUnary(@NotNull final UriParserParser.AltUnaryContext ctx) {
return new UnaryImpl(
ctx.unary().NOT() == null ? UnaryOperatorKind.MINUS : UnaryOperatorKind.NOT,
- (Expression) ctx.commonExpr().accept(this));
+ (Expression) ctx.commonExpr().accept(this),
+ null);
}
@Override
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/104ecf43/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
index a40f4ec..4b43cd9 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
@@ -80,6 +80,7 @@ public class UriTokenizer {
GreaterThanOrEqualsOperator,
LessThanOperator,
LessThanOrEqualsOperator,
+ HasOperator,
AddOperator,
SubOperator,
MulOperator,
@@ -140,6 +141,7 @@ public class UriTokenizer {
* The order in which this method is called with different token kinds is important,
* not only for performance reasons but also if tokens can start with the same characters
* (e.g., a qualified name starts with an OData identifier).
+ * The index is advanced to the end of this token if the token is found.
* @param allowedTokenKind the kind of token to expect
* @return <code>true</code> if the token is found; <code>false</code> otherwise
* @see #getText()
@@ -288,6 +290,9 @@ public class UriTokenizer {
case LessThanOrEqualsOperator:
found = nextBinaryOperator("le");
break;
+ case HasOperator:
+ found = nextBinaryOperator("has");
+ break;
case AddOperator:
found = nextBinaryOperator("add");
break;
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/104ecf43/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/BinaryImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/BinaryImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/BinaryImpl.java
index 3f2e8f2..2439bcf 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/BinaryImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/BinaryImpl.java
@@ -18,6 +18,7 @@
*/
package org.apache.olingo.server.core.uri.queryoption.expression;
+import org.apache.olingo.commons.api.edm.EdmType;
import org.apache.olingo.server.api.ODataApplicationException;
import org.apache.olingo.server.api.uri.queryoption.expression.Binary;
import org.apache.olingo.server.api.uri.queryoption.expression.BinaryOperatorKind;
@@ -30,11 +31,14 @@ public class BinaryImpl implements Binary {
private final Expression left;
private final BinaryOperatorKind operator;
private final Expression right;
+ private final EdmType type;
- public BinaryImpl(final Expression left, final BinaryOperatorKind operator, final Expression right) {
+ public BinaryImpl(final Expression left, final BinaryOperatorKind operator, final Expression right,
+ final EdmType type) {
this.left = left;
this.operator = operator;
this.right = right;
+ this.type = type;
}
@Override
@@ -52,6 +56,10 @@ public class BinaryImpl implements Binary {
return right;
}
+ public EdmType getType() {
+ return type;
+ }
+
@Override
public <T> T accept(final ExpressionVisitor<T> visitor) throws ExpressionVisitException, ODataApplicationException {
T left = this.left.accept(visitor);
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/104ecf43/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/MethodImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/MethodImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/MethodImpl.java
index 1c8ce64..0346292 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/MethodImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/MethodImpl.java
@@ -22,12 +22,16 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
+import org.apache.olingo.commons.api.edm.EdmType;
import org.apache.olingo.server.api.ODataApplicationException;
import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
import org.apache.olingo.server.api.uri.queryoption.expression.ExpressionVisitException;
import org.apache.olingo.server.api.uri.queryoption.expression.ExpressionVisitor;
import org.apache.olingo.server.api.uri.queryoption.expression.Method;
import org.apache.olingo.server.api.uri.queryoption.expression.MethodKind;
+import org.apache.olingo.server.api.uri.queryoption.expression.TypeLiteral;
+import org.apache.olingo.server.core.ODataImpl;
public class MethodImpl implements Method {
@@ -44,6 +48,72 @@ public class MethodImpl implements Method {
return method;
}
+ public EdmType getType() {
+ EdmPrimitiveTypeKind kind = null;
+ switch (method) {
+ case CONTAINS:
+ case STARTSWITH:
+ case ENDSWITH:
+ kind = EdmPrimitiveTypeKind.Boolean;
+ break;
+ case LENGTH:
+ case INDEXOF:
+ kind = EdmPrimitiveTypeKind.Int32;
+ break;
+ case SUBSTRING:
+ case TOLOWER:
+ case TOUPPER:
+ case TRIM:
+ case CONCAT:
+ kind = EdmPrimitiveTypeKind.String;
+ break;
+ case YEAR:
+ case MONTH:
+ case DAY:
+ case HOUR:
+ case MINUTE:
+ case SECOND:
+ kind = EdmPrimitiveTypeKind.Int32;
+ break;
+ case FRACTIONALSECONDS:
+ case TOTALSECONDS:
+ kind = EdmPrimitiveTypeKind.Decimal;
+ break;
+ case DATE:
+ kind = EdmPrimitiveTypeKind.Date;
+ break;
+ case TIME:
+ kind = EdmPrimitiveTypeKind.TimeOfDay;
+ break;
+ case TOTALOFFSETMINUTES:
+ kind = EdmPrimitiveTypeKind.Int32;
+ break;
+ case MINDATETIME:
+ case MAXDATETIME:
+ case NOW:
+ kind = EdmPrimitiveTypeKind.DateTimeOffset;
+ break;
+ case ROUND:
+ case FLOOR:
+ case CEILING:
+ kind = EdmPrimitiveTypeKind.Double; // Needs to be refined if Decimal must be distinguished from Double.
+ break;
+ case GEODISTANCE:
+ case GEOLENGTH:
+ kind = EdmPrimitiveTypeKind.Double;
+ break;
+ case GEOINTERSECTS:
+ kind = EdmPrimitiveTypeKind.Boolean;
+ break;
+ case CAST:
+ return ((TypeLiteral) parameters.get(parameters.size() - 1)).getType();
+ case ISOF:
+ kind = EdmPrimitiveTypeKind.Boolean;
+ break;
+ }
+ return new ODataImpl().createPrimitiveTypeInstance(kind);
+ }
+
@Override
public List<Expression> getParameters() {
return parameters == null ?
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/104ecf43/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/UnaryImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/UnaryImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/UnaryImpl.java
index 910997e..86639a6 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/UnaryImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/UnaryImpl.java
@@ -18,6 +18,7 @@
*/
package org.apache.olingo.server.core.uri.queryoption.expression;
+import org.apache.olingo.commons.api.edm.EdmType;
import org.apache.olingo.server.api.ODataApplicationException;
import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
import org.apache.olingo.server.api.uri.queryoption.expression.ExpressionVisitException;
@@ -29,10 +30,12 @@ public class UnaryImpl implements Unary {
private final UnaryOperatorKind operator;
private final Expression expression;
+ private final EdmType type;
- public UnaryImpl(final UnaryOperatorKind operator, final Expression expression) {
+ public UnaryImpl(final UnaryOperatorKind operator, final Expression expression, final EdmType type) {
this.operator = operator;
this.expression = expression;
+ this.type = type;
}
@Override
@@ -45,6 +48,10 @@ public class UnaryImpl implements Unary {
return expression;
}
+ public EdmType getType() {
+ return type;
+ }
+
@Override
public <T> T accept(final ExpressionVisitor<T> visitor) throws ExpressionVisitException, ODataApplicationException {
T operand = expression.accept(visitor);
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/104ecf43/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java
index 58f2a1f..183ff22 100644
--- a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java
+++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java
@@ -21,15 +21,19 @@ package org.apache.olingo.server.core.uri.parser;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import java.util.Locale;
+import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind;
import org.junit.Test;
public class ExpressionParserTest {
+ private final OData odata = OData.newInstance();
+
@Test
public void equality() throws Exception {
Expression expression = parseExpression("5 eq 5");
@@ -37,6 +41,12 @@ public class ExpressionParserTest {
expression = parseExpression("5 ne 5");
assertEquals("{5 NE 5}", expression.toString());
+
+ assertEquals("{1 EQ null}", parseExpression("1 eq null").toString());
+ assertEquals("{null NE 2}", parseExpression("null ne 2").toString());
+ assertEquals("{null EQ null}", parseExpression("null eq null").toString());
+
+ wrongExpression("5 eq '5'");
}
@Test
@@ -52,6 +62,14 @@ public class ExpressionParserTest {
expression = parseExpression("5 le 5");
assertEquals("{5 LE 5}", expression.toString());
+
+ assertEquals("{5 LE 5.1}", parseExpression("5 le 5.1").toString());
+
+ assertEquals("{1 GT null}", parseExpression("1 gt null").toString());
+ assertEquals("{null GE 2}", parseExpression("null ge 2").toString());
+ assertEquals("{null LE null}", parseExpression("null le null").toString());
+
+ wrongExpression("5 gt duration'PT5H'");
}
@Test
@@ -59,8 +77,37 @@ public class ExpressionParserTest {
Expression expression = parseExpression("5 add 5");
assertEquals("{5 ADD 5}", expression.toString());
- expression = parseExpression("5 sub 5");
- assertEquals("{5 SUB 5}", expression.toString());
+ expression = parseExpression("5 sub 5.1");
+ assertEquals("{5 SUB 5.1}", expression.toString());
+
+ expression = parseExpression("2000-02-29 sub 2016-02-29");
+ assertEquals("{2000-02-29 SUB 2016-02-29}", expression.toString());
+
+ expression = parseExpression("2000-02-29T00:00:00Z sub 2016-02-29T01:02:03Z");
+ assertEquals("{2000-02-29T00:00:00Z SUB 2016-02-29T01:02:03Z}", expression.toString());
+
+ expression = parseExpression("duration'PT1H' add duration'PT1M'");
+ assertEquals("{duration'PT1H' ADD duration'PT1M'}", expression.toString());
+
+ expression = parseExpression("2016-01-01 add duration'P60D'");
+ assertEquals("{2016-01-01 ADD duration'P60D'}", expression.toString());
+
+ expression = parseExpression("2000-02-29T00:00:00Z add duration'PT12H'");
+ assertEquals("{2000-02-29T00:00:00Z ADD duration'PT12H'}", expression.toString());
+
+ assertEquals("{1 ADD null}", parseExpression("1 add null").toString());
+ assertEquals("{null ADD 2}", parseExpression("null add 2").toString());
+ assertEquals("{null SUB null}", parseExpression("null sub null").toString());
+
+ wrongExpression("1 add '2'");
+ wrongExpression("'1' add 2");
+ wrongExpression("1 add 2000-02-29");
+ wrongExpression("11:12:13 sub 2000-02-29T11:12:13Z");
+ wrongExpression("2000-02-29 add 2016-02-29");
+ wrongExpression("2000-02-29T00:00:00Z add 2016-02-29T01:02:03Z");
+ wrongExpression("2000-02-29T00:00:00Z add 1");
+ wrongExpression("2000-02-29 sub 1");
+ wrongExpression("duration'P7D' add 2000-02-29");
}
@Test
@@ -73,6 +120,8 @@ public class ExpressionParserTest {
expression = parseExpression("5 mod 5");
assertEquals("{5 MOD 5}", expression.toString());
+
+ wrongExpression("1 mod '2'");
}
@Test
@@ -81,9 +130,12 @@ public class ExpressionParserTest {
assertEquals("{MINUS 5}", expression.toString());
assertEquals("{MINUS -1}", parseExpression("--1").toString());
+ assertEquals("{MINUS duration'PT1M'}", parseExpression("-duration'PT1M'").toString());
+
+ expression = parseExpression("not false");
+ assertEquals("{NOT false}", expression.toString());
- expression = parseExpression("not 5");
- assertEquals("{NOT 5}", expression.toString());
+ wrongExpression("-11:12:13");
}
@Test
@@ -111,6 +163,8 @@ public class ExpressionParserTest {
expression = parseMethod(TokenKind.MindatetimeMethod);
assertEquals("{mindatetime []}", expression.toString());
+
+ wrongExpression("now(1)");
}
@Test
@@ -148,16 +202,79 @@ public class ExpressionParserTest {
expression = parseMethod(TokenKind.SecondMethod, dateTimeOffsetValue);
assertEquals("{second [" + dateTimeOffsetValue + "]}", expression.toString());
+
+ expression = parseMethod(TokenKind.DateMethod, dateTimeOffsetValue);
+ assertEquals("{date [" + dateTimeOffsetValue + "]}", expression.toString());
+
+ expression = parseMethod(TokenKind.TotalsecondsMethod, "duration'PT1H'");
+ assertEquals("{totalseconds [duration'PT1H']}", expression.toString());
+
+ expression = parseMethod(TokenKind.RoundMethod, "3.141592653589793");
+ assertEquals("{round [3.141592653589793]}", expression.toString());
+
+ assertEquals("{hour [null]}", parseMethod(TokenKind.HourMethod, new String[] { null }).toString());
+
+ wrongExpression("trim()");
+ wrongExpression("trim(1)");
+ wrongExpression("ceiling('1.2')");
+ }
+
+ @Test
+ public void twoParameterMethods() throws Exception {
+ Expression expression = parseMethod(TokenKind.ContainsMethod, "'a'", "'b'");
+ assertEquals("{contains ['a', 'b']}", expression.toString());
+
+ expression = parseMethod(TokenKind.EndswithMethod, "'a'", "'b'");
+ assertEquals("{endswith ['a', 'b']}", expression.toString());
+
+ expression = parseMethod(TokenKind.StartswithMethod, "'a'", "'b'");
+ assertEquals("{startswith ['a', 'b']}", expression.toString());
+
+ expression = parseMethod(TokenKind.IndexofMethod, "'a'", "'b'");
+ assertEquals("{indexof ['a', 'b']}", expression.toString());
+
+ expression = parseMethod(TokenKind.ConcatMethod, "'a'", "'b'");
+ assertEquals("{concat ['a', 'b']}", expression.toString());
+
+ // TODO: Geo methods.
+// expression = parseMethod(TokenKind.GeoDistanceMethod,
+// "geography'SRID=0;Point(1.2 3.4)'", "geography'SRID=0;Point(5.6 7.8)'");
+// assertEquals("{geo.distance [geography'SRID=0;Point(1.2 3.4)', geography'SRID=0;Point(5.6 7.8)']}",
+// expression.toString());
+//
+// expression = parseMethod(TokenKind.GeoIntersectsMethod);
+// assertEquals("{geo.intersects []}", expression.toString());
+
+ assertEquals("{startswith [null, 'b']}", parseMethod(TokenKind.StartswithMethod, null, "'b'").toString());
+ assertEquals("{indexof ['a', null]}", parseMethod(TokenKind.IndexofMethod, "'a'", null).toString());
+
+ wrongExpression("concat('a')");
+ wrongExpression("endswith('a',1)");
+}
+
+ @Test
+ public void variableParameterNumberMethods() throws Exception {
+ Expression expression = parseMethod(TokenKind.SubstringMethod, "'abc'", "1", "2");
+ assertEquals("{substring ['abc', 1, 2]}", expression.toString());
+ expression = parseMethod(TokenKind.SubstringMethod, "'abc'", "1");
+ assertEquals("{substring ['abc', 1]}", expression.toString());
+
+ wrongExpression("substring('abc')");
+ wrongExpression("substring('abc',1,2,3)");
+ wrongExpression("substring(1,2)");
}
private Expression parseMethod(TokenKind kind, String... parameters) throws UriParserException {
String expressionString = kind.name().substring(0, kind.name().indexOf("Method"))
.toLowerCase(Locale.ROOT).replace("geo", "geo.") + '(';
- for (int i = 0; i < parameters.length; i++) {
- if (i > 0) {
+ boolean first = true;
+ for (final String parameter : parameters) {
+ if (first) {
+ first = false;
+ } else {
expressionString += ',';
}
- expressionString += parameters[i];
+ expressionString += parameter;
}
expressionString += ')';
@@ -168,9 +285,18 @@ public class ExpressionParserTest {
private Expression parseExpression(final String expressionString) throws UriParserException {
UriTokenizer tokenizer = new UriTokenizer(expressionString);
- Expression expression = new ExpressionParser().parse(tokenizer);
+ Expression expression = new ExpressionParser(null, odata).parse(tokenizer);
assertNotNull(expression);
assertTrue(tokenizer.next(TokenKind.EOF));
return expression;
}
+
+ private void wrongExpression(final String expressionString) {
+ try {
+ new ExpressionParser(null, odata).parse(new UriTokenizer(expressionString));
+ fail("Expected exception not thrown.");
+ } catch (final UriParserException e) {
+ assertNotNull(e);
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/104ecf43/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java
index b5614ad..1b2d508 100644
--- a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java
+++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java
@@ -412,7 +412,7 @@ public class UriTokenizerTest {
assertTrue(tokenizer.next(TokenKind.IntegerValue));
assertTrue(tokenizer.next(TokenKind.EOF));
- tokenizer = new UriTokenizer("1 gt 2 or 3 ge 4 or 5 lt 6");
+ tokenizer = new UriTokenizer("1 gt 2 or 3 ge 4 or 5 lt 6 or 7 has namespace.name'flag1,flag2'");
assertTrue(tokenizer.next(TokenKind.IntegerValue));
assertTrue(tokenizer.next(TokenKind.GreaterThanOperator));
assertTrue(tokenizer.next(TokenKind.IntegerValue));
@@ -424,6 +424,10 @@ public class UriTokenizerTest {
assertTrue(tokenizer.next(TokenKind.IntegerValue));
assertTrue(tokenizer.next(TokenKind.LessThanOperator));
assertTrue(tokenizer.next(TokenKind.IntegerValue));
+ assertTrue(tokenizer.next(TokenKind.OrOperator));
+ assertTrue(tokenizer.next(TokenKind.IntegerValue));
+ assertTrue(tokenizer.next(TokenKind.HasOperator));
+ assertTrue(tokenizer.next(TokenKind.EnumValue));
assertTrue(tokenizer.next(TokenKind.EOF));
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/104ecf43/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/queryoption/expression/ExpressionTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/queryoption/expression/ExpressionTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/queryoption/expression/ExpressionTest.java
index ec5ce6e..864b17a 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/queryoption/expression/ExpressionTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/queryoption/expression/ExpressionTest.java
@@ -31,14 +31,13 @@ import org.apache.olingo.commons.api.edm.EdmAction;
import org.apache.olingo.commons.api.edm.EdmEntityType;
import org.apache.olingo.commons.api.edm.EdmEnumType;
import org.apache.olingo.commons.api.edm.EdmFunction;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
import org.apache.olingo.server.api.OData;
-import org.apache.olingo.server.api.ODataApplicationException;
import org.apache.olingo.server.api.edmx.EdmxReference;
import org.apache.olingo.server.api.uri.UriInfoKind;
import org.apache.olingo.server.api.uri.UriInfoResource;
import org.apache.olingo.server.api.uri.queryoption.expression.BinaryOperatorKind;
import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
-import org.apache.olingo.server.api.uri.queryoption.expression.ExpressionVisitException;
import org.apache.olingo.server.api.uri.queryoption.expression.MethodKind;
import org.apache.olingo.server.api.uri.queryoption.expression.UnaryOperatorKind;
import org.apache.olingo.server.core.uri.UriInfoImpl;
@@ -53,7 +52,8 @@ import org.apache.olingo.server.tecsvc.provider.FunctionProvider;
import org.junit.Test;
public class ExpressionTest {
- private static final Edm edm = OData.newInstance().createServiceMetadata(
+ private static final OData odata = OData.newInstance();
+ private static final Edm edm = odata.createServiceMetadata(
new EdmTechProvider(), Collections.<EdmxReference> emptyList()).getEdm();
@Test
@@ -69,7 +69,7 @@ public class ExpressionTest {
}
@Test
- public void aliasExpression() throws ExpressionVisitException, ODataApplicationException {
+ public void aliasExpression() throws Exception {
AliasImpl expression = new AliasImpl("Test");
assertEquals("Test", expression.getParameterName());
@@ -79,47 +79,50 @@ public class ExpressionTest {
}
@Test
- public void binaryExpression() throws ExpressionVisitException, ODataApplicationException {
- Expression expressionLeft = new LiteralImpl("A", null);
- Expression expressionRight = new LiteralImpl("B", null);
+ public void binaryExpression() throws Exception {
+ Expression expressionLeft = new LiteralImpl("2", odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Byte));
+ Expression expressionRight = new LiteralImpl("-1", odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.SByte));
- BinaryImpl expression = new BinaryImpl(expressionLeft, BinaryOperatorKind.SUB, expressionRight);
+ BinaryImpl expression = new BinaryImpl(expressionLeft, BinaryOperatorKind.SUB, expressionRight,
+ odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Byte));
assertEquals(expressionLeft, expression.getLeftOperand());
assertEquals(expressionRight, expression.getRightOperand());
assertEquals(BinaryOperatorKind.SUB, expression.getOperator());
+ assertEquals(odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Byte), expression.getType());
String output = expression.accept(new FilterTreeToText());
- assertEquals("<<A> sub <B>>", output);
+ assertEquals("<<2> sub <-1>>", output);
}
@Test
- public void enumerationExpression() throws ExpressionVisitException, ODataApplicationException {
+ public void enumerationExpression() throws Exception {
EdmEnumType type = edm.getEnumType(EnumTypeProvider.nameENString);
assertNotNull(type);
- EnumerationImpl expression = new EnumerationImpl(type, Arrays.asList("A", "B"));
+ EnumerationImpl expression = new EnumerationImpl(type, Arrays.asList("String1", "String2"));
assertEquals(type, expression.getType());
- assertEquals("A", expression.getValues().get(0));
- assertEquals("B", expression.getValues().get(1));
- assertEquals("<olingo.odata.test1.ENString<A,B>>", expression.accept(new FilterTreeToText()));
+ assertEquals("String1", expression.getValues().get(0));
+ assertEquals("String2", expression.getValues().get(1));
+ assertEquals("<olingo.odata.test1.ENString<String1,String2>>", expression.accept(new FilterTreeToText()));
}
@Test
- public void lambdaRefExpression() throws ExpressionVisitException, ODataApplicationException {
+ public void lambdaRefExpression() throws Exception {
LambdaRefImpl expression = new LambdaRefImpl("A");
assertEquals("A", expression.getVariableName());
assertEquals("<A>", expression.accept(new FilterTreeToText()));
}
@Test
- public void literalExpression() throws ExpressionVisitException, ODataApplicationException {
- LiteralImpl expression = new LiteralImpl("A", null);
- assertEquals("A", expression.getText());
- assertEquals("<A>", expression.accept(new FilterTreeToText()));
+ public void literalExpression() throws Exception {
+ LiteralImpl expression = new LiteralImpl("'A'", odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.String));
+ assertEquals("'A'", expression.getText());
+ assertEquals("<'A'>", expression.accept(new FilterTreeToText()));
+ assertEquals(odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.String), expression.getType());
}
@Test
- public void memberExpression() throws ExpressionVisitException, ODataApplicationException {
+ public void memberExpression() throws Exception {
EdmEntityType entityType = edm.getEntityType(EntityTypeProvider.nameETKeyNav);
// UriResourceImpl
@@ -189,20 +192,21 @@ public class ExpressionTest {
}
@Test
- public void methodCallExpression() throws ExpressionVisitException, ODataApplicationException {
- Expression p0 = new LiteralImpl("A", null);
- Expression p1 = new LiteralImpl("B", null);
+ public void methodCallExpression() throws Exception {
+ Expression p0 = new LiteralImpl("'A'", odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.String));
+ Expression p1 = new LiteralImpl("'B'", odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.String));
MethodImpl expression = new MethodImpl(MethodKind.CONCAT, Arrays.asList(p0, p1));
assertEquals(MethodKind.CONCAT, expression.getMethod());
- assertEquals("<concat(<A>,<B>)>", expression.accept(new FilterTreeToText()));
+ assertEquals("<concat(<'A'>,<'B'>)>", expression.accept(new FilterTreeToText()));
+ assertEquals(odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.String), expression.getType());
assertEquals(p0, expression.getParameters().get(0));
assertEquals(p1, expression.getParameters().get(1));
}
@Test
- public void typeLiteralExpression() throws ExpressionVisitException, ODataApplicationException {
+ public void typeLiteralExpression() throws Exception {
EdmEntityType entityBaseType = edm.getEntityType(EntityTypeProvider.nameETBaseTwoKeyNav);
TypeLiteralImpl expression = new TypeLiteralImpl(entityBaseType);
@@ -211,13 +215,15 @@ public class ExpressionTest {
}
@Test
- public void unaryExpression() throws ExpressionVisitException, ODataApplicationException {
- Expression operand = new LiteralImpl("A", null);
- UnaryImpl expression = new UnaryImpl(UnaryOperatorKind.MINUS, operand);
+ public void unaryExpression() throws Exception {
+ Expression operand = new LiteralImpl("1.2", odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Decimal));
+ UnaryImpl expression = new UnaryImpl(UnaryOperatorKind.MINUS, operand,
+ odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Decimal));
assertEquals(UnaryOperatorKind.MINUS, expression.getOperator());
assertEquals(operand, expression.getOperand());
+ assertEquals(odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Decimal), expression.getType());
- assertEquals("<- <A>>", expression.accept(new FilterTreeToText()));
+ assertEquals("<- <1.2>>", expression.accept(new FilterTreeToText()));
}
}
[07/30] olingo-odata4 git commit: Merge remote-tracking branch
'origin/OLINGO-834_RefactorUriParsing' into OLINGO-834_Filter_Parser
Posted by ch...@apache.org.
Merge remote-tracking branch 'origin/OLINGO-834_RefactorUriParsing' into OLINGO-834_Filter_Parser
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/ef19c9be
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/ef19c9be
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/ef19c9be
Branch: refs/heads/master
Commit: ef19c9be1f6714b7c50aea3ff5623bb2d5857653
Parents: 7b23ad7 7bc932a
Author: Christian Amend <ch...@sap.com>
Authored: Thu Dec 10 15:34:39 2015 +0100
Committer: Christian Amend <ch...@sap.com>
Committed: Thu Dec 10 15:34:39 2015 +0100
----------------------------------------------------------------------
.../olingo/fit/tecsvc/client/BasicITCase.java | 2 +-
.../core/edm/primitivetype/EdmBinary.java | 12 +-
.../edm/provider/EdmActionImportImplTest.java | 2 +-
.../core/edm/provider/EdmProviderImplTest.java | 4 +-
.../core/edm/provider/EdmSchemaImplTest.java | 1 +
.../apache/olingo/server/core/ErrorHandler.java | 8 +-
.../olingo/server/core/ServiceDispatcher.java | 4 +-
.../olingo/server/core/ServiceRequest.java | 6 +-
.../apache/olingo/server/core/ODataHandler.java | 4 +-
.../olingo/server/core/uri/UriHelperImpl.java | 9 +-
.../uri/UriResourceNavigationPropertyImpl.java | 5 +-
.../core/uri/UriResourceWithKeysImpl.java | 3 +-
.../olingo/server/core/uri/parser/Parser.java | 202 +++---
.../core/uri/parser/ResourcePathParser.java | 692 +++++++++++++++++++
.../core/uri/parser/UriParseTreeVisitor.java | 2 +-
.../server/core/uri/parser/UriTokenizer.java | 592 ++++++++++++++++
.../server/core/uri/validator/UriValidator.java | 74 +-
.../core/uri/parser/UriTokenizerTest.java | 369 ++++++++++
.../uri/parser/search/SearchTokenizerTest.java | 1 -
.../server/tecsvc/data/DataProviderTest.java | 4 +-
.../server/core/PreconditionsValidatorTest.java | 25 +-
.../serializer/utils/ContextURLHelperTest.java | 4 +-
.../olingo/server/core/uri/UriHelperTest.java | 4 +-
.../server/core/uri/UriResourceImplTest.java | 14 +-
.../core/uri/antlr/TestFullResourcePath.java | 154 +++--
.../core/uri/antlr/TestUriParserImpl.java | 15 +-
.../server/core/uri/parser/ParserTest.java | 4 +-
.../core/uri/testutil/FilterValidator.java | 62 +-
.../core/uri/testutil/ParserWithLogging.java | 5 +-
.../core/uri/testutil/ResourceValidator.java | 13 +-
.../core/uri/testutil/TestUriValidator.java | 14 +-
.../core/uri/validator/UriValidatorTest.java | 17 +-
32 files changed, 1973 insertions(+), 354 deletions(-)
----------------------------------------------------------------------
[23/30] olingo-odata4 git commit: [OLINGO-834] $expand parser in Java
+ clean-up
Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
deleted file mode 100644
index 1bab218..0000000
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
+++ /dev/null
@@ -1,2313 +0,0 @@
-/*
- * 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.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import org.antlr.v4.runtime.misc.NotNull;
-import org.antlr.v4.runtime.misc.ParseCancellationException;
-import org.antlr.v4.runtime.tree.ParseTree;
-import org.apache.olingo.commons.api.edm.Edm;
-import org.apache.olingo.commons.api.edm.EdmAction;
-import org.apache.olingo.commons.api.edm.EdmActionImport;
-import org.apache.olingo.commons.api.edm.EdmComplexType;
-import org.apache.olingo.commons.api.edm.EdmElement;
-import org.apache.olingo.commons.api.edm.EdmEntityContainer;
-import org.apache.olingo.commons.api.edm.EdmEntitySet;
-import org.apache.olingo.commons.api.edm.EdmEntityType;
-import org.apache.olingo.commons.api.edm.EdmEnumType;
-import org.apache.olingo.commons.api.edm.EdmFunction;
-import org.apache.olingo.commons.api.edm.EdmFunctionImport;
-import org.apache.olingo.commons.api.edm.EdmNavigationProperty;
-import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
-import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
-import org.apache.olingo.commons.api.edm.EdmProperty;
-import org.apache.olingo.commons.api.edm.EdmReturnType;
-import org.apache.olingo.commons.api.edm.EdmSingleton;
-import org.apache.olingo.commons.api.edm.EdmStructuredType;
-import org.apache.olingo.commons.api.edm.EdmType;
-import org.apache.olingo.commons.api.edm.FullQualifiedName;
-import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
-import org.apache.olingo.commons.api.ex.ODataRuntimeException;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory;
-import org.apache.olingo.server.api.uri.UriInfoKind;
-import org.apache.olingo.server.api.uri.UriInfoResource;
-import org.apache.olingo.server.api.uri.UriParameter;
-import org.apache.olingo.server.api.uri.UriResource;
-import org.apache.olingo.server.api.uri.UriResourceEntitySet;
-import org.apache.olingo.server.api.uri.UriResourceFunction;
-import org.apache.olingo.server.api.uri.UriResourceNavigation;
-import org.apache.olingo.server.api.uri.UriResourcePartTyped;
-import org.apache.olingo.server.api.uri.UriResourceRoot;
-import org.apache.olingo.server.api.uri.queryoption.SelectItem;
-import org.apache.olingo.server.api.uri.queryoption.expression.BinaryOperatorKind;
-import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
-import org.apache.olingo.server.api.uri.queryoption.expression.MethodKind;
-import org.apache.olingo.server.api.uri.queryoption.expression.UnaryOperatorKind;
-import org.apache.olingo.server.core.uri.UriInfoImpl;
-import org.apache.olingo.server.core.uri.UriParameterImpl;
-import org.apache.olingo.server.core.uri.UriResourceActionImpl;
-import org.apache.olingo.server.core.uri.UriResourceComplexPropertyImpl;
-import org.apache.olingo.server.core.uri.UriResourceCountImpl;
-import org.apache.olingo.server.core.uri.UriResourceEntitySetImpl;
-import org.apache.olingo.server.core.uri.UriResourceFunctionImpl;
-import org.apache.olingo.server.core.uri.UriResourceImpl;
-import org.apache.olingo.server.core.uri.UriResourceItImpl;
-import org.apache.olingo.server.core.uri.UriResourceLambdaAllImpl;
-import org.apache.olingo.server.core.uri.UriResourceLambdaAnyImpl;
-import org.apache.olingo.server.core.uri.UriResourceLambdaVarImpl;
-import org.apache.olingo.server.core.uri.UriResourceNavigationPropertyImpl;
-import org.apache.olingo.server.core.uri.UriResourcePrimitivePropertyImpl;
-import org.apache.olingo.server.core.uri.UriResourceRefImpl;
-import org.apache.olingo.server.core.uri.UriResourceRootImpl;
-import org.apache.olingo.server.core.uri.UriResourceSingletonImpl;
-import org.apache.olingo.server.core.uri.UriResourceStartingTypeFilterImpl;
-import org.apache.olingo.server.core.uri.UriResourceTypedImpl;
-import org.apache.olingo.server.core.uri.UriResourceValueImpl;
-import org.apache.olingo.server.core.uri.UriResourceWithKeysImpl;
-import org.apache.olingo.server.core.uri.antlr.UriLexer;
-import org.apache.olingo.server.core.uri.antlr.UriParserBaseVisitor;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.AllEOFContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.AllExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltAddContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltAllContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltAndContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltAnyContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltComparismContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltEqualityContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltHasContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltMultContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltOrContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.AnyExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.ArrayOrObjectContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.BinaryLiteralContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.BooleanNonCaseLiteralContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.CastExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.CeilingMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.ConcatMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.ConstSegmentContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.ContainsMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.DateLiteralContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.DateMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.DatetimeoffsetLiteralContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.DayMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.DecimalLiteralContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.DurationLiteralContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.EndsWithMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.EntityEOFContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.EnumLiteralContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandCountOptionContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandItemContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandItemsContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandItemsEOFContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandOptionContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandPathContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandPathExtensionContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandRefOptionContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.FilterContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.FilterExpressionEOFContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.FloorMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.FractionalsecondsMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.GeoDistanceMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.GeoIntersectsMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.GeoLengthMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.GuidLiteralContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.HourMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.IndexOfMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.InlinecountContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.IntLiteralContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.IsofExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.LengthMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.LevelsContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.MaxDateTimeMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.MemberExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.MetadataEOFContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.MinDateTimeMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.MinuteMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.MonthMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.NameValueOptListContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.NameValuePairContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.NamespaceContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.NaninfinityLiteralContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.NowMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.NullruleLiteralContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.OrderByContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.OrderByEOFContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.OrderByItemContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.OrderListContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.PathSegmentContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.PathSegmentsContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.PrimitiveLiteralContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.QueryOptionContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.QueryOptionsContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.RootExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.RoundMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.SearchSpecialTokenContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.SecondMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.SelectContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.SelectEOFContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.SelectItemContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.SelectSegmentContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.SkipContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.SkiptokenContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.StartsWithMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.StringLiteralContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.SubstringMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.TimeMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.TimeofdayLiteralContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.ToLowerMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.ToUpperMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.TopContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.TotalOffsetMinutesMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.TotalsecondsMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.TrimMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.YearMethodCallExprContext;
-import org.apache.olingo.server.core.uri.parser.UriParserSemanticException.MessageKeys;
-import org.apache.olingo.server.core.uri.queryoption.CountOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.ExpandItemImpl;
-import org.apache.olingo.server.core.uri.queryoption.ExpandOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.FilterOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.LevelsOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.OrderByItemImpl;
-import org.apache.olingo.server.core.uri.queryoption.OrderByOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.QueryOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.SelectItemImpl;
-import org.apache.olingo.server.core.uri.queryoption.SelectOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.SkipOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.SkipTokenOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.SystemQueryOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.TopOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.expression.AliasImpl;
-import org.apache.olingo.server.core.uri.queryoption.expression.BinaryImpl;
-import org.apache.olingo.server.core.uri.queryoption.expression.EnumerationImpl;
-import org.apache.olingo.server.core.uri.queryoption.expression.LiteralImpl;
-import org.apache.olingo.server.core.uri.queryoption.expression.MemberImpl;
-import org.apache.olingo.server.core.uri.queryoption.expression.MethodImpl;
-import org.apache.olingo.server.core.uri.queryoption.expression.TypeLiteralImpl;
-import org.apache.olingo.server.core.uri.queryoption.expression.UnaryImpl;
-
-/**
- * Converts the URI parse tree as generated by ANTLR into an internal representation
- * suitable to give to an application.
- * While converting the tree is only validated against the EDM if necessary.
- * <br>
- * Attention:
- * <ul>
- * <li>This UriVisitor is at somes point more lax than the original ABNF.</li>
- * <li>It is more tolerable against additional white spaces.</li>
- * </ul>
- * Currently not supported are
- * <ul>
- * <li>parsing the context of $metadata</li>
- * <li>parsing $search</li>
- * </ul>
- */
-public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
-
- public UriContext context = null;
-
- public Edm edm;
-
- public EdmEntityContainer edmEntityContainer;
-
- // --- class ---
- public UriParseTreeVisitor(final Edm edm, final UriContext context) {
- this.edm = edm;
- this.context = context;
- edmEntityContainer = edm.getEntityContainer();
- }
-
- @Override
- protected Object aggregateResult(final Object aggregate, final Object nextResult) {
- if (aggregate != null) {
- return aggregate;
- } else {
- return nextResult;
- }
- }
-
- private FullQualifiedName getFullNameFromContext(final NamespaceContext vNS, final String odi) {
- String namespace = vNS.getText();
- namespace = namespace.substring(0, namespace.length() - 1); // vNS contains a trailing point that has to be removed
- return new FullQualifiedName(namespace, odi);
- }
-
- private UriContext.LambdaVariable getLambdaVar(final String odi) {
- for (UriContext.LambdaVariable item : context.allowedLambdaVariables) {
- if (item.name.equals(odi)) {
- return item;
- }
- }
- return null;
- }
-
- public UriResourceTypedImpl readResourcePathSegment(final PathSegmentContext ctx) {
-
- final boolean checkFirst =
- context.contextUriInfo.getLastResourcePart() == null
- || context.contextUriInfo.getLastResourcePart() instanceof UriResourceRootImpl;
-
- String odi = ctx.vODI.getText();
-
- boolean searchInContainer = true;
- // validate if context type and according property is available
- // otherwise search in container for first element
- if (checkFirst && ctx.vNS == null && !context.contextTypes.isEmpty()) {
- EdmType sourceType = context.contextTypes.peek();
- if (sourceType instanceof EdmStructuredType) {
- EdmStructuredType str = (EdmStructuredType) sourceType;
- EdmElement property = str.getProperty(odi);
- if (property != null) {
- searchInContainer = false;
- }
- }
- }
-
- if (searchInContainer) {
- final List<UriResource> parts = context.contextUriInfo.getUriResourceParts();
- // check EntitySet
- EdmEntitySet edmEntitySet = edmEntityContainer.getEntitySet(odi);
- if (edmEntitySet != null
- && (parts.isEmpty() || !(parts.get(0) instanceof UriResourcePartTyped)
- || parts.get(0) instanceof UriResourceRoot)) {
- ensureNamespaceIsNull(ctx.vNS);
- context.contextUriInfo.addResourcePart(
- new UriResourceEntitySetImpl(edmEntitySet));
- return null;
- }
-
- // check Singleton
- EdmSingleton edmSingleton = edmEntityContainer.getSingleton(odi);
- if (edmSingleton != null
- && (parts.isEmpty() || !(parts.get(0) instanceof UriResourcePartTyped)
- || parts.get(0) instanceof UriResourceRoot)) {
- ensureNamespaceIsNull(ctx.vNS);
- context.contextUriInfo.addResourcePart(
- new UriResourceSingletonImpl(edmSingleton));
- return null;
- }
-
- // check ActionImport
- EdmActionImport edmActionImport = edmEntityContainer.getActionImport(odi);
- if (edmActionImport != null
- && (parts.isEmpty() || !(parts.get(0) instanceof UriResourcePartTyped)
- || parts.get(0) instanceof UriResourceRoot)) {
- ensureNamespaceIsNull(ctx.vNS);
- context.contextUriInfo.addResourcePart(
- new UriResourceActionImpl(edmActionImport));
- return null;
- }
-
- // check FunctionImport
- EdmFunctionImport edmFunctionImport = edmEntityContainer.getFunctionImport(odi);
-
- if(edmFunctionImport != null && context.contextReadingQueryPart) {
- throw wrap(new UriParserSemanticException("Function Imports are not allowed in $filter or $orderby",
- UriParserSemanticException.MessageKeys.FUNCTION_IMPORT_NOT_ALLOWED, odi));
- }
-
- if (edmFunctionImport != null
- && (parts.isEmpty() || !(parts.get(0) instanceof UriResourcePartTyped)
- || parts.get(0) instanceof UriResourceRoot)) {
-
- // read the URI parameters
- if (ctx.vlNVO.isEmpty()) {
- throw wrap(new UriParserSyntaxException(
- "Function imports must have a (possibly empty) parameter list written in parentheses",
- UriParserSyntaxException.MessageKeys.SYNTAX));
- }
- context.contextReadingFunctionParameters = true;
- @SuppressWarnings("unchecked")
- List<UriParameter> parameters = (List<UriParameter>) ctx.vlNVO.get(0).accept(this);
- context.contextReadingFunctionParameters = false;
-
- // mark parameters as consumed
- ctx.vlNVO.remove(0);
-
- // collect parameter names
- List<String> names = new ArrayList<String>();
- for (UriParameter item : parameters) {
- names.add(item.getName());
- }
-
- // get function from function import
- EdmFunction function = edmFunctionImport.getUnboundFunction(names);
- if (function == null) {
- StringBuilder tmp = new StringBuilder();
- for (String name : names) {
- tmp.append((tmp.length() != 0 ? "," : "")).append(name);
- }
- throw wrap(new UriParserSemanticException("Function of functionimport '" + edmFunctionImport.getName()
- + "' with parameters [" + tmp.toString() + "] not found",
- UriParserSemanticException.MessageKeys.FUNCTION_NOT_FOUND, edmFunctionImport.getName(), tmp.toString()));
- }
-
- ensureNamespaceIsNull(ctx.vNS);
- UriResourceFunctionImpl uriResource = new UriResourceFunctionImpl(edmFunctionImport,
- edmFunctionImport.getUnboundFunction(names),
- parameters);
- context.contextUriInfo.addResourcePart(uriResource);
- return null;
- }
- }
-
- EdmType sourceType;
- boolean sourceIsCollection = false;
- final UriResource lastResourcePart = context.contextUriInfo.getLastResourcePart();
-
- if (lastResourcePart == null) {
- if (context.contextTypes.isEmpty()) {
- if (checkFirst && ctx.vNS == null) {
- throw wrap(new UriParserSemanticException(
- "Cannot find EntitySet, Singleton, ActionImport or FunctionImport with name '" + odi + "'.",
- UriParserSemanticException.MessageKeys.RESOURCE_NOT_FOUND, odi));
- }
- throw wrap(new UriParserSemanticException(
- "Resource part '" + odi + "' can only applied on typed resource parts",
- UriParserSemanticException.MessageKeys.RESOURCE_PART_ONLY_FOR_TYPED_PARTS, odi));
- }
- sourceType = context.contextTypes.peek();
- sourceIsCollection = context.isCollection;
- } else if (lastResourcePart instanceof UriResourcePartTyped) {
- sourceType = ParserHelper.getTypeInformation((UriResourcePartTyped) lastResourcePart);
- sourceIsCollection = ((UriResourcePartTyped) lastResourcePart).isCollection();
- } else {
- throw wrap(new UriParserSemanticException(
- "Resource part '" + odi + "' can only be applied on typed resource parts.",
- UriParserSemanticException.MessageKeys.RESOURCE_PART_ONLY_FOR_TYPED_PARTS, odi));
- }
-
- if (ctx.vNS == null) { // without namespace
-
- // first check for lambda variable because a newly add property should not shadow a long used lambda variable
- UriContext.LambdaVariable lVar = getLambdaVar(odi);
- if (lVar != null) {
- UriResourceLambdaVarImpl lambdaResource = new UriResourceLambdaVarImpl(lVar.name, lVar.type);
- context.contextUriInfo.addResourcePart(lambdaResource);
- return null;
- }
-
- if (!(sourceType instanceof EdmStructuredType)) {
- throw wrap(new UriParserSemanticException(
- "Cannot parse '" + odi + "'; previous path segment is not a structural type.",
- UriParserSemanticException.MessageKeys.RESOURCE_PART_MUST_BE_PRECEDED_BY_STRUCTURAL_TYPE, odi));
- }
-
- if ((ctx.depth() <= 2 // path evaluation for the resource path
- || lastResourcePart instanceof UriResourceTypedImpl
- || lastResourcePart instanceof UriResourceNavigationPropertyImpl)
- && sourceIsCollection) {
- throw wrap(new UriParserSemanticException("Property '" + odi + "' is not allowed after collection.",
- UriParserSemanticException.MessageKeys.PROPERTY_AFTER_COLLECTION, odi));
- }
-
- EdmStructuredType structType = (EdmStructuredType) sourceType;
-
- EdmElement property = structType.getProperty(odi);
- if (property == null) {
- throw wrap(new UriParserSemanticException("Property '" + odi + "' not found in type '"
- + structType.getFullQualifiedName().getFullQualifiedNameAsString() + "'",
- ctx.depth() > 2 ? // path evaluation inside an expression or for the resource path?
- UriParserSemanticException.MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE
- : UriParserSemanticException.MessageKeys.PROPERTY_NOT_IN_TYPE,
- structType.getFullQualifiedName().getFullQualifiedNameAsString(), odi));
- }
-
- if (property instanceof EdmProperty) {
- if (((EdmProperty) property).isPrimitive()
- || property.getType().getKind() == EdmTypeKind.ENUM
- || property.getType().getKind() == EdmTypeKind.DEFINITION) {
- // create simple property
- UriResourcePrimitivePropertyImpl simpleResource =
- new UriResourcePrimitivePropertyImpl((EdmProperty) property);
- context.contextUriInfo.addResourcePart(simpleResource);
- return null;
- } else {
- // create complex property
- UriResourceComplexPropertyImpl complexResource = new UriResourceComplexPropertyImpl((EdmProperty) property);
- context.contextUriInfo.addResourcePart(complexResource);
- return null;
- }
- } else if (property instanceof EdmNavigationProperty) {
- // create navigation property
- if (context.contextVisitExpandResourcePath && ctx.vlNVO.size() > 0) {
- throw wrap(new UriParserSemanticException(
- "Navigation properties in expand system query options must not be followed by a key.",
- UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED));
- }
-
- UriResourceNavigationPropertyImpl navigationResource =
- new UriResourceNavigationPropertyImpl((EdmNavigationProperty) property);
- context.contextUriInfo.addResourcePart(navigationResource);
- return null;
- } else {
- throw wrap(new UriParserSemanticException("Unkown type for property '" + property + "'",
- UriParserSemanticException.MessageKeys.UNKNOWN_PROPERTY_TYPE, property.getName()));
- }
-
- } else { // with namespace
-
- FullQualifiedName fullFilterName = getFullNameFromContext(ctx.vNS, odi);
-
- // EdmType lastType = getLastType(lastTyped);
- if (sourceType instanceof EdmEntityType) {
-
- EdmEntityType filterEntityType = edm.getEntityType(fullFilterName);
- if (filterEntityType != null) {
- // is entity type cast
- if (!(filterEntityType.compatibleTo(sourceType))) {
- throw wrap(new UriParserSemanticException(
- "Entity typefilter not compatible to previous path segment: " + fullFilterName.toString(),
- UriParserSemanticException.MessageKeys.INCOMPATIBLE_TYPE_FILTER, fullFilterName.toString()));
- }
-
- if (lastResourcePart == null) {
- // this may be the case if a member expression within a filter starts with a typeCast
- UriResourceStartingTypeFilterImpl uriResource = new UriResourceStartingTypeFilterImpl(
- filterEntityType,
- sourceIsCollection);
- if (sourceIsCollection) {
- uriResource.setCollectionTypeFilter(filterEntityType);
- } else {
- uriResource.setEntryTypeFilter(filterEntityType);
- }
- context.contextUriInfo.addResourcePart(uriResource);
- return null;
- } else {
-
- // check if last segment may contain key properties
- if (lastResourcePart instanceof UriResourceWithKeysImpl) {
- UriResourceWithKeysImpl lastPartWithKeys = (UriResourceWithKeysImpl) lastResourcePart;
-
- if (!lastPartWithKeys.isCollection()) {
- if (lastPartWithKeys.getTypeFilterOnEntry() != null) {
- throw wrap(new UriParserSemanticException("Entry typefilters are not chainable, used '"
- + getName(filterEntityType) + "' behind '"
- + getName(lastPartWithKeys.getTypeFilterOnEntry()) + "'",
- UriParserSemanticException.MessageKeys.TYPE_FILTER_NOT_CHAINABLE,
- getName(lastPartWithKeys.getTypeFilterOnEntry()), getName(filterEntityType)));
- }
- lastPartWithKeys.setEntryTypeFilter(filterEntityType);
- return null;
- } else {
- if (lastPartWithKeys.getTypeFilterOnCollection() != null) {
- throw wrap(new UriParserSemanticException("Collection typefilters are not chainable, used '"
- + getName(filterEntityType) + "' behind '"
- + getName(lastPartWithKeys.getTypeFilterOnCollection()) + "'",
- UriParserSemanticException.MessageKeys.TYPE_FILTER_NOT_CHAINABLE,
- getName(lastPartWithKeys.getTypeFilterOnCollection()), getName(filterEntityType)));
- }
- lastPartWithKeys.setCollectionTypeFilter(filterEntityType);
- return null;
- }
- } else if (lastResourcePart instanceof UriResourceTypedImpl) {
- UriResourceTypedImpl lastPartTyped = (UriResourceTypedImpl) lastResourcePart;
- if (lastPartTyped.getTypeFilter() != null) {
- throw wrap(new UriParserSemanticException("Typefilters are not chainable, used '"
- + getName(filterEntityType) + "' behind '"
- + getName(lastPartTyped.getTypeFilter()) + "'",
- UriParserSemanticException.MessageKeys.TYPE_FILTER_NOT_CHAINABLE,
- getName(lastPartTyped.getTypeFilter()), getName(filterEntityType)));
- }
-
- lastPartTyped.setTypeFilter(filterEntityType);
- return null;
- } else {
- throw wrap(new UriParserSemanticException("Path segment before '" + getName(filterEntityType)
- + "' not typed",
- UriParserSemanticException.MessageKeys.PREVIOUS_PART_NOT_TYPED, getName(filterEntityType)));
- }
- }
- }
-
- } else if (sourceType instanceof EdmComplexType) {
-
- EdmComplexType filterComplexType = edm.getComplexType(fullFilterName);
-
- if (filterComplexType != null) {
-
- // is complex type cast
- if (!(filterComplexType.compatibleTo(sourceType))) {
- throw wrap(new UriParserSemanticException(
- "Complex typefilter '" + getName(sourceType) + "'not compatible type of previous path segment '"
- + getName(filterComplexType) + "'",
- UriParserSemanticException.MessageKeys.INCOMPATIBLE_TYPE_FILTER, getName(sourceType)));
- }
-
- // is simple complex type cast
- if (lastResourcePart == null) {
- // this may be the case if a member expression within a filter starts with a typeCast
- UriResourceStartingTypeFilterImpl uriResource =
- new UriResourceStartingTypeFilterImpl(filterComplexType, sourceIsCollection);
-
- if (sourceIsCollection) {
- uriResource.setCollectionTypeFilter(filterComplexType);
- } else {
- uriResource.setEntryTypeFilter(filterComplexType);
- }
- context.contextUriInfo.addResourcePart(uriResource);
- return null;
- } else {
- if (lastResourcePart instanceof UriResourceWithKeysImpl) {
- // e.g. in case of function returning complex data or a list of complex data
- UriResourceWithKeysImpl lastPartWithKeys = (UriResourceWithKeysImpl) lastResourcePart;
-
- if (!lastPartWithKeys.isCollection()) {
- if (lastPartWithKeys.getTypeFilterOnEntry() != null) {
- throw wrap(new UriParserSemanticException("Entry typefilters are not chainable, used '"
- + getName(filterComplexType) + "' behind '"
- + getName(lastPartWithKeys.getTypeFilterOnEntry()) + "'",
- UriParserSemanticException.MessageKeys.TYPE_FILTER_NOT_CHAINABLE,
- getName(lastPartWithKeys.getTypeFilterOnEntry()), getName(filterComplexType)));
- }
- lastPartWithKeys.setEntryTypeFilter(filterComplexType);
- return null;
- } else {
- if (lastPartWithKeys.getTypeFilterOnCollection() != null) {
- throw wrap(new UriParserSemanticException("Collection typefilters are not chainable, used '"
- + getName(filterComplexType) + "' behind '"
- + getName(lastPartWithKeys.getTypeFilterOnCollection()) + "'",
- UriParserSemanticException.MessageKeys.TYPE_FILTER_NOT_CHAINABLE,
- getName(lastPartWithKeys.getTypeFilterOnCollection()), getName(filterComplexType)));
- }
- lastPartWithKeys.setCollectionTypeFilter(filterComplexType);
- return null;
- }
-
- } else if (lastResourcePart instanceof UriResourceTypedImpl) {
- UriResourceTypedImpl lastPartTyped = (UriResourceTypedImpl) lastResourcePart;
- if (lastPartTyped.getTypeFilter() != null) {
- throw wrap(new UriParserSemanticException("Typefilters are not chainable, used '"
- + getName(filterComplexType) + "' behind '"
- + getName(lastPartTyped.getTypeFilter()) + "'",
- UriParserSemanticException.MessageKeys.TYPE_FILTER_NOT_CHAINABLE,
- getName(lastPartTyped.getTypeFilter()), getName(filterComplexType)));
- }
-
- lastPartTyped.setTypeFilter(filterComplexType);
- return null;
- } else {
- throw wrap(new UriParserSemanticException("Path segment before '" + getName(filterComplexType)
- + "' not typed",
- UriParserSemanticException.MessageKeys.PREVIOUS_PART_NOT_TYPED, getName(filterComplexType)));
- }
- }
- }
- }
-
- FullQualifiedName fullBindingTypeName = sourceType.getFullQualifiedName();
-
- // check for action
- EdmAction action = edm.getBoundAction(fullFilterName, fullBindingTypeName, sourceIsCollection);
- if (action != null) {
- UriResourceActionImpl pathInfoAction = new UriResourceActionImpl(action);
- context.contextUriInfo.addResourcePart(pathInfoAction);
- return null;
- }
-
- // do a check for bound functions (which requires a parameter list)
- if (ctx.vlNVO.size() == 0) {
- throw wrap(new UriParserSemanticException("Unknown type for type cast " + fullFilterName.toString()
- + " not found", UriParserSemanticException.MessageKeys.UNKNOWN_TYPE, fullFilterName.toString()));
- }
-
- context.contextReadingFunctionParameters = true;
- @SuppressWarnings("unchecked")
- List<UriParameter> parameters = (List<UriParameter>) ctx.vlNVO.get(0).accept(this);
- context.contextReadingFunctionParameters = false;
-
- // get names of function parameters
- List<String> names = new ArrayList<String>();
- for (UriParameter item : parameters) {
- names.add(item.getName());
- }
-
- EdmFunction function = edm.getBoundFunction(fullFilterName, fullBindingTypeName, sourceIsCollection, names);
-
- if (function != null) {
- UriResourceFunctionImpl pathInfoFunction = new UriResourceFunctionImpl(null, function, parameters);
- context.contextUriInfo.addResourcePart(pathInfoFunction);
-
- // mark parameters as consumed
- ctx.vlNVO.remove(0);
- return null;
- }
-
- // check for unbound function in the $filter case ( where the previous resource segment is a $it)
- function = edm.getUnboundFunction(fullFilterName, names);
-
- if (function != null) {
- UriResourceFunctionImpl pathInfoFunction = new UriResourceFunctionImpl(null, function, parameters);
- context.contextUriInfo.addResourcePart(pathInfoFunction);
-
- // mark parameters as consumed
- ctx.vlNVO.remove(0);
- return null;
- }
-
- throw wrap(new UriParserSemanticException("Unknown resource path segment:" + fullFilterName.toString(),
- UriParserSemanticException.MessageKeys.UNKNOWN_PART, fullFilterName.toString()));
- }
- }
-
- /**
- * Ensures that the namespace of the first resource parts is null
- * @param vNS namespace or null
- */
- private void ensureNamespaceIsNull(final NamespaceContext vNS) {
- if (vNS != null && context.contextUriInfo.getLastResourcePart() == null) {
- // First resource part and namespace is not null!
- throw wrap(new UriParserSemanticException("Namespace is not allowed for EntitySets, Singeltons, "
- + " Action Imports and Function Imports. Found " + vNS.getText(),
- UriParserSemanticException.MessageKeys.NAMESPACE_NOT_ALLOWED_AT_FIRST_ELEMENT, vNS.getText()));
- }
- }
-
- private String getName(final EdmType type) {
- return type.getFullQualifiedName().getFullQualifiedNameAsString();
- }
-
- @Override
- public Object visitAllEOF(final AllEOFContext ctx) {
- context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.all);
- return null;
- }
-
- @Override
- public Object visitAllExpr(final AllExprContext ctx) {
- UriResource obj = context.contextUriInfo.getLastResourcePart();
- if (!(obj instanceof UriResourcePartTyped)) {
- throw wrap(new UriParserSemanticException("all only allowed on typed path segments",
- UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PARTS, "all"));
- } else if (obj instanceof UriResourceNavigation) {
- if (!((UriResourceNavigation) obj).getKeyPredicates().isEmpty()) {
- throw wrap(new UriParserSemanticException(
- "Any lamdba expression must not be following navigation properties with key predicates.",
- UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED));
- }
- }
-
- UriContext.LambdaVariable var = new UriContext.LambdaVariable();
- var.name = ctx.vLV.getText();
- var.type = ParserHelper.getTypeInformation((UriResourcePartTyped) obj);
-
- context.allowedLambdaVariables.push(var);
- Expression expression = (Expression) ctx.vLE.accept(this);
- context.allowedLambdaVariables.pop();
- return new UriResourceLambdaAllImpl(var.name, expression);
- }
-
- @Override
- public Expression visitAltAdd(final AltAddContext ctx) {
- int tokenIndex = ctx.vO.getType();
- return new BinaryImpl(
- (Expression) ctx.vE1.accept(this),
- tokenIndex == UriLexer.ADD ? BinaryOperatorKind.ADD : BinaryOperatorKind.SUB,
- (Expression) ctx.vE2.accept(this),
- null);
- }
-
- @Override
- public Object visitAltAll(final AltAllContext ctx) {
-
- UriInfoImpl uriInfoImplpath = new UriInfoImpl().setKind(UriInfoKind.resource);
-
- uriInfoImplpath.addResourcePart((UriResourceImpl) super.visitAltAll(ctx));
-
- EdmType startType = removeUriResourceStartingTypeFilterImpl(uriInfoImplpath);
-
- return new MemberImpl(uriInfoImplpath, startType);
- }
-
- private EdmType removeUriResourceStartingTypeFilterImpl(final UriInfoImpl uriInfoImplpath) {
-
- List<UriResource> segments = uriInfoImplpath.getUriResourceParts();
- if (segments.size() == 0) {
- return null;
- }
-
- UriResource segment = segments.get(0);
- if (segment instanceof UriResourceStartingTypeFilterImpl) {
- UriResourceStartingTypeFilterImpl startingTypeFilter = (UriResourceStartingTypeFilterImpl) segment;
-
- EdmType type = null;
- if (startingTypeFilter.getTypeFilterOnEntry() != null) {
- type = startingTypeFilter.getTypeFilterOnEntry();
- } else if (startingTypeFilter.getTypeFilterOnCollection() != null) {
- type = startingTypeFilter.getTypeFilterOnCollection();
- } else {
- type = startingTypeFilter.getType();
- }
-
- uriInfoImplpath.removeResourcePart(0);
- return type;
- }
-
- return null;
- }
-
- @Override
- public Expression visitAltAnd(final AltAndContext ctx) {
- return new BinaryImpl(
- (Expression) ctx.vE1.accept(this),
- BinaryOperatorKind.AND,
- (Expression) ctx.vE2.accept(this),
- EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Boolean));
- }
-
- @Override
- public Object visitAltAny(final AltAnyContext ctx) {
- UriInfoImpl uriInfoImplpath = new UriInfoImpl().setKind(UriInfoKind.resource);
-
- uriInfoImplpath.addResourcePart((UriResourceImpl) super.visitAltAny(ctx));
-
- EdmType startType = removeUriResourceStartingTypeFilterImpl(uriInfoImplpath);
-
- return new MemberImpl(uriInfoImplpath, startType);
- }
-
- @Override
- public Expression visitAltComparism(final AltComparismContext ctx) {
- int tokenIndex = ctx.vO.getType();
- BinaryOperatorKind kind = null;
- if (tokenIndex == UriLexer.GT) {
- kind = BinaryOperatorKind.GT;
- } else if (tokenIndex == UriLexer.GE) {
- kind = BinaryOperatorKind.GE;
- } else if (tokenIndex == UriLexer.LT) {
- kind = BinaryOperatorKind.LT;
- } else if (tokenIndex == UriLexer.LE) {
- kind = BinaryOperatorKind.LE;
- }
- return new BinaryImpl(
- (Expression) ctx.vE1.accept(this),
- kind,
- (Expression) ctx.vE2.accept(this),
- EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Boolean));
- }
-
- @Override
- public Object visitEntityEOF(final EntityEOFContext ctx) {
- String odi = ctx.vODI.getText();
- FullQualifiedName fullName = getFullNameFromContext(ctx.vNS, odi);
-
- EdmEntityType type = edm.getEntityType(fullName);
- if (type == null) {
- throw wrap(new UriParserSemanticException("Expected EntityTypeName",
- UriParserSemanticException.MessageKeys.UNKNOWN_ENTITY_TYPE, fullName.toString()));
- }
- context.contextUriInfo.setEntityTypeCast(type);
-
- // contextUriInfo = uriInfo;
- context.contextTypes.push(context.contextUriInfo.getEntityTypeCast());
- context.isCollection = true; // TODO: check!
-
- return null;
- }
-
- @Override
- public Expression visitAltEquality(final AltEqualityContext ctx) {
- int tokenIndex = ctx.vO.getType();
- return new BinaryImpl(
- (Expression) ctx.vE1.accept(this),
- tokenIndex == UriLexer.EQ_ALPHA ? BinaryOperatorKind.EQ : BinaryOperatorKind.NE,
- (Expression) ctx.vE2.accept(this),
- EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Boolean));
- }
-
- @Override
- public Object visitAltHas(final AltHasContext ctx) {
- return new BinaryImpl(
- (Expression) ctx.vE1.accept(this),
- BinaryOperatorKind.HAS,
- (Expression) ctx.vE2.accept(this),
- EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Boolean));
- }
-
- @Override
- public Object visitMetadataEOF(final MetadataEOFContext ctx) {
-
- context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.metadata);
- return null;
- }
-
- @Override
- public Expression visitAltMult(final AltMultContext ctx) {
- int tokenIndex = ctx.vO.getType();
- BinaryOperatorKind kind;
- if (tokenIndex == UriLexer.MUL) {
- kind = BinaryOperatorKind.MUL;
- } else if (tokenIndex == UriLexer.DIV) {
- kind = BinaryOperatorKind.DIV;
- } else {
- kind = BinaryOperatorKind.MOD;
- }
- return new BinaryImpl(
- (Expression) ctx.vE1.accept(this),
- kind,
- (Expression) ctx.vE2.accept(this),
- null);
- }
-
- @Override
- public Expression visitAltOr(final AltOrContext ctx) {
- return new BinaryImpl(
- (Expression) ctx.vE1.accept(this),
- BinaryOperatorKind.OR,
- (Expression) ctx.vE2.accept(this),
- EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Boolean));
- }
-
- @Override
- public Object visitAnyExpr(final AnyExprContext ctx) {
- if (ctx.vLV != null) {
- UriResourceImpl lastResourcePart = (UriResourceImpl) context.contextUriInfo.getLastResourcePart();
- if (!(lastResourcePart instanceof UriResourcePartTyped)) {
- throw wrap(new UriParserSemanticException("any only allowed on typed path segments",
- UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PARTS, "any"));
- } else if (lastResourcePart instanceof UriResourceNavigation) {
- if (!((UriResourceNavigation) lastResourcePart).getKeyPredicates().isEmpty()) {
- throw wrap(new UriParserSemanticException(
- "Any lamdba expression must not be following navigation properties with key predicates",
- UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED));
- }
- }
-
- UriContext.LambdaVariable var = new UriContext.LambdaVariable();
- var.name = ctx.vLV.getText();
- var.type = ParserHelper.getTypeInformation((UriResourcePartTyped) lastResourcePart);
-
- context.allowedLambdaVariables.push(var);
- Expression expression = (Expression) ctx.vLE.accept(this);
- context.allowedLambdaVariables.pop();
- return new UriResourceLambdaAnyImpl(var.name, expression);
- }
- return null;
- }
-
- @Override
- public Object visitBooleanNonCaseLiteral(final BooleanNonCaseLiteralContext ctx) {
- final String text = ctx.getText().toLowerCase();
- return new LiteralImpl(text.equals("false") ? "false" : "true",
- EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Boolean));
- }
-
- @Override
- public Expression visitCastExpr(final CastExprContext ctx) {
- List<Expression> parameters = new ArrayList<Expression>();
- if (ctx.vE1 != null) {
- // is optional parameter
- parameters.add((Expression) ctx.vE1.accept(this));
- }
-
- String namespace = ctx.vNS.getText();
- namespace = namespace.substring(0, namespace.length() - 1);
-
- FullQualifiedName fullName = new FullQualifiedName(namespace, ctx.vODI.getText());
- EdmType type = getType(fullName);
- parameters.add(new TypeLiteralImpl(type));
- return new MethodImpl(MethodKind.CAST, parameters);
- }
-
- private EdmType getType(final FullQualifiedName fullName) {
- EdmType type = null;
-
- type = edm.getEntityType(fullName);
- if (type != null) {
- return type;
- }
-
- type = edm.getComplexType(fullName);
- if (type != null) {
- return type;
- }
-
- type = edm.getTypeDefinition(fullName);
- if (type != null) {
- return type;
- }
-
- type = edm.getEnumType(fullName);
- if (type != null) {
- return type;
- }
-
- if (fullName.getNamespace().equals(EdmPrimitiveType.EDM_NAMESPACE)) {
- final EdmPrimitiveTypeKind typeKind = EdmPrimitiveTypeKind.valueOf(fullName.getName());
- type = EdmPrimitiveTypeFactory.getInstance(typeKind);
- if (type != null) {
- return type;
- }
- }
-
- return null;
-
- }
-
- @Override
- public Expression visitCeilingMethodCallExpr(final CeilingMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.CEILING, Collections.singletonList((Expression) ctx.vE1.accept(this)));
- }
-
- @Override
- public Expression visitConcatMethodCallExpr(final ConcatMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.CONCAT, Arrays.asList(
- (Expression) ctx.vE1.accept(this),
- (Expression) ctx.vE2.accept(this)));
- }
-
- @Override
- public Object visitConstSegment(final ConstSegmentContext ctx) {
- UriInfoImpl uriInfoResource = context.contextUriInfo;
- UriResource pathInfo = uriInfoResource.getLastResourcePart();
-
- if (ctx.vV != null) {
- if (pathInfo instanceof UriResourcePartTyped) {
- if (!((UriResourcePartTyped) pathInfo).isCollection()) {
- context.contextUriInfo.addResourcePart(new UriResourceValueImpl());
- } else {
- throw wrap(new UriParserSemanticException("$value only allowed on typed path segments",
- UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PARTS, "$value"));
- }
- return null;
- } else {
- throw wrap(new UriParserSemanticException("$value only allowed on typed path segments",
- UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PARTS, "$value"));
- }
-
- } else if (ctx.vC != null) {
- if (pathInfo instanceof UriResourcePartTyped) {
- if (((UriResourcePartTyped) pathInfo).isCollection()) {
- context.contextUriInfo.addResourcePart(new UriResourceCountImpl());
- } else {
- throw wrap(new UriParserSemanticException("$count only allowed on collection properties",
- UriParserSemanticException.MessageKeys.ONLY_FOR_COLLECTIONS, "$count"));
- }
- } else {
- throw wrap(new UriParserSemanticException("$count only allowed on typed properties",
- UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PARTS, "$count"));
- }
- } else if (ctx.vR != null) {
- if (pathInfo instanceof UriResourcePartTyped) {
- EdmType type = ((UriResourcePartTyped) pathInfo).getType();
- if (type instanceof EdmEntityType) {
- context.contextUriInfo.addResourcePart(new UriResourceRefImpl());
- } else {
- throw wrap(new UriParserSemanticException("$ref only allowed on entity types",
- UriParserSemanticException.MessageKeys.ONLY_FOR_ENTITY_TYPES, "$ref"));
- }
- } else {
- throw wrap(new UriParserSemanticException("$ref only allowed on typed properties",
- UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PROPERTIES, "$ref"));
- }
-
- } else if (ctx.vAll != null) {
- context.contextUriInfo.addResourcePart((UriResourceLambdaAllImpl) ctx.vAll.accept(this));
- } else if (ctx.vAny != null) {
- context.contextUriInfo.addResourcePart((UriResourceLambdaAnyImpl) ctx.vAny.accept(this));
- }
- return null;
- }
-
- @Override
- public Expression visitContainsMethodCallExpr(final ContainsMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.CONTAINS, Arrays.asList(
- (Expression) ctx.vE1.accept(this),
- (Expression) ctx.vE2.accept(this)));
- }
-
- @Override
- public Object visitDateMethodCallExpr(final DateMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.DATE, Collections.singletonList((Expression) ctx.vE1.accept(this)));
- }
-
- @Override
- public Expression visitDayMethodCallExpr(final DayMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.DAY, Collections.singletonList((Expression) ctx.vE1.accept(this)));
- }
-
- @Override
- public Expression visitGeoDistanceMethodCallExpr(final GeoDistanceMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.GEODISTANCE, Arrays.asList(
- (Expression) ctx.vE1.accept(this),
- (Expression) ctx.vE2.accept(this)));
- }
-
- @Override
- public Object visitEndsWithMethodCallExpr(final EndsWithMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.ENDSWITH, Arrays.asList(
- (Expression) ctx.vE1.accept(this),
- (Expression) ctx.vE2.accept(this)));
- }
-
- @Override
- public Object visitEnumLiteral(final EnumLiteralContext ctx) {
- // get type
- final String odi = ctx.vODI.getText();
-
- final FullQualifiedName fullName = getFullNameFromContext(ctx.vNS, odi);
- final EdmEnumType edmEnumType = edm.getEnumType(fullName);
- if (edmEnumType == null) {
- throw wrap(new UriParserSemanticException(
- "Enum type '" + fullName.getFullQualifiedNameAsString() + "' not found!",
- UriParserSemanticException.MessageKeys.UNKNOWN_TYPE, fullName.getFullQualifiedNameAsString()));
- }
-
- String valueString = ctx.vValues.getText();
- valueString = valueString.substring(1, valueString.length() - 1);
- String[] values = valueString.split(",");
- return new EnumerationImpl(edmEnumType, Arrays.asList(values));
- }
-
- @Override
- public Object visitExpandItems(final ExpandItemsContext ctx) {
- ExpandOptionImpl expand = new ExpandOptionImpl();
- expand.setText(ctx.getText());
- for (ExpandItemContext eI : ctx.vlEI) {
- expand.addExpandItem((ExpandItemImpl) eI.accept(this));
- }
-
- return expand;
- }
-
- @Override
- public Object visitExpandItem(final ExpandItemContext ctx) {
-
- ExpandItemImpl expandItem = null;
- if (ctx.vS != null) {
- expandItem = new ExpandItemImpl().setIsStar(true);
- if (ctx.vR != null) {
- expandItem.setIsRef(true);
- } else if (ctx.vM != null) {
- LevelsOptionImpl levels = new LevelsOptionImpl().setMax();
- levels.setText(ctx.vM.getText());
- try {
- expandItem.setSystemQueryOption(levels);
- } catch (ODataRuntimeException e) {
- // Thrown if duplicated system query options are detected
- throw wrap(new UriParserSyntaxException("Double system query option!", e,
- UriParserSyntaxException.MessageKeys.DOUBLE_SYSTEM_QUERY_OPTION, e.getMessage()));
- }
- } else if (ctx.vL != null) {
- LevelsOptionImpl levels = new LevelsOptionImpl();
- String text = ctx.vL.getText();
- levels.setText(text);
- levels.setValue(Integer.parseInt(text));
- try {
- expandItem.setSystemQueryOption(levels);
- } catch (ODataRuntimeException e) {
- // Thrown if duplicated system query options are detected
- throw wrap(new UriParserSyntaxException("Double system query option!", e,
- UriParserSyntaxException.MessageKeys.DOUBLE_SYSTEM_QUERY_OPTION, e.getMessage()));
- }
- }
-
- } else if (ctx.vEP != null) {
- expandItem = (ExpandItemImpl) ctx.vEP.accept(this);
-
- if (ctx.vEPE != null) {
- ExpandItemImpl contextExpandItemPathBU = context.contextExpandItemPath;
- context.contextExpandItemPath = expandItem;
-
- @SuppressWarnings("unchecked")
- List<SystemQueryOptionImpl> list = (List<SystemQueryOptionImpl>) ctx.vEPE.accept(this);
- try {
- for (SystemQueryOptionImpl option : list) {
- expandItem.setSystemQueryOption(option);
- }
- } catch (ODataRuntimeException e) {
- // Thrown if duplicated system query options are detected
- throw wrap(new UriParserSyntaxException("Double system query option!", e,
- UriParserSyntaxException.MessageKeys.DOUBLE_SYSTEM_QUERY_OPTION, e.getMessage()));
- }
- context.contextExpandItemPath = contextExpandItemPathBU;
- }
- }
-
- return expandItem;
-
- }
-
- @Override
- public Object visitExpandPath(final ExpandPathContext ctx) {
- ExpandItemImpl expandItem = new ExpandItemImpl();
-
- // save context
- ExpandItemImpl contextExpandItemPathBU = context.contextExpandItemPath;
- UriInfoImpl uriInfoResourceBU = context.contextUriInfo;
-
- // set tmp context
- context.contextExpandItemPath = expandItem;
- context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.resource);
-
- context.contextVisitExpandResourcePath = true;
- super.visitExpandPath(ctx);
- context.contextVisitExpandResourcePath = false;
-
- EdmType startType = removeUriResourceStartingTypeFilterImpl(context.contextUriInfo);
- expandItem.setResourcePath(context.contextUriInfo);
- if (startType != null) {
- expandItem.setTypeFilter(startType);
- }
-
- // reset context
- context.contextUriInfo = uriInfoResourceBU;
- context.contextExpandItemPath = contextExpandItemPathBU;
-
- // test
- validate(uriInfoResourceBU.asUriInfoResource(), expandItem);
- //
-
- return expandItem;
- }
-
- private void validate(UriInfoResource uriInfoResource, ExpandItemImpl expandItem) {
- if (uriInfoResource != null) {
- EdmEntityType type = getEntityType(uriInfoResource);
- EdmEntityType name = getEntityType(expandItem.getResourcePath());
-
- if (name != null && type != null) {
- EdmElement property = type.getProperty(name.getName());
- if (!(property instanceof EdmNavigationProperty)) {
- throw wrap(new UriParserSemanticException(
- "NavigationProperty '" + name.getName() + "' not found in type '"
- + type.getFullQualifiedName().getFullQualifiedNameAsString() + "'",
- UriParserSemanticException.MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE,
- name.getFullQualifiedName().getFullQualifiedNameAsString(),
- type.getFullQualifiedName().getFullQualifiedNameAsString()));
- }
- }
- }
- }
-
- private EdmEntityType getEntityType(UriInfoResource test) {
- List<UriResource> parts = test.getUriResourceParts();
- if (!parts.isEmpty()) {
- UriResource lastPart = parts.get(parts.size() - 1);
- if (lastPart instanceof UriResourceEntitySet) {
- UriResourceEntitySet entitySet = (UriResourceEntitySet) lastPart;
- return entitySet.getEntityType();
- }
- }
- return null;
- }
-
- @Override
- public Object visitExpandPathExtension(final ExpandPathExtensionContext ctx) {
- List<SystemQueryOptionImpl> list = new ArrayList<SystemQueryOptionImpl>();
-
- EdmType targetType = null;
- boolean isColl = false;
- if (context.contextExpandItemPath == null) {
- // use the type of the last resource path segement
- UriResourceTypedImpl lastSegment = (UriResourceTypedImpl) context.contextUriInfo.getLastResourcePart();
- targetType = ParserHelper.getTypeInformation(lastSegment);
- isColl = lastSegment.isCollection();
- } else {
- if (context.contextExpandItemPath.getResourcePath() == null) {
- // use the type of the last resource path segement
- UriResourceTypedImpl lastSegment = (UriResourceTypedImpl) context.contextUriInfo.getLastResourcePart();
- targetType = ParserHelper.getTypeInformation(lastSegment);
- isColl = lastSegment.isCollection();
- } else {
- // use the type of the last ''expand'' path segement
- UriInfoImpl info = (UriInfoImpl) context.contextExpandItemPath.getResourcePath();
- targetType = ParserHelper.getTypeInformation((UriResourcePartTyped) info.getLastResourcePart());
- isColl = ((UriResourcePartTyped) info.getLastResourcePart()).isCollection();
- }
- }
-
- context.contextTypes.push(targetType);
- context.isCollection = isColl;
-
- if (ctx.vC != null) {
- UriInfoImpl resourcePath = (UriInfoImpl) context.contextExpandItemPath.getResourcePath();
- resourcePath.addResourcePart(new UriResourceCountImpl());
-
- for (ExpandCountOptionContext s : ctx.vlEOC) {
- list.add((SystemQueryOptionImpl) s.accept(this));
- }
- } else if (ctx.vR != null) {
- UriInfoImpl resourcePath = (UriInfoImpl) context.contextExpandItemPath.getResourcePath();
- resourcePath.addResourcePart(new UriResourceRefImpl());
-
- for (ExpandRefOptionContext s : ctx.vlEOR) {
- list.add((SystemQueryOptionImpl) s.accept(this));
- }
- } else {
- for (ExpandOptionContext s : ctx.vlEO) {
- list.add((SystemQueryOptionImpl) s.accept(this));
- }
- }
-
- context.contextTypes.pop();
- return list;
-
- }
-
- @Override
- public Object visitFilter(final FilterContext ctx) {
- context.contextReadingQueryPart = true;
- final FilterOptionImpl result = new FilterOptionImpl().setExpression((Expression) ctx.children.get(2)
- .accept(this));
- context.contextReadingQueryPart = false;
-
- return result;
- }
-
- @Override
- public Object visitFilterExpressionEOF(final FilterExpressionEOFContext ctx) {
- context.contextReadingQueryPart = true;
- final FilterOptionImpl result = new FilterOptionImpl().setExpression((Expression) ctx.children.get(0)
- .accept(this));
- context.contextReadingQueryPart = false;
-
- return result;
- }
-
- @Override
- public Expression visitFloorMethodCallExpr(final FloorMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.FLOOR, Collections.singletonList((Expression) ctx.vE1.accept(this)));
- }
-
- @Override
- public Expression visitFractionalsecondsMethodCallExpr(final FractionalsecondsMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.FRACTIONALSECONDS, Collections.singletonList((Expression) ctx.vE1.accept(this)));
- }
-
- @Override
- public Expression visitGeoLengthMethodCallExpr(final GeoLengthMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.GEOLENGTH, Collections.singletonList((Expression) ctx.vE1.accept(this)));
- }
-
- @Override
- public Expression visitHourMethodCallExpr(final HourMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.HOUR, Collections.singletonList((Expression) ctx.vE1.accept(this)));
- }
-
- @Override
- public Expression visitIndexOfMethodCallExpr(final IndexOfMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.INDEXOF, Arrays.asList(
- (Expression) ctx.vE1.accept(this),
- (Expression) ctx.vE2.accept(this)));
- }
-
- @Override
- public Object visitInlinecount(final InlinecountContext ctx) {
- final String text = ctx.children.get(2).getText();
- return new CountOptionImpl()
- .setValue(text.equalsIgnoreCase("true") ? true : false)
- .setText(text);
- }
-
- @Override
- public Expression visitGeoIntersectsMethodCallExpr(final GeoIntersectsMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.GEOINTERSECTS, Arrays.asList(
- (Expression) ctx.vE1.accept(this),
- (Expression) ctx.vE2.accept(this)));
- }
-
- @Override
- public Expression visitIsofExpr(final IsofExprContext ctx) {
- List<Expression> parameters = new ArrayList<Expression>();
- if (ctx.vE1 != null) {
- parameters.add((Expression) ctx.vE1.accept(this));
- }
-
- String namespace = ctx.vNS.getText();
- namespace = namespace.substring(0, namespace.length() - 1);
-
- FullQualifiedName fullName = new FullQualifiedName(namespace, ctx.vODI.getText());
- EdmType type = getType(fullName);
- parameters.add(new TypeLiteralImpl(type));
-
- return new MethodImpl(MethodKind.ISOF, parameters);
- }
-
- @Override
- public Expression visitLengthMethodCallExpr(final LengthMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.LENGTH, Collections.singletonList((Expression) ctx.vE1.accept(this)));
- }
-
- @Override
- public Object visitLevels(final LevelsContext ctx) {
-
- LevelsOptionImpl levels = new LevelsOptionImpl();
-
- String text = ctx.children.get(2).getText();
-
- if (text.equals("max")) {
- levels.setMax();
- } else {
- levels.setValue(Integer.parseInt(text));
- }
- levels.setText(text);
-
- return levels;
-
- }
-
- @Override
- public Expression visitMaxDateTimeMethodCallExpr(final MaxDateTimeMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.MAXDATETIME, null);
- }
-
- @Override
- public Object visitMemberExpr(final MemberExprContext ctx) {
-
- UriInfoImpl uriInfoImplpath = new UriInfoImpl().setKind(UriInfoKind.resource);
-
- if (context.contextTypes.isEmpty()) {
- throw wrap(new UriParserSemanticException("Expression '" + ctx.getText() + "' is not allowed as key value.",
- UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, ctx.getText()));
- }
-
- if (ctx.vIt != null || ctx.vIts != null) {
- uriInfoImplpath.addResourcePart(new UriResourceItImpl(context.contextTypes.peek(), context.isCollection));
- }
-
- if (ctx.vPs != null) {
- // save the context
- UriInfoImpl backupUriInfoPath = context.contextUriInfo;
-
- // set temporary uriInfoPath
- context.contextUriInfo = uriInfoImplpath;
-
- ctx.vPs.accept(this);
-
- // reset context
- context.contextUriInfo = backupUriInfoPath;
- }
-
- if (ctx.vALL != null) {
- uriInfoImplpath.addResourcePart((UriResourceImpl) ctx.vALL.accept(this));
- }
- if (ctx.vANY != null) {
- uriInfoImplpath.addResourcePart((UriResourceImpl) ctx.vANY.accept(this));
- }
-
- EdmType startType = removeUriResourceStartingTypeFilterImpl(uriInfoImplpath);
-
- return new MemberImpl(uriInfoImplpath, startType);
- }
-
- @Override
- public Expression visitMinDateTimeMethodCallExpr(final MinDateTimeMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.MINDATETIME, null);
- }
-
- @Override
- public Expression visitMinuteMethodCallExpr(final MinuteMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.MINUTE, Collections.singletonList((Expression) ctx.vE1.accept(this)));
- }
-
- @Override
- public Expression visitMonthMethodCallExpr(final MonthMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.MONTH, Collections.singletonList((Expression) ctx.vE1.accept(this)));
- }
-
- @Override
- public Object visitNameValueOptList(final NameValueOptListContext ctx) {
- if (ctx.vVO != null) {
- // This branch is chosen if the key predicate is a common expression e.g. EntitySet(0)
-
- // is single key predicate without a name
- String valueText = ctx.vVO.getText();
- Expression expression = null;
- try {
- expression = (Expression) ctx.vVO.accept(this);
- } catch (final RuntimeException e) {
- throw wrap(new UriParserSemanticException("Invalid key value: " + valueText, e,
- UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, valueText));
- }
-
- // get type of last resource part
- UriResource last = context.contextUriInfo.getLastResourcePart();
- if (!(last instanceof UriResourcePartTyped)) {
- throw wrap(new UriParserSemanticException("Parameters list on untyped resource path segment not allowed",
- UriParserSemanticException.MessageKeys.PARAMETERS_LIST_ONLY_FOR_TYPED_PARTS));
-
- } else if (last instanceof UriResourceFunction) {
- // Handle functions
- final UriResourceFunction uriResourceFunction =
- (UriResourceFunction) context.contextUriInfo.getLastResourcePart();
- final EdmReturnType returnType = uriResourceFunction.getFunction().getReturnType();
-
- if (returnType.getType().getKind() != EdmTypeKind.ENTITY || !returnType.isCollection()) {
- throw wrap(new UriParserSemanticException("No keys allowed",
- UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED));
- } else {
- // The functions returns a collection of entities
- // Get the EDM Type and determine how many key predicates are needed. In this case only one
- // key predicate is allowed. If the entity type needs more than one key predicate, the client
- // has to use the key value syntax e.g. EntitySet(ID=1,Order=2)
- final EdmEntityType entityType = (EdmEntityType) uriResourceFunction.getFunction().getReturnType().getType();
- final List<String> lastKeyPredicates = entityType.getKeyPredicateNames();
-
- if (lastKeyPredicates.size() == 1) {
- return Collections.singletonList(new UriParameterImpl()
- .setName(lastKeyPredicates.get(0))
- .setText(valueText)
- .setExpression(expression));
- } else {
- throw wrap(new UriParserSemanticException("Wrong number of key properties.",
- UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
- Integer.toString(lastKeyPredicates.size()), "1"));
- }
- }
- } else {
- // Handle EntitySets
- EdmEntityType lastType = (EdmEntityType) ((UriResourcePartTyped) last).getType();
-
- // get list of keys for lastType
- List<String> lastKeyPredicates = lastType.getKeyPredicateNames();
-
- // If there is exactly one key defined in the EDM, then this key is the key written in the URI,
- // so fill the keylist with this key and return.
- if (lastKeyPredicates.size() == 1) {
- return Collections.singletonList(new UriParameterImpl()
- .setName(lastKeyPredicates.get(0))
- .setText(valueText)
- .setExpression(expression));
- }
-
- // There are more keys defined in the EDM, but only one is written in the URI. This is allowed only if
- // referential constraints are defined on this navigation property which can be used to fill up all
- // required keys.
- // For using referential constraints the last resource part must be a navigation property.
- if (!(context.contextUriInfo.getLastResourcePart() instanceof UriResourceNavigationPropertyImpl)) {
- throw wrap(new UriParserSemanticException("Wrong number of key properties.",
- UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
- Integer.toString(lastKeyPredicates.size()), "1"));
- }
- UriResourceNavigationPropertyImpl lastNav = (UriResourceNavigationPropertyImpl) last;
-
- // get the partner of the navigation property
- EdmNavigationProperty partner = lastNav.getProperty().getPartner();
- if (partner == null) {
- throw wrap(new UriParserSemanticException("Wrong number of key properties.",
- UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
- Integer.toString(lastKeyPredicates.size()), "1"));
- }
-
- // create the keylist
- List<UriParameterImpl> list = new ArrayList<UriParameterImpl>();
-
- // Find the keys not filled by referential constraints
- // and collect the other keys filled by referential constraints.
- String missedKey = null;
- for (String item : lastKeyPredicates) {
- String property = partner.getReferencingPropertyName(item);
- if (property != null) {
- list.add(new UriParameterImpl().setName(item).setReferencedProperty(property));
- } else {
- if (missedKey == null) {
- missedKey = item;
- } else {
- // two of more keys are missing
- throw wrap(new UriParserSemanticException("Not enough referential constraints defined",
- UriParserSemanticException.MessageKeys.NOT_ENOUGH_REFERENTIAL_CONSTRAINTS));
- }
- }
- }
-
- // 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) {
- // The client provided a list of key values pairs e.g. EntitySet(ID=1,Order=2)
- List<UriParameterImpl> list = new ArrayList<UriParameterImpl>();
-
- for (ParseTree c : ctx.vNVL.vlNVP) {
- list.add((UriParameterImpl) c.accept(this));
- }
-
- if (context.contextReadingFunctionParameters) {
- return list;
- }
-
- UriResource last = context.contextUriInfo.getLastResourcePart();
-
- // get type of last resource part
- if (!(last instanceof UriResourcePartTyped)) {
- throw wrap(new UriParserSemanticException("Parameters list on untyped resource path segment not allowed",
- UriParserSemanticException.MessageKeys.PARAMETERS_LIST_ONLY_FOR_TYPED_PARTS));
- }
- if (last instanceof UriResourceFunction) {
- final UriResourceFunction uriResourceFunction = (UriResourceFunction) context.contextUriInfo
- .getLastResourcePart();
- final EdmReturnType returnType = uriResourceFunction.getFunction().getReturnType();
-
- if (returnType.getType().getKind() != EdmTypeKind.ENTITY || !returnType.isCollection()) {
- throw wrap(new UriParserSemanticException("No keys allowed",
- UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED));
- } else {
- // The functions returns a collection of entities
- // Get the EDM Type and determine how many key predicates are needed.
- // In case of functions all key predicates must be provided by the client.
- final EdmEntityType entityType = (EdmEntityType) uriResourceFunction.getFunction().getReturnType().getType();
- final List<String> lastKeyPredicates = entityType.getKeyPredicateNames();
-
- if (lastKeyPredicates.size() == list.size()) {
- return list;
- } else {
- throw wrap(new UriParserSemanticException("Wrong number of key properties.",
- UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
- Integer.toString(lastKeyPredicates.size()), "1"));
- }
- }
- } else {
- // Handle entity sets
- EdmEntityType lastType = (EdmEntityType) ((UriResourcePartTyped) last).getType();
-
- // get list of keys for lastType
- List<String> 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 constraints
- // for using referential constraints the last resource part must be a navigation property
- if (!(context.contextUriInfo.getLastResourcePart() instanceof UriResourceNavigationPropertyImpl)) {
- throw wrap(new UriParserSemanticException("Wrong number of key properties.",
- UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
- Integer.toString(lastKeyPredicates.size()), Integer.toString(list.size())));
- }
- UriResourceNavigationPropertyImpl lastNav = (UriResourceNavigationPropertyImpl) last;
-
- // get the partner of the navigation property
- EdmNavigationProperty partner = lastNav.getProperty().getPartner();
- if (partner == null) {
- throw wrap(new UriParserSemanticException("Wrong number of key properties.",
- UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
- Integer.toString(lastKeyPredicates.size()), Integer.toString(list.size())));
- }
-
- // fill missing keys from referential constraints
- 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).setReferencedProperty(property));
- }
- }
- }
-
- // check again if all key predicates are filled from the URI
- if (list.size() == lastKeyPredicates.size()) {
- return list;
- } else {
- throw wrap(new UriParserSemanticException("Wrong number of key properties.",
- UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
- Integer.toString(lastKeyPredicates.size()), Integer.toString(list.size())));
- }
- }
- } else {
- // No key predicates are provided by the client
-
- if (context.contextReadingFunctionParameters) {
- return Collections.emptyList();
- } else {
- final UriResource last = context.contextUriInfo.getLastResourcePart();
- final int number = last instanceof UriResourcePartTyped ? ((EdmEntityType) ((UriResourcePartTyped) last)
- .getType()).getKeyPredicateNames().size() : 0;
- throw wrap(new UriParserSemanticException("Wrong number of key properties.",
- UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES, Integer.toString(number), "0"));
- }
- }
- }
-
- @Override
- public UriParameterImpl visitNameValuePair(final NameValuePairContext ctx) {
- UriParameterImpl uriParameter = new UriParameterImpl();
- uriParameter.setName(ctx.vODI.getText());
-
- if (ctx.vCOM != null) {
- final String text = ctx.vCOM.getText();
- uriParameter.setText("null".equals(text) ? null : text);
- uriParameter.setExpression((Expression) ctx.vCOM.accept(this));
- } else {
- uriParameter.setAlias("@" + ctx.vALI.getText());
- }
-
- return uriParameter;
- }
-
- @Override
- public Object visitNaninfinityLiteral(final NaninfinityLiteralContext ctx) {
- return new LiteralImpl(ctx.getText(),
- EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal));
- }
-
- @Override
- public Expression visitNowMethodCallExpr(final NowMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.NOW, null);
- }
-
- @Override
- public Object visitNullruleLiteral(final NullruleLiteralContext ctx) {
- return new LiteralImpl("null", null);
- }
-
- @Override
- public Object visitOrderBy(final OrderByContext ctx) {
-
- OrderByOptionImpl orderBy = new OrderByOptionImpl();
-
- for (OrderByItemContext item : ((OrderListContext) ctx.getChild(2)).vlOI) {
- OrderByItemImpl oItem = (OrderByItemImpl) item.accept(this);
- orderBy.addOrder(oItem);
- }
-
- return orderBy;
- }
-
- @Override
- public Object visitOrderByEOF(final OrderByEOFContext ctx) {
- context.contextReadingQueryPart = true;
-
- OrderByOptionImpl orderBy = new OrderByOptionImpl();
-
- for (OrderByItemContext item : ((OrderListContext) ctx.getChild(0)).vlOI) {
- OrderByItemImpl oItem = (OrderByItemImpl) item.accept(this);
- orderBy.addOrder(oItem);
- }
-
- context.contextReadingFunctionParameters = false;
- return orderBy;
- }
-
- @Override
- public Object visitOrderByItem(final OrderByItemContext ctx) {
- OrderByItemImpl oItem = new OrderByItemImpl();
- if (ctx.vD != null) {
- oItem.setDescending(true);
- }
-
- oItem.setExpression((Expression) ctx.vC.accept(this));
- return oItem;
- }
-
- @Override
- public Object visitPathSegment(final PathSegmentContext ctx) {
- readResourcePathSegment(ctx);
- /*
- * if (contextUriInfo.getLastResourcePart() == null ||
- * contextUriInfo.getLastResourcePart() instanceof UriResourceRootImpl) {
- *
- * } else {
- * readNextPathInfoSegment(ctx);
- * }
- */
- UriResourceImpl pathInfoSegment = (UriResourceImpl) context.contextUriInfo.getLastResourcePart();
-
- if (ctx.vlNVO.size() > 0) {
- // check for keyPredicates
- if (pathInfoSegment instanceof UriResourceWithKeysImpl) {
- if (ctx.vlNVO.size() > 1) {
- throw wrap(new UriParserSemanticException("More than one key predicates found",
- UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES, "1",
- Integer.toString(ctx.vlNVO.size())));
- }
-
- @SuppressWarnings("unchecked")
- List<UriParameter> list = (List<UriParameter>) ctx.vlNVO.get(0).accept(this);
- ((UriResourceWithKeysImpl) pathInfoSegment)
- .setKeyPredicates(list);
- } else {
- throw wrap(new UriParserSemanticException("Key properties not allowed",
- UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED));
- }
- }
-
- return pathInfoSegment;
- }
-
- @Override
- public Object visitPathSegments(final PathSegmentsContext ctx) {
- // path segment
- for (PathSegmentContext it : ctx.vlPS) {
- it.accept(this);
- }
-
- // const segment
- if (ctx.vCS != null) {
- ctx.vCS.accept(this);
- }
- return null;
- }
-
- @Override
- public Object visitPrimitiveLiteral(final PrimitiveLiteralContext ctx) {
- ParseTree child1 = ctx.children.get(0);
-
- if (child1 instanceof EnumLiteralContext
- || child1 instanceof BooleanNonCaseLiteralContext
- || child1 instanceof NullruleLiteralContext
- || child1 instanceof NaninfinityLiteralContext
- || child1 instanceof StringLiteralContext
- || child1 instanceof IntLiteralContext
- || child1 instanceof BinaryLiteralContext
- || child1 instanceof DateLiteralContext
- || child1 instanceof DatetimeoffsetLiteralContext
- || child1 instanceof DurationLiteralContext
- || child1 instanceof GuidLiteralContext
- || child1 instanceof TimeofdayLiteralContext
- || child1 instanceof DecimalLiteralContext
- || child1 instanceof BinaryLiteralContext) {
- return child1.accept(this);
- }
-
- // TODO Implement geography types and set a proper type
- return new LiteralImpl(ctx.getText(), null);
- }
-
- @Override
- public Object visitBinaryLiteral(BinaryLiteralContext ctx) {
- return new LiteralImpl(ctx.getText(),
- EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Binary));
- }
-
- @Override
- public Object visitStringLiteral(final StringLiteralContext ctx) {
- return new LiteralImpl(ctx.getText(),
- EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.String));
- }
-
- @Override
- public Object visitDecimalLiteral(final DecimalLiteralContext ctx) {
- final EdmType type = EdmPrimitiveTypeFactory.getInstance(
- ctx.getText().contains("e") || ctx.getText().contains("E") ?
- EdmPrimitiveTypeKind.Double :
- EdmPrimitiveTypeKind.Decimal);
-
- return new LiteralImpl(ctx.getText(), type);
- }
-
- @Override
- public Object visitIntLiteral(final IntLiteralContext ctx) {
- EdmPrimitiveTypeKind typeKind = null;
- try {
- final long value = Long.parseLong(ctx.getText());
- if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) {
- typeKind = EdmPrimitiveTypeKind.SByte;
- } else if (value >= 0 && value <= 255) {
- typeKind = EdmPrimitiveTypeKind.Byte;
- } else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) {
- typeKind = EdmPrimitiveTypeKind.Int16;
- } else if (value >= Integer.MIN_VALUE && value <= Integer.MAX_VALUE) {
- typeKind = EdmPrimitiveTypeKind.Int32;
- } else {
- typeKind = EdmPrimitiveTypeKind.Int64;
- }
- } catch (NumberFormatException e) {
- return new LiteralImpl(ctx.getText(),
- EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal));
- }
- return new LiteralImpl(ctx.getText(),
- EdmPrimitiveTypeFactory.getInstance(typeKind));
- }
-
- @Override
- public Object visitDateLiteral(final DateLiteralContext ctx) {
- return new LiteralImpl(ctx.getText(),
- EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Date));
- }
-
- @Override
- public Object visitDatetimeoffsetLiteral(final DatetimeoffsetLiteralContext ctx) {
- return new LiteralImpl(ctx.getText(),
- EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.DateTimeOffset));
- }
-
- @Override
- public Object visitDurationLiteral(final DurationLiteralContext ctx) {
- return new LiteralImpl(ctx.getText(),
- EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Duration));
- }
-
- @Override
- public Object visitGuidLiteral(final GuidLiteralContext ctx) {
- return new LiteralImpl(ctx.getText(),
- EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Guid));
- }
-
- @Override
- public Object visitTimeofdayLiteral(final TimeofdayLiteralContext ctx) {
- return new LiteralImpl(ctx.getText(),
- EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.TimeOfDay));
- }
-
- @Override
- public Object visitQueryOptions(final QueryOptionsContext ctx) {
-
- List<QueryOptionImpl> qpList = new ArrayList<QueryOptionImpl>();
- for (QueryOptionContext entityOption : ctx.vlQO) {
- qpList.add((QueryOptionImpl) entityOption.accept(this));
- }
-
- return qpList;
- }
-
- @Override
- public Object visitRootExpr(final RootExprContext ctx) {
-
- UriResource lastResource = context.contextUriInfo.getLastResourcePart();
-
- if (!(lastResource instanceof UriResourcePartTyped)) {
- throw wrap(new UriParserSemanticException("Resource path not typed",
- UriParserSemanticException.MessageKeys.RESOURCE_PATH_NOT_TYPED));
- }
-
- UriResourcePartTyped lastType = (UriResourcePartTyped) lastResource;
-
- UriResourceRootImpl pathInfoRoot = new UriResourceRootImpl(
- ParserHelper.getTypeInformation(lastType),
- lastType.isCollection());
-
- UriInfoImpl uriInfoImplpath = new UriInfoImpl().setKind(UriInfoKind.resource);
- uriInfoImplpath.addResourcePart(pathInfoRoot);
-
- if (ctx.vPs != null) {
- // store the context uriInfoPath
- UriInfoImpl backupUriInfoPath = context.contextUriInfo;
-
- // set temporary uriInfoPath to collect the path information of the memberExpression
- context.contextUriInfo = uriInfoImplpath;
-
- ctx.vPs.accept(this);
-
- context.contextUriInfo = backupUriInfoPath;
-
- }
- return new MemberImpl(uriInfoImplpath, null);
-
- }
-
- @Override
- public Expression visitRoundMethodCallExpr(final RoundMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.ROUND, Collections.singletonList((Expression) ctx.vE1.accept(this)));
- }
-
- @Override
- public Expression visitSecondMethodCallExpr(final SecondMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.SECOND, Collections.singletonList((Expression) ctx.vE1.accept(this)));
- }
-
- @Override
- public Object visitSelect(final SelectContext ctx) {
- List<SelectItem> selectItems = new ArrayList<SelectItem>();
- for (SelectItemContext si : ctx.vlSI) {
- selectItems.add((SelectItem) si.accept(this));
- }
-
- return new SelectOptionImpl().setSelectItems(selectItems).setText(ctx.children.get(2).getText());
- }
-
- @Override
- public Object visitSelectEOF(final SelectEOFContext ctx) {
- context.contextReadingQueryPart = true;
- List<SelectItem> selectItems = new ArrayList<SelectItem>();
- for (SelectItemContext si : ctx.vlSI) {
- selectItems.add((SelectItem) si.accept(this));
- }
-
- final QueryOptionImpl result = new SelectOptionImpl().setSelectItems(selectItems).setText(ctx.getText());
- context.contextReadingQueryPart = false;
-
- return result;
- }
-
- @Override
- public Object visitSelectItem(final SelectItemContext ctx) {
- SelectItemImpl selectItem = new SelectItemImpl();
-
- context.contextSelectItem = selectItem;
- for (SelectSegmentContext si : ctx.vlSS) {
- si.accept(this);
- }
- context.contextSelectItem = null;
-
- return selectItem;
- }
-
- @Override
- public Object visitSelectSegment(final SelectSegmentContext ctx) {
-
- if (ctx.vS != null) {
- if (ctx.vNS != null) {
- String namespace = ctx.vNS.getText();
- namespace = namespace.substring(0, namespace.length() - 1);
- FullQualifiedName fullName = new FullQualifiedName(namespace, "*");
- context.contextSelectItem.addAllOperationsInSchema(fullName);
- } else {
- context.contextSelectItem.setStar(true);
- }
- return null;
- }
-
- String odi = ctx.vODI.getText();
- if (ctx.vNS == null) {
-
- EdmType prevType = null;
- if (context.contextSelectItem.getResourcePath() == null) {
- prevType = context.contextTypes.peek();
- } else {
- UriInfoImpl uriInfo = (UriInfoImpl) context.contextSelectItem.getResourcePath();
- UriResource last = uriInfo.getLastResourcePart();
-
- prevType = ParserHelper.getTypeInformation((UriResourcePartTyped) last);
- if (prevType == null) {
- throw wrap(new UriParserSemanticException("prev segment not typed",
- UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PARTS, "select"));
- }
- }
-
- if (!(prevType instanceof EdmStructuredType)) {
- throw wrap(new UriParserSemanticException("Previous select item is not a structural type",
- UriParserSemanticException.MessageKeys.ONLY_FOR_STRUCTURAL_TYPES, "select"));
<TRUNCATED>
[20/30] olingo-odata4 git commit: [OLINGO-834] $expand parser in Java
+ clean-up
Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestLexer.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestLexer.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestLexer.java
index 6df6759..6102fd8 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestLexer.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestLexer.java
@@ -18,16 +18,22 @@
*/
package org.apache.olingo.server.core.uri.antlr;
-import org.antlr.v4.runtime.Lexer;
-import org.apache.olingo.server.core.uri.testutil.TokenValidator;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.olingo.server.core.uri.parser.UriTokenizer;
+import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind;
import org.junit.Test;
+/**
+ * Tests originally written for the ANTLR lexer.
+ */
public class TestLexer {
private TokenValidator test = null;
- private static final String cPCT_ENCODED = "%45%46%47" + "%22" + "%5C";// last two chars are not in
- // cPCT_ENCODED_UNESCAPED
+ // The last two chars are not in cPCT_ENCODED_UNESCAPED.
+ private static final String cPCT_ENCODED = "%45%46%47" + "%22" + "%5C";
private static final String cUNRESERVED = "ABCabc123-._~";
private static final String cOTHER_DELIMS = "!()*+,;";
private static final String cSUB_DELIMS = "$&'=" + cOTHER_DELIMS;
@@ -39,265 +45,279 @@ public class TestLexer {
}
@Test
- public void test() {
-
- // test.log(1).run("ESAllPrim?$orderby=PropertyDouble eq 3.5E+38");
+ public void unary() {
+ test.run("-a eq a").has(TokenKind.MinusOperator, TokenKind.ODataIdentifier, TokenKind.EqualsOperator,
+ TokenKind.ODataIdentifier).isInput();
}
- // ;------------------------------------------------------------------------------
- // ; 0. URI
- // ;------------------------------------------------------------------------------
-
@Test
- public void testUnary() {
- test.run("- a eq a").isAllInput();
+ public void uriTokens() {
+// test.run("#").isType(TokenKind.FRAGMENT).isInput();
+ test.run("$count").has(TokenKind.COUNT).isInput();
+ test.run("$ref").has(TokenKind.REF).isInput();
+ test.run("$value").has(TokenKind.VALUE).isInput();
}
@Test
- public void testUriTokens() {
- test.globalMode(UriLexer.MODE_QUERY);
- test.run("#").isText("#").isType(UriLexer.FRAGMENT);
- test.run("$count").isText("$count").isType(UriLexer.COUNT);
- test.run("$ref").isText("$ref").isType(UriLexer.REF);
- test.run("$value").isText("$value").isType(UriLexer.VALUE);
+ public void queryOptionsTokens() {
+ test.run("$skip=1").has(TokenKind.SKIP, TokenKind.EQ, TokenKind.IntegerValue).isInput();
+ test.run("$skip=2").has(TokenKind.SKIP, TokenKind.EQ, TokenKind.IntegerValue).isInput();
+ test.run("$skip=123").has(TokenKind.SKIP, TokenKind.EQ, TokenKind.IntegerValue).isInput();
+
+ test.run("$top=1").has(TokenKind.TOP, TokenKind.EQ, TokenKind.IntegerValue).isInput();
+ test.run("$top=2").has(TokenKind.TOP, TokenKind.EQ, TokenKind.IntegerValue).isInput();
+ test.run("$top=123").has(TokenKind.TOP, TokenKind.EQ, TokenKind.IntegerValue).isInput();
+
+ test.run("$levels=1").has(TokenKind.LEVELS, TokenKind.EQ, TokenKind.IntegerValue).isInput();
+ test.run("$levels=2").has(TokenKind.LEVELS, TokenKind.EQ, TokenKind.IntegerValue).isInput();
+ test.run("$levels=123").has(TokenKind.LEVELS, TokenKind.EQ, TokenKind.IntegerValue).isInput();
+ test.run("$levels=max").has(TokenKind.LEVELS, TokenKind.EQ, TokenKind.MAX).isInput();
+
+// test.run("$format=atom").has(TokenKind.FORMAT, TokenKind.EQ, TokenKind.ODataIdentifier).isInput();
+// test.run("$format=json").has(TokenKind.FORMAT, TokenKind.EQ, TokenKind.ODataIdentifier).isInput();
+// test.run("$format=xml").has(TokenKind.FORMAT,, TokenKind.EQ, TokenKind.ODataIdentifier).isInput();
+// test.run("$format=abc/def").has(TokenKind.FORMAT, TokenKind.EQ,
+// TokenKind.ODataIdentifier, TokenKind.SLASH, TokenKind.ODataIdentifier).isInput();
+
+// test.run("$id=123").has(TokenKind.ID, TokenKind.EQ, TokenKind.IntegerValue).isInput();
+// test.run("$id=ABC").has(TokenKind.ID, TokenKind.EQ, TokenKind.ODataIdentifier).isInput();
+
+// test.run("$skiptoken=ABC").has(TokenKind.SKIPTOKEN, TokenKind.EQ, TokenKind.ODataIdentifier).isInput();
+// test.run("$skiptoken=ABC").has(TokenKind.SKIPTOKEN, TokenKind.EQ, TokenKind.ODataIdentifier).isInput();
+
+ test.run("$search=\"ABC\"").has(TokenKind.SEARCH, TokenKind.EQ, TokenKind.Phrase).isInput();
+ test.run("$search=ABC").has(TokenKind.SEARCH, TokenKind.EQ, TokenKind.Word).isInput();
+ test.run("$search=\"A%20B%20C\"").has(TokenKind.SEARCH, TokenKind.EQ, TokenKind.Phrase).isInput();
+ test.run("$search=Test Test").has(TokenKind.SEARCH, TokenKind.EQ, TokenKind.Word,
+ TokenKind.AndOperatorSearch, TokenKind.Word).isInput();
+ test.run("$search=Test&$filter=ABC eq 1").has(TokenKind.SEARCH, TokenKind.EQ, TokenKind.Word);
}
- // ;------------------------------------------------------------------------------
- // ; 2. Query Options
- // ;------------------------------------------------------------------------------
@Test
- public void testQueryOptionsTokens() {
-
- test.globalMode(UriLexer.MODE_QUERY);
- test.run("$skip=1").isAllText("$skip=1").isType(UriLexer.SKIP_QO);
- test.run("$skip=2").isAllText("$skip=2").isType(UriLexer.SKIP_QO);
- test.run("$skip=123").isAllText("$skip=123").isType(UriLexer.SKIP_QO);
-
- test.run("$top=1").isAllText("$top=1").isType(UriLexer.TOP);
- test.run("$top=2").isAllText("$top=2").isType(UriLexer.TOP);
- test.run("$top=123").isAllText("$top=123").isType(UriLexer.TOP);
-
- test.run("$levels=1").isAllText("$levels=1").isType(UriLexer.LEVELS);
- test.run("$levels=2").isAllText("$levels=2").isType(UriLexer.LEVELS);
- test.run("$levels=123").isAllText("$levels=123").isType(UriLexer.LEVELS);
- test.run("$levels=max").isAllText("$levels=max").isType(UriLexer.LEVELS);
-
- test.run("$format=atom").isAllText("$format=atom").isType(UriLexer.FORMAT);
- test.run("$format=json").isAllText("$format=json").isType(UriLexer.FORMAT);
- test.run("$format=xml").isAllText("$format=xml").isType(UriLexer.FORMAT);
- test.run("$format=abc/def").isAllText("$format=abc/def").isType(UriLexer.FORMAT);
-
- test.run("$id=123").isAllText("$id=123").isType(UriLexer.ID);
- test.run("$id=ABC").isAllText("$id=ABC").isType(UriLexer.ID);
-
- test.run("$skiptoken=ABC").isAllText("$skiptoken=ABC").isType(UriLexer.SKIPTOKEN);
- test.run("$skiptoken=ABC").isAllText("$skiptoken=ABC").isType(UriLexer.SKIPTOKEN);
-
- test.run("$search=\"ABC\"").isAllText("$search=\"ABC\"").isType(UriLexer.SEARCH);
- test.run("$search=ABC").isAllText("$search=ABC").isType(UriLexer.SEARCH);
- test.run("$search=\"A%20B%20C\"").isAllText("$search=\"A%20B%20C\"").isType(UriLexer.SEARCH);
- test.run("$search=Test Test").isAllText("$search=Test Test").isType(UriLexer.SEARCH);
- test.run("$search=Test&$filter=ABC eq 1").isAllText("$search=Test&$filter=ABC eq 1").isType(UriLexer.SEARCH);
- }
-
- @Test
- public void testQueryOptionsDefaultMode() {
- // First set query mode, than use expand(switches to default mode) and use nested system query options
- test.globalMode(UriLexer.MODE_QUERY);
- test.run("$expand=ABC($skip=1)").isAllText("$expand=ABC($skip=1)").at(4).isType(UriLexer.SKIP_QO);
- test.run("$expand=ABC($skip=2)").isAllText("$expand=ABC($skip=2)").at(4).isType(UriLexer.SKIP_QO);
- test.run("$expand=ABC($skip=123)").isAllText("$expand=ABC($skip=123)").at(4).isType(UriLexer.SKIP_QO);
- test.run("$expand=ABC($search=abc)").isAllText("$expand=ABC($search=abc)").at(4).isType(UriLexer.SEARCH_INLINE);
- test.run("$expand=ABC($search=\"123\")").isAllText("$expand=ABC($search=\"123\")")
- .at(4).isType(UriLexer.SEARCH_INLINE)
- .at(6).isType(UriLexer.SEARCHPHRASE);
- test.run("$expand=ABC($top=1)").isAllText("$expand=ABC($top=1)").at(4).isType(UriLexer.TOP);
- test.run("$expand=ABC($top=2)").isAllText("$expand=ABC($top=2)").at(4).isType(UriLexer.TOP);
- test.run("$expand=ABC($top=123)").isAllText("$expand=ABC($top=123)").at(4).isType(UriLexer.TOP);
-
- test.run("$expand=ABC($expand=DEF($skip=1))").isAllText("$expand=ABC($expand=DEF($skip=1))")
- .at(8).isType(UriLexer.SKIP_QO);
- test.run("$expand=ABC($expand=DEF($skip=2))").isAllText("$expand=ABC($expand=DEF($skip=2))")
- .at(8).isType(UriLexer.SKIP_QO);
- test.run("$expand=ABC($expand=DEF($skip=123))").isAllText("$expand=ABC($expand=DEF($skip=123))")
- .at(8).isType(UriLexer.SKIP_QO);
-
- test.run("$expand=ABC($expand=DEF($top=1))").isAllText("$expand=ABC($expand=DEF($top=1))")
- .at(8).isType(UriLexer.TOP);
- test.run("$expand=ABC($expand=DEF($top=2))").isAllText("$expand=ABC($expand=DEF($top=2))")
- .at(8).isType(UriLexer.TOP);
- test.run("$expand=ABC($expand=DEF($top=123))").isAllText("$expand=ABC($expand=DEF($top=123))")
- .at(8).isType(UriLexer.TOP);
- test.run("$expand=ABC($expand=DEF($search=Test Test))").isAllText("$expand=ABC($expand=DEF($search=Test Test))")
- .at(8).isType(UriLexer.SEARCH_INLINE)
- .at(10).isType(UriLexer.SEARCHWORD)
- .at(12).isType(UriLexer.SEARCHWORD);
+ public void queryOptionsDefaultMode() {
+ test.run("$expand=ABC($skip=1)").has(TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.SKIP, TokenKind.EQ, TokenKind.IntegerValue, TokenKind.CLOSE).isInput();
+ test.run("$expand=ABC($skip=123)").has(TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.SKIP, TokenKind.EQ, TokenKind.IntegerValue, TokenKind.CLOSE).isInput();
+ test.run("$expand=ABC($search=abc)").has(TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.SEARCH, TokenKind.EQ, TokenKind.Word, TokenKind.CLOSE).isInput();
+ test.run("$expand=ABC($search=\"123\")").has(TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.SEARCH, TokenKind.EQ, TokenKind.Phrase, TokenKind.CLOSE).isInput();
+ test.run("$expand=ABC($top=1)").has(TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.TOP, TokenKind.EQ, TokenKind.IntegerValue, TokenKind.CLOSE).isInput();
+ test.run("$expand=ABC($top=123)").has(TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.TOP, TokenKind.EQ, TokenKind.IntegerValue, TokenKind.CLOSE).isInput();
+
+ test.run("$expand=ABC($expand=DEF($skip=1))").has(TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.SKIP, TokenKind.EQ, TokenKind.IntegerValue, TokenKind.CLOSE, TokenKind.CLOSE)
+ .isInput();
+ test.run("$expand=ABC($expand=DEF($skip=123))").has(TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.SKIP, TokenKind.EQ, TokenKind.IntegerValue, TokenKind.CLOSE, TokenKind.CLOSE)
+ .isInput();
+
+ test.run("$expand=ABC($expand=DEF($top=1))").has(TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.TOP, TokenKind.EQ, TokenKind.IntegerValue, TokenKind.CLOSE, TokenKind.CLOSE)
+ .isInput();
+ test.run("$expand=ABC($expand=DEF($top=123))").has(TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.TOP, TokenKind.EQ, TokenKind.IntegerValue, TokenKind.CLOSE, TokenKind.CLOSE)
+ .isInput();
+
+ test.run("$expand=ABC($expand=DEF($search=Test Test))")
+ .has(TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.SEARCH, TokenKind.EQ, TokenKind.Word,
+ TokenKind.AndOperatorSearch, TokenKind.Word, TokenKind.CLOSE, TokenKind.CLOSE)
+ .isInput();
test.run("$expand=ABC($expand=DEF($search=\"Test\" \"Test\"))")
- .isAllText("$expand=ABC($expand=DEF($search=\"Test\" \"Test\"))")
- .at(8).isType(UriLexer.SEARCH_INLINE)
- .at(10).isType(UriLexer.SEARCHPHRASE)
- .at(12).isType(UriLexer.SEARCHPHRASE);
+ .has(TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.SEARCH, TokenKind.EQ, TokenKind.Phrase,
+ TokenKind.AndOperatorSearch, TokenKind.Phrase, TokenKind.CLOSE, TokenKind.CLOSE)
+ .isInput();
test.run("$expand=ABC($expand=DEF($search=\"Test\" \"Test\";$filter=PropertyInt16 eq 0;$orderby=PropertyInt16))")
- .isAllText("$expand=ABC($expand=DEF($search=\"Test\" \"Test\";$filter=PropertyInt16 " +
- "eq 0;$orderby=PropertyInt16))")
- .at(8).isType(UriLexer.SEARCH_INLINE)
- .at(10).isType(UriLexer.SEARCHPHRASE)
- .at(12).isType(UriLexer.SEARCHPHRASE)
- .at(13).isType(UriLexer.SEMI)
- .at(14).isType(UriLexer.FILTER)
- .at(22).isType(UriLexer.ORDERBY);
+ .has(TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.SEARCH, TokenKind.EQ, TokenKind.Phrase,
+ TokenKind.AndOperatorSearch, TokenKind.Phrase, TokenKind.SEMI,
+ TokenKind.FILTER, TokenKind.EQ, TokenKind.ODataIdentifier, TokenKind.EqualsOperator,
+ TokenKind.IntegerValue, TokenKind.SEMI,
+ TokenKind.ORDERBY, TokenKind.EQ, TokenKind.ODataIdentifier, TokenKind.CLOSE, TokenKind.CLOSE)
+ .isInput();
}
-
- // ;------------------------------------------------------------------------------
- // ; 4. Expressions
- // ;------------------------------------------------------------------------------
- @Test
- public void testQueryExpressions() {
- test.globalMode(Lexer.DEFAULT_MODE);
-
- test.run("$it").isText("$it").isType(UriLexer.IT);
-
- test.run("$filter=contains(").at(2).isText("contains(").isType(UriLexer.CONTAINS_WORD);
-
- test.run("$filter=containsabc").at(2).isText("containsabc")
- .isType(UriLexer.ODATAIDENTIFIER); // test that this is a ODI
-
- test.run("$filter=startswith(").at(2).isText("startswith(").isType(UriLexer.STARTSWITH_WORD);
- test.run("$filter=endswith(").at(2).isText("endswith(").isType(UriLexer.ENDSWITH_WORD);
- test.run("$filter=length(").at(2).isText("length(").isType(UriLexer.LENGTH_WORD);
- test.run("$filter=indexof(").at(2).isText("indexof(").isType(UriLexer.INDEXOF_WORD);
- test.run("$filter=substring(").at(2).isText("substring(").isType(UriLexer.SUBSTRING_WORD);
- test.run("$filter=tolower(").at(2).isText("tolower(").isType(UriLexer.TOLOWER_WORD);
- test.run("$filter=toupper(").at(2).isText("toupper(").isType(UriLexer.TOUPPER_WORD);
- test.run("$filter=trim(").at(2).isText("trim(").isType(UriLexer.TRIM_WORD);
- test.run("$filter=concat(").at(2).isText("concat(").isType(UriLexer.CONCAT_WORD);
+ @Test
+ public void queryExpressions() {
+ test.run("$it").has(TokenKind.IT).isText("$it");
+
+ test.run("$filter=contains(").has(TokenKind.FILTER, TokenKind.EQ, TokenKind.ContainsMethod).isText("contains(");
+
+ test.run("$filter=containsabc").has(TokenKind.FILTER, TokenKind.EQ, TokenKind.ODataIdentifier)
+ .isText("containsabc");
+
+ test.run("$filter=startswith(").has(TokenKind.FILTER, TokenKind.EQ, TokenKind.StartswithMethod)
+ .isText("startswith(");
+ test.run("$filter=endswith(").has(TokenKind.FILTER, TokenKind.EQ, TokenKind.EndswithMethod).isText("endswith(");
+ test.run("$filter=length(").has(TokenKind.FILTER, TokenKind.EQ, TokenKind.LengthMethod).isText("length(");
+ test.run("$filter=indexof(").has(TokenKind.FILTER, TokenKind.EQ, TokenKind.IndexofMethod).isText("indexof(");
+ test.run("$filter=substring(").has(TokenKind.FILTER, TokenKind.EQ, TokenKind.SubstringMethod).isText("substring(");
+ test.run("$filter=tolower(").has(TokenKind.FILTER, TokenKind.EQ, TokenKind.TolowerMethod).isText("tolower(");
+ test.run("$filter=toupper(").has(TokenKind.FILTER, TokenKind.EQ, TokenKind.ToupperMethod).isText("toupper(");
+ test.run("$filter=trim(").has(TokenKind.FILTER, TokenKind.EQ, TokenKind.TrimMethod).isText("trim(");
+ test.run("$filter=concat(").has(TokenKind.FILTER, TokenKind.EQ, TokenKind.ConcatMethod).isText("concat(");
}
- // ;------------------------------------------------------------------------------
- // ; 7. Literal Data Values
- // ;------------------------------------------------------------------------------
-
@Test
- public void testLiteralDataValues() {
- test.globalMode(Lexer.DEFAULT_MODE);
+ public void literalDataValues() {
// null
- test.run("null").isInput().isType(UriLexer.NULLVALUE);
+ test.run("null").has(TokenKind.NULL).isInput();
// binary
- test.run("binary'ABCD'").isInput().isType(UriLexer.BINARY);
- test.run("BiNaRy'ABCD'").isInput().isType(UriLexer.BINARY);
+ test.run("binary'ABCD'").has(TokenKind.BinaryValue).isInput();
+ test.run("BiNaRy'ABCD'").has(TokenKind.BinaryValue).isInput();
// boolean
- test.run("true").isInput().isType(UriLexer.TRUE);
- test.run("false").isInput().isType(UriLexer.FALSE);
- test.run("TrUe").isInput().isType(UriLexer.BOOLEAN);
- test.run("FaLsE").isInput().isType(UriLexer.BOOLEAN);
+ test.run("true").has(TokenKind.BooleanValue).isInput();
+ test.run("false").has(TokenKind.BooleanValue).isInput();
+ test.run("TrUe").has(TokenKind.BooleanValue).isInput();
+ test.run("FaLsE").has(TokenKind.BooleanValue).isInput();
// Lexer rule INT
- test.run("123").isInput().isType(UriLexer.INT);
- test.run("123456789").isInput().isType(UriLexer.INT);
- test.run("+123").isInput().isType(UriLexer.INT);
- test.run("+123456789").isInput().isType(UriLexer.INT);
- test.run("-123").isInput().isType(UriLexer.INT);
- test.run("-123456789").isInput().isType(UriLexer.INT);
+ test.run("123").has(TokenKind.IntegerValue).isInput();
+ test.run("123456789").has(TokenKind.IntegerValue).isInput();
+ test.run("+123").has(TokenKind.IntegerValue).isInput();
+ test.run("+123456789").has(TokenKind.IntegerValue).isInput();
+ test.run("-123").has(TokenKind.IntegerValue).isInput();
+ test.run("-123456789").has(TokenKind.IntegerValue).isInput();
// Lexer rule DECIMAL
- test.run("0.1").isInput().isType(UriLexer.DECIMAL);
- test.run("1.1").isInput().isType(UriLexer.DECIMAL);
- test.run("+0.1").isInput().isType(UriLexer.DECIMAL);
- test.run("+1.1").isInput().isType(UriLexer.DECIMAL);
- test.run("-0.1").isInput().isType(UriLexer.DECIMAL);
- test.run("-1.1").isInput().isType(UriLexer.DECIMAL);
+ test.run("0.1").has(TokenKind.DecimalValue).isInput();
+ test.run("1.1").has(TokenKind.DecimalValue).isInput();
+ test.run("+0.1").has(TokenKind.DecimalValue).isInput();
+ test.run("+1.1").has(TokenKind.DecimalValue).isInput();
+ test.run("-0.1").has(TokenKind.DecimalValue).isInput();
+ test.run("-1.1").has(TokenKind.DecimalValue).isInput();
// Lexer rule EXP
- test.run("1.1e+1").isInput().isType(UriLexer.DECIMAL);
- test.run("1.1e-1").isInput().isType(UriLexer.DECIMAL);
+ test.run("1.1e+1").has(TokenKind.DoubleValue).isInput();
+ test.run("1.1e-1").has(TokenKind.DoubleValue).isInput();
- test.run("NaN").isInput().isType(UriLexer.NANINFINITY);
- test.run("-INF").isInput().isType(UriLexer.NANINFINITY);
- test.run("INF").isInput().isType(UriLexer.NANINFINITY);
+ test.run("NaN").has(TokenKind.DoubleValue).isInput();
+ test.run("-INF").has(TokenKind.DoubleValue).isInput();
+ test.run("INF").has(TokenKind.DoubleValue).isInput();
// Lexer rule GUID
- test.run("1234ABCD-12AB-23CD-45EF-123456780ABC").isInput().isType(UriLexer.GUID);
- test.run("1234ABCD-12AB-23CD-45EF-123456780ABC").isInput().isType(UriLexer.GUID);
+ test.run("1234ABCD-12AB-23CD-45EF-123456780ABC").has(TokenKind.GuidValue).isInput();
+ test.run("1234ABCD-12AB-23CD-45EF-123456780ABC").has(TokenKind.GuidValue).isInput();
// Lexer rule DATE
- test.run("2013-11-15").isInput().isType(UriLexer.DATE);
+ test.run("2013-11-15").has(TokenKind.DateValue).isInput();
// Lexer rule DATETIMEOFFSET
- test.run("2013-11-15T13:35Z").isInput().isType(UriLexer.DATETIMEOFFSET);
- test.run("2013-11-15T13:35:10Z").isInput().isType(UriLexer.DATETIMEOFFSET);
- test.run("2013-11-15T13:35:10.1234Z").isInput().isType(UriLexer.DATETIMEOFFSET);
+ test.run("2013-11-15T13:35Z").has(TokenKind.DateTimeOffsetValue).isInput();
+ test.run("2013-11-15T13:35:10Z").has(TokenKind.DateTimeOffsetValue).isInput();
+ test.run("2013-11-15T13:35:10.1234Z").has(TokenKind.DateTimeOffsetValue).isInput();
- test.run("2013-11-15T13:35:10.1234+01:30").isInput().isType(UriLexer.DATETIMEOFFSET);
- test.run("2013-11-15T13:35:10.1234-01:12").isInput().isType(UriLexer.DATETIMEOFFSET);
+ test.run("2013-11-15T13:35:10.1234+01:30").has(TokenKind.DateTimeOffsetValue).isInput();
+ test.run("2013-11-15T13:35:10.1234-01:12").has(TokenKind.DateTimeOffsetValue).isInput();
- test.run("2013-11-15T13:35Z").isInput().isType(UriLexer.DATETIMEOFFSET);
+ test.run("2013-11-15T13:35Z").has(TokenKind.DateTimeOffsetValue).isInput();
// Lexer rule DURATION
- test.run("duration'PT67S'").isInput().isType(UriLexer.DURATION);
- test.run("duration'PT67.89S'").isInput().isType(UriLexer.DURATION);
-
- test.run("duration'PT5M'").isInput().isType(UriLexer.DURATION);
- test.run("duration'PT5M67S'").isInput().isType(UriLexer.DURATION);
- test.run("duration'PT5M67.89S'").isInput().isType(UriLexer.DURATION);
-
- test.run("duration'PT4H'").isInput().isType(UriLexer.DURATION);
- test.run("duration'PT4H67S'").isInput().isType(UriLexer.DURATION);
- test.run("duration'PT4H67.89S'").isInput().isType(UriLexer.DURATION);
- test.run("duration'PT4H5M'").isInput().isType(UriLexer.DURATION);
- test.run("duration'PT4H5M67S'").isInput().isType(UriLexer.DURATION);
- test.run("duration'PT4H5M67.89S'").isInput().isType(UriLexer.DURATION);
-
- test.run("duration'P3D'");
- test.run("duration'P3DT67S'").isInput().isType(UriLexer.DURATION);
- test.run("duration'P3DT67.89S'").isInput().isType(UriLexer.DURATION);
- test.run("duration'P3DT5M'").isInput().isType(UriLexer.DURATION);
- test.run("duration'P3DT5M67S'").isInput().isType(UriLexer.DURATION);
- test.run("duration'P3DT5M67.89S'").isInput().isType(UriLexer.DURATION);
- test.run("duration'P3DT4H'").isInput().isType(UriLexer.DURATION);
- test.run("duration'P3DT4H67S'").isInput().isType(UriLexer.DURATION);
- test.run("duration'P3DT4H67.89S'").isInput().isType(UriLexer.DURATION);
- test.run("duration'P3DT4H5M'").isInput().isType(UriLexer.DURATION);
- test.run("duration'P3DT4H5M67S'").isInput().isType(UriLexer.DURATION);
- test.run("duration'P3DT4H5M67.89S'").isInput().isType(UriLexer.DURATION);
-
- test.run("DuRaTiOn'P3DT4H5M67.89S'").isInput().isType(UriLexer.DURATION);
- test.run("DuRaTiOn'-P3DT4H5M67.89S'").isInput().isType(UriLexer.DURATION);
-
- test.run("20:00").isInput().isType(UriLexer.TIMEOFDAY);
- test.run("20:15:01").isInput().isType(UriLexer.TIMEOFDAY);
- test.run("20:15:01.02").isInput().isType(UriLexer.TIMEOFDAY);
-
- test.run("20:15:01.02").isInput().isType(UriLexer.TIMEOFDAY);
+ test.run("duration'PT67S'").has(TokenKind.DurationValue).isInput();
+ test.run("duration'PT67.89S'").has(TokenKind.DurationValue).isInput();
+
+ test.run("duration'PT5M'").has(TokenKind.DurationValue).isInput();
+ test.run("duration'PT5M67S'").has(TokenKind.DurationValue).isInput();
+ test.run("duration'PT5M67.89S'").has(TokenKind.DurationValue).isInput();
+
+ test.run("duration'PT4H'").has(TokenKind.DurationValue).isInput();
+ test.run("duration'PT4H67S'").has(TokenKind.DurationValue).isInput();
+ test.run("duration'PT4H67.89S'").has(TokenKind.DurationValue).isInput();
+ test.run("duration'PT4H5M'").has(TokenKind.DurationValue).isInput();
+ test.run("duration'PT4H5M67S'").has(TokenKind.DurationValue).isInput();
+ test.run("duration'PT4H5M67.89S'").has(TokenKind.DurationValue).isInput();
+
+ test.run("duration'P3D'").has(TokenKind.DurationValue).isInput();
+ test.run("duration'P3DT67S'").has(TokenKind.DurationValue).isInput();
+ test.run("duration'P3DT67.89S'").has(TokenKind.DurationValue).isInput();
+ test.run("duration'P3DT5M'").has(TokenKind.DurationValue).isInput();
+ test.run("duration'P3DT5M67S'").has(TokenKind.DurationValue).isInput();
+ test.run("duration'P3DT5M67.89S'").has(TokenKind.DurationValue).isInput();
+ test.run("duration'P3DT4H'").has(TokenKind.DurationValue).isInput();
+ test.run("duration'P3DT4H67S'").has(TokenKind.DurationValue).isInput();
+ test.run("duration'P3DT4H67.89S'").has(TokenKind.DurationValue).isInput();
+ test.run("duration'P3DT4H5M'").has(TokenKind.DurationValue).isInput();
+ test.run("duration'P3DT4H5M67S'").has(TokenKind.DurationValue).isInput();
+ test.run("duration'P3DT4H5M67.89S'").has(TokenKind.DurationValue).isInput();
+
+ test.run("DuRaTiOn'P3DT4H5M67.89S'").has(TokenKind.DurationValue).isInput();
+ test.run("DuRaTiOn'-P3DT4H5M67.89S'").has(TokenKind.DurationValue).isInput();
+
+ test.run("20:00").has(TokenKind.TimeOfDayValue).isInput();
+ test.run("20:15:01").has(TokenKind.TimeOfDayValue).isInput();
+ test.run("20:15:01.02").has(TokenKind.TimeOfDayValue).isInput();
+
+ test.run("20:15:01.02").has(TokenKind.TimeOfDayValue).isInput();
// String
- test.run("'ABC'").isText("'ABC'").isType(UriLexer.STRING);
- test.run("'A%20C'").isInput().isType(UriLexer.STRING);
- test.run("'%20%20%20ABC'").isInput().isType(UriLexer.STRING);
-
+ test.run("'ABC'").has(TokenKind.StringValue).isInput();
+ test.run("'A%20C'").has(TokenKind.StringValue).isInput();
+ test.run("'%20%20%20ABC'").has(TokenKind.StringValue).isInput();
}
@Test
- public void testDelims() {
- String reserved = "/";
- test.globalMode(UriLexer.MODE_QUERY);
+ public void delims() {
+ final String reserved = "/";
// Test lexer rule UNRESERVED
- test.run("$format=A/" + cUNRESERVED).isAllInput().isType(UriLexer.FORMAT);
- test.run("$format=A/" + cUNRESERVED + reserved).isType(UriLexer.FORMAT).at(4).isText(cUNRESERVED);
+// test.run("$format=A/" + cUNRESERVED).has(TokenKind.FORMAT).isInput();
+// test.run("$format=A/" + cUNRESERVED + reserved).has(TokenKind.FORMAT).isText(cUNRESERVED);
// Test lexer rule PCT_ENCODED
- test.run("$format=A/" + cPCT_ENCODED).isAllInput().isType(UriLexer.FORMAT);
- test.run("$format=A/" + cPCT_ENCODED + reserved).isType(UriLexer.FORMAT).at(4).isText(cPCT_ENCODED);
+// test.run("$format=A/" + cPCT_ENCODED).has(TokenKind.FORMAT).isInput();
+// test.run("$format=A/" + cPCT_ENCODED + reserved).has(TokenKind.FORMAT).isText(cPCT_ENCODED);
// Test lexer rule SUB_DELIMS
- test.run("$format=A/" + cSUB_DELIMS).isAllInput().isType(UriLexer.FORMAT);
- test.run("$format=A/" + cSUB_DELIMS + reserved).isType(UriLexer.FORMAT).at(4).isText("$");
+// test.run("$format=A/" + cSUB_DELIMS).has(TokenKind.FORMAT).isInput();
+// test.run("$format=A/" + cSUB_DELIMS + reserved).has(TokenKind.FORMAT).isText("$");
// Test lexer rule PCHAR rest
- test.run("$format=A/:@").isAllText("$format=A/:@").isType(UriLexer.FORMAT);
- test.run("$format=A/:@" + reserved).isType(UriLexer.FORMAT).at(4).isText(":@");
+// test.run("$format=A/:@").has(TokenKind.FORMAT).isInput();
+// test.run("$format=A/:@" + reserved).has(TokenKind.FORMAT).isText(":@");
// Test lexer rule PCHAR all
- test.run("$format=" + cPCHAR + "/" + cPCHAR).isAllInput().isType(UriLexer.FORMAT);
-
+// test.run("$format=" + cPCHAR + "/" + cPCHAR).has(TokenKind.FORMAT).isInput();
}
+ public class TokenValidator {
+
+ private String input = null;
+ private UriTokenizer tokenizer = null;
+ private String curText = null;
+
+ public TokenValidator run(final String uri) {
+ input = uri;
+ tokenizer = new UriTokenizer(uri);
+ curText = "";
+ return this;
+ }
+
+ public TokenValidator has(final TokenKind... expected) {
+ for (final TokenKind kind : expected) {
+ assertTrue(tokenizer.next(kind));
+ curText += tokenizer.getText();
+ }
+ return this;
+ }
+
+ public TokenValidator isText(final String expected) {
+ assertEquals(expected, tokenizer.getText());
+ return this;
+ }
+
+ public TokenValidator isInput() {
+ assertEquals(input, curText);
+ assertTrue(tokenizer.next(TokenKind.EOF));
+ return this;
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestUriParserImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestUriParserImpl.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestUriParserImpl.java
index 8790766..dd517f9 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestUriParserImpl.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestUriParserImpl.java
@@ -27,7 +27,7 @@ import org.apache.olingo.server.api.edmx.EdmxReference;
import org.apache.olingo.server.api.uri.UriInfoKind;
import org.apache.olingo.server.api.uri.UriResourceKind;
import org.apache.olingo.server.api.uri.queryoption.expression.MethodKind;
-import org.apache.olingo.server.core.uri.parser.UriParserSyntaxException;
+import org.apache.olingo.server.core.uri.parser.UriParserSemanticException;
import org.apache.olingo.server.core.uri.testutil.FilterValidator;
import org.apache.olingo.server.core.uri.testutil.ResourceValidator;
import org.apache.olingo.server.core.uri.testutil.TestUriValidator;
@@ -67,8 +67,7 @@ public class TestUriParserImpl {
+ "," + PropertyDateTimeOffset + "," + PropertyDuration + "," + PropertyGuid + "," + PropertyTimeOfDay;
@Test
- public void testBoundFunctionImport_VarParameters() {
-
+ public void boundFunctionImport_VarParameters() {
// no input
testRes.run("ESKeyNav(1)/olingo.odata.test1.BFCETKeyNavRTETKeyNav()")
.at(0).isUriPathInfoKind(UriResourceKind.entitySet)
@@ -89,9 +88,8 @@ public class TestUriParserImpl {
}
@Test
- public void testFunctionBound_varReturnType() {
-
- String esTwoKeyNav = "ESTwoKeyNav(PropertyInt16=1,PropertyString='ABC')";
+ public void functionBound_varReturnType() {
+ final String esTwoKeyNav = "ESTwoKeyNav(PropertyInt16=1,PropertyString='ABC')";
// returning primitive
testRes.run("ESTwoKeyNav/olingo.odata.test1.BFCESTwoKeyNavRTString()")
@@ -151,8 +149,7 @@ public class TestUriParserImpl {
}
@Test
- public void runActionImport_VarReturnType() {
-
+ public void actionImport_VarReturnType() {
testRes.run(ContainerProvider.AIRT_STRING).isKind(UriInfoKind.resource)
.first()
.isActionImport(ContainerProvider.AIRT_STRING)
@@ -189,7 +186,6 @@ public class TestUriParserImpl {
@Test
public void count() {
-
// count entity set
testRes.run("ESAllPrim/$count")
.at(0)
@@ -216,7 +212,7 @@ public class TestUriParserImpl {
}
@Test
- public void runCrossJoin() throws Exception {
+ public void crossJoin() throws Exception {
testUri.run("$crossjoin(ESAllKey)")
.isKind(UriInfoKind.crossjoin)
.isCrossJoinEntityList(Arrays.asList("ESAllKey"));
@@ -226,29 +222,15 @@ public class TestUriParserImpl {
.isCrossJoinEntityList(Arrays.asList("ESAllKey", "ESTwoPrim"));
}
- @Test(expected = UriValidationException.class)
- public void testEntityFailOnValidation1() throws Exception {
+ @Test
+ public void entityFailOnValidation() throws Exception {
// simple entity set; with qualifiedentityTypeName; with filter
- testUri.run("$entity/olingo.odata.test1.ETTwoPrim", "$filter=PropertyInt16 eq 123&$id=ESAllKey")
- .isIdText("ESAllKey")
- .goFilter().is("<<PropertyInt16> eq <123>>");
- }
-
- @Test(expected = UriParserSyntaxException.class)
- public void testEntityFailOnValidation2() throws Exception {
- // simple entity set; with qualifiedentityTypeName; with 2xformat(before and after), expand, filter
- testUri.run("$entity/olingo.odata.test1.ETTwoPrim",
- "$format=xml&$expand=*&abc=123&$id=ESBase&xyz=987&$filter=PropertyInt16 eq 123&$format=atom&$select=*")
- .isFormatText("atom")
- .isCustomParameter(0, "abc", "123")
- .isIdText("ESBase")
- .isCustomParameter(1, "xyz", "987")
- .isSelectItemStar(0);
+ testUri.runEx("$entity/olingo.odata.test1.ETTwoPrim", "$filter=PropertyInt16 eq 123&$id=ESAllKey")
+ .isExValidation(UriValidationException.MessageKeys.SYSTEM_QUERY_OPTION_NOT_ALLOWED);
}
@Test
- public void testEntity() throws Exception {
-
+ public void entity() throws Exception {
// simple entity set
testUri.run("$entity", "$id=ESAllPrim").isKind(UriInfoKind.entityId)
.isKind(UriInfoKind.entityId)
@@ -311,14 +293,11 @@ public class TestUriParserImpl {
.isKind(UriInfoKind.entityId)
.isEntityType(EntityTypeProvider.nameETBase)
.isIdText("ESTwoPrim")
- .isExpandText("*")
.goExpand().first().isSegmentStar();
-
}
@Test
public void entitySet() throws Exception {
-
// plain entity set
testRes.run("ESAllPrim")
.isEntitySet("ESAllPrim")
@@ -342,7 +321,7 @@ public class TestUriParserImpl {
.isKeyPredicate(1, "PropertyString", "'ABC'");
// with all keys
- testRes.run("ESAllKey(" + encode(allKeys) + ")")
+ testRes.run("ESAllKey(" + allKeys + ")")
.isEntitySet("ESAllKey")
.isKeyPredicate(0, "PropertyString", "'ABC'")
.isKeyPredicate(1, "PropertyInt16", "1")
@@ -360,10 +339,7 @@ public class TestUriParserImpl {
}
@Test
- public void testEntitySet_NavigationProperty() {
-
- // plain entity set ...
-
+ public void entitySet_NavigationProperty() {
// with navigation property
testRes.run("ESKeyNav(1)/NavPropertyETTwoKeyNavOne")
.at(0)
@@ -467,10 +443,7 @@ public class TestUriParserImpl {
}
@Test
- public void testEntitySet_Property() {
-
- // plain entity set ...
-
+ public void entitySet_Property() {
// with property
testRes.run("ESAllPrim(1)/PropertyString")
.at(0)
@@ -499,8 +472,7 @@ public class TestUriParserImpl {
}
@Test
- public void testEntitySet_TypeFilter() {
-
+ public void entitySet_TypeFilter() {
// filter
testRes.run("ESTwoPrim/olingo.odata.test1.ETBase")
.at(0)
@@ -556,57 +528,53 @@ public class TestUriParserImpl {
.at(1)
.isPrimitiveProperty("AdditionalPropertyString_5", PropertyProvider.nameString, false)
.isType(PropertyProvider.nameString);
-
}
@Test
public void unary() throws Exception {
- testFilter.runOnETAllPrim("not PropertyBoolean").isCompr("<not <PropertyBoolean>>");
- testFilter.runOnETAllPrim("-PropertyInt16 eq PropertyInt16").isCompr("<<- <PropertyInt16>> eq <PropertyInt16>>");
+ testFilter.runOnETAllPrim("not PropertyBoolean").is("<not <PropertyBoolean>>");
+ testFilter.runOnETAllPrim("-PropertyInt16 eq PropertyInt16").is("<<- <PropertyInt16>> eq <PropertyInt16>>");
}
- // TODO: Use correct types.
@Test
- @Ignore
public void filterComplexMixedPriority() throws Exception {
- testFilter.runOnETAllPrim("PropertyInt16 or PropertyInt32 and PropertyInt64")
- .isCompr("<<PropertyInt16> or <<PropertyInt32> and <PropertyInt64>>>");
- testFilter.runOnETAllPrim("PropertyInt16 or PropertyInt32 and PropertyInt64 eq PropertyByte")
- .isCompr("<<PropertyInt16> or <<PropertyInt32> and <<PropertyInt64> eq <PropertyByte>>>>");
- testFilter.runOnETAllPrim("PropertyInt16 or PropertyInt32 eq PropertyInt64 and PropertyByte")
- .isCompr("<<PropertyInt16> or <<<PropertyInt32> eq <PropertyInt64>> and <PropertyByte>>>");
- testFilter.runOnETAllPrim("PropertyInt16 or PropertyInt32 eq PropertyInt64 and PropertyByte eq PropertySByte")
- .isCompr("<<PropertyInt16> or <<<PropertyInt32> eq <PropertyInt64>> "
+ testFilter.runOnETAllPrim("PropertyBoolean or true and false")
+ .is("<<PropertyBoolean> or <<true> and <false>>>");
+ testFilter.runOnETAllPrim("PropertyBoolean or true and PropertyInt64 eq PropertyByte")
+ .is("<<PropertyBoolean> or <<true> and <<PropertyInt64> eq <PropertyByte>>>>");
+ testFilter.runOnETAllPrim("PropertyBoolean or PropertyInt32 eq PropertyInt64 and true")
+ .is("<<PropertyBoolean> or <<<PropertyInt32> eq <PropertyInt64>> and <true>>>");
+ testFilter.runOnETAllPrim("PropertyBoolean or PropertyInt32 eq PropertyInt64 and PropertyByte eq PropertySByte")
+ .is("<<PropertyBoolean> or <<<PropertyInt32> eq <PropertyInt64>> "
+ "and <<PropertyByte> eq <PropertySByte>>>>");
- testFilter.runOnETAllPrim("PropertyInt16 eq PropertyInt32 or PropertyInt64 and PropertyByte")
- .isCompr("<<<PropertyInt16> eq <PropertyInt32>> or <<PropertyInt64> and <PropertyByte>>>");
- testFilter.runOnETAllPrim("PropertyInt16 eq PropertyInt32 or PropertyInt64 and PropertyByte eq PropertySByte")
- .isCompr("<<<PropertyInt16> eq <PropertyInt32>> "
- + "or <<PropertyInt64> and <<PropertyByte> eq <PropertySByte>>>>");
- testFilter.runOnETAllPrim("PropertyInt16 eq PropertyInt32 or PropertyInt64 eq PropertyByte and PropertySByte")
- .isCompr("<<<PropertyInt16> eq <PropertyInt32>> "
- + "or <<<PropertyInt64> eq <PropertyByte>> and <PropertySByte>>>");
+ testFilter.runOnETAllPrim("PropertyInt16 eq PropertyInt32 or PropertyBoolean and true")
+ .is("<<<PropertyInt16> eq <PropertyInt32>> or <<PropertyBoolean> and <true>>>");
+ testFilter.runOnETAllPrim("PropertyInt16 eq PropertyInt32 or PropertyBoolean and PropertyByte eq PropertySByte")
+ .is("<<<PropertyInt16> eq <PropertyInt32>> "
+ + "or <<PropertyBoolean> and <<PropertyByte> eq <PropertySByte>>>>");
+ testFilter.runOnETAllPrim("PropertyInt16 eq PropertyInt32 or PropertyInt64 eq PropertyByte and PropertyBoolean")
+ .is("<<<PropertyInt16> eq <PropertyInt32>> "
+ + "or <<<PropertyInt64> eq <PropertyByte>> and <PropertyBoolean>>>");
testFilter.runOnETAllPrim("PropertyInt16 eq PropertyInt32 or PropertyInt64 eq PropertyByte "
+ "and PropertySByte eq PropertyDecimal")
- .isCompr("<<<PropertyInt16> eq <PropertyInt32>> or <<<PropertyInt64> eq <PropertyByte>> "
+ .is("<<<PropertyInt16> eq <PropertyInt32>> or <<<PropertyInt64> eq <PropertyByte>> "
+ "and <<PropertySByte> eq <PropertyDecimal>>>>");
}
@Test
public void filterSimpleSameBinaryBinaryBinaryPriority() throws Exception {
- testFilter.runOnETAllPrim("1 add 2 add 3 add 4").isCompr("<<< <1> add <2>> add <3>> add <4>>");
- testFilter.runOnETAllPrim("1 add 2 add 3 div 4").isCompr("<< <1> add <2>> add <<3> div <4>>>");
- testFilter.runOnETAllPrim("1 add 2 div 3 add 4").isCompr("<< <1> add <<2> div <3>>> add <4>>");
- testFilter.runOnETAllPrim("1 add 2 div 3 div 4").isCompr("< <1> add <<<2> div <3>> div <4>>>");
- testFilter.runOnETAllPrim("1 div 2 add 3 add 4").isCompr("<<< <1> div <2>> add <3>> add <4>>");
- testFilter.runOnETAllPrim("1 div 2 add 3 div 4").isCompr("<< <1> div <2>> add <<3> div <4>>>");
- testFilter.runOnETAllPrim("1 div 2 div 3 add 4").isCompr("<<< <1> div <2>> div <3>> add <4>>");
- testFilter.runOnETAllPrim("1 div 2 div 3 div 4").isCompr("<<< <1> div <2>> div <3>> div <4>>");
+ testFilter.runOnETAllPrim("1 add 2 add 3 add 4 ge 0").isCompr("<<<< <1> add <2>> add <3>> add <4>> ge <0>>");
+ testFilter.runOnETAllPrim("1 add 2 add 3 div 4 ge 0").isCompr("<<< <1> add <2>> add <<3> div <4>>> ge <0>>");
+ testFilter.runOnETAllPrim("1 add 2 div 3 add 4 ge 0").isCompr("<<< <1> add <<2> div <3>>> add <4>> ge <0>>");
+ testFilter.runOnETAllPrim("1 add 2 div 3 div 4 ge 0").isCompr("<< <1> add <<<2> div <3>> div <4>>> ge <0>>");
+ testFilter.runOnETAllPrim("1 div 2 add 3 add 4 ge 0").isCompr("<<<< <1> div <2>> add <3>> add <4>> ge <0>>");
+ testFilter.runOnETAllPrim("1 div 2 add 3 div 4 ge 0").isCompr("<<< <1> div <2>> add <<3> div <4>>> ge <0>>");
+ testFilter.runOnETAllPrim("1 div 2 div 3 add 4 ge 0").isCompr("<<<< <1> div <2>> div <3>> add <4>> ge <0>>");
+ testFilter.runOnETAllPrim("1 div 2 div 3 div 4 ge 0").isCompr("<<<< <1> div <2>> div <3>> div <4>> ge <0>>");
}
@Test
- public void testFunctionImport_VarParameters() {
-
+ public void functionImport_VarParameters() {
// no input
testRes.run("FINRTInt16()")
.isFunctionImport("FINRTInt16")
@@ -627,7 +595,7 @@ public class TestUriParserImpl {
}
@Test
- public void testFunctionImport_VarReturning() {
+ public void functionImport_VarReturning() {
// returning primitive
testRes.run("FINRTInt16()")
.isFunctionImport("FINRTInt16")
@@ -666,8 +634,7 @@ public class TestUriParserImpl {
}
@Test
- public void testFunctionImportChain() {
-
+ public void functionImportChain() {
// test chain; returning single complex
testRes.run("FICRTCTAllPrimTwoParam(ParameterString='ABC',ParameterInt16=1)/PropertyInt16")
.at(0)
@@ -710,12 +677,10 @@ public class TestUriParserImpl {
.isKeyPredicate(1, "PropertyString", "'ABC'")
.at(1)
.isPrimitiveProperty("PropertyInt16", PropertyProvider.nameInt16, false);
-
}
@Test
- public void testMetaData() throws Exception {
-
+ public void metaData() throws Exception {
// Parsing the fragment may be used if a uri has to be parsed on the consumer side.
// On the producer side this feature is currently not supported, so the context fragment
// part is only available as text.
@@ -879,12 +844,12 @@ public class TestUriParserImpl {
}
@Test
- public void testRef() throws Exception {
+ public void ref() throws Exception {
testUri.run("ESKeyNav(1)/NavPropertyETTwoKeyNavOne/$ref");
}
@Test
- public void testSingleton() {
+ public void singleton() {
// plain singleton
testRes.run("SINav")
.isSingleton("SINav")
@@ -892,10 +857,7 @@ public class TestUriParserImpl {
}
@Test
- public void testNavigationProperty() {
-
- // plain entity set ...
-
+ public void navigationProperty() {
// with navigation property
testRes.run("ESKeyNav(1)/NavPropertyETTwoKeyNavOne")
.at(0).isEntitySet("ESKeyNav")
@@ -969,10 +931,7 @@ public class TestUriParserImpl {
}
@Test
- public void testSingleton_Property() {
-
- // plain singleton ...
-
+ public void singleton_Property() {
// with property
testRes.run("SINav/PropertyInt16")
.at(0)
@@ -1002,72 +961,51 @@ public class TestUriParserImpl {
}
@Test
- public void testValue() throws Exception {
+ public void value() throws Exception {
testUri.run("ESAllPrim(1)/PropertyString/$value");
}
- @Test(expected = UriValidationException.class)
- public void testMemberStartingWithCastFailOnValidation1() throws Exception {
+ @Test
+ public void memberStartingWithCastFailOnValidation1() throws Exception {
// on EntityType entry
- testUri.run("ESTwoKeyNav(ParameterInt16=1,PropertyString='ABC')",
+ testUri.runEx("ESTwoKeyNav(Property16=1,PropertyString='ABC')",
"$filter=olingo.odata.test1.ETBaseTwoKeyNav/PropertyDate")
- .goFilter().root().isMember()
- .isMemberStartType(EntityTypeProvider.nameETBaseTwoKeyNav).goPath()
- // .at(0)
- // .isUriPathInfoKind(UriResourceKind.startingTypeFilter)
- // .isType(EntityTypeProvider.nameETTwoKeyNav, false)
- // .isTypeFilterOnEntry(EntityTypeProvider.nameETBaseTwoKeyNav)
- .at(0).isType(PropertyProvider.nameDate);
+ .isExValidation(UriValidationException.MessageKeys.INVALID_KEY_PROPERTY);
}
- @Test(expected = UriValidationException.class)
- public void testMemberStartingWithCastFailOnValidation2() throws Exception {
- testUri.run("FICRTCTTwoPrimTwoParam(ParameterInt16=1,ParameterString='2')",
+ @Test
+ public void memberStartingWithCastFailOnValidation2() throws Exception {
+ testUri.runEx("FICRTCTTwoPrimTwoParam(ParameterInt16=1,ParameterString='2')",
"$filter=olingo.odata.test1.CTBase/AdditionalPropString")
- .goFilter().root().isMember()
- .isMemberStartType(ComplexTypeProvider.nameCTBase).goPath()
- // .at(0)
- // .isUriPathInfoKind(UriResourceKind.startingTypeFilter)
- // .isType(ComplexTypeProvider.nameCTTwoPrim, false)
- // .isTypeFilterOnEntry(ComplexTypeProvider.nameCTBase)
- .at(0).isType(PropertyProvider.nameString);
+ .isExSemantic(UriParserSemanticException.MessageKeys.TYPES_NOT_COMPATIBLE);
}
@Test
- public void testMemberStartingWithCast() throws Exception {
-
+ public void memberStartingWithCast() throws Exception {
// on EntityType collection
- testUri.run("ESTwoKeyNav", "$filter=olingo.odata.test1.ETBaseTwoKeyNav/PropertyDate")
- .goFilter().root().isMember()
+ testFilter.runOnETTwoKeyNav("olingo.odata.test1.ETBaseTwoKeyNav/PropertyDate eq null")
+ .left()
+ .isMember()
.isMemberStartType(EntityTypeProvider.nameETBaseTwoKeyNav).goPath()
- // .at(0)
- // .isUriPathInfoKind(UriResourceKind.startingTypeFilter)
- // .isType(EntityTypeProvider.nameETTwoKeyNav, true)
- // .isTypeFilterOnCollection(EntityTypeProvider.nameETBaseTwoKeyNav)
.at(0).isType(PropertyProvider.nameDate);
// on Complex collection
testUri.run("FICRTCollCTTwoPrimTwoParam(ParameterInt16=1,ParameterString='2')",
- "$filter=olingo.odata.test1.CTBase/AdditionalPropString")
- .goFilter().root().isMember()
+ "$filter=olingo.odata.test1.CTBase/AdditionalPropString eq null")
+ .goFilter().left().isMember()
.isMemberStartType(ComplexTypeProvider.nameCTBase).goPath()
- // .at(0)
- // .isUriPathInfoKind(UriResourceKind.startingTypeFilter)
- // .isType(ComplexTypeProvider.nameCTTwoPrim, true)
- // .isTypeFilterOnCollection(ComplexTypeProvider.nameCTBase)
.at(0).isType(PropertyProvider.nameString);
-
}
@Test
- public void testComplexTypeCastFollowingAsCollection() throws Exception {
+ public void complexTypeCastFollowingAsCollection() throws Exception {
testUri.run("FICRTCollCTTwoPrimTwoParam(ParameterInt16=1,ParameterString='2')/olingo.odata.test1.CTBase");
}
@Test
- public void testAlias() throws Exception {
- testUri.run("ESAllPrim", "$filter=PropertyInt16 eq @p1&@p1=1")
- .goFilter().is("<<PropertyInt16> eq <@p1>>");
+ public void alias() throws Exception {
+ testFilter.runOnETAllPrim("PropertyInt16 eq @p1&@p1=1")
+ .is("<<PropertyInt16> eq <@p1>>");
}
@Test
@@ -1087,26 +1025,22 @@ public class TestUriParserImpl {
@Test
public void customQueryOption() throws Exception {
testUri.run("ESTwoKeyNav", "custom")
- .isCustomParameter(0, "custom", "");
+ .isCustomParameter(0, "custom", "");
testUri.run("ESTwoKeyNav", "custom=ABC")
- .isCustomParameter(0, "custom", "ABC");
+ .isCustomParameter(0, "custom", "ABC");
}
@Test
@Ignore("Geo types are not supported yet.")
public void geo() throws Exception {
testFilter.runOnETAllPrim("geo.distance(PropertySByte,PropertySByte)")
- .is("<geo.distance(<PropertySByte>,<PropertySByte>)>")
- .isMethod(MethodKind.GEODISTANCE, 2);
+ .is("<geo.distance(<PropertySByte>,<PropertySByte>)>")
+ .isMethod(MethodKind.GEODISTANCE, 2);
testFilter.runOnETAllPrim("geo.length(PropertySByte)")
- .is("<geo.length(<PropertySByte>)>")
- .isMethod(MethodKind.GEOLENGTH, 1);
+ .is("<geo.length(<PropertySByte>)>")
+ .isMethod(MethodKind.GEOLENGTH, 1);
testFilter.runOnETAllPrim("geo.intersects(PropertySByte,PropertySByte)")
- .is("<geo.intersects(<PropertySByte>,<PropertySByte>)>")
- .isMethod(MethodKind.GEOINTERSECTS, 2);
- }
-
- private final String encode(final String uriPart) {
- return uriPart.replaceAll(":", "%3A");
+ .is("<geo.intersects(<PropertySByte>,<PropertySByte>)>")
+ .isMethod(MethodKind.GEOINTERSECTS, 2);
}
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/parser/ParserTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/parser/ParserTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/parser/ParserTest.java
index f54ad04..af523aa 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/parser/ParserTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/parser/ParserTest.java
@@ -18,12 +18,18 @@
*/
package org.apache.olingo.server.core.uri.parser;
+import java.util.Collections;
+
import org.apache.olingo.commons.api.edm.Edm;
import org.apache.olingo.commons.api.edm.EdmEntityContainer;
import org.apache.olingo.commons.api.edm.EdmEntitySet;
import org.apache.olingo.commons.api.edm.EdmEntityType;
+import org.apache.olingo.commons.api.edm.EdmKeyPropertyRef;
import org.apache.olingo.commons.api.edm.EdmNavigationProperty;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
+import org.apache.olingo.commons.api.edm.EdmProperty;
import org.apache.olingo.commons.api.edm.FullQualifiedName;
+import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.uri.UriInfoKind;
import org.apache.olingo.server.core.uri.testutil.TestUriValidator;
import org.junit.Test;
@@ -33,17 +39,57 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
/**
- * All Tests which involves the <code>Parser</code> implementation
- * (and with that also the <code>UriParseTreeVisitor</code>).
+ * Tests of the <code>Parser</code> implementation that require mocking of the EDM.
*/
public class ParserTest {
+ @Test
+ public void navPropertySameNameAsEntitySet() throws Exception {
+ final String namespace = "namespace";
+ final String entityTypeName = "ETNavProp";
+ final FullQualifiedName nameETNavProp = new FullQualifiedName(namespace, entityTypeName);
+ final String entitySetName = "ESNavProp";
+ final String keyPropertyName = "a";
+ EdmProperty keyProperty = Mockito.mock(EdmProperty.class);
+ Mockito.when(keyProperty.getType())
+ .thenReturn(OData.newInstance().createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Byte));
+ EdmKeyPropertyRef keyPropertyRef = Mockito.mock(EdmKeyPropertyRef.class);
+ Mockito.when(keyPropertyRef.getName()).thenReturn(keyPropertyName);
+ Mockito.when(keyPropertyRef.getProperty()).thenReturn(keyProperty);
+ EdmNavigationProperty navProperty = Mockito.mock(EdmNavigationProperty.class);
+ Mockito.when(navProperty.getName()).thenReturn(entitySetName);
+ Mockito.when(navProperty.isCollection()).thenReturn(true);
+ EdmEntityType entityType = Mockito.mock(EdmEntityType.class);
+ Mockito.when(entityType.getFullQualifiedName()).thenReturn(nameETNavProp);
+ Mockito.when(entityType.getKeyPredicateNames()).thenReturn(Collections.singletonList(keyPropertyName));
+ Mockito.when(entityType.getKeyPropertyRefs()).thenReturn(Collections.singletonList(keyPropertyRef));
+ Mockito.when(entityType.getNavigationProperty(entitySetName)).thenReturn(navProperty);
+ Mockito.when(navProperty.getType()).thenReturn(entityType);
+ EdmEntitySet entitySet = Mockito.mock(EdmEntitySet.class);
+ Mockito.when(entitySet.getName()).thenReturn(entitySetName);
+ Mockito.when(entitySet.getEntityType()).thenReturn(entityType);
+ EdmEntityContainer container = Mockito.mock(EdmEntityContainer.class);
+ Mockito.when(container.getEntitySet(entitySetName)).thenReturn(entitySet);
+ Edm mockedEdm = Mockito.mock(Edm.class);
+ Mockito.when(mockedEdm.getEntityContainer()).thenReturn(container);
+ new TestUriValidator().setEdm(mockedEdm)
+ .run("ESNavProp(1)/ESNavProp(2)/ESNavProp(3)/ESNavProp")
+ .goPath()
+ .at(0).isEntitySet(entitySetName)
+ .at(0).isKeyPredicate(0, keyPropertyName, "1")
+ .at(1).isNavProperty(entitySetName, nameETNavProp, false)
+ .at(1).isKeyPredicate(0, keyPropertyName, "2")
+ .at(2).isNavProperty(entitySetName, nameETNavProp, false)
+ .at(2).isKeyPredicate(0, keyPropertyName, "3")
+ .at(3).isNavProperty(entitySetName, nameETNavProp, true);
+ }
+
/**
* Test for EntitySet and NavigationProperty with same name defined in metadata.
* (related to Olingo issue OLINGO-741)
*/
@Test
- public void parseEntitySetAndNavigationPropertyWithSameName() throws Exception {
+ public void expandNavigationPropertyWithSameNameAsEntitySet() throws Exception {
TestUriValidator testUri = new TestUriValidator();
Edm mockEdm = Mockito.mock(Edm.class);
@@ -60,7 +106,7 @@ public class ParserTest {
Mockito.when(typeCategory.getNamespace()).thenReturn("NS");
Mockito.when(esCategory.getEntityType()).thenReturn(typeCategory);
Mockito.when(productsNavigation.getName()).thenReturn("Products");
- Mockito.when(typeCategory.getProperty("Products")).thenReturn(productsNavigation);
+ Mockito.when(typeCategory.getNavigationProperty("Products")).thenReturn(productsNavigation);
Mockito.when(container.getEntitySet("Category")).thenReturn(esCategory);
Mockito.when(container.getEntitySet("Products")).thenReturn(esProduct);
Mockito.when(productsType.getFullQualifiedName()).thenReturn(nameProducts);
@@ -122,7 +168,7 @@ public class ParserTest {
.isType(new FullQualifiedName("NS", "Category"), false);
fail("Expected exception was not thrown.");
} catch (final UriParserException e) {
- assertEquals("NavigationProperty 'Category' not found in type 'NS.Products'", e.getMessage());
+ assertEquals("Navigation Property 'Category' not found in type 'NS.Products'.", e.getMessage());
}
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/ExpandValidator.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/ExpandValidator.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/ExpandValidator.java
index 5638227..35245b4 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/ExpandValidator.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/ExpandValidator.java
@@ -19,6 +19,7 @@
package org.apache.olingo.server.core.uri.testutil;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -151,12 +152,6 @@ public class ExpandValidator implements TestValidator {
return this;
}
- public ExpandValidator isSelectText(final String text) {
- final QueryOption option = expandItem.getSelectOption();
- assertEquals(text, option.getText());
- return this;
- }
-
public ExpandValidator isSelectItemStar(final int index) {
SelectOption select = expandItem.getSelectOption();
SelectItem item = select.getSelectItems().get(index);
@@ -171,12 +166,6 @@ public class ExpandValidator implements TestValidator {
return this;
}
- public ExpandValidator isFilterOptionText(final String text) {
- QueryOption option = expandItem.getFilterOption();
- assertEquals(text, option.getText());
- return this;
- }
-
public ExpandValidator isFilterSerialized(final String serialized) {
FilterOption filter = expandItem.getFilterOption();
@@ -201,7 +190,13 @@ public class ExpandValidator implements TestValidator {
}
public ExpandValidator isExpandStartType(final FullQualifiedName fullName) {
+ assertNotNull(expandItem.getStartTypeFilter());
assertEquals(fullName, expandItem.getStartTypeFilter().getFullQualifiedName());
return this;
}
+
+ public ExpandValidator isSearchSerialized(final String serialized) {
+ assertEquals(serialized, expandItem.getSearchOption().getSearchExpression().toString());
+ return this;
+ }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/FilterValidator.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/FilterValidator.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/FilterValidator.java
index 0800dd0..161299c 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/FilterValidator.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/FilterValidator.java
@@ -46,13 +46,16 @@ import org.apache.olingo.server.api.uri.queryoption.expression.Member;
import org.apache.olingo.server.api.uri.queryoption.expression.Method;
import org.apache.olingo.server.api.uri.queryoption.expression.MethodKind;
import org.apache.olingo.server.api.uri.queryoption.expression.TypeLiteral;
+import org.apache.olingo.server.api.uri.queryoption.expression.Unary;
import org.apache.olingo.server.core.uri.UriResourceFunctionImpl;
import org.apache.olingo.server.core.uri.parser.Parser;
import org.apache.olingo.server.core.uri.parser.UriParserException;
import org.apache.olingo.server.core.uri.parser.UriParserSemanticException;
import org.apache.olingo.server.core.uri.parser.UriParserSyntaxException;
+import org.apache.olingo.server.core.uri.queryoption.expression.BinaryImpl;
import org.apache.olingo.server.core.uri.queryoption.expression.MemberImpl;
import org.apache.olingo.server.core.uri.queryoption.expression.MethodImpl;
+import org.apache.olingo.server.core.uri.queryoption.expression.UnaryImpl;
import org.apache.olingo.server.core.uri.validator.UriValidationException;
public class FilterValidator implements TestValidator {
@@ -127,7 +130,7 @@ public class FilterValidator implements TestValidator {
}
public FilterValidator runOrderByOnETTwoKeyNavEx(final String orderBy) throws UriParserException {
- return runUriOrderByEx("ESTwoKeyNav", "$orderby=" + orderBy.trim());
+ return runUriEx("ESTwoKeyNav", "$orderby=" + orderBy.trim());
}
public FilterValidator runOnETTwoKeyNav(final String filter) throws UriParserException, UriValidationException {
@@ -225,19 +228,6 @@ public class FilterValidator implements TestValidator {
return this;
}
- public FilterValidator runUriOrderByEx(final String path, final String query) {
- exception = null;
- try {
- new Parser(edm, odata).parseUri(path, query, null);
- fail("Expected exception not thrown.");
- } catch (final UriParserException e) {
- exception = e;
- } catch (final UriValidationException e) {
- exception = e;
- }
- return this;
- }
-
// --- Navigation ---
public ExpandValidator goUpToExpandValidator() {
@@ -274,8 +264,8 @@ public class FilterValidator implements TestValidator {
// --- Validation ---
/**
- * Validates the serialized filterTree against a given filterString
- * The given expected filterString is compressed before to allow better readable code in the unit tests
+ * Validates the serialized filterTree against a given filterString.
+ * The given expected filterString is compressed before to allow better readable code in the unit tests.
* @param toBeCompr
* @return {@link FilterValidator}
*/
@@ -310,14 +300,19 @@ public class FilterValidator implements TestValidator {
EdmType actualType = null;
if (curExpression instanceof Member) {
- Member member = (Member) curExpression;
- actualType = member.getType();
+ actualType = ((Member) curExpression).getType();
} else if (curExpression instanceof TypeLiteral) {
- TypeLiteral typeLiteral = (TypeLiteral) curExpression;
- actualType = typeLiteral.getType();
+ actualType = ((TypeLiteral) curExpression).getType();
} else if (curExpression instanceof Literal) {
- Literal typeLiteral = (Literal) curExpression;
- actualType = typeLiteral.getType();
+ actualType = ((Literal) curExpression).getType();
+ } else if (curExpression instanceof Enumeration) {
+ actualType = ((Enumeration) curExpression).getType();
+ } else if (curExpression instanceof Unary) {
+ actualType = ((UnaryImpl) curExpression).getType();
+ } else if (curExpression instanceof Binary) {
+ actualType = ((BinaryImpl) curExpression).getType();
+ } else if (curExpression instanceof Method) {
+ actualType = ((MethodImpl) curExpression).getType();
}
if (actualType == null) {
@@ -349,7 +344,6 @@ public class FilterValidator implements TestValidator {
curExpression = ((Binary) curExpression).getRightOperand();
return this;
-
}
public FilterValidator isLiteral(final String literalText) {
@@ -361,9 +355,9 @@ public class FilterValidator implements TestValidator {
assertEquals(literalText, actualLiteralText);
return this;
}
-
- public FilterValidator isLiteralType(EdmType edmType) {
- if(!(curExpression instanceof Literal)) {
+
+ public FilterValidator isLiteralType(final EdmType edmType) {
+ if (!(curExpression instanceof Literal)) {
fail("Current expression is not a literal");
}
@@ -374,7 +368,7 @@ public class FilterValidator implements TestValidator {
}
public FilterValidator isNullLiteralType() {
- if(!(curExpression instanceof Literal)) {
+ if (!(curExpression instanceof Literal)) {
fail("Current expression is not a literal");
}
@@ -495,12 +489,4 @@ public class FilterValidator implements TestValidator {
assertEquals(messageKey, exception.getMessageKey());
return this;
}
-
- public FilterValidator isNull() {
- return isLiteral("null");
- }
-
- public FilterValidator isTrue() {
- return isLiteral("true");
- }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/TestUriValidator.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/TestUriValidator.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/TestUriValidator.java
index 1dbe62b..fbce5c9 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/TestUriValidator.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/TestUriValidator.java
@@ -140,6 +140,20 @@ public class TestUriValidator implements TestValidator {
return this;
}
+ public TestUriValidator isSelectItemStar(final int index) {
+ final SelectOption select = uriInfo.getSelectOption();
+ SelectItem item = select.getSelectItems().get(index);
+ assertTrue(item.isStar());
+ return this;
+ }
+
+ public TestUriValidator isSelectItemAllOp(final int index, final FullQualifiedName fqn) {
+ final SelectOption select = uriInfo.getSelectOption();
+ SelectItem item = select.getSelectItems().get(index);
+ assertEquals(fqn, item.getAllOperationsInSchemaNameSpace());
+ return this;
+ }
+
// Validation
public TestUriValidator isKind(final UriInfoKind kind) {
assertEquals(kind, uriInfo.getKind());
@@ -202,16 +216,6 @@ public class TestUriValidator implements TestValidator {
return this;
}
- public TestUriValidator isExpandText(final String text) {
- assertEquals(text, uriInfo.getExpandOption().getText());
- return this;
- }
-
- public TestUriValidator isSelectText(final String text) {
- assertEquals(text, uriInfo.getSelectOption().getText());
- return this;
- }
-
public TestUriValidator isFormatText(final String text) {
assertEquals(text, uriInfo.getFormatOption().getText());
return this;
@@ -234,18 +238,4 @@ public class TestUriValidator implements TestValidator {
assertEquals(fullName, uriInfo.getEntityTypeCast().getFullQualifiedName());
return this;
}
-
- public TestUriValidator isSelectItemStar(final int index) {
- final SelectOption select = uriInfo.getSelectOption();
- SelectItem item = select.getSelectItems().get(index);
- assertTrue(item.isStar());
- return this;
- }
-
- public TestUriValidator isSelectItemAllOp(final int index, final FullQualifiedName fqn) {
- final SelectOption select = uriInfo.getSelectOption();
- SelectItem item = select.getSelectItems().get(index);
- assertEquals(fqn, item.getAllOperationsInSchemaNameSpace());
- return this;
- }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/TokenValidator.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/TokenValidator.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/TokenValidator.java
deleted file mode 100644
index 547c2ea..0000000
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/TokenValidator.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * 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.testutil;
-
-import static org.junit.Assert.assertEquals;
-
-import java.util.List;
-
-import org.antlr.v4.runtime.ANTLRInputStream;
-import org.antlr.v4.runtime.Token;
-import org.apache.olingo.server.core.uri.antlr.UriLexer;
-
-public class TokenValidator {
-
- private String input = null;
- private List<? extends Token> tokens = null;
- private Token curToken = null;
- private Exception curException = null;
-
- private int startMode;
-
- // --- Execution ---
-
- public TokenValidator run(final String uri) {
- input = uri;
- tokens = parseInput(uri);
- first();
- return this;
- }
-
- // --- Navigation ---
-
- // navigate within the tokenlist
- public TokenValidator first() {
- try {
- curToken = tokens.get(0);
- } catch (IndexOutOfBoundsException ex) {
- curToken = null;
- }
- return this;
- }
-
- public TokenValidator last() {
- curToken = tokens.get(tokens.size() - 1);
- return this;
- }
-
- public TokenValidator at(final int index) {
- try {
- curToken = tokens.get(index);
- } catch (IndexOutOfBoundsException ex) {
- curToken = null;
- }
- return this;
- }
-
- // --- Validation ---
-
- public TokenValidator isText(final String expected) {
- assertEquals(expected, curToken.getText());
- return this;
- }
-
- public TokenValidator isAllText(final String expected) {
- String actual = "";
-
- for (Token curToken : tokens) {
- actual += curToken.getText();
- }
- assertEquals(expected, actual);
- return this;
- }
-
- public TokenValidator isAllInput() {
- String actual = "";
-
- for (Token curToken : tokens) {
- actual += curToken.getText();
- }
- assertEquals(input, actual);
- return this;
- }
-
- public TokenValidator isInput() {
- assertEquals(input, curToken.getText());
- return this;
- }
-
- public TokenValidator isType(final int expected) {
- assertEquals(UriLexer.VOCABULARY.getDisplayName(expected), UriLexer.VOCABULARY.getDisplayName(curToken.getType()));
- return this;
- }
-
- public TokenValidator isExType(final Class<?> exClass) {
- assertEquals(exClass, curException.getClass());
- return this;
- }
-
- public void globalMode(final int mode) {
- startMode = mode;
- }
-
- // --- Helper ---
-
- private List<? extends Token> parseInput(final String input) {
- ANTLRInputStream inputStream = new ANTLRInputStream(input);
- UriLexer lexer = new UriLexer(inputStream);
- lexer.mode(startMode);
- return lexer.getAllTokens();
- }
-}
[30/30] olingo-odata4 git commit: [OLINGO-834] Shift dependecies from
commons to core
Posted by ch...@apache.org.
[OLINGO-834] Shift dependecies from commons to core
The dependencies were not used in the commons part of the library
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/b0866014
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/b0866014
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/b0866014
Branch: refs/heads/master
Commit: b0866014df9d876cb44ea1f9632cab5ca95be7f5
Parents: 53d2e8b
Author: Christian Amend <ch...@sap.com>
Authored: Fri Jan 8 13:12:45 2016 +0100
Committer: Christian Amend <ch...@sap.com>
Committed: Fri Jan 8 13:12:45 2016 +0100
----------------------------------------------------------------------
lib/client-core/pom.xml | 21 +++++++++++++++++++++
lib/commons-core/pom.xml | 22 ----------------------
lib/server-core/pom.xml | 14 ++++++++++++++
3 files changed, 35 insertions(+), 22 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b0866014/lib/client-core/pom.xml
----------------------------------------------------------------------
diff --git a/lib/client-core/pom.xml b/lib/client-core/pom.xml
index a9c7f7a..092ffac 100644
--- a/lib/client-core/pom.xml
+++ b/lib/client-core/pom.xml
@@ -46,6 +46,27 @@
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-annotations</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.dataformat</groupId>
+ <artifactId>jackson-dataformat-xml</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml</groupId>
+ <artifactId>aalto-xml</artifactId>
+ </dependency>
+
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b0866014/lib/commons-core/pom.xml
----------------------------------------------------------------------
diff --git a/lib/commons-core/pom.xml b/lib/commons-core/pom.xml
index 2c069f9..e9c0179 100644
--- a/lib/commons-core/pom.xml
+++ b/lib/commons-core/pom.xml
@@ -46,27 +46,6 @@
</dependency>
<dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-core</artifactId>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-databind</artifactId>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-annotations</artifactId>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.dataformat</groupId>
- <artifactId>jackson-dataformat-xml</artifactId>
- </dependency>
- <dependency>
- <groupId>com.fasterxml</groupId>
- <artifactId>aalto-xml</artifactId>
- </dependency>
-
- <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
@@ -99,7 +78,6 @@
org.apache.olingo.commons.core.edm,
org.apache.olingo.commons.core.edm.provider,
org.apache.olingo.commons.core.edm.primitivetype,
- org.apache.olingo.commons.core.serialization
</Export-Package>
<Import-Package>
*
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b0866014/lib/server-core/pom.xml
----------------------------------------------------------------------
diff --git a/lib/server-core/pom.xml b/lib/server-core/pom.xml
index 6e22690..0c329d9 100644
--- a/lib/server-core/pom.xml
+++ b/lib/server-core/pom.xml
@@ -57,6 +57,20 @@
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.fasterxml</groupId>
+ <artifactId>aalto-xml</artifactId>
+ </dependency>
+
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
[25/30] olingo-odata4 git commit: [OLINGO-834] $expand parser in Java
+ clean-up
Posted by ch...@apache.org.
[OLINGO-834] $expand parser in Java + clean-up
Signed-off-by: Christian Amend <ch...@sap.com>
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/8925274c
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/8925274c
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/8925274c
Branch: refs/heads/master
Commit: 8925274c0b5bd6936c3f6c1d3ab55608ced2cf13
Parents: 8919d3e
Author: Klaus Straubinger <kl...@sap.com>
Authored: Thu Jan 7 13:55:34 2016 +0100
Committer: Christian Amend <ch...@sap.com>
Committed: Thu Jan 7 14:02:09 2016 +0100
----------------------------------------------------------------------
.../tecsvc/client/FilterSystemQueryITCase.java | 7 +-
.../tecsvc/client/OrderBySystemQueryITCase.java | 7 +-
.../server/api/uri/queryoption/ExpandItem.java | 1 -
.../server/core/uri/parser/ExpandParser.java | 282 +++
.../core/uri/parser/ExpressionParser.java | 332 +--
.../server/core/uri/parser/FilterParser.java | 11 +-
.../olingo/server/core/uri/parser/Parser.java | 234 +-
.../server/core/uri/parser/ParserHelper.java | 34 +-
.../core/uri/parser/ResourcePathParser.java | 62 +-
.../server/core/uri/parser/SearchParser.java | 108 +
.../server/core/uri/parser/UriContext.java | 115 -
.../core/uri/parser/UriParseTreeVisitor.java | 2313 ------------------
.../server/core/uri/parser/UriTokenizer.java | 211 +-
.../uri/queryoption/expression/AliasImpl.java | 4 +
.../queryoption/expression/EnumerationImpl.java | 6 +
.../queryoption/expression/LambdaRefImpl.java | 5 +
.../queryoption/expression/TypeLiteralImpl.java | 5 +
.../server-core-exceptions-i18n.properties | 8 +-
.../core/uri/parser/ExpressionParserTest.java | 14 +-
.../core/uri/parser/UriTokenizerTest.java | 82 +-
.../search/SearchParserAndTokenizerTest.java | 44 +-
.../core/uri/antlr/TestFullResourcePath.java | 1311 +++++-----
.../olingo/server/core/uri/antlr/TestLexer.java | 450 ++--
.../core/uri/antlr/TestUriParserImpl.java | 220 +-
.../server/core/uri/parser/ParserTest.java | 56 +-
.../core/uri/testutil/ExpandValidator.java | 19 +-
.../core/uri/testutil/FilterValidator.java | 56 +-
.../core/uri/testutil/TestUriValidator.java | 38 +-
.../core/uri/testutil/TokenValidator.java | 127 -
29 files changed, 1941 insertions(+), 4221 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/FilterSystemQueryITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/FilterSystemQueryITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/FilterSystemQueryITCase.java
index ca6eb21..6865a65 100644
--- a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/FilterSystemQueryITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/FilterSystemQueryITCase.java
@@ -35,11 +35,8 @@ import org.apache.olingo.commons.api.edm.FullQualifiedName;
import org.apache.olingo.commons.api.http.HttpHeader;
import org.apache.olingo.commons.api.http.HttpStatusCode;
import org.junit.Assert;
-import org.junit.Ignore;
import org.junit.Test;
-// TODO
-@Ignore
public class FilterSystemQueryITCase extends AbstractParamTecSvcITCase {
private static final String ES_COMP_ALL_PRIM = "ESCompAllPrim";
@@ -212,7 +209,7 @@ public class FilterSystemQueryITCase extends AbstractParamTecSvcITCase {
sendRequest(ES_TWO_KEY_NAV, "PropertyComp/PropertyComp/PropertyBoolean eq not null");
assertEquals(0, result.getBody().getEntities().size());
- result = sendRequest(ES_TWO_KEY_NAV, "PropertyComp/PropertyComp/PropertyBoolean eq 0 add -(5 add null)");
+ result = sendRequest(ES_TWO_KEY_NAV, "PropertyComp/PropertyComp/PropertyInt16 eq 0 add -(5 add null)");
assertEquals(0, result.getBody().getEntities().size());
}
@@ -357,7 +354,7 @@ public class FilterSystemQueryITCase extends AbstractParamTecSvcITCase {
@Test
public void notOperator() {
- ODataRetrieveResponse<ClientEntitySet> result = sendRequest(ES_TWO_KEY_NAV, "not(PropertyInt16 eq 1)");
+ ODataRetrieveResponse<ClientEntitySet> result = sendRequest(ES_TWO_KEY_NAV, "not (PropertyInt16 eq 1)");
assertEquals(2, result.getBody().getEntities().size());
ClientEntity clientEntity = result.getBody().getEntities().get(0);
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/OrderBySystemQueryITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/OrderBySystemQueryITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/OrderBySystemQueryITCase.java
index 0e31b33..8e16a70 100644
--- a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/OrderBySystemQueryITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/OrderBySystemQueryITCase.java
@@ -30,11 +30,8 @@ import org.apache.olingo.client.api.domain.ClientEntitySet;
import org.apache.olingo.client.api.domain.ClientValuable;
import org.apache.olingo.commons.api.http.HttpStatusCode;
import org.junit.Assert;
-import org.junit.Ignore;
import org.junit.Test;
-// TODO
-@Ignore
public class OrderBySystemQueryITCase extends AbstractParamTecSvcITCase {
private static final String ES_TWO_PRIM = "ESTwoPrim";
@@ -74,7 +71,7 @@ public class OrderBySystemQueryITCase extends AbstractParamTecSvcITCase {
@Test
public void multipleOrderBy() {
- final ODataRetrieveResponse<ClientEntitySet> response = sendRequest(ES_ALL_PRIM, "PropertyByte, PropertyInt16");
+ final ODataRetrieveResponse<ClientEntitySet> response = sendRequest(ES_ALL_PRIM, "PropertyByte,PropertyInt16");
assertEquals(3, response.getBody().getEntities().size());
ClientEntity clientEntity = response.getBody().getEntities().get(0);
@@ -90,7 +87,7 @@ public class OrderBySystemQueryITCase extends AbstractParamTecSvcITCase {
@Test
public void multipleOrderByDescending() {
final ODataRetrieveResponse<ClientEntitySet> response =
- sendRequest(ES_ALL_PRIM, "PropertyByte, PropertyInt16 desc");
+ sendRequest(ES_ALL_PRIM, "PropertyByte,PropertyInt16 desc");
assertEquals(3, response.getBody().getEntities().size());
ClientEntity clientEntity = response.getBody().getEntities().get(0);
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/queryoption/ExpandItem.java
----------------------------------------------------------------------
diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/queryoption/ExpandItem.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/queryoption/ExpandItem.java
index a16c137..fccf844 100644
--- a/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/queryoption/ExpandItem.java
+++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/queryoption/ExpandItem.java
@@ -38,7 +38,6 @@ public interface ExpandItem {
FilterOption getFilterOption();
/**
- * <b>CURRENTLY NOT SUPPORTED. WILL ALWAYS RETURN NULL</b>
* @return Information of the option $search when used within $expand
*/
SearchOption getSearchOption();
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpandParser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpandParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpandParser.java
new file mode 100644
index 0000000..d8209d8
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpandParser.java
@@ -0,0 +1,282 @@
+/*
+ * 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 org.apache.olingo.commons.api.edm.Edm;
+import org.apache.olingo.commons.api.edm.EdmEntityType;
+import org.apache.olingo.commons.api.edm.EdmNavigationProperty;
+import org.apache.olingo.commons.api.edm.EdmProperty;
+import org.apache.olingo.commons.api.edm.EdmStructuredType;
+import org.apache.olingo.commons.api.edm.FullQualifiedName;
+import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
+import org.apache.olingo.commons.api.ex.ODataRuntimeException;
+import org.apache.olingo.server.api.OData;
+import org.apache.olingo.server.api.uri.UriInfoKind;
+import org.apache.olingo.server.api.uri.UriResourceNavigation;
+import org.apache.olingo.server.api.uri.UriResourcePartTyped;
+import org.apache.olingo.server.api.uri.queryoption.ExpandItem;
+import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
+import org.apache.olingo.server.api.uri.queryoption.LevelsExpandOption;
+import org.apache.olingo.server.api.uri.queryoption.SystemQueryOption;
+import org.apache.olingo.server.api.uri.queryoption.SystemQueryOptionKind;
+import org.apache.olingo.server.core.uri.UriInfoImpl;
+import org.apache.olingo.server.core.uri.UriResourceComplexPropertyImpl;
+import org.apache.olingo.server.core.uri.UriResourceCountImpl;
+import org.apache.olingo.server.core.uri.UriResourceNavigationPropertyImpl;
+import org.apache.olingo.server.core.uri.UriResourceRefImpl;
+import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind;
+import org.apache.olingo.server.core.uri.queryoption.CountOptionImpl;
+import org.apache.olingo.server.core.uri.queryoption.ExpandItemImpl;
+import org.apache.olingo.server.core.uri.queryoption.ExpandOptionImpl;
+import org.apache.olingo.server.core.uri.queryoption.LevelsOptionImpl;
+import org.apache.olingo.server.core.uri.queryoption.SkipOptionImpl;
+import org.apache.olingo.server.core.uri.queryoption.TopOptionImpl;
+import org.apache.olingo.server.core.uri.validator.UriValidationException;
+
+public class ExpandParser {
+
+ private final Edm edm;
+ private final OData odata;
+
+ public ExpandParser(final Edm edm, final OData odata) {
+ this.edm = edm;
+ this.odata = odata;
+ }
+
+ public ExpandOption parse(UriTokenizer tokenizer, final EdmStructuredType referencedType)
+ throws UriParserException, UriValidationException {
+ ExpandOptionImpl expandOption = new ExpandOptionImpl();
+ do {
+ final ExpandItem item = parseItem(tokenizer, referencedType);
+ expandOption.addExpandItem(item);
+ } while (tokenizer.next(TokenKind.COMMA));
+
+ return expandOption;
+ }
+
+ private ExpandItem parseItem(UriTokenizer tokenizer, final EdmStructuredType referencedType)
+ throws UriParserException, UriValidationException {
+ ExpandItemImpl item = new ExpandItemImpl();
+ if (tokenizer.next(TokenKind.STAR)) {
+ item.setIsStar(true);
+ if (tokenizer.next(TokenKind.SLASH)) {
+ ParserHelper.requireNext(tokenizer, TokenKind.REF);
+ item.setIsRef(true);
+ } else if (tokenizer.next(TokenKind.OPEN)) {
+ ParserHelper.requireNext(tokenizer, TokenKind.LEVELS);
+ ParserHelper.requireNext(tokenizer, TokenKind.EQ);
+ item.setSystemQueryOption((SystemQueryOption) parseLevels(tokenizer));
+ ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
+ }
+
+ } else {
+ final EdmStructuredType typeCast = parseTypeCast(tokenizer, referencedType);
+ if (typeCast != null) {
+ item.setTypeFilter(typeCast);
+ ParserHelper.requireNext(tokenizer, TokenKind.SLASH);
+ }
+
+ UriInfoImpl resource = parseExpandPath(tokenizer, referencedType);
+
+ UriResourcePartTyped lastPart = (UriResourcePartTyped) resource.getLastResourcePart();
+
+ boolean hasSlash = false;
+ if (tokenizer.next(TokenKind.SLASH)) {
+ hasSlash = true;
+ if (lastPart instanceof UriResourceNavigation) {
+ UriResourceNavigationPropertyImpl navigationResource = (UriResourceNavigationPropertyImpl) lastPart;
+ final EdmNavigationProperty navigationProperty = navigationResource.getProperty();
+ final EdmStructuredType typeCastSuffix = parseTypeCast(tokenizer, navigationProperty.getType());
+ if (typeCastSuffix != null) {
+ if (navigationProperty.isCollection()) {
+ navigationResource.setCollectionTypeFilter(typeCastSuffix);
+ } else {
+ navigationResource.setEntryTypeFilter(typeCastSuffix);
+ }
+ hasSlash = false;
+ }
+ }
+ }
+
+ final EdmStructuredType newReferencedType = (EdmStructuredType) lastPart.getType();
+ final boolean newReferencedIsCollection = lastPart.isCollection();
+ if (hasSlash || tokenizer.next(TokenKind.SLASH)) {
+ if (tokenizer.next(TokenKind.REF)) {
+ resource.addResourcePart(new UriResourceRefImpl());
+ parseOptions(tokenizer, newReferencedType, newReferencedIsCollection, item, true, false);
+ } else {
+ ParserHelper.requireNext(tokenizer, TokenKind.COUNT);
+ resource.addResourcePart(new UriResourceCountImpl());
+ parseOptions(tokenizer, newReferencedType, newReferencedIsCollection, item, false, true);
+ }
+ } else {
+ parseOptions(tokenizer, newReferencedType, newReferencedIsCollection, item, false, false);
+ }
+
+ item.setResourcePath(resource);
+ }
+
+ return item;
+ }
+
+ private EdmStructuredType parseTypeCast(UriTokenizer tokenizer, final EdmStructuredType referencedType)
+ throws UriParserException {
+ if (tokenizer.next(TokenKind.QualifiedName)) {
+ final FullQualifiedName qualifiedName = new FullQualifiedName(tokenizer.getText());
+ final EdmStructuredType type = referencedType instanceof EdmEntityType ?
+ edm.getEntityType(qualifiedName) :
+ edm.getComplexType(qualifiedName);
+ if (type == null) {
+ throw new UriParserSemanticException("Type '" + qualifiedName + "' not found.",
+ UriParserSemanticException.MessageKeys.UNKNOWN_PART, qualifiedName.getFullQualifiedNameAsString());
+ } else {
+ if (!type.compatibleTo(referencedType)) {
+ throw new UriParserSemanticException("The type cast '" + qualifiedName + "' is not compatible.",
+ UriParserSemanticException.MessageKeys.INCOMPATIBLE_TYPE_FILTER, type.getName());
+ }
+ }
+ return type;
+ }
+ return null;
+ }
+
+ private UriInfoImpl parseExpandPath(UriTokenizer tokenizer, final EdmStructuredType referencedType)
+ throws UriParserException {
+ UriInfoImpl resource = new UriInfoImpl().setKind(UriInfoKind.resource);
+
+ EdmStructuredType type = referencedType;
+ String name = null;
+ while (tokenizer.next(TokenKind.ODataIdentifier)) {
+ name = tokenizer.getText();
+ final EdmProperty property = referencedType.getStructuralProperty(name);
+ if (property != null && property.getType().getKind() == EdmTypeKind.COMPLEX) {
+ type = (EdmStructuredType) property.getType();
+ UriResourceComplexPropertyImpl complexResource = new UriResourceComplexPropertyImpl(property);
+ ParserHelper.requireNext(tokenizer, TokenKind.SLASH);
+ final EdmStructuredType typeCast = parseTypeCast(tokenizer, type);
+ if (typeCast != null) {
+ complexResource.setTypeFilter(typeCast);
+ ParserHelper.requireNext(tokenizer, TokenKind.SLASH);
+ type = typeCast;
+ }
+ resource.addResourcePart(complexResource);
+ }
+ }
+
+ final EdmNavigationProperty navigationProperty = type.getNavigationProperty(name);
+ if (navigationProperty == null) {
+ // TODO: could also have been star after complex property (and maybe type cast)
+ throw new UriParserSemanticException(
+ "Navigation Property '" + name + "' not found in type '" + type.getFullQualifiedName() + "'.",
+ UriParserSemanticException.MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE, type.getName(), name);
+ } else {
+ resource.addResourcePart(new UriResourceNavigationPropertyImpl(navigationProperty));
+ }
+
+ return resource;
+ }
+
+ private void parseOptions(UriTokenizer tokenizer,
+ final EdmStructuredType referencedType, final boolean referencedIsCollection,
+ ExpandItemImpl item,
+ final boolean forRef, final boolean forCount) throws UriParserException, UriValidationException {
+ if (tokenizer.next(TokenKind.OPEN)) {
+ do {
+ SystemQueryOption systemQueryOption;
+ if (!forCount && tokenizer.next(TokenKind.COUNT)) {
+ ParserHelper.requireNext(tokenizer, TokenKind.EQ);
+ ParserHelper.requireNext(tokenizer, TokenKind.BooleanValue);
+ CountOptionImpl countOption = new CountOptionImpl();
+ countOption.setText(tokenizer.getText());
+ countOption.setValue(Boolean.parseBoolean(tokenizer.getText()));
+ systemQueryOption = countOption;
+
+ } else if (!forRef && !forCount && tokenizer.next(TokenKind.EXPAND)) {
+ ParserHelper.requireNext(tokenizer, TokenKind.EQ);
+ systemQueryOption = new ExpandParser(edm, odata).parse(tokenizer, referencedType);
+
+ } else if (tokenizer.next(TokenKind.FILTER)) {
+ ParserHelper.requireNext(tokenizer, TokenKind.EQ);
+ systemQueryOption = new FilterParser(edm, odata).parse(tokenizer, referencedType, null);
+
+ } else if (!forRef && !forCount && tokenizer.next(TokenKind.LEVELS)) {
+ ParserHelper.requireNext(tokenizer, TokenKind.EQ);
+ systemQueryOption = (SystemQueryOption) parseLevels(tokenizer);
+
+ } else if (!forCount && tokenizer.next(TokenKind.ORDERBY)) {
+ ParserHelper.requireNext(tokenizer, TokenKind.EQ);
+ systemQueryOption = new OrderByParser(edm, odata).parse(tokenizer, referencedType, null);
+
+ } else if (tokenizer.next(TokenKind.SEARCH)) {
+ ParserHelper.requireNext(tokenizer, TokenKind.EQ);
+ systemQueryOption = new SearchParser().parse(tokenizer);
+
+ } else if (!forRef && !forCount && tokenizer.next(TokenKind.SELECT)) {
+ ParserHelper.requireNext(tokenizer, TokenKind.EQ);
+ systemQueryOption = new SelectParser(edm).parse(tokenizer, referencedType, referencedIsCollection);
+
+ } else if (!forCount && tokenizer.next(TokenKind.SKIP)) {
+ ParserHelper.requireNext(tokenizer, TokenKind.EQ);
+ ParserHelper.requireNext(tokenizer, TokenKind.IntegerValue);
+ final int value = ParserHelper.parseNonNegativeInteger(SystemQueryOptionKind.SKIP.toString(),
+ tokenizer.getText(), true);
+ SkipOptionImpl skipOption = new SkipOptionImpl();
+ skipOption.setText(tokenizer.getText());
+ skipOption.setValue(value);
+ systemQueryOption = skipOption;
+
+ } else if (!forCount && tokenizer.next(TokenKind.TOP)) {
+ ParserHelper.requireNext(tokenizer, TokenKind.EQ);
+ ParserHelper.requireNext(tokenizer, TokenKind.IntegerValue);
+ final int value = ParserHelper.parseNonNegativeInteger(SystemQueryOptionKind.TOP.toString(),
+ tokenizer.getText(), true);
+ TopOptionImpl topOption = new TopOptionImpl();
+ topOption.setText(tokenizer.getText());
+ topOption.setValue(value);
+ systemQueryOption = topOption;
+
+ } else {
+ throw new UriParserSyntaxException("Allowed query option expected.",
+ UriParserSyntaxException.MessageKeys.SYNTAX);
+ }
+ try {
+ item.setSystemQueryOption(systemQueryOption);
+ } catch (final ODataRuntimeException e) {
+ throw new UriParserSyntaxException("Double system query option '" + systemQueryOption.getName() + "'.", e,
+ UriParserSyntaxException.MessageKeys.DOUBLE_SYSTEM_QUERY_OPTION, systemQueryOption.getName());
+ }
+ } while (tokenizer.next(TokenKind.SEMI));
+ ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
+ }
+ }
+
+ private LevelsExpandOption parseLevels(UriTokenizer tokenizer) throws UriParserException {
+ final LevelsOptionImpl option = new LevelsOptionImpl();
+ if (tokenizer.next(TokenKind.MAX)) {
+ option.setText(tokenizer.getText());
+ option.setMax();
+ } else {
+ ParserHelper.requireNext(tokenizer, TokenKind.IntegerValue);
+ option.setText(tokenizer.getText());
+ option.setValue(
+ ParserHelper.parseNonNegativeInteger(SystemQueryOptionKind.LEVELS.toString(), tokenizer.getText(), false));
+ }
+ return option;
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java
index 049880f..6fa415f 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java
@@ -47,9 +47,6 @@ import org.apache.olingo.commons.api.edm.EdmType;
import org.apache.olingo.commons.api.edm.EdmTypeDefinition;
import org.apache.olingo.commons.api.edm.FullQualifiedName;
import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmByte;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmSByte;
import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.uri.UriParameter;
import org.apache.olingo.server.api.uri.UriResourceFunction;
@@ -161,7 +158,7 @@ public class ExpressionParser {
private static final Map<TokenKind, EdmPrimitiveTypeKind> tokenToPrimitiveType;
static {
- /* Enum and null are not present in the map. These have to be handled differently */
+ /* Enum and null are not present in the map. These have to be handled differently. */
Map<TokenKind, EdmPrimitiveTypeKind> temp = new HashMap<TokenKind, EdmPrimitiveTypeKind>();
temp.put(TokenKind.BooleanValue, EdmPrimitiveTypeKind.Boolean);
temp.put(TokenKind.StringValue, EdmPrimitiveTypeKind.String);
@@ -242,9 +239,9 @@ public class ExpressionParser {
}
private Expression parseExprRel() throws UriParserException, UriValidationException {
- if(tokenizer.next(TokenKind.IsofMethod)) {
- // The isof method is a terminal. So no further operators are allowed
- return parseIsOfMethod(TokenKind.IsofMethod);
+ if (tokenizer.next(TokenKind.IsofMethod)) {
+ // The isof method is a terminal. So no further operators are allowed.
+ return parseIsOfOrCastMethod(MethodKind.ISOF);
} else {
Expression left = parseExprAdd();
TokenKind operatorTokenKind = ParserHelper.next(tokenizer,
@@ -264,30 +261,25 @@ public class ExpressionParser {
}
}
- private Expression parseIsOfMethod(final TokenKind lastToken) throws UriParserException, UriValidationException {
- if(lastToken == TokenKind.IsofMethod) {
- // The TokenKind 'IsOfMethod' consumes also the opening parenthesis
-
- // The first parameter could be an expression or a type literal
- final List<Expression> parameters = new ArrayList<Expression>();
+ private Expression parseIsOfOrCastMethod(final MethodKind kind) throws UriParserException, UriValidationException {
+ // The TokenKind 'IsOfMethod' consumes also the opening parenthesis.
+ // The first parameter could be an expression or a type literal.
+ List<Expression> parameters = new ArrayList<Expression>();
+ parameters.add(parseExpression());
+ if (!(parameters.get(0) instanceof TypeLiteral)) {
+ // The first parameter is not a type literal, so there must be a second parameter.
+ ParserHelper.requireNext(tokenizer, TokenKind.COMMA);
parameters.add(parseExpression());
- if(!(parameters.get(0) instanceof TypeLiteral)) {
- // The first parameter is not a type literal, so there must be a second parameter
- ParserHelper.requireNext(tokenizer, TokenKind.COMMA);
- parameters.add(parseExpression());
-
- // The second parameter must be a type literal
- if(!(parameters.get(1) instanceof TypeLiteral)) {
- throw new UriParserSemanticException("Type literal extected",
- UriParserSemanticException.MessageKeys.INCOMPATIBLE_TYPE_FILTER);
- }
+
+ // The second parameter must be a type literal.
+ if (!(parameters.get(1) instanceof TypeLiteral)) {
+ throw new UriParserSemanticException("Type literal expected.",
+ UriParserSemanticException.MessageKeys.INCOMPATIBLE_TYPE_FILTER);
}
-
- ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
- return new MethodImpl(MethodKind.ISOF, parameters);
- } else {
- throw new UriParserSyntaxException("Unexpected token.", UriParserSyntaxException.MessageKeys.SYNTAX);
}
+
+ ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
+ return new MethodImpl(kind, parameters);
}
private Expression parseExprAdd() throws UriParserException, UriValidationException {
@@ -296,9 +288,9 @@ public class ExpressionParser {
// Null for everything other than ADD or SUB
while (operatorTokenKind != null) {
final Expression right = parseExprMul();
- checkAddSubTypes(left, right, operatorTokenKind == TokenKind.AddOperator);
- left = new BinaryImpl(left, tokenToBinaryOperator.get(operatorTokenKind), right,
- odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Double));
+ final EdmType resultType = getAddSubTypeAndCheckLeftAndRight(left, right,
+ operatorTokenKind == TokenKind.SubOperator);
+ left = new BinaryImpl(left, tokenToBinaryOperator.get(operatorTokenKind), right, resultType);
operatorTokenKind = ParserHelper.next(tokenizer, TokenKind.AddOperator, TokenKind.SubOperator);
}
return left;
@@ -328,10 +320,7 @@ public class ExpressionParser {
}
private Expression parseExprUnary() throws UriParserException, UriValidationException {
- final TokenKind operatorTokenKind = ParserHelper.next(tokenizer, TokenKind.MINUS, TokenKind.NotOperator,
- TokenKind.CastMethod);
-
- if(operatorTokenKind == TokenKind.MINUS) {
+ if (tokenizer.next(TokenKind.MinusOperator)) {
final Expression expression = parseExprPrimary();
checkType(expression,
EdmPrimitiveTypeKind.Int16, EdmPrimitiveTypeKind.Int32, EdmPrimitiveTypeKind.Int64,
@@ -339,37 +328,14 @@ public class ExpressionParser {
EdmPrimitiveTypeKind.Decimal, EdmPrimitiveTypeKind.Single, EdmPrimitiveTypeKind.Double,
EdmPrimitiveTypeKind.Duration);
return new UnaryImpl(UnaryOperatorKind.MINUS, expression, getType(expression));
- } else if(operatorTokenKind == TokenKind.NotOperator) {
+ } else if (tokenizer.next(TokenKind.NotOperator)) {
final Expression expression = parseExprPrimary();
checkType(expression, EdmPrimitiveTypeKind.Boolean);
return new UnaryImpl(UnaryOperatorKind.NOT, expression, getType(expression));
- } else if(operatorTokenKind == TokenKind.CastMethod) {
- return parseCastMethod(operatorTokenKind);
+ } else if (tokenizer.next(TokenKind.CastMethod)) {
+ return parseIsOfOrCastMethod(MethodKind.CAST);
} else {
- final Expression expression = parseExprPrimary();
- return expression;
- }
- }
-
- private Expression parseCastMethod(final TokenKind lastToken) throws UriParserException, UriValidationException {
- // The TokenKind 'CastMethod' consumes also the opening parenthesis
- if(lastToken == TokenKind.CastMethod) {
- final List<Expression> parameters = new ArrayList<Expression>();
- parameters.add(parseExpression());
-
- if(!(parameters.get(0) instanceof TypeLiteral)) {
- ParserHelper.requireNext(tokenizer, TokenKind.COMMA);
- parameters.add(parseExpression());
- if(!(parameters.get(1) instanceof TypeLiteral)) {
- throw new UriParserSemanticException("Type literal extected",
- UriParserSemanticException.MessageKeys.INCOMPATIBLE_TYPE_FILTER);
- }
- }
-
- ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
- return new MethodImpl(MethodKind.CAST, parameters);
- } else {
- throw new UriParserSyntaxException("Unexpected token.", UriParserSyntaxException.MessageKeys.SYNTAX);
+ return parseExprPrimary();
}
}
@@ -433,22 +399,20 @@ public class ExpressionParser {
private Expression parseMethod(final TokenKind nextMethod) throws UriParserException, UriValidationException {
// The method token text includes the opening parenthesis so that method calls can be recognized unambiguously.
// OData identifiers have to be considered after that.
-
final MethodKind methodKind = tokenToMethod.get(nextMethod);
return new MethodImpl(methodKind, parseMethodParameters(methodKind));
}
- private Expression parsePrimitive(TokenKind nextPrimitive) throws UriParserException {
+ private Expression parsePrimitive(final TokenKind primitiveTokenKind) throws UriParserException {
final String primitiveValueLiteral = tokenizer.getText();
- if (nextPrimitive == TokenKind.EnumValue) {
+ if (primitiveTokenKind == TokenKind.EnumValue) {
return createEnumExpression(primitiveValueLiteral);
} else {
- EdmPrimitiveTypeKind primitiveTypeKind = tokenToPrimitiveType.get(nextPrimitive);
-
- if(primitiveTypeKind == EdmPrimitiveTypeKind.Int64) {
+ EdmPrimitiveTypeKind primitiveTypeKind = tokenToPrimitiveType.get(primitiveTokenKind);
+ if (primitiveTypeKind == EdmPrimitiveTypeKind.Int64) {
primitiveTypeKind = determineIntegerType(primitiveValueLiteral);
}
-
+
final EdmPrimitiveType type = primitiveTypeKind == null ?
// Null handling
null :
@@ -472,12 +436,11 @@ public class ExpressionParser {
} else {
typeKind = EdmPrimitiveTypeKind.Int64;
}
- } catch (NumberFormatException e) {
- // This should never happen. Because the tokenizer has figured out that the literal is an integer
- throw new UriParserSyntaxException(intValueAsString + " is not an integer",
+ } catch (final NumberFormatException e) {
+ // This should never happen because the tokenizer has figured out that the literal is an integer.
+ throw new UriParserSyntaxException("'" + intValueAsString + "' is not an integer.", e,
UriParserSyntaxException.MessageKeys.SYNTAX);
}
-
return typeKind;
}
@@ -622,19 +585,19 @@ public class ExpressionParser {
if (filterType == null) {
filterType = edm.getComplexType(fullQualifiedName);
}
-
- if(filterType == null) {
- filterType = getEdmType(fullQualifiedName);
+
+ if (filterType == null) {
+ filterType = getPrimitiveType(fullQualifiedName);
}
-
- if(filterType == null) {
+
+ if (filterType == null) {
filterType = edm.getEnumType(fullQualifiedName);
}
-
- if(filterType == null) {
+
+ if (filterType == null) {
filterType = edm.getTypeDefinition(fullQualifiedName);
}
-
+
if (filterType != null) {
if (tokenizer.next(TokenKind.SLASH)) {
// Leading type cast
@@ -642,30 +605,29 @@ public class ExpressionParser {
startTypeFilter = filterType;
final TokenKind tokenKind = ParserHelper.next(tokenizer, TokenKind.QualifiedName, TokenKind.ODataIdentifier);
- parseMemberExpression(tokenKind, uriInfo, new UriResourceStartingTypeFilterImpl(filterType, false),
- false);
+ parseMemberExpression(tokenKind, uriInfo, new UriResourceStartingTypeFilterImpl(filterType, false), false);
} else {
// Type literal
return new TypeLiteralImpl(filterType);
}
} else {
- // Must be bound or unbound function.
+ // Must be bound or unbound function.
parseFunction(fullQualifiedName, uriInfo, referringType, true);
}
} else if (lastTokenKind == TokenKind.ODataIdentifier) {
parseFirstMemberODataIdentifier(uriInfo);
}
-
+
return new MemberImpl(uriInfo, startTypeFilter);
}
- private EdmType getEdmType(final FullQualifiedName fullQualifiedName) {
- if(!fullQualifiedName.getNamespace().equals(EdmPrimitiveType.EDM_NAMESPACE)) {
+ private EdmType getPrimitiveType(final FullQualifiedName fullQualifiedName) {
+ if (EdmPrimitiveType.EDM_NAMESPACE.equals(fullQualifiedName.getNamespace())) {
+ final EdmPrimitiveTypeKind primitiveTypeKind = EdmPrimitiveTypeKind.valueOf(fullQualifiedName.getName());
+ return primitiveTypeKind == null ? null : odata.createPrimitiveTypeInstance(primitiveTypeKind);
+ } else {
return null;
}
-
- final EdmPrimitiveTypeKind primitiveTypeKind = EdmPrimitiveTypeKind.valueOfFQN(fullQualifiedName);
- return primitiveTypeKind == null ? null : EdmPrimitiveTypeFactory.getInstance(primitiveTypeKind);
}
private void parseDollarRoot(UriInfoImpl uriInfo) throws UriParserException, UriValidationException {
@@ -694,7 +656,7 @@ public class ExpressionParser {
parseSingleNavigationExpr(uriInfo, resource);
}
- private void parseDollarIt(UriInfoImpl uriInfo, EdmType referringType)
+ private void parseDollarIt(UriInfoImpl uriInfo, final EdmType referringType)
throws UriParserException, UriValidationException {
UriResourceItImpl itResource = new UriResourceItImpl(referringType, false);
uriInfo.addResourcePart(itResource);
@@ -759,16 +721,14 @@ public class ExpressionParser {
if (edmEntityType != null) {
if (allowTypeFilter) {
setTypeFilter(lastResource, edmEntityType);
-
- if(tokenizer.next(TokenKind.SLASH)) {
- final TokenKind nextTokenKind = ParserHelper.next(tokenizer, TokenKind.QualifiedName,
- TokenKind.ODataIdentifier);
- if(nextTokenKind == TokenKind.ODataIdentifier) {
- parsePropertyPathExpr(uriInfo, lastResource);
- } else if(nextTokenKind == TokenKind.QualifiedName) {
+
+ if (tokenizer.next(TokenKind.SLASH)) {
+ if (tokenizer.next(TokenKind.QualifiedName)) {
parseBoundFunction(fullQualifiedName, uriInfo, lastResource);
+ } else if (tokenizer.next(TokenKind.ODataIdentifier)) {
+ parsePropertyPathExpr(uriInfo, lastResource);
} else {
- throw new UriParserSyntaxException("Extected OData Identifier or Full Qualified Name",
+ throw new UriParserSyntaxException("Expected OData Identifier or Full Qualified Name.",
UriParserSyntaxException.MessageKeys.SYNTAX);
}
}
@@ -814,7 +774,9 @@ public class ExpressionParser {
if (property == null) {
throw new UriParserSemanticException("Unknown property.",
- UriParserSemanticException.MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE, oDataIdentifier);
+ UriParserSemanticException.MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE,
+ lastType.getFullQualifiedName().getFullQualifiedNameAsString(),
+ oDataIdentifier);
}
if (property.getType() instanceof EdmComplexType) {
@@ -823,7 +785,9 @@ public class ExpressionParser {
uriInfo.addResourcePart(complexResource);
if (property.isCollection()) {
- parseCollectionPathExpr(uriInfo, complexResource);
+ if (tokenizer.next(TokenKind.SLASH)) {
+ parseCollectionPathExpr(uriInfo, complexResource);
+ }
} else {
parseComplexPathExpr(uriInfo, complexResource);
}
@@ -847,7 +811,9 @@ public class ExpressionParser {
uriInfo.addResourcePart(primitiveResource);
if (property.isCollection()) {
- parseCollectionPathExpr(uriInfo, primitiveResource);
+ if (tokenizer.next(TokenKind.SLASH)) {
+ parseCollectionPathExpr(uriInfo, primitiveResource);
+ }
} else {
parseSinglePathExpr(uriInfo, primitiveResource);
}
@@ -856,7 +822,6 @@ public class ExpressionParser {
private void parseSingleNavigationExpr(UriInfoImpl uriInfo, final UriResourcePartTyped lastResource)
throws UriParserException, UriValidationException {
- // TODO: Is that correct?
if (tokenizer.next(TokenKind.SLASH)) {
final TokenKind tokenKind = ParserHelper.next(tokenizer, TokenKind.QualifiedName, TokenKind.ODataIdentifier);
parseMemberExpression(tokenKind, uriInfo, lastResource, true);
@@ -865,8 +830,22 @@ public class ExpressionParser {
private void parseCollectionNavigationExpr(UriInfoImpl uriInfo, UriResourcePartTyped lastResource)
throws UriParserException, UriValidationException {
- // TODO: Is type cast missing?
- if (tokenizer.next(TokenKind.OPEN)) {
+ boolean hasSlash = false;
+ if (tokenizer.next(TokenKind.SLASH)) {
+ hasSlash = true;
+ if (tokenizer.next(TokenKind.QualifiedName)) {
+ final FullQualifiedName qualifiedName = new FullQualifiedName(tokenizer.getText());
+ final EdmEntityType edmEntityType = edm.getEntityType(qualifiedName);
+ if (edmEntityType == null) {
+ parseBoundFunction(qualifiedName, uriInfo, lastResource);
+ } else {
+ setTypeFilter(lastResource, edmEntityType);
+ }
+ hasSlash = false;
+ }
+ }
+
+ if (!hasSlash && tokenizer.next(TokenKind.OPEN)) {
if (lastResource instanceof UriResourceNavigation) {
((UriResourceNavigationPropertyImpl) lastResource).setKeyPredicates(
ParserHelper.parseNavigationKeyPredicate(tokenizer,
@@ -883,7 +862,10 @@ public class ExpressionParser {
}
parseSingleNavigationExpr(uriInfo, lastResource);
}
- parseCollectionPathExpr(uriInfo, lastResource);
+
+ if (hasSlash || tokenizer.next(TokenKind.SLASH)) {
+ parseCollectionPathExpr(uriInfo, lastResource);
+ }
}
private void parseSinglePathExpr(UriInfoImpl uriInfo, final UriResourcePartTyped lastResource)
@@ -932,25 +914,23 @@ public class ExpressionParser {
private void parseCollectionPathExpr(UriInfoImpl uriInfo, final UriResourcePartTyped lastResource)
throws UriParserException, UriValidationException {
-
- if (tokenizer.next(TokenKind.SLASH)) {
- if (tokenizer.next(TokenKind.COUNT)) {
- uriInfo.addResourcePart(new UriResourceCountImpl());
- } else if (tokenizer.next(TokenKind.ANY)) {
- uriInfo.addResourcePart(parseLambdaRest(TokenKind.ANY, lastResource));
- } else if (tokenizer.next(TokenKind.ALL)) {
- uriInfo.addResourcePart(parseLambdaRest(TokenKind.ALL, lastResource));
- } else if (tokenizer.next(TokenKind.QualifiedName)) {
- final FullQualifiedName fullQualifiedName = new FullQualifiedName(tokenizer.getText());
- parseBoundFunction(fullQualifiedName, uriInfo, lastResource);
- }
+ // The initial slash (see grammar) must have been checked and consumed by the caller.
+ if (tokenizer.next(TokenKind.COUNT)) {
+ uriInfo.addResourcePart(new UriResourceCountImpl());
+ } else if (tokenizer.next(TokenKind.ANY)) {
+ uriInfo.addResourcePart(parseLambdaRest(TokenKind.ANY, lastResource));
+ } else if (tokenizer.next(TokenKind.ALL)) {
+ uriInfo.addResourcePart(parseLambdaRest(TokenKind.ALL, lastResource));
+ } else if (tokenizer.next(TokenKind.QualifiedName)) {
+ final FullQualifiedName fullQualifiedName = new FullQualifiedName(tokenizer.getText());
+ parseBoundFunction(fullQualifiedName, uriInfo, lastResource);
}
}
private void parseFunction(final FullQualifiedName fullQualifiedName, UriInfoImpl uriInfo,
final EdmType lastType, final boolean lastIsCollection) throws UriParserException, UriValidationException {
- final List<UriParameter> parameters = ParserHelper.parseFunctionParameters(tokenizer, true);
+ final List<UriParameter> parameters = ParserHelper.parseFunctionParameters(tokenizer, edm, referringType, true);
final List<String> parameterNames = ParserHelper.getParameterNames(parameters);
final EdmFunction boundFunction = edm.getBoundFunction(fullQualifiedName,
lastType.getFullQualifiedName(), lastIsCollection, parameterNames);
@@ -966,18 +946,19 @@ public class ExpressionParser {
return;
}
- throw new UriParserSemanticException("No function found.",
+ throw new UriParserSemanticException("No function '" + fullQualifiedName + "' found.",
UriParserSemanticException.MessageKeys.FUNCTION_NOT_FOUND, fullQualifiedName.getFullQualifiedNameAsString());
}
private void parseBoundFunction(final FullQualifiedName fullQualifiedName, UriInfoImpl uriInfo,
final UriResourcePartTyped lastResource) throws UriParserException, UriValidationException {
- final List<UriParameter> parameters = ParserHelper.parseFunctionParameters(tokenizer, true);
+ final EdmType type = lastResource.getType();
+ final List<UriParameter> parameters = ParserHelper.parseFunctionParameters(tokenizer, edm, referringType, true);
final List<String> parameterNames = ParserHelper.getParameterNames(parameters);
final EdmFunction boundFunction = edm.getBoundFunction(fullQualifiedName,
- lastResource.getType().getFullQualifiedName(), lastResource.isCollection(), parameterNames);
+ type.getFullQualifiedName(), lastResource.isCollection(), parameterNames);
if (boundFunction == null) {
- throw new UriParserSemanticException("Bound function not found.",
+ throw new UriParserSemanticException("Bound function '" + fullQualifiedName + "' not found.",
UriParserSemanticException.MessageKeys.FUNCTION_NOT_FOUND, fullQualifiedName.getFullQualifiedNameAsString());
}
parseFunctionRest(uriInfo, boundFunction, parameters);
@@ -995,19 +976,23 @@ public class ExpressionParser {
if (function.isComposable()) {
if (edmType instanceof EdmEntityType ) {
if (isCollection) {
- parseCollectionNavigationExpr(uriInfo, functionResource);
+ parseCollectionNavigationExpr(uriInfo, functionResource);
} else {
parseSingleNavigationExpr(uriInfo, functionResource);
}
} else if (edmType instanceof EdmComplexType) {
if (isCollection) {
- parseCollectionPathExpr(uriInfo, functionResource);
+ if (tokenizer.next(TokenKind.SLASH)) {
+ parseCollectionPathExpr(uriInfo, functionResource);
+ }
} else {
parseComplexPathExpr(uriInfo, functionResource);
}
} else if (edmType instanceof EdmPrimitiveType) {
if (isCollection) {
- parseCollectionPathExpr(uriInfo, functionResource);
+ if (tokenizer.next(TokenKind.SLASH)) {
+ parseCollectionPathExpr(uriInfo, functionResource);
+ }
} else {
parseSinglePathExpr(uriInfo, functionResource);
}
@@ -1077,7 +1062,7 @@ public class ExpressionParser {
TokenKind.YearMethod);
}
- private EdmType getType(final Expression expression) throws UriParserException {
+ protected static EdmType getType(final Expression expression) throws UriParserException {
EdmType type;
if (expression instanceof Literal) {
type = ((Literal) expression).getType();
@@ -1108,13 +1093,12 @@ public class ExpressionParser {
return type;
}
- private boolean isType(final Expression expression, final EdmPrimitiveTypeKind... kinds) throws UriParserException {
- final EdmType expressionType = getType(expression);
- if (expressionType == null) {
+ private boolean isType(final EdmType type, final EdmPrimitiveTypeKind... kinds) throws UriParserException {
+ if (type == null) {
return true;
}
for (final EdmPrimitiveTypeKind kind : kinds) {
- if (expressionType.equals(odata.createPrimitiveTypeInstance(kind))) {
+ if (type.equals(odata.createPrimitiveTypeInstance(kind))) {
return true;
}
}
@@ -1122,12 +1106,13 @@ public class ExpressionParser {
}
private void checkType(final Expression expression, final EdmPrimitiveTypeKind... kinds) throws UriParserException {
- if (!isType(expression, kinds)) {
+ final EdmType type = getType(expression);
+ if (!isType(type, kinds)) {
throw new UriParserSemanticException("Incompatible type.",
UriParserSemanticException.MessageKeys.UNKNOWN_TYPE, // TODO: better message
- getType(expression) == null ?
+ type == null ?
"" :
- getType(expression).getFullQualifiedName().getFullQualifiedNameAsString());
+ type.getFullQualifiedName().getFullQualifiedNameAsString());
}
}
@@ -1137,21 +1122,21 @@ public class ExpressionParser {
if (leftType == null || rightType == null || leftType.equals(rightType)) {
return;
}
-
+
// Numeric promotion for Edm.Byte and Edm.SByte
- if((leftType instanceof EdmByte || leftType instanceof EdmSByte)
- && (rightType instanceof EdmByte || rightType instanceof EdmSByte)) {
+ if (isType(leftType, EdmPrimitiveTypeKind.Byte, EdmPrimitiveTypeKind.SByte)
+ && isType(rightType, EdmPrimitiveTypeKind.Byte, EdmPrimitiveTypeKind.SByte)) {
return;
}
-
+
if (leftType.getKind() != EdmTypeKind.PRIMITIVE
|| rightType.getKind() != EdmTypeKind.PRIMITIVE
|| !(((EdmPrimitiveType) leftType).isCompatible((EdmPrimitiveType) rightType)
- || ((EdmPrimitiveType) rightType).isCompatible((EdmPrimitiveType) leftType)))
- {
+ || ((EdmPrimitiveType) rightType).isCompatible((EdmPrimitiveType) leftType))) {
throw new UriParserSemanticException("Incompatible types.",
- UriParserSemanticException.MessageKeys.TYPES_NOT_COMPATIBLE, leftType.getFullQualifiedName().toString(),
- rightType.getFullQualifiedName().toString());
+ UriParserSemanticException.MessageKeys.TYPES_NOT_COMPATIBLE,
+ leftType.getFullQualifiedName().getFullQualifiedNameAsString(),
+ rightType.getFullQualifiedName().getFullQualifiedNameAsString());
}
}
@@ -1164,12 +1149,12 @@ public class ExpressionParser {
}
return type;
}
-
+
private boolean isEnumType(final Expression expression) throws UriParserException {
final EdmType expressionType = getType(expression);
return expressionType == null
|| expressionType.getKind() == EdmTypeKind.ENUM
- || isType(expression,
+ || isType(expressionType,
EdmPrimitiveTypeKind.Int16, EdmPrimitiveTypeKind.Int32, EdmPrimitiveTypeKind.Int64,
EdmPrimitiveTypeKind.Byte, EdmPrimitiveTypeKind.SByte);
}
@@ -1208,44 +1193,69 @@ public class ExpressionParser {
EdmPrimitiveTypeKind.Date, EdmPrimitiveTypeKind.TimeOfDay,
EdmPrimitiveTypeKind.DateTimeOffset, EdmPrimitiveTypeKind.Duration);
if (!(((EdmPrimitiveType) leftType).isCompatible((EdmPrimitiveType) rightType)
- || ((EdmPrimitiveType) rightType).isCompatible((EdmPrimitiveType) leftType))) {
+ || ((EdmPrimitiveType) rightType).isCompatible((EdmPrimitiveType) leftType))) {
throw new UriParserSemanticException("Incompatible types.",
- UriParserSemanticException.MessageKeys.UNKNOWN_TYPE, ""); // TODO: better message
+ UriParserSemanticException.MessageKeys.TYPES_NOT_COMPATIBLE,
+ leftType.getFullQualifiedName().getFullQualifiedNameAsString(),
+ rightType.getFullQualifiedName().getFullQualifiedNameAsString());
}
}
- private void checkAddSubTypes(final Expression left, final Expression right, final boolean isAdd)
+ private EdmType getAddSubTypeAndCheckLeftAndRight(final Expression left, final Expression right, final boolean isSub)
throws UriParserException {
final EdmType leftType = getType(left);
final EdmType rightType = getType(right);
- if (leftType == null || rightType == null
- || isType(left,
+ if (leftType == null || rightType == null) {
+ return null;
+ }
+ if (isType(leftType,
EdmPrimitiveTypeKind.Int16, EdmPrimitiveTypeKind.Int32, EdmPrimitiveTypeKind.Int64,
EdmPrimitiveTypeKind.Byte, EdmPrimitiveTypeKind.SByte,
EdmPrimitiveTypeKind.Decimal, EdmPrimitiveTypeKind.Single, EdmPrimitiveTypeKind.Double)
- && isType(right,
+ && isType(rightType,
EdmPrimitiveTypeKind.Int16, EdmPrimitiveTypeKind.Int32, EdmPrimitiveTypeKind.Int64,
EdmPrimitiveTypeKind.Byte, EdmPrimitiveTypeKind.SByte,
EdmPrimitiveTypeKind.Decimal, EdmPrimitiveTypeKind.Single, EdmPrimitiveTypeKind.Double)) {
- return;
+ // The result type must be able to handle the overflow,
+ // so we return always a wider type than the types of the operands.
+ if (isType(leftType, EdmPrimitiveTypeKind.Decimal, EdmPrimitiveTypeKind.Single, EdmPrimitiveTypeKind.Double)
+ || isType(rightType,
+ EdmPrimitiveTypeKind.Decimal, EdmPrimitiveTypeKind.Single, EdmPrimitiveTypeKind.Double)) {
+ return odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Double);
+ } else if (isType(leftType, EdmPrimitiveTypeKind.Int64) || isType(rightType, EdmPrimitiveTypeKind.Int64)) {
+ return odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Decimal);
+ } else if (isType(leftType, EdmPrimitiveTypeKind.Int32) || isType(rightType, EdmPrimitiveTypeKind.Int32)) {
+ return odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int64);
+ } else if (isType(leftType, EdmPrimitiveTypeKind.Int16) || isType(rightType, EdmPrimitiveTypeKind.Int16)) {
+ return odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int32);
+ } else {
+ return odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int16);
+ }
}
- if (isType(left, EdmPrimitiveTypeKind.DateTimeOffset)
- && (isType(right, EdmPrimitiveTypeKind.Duration)
- || isType(right, EdmPrimitiveTypeKind.DateTimeOffset) && !isAdd)) {
- return;
+ if ((isType(leftType, EdmPrimitiveTypeKind.DateTimeOffset)
+ || isType(leftType, EdmPrimitiveTypeKind.Duration))
+ && isType(rightType, EdmPrimitiveTypeKind.Duration)) {
+ return leftType;
}
- if (isType(left, EdmPrimitiveTypeKind.Duration) && isType(right, EdmPrimitiveTypeKind.Duration)
- || isType(left, EdmPrimitiveTypeKind.Date)
- && (isType(right, EdmPrimitiveTypeKind.Duration) || isType(right, EdmPrimitiveTypeKind.Date) && !isAdd)) {
- return;
+ if (isType(leftType, EdmPrimitiveTypeKind.Date) && isType(rightType, EdmPrimitiveTypeKind.Duration)) {
+ return odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.DateTimeOffset);
+ }
+ if (isSub
+ && (isType(leftType, EdmPrimitiveTypeKind.DateTimeOffset)
+ && isType(rightType, EdmPrimitiveTypeKind.DateTimeOffset)
+ || isType(leftType, EdmPrimitiveTypeKind.Date)
+ && isType(rightType, EdmPrimitiveTypeKind.Date))) {
+ return odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Duration);
}
throw new UriParserSemanticException("Incompatible types.",
- UriParserSemanticException.MessageKeys.UNKNOWN_TYPE, ""); // TODO: better message
+ UriParserSemanticException.MessageKeys.TYPES_NOT_COMPATIBLE,
+ leftType.getFullQualifiedName().getFullQualifiedNameAsString(),
+ rightType.getFullQualifiedName().getFullQualifiedNameAsString());
}
private void checkStructuredTypeFilter(final EdmType type, final EdmType filterType)
throws UriParserException {
- if (!(filterType instanceof EdmStructuredType && ((EdmStructuredType)filterType).compatibleTo(type))) {
+ if (!(filterType instanceof EdmStructuredType && ((EdmStructuredType) filterType).compatibleTo(type))) {
throw new UriParserSemanticException("Incompatible type filter.",
UriParserSemanticException.MessageKeys.INCOMPATIBLE_TYPE_FILTER,
filterType.getFullQualifiedName().getFullQualifiedNameAsString());
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/FilterParser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/FilterParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/FilterParser.java
index e2767a1..dd73009 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/FilterParser.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/FilterParser.java
@@ -21,6 +21,7 @@ package org.apache.olingo.server.core.uri.parser;
import java.util.Collection;
import org.apache.olingo.commons.api.edm.Edm;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
import org.apache.olingo.commons.api.edm.EdmType;
import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.uri.queryoption.FilterOption;
@@ -43,7 +44,13 @@ public class FilterParser {
throws UriParserException, UriValidationException {
final Expression filterExpression = new ExpressionParser(edm, odata)
.parse(tokenizer, referencedType, crossjoinEntitySetNames);
- // TODO: Check that the expression is boolean.
- return new FilterOptionImpl().setExpression(filterExpression);
+ final EdmType type = ExpressionParser.getType(filterExpression);
+ if (type == null || type.equals(odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Boolean))) {
+ return new FilterOptionImpl().setExpression(filterExpression);
+ } else {
+ throw new UriParserSemanticException("Filter expressions must be boolean.",
+ UriParserSemanticException.MessageKeys.TYPES_NOT_COMPATIBLE,
+ "Edm.Boolean", type.getFullQualifiedName().getFullQualifiedNameAsString());
+ }
}
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
index 47efda5..3125fa6 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
@@ -18,18 +18,11 @@
*/
package org.apache.olingo.server.core.uri.parser;
+import java.util.ArrayDeque;
+import java.util.Deque;
import java.util.List;
-import org.antlr.v4.runtime.ANTLRInputStream;
-import org.antlr.v4.runtime.BailErrorStrategy;
-import org.antlr.v4.runtime.CommonTokenStream;
-import org.antlr.v4.runtime.Lexer;
-import org.antlr.v4.runtime.ParserRuleContext;
-import org.antlr.v4.runtime.RecognitionException;
-import org.antlr.v4.runtime.atn.PredictionMode;
-import org.antlr.v4.runtime.misc.ParseCancellationException;
import org.apache.olingo.commons.api.edm.Edm;
-import org.apache.olingo.commons.api.edm.EdmEntityContainer;
import org.apache.olingo.commons.api.edm.EdmEntitySet;
import org.apache.olingo.commons.api.edm.EdmStructuredType;
import org.apache.olingo.commons.api.edm.EdmType;
@@ -52,14 +45,10 @@ import org.apache.olingo.server.api.uri.queryoption.SystemQueryOptionKind;
import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
import org.apache.olingo.server.core.uri.UriInfoImpl;
import org.apache.olingo.server.core.uri.UriResourceStartingTypeFilterImpl;
-import org.apache.olingo.server.core.uri.antlr.UriLexer;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandItemsEOFContext;
import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind;
import org.apache.olingo.server.core.uri.parser.search.SearchParser;
import org.apache.olingo.server.core.uri.queryoption.AliasQueryOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.CountOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.ExpandOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.FormatOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.IdOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.SkipOptionImpl;
@@ -77,8 +66,6 @@ public class Parser {
private final Edm edm;
private final OData odata;
- private enum ParserEntryRules { ExpandItems }
-
public Parser(final Edm edm, final OData odata) {
this.edm = edm;
this.odata = odata;
@@ -87,8 +74,9 @@ public class Parser {
public UriInfo parseUri(final String path, final String query, final String fragment)
throws UriParserException, UriValidationException {
- UriContext context = new UriContext();
- UriParseTreeVisitor uriParseTreeVisitor = new UriParseTreeVisitor(edm, context);
+ UriInfoImpl contextUriInfo = new UriInfoImpl();
+ Deque<EdmType> contextTypes = new ArrayDeque<EdmType>();
+ boolean contextIsCollection = false;
final List<String> pathSegmentsDecoded = UriDecoder.splitAndDecodePath(path);
final int numberOfSegments = pathSegmentsDecoded.size();
@@ -98,49 +86,46 @@ public class Parser {
if (firstSegment.isEmpty()) {
ensureLastSegment(firstSegment, 0, numberOfSegments);
- context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.service);
+ contextUriInfo.setKind(UriInfoKind.service);
} else if (firstSegment.equals("$batch")) {
ensureLastSegment(firstSegment, 1, numberOfSegments);
- context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.batch);
+ contextUriInfo.setKind(UriInfoKind.batch);
} else if (firstSegment.equals("$metadata")) {
ensureLastSegment(firstSegment, 1, numberOfSegments);
- context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.metadata);
- context.contextUriInfo.setFragment(fragment);
+ contextUriInfo.setKind(UriInfoKind.metadata);
+ contextUriInfo.setFragment(fragment);
} else if (firstSegment.equals("$all")) {
ensureLastSegment(firstSegment, 1, numberOfSegments);
- context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.all);
+ contextUriInfo.setKind(UriInfoKind.all);
// This loads nearly the whole schema, but sooner or later '$all' needs all entity sets anyway.
for (final EdmEntitySet entitySet : edm.getEntityContainer().getEntitySets()) {
- context.contextTypes.push(entitySet.getEntityType());
+ contextTypes.push(entitySet.getEntityType());
}
- context.isCollection = true;
+ contextIsCollection = true;
} else if (firstSegment.equals("$entity")) {
if (numberOfSegments > 1) {
final String typeCastSegment = pathSegmentsDecoded.get(1);
ensureLastSegment(typeCastSegment, 2, numberOfSegments);
- context.contextUriInfo = new ResourcePathParser(edm).parseDollarEntityTypeCast(typeCastSegment);
- context.contextTypes.push(context.contextUriInfo.getEntityTypeCast());
+ contextUriInfo = new ResourcePathParser(edm).parseDollarEntityTypeCast(typeCastSegment);
+ contextTypes.push(contextUriInfo.getEntityTypeCast());
} else {
- context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.entityId);
+ contextUriInfo.setKind(UriInfoKind.entityId);
// The type of the entity is not known until the $id query option has been parsed.
+ // TODO: Set the type (needed for the evaluation of system query options).
}
- context.isCollection = false;
+ contextIsCollection = false;
} else if (firstSegment.startsWith("$crossjoin")) {
ensureLastSegment(firstSegment, 1, numberOfSegments);
- context.contextUriInfo = new ResourcePathParser(edm).parseCrossjoinSegment(firstSegment);
- final EdmEntityContainer container = edm.getEntityContainer();
- for (final String name : context.contextUriInfo.getEntitySetNames()) {
- context.contextTypes.push(container.getEntitySet(name).getEntityType());
- }
- context.isCollection = true;
+ contextUriInfo = new ResourcePathParser(edm).parseCrossjoinSegment(firstSegment);
+ contextIsCollection = true;
} else {
- context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.resource);
+ contextUriInfo.setKind(UriInfoKind.resource);
final ResourcePathParser resourcePathParser = new ResourcePathParser(edm);
int count = 0;
UriResource lastSegment = null;
@@ -168,7 +153,7 @@ public class Parser {
} else {
lastSegment = segment;
}
- context.contextUriInfo.addResourcePart(segment);
+ contextUriInfo.addResourcePart(segment);
}
}
@@ -176,9 +161,9 @@ public class Parser {
final UriResourcePartTyped typed = (UriResourcePartTyped) lastSegment;
final EdmType type = ParserHelper.getTypeInformation(typed);
if (type != null) { // could be null for, e.g., actions without return type
- context.contextTypes.push(type);
+ contextTypes.push(type);
}
- context.isCollection = typed.isCollection();
+ contextIsCollection = typed.isCollection();
}
}
@@ -191,9 +176,10 @@ public class Parser {
SystemQueryOption systemOption = null;
if (optionName.equals(SystemQueryOptionKind.FILTER.toString())) {
UriTokenizer filterTokenizer = new UriTokenizer(optionValue);
- // The Referring type could also be a primitive type not only a structured type
- systemOption = new FilterParser(edm, odata).parse(filterTokenizer, context.contextTypes.peek(),
- context.contextUriInfo.getEntitySetNames());
+ // The referring type could be a primitive type or a structured type.
+ systemOption = new FilterParser(edm, odata).parse(filterTokenizer,
+ contextTypes.peek(),
+ contextUriInfo.getEntitySetNames());
checkOptionEOF(filterTokenizer, optionName, optionValue);
} else if (optionName.equals(SystemQueryOptionKind.FORMAT.toString())) {
@@ -211,19 +197,26 @@ public class Parser {
systemOption = formatOption;
} else if (optionName.equals(SystemQueryOptionKind.EXPAND.toString())) {
- try {
- ExpandItemsEOFContext ctxExpandItems =
- (ExpandItemsEOFContext) parseRule(optionValue, ParserEntryRules.ExpandItems);
- systemOption = (ExpandOptionImpl) uriParseTreeVisitor.visitExpandItemsEOF(ctxExpandItems);
- } catch (final ParseCancellationException e) {
- throw e.getCause() instanceof UriParserException ?
- (UriParserException) e.getCause() :
- new UriParserSyntaxException("Syntax error", e, UriParserSyntaxException.MessageKeys.SYNTAX);
+ if (contextTypes.peek() instanceof EdmStructuredType
+ || !contextUriInfo.getEntitySetNames().isEmpty()
+ || contextUriInfo.getKind() == UriInfoKind.entityId) { // TODO: Remove once the type has been set above.
+ UriTokenizer expandTokenizer = new UriTokenizer(optionValue);
+ systemOption = new ExpandParser(edm, odata).parse(expandTokenizer,
+ contextTypes.peek() instanceof EdmStructuredType ? (EdmStructuredType) contextTypes.peek() : null);
+ checkOptionEOF(expandTokenizer, optionName, optionValue);
+ } else {
+ throw new UriValidationException("Expand is only allowed on structured types!",
+ UriValidationException.MessageKeys.SYSTEM_QUERY_OPTION_NOT_ALLOWED, optionName);
}
} else if (optionName.equals(SystemQueryOptionKind.ID.toString())) {
IdOptionImpl idOption = new IdOptionImpl();
idOption.setText(optionValue);
+ if (optionValue == null || optionValue.isEmpty()) {
+ throw new UriParserSyntaxException("Illegal value of $id option!",
+ UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION,
+ optionName, optionValue);
+ }
idOption.setValue(optionValue);
systemOption = idOption;
@@ -234,10 +227,8 @@ public class Parser {
} else if (optionName.equals(SystemQueryOptionKind.ORDERBY.toString())) {
UriTokenizer orderByTokenizer = new UriTokenizer(optionValue);
systemOption = new OrderByParser(edm, odata).parse(orderByTokenizer,
- context.contextTypes.peek() instanceof EdmStructuredType ?
- (EdmStructuredType) context.contextTypes.peek() :
- null,
- context.contextUriInfo.getEntitySetNames());
+ contextTypes.peek() instanceof EdmStructuredType ? (EdmStructuredType) contextTypes.peek() : null,
+ contextUriInfo.getEntitySetNames());
checkOptionEOF(orderByTokenizer, optionName, optionValue);
} else if (optionName.equals(SystemQueryOptionKind.SEARCH.toString())) {
@@ -246,40 +237,31 @@ public class Parser {
} else if (optionName.equals(SystemQueryOptionKind.SELECT.toString())) {
UriTokenizer selectTokenizer = new UriTokenizer(optionValue);
systemOption = new SelectParser(edm).parse(selectTokenizer,
- context.contextTypes.peek() instanceof EdmStructuredType ?
- (EdmStructuredType) context.contextTypes.peek() :
- null,
- context.isCollection);
+ contextTypes.peek() instanceof EdmStructuredType ? (EdmStructuredType) contextTypes.peek() : null,
+ contextIsCollection);
checkOptionEOF(selectTokenizer, optionName, optionValue);
} else if (optionName.equals(SystemQueryOptionKind.SKIP.toString())) {
SkipOptionImpl skipOption = new SkipOptionImpl();
skipOption.setText(optionValue);
- try {
- skipOption.setValue(Integer.parseInt(optionValue));
- } catch (final NumberFormatException e) {
- throw new UriParserSyntaxException("Illegal value of $skip option!", e,
- UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION,
- optionName, optionValue);
- }
+ skipOption.setValue(ParserHelper.parseNonNegativeInteger(optionName, optionValue, true));
systemOption = skipOption;
} else if (optionName.equals(SystemQueryOptionKind.SKIPTOKEN.toString())) {
SkipTokenOptionImpl skipTokenOption = new SkipTokenOptionImpl();
skipTokenOption.setText(optionValue);
+ if (optionValue == null || optionValue.isEmpty()) {
+ throw new UriParserSyntaxException("Illegal value of $skiptoken option!",
+ UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION,
+ optionName, optionValue);
+ }
skipTokenOption.setValue(optionValue);
systemOption = skipTokenOption;
} else if (optionName.equals(SystemQueryOptionKind.TOP.toString())) {
TopOptionImpl topOption = new TopOptionImpl();
topOption.setText(optionValue);
- try {
- topOption.setValue(Integer.parseInt(optionValue));
- } catch (final NumberFormatException e) {
- throw new UriParserSyntaxException("Illegal value of $top option!", e,
- UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION,
- optionName, optionValue);
- }
+ topOption.setValue(ParserHelper.parseNonNegativeInteger(optionName, optionValue, true));
systemOption = topOption;
} else if (optionName.equals(SystemQueryOptionKind.COUNT.toString())) {
@@ -299,14 +281,14 @@ public class Parser {
UriParserSyntaxException.MessageKeys.UNKNOWN_SYSTEM_QUERY_OPTION, optionName);
}
try {
- context.contextUriInfo.setSystemQueryOption(systemOption);
+ contextUriInfo.setSystemQueryOption(systemOption);
} catch (final ODataRuntimeException e) {
throw new UriParserSyntaxException("Double system query option!", e,
UriParserSyntaxException.MessageKeys.DOUBLE_SYSTEM_QUERY_OPTION, optionName);
}
} else if (optionName.startsWith(AT)) {
- if (context.contextUriInfo.getAlias(optionName) == null) {
+ if (contextUriInfo.getAlias(optionName) == null) {
// TODO: Create a proper alias-value parser that can parse also common expressions.
Expression expression = null;
UriTokenizer aliasTokenizer = new UriTokenizer(optionValue);
@@ -318,13 +300,13 @@ public class Parser {
} else {
UriTokenizer aliasValueTokenizer = new UriTokenizer(optionValue);
expression = new ExpressionParser(edm, odata).parse(aliasValueTokenizer, null,
- context.contextUriInfo.getEntitySetNames());
+ contextUriInfo.getEntitySetNames());
if (!aliasValueTokenizer.next(TokenKind.EOF)) {
throw new UriParserSyntaxException("Illegal value for alias '" + optionName + "'.",
UriParserSyntaxException.MessageKeys.SYNTAX);
}
}
- context.contextUriInfo.addAlias((AliasQueryOption) new AliasQueryOptionImpl()
+ contextUriInfo.addAlias((AliasQueryOption) new AliasQueryOptionImpl()
.setAliasValue(expression)
.setName(optionName)
.setText(NULL.equals(optionValue) ? null : optionValue));
@@ -334,11 +316,11 @@ public class Parser {
}
} else {
- context.contextUriInfo.addCustomQueryOption((CustomQueryOption) option);
+ contextUriInfo.addCustomQueryOption((CustomQueryOption) option);
}
}
- return context.contextUriInfo;
+ return contextUriInfo;
}
private void ensureLastSegment(final String segment, final int pos, final int size)
@@ -362,102 +344,4 @@ public class Parser {
optionName, optionValue);
}
}
-
- private ParserRuleContext parseRule(final String input, final ParserEntryRules entryPoint)
- throws UriParserSyntaxException {
- UriParserParser parser = null;
- UriLexer lexer = null;
- ParserRuleContext ret = null;
-
- // Use 2 stage approach to improve performance
- // see https://github.com/antlr/antlr4/issues/192
-
- // stage = 1
- try {
-
- // create parser
- lexer = new UriLexer(new ANTLRInputStream(input));
- parser = new UriParserParser(new CommonTokenStream(lexer));
-
- // Set error strategy
- addStage1ErrorStrategy(parser);
-
- // Set error collector
- addStage1ErrorListener(parser);
-
- // user the faster LL parsing
- parser.getInterpreter().setPredictionMode(PredictionMode.SLL);
-
- // parse
- switch (entryPoint) {
- case ExpandItems:
- lexer.mode(Lexer.DEFAULT_MODE);
- ret = parser.expandItemsEOF();
- break;
- default:
- break;
-
- }
-
- } catch (ParseCancellationException hardException) {
- // stage = 2
- try {
-
- // create parser
- lexer = new UriLexer(new ANTLRInputStream(input));
- parser = new UriParserParser(new CommonTokenStream(lexer));
-
- // Set error strategy
- addStage2ErrorStrategy(parser);
-
- // Set error collector
- addStage2ErrorListener(parser);
-
- // Use the slower SLL parsing
- parser.getInterpreter().setPredictionMode(PredictionMode.LL);
-
- // parse
- switch (entryPoint) {
- case ExpandItems:
- lexer.mode(Lexer.DEFAULT_MODE);
- ret = parser.expandItemsEOF();
- break;
- default:
- break;
- }
-
- } catch (final RecognitionException weakException) {
- throw new UriParserSyntaxException("Error in syntax", weakException,
- UriParserSyntaxException.MessageKeys.SYNTAX);
-
- // exceptionOnStage = 2;
- }
- } catch (final RecognitionException hardException) {
- throw new UriParserSyntaxException("Error in syntax", hardException,
- UriParserSyntaxException.MessageKeys.SYNTAX);
- }
-
- return ret;
- }
-
- protected void addStage1ErrorStrategy(final UriParserParser parser) {
- // Throw exception at first syntax error
- parser.setErrorHandler(new BailErrorStrategy());
-
- }
-
- protected void addStage2ErrorStrategy(final UriParserParser parser) {
- // Throw exception at first syntax error
- parser.setErrorHandler(new BailErrorStrategy());
- }
-
- protected void addStage1ErrorListener(final UriParserParser parser) {
- // No error logging to System.out or System.err, only exceptions used (depending on ErrorStrategy)
- parser.removeErrorListeners();
- }
-
- protected void addStage2ErrorListener(final UriParserParser parser) {
- // No error logging to System.out or System.err, only exceptions used (depending on ErrorStrategy)
- parser.removeErrorListeners();
- }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java
index 65ee461..7f4abf7 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java
@@ -23,6 +23,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import org.apache.olingo.commons.api.edm.Edm;
import org.apache.olingo.commons.api.edm.EdmEntityType;
import org.apache.olingo.commons.api.edm.EdmKeyPropertyRef;
import org.apache.olingo.commons.api.edm.EdmNavigationProperty;
@@ -36,6 +37,8 @@ import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.uri.UriParameter;
import org.apache.olingo.server.api.uri.UriResourcePartTyped;
+import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
+import org.apache.olingo.server.api.uri.queryoption.expression.Literal;
import org.apache.olingo.server.core.ODataImpl;
import org.apache.olingo.server.core.uri.UriParameterImpl;
import org.apache.olingo.server.core.uri.UriResourceTypedImpl;
@@ -88,8 +91,9 @@ public class ParserHelper {
TokenKind.EnumValue);
}
- protected static List<UriParameter> parseFunctionParameters(UriTokenizer tokenizer, final boolean withComplex)
- throws UriParserException {
+ protected static List<UriParameter> parseFunctionParameters(UriTokenizer tokenizer,
+ final Edm edm, final EdmType referringType, final boolean withComplex)
+ throws UriParserException, UriValidationException {
List<UriParameter> parameters = new ArrayList<UriParameter>();
ParserHelper.requireNext(tokenizer, TokenKind.OPEN);
if (tokenizer.next(TokenKind.CLOSE)) {
@@ -115,6 +119,13 @@ public class ParserHelper {
throw new UriParserSemanticException("A JSON array or object is not allowed as parameter value.",
UriParserSemanticException.MessageKeys.COMPLEX_PARAMETER_IN_RESOURCE_PATH, tokenizer.getText());
}
+ } else if (withComplex) {
+ final Expression expression = new ExpressionParser(edm, odata).parse(tokenizer, referringType, null);
+ parameters.add(new UriParameterImpl().setName(name)
+ .setText(expression instanceof Literal ?
+ "null".equals(((Literal) expression).getText()) ? null : ((Literal) expression).getText() :
+ null)
+ .setExpression(expression instanceof Literal ? null : expression));
} else if (nextPrimitiveValue(tokenizer) == null) {
throw new UriParserSemanticException("Wrong parameter value.",
UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, "");
@@ -387,4 +398,23 @@ public class ParserHelper {
return type;
}
+
+ protected static int parseNonNegativeInteger(final String optionName, final String optionValue,
+ final boolean zeroAllowed) throws UriParserException {
+ int value;
+ try {
+ value = Integer.parseInt(optionValue);
+ } catch (final NumberFormatException e) {
+ throw new UriParserSyntaxException("Illegal value of '" + optionName + "' option!", e,
+ UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION,
+ optionName, optionValue);
+ }
+ if (value > 0 || value == 0 && zeroAllowed) {
+ return value;
+ } else {
+ throw new UriParserSyntaxException("Illegal value of '" + optionName + "' option!",
+ UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION,
+ optionName, optionValue);
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ResourcePathParser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ResourcePathParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ResourcePathParser.java
index 1cd4d7a..87cb91a 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ResourcePathParser.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ResourcePathParser.java
@@ -261,30 +261,33 @@ public class ResourcePathParser {
throws UriParserException, UriValidationException {
final FullQualifiedName name = new FullQualifiedName(tokenizer.getText());
requireTyped(previous, name.getFullQualifiedNameAsString());
- final UriResourcePartTyped previousTyped = (UriResourcePartTyped) previous;
- final EdmType previousTypeFilter = getPreviousTypeFilter(previousTyped);
- final EdmType previousType = previousTypeFilter == null ? previousTyped.getType() : previousTypeFilter;
- final EdmAction boundAction = edm.getBoundAction(name,
- previousType.getFullQualifiedName(),
- previousTyped.isCollection());
- if (boundAction != null) {
- ParserHelper.requireTokenEnd(tokenizer);
- return new UriResourceActionImpl(boundAction);
- }
- EdmStructuredType type = edm.getEntityType(name);
- if (type == null) {
- type = edm.getComplexType(name);
- }
- if (type != null) {
- return typeCast(name, type, previousTyped);
- }
- if (tokenizer.next(TokenKind.EOF)) {
- throw new UriParserSemanticException("Type '" + name.getFullQualifiedNameAsString() + "' not found.",
- UriParserSemanticException.MessageKeys.UNKNOWN_TYPE, name.getFullQualifiedNameAsString());
- }
- return functionCall(null, name,
- previousType.getFullQualifiedName(),
- previousTyped.isCollection());
+ final UriResourcePartTyped previousTyped = (UriResourcePartTyped) previous;
+ final EdmType previousTypeFilter = getPreviousTypeFilter(previousTyped);
+ final EdmType previousType = previousTypeFilter == null ? previousTyped.getType() : previousTypeFilter;
+
+ // We check for bound actions first because they cannot be followed by anything.
+ final EdmAction boundAction =
+ edm.getBoundAction(name, previousType.getFullQualifiedName(), previousTyped.isCollection());
+ if (boundAction != null) {
+ ParserHelper.requireTokenEnd(tokenizer);
+ return new UriResourceActionImpl(boundAction);
+ }
+
+ // Type casts can be syntactically indistinguishable from bound function calls in the case of additional keys.
+ // But normally they are shorter, so they come next.
+ final EdmStructuredType type = previousTyped.getType() instanceof EdmEntityType ?
+ edm.getEntityType(name) :
+ edm.getComplexType(name);
+ if (type != null) {
+ return typeCast(name, type, previousTyped);
+ }
+ if (tokenizer.next(TokenKind.EOF)) {
+ throw new UriParserSemanticException("Type '" + name.getFullQualifiedNameAsString() + "' not found.",
+ UriParserSemanticException.MessageKeys.UNKNOWN_TYPE, name.getFullQualifiedNameAsString());
+ }
+
+ // Now a bound function call is the only remaining option.
+ return functionCall(null, name, previousType.getFullQualifiedName(), previousTyped.isCollection());
}
private void requireTyped(final UriResource previous, final String forWhat) throws UriParserException {
@@ -317,8 +320,13 @@ public class ResourcePathParser {
((UriResourceWithKeysImpl) previousTyped).setEntryTypeFilter(type);
}
if (tokenizer.next(TokenKind.OPEN)) {
- ((UriResourceWithKeysImpl) previousTyped).setKeyPredicates(
- ParserHelper.parseKeyPredicate(tokenizer, (EdmEntityType) type, null));
+ final List<UriParameter> keys = ParserHelper.parseKeyPredicate(tokenizer, (EdmEntityType) type, null);
+ if (previousTyped.isCollection()) {
+ ((UriResourceWithKeysImpl) previousTyped).setKeyPredicates(keys);
+ } else {
+ throw new UriParserSemanticException("Key not allowed here.",
+ UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED);
+ }
}
} else {
previousTypeFilter = ((UriResourceTypedImpl) previousTyped).getTypeFilter();
@@ -351,7 +359,7 @@ public class ResourcePathParser {
private UriResource functionCall(final EdmFunctionImport edmFunctionImport,
final FullQualifiedName boundFunctionName, final FullQualifiedName bindingParameterTypeName,
final boolean isBindingParameterCollection) throws UriParserException, UriValidationException {
- final List<UriParameter> parameters = ParserHelper.parseFunctionParameters(tokenizer, false);
+ final List<UriParameter> parameters = ParserHelper.parseFunctionParameters(tokenizer, edm, null, false);
final List<String> names = ParserHelper.getParameterNames(parameters);
EdmFunction function = null;
if (edmFunctionImport != null) {
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/SearchParser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/SearchParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/SearchParser.java
new file mode 100644
index 0000000..a072327
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/SearchParser.java
@@ -0,0 +1,108 @@
+/*
+ * 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 org.apache.olingo.server.api.uri.queryoption.SearchOption;
+import org.apache.olingo.server.api.uri.queryoption.search.SearchBinaryOperatorKind;
+import org.apache.olingo.server.api.uri.queryoption.search.SearchExpression;
+import org.apache.olingo.server.api.uri.queryoption.search.SearchTerm;
+import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind;
+import org.apache.olingo.server.core.uri.parser.search.SearchBinaryImpl;
+import org.apache.olingo.server.core.uri.parser.search.SearchParserException;
+import org.apache.olingo.server.core.uri.parser.search.SearchTermImpl;
+import org.apache.olingo.server.core.uri.parser.search.SearchUnaryImpl;
+import org.apache.olingo.server.core.uri.queryoption.SearchOptionImpl;
+
+/**
+ * Parses search expressions according to the following (rewritten) grammar:
+ * <pre>
+ * SearchExpr ::= ExprOR
+ * ExprOR ::= ExprAnd ('OR' ExprAnd)*
+ * ExprAnd ::= Term ('AND'? Term)*
+ * Term ::= ('NOT'? (Word | Phrase)) | ('(' SearchExpr ')')
+ * </pre>
+ */
+public class SearchParser {
+
+ public SearchOption parse(UriTokenizer tokenizer) throws SearchParserException {
+ SearchOptionImpl searchOption = new SearchOptionImpl();
+ searchOption.setSearchExpression(processExprOr(tokenizer));
+ return searchOption;
+ }
+
+ private SearchExpression processExprOr(UriTokenizer tokenizer) throws SearchParserException {
+ SearchExpression left = processExprAnd(tokenizer);
+
+ while (tokenizer.next(TokenKind.OrOperatorSearch)) {
+ final SearchExpression right = processExprAnd(tokenizer);
+ left = new SearchBinaryImpl(left, SearchBinaryOperatorKind.OR, right);
+ }
+
+ return left;
+ }
+
+ private SearchExpression processExprAnd(UriTokenizer tokenizer) throws SearchParserException {
+ SearchExpression left = processTerm(tokenizer);
+
+ while (tokenizer.next(TokenKind.AndOperatorSearch)) { // Could be whitespace or whitespace-surrounded 'AND'.
+ final SearchExpression right = processTerm(tokenizer);
+ left = new SearchBinaryImpl(left, SearchBinaryOperatorKind.AND, right);
+ }
+
+ return left;
+ }
+
+ private SearchExpression processTerm(UriTokenizer tokenizer) throws SearchParserException {
+ if (tokenizer.next(TokenKind.OPEN)) {
+ final SearchExpression expr = processExprOr(tokenizer);
+ if (!tokenizer.next(TokenKind.CLOSE)) {
+ throw new SearchParserException("Missing close parenthesis after open parenthesis.",
+ SearchParserException.MessageKeys.MISSING_CLOSE);
+ }
+ return expr;
+ } else if (tokenizer.next(TokenKind.NotOperatorSearch)) {
+ return processNot(tokenizer);
+ } else if (tokenizer.next(TokenKind.Word)) {
+ return new SearchTermImpl(tokenizer.getText());
+ } else if (tokenizer.next(TokenKind.Phrase)) {
+ return processPhrase(tokenizer);
+ } else {
+ throw new SearchParserException("Expected PHRASE or WORD not found.",
+ SearchParserException.MessageKeys.EXPECTED_DIFFERENT_TOKEN, "PHRASE, WORD", "");
+ }
+ }
+
+ private SearchExpression processNot(UriTokenizer tokenizer) throws SearchParserException {
+ if (tokenizer.next(TokenKind.Word)) {
+ return new SearchUnaryImpl(new SearchTermImpl(tokenizer.getText()));
+ } else if (tokenizer.next(TokenKind.Phrase)) {
+ return new SearchUnaryImpl(processPhrase(tokenizer));
+ } else {
+ throw new SearchParserException("NOT must be followed by a term.",
+ SearchParserException.MessageKeys.INVALID_NOT_OPERAND, "");
+ }
+ }
+
+ private SearchTerm processPhrase(UriTokenizer tokenizer) {
+ final String literal = tokenizer.getText();
+ return new SearchTermImpl(literal.substring(1, literal.length() - 1)
+ .replace("\\\"", "\"")
+ .replace("\\\\", "\\"));
+ }
+}