Repository: olingo-odata4 Updated Branches: refs/heads/master 981084fe1 -> 9333c090f
[OLINGO-916] more robust simple-key parsing Signed-off-by: Christian Amend <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/9333c090 Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/9333c090 Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/9333c090 Branch: refs/heads/master Commit: 9333c090fd9fc99dcbb9e5b40fe15dc2671055db Parents: 981084f Author: Klaus Straubinger <[email protected]> Authored: Tue Mar 29 10:55:21 2016 +0200 Committer: Christian Amend <[email protected]> Committed: Tue Mar 29 12:31:19 2016 +0200 ---------------------------------------------------------------------- .../olingo/server/core/ODataHandlerImpl.java | 2 +- .../server/core/uri/parser/ExpandParser.java | 37 ++------- .../core/uri/parser/ExpressionParser.java | 39 ++++----- .../server/core/uri/parser/ParserHelper.java | 86 +++++++++++--------- .../core/uri/testutil/ExpandValidator.java | 8 +- 5 files changed, 76 insertions(+), 96 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9333c090/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandlerImpl.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandlerImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandlerImpl.java index da4856a..921124c 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandlerImpl.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandlerImpl.java @@ -133,7 +133,7 @@ public class ODataHandlerImpl implements ODataHandler { throw e; } - final int measurementUriParser = debugger.startRuntimeMeasurement("UriParser", "parseUri"); + final int measurementUriParser = debugger.startRuntimeMeasurement("Parser", "parseUri"); try { uriInfo = new Parser(serviceMetadata.getEdm(), odata) .parseUri(request.getRawODataPath(), request.getRawQueryPath(), null); http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9333c090/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 index bae2bdd..1da143a 100644 --- 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 @@ -22,11 +22,9 @@ import java.util.Collection; 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.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; @@ -127,13 +125,13 @@ public class ExpandParser { } } else { - final EdmStructuredType typeCast = parseTypeCast(tokenizer, referencedType); + final EdmStructuredType typeCast = ParserHelper.parseTypeCast(tokenizer, edm, referencedType); if (typeCast != null) { item.setTypeFilter(typeCast); ParserHelper.requireNext(tokenizer, TokenKind.SLASH); } - UriInfoImpl resource = parseExpandPath(tokenizer, referencedType, item); + UriInfoImpl resource = parseExpandPath(tokenizer, edm, referencedType, item); UriResourcePartTyped lastPart = (UriResourcePartTyped) resource.getLastResourcePart(); @@ -143,7 +141,8 @@ public class ExpandParser { if (lastPart instanceof UriResourceNavigation) { UriResourceNavigationPropertyImpl navigationResource = (UriResourceNavigationPropertyImpl) lastPart; final EdmNavigationProperty navigationProperty = navigationResource.getProperty(); - final EdmStructuredType typeCastSuffix = parseTypeCast(tokenizer, navigationProperty.getType()); + final EdmStructuredType typeCastSuffix = ParserHelper.parseTypeCast(tokenizer, edm, + navigationProperty.getType()); if (typeCastSuffix != null) { if (navigationProperty.isCollection()) { navigationResource.setCollectionTypeFilter(typeCastSuffix); @@ -178,34 +177,12 @@ public class ExpandParser { 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, - ExpandItemImpl item) throws UriParserException { + protected static UriInfoImpl parseExpandPath(UriTokenizer tokenizer, final Edm edm, + final EdmStructuredType referencedType, ExpandItemImpl item) 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); @@ -213,7 +190,7 @@ public class ExpandParser { type = (EdmStructuredType) property.getType(); UriResourceComplexPropertyImpl complexResource = new UriResourceComplexPropertyImpl(property); ParserHelper.requireNext(tokenizer, TokenKind.SLASH); - final EdmStructuredType typeCast = parseTypeCast(tokenizer, type); + final EdmStructuredType typeCast = ParserHelper.parseTypeCast(tokenizer, edm, type); if (typeCast != null) { complexResource.setTypeFilter(typeCast); ParserHelper.requireNext(tokenizer, TokenKind.SLASH); http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9333c090/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 ee83a53..c9f8b21 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 @@ -286,14 +286,8 @@ public class ExpressionParser { // Null for everything other than MUL or DIV or MOD while (operatorTokenKind != null) { final Expression right = parseExprUnary(); - 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); + checkNumericType(left); + checkNumericType(right); left = new BinaryImpl(left, tokenToBinaryOperator.get(operatorTokenKind), right, odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Double)); operatorTokenKind = ParserHelper.next(tokenizer, @@ -305,11 +299,9 @@ public class ExpressionParser { private Expression parseExprUnary() throws UriParserException, UriValidationException { if (tokenizer.next(TokenKind.MinusOperator)) { final Expression expression = parseExprPrimary(); - checkType(expression, - EdmPrimitiveTypeKind.Int16, EdmPrimitiveTypeKind.Int32, EdmPrimitiveTypeKind.Int64, - EdmPrimitiveTypeKind.Byte, EdmPrimitiveTypeKind.SByte, - EdmPrimitiveTypeKind.Decimal, EdmPrimitiveTypeKind.Single, EdmPrimitiveTypeKind.Double, - EdmPrimitiveTypeKind.Duration); + if (!isType(getType(expression), EdmPrimitiveTypeKind.Duration)) { + checkNumericType(expression); + } return new UnaryImpl(UnaryOperatorKind.MINUS, expression, getType(expression)); } else if (tokenizer.next(TokenKind.NotOperator)) { final Expression expression = parseExprPrimary(); @@ -538,15 +530,11 @@ public class ExpressionParser { parameters.add(parameterFirst); ParserHelper.requireNext(tokenizer, TokenKind.COMMA); final Expression parameterSecond = parseExpression(); - checkType(parameterSecond, - EdmPrimitiveTypeKind.Int64, EdmPrimitiveTypeKind.Int32, EdmPrimitiveTypeKind.Int16, - EdmPrimitiveTypeKind.Byte, EdmPrimitiveTypeKind.SByte); + checkIntegerType(parameterSecond); parameters.add(parameterSecond); if (tokenizer.next(TokenKind.COMMA)) { final Expression parameterThird = parseExpression(); - checkType(parameterThird, - EdmPrimitiveTypeKind.Int64, EdmPrimitiveTypeKind.Int32, EdmPrimitiveTypeKind.Int16, - EdmPrimitiveTypeKind.Byte, EdmPrimitiveTypeKind.SByte); + checkIntegerType(parameterThird); parameters.add(parameterThird); } break; @@ -1084,6 +1072,19 @@ public class ExpressionParser { } } + protected void checkIntegerType(final Expression expression) throws UriParserException { + checkType(expression, + EdmPrimitiveTypeKind.Int64, EdmPrimitiveTypeKind.Int32, EdmPrimitiveTypeKind.Int16, + EdmPrimitiveTypeKind.Byte, EdmPrimitiveTypeKind.SByte); + } + + protected void checkNumericType(final Expression expression) throws UriParserException { + checkType(expression, + EdmPrimitiveTypeKind.Int64, EdmPrimitiveTypeKind.Int32, EdmPrimitiveTypeKind.Int16, + EdmPrimitiveTypeKind.Byte, EdmPrimitiveTypeKind.SByte, + EdmPrimitiveTypeKind.Decimal, EdmPrimitiveTypeKind.Single, EdmPrimitiveTypeKind.Double); + } + private void checkEqualityTypes(final Expression left, final Expression right) throws UriParserException { final EdmType leftType = getType(left); final EdmType rightType = getType(right); http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9333c090/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 0ca0ce6..f952c80 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 @@ -38,8 +38,10 @@ 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.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; @@ -306,17 +308,24 @@ public class ParserHelper { } } - if(tokenizer.next(TokenKind.GuidValue)) { - keys.add(parseSimpleKey(tokenizer, edm, referringType, aliases, keyPropertyRefs, referencedNames, true)); - } else if (tokenizer.next(TokenKind.ODataIdentifier)) { - keys.addAll(compoundKey(tokenizer, edmEntityType, edm, referringType, aliases)); - } else if (keyPropertyRefs.size() - referencedNames.size() == 1) { - keys.add(parseSimpleKey(tokenizer, edm, referringType, aliases, keyPropertyRefs, referencedNames, false)); - } 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 (keyPropertyRefs.size() - referencedNames.size() == 1) { + for (final EdmKeyPropertyRef candidate : keyPropertyRefs) { + if (referencedNames.get(candidate.getName()) == null) { + final UriParameter simpleKey = simpleKey(tokenizer, candidate, edm, referringType, aliases); + if (simpleKey != null) { + keys.add(simpleKey); + } + break; + } + } + } + if (keys.isEmpty()) { + if (tokenizer.next(TokenKind.ODataIdentifier)) { + keys.addAll(compoundKey(tokenizer, edmEntityType, edm, referringType, aliases)); + } else { + throw new UriParserSemanticException("The key value is not valid.", + UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, ""); + } } if (keys.size() < keyPropertyRefs.size() && partner != null) { @@ -346,42 +355,18 @@ public class ParserHelper { } } - private static UriParameter parseSimpleKey(final UriTokenizer tokenizer, final Edm edm, final EdmType referringType, - final Map<String, AliasQueryOption> aliases, - final List<EdmKeyPropertyRef> keyPropertyRefs, - final Map<String, String> referencedNames, final boolean tokenConsumed) - throws UriParserException, UriValidationException { - - for (final EdmKeyPropertyRef candidate : keyPropertyRefs) { - if (referencedNames.get(candidate.getName()) == null) { - return simpleKey(tokenizer, candidate, edm, referringType, aliases, tokenConsumed); - } - } - throw new UriParserSemanticException("No suitable key found.", - UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES, - "0", String.valueOf(keyPropertyRefs.size())); - } - private static UriParameter simpleKey(UriTokenizer tokenizer, final EdmKeyPropertyRef edmKeyPropertyRef, - final Edm edm, final EdmType referringType, - final Map<String, AliasQueryOption> aliases, final boolean tokenConsumed) + final Edm edm, final EdmType referringType, final Map<String, AliasQueryOption> aliases) throws UriParserException, UriValidationException { final EdmProperty edmProperty = edmKeyPropertyRef == null ? null : edmKeyPropertyRef.getProperty(); - final EdmPrimitiveType primitiveType = edmProperty == null ? null : (EdmPrimitiveType) edmProperty.getType(); - final boolean nullable = edmProperty != null && edmProperty.isNullable(); - - boolean primitiveTypeAvailable = tokenConsumed; - if(!tokenConsumed) { - primitiveTypeAvailable = nextPrimitiveTypeValue(tokenizer, primitiveType, nullable); - } - if (primitiveTypeAvailable) { + 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, edm, referringType, aliases); } else { - String keyPropertyRefName = edmKeyPropertyRef == null ? "NULL EdmKeyPropertyRef" : edmKeyPropertyRef.getName(); - throw new UriParserSemanticException("The key value is not valid.", - UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, keyPropertyRefName); + return null; } } @@ -548,6 +533,27 @@ public class ParserHelper { return names; } + protected static EdmStructuredType parseTypeCast(UriTokenizer tokenizer, final Edm edm, + 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; + } + protected static EdmType getTypeInformation(final UriResourcePartTyped resourcePart) { EdmType type = null; if (resourcePart instanceof UriResourceWithKeysImpl) { http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9333c090/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 35245b4..104b156 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 @@ -109,12 +109,8 @@ public class ExpandValidator implements TestValidator { public ExpandValidator next() { expandItemIndex++; - - try { - expandItem = expandOption.getExpandItems().get(expandItemIndex); - } catch (IndexOutOfBoundsException ex) { - fail("not enough segments"); - } + assertTrue("not enough segments", expandItemIndex < expandOption.getExpandItems().size()); + expandItem = expandOption.getExpandItems().get(expandItemIndex); return this; }
