Repository: olingo-odata2 Updated Branches: refs/heads/master 7d882075a -> 919d4ac0f
[OLINGO-1026] existence check of navigation target in filter/orderby Signed-off-by: Christian Amend <christian.am...@sap.com> Project: http://git-wip-us.apache.org/repos/asf/olingo-odata2/repo Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata2/commit/919d4ac0 Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata2/tree/919d4ac0 Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata2/diff/919d4ac0 Branch: refs/heads/master Commit: 919d4ac0f85f59295f7fde00a9f8cdc12085e441 Parents: 7d88207 Author: Klaus Straubinger <klaus.straubin...@sap.com> Authored: Wed Sep 21 15:16:04 2016 +0200 Committer: Christian Amend <christian.am...@sap.com> Committed: Wed Sep 21 15:23:18 2016 +0200 ---------------------------------------------------------------------- .../expression/ExpressionParserException.java | 10 +- .../expression/FilterParserExceptionImpl.java | 13 +- .../core/uri/expression/FilterParserImpl.java | 108 ++---- .../src/main/resources/i18n.properties | 5 +- .../src/main/resources/i18n_en.properties | 5 +- .../odata2/core/uri/expression/ParserTool.java | 384 +++---------------- .../odata2/core/uri/expression/TestBase.java | 12 +- .../odata2/core/uri/expression/TestParser.java | 233 +++++------ .../odata2/ref/processor/ListsProcessor.java | 84 ++-- .../olingo/odata2/testutil/mock/TecEdmInfo.java | 22 +- .../mock/TechnicalScenarioEdmProvider.java | 21 +- 11 files changed, 289 insertions(+), 608 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/919d4ac0/odata2-lib/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/ExpressionParserException.java ---------------------------------------------------------------------- diff --git a/odata2-lib/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/ExpressionParserException.java b/odata2-lib/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/ExpressionParserException.java index c9b84a5..1ca309a 100644 --- a/odata2-lib/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/ExpressionParserException.java +++ b/odata2-lib/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/ExpressionParserException.java @@ -45,10 +45,10 @@ public class ExpressionParserException extends ODataBadRequestException { ExpressionParserException.class, "COMMA_OR_END_EXPECTED_AT_POS"); public static final MessageReference EXPRESSION_EXPECTED_AT_POS = createMessageReference( ExpressionParserException.class, "EXPRESSION_EXPECTED_AT_POS"); - public static final MessageReference MISSING_CLOSING_PHARENTHESIS = createMessageReference( - ExpressionParserException.class, "MISSING_CLOSING_PHARENTHESIS"); - public static final MessageReference COMMA_OR_CLOSING_PHARENTHESIS_EXPECTED_AFTER_POS = createMessageReference( - ExpressionParserException.class, "COMMA_OR_CLOSING_PHARENTHESIS_EXPECTED_AFTER_POS"); + public static final MessageReference MISSING_CLOSING_PARENTHESIS = createMessageReference( + ExpressionParserException.class, "MISSING_CLOSING_PARENTHESIS"); + public static final MessageReference COMMA_OR_CLOSING_PARENTHESIS_EXPECTED_AFTER_POS = createMessageReference( + ExpressionParserException.class, "COMMA_OR_CLOSING_PARENTHESIS_EXPECTED_AFTER_POS"); public static final MessageReference INVALID_METHOD_CALL = createMessageReference(ExpressionParserException.class, "INVALID_METHOD_CALL"); public static final MessageReference TYPE_EXPECTED_AT = createMessageReference(ExpressionParserException.class, @@ -73,6 +73,8 @@ public class ExpressionParserException extends ODataBadRequestException { ExpressionParserException.class, "LEFT_SIDE_NOT_A_PROPERTY"); public static final MessageReference PROPERTY_NAME_NOT_FOUND_IN_TYPE = createMessageReference( ExpressionParserException.class, "PROPERTY_NAME_NOT_FOUND_IN_TYPE"); + public static final MessageReference INVALID_MULTIPLICITY = createMessageReference( + ExpressionParserException.class, "INVALID_MULTIPLICITY"); // validation exceptions texts - binary public static final MessageReference INVALID_TYPES_FOR_BINARY_OPERATOR = createMessageReference( http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/919d4ac0/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/FilterParserExceptionImpl.java ---------------------------------------------------------------------- diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/FilterParserExceptionImpl.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/FilterParserExceptionImpl.java index 403fe2f..25a4d36 100644 --- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/FilterParserExceptionImpl.java +++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/FilterParserExceptionImpl.java @@ -22,7 +22,6 @@ import org.apache.olingo.odata2.api.edm.EdmException; import org.apache.olingo.odata2.api.edm.EdmStructuralType; import org.apache.olingo.odata2.api.edm.EdmType; import org.apache.olingo.odata2.api.exception.MessageReference; -import org.apache.olingo.odata2.api.exception.ODataBadRequestException; import org.apache.olingo.odata2.api.uri.expression.BinaryOperator; import org.apache.olingo.odata2.api.uri.expression.CommonExpression; import org.apache.olingo.odata2.api.uri.expression.ExpressionParserException; @@ -39,10 +38,6 @@ import org.apache.olingo.odata2.api.uri.expression.PropertyExpression; public class FilterParserExceptionImpl extends ExpressionParserException { private static final long serialVersionUID = 77L; - static public ExpressionParserException createCOMMON() { - return new ExpressionParserException(ODataBadRequestException.COMMON); - } - static public ExpressionParserException createERROR_IN_TOKENIZER(final TokenizerException exceptionTokenizer, final String expression) { Token token = exceptionTokenizer.getToken(); @@ -105,9 +100,9 @@ public class FilterParserExceptionImpl extends ExpressionParserException { return new ExpressionParserException(msgRef); } - static public ExpressionParserException createCOMMA_OR_CLOSING_PHARENTHESIS_EXPECTED_AFTER_POS(final Token token, + static public ExpressionParserException createCOMMA_OR_CLOSING_PARENTHESIS_EXPECTED_AFTER_POS(final Token token, final String expression) { - MessageReference msgRef = ExpressionParserException.COMMA_OR_CLOSING_PHARENTHESIS_EXPECTED_AFTER_POS.create(); + MessageReference msgRef = ExpressionParserException.COMMA_OR_CLOSING_PARENTHESIS_EXPECTED_AFTER_POS.create(); msgRef.addContent(Integer.toString(token.getPosition() + token.getUriLiteral().length())); msgRef.addContent(expression); @@ -248,9 +243,9 @@ public class FilterParserExceptionImpl extends ExpressionParserException { return new ExpressionParserException(msgRef); } - public static ExpressionParserException createMISSING_CLOSING_PHARENTHESIS(final int position, + public static ExpressionParserException createMISSING_CLOSING_PARENTHESIS(final int position, final String expression, final TokenizerExpectError e) { - MessageReference msgRef = ExpressionParserException.MISSING_CLOSING_PHARENTHESIS.create(); + MessageReference msgRef = ExpressionParserException.MISSING_CLOSING_PARENTHESIS.create(); msgRef.addContent(position + 1); msgRef.addContent(expression); http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/919d4ac0/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/FilterParserImpl.java ---------------------------------------------------------------------- diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/FilterParserImpl.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/FilterParserImpl.java index 47be745..fe54085 100644 --- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/FilterParserImpl.java +++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/FilterParserImpl.java @@ -27,10 +27,12 @@ import java.util.Map; import org.apache.olingo.odata2.api.edm.EdmComplexType; import org.apache.olingo.odata2.api.edm.EdmEntityType; import org.apache.olingo.odata2.api.edm.EdmException; +import org.apache.olingo.odata2.api.edm.EdmMultiplicity; import org.apache.olingo.odata2.api.edm.EdmSimpleType; import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind; import org.apache.olingo.odata2.api.edm.EdmStructuralType; import org.apache.olingo.odata2.api.edm.EdmType; +import org.apache.olingo.odata2.api.edm.EdmTypeKind; import org.apache.olingo.odata2.api.edm.EdmTyped; import org.apache.olingo.odata2.api.uri.expression.BinaryExpression; import org.apache.olingo.odata2.api.uri.expression.BinaryOperator; @@ -209,7 +211,7 @@ public class FilterParserImpl implements FilterParser { } catch (TokenizerExpectError e) { // Internal parsing error, even if there are no more token (then there should be a different exception). // Tested with TestParserExceptions.TestPMreadParenthesis - throw FilterParserExceptionImpl.createMISSING_CLOSING_PHARENTHESIS(openParenthesis.getPosition(), curExpression, + throw FilterParserExceptionImpl.createMISSING_CLOSING_PARENTHESIS(openParenthesis.getPosition(), curExpression, e); } return parenthesisExpression; @@ -246,7 +248,7 @@ public class FilterParserImpl implements FilterParser { while (token.getKind() != TokenKind.CLOSEPAREN) { if (readComma == false) { // Tested with TestParserExceptions.TestPMreadParameters CASE 12 e.g. "$filter=concat('a' 'b')" - throw FilterParserExceptionImpl.createCOMMA_OR_CLOSING_PHARENTHESIS_EXPECTED_AFTER_POS(tokenList + throw FilterParserExceptionImpl.createCOMMA_OR_CLOSING_PARENTHESIS_EXPECTED_AFTER_POS(tokenList .lookPrevToken(), curExpression); } expression = readElement(null); @@ -264,7 +266,7 @@ public class FilterParserImpl implements FilterParser { token = tokenList.lookToken(); if (token == null) { // Tested with TestParserExceptions.TestPMreadParameters CASE 2 e.g. "$filter=concat(123" - throw FilterParserExceptionImpl.createCOMMA_OR_CLOSING_PHARENTHESIS_EXPECTED_AFTER_POS(tokenList + throw FilterParserExceptionImpl.createCOMMA_OR_CLOSING_PARENTHESIS_EXPECTED_AFTER_POS(tokenList .lookPrevToken(), curExpression); } @@ -444,7 +446,7 @@ public class FilterParserImpl implements FilterParser { final Token propertyToken, final ActualBinaryOperator actBinOp) throws ExpressionParserException, ExpressionParserInternalError { - // Exist if no edm provided + // Exit if no edm provided if (resourceEntityType == null) { return; } @@ -504,6 +506,12 @@ public class FilterParserImpl implements FilterParser { if (edmProperty != null) { property.setEdmProperty(edmProperty); property.setEdmType(edmProperty.getType()); + if (edmProperty.getMultiplicity() == EdmMultiplicity.MANY) { + throw new ExpressionParserException( + ExpressionParserException.INVALID_MULTIPLICITY.create() + .addContent(propertyName) + .addContent(propertyToken.getPosition() + 1)); + } } else { // Tested with TestParserExceptions.TestPMvalidateEdmProperty CASE 3 throw FilterParserExceptionImpl.createPROPERTY_NAME_NOT_FOUND_IN_TYPE(parentType, property, propertyToken, @@ -516,58 +524,6 @@ public class FilterParserImpl implements FilterParser { } } - /* - * protected void validateEdmPropertyOfComplexType1(EdmComplexType parentType, PropertyExpressionImpl property, Token - * propertyToken) throws FilterParserException, FilterParserInternalError - * { - * try { - * String propertyName = property.getUriLiteral(); - * EdmTyped edmProperty = parentType.getProperty(propertyName); - * - * if (edmProperty != null) - * { - * property.setEdmProperty(edmProperty); - * property.setEdmType(edmProperty.getType()); - * } - * else - * { - * //Tested with TestParserExceptions.TestPMvalidateEdmProperty CASE 3 - * throw FilterParserExceptionImpl.createPROPERTY_NAME_NOT_FOUND_IN_TYPE(parentType, property, propertyToken, - * curExpression); - * } - * - * } catch (EdmException e) { - * // not Tested, should not occur - * throw FilterParserInternalError.createERROR_ACCESSING_EDM(e); - * } - * } - * - * protected void validateEdmPropertyOfEntityType1(EdmEntityType parentType, PropertyExpressionImpl property, Token - * propertyToken) throws FilterParserException, FilterParserInternalError - * { - * try { - * String propertyName = property.getUriLiteral(); - * EdmTyped edmProperty = parentType.getProperty(propertyName); - * - * if (edmProperty != null) - * { - * property.setEdmProperty(edmProperty); - * property.setEdmType(edmProperty.getType()); - * } - * else - * { - * //Tested with TestParserExceptions.TestPMvalidateEdmProperty CASE 1 - * throw FilterParserExceptionImpl.createPROPERTY_NAME_NOT_FOUND_IN_TYPE(parentType, property, propertyToken, - * curExpression); - * } - * - * } catch (EdmException e) { - * // not Tested, should not occur - * throw FilterParserInternalError.createERROR_ACCESSING_EDM(e); - * } - * } - */ - protected void validateUnaryOperatorTypes(final UnaryExpression unaryExpression) throws ExpressionParserInternalError { InfoUnaryOperator unOpt = availableUnaryOperators.get(unaryExpression.getOperator().toUriLiteral()); @@ -591,21 +547,29 @@ public class FilterParserImpl implements FilterParser { InfoBinaryOperator binOpt = availableBinaryOperators.get(binaryExpression.getOperator().toUriLiteral()); List<EdmType> actualParameterTypes = new ArrayList<EdmType>(); - EdmType operand = binaryExpression.getLeftOperand().getEdmType(); - - if ((operand == null) && (resourceEntityType == null)) { + final EdmType leftType = binaryExpression.getLeftOperand().getEdmType(); + if (leftType == null && resourceEntityType == null) { return; } - actualParameterTypes.add(operand); + actualParameterTypes.add(leftType); - operand = binaryExpression.getRightOperand().getEdmType(); + final EdmType rightType = binaryExpression.getRightOperand().getEdmType(); + if (rightType == null && resourceEntityType == null) { + return; + } + actualParameterTypes.add(rightType); - if ((operand == null) && (resourceEntityType == null)) { + // special case for navigation property (non-)equality comparison with null + if (binOpt.getCategory().equals("Equality") + && (leftType.getKind() == EdmTypeKind.ENTITY + && rightType == EdmSimpleTypeFacadeImpl.getEdmSimpleType(EdmSimpleTypeKind.Null) + || leftType == EdmSimpleTypeFacadeImpl.getEdmSimpleType(EdmSimpleTypeKind.Null) + && rightType.getKind() == EdmTypeKind.ENTITY)) { + binaryExpression.setEdmType(EdmSimpleTypeFacadeImpl.getEdmSimpleType(EdmSimpleTypeKind.Boolean)); return; } - actualParameterTypes.add(operand); - ParameterSet parameterSet = binOpt.validateParameterSet(actualParameterTypes); + final ParameterSet parameterSet = binOpt.validateParameterSet(actualParameterTypes); if (parameterSet == null) { BinaryExpressionImpl binaryExpressionImpl = (BinaryExpressionImpl) binaryExpression; @@ -624,7 +588,7 @@ public class FilterParserImpl implements FilterParser { List<EdmType> actualParameterTypes = new ArrayList<EdmType>(); // If there are no parameter then don't perform a type check - if (methodExpression.getParameters().size() == 0) { + if (methodExpression.getParameters().isEmpty()) { return; } @@ -632,7 +596,7 @@ public class FilterParserImpl implements FilterParser { // If there is not at parsing time its not possible to determine the type of eg myPropertyName. // Since this should not cause validation errors null type node arguments are leading to bypass // the validation - if ((parameter.getEdmType() == null) && (resourceEntityType == null)) { + if (parameter.getEdmType() == null && resourceEntityType == null) { return; } actualParameterTypes.add(parameter.getEdmType()); @@ -674,7 +638,7 @@ public class FilterParserImpl implements FilterParser { EdmSimpleType binary = EdmSimpleTypeFacadeImpl.getEdmSimpleType(EdmSimpleTypeKind.Binary); EdmSimpleType null_ = EdmSimpleTypeFacadeImpl.getEdmSimpleType(EdmSimpleTypeKind.Null); - // ---Memeber member access--- + // ---Member member access--- lAvailableBinaryOperators.put("/", new InfoBinaryOperator(BinaryOperator.PROPERTY_ACCESS, "Primary", 100, new ParameterSetCombination.PSCReturnTypeEqLastParameter()));// todo fix this @@ -766,7 +730,7 @@ public class FilterParserImpl implements FilterParser { combination.add(new ParameterSet(boolean_, double_, double_)); combination.add(new ParameterSet(boolean_, decimal, decimal)); combination.add(new ParameterSet(boolean_, binary, binary)); - + combination.add(new ParameterSet(boolean_, string, null_)); combination.add(new ParameterSet(boolean_, null_, string)); @@ -842,23 +806,23 @@ public class FilterParserImpl implements FilterParser { lAvailableBinaryOperators.put(BinaryOperator.NE.toUriLiteral(), new InfoBinaryOperator(BinaryOperator.NE, "Equality", 30, combination)); - // "---Conditinal AND--- + // "---Conditional AND--- combination = new ParameterSetCombination.PSCflex(); combination.add(new ParameterSet(boolean_, boolean_, boolean_)); combination.add(new ParameterSet(boolean_, boolean_, null_)); combination.add(new ParameterSet(boolean_, null_, boolean_)); lAvailableBinaryOperators.put(BinaryOperator.AND.toUriLiteral(), new InfoBinaryOperator(BinaryOperator.AND, - "Conditinal", 20, combination)); + "Conditional", 20, combination)); - // ---Conditinal OR--- + // ---Conditional OR--- combination = new ParameterSetCombination.PSCflex(); combination.add(new ParameterSet(boolean_, boolean_, boolean_)); combination.add(new ParameterSet(boolean_, boolean_, null_)); combination.add(new ParameterSet(boolean_, null_, boolean_)); lAvailableBinaryOperators.put(BinaryOperator.OR.toUriLiteral(), new InfoBinaryOperator(BinaryOperator.OR, - "Conditinal", 10, combination)); + "Conditional", 10, combination)); // endswith combination = new ParameterSetCombination.PSCflex(); http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/919d4ac0/odata2-lib/odata-core/src/main/resources/i18n.properties ---------------------------------------------------------------------- diff --git a/odata2-lib/odata-core/src/main/resources/i18n.properties b/odata2-lib/odata-core/src/main/resources/i18n.properties index 42311e4..2de9892 100644 --- a/odata2-lib/odata-core/src/main/resources/i18n.properties +++ b/odata2-lib/odata-core/src/main/resources/i18n.properties @@ -197,12 +197,12 @@ org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.COMMON=Err org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.INVALID_TRAILING_TOKEN_DETECTED_AFTER_PARSING=Invalid token "%1$s" detected after parsing at position %2$s in "%3$s". org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.TOKEN_UNDETERMINATED_STRING=Unterminated string literal at position %1$s in "%2$s". org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.INVALID_TYPES_FOR_BINARY_OPERATOR=Operator "%1$s" incompatible with operand types "%2$s" and "%3$s" at position %4$s in "%5$s". -org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.MISSING_CLOSING_PHARENTHESIS=Missing closing parenthesis ")" for opening parenthesis "(" at position %1$s in "%2$s". +org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.MISSING_CLOSING_PARENTHESIS=Missing closing parenthesis ")" for opening parenthesis "(" at position %1$s in "%2$s". org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.ERROR_IN_TOKENIZER=Error while tokenizing a ODATA expression on token "%1$s" at position %2$s in "%3$s". org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.EXPRESSION_EXPECTED_AFTER_POS=Expression expected after position %1$s in "%2$s". org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.COMMA_OR_END_EXPECTED_AT_POS=Comma or end of expression expected at position %1$s in "%2$s". org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.EXPRESSION_EXPECTED_AT_POS=Expression expected at position %1$s in "%2$s". -org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.COMMA_OR_CLOSING_PHARENTHESIS_EXPECTED_AFTER_POS=")" or "," expected after position %1$s in "%2$s". +org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.COMMA_OR_CLOSING_PARENTHESIS_EXPECTED_AFTER_POS=")" or "," expected after position %1$s in "%2$s". org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.INVALID_METHOD_CALL=Unknown function "%1$s" at position %2$s in "%3$s". org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.METHOD_WRONG_ARG_EXACT=No applicable method found for "%1$s" at position %2$s in "%3$s" with the specified arguments. Method "%1$s" requires exact %4$s argument(s). org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.METHOD_WRONG_ARG_BETWEEN=No applicable method found for "%1$s" at position %2$s in "%3$s" with the specified arguments. Method "%1$s" requires between %4$s and %5$s arguments. @@ -212,6 +212,7 @@ org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.METHOD_WRO org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.LEFT_SIDE_NOT_STRUCTURAL_TYPE=No property "%1$s" exists in type "%2$s" at position %3$s in "%4$s". org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.LEFT_SIDE_NOT_A_PROPERTY=Leftside of method operator at position %1$s is not a property in "%2$s". org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.PROPERTY_NAME_NOT_FOUND_IN_TYPE=No property "%1$s" exists in type "%2$s" at position %3$s in "%4$s". +org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.INVALID_MULTIPLICITY=The property '%1$s' at position %2$s has the wrong multiplicity. org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.INVALID_SORT_ORDER=Invalid sort order in OData orderby parser at position %1$s in "%2$s". org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.TYPE_EXPECTED_AT=Expression of type "%1$s" expected at position %2$s in "%3$s" (actual type is "%4$s"). org.apache.olingo.odata2.core.uri.expression.ExpressionParserInternalError.ERROR_PARSING_METHOD=Internal error in OData filter parser while parsing a method expression. http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/919d4ac0/odata2-lib/odata-core/src/main/resources/i18n_en.properties ---------------------------------------------------------------------- diff --git a/odata2-lib/odata-core/src/main/resources/i18n_en.properties b/odata2-lib/odata-core/src/main/resources/i18n_en.properties index 7de9229..83fd9b0 100644 --- a/odata2-lib/odata-core/src/main/resources/i18n_en.properties +++ b/odata2-lib/odata-core/src/main/resources/i18n_en.properties @@ -139,11 +139,11 @@ org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.COMMON=Err org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.INVALID_TRAILING_TOKEN_DETECTED_AFTER_PARSING=Invalid token "%1$s" detected after parsing at position %2$s in "%3$s". org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.TOKEN_UNDETERMINATED_STRING=Unterminated string literal at position %1$s in "%2$s". org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.INVALID_TYPES_FOR_BINARY_OPERATOR=Operator "%1$s" incompatible with operand types "%2$s" and "%3$s" at position %4$s in "%5$s". -org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.MISSING_CLOSING_PHARENTHESIS=Missing closing parenthesis ")" for opening parenthesis "(" at position %1$s in "%2$s". +org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.MISSING_CLOSING_PARENTHESIS=Missing closing parenthesis ")" for opening parenthesis "(" at position %1$s in "%2$s". org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.ERROR_IN_TOKENIZER=Error while tokenizing a ODATA expression on token '%1$s' at position '%2$s'. org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.EXPRESSION_EXPECTED_AFTER_POS=Expression expected after position %1$s in "%2$s". org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.EXPRESSION_EXPECTED_AT_POS=Expression expected at position %1$s. -org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.COMMA_OR_CLOSING_PHARENTHESIS_EXPECTED_AFTER_POS=")" or "," expected after position %1$s. +org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.COMMA_OR_CLOSING_PARENTHESIS_EXPECTED_AFTER_POS=")" or "," expected after position %1$s. org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.METHOD_WRONG_ARG_EXACT=No applicable method found for "%1$s" at position %2$s in "%3$s" with the specified arguments. Method "%1$s" requires exact %4$s argument(s). org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.METHOD_WRONG_ARG_BETWEEN=No applicable method found for "%1$s" at position %2$s in "%3$s" with the specified arguments. Method "%1$s" requires between %4$s and %5$s arguments. @@ -152,6 +152,7 @@ org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.METHOD_WRO org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.LEFT_SIDE_NOT_STRUCTURAL_TYPE=No property "%1$s" exists in type "%2$s" at position %3$s in "%4$s". org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.LEFT_SIDE_NOT_A_PROPERTY=Leftside of method operator at position %1$s is not a property in "%2$s". org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.PROPERTY_NAME_NOT_FOUND_IN_TYPE=No property "%1$s" exists in type "%2$s" at position %3$s in "%4$s". +org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.INVALID_MULTIPLICITY=The property '%1$s' at position %2$s has the wrong multiplicity. org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.INVALID_SORT_ORDER=Invalid sort order in OData orderby parser at position %1$s in %2$s. org.apache.olingo.odata2.core.uri.expression.ExpressionParserInternalError.ERROR_PARSING_METHOD=Internal error in OData filter parser while parsing a method expression. org.apache.olingo.odata2.core.uri.expression.ExpressionParserInternalError.ERROR_PARSING_PARENTHESIS=Internal error in OData filter parser while parsing a parenthesis expression. http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/919d4ac0/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/uri/expression/ParserTool.java ---------------------------------------------------------------------- diff --git a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/uri/expression/ParserTool.java b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/uri/expression/ParserTool.java index 1c7d08b..7c2357e 100644 --- a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/uri/expression/ParserTool.java +++ b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/uri/expression/ParserTool.java @@ -19,13 +19,15 @@ package org.apache.olingo.odata2.core.uri.expression; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.util.Locale; -import org.apache.log4j.xml.DOMConfigurator; import org.apache.olingo.odata2.api.edm.EdmEntityType; -import org.apache.olingo.odata2.api.edm.EdmException; import org.apache.olingo.odata2.api.edm.EdmProperty; import org.apache.olingo.odata2.api.edm.EdmType; import org.apache.olingo.odata2.api.exception.MessageReference; @@ -40,78 +42,31 @@ import org.apache.olingo.odata2.api.uri.expression.SortOrder; import org.apache.olingo.odata2.core.exception.MessageService; import org.apache.olingo.odata2.core.exception.MessageService.Message; import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** - * + * Helper for testing the expression parser. */ public class ParserTool { - static { - DOMConfigurator.configureAndWatch("log4j.xml"); - } - - private static final Logger log = LoggerFactory.getLogger(ParserTool.class); - - private static boolean debug = false; - private String expression; private CommonExpression tree; private CommonExpression curNode; private Exception curException; private static final Locale DEFAULT_LANGUAGE = new Locale("test", "FOO"); - public static void dout(final String out) { - if (debug) { - ParserTool.log.debug(out); - } - } - - public static void out(final String out) { - ParserTool.log.debug(out); - } - - public ParserTool(final String expression, final boolean isOrder, final boolean addTestfunctions, - final boolean allowOnlyBinary) { - dout("ParserTool - Testing: " + expression); - this.expression = expression; - - try { - if (!isOrder) { - FilterParserImplTool parser = new FilterParserImplTool(null); - if (addTestfunctions) { - parser.addTestfunctions(); - } - tree = parser.parseFilterString(expression, allowOnlyBinary).getExpression(); - } else { - OrderByParserImpl parser = new OrderByParserImpl(null); - tree = parser.parseOrderByString(expression); - } - } catch (ExpressionParserException e) { - curException = e; - } catch (ExpressionParserInternalError e) { - curException = e; - } - - curNode = tree; - } - public ParserTool(final String expression, final boolean isOrder, final boolean addTestfunctions, final boolean allowOnlyBinary, final EdmEntityType resourceEntityType) { - dout("ParserTool - Testing: " + expression); this.expression = expression; try { - if (!isOrder) { + if (isOrder) { + tree = new OrderByParserImpl(resourceEntityType).parseOrderByString(expression); + } else { FilterParserImplTool parser = new FilterParserImplTool(resourceEntityType); if (addTestfunctions) { parser.addTestfunctions(); } tree = parser.parseFilterString(expression, allowOnlyBinary).getExpression(); - } else { - OrderByParserImpl parser = new OrderByParserImpl(resourceEntityType); - tree = parser.parseOrderByString(expression); } } catch (ExpressionParserException e) { curException = e; @@ -124,16 +79,12 @@ public class ParserTool { ParserTool aKind(final ExpressionKind kind) { String info = "GetInfoKind(" + expression + ")-->"; - dout(" " + info + "Expected: " + kind.toString() + " Actual: " + curNode.getKind().toString()); - assertEquals(info, kind, curNode.getKind()); return this; } public ParserTool aUriLiteral(final String uriLiteral) { String info = "GetUriLiteral(" + expression + ")-->"; - dout(" " + info + "Expected: " + uriLiteral + " Actual: " + curNode.getUriLiteral()); - assertEquals(info, uriLiteral, curNode.getUriLiteral()); return this; } @@ -148,15 +99,8 @@ public class ParserTool { public ParserTool aExType(final Class<? extends Exception> expected) { String info = "GetExceptionType(" + expression + ")-->"; - if (curException == null) { - fail("Error in aExType: Expected exception " + expected.getName()); - } - - dout(" " + info + "Expected: " + expected.getName() + " Actual: " + curException.getClass().getName()); - - if (expected != curException.getClass()) { - fail(" " + info + "Expected: " + expected.getName() + " Actual: " + curException.getClass().getName()); - } + assertNotNull(info, curException); + assertTrue(info, expected.isAssignableFrom(curException.getClass())); return this; } @@ -169,24 +113,11 @@ public class ParserTool { */ public ParserTool aExMsgText(final String messageText) { String info = "aExMessageText(" + expression + ")-->"; - if (curException == null) { - fail("Error in aExMessageText: Expected exception."); - } - - ODataMessageException messageException; - try { - messageException = (ODataMessageException) curException; - } catch (ClassCastException ex) { - fail("Error in aExNext: curException not an ODataMessageException"); - return this; - } - - Message ms = MessageService.getMessage(DEFAULT_LANGUAGE, messageException.getMessageReference()); - info = " " + info + "Expected: '" + messageText + "' Actual: '" + ms.getText() + "'"; + aExType(ODataMessageException.class); - dout(info); - assertEquals(info, messageText, ms.getText()); + info = " " + info + "Expected: '" + messageText + "' Actual: '" + getExceptionText() + "'"; + assertEquals(info, messageText, getExceptionText()); return this; } @@ -199,27 +130,12 @@ public class ParserTool { */ public ParserTool aExMsgContentAllSet() { String info = "aExMessageTextNoEmptyTag(" + expression + ")-->"; - if (curException == null) { - fail("Error in aExMessageText: Expected exception."); - } - - ODataMessageException messageException; - - try { - messageException = (ODataMessageException) curException; - } catch (ClassCastException ex) { - fail("Error in aExNext: curException not an ODataMessageException"); - return this; - } - Message ms = MessageService.getMessage(DEFAULT_LANGUAGE, messageException.getMessageReference()); - info = " " + info + "Messagetext: '" + ms.getText() + "contains [%"; + aExType(ODataMessageException.class); - dout(info); + info = " " + info + "Messagetext: '" + getExceptionText() + "contains [%"; + assertFalse(info, getExceptionText().contains("[%")); - if (ms.getText().contains("[%")) { - fail(info); - } return this; } @@ -229,74 +145,23 @@ public class ParserTool { * @return ParserTool */ public ParserTool aExMsgNotEmpty() { - String info = "aExTextNotEmpty(" + expression + ")-->"; - if (curException == null) { - fail("Error in aExMessageText: Expected exception."); - } + String info = "aExMsgNotEmpty(" + expression + ")-->"; - ODataMessageException messageException; + aExType(ODataMessageException.class); - try { - messageException = (ODataMessageException) curException; - } catch (ClassCastException ex) { - fail("Error in aExNext: curException not an ODataMessageException"); - return this; - } - - Message ms = MessageService.getMessage(DEFAULT_LANGUAGE, messageException.getMessageReference()); info = " " + info + "check if Messagetext is empty"; - dout(info); + assertFalse(info, getExceptionText().isEmpty()); - if (ms.getText().length() == 0) { - fail(info); - } return this; } public ParserTool aExKey(final MessageReference expressionExpectedAtPos) { - String expectedKey = expressionExpectedAtPos.getKey(); - ODataMessageException messageException; - String info = "GetExceptionType(" + expression + ")-->"; - if (curException == null) { - fail("Error in aExType: Expected exception"); - } - - try { - messageException = (ODataMessageException) curException; - } catch (ClassCastException ex) { - fail("Error in aExNext: curException not an ODataMessageException"); - return this; - } - - String actualKey = messageException.getMessageReference().getKey(); - dout(" " + info + "Expected key: " + expectedKey + " Actual: " + actualKey); - - if (expectedKey != actualKey) { - fail(" " + info + "Expected: " + expectedKey + " Actual: " + actualKey); - } - return this; - } - - public ParserTool printExMessage() { - ODataMessageException messageException; - if (curException == null) { - fail("Error in aExMsgPrint: Expected exception"); - } - - try { - messageException = (ODataMessageException) curException; - } catch (ClassCastException ex) { - fail("Error in aExNext: curException not an ODataMessageException"); - return this; - } - - Message ms = MessageService.getMessage(DEFAULT_LANGUAGE, messageException.getMessageReference()); - out("Messge --> "); - out(" " + ms.getText()); - out("Messge <-- "); + aExType(ODataMessageException.class); + assertEquals(info, expressionExpectedAtPos.getKey(), + ((ODataMessageException) curException).getMessageReference().getKey()); return this; } @@ -305,62 +170,13 @@ public class ParserTool { Message ms = MessageService.getMessage(DEFAULT_LANGUAGE, messageException.getMessageReference()); return ms.getText(); - - } - - public ParserTool printSerialized() { - String actual = null; - ExpressionVisitor visitor = new VisitorTool(); - try { - actual = tree.accept(visitor).toString(); - } catch (ExceptionVisitExpression e) { - fail("Error in visitor:" + e.getLocalizedMessage()); - } catch (ODataApplicationException e) { - fail("Error in visitor:" + e.getLocalizedMessage()); - } - - out("Messge --> "); - out(" " + actual); - out("Messge <-- "); - return this; - } - - public ParserTool exPrintStack() { - curException.printStackTrace(); - return this; - } - - public ParserTool exNext() { - try { - curException = (Exception) curException.getCause(); - } catch (ClassCastException ex) { - fail("Error in aExNext: Cause not an Exception"); - } - return this; - } - - private void checkNoException(final String infoMethod) { - if (curException != null) { - fail("Error in " + infoMethod + ": exception '" + getExceptionText() + "' occured!"); - } } public ParserTool aEdmType(final EdmType type) { - checkNoException("aEdmType"); + assertNull("aEdmType", curException); String info = "GetEdmType(" + expression + ")-->"; - try { - if (curNode.getEdmType() == null) { - dout(" " + info + "Expected: " + type.getName() + " Actual: " + "null"); - fail("Error in aEdmType: type of curNode is null"); - } - - dout(" " + info + "Expected: " + type.getName() + " Actual: " + curNode.getEdmType().getName()); - - } catch (EdmException e) { - fail("Error in aEdmType:" + e.getLocalizedMessage()); - } - + assertNotNull(curNode.getEdmType()); assertEquals(info, type, curNode.getEdmType()); return this; } @@ -368,59 +184,26 @@ public class ParserTool { public ParserTool aSortOrder(final SortOrder orderType) { String info = "GetSortOrder(" + expression + ")-->"; - if (curNode.getKind() != ExpressionKind.ORDER) { - String out = info + "Expected: " + ExpressionKind.ORDER + " Actual: " + curNode.getKind().toString(); - dout(" " + out); - fail(out); - } - - OrderExpressionImpl orderExpression = (OrderExpressionImpl) curNode; - dout(" " + info + "Expected: " + orderType.toString() + " Actual: " + orderExpression.getSortOrder().toString()); - - assertEquals(info, orderType, orderExpression.getSortOrder()); + aKind(ExpressionKind.ORDER); + assertEquals(info, orderType, ((OrderExpressionImpl) curNode).getSortOrder()); return this; } public ParserTool aExpr() { String info = "GetExpr(" + expression + ")-->"; - if ((curNode.getKind() != ExpressionKind.ORDER) && (curNode.getKind() != ExpressionKind.FILTER)) { - String out = - info + "Expected: " + ExpressionKind.ORDER + " or " + ExpressionKind.FILTER + " Actual: " - + curNode.getKind().toString(); - dout(" " + out); - fail(out); - } - - if (curNode.getKind() == ExpressionKind.FILTER) { - FilterExpressionImpl filterExpression = (FilterExpressionImpl) curNode; - curNode = filterExpression.getExpression(); - } else { - OrderExpressionImpl orderByExpression = (OrderExpressionImpl) curNode; - curNode = orderByExpression.getExpression(); - } + aKind(ExpressionKind.ORDER); + curNode = ((OrderExpressionImpl) curNode).getExpression(); + assertNotNull(info, curNode); return this; } - public ParserTool aEdmProperty(final EdmProperty string) { + public ParserTool aEdmProperty(final EdmProperty property) { String info = "GetEdmProperty(" + expression + ")-->"; - if (curNode.getKind() != ExpressionKind.PROPERTY) { - String out = info + "Expected: " + ExpressionKind.PROPERTY + " Actual: " + curNode.getKind().toString(); - dout(" " + out); - fail(out); - } - - PropertyExpressionImpl propertyExpression = (PropertyExpressionImpl) curNode; - try { - dout(" " + info + "Expected: Property'" + string.getName() + "' Actual: " - + propertyExpression.getEdmProperty().getName()); - } catch (EdmException e) { - fail("Error in aEdmProperty:" + e.getLocalizedMessage()); - } - - assertEquals(info, string, propertyExpression.getEdmProperty()); + aKind(ExpressionKind.PROPERTY); + assertEquals(info, property, ((PropertyExpressionImpl) curNode).getEdmProperty()); return this; } @@ -430,7 +213,7 @@ public class ParserTool { } public ParserTool aSerialized(final String expected) { - checkNoException("aSerialized"); + assertNull("aSerialized", curException); String actual = null; ExpressionVisitor visitor = new VisitorTool(); @@ -443,103 +226,61 @@ public class ParserTool { } String info = "GetSerialized(" + expression + ")-->"; - dout(" " + info + "Expected: " + expected + " Actual: " + actual); - assertEquals(info, expected, actual); return this; } public ParserTool left() { - switch (curNode.getKind()) { - case BINARY: + String info = "param(" + expression + ")-->"; + + assertTrue(info, curNode.getKind() == ExpressionKind.BINARY + || curNode.getKind() == ExpressionKind.UNARY + || curNode.getKind() == ExpressionKind.MEMBER); + + if (curNode.getKind() == ExpressionKind.BINARY) { curNode = ((BinaryExpressionImpl) curNode).getLeftOperand(); - break; - case MEMBER: - curNode = ((MemberExpressionImpl) curNode).getPath(); - break; - case LITERAL: - case METHOD: - case PROPERTY: - String info = "param(" + expression + ")-->"; - info = - " " + info + "Expected: " + ExpressionKind.BINARY.toString() + " or " + ExpressionKind.MEMBER.toString() - + " Actual: " + curNode.getKind(); - dout(info); - fail(info); - break; - case UNARY: + } else if (curNode.getKind() == ExpressionKind.UNARY) { curNode = ((UnaryExpressionImpl) curNode).getOperand(); - break; - default: - break; + } else if (curNode.getKind() == ExpressionKind.MEMBER) { + curNode = ((MemberExpressionImpl) curNode).getPath(); } return this; } public ParserTool right() { - switch (curNode.getKind()) { - case BINARY: + String info = "param(" + expression + ")-->"; + + assertTrue(info, curNode.getKind() == ExpressionKind.BINARY + || curNode.getKind() == ExpressionKind.UNARY + || curNode.getKind() == ExpressionKind.MEMBER); + + if (curNode.getKind() == ExpressionKind.BINARY) { curNode = ((BinaryExpressionImpl) curNode).getRightOperand(); - break; - case MEMBER: - curNode = ((MemberExpressionImpl) curNode).getProperty(); - break; - case LITERAL: - case METHOD: - case PROPERTY: - String info = "param(" + expression + ")-->"; - info = - " " + info + "Expected: " + ExpressionKind.BINARY.toString() + " or " + ExpressionKind.MEMBER.toString() - + " Actual: " + curNode.getKind(); - dout(info); - fail(info); - break; - case UNARY: + } else if (curNode.getKind() == ExpressionKind.UNARY) { curNode = ((UnaryExpressionImpl) curNode).getOperand(); - break; - default: - break; + } else if (curNode.getKind() == ExpressionKind.MEMBER) { + curNode = ((MemberExpressionImpl) curNode).getProperty(); } return this; } public ParserTool order(final int i) { - if (curNode.getKind() != ExpressionKind.ORDERBY) { - String info = "param(" + expression + ")-->"; - info = " " + info + "Expected: " + ExpressionKind.ORDERBY.toString() + " Actual: " + curNode.getKind(); - dout(info); - fail(info); - } + String info = "param(" + expression + ")-->"; + aKind(ExpressionKind.ORDERBY); OrderByExpressionImpl orderByExpressionImpl = (OrderByExpressionImpl) curNode; - if (i >= orderByExpressionImpl.getOrdersCount()) { - String info = "param(" + expression + ")-->"; - info = " " + info + "Too wrong index! Expected max: " + orderByExpressionImpl.getOrdersCount() + " Actual: " + i; - dout(info); - fail(info); - } + assertTrue(info, i < orderByExpressionImpl.getOrdersCount()); curNode = orderByExpressionImpl.getOrders().get(i); return this; - } public ParserTool param(final int i) { - if (curNode.getKind() != ExpressionKind.METHOD) { - String info = "param(" + expression + ")-->"; - info = " " + info + "Expected: " + ExpressionKind.METHOD.toString() + " Actual: " + curNode.getKind(); - dout(info); - fail(info); - } + String info = "param(" + expression + ")-->"; + aKind(ExpressionKind.METHOD); MethodExpressionImpl methodExpressionImpl = (MethodExpressionImpl) curNode; - if (i >= methodExpressionImpl.getParameterCount()) { - String info = "param(" + expression + ")-->"; - info = - " " + info + "Too wrong index! Expected max: " + methodExpressionImpl.getParameterCount() + " Actual: " + i; - dout(info); - fail(info); - } + assertTrue(info, i < methodExpressionImpl.getParameterCount()); curNode = methodExpressionImpl.getParameters().get(i); return this; @@ -569,7 +310,7 @@ public class ParserTool { public static class testParserTool { @Test public void testCompr() { - // leading and trainling spaces + // leading and trailing spaces assertEquals("Error in parsertool", compress(" a"), "a"); assertEquals("Error in parsertool", compress("a "), "a"); assertEquals("Error in parsertool", compress(" a "), "a"); @@ -588,9 +329,4 @@ public class ParserTool { assertEquals("Error in parsertool", compress(" { a { } a } "), "{a {} a}"); } } - - public ParserTool exRoot() { - return this; - } - } http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/919d4ac0/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/uri/expression/TestBase.java ---------------------------------------------------------------------- diff --git a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/uri/expression/TestBase.java b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/uri/expression/TestBase.java index 5a636fe..cdb92a3 100644 --- a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/uri/expression/TestBase.java +++ b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/uri/expression/TestBase.java @@ -37,15 +37,15 @@ public class TestBase { } static public ParserTool GetPTF(final String expression) { - return new ParserTool(expression, false, true, false); + return new ParserTool(expression, false, true, false, null); } static public ParserTool GetPTF_onlyBinary(final String expression) { - return new ParserTool(expression, false, true, true); + return new ParserTool(expression, false, true, true, null); } static public ParserTool GetPTFE(final String expression) { - return new ParserTool(expression, false, true, false); + return new ParserTool(expression, false, true, false, null); } static public ParserTool GetPTF(final EdmEntityType resourceEntityType, final String expression) { @@ -53,7 +53,7 @@ public class TestBase { } static public ParserTool GetPTO(final String expression) { - return new ParserTool(expression, true, true, false); + return new ParserTool(expression, true, true, false, null); } static public ParserTool GetPTO(final EdmEntityType resourceEntityType, final String expression) { @@ -61,7 +61,7 @@ public class TestBase { } static public ParserTool GetPTF_noTEST(final String expression) { - return new ParserTool(expression, false, false, false); + return new ParserTool(expression, false, false, false, null); } static public ParserTool GetPTF_noTEST(final EdmEntityType resourceEntityType, final String expression) { @@ -69,7 +69,7 @@ public class TestBase { } static public ParserTool GetPTO_noTEST(final String expression) { - return new ParserTool(expression, true, false, true); + return new ParserTool(expression, true, false, true, null); } static public ParserTool GetPTO_noTEST(final EdmEntityType resourceEntityType, final String expression) { http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/919d4ac0/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/uri/expression/TestParser.java ---------------------------------------------------------------------- diff --git a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/uri/expression/TestParser.java b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/uri/expression/TestParser.java index 84a48e8..bbec5d9 100644 --- a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/uri/expression/TestParser.java +++ b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/uri/expression/TestParser.java @@ -18,15 +18,8 @@ ******************************************************************************/ package org.apache.olingo.odata2.core.uri.expression; -import static org.junit.Assert.fail; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - import org.apache.olingo.odata2.api.edm.EdmComplexType; import org.apache.olingo.odata2.api.edm.EdmEntityType; -import org.apache.olingo.odata2.api.edm.EdmException; import org.apache.olingo.odata2.api.edm.EdmProperty; import org.apache.olingo.odata2.api.edm.EdmSimpleType; import org.apache.olingo.odata2.api.uri.expression.ExpressionKind; @@ -44,6 +37,7 @@ import org.apache.olingo.odata2.core.edm.EdmGuid; import org.apache.olingo.odata2.core.edm.EdmInt16; import org.apache.olingo.odata2.core.edm.EdmInt32; import org.apache.olingo.odata2.core.edm.EdmInt64; +import org.apache.olingo.odata2.core.edm.EdmNull; import org.apache.olingo.odata2.core.edm.EdmSByte; import org.apache.olingo.odata2.core.edm.EdmSingle; import org.apache.olingo.odata2.core.edm.EdmString; @@ -58,39 +52,39 @@ import org.junit.Test; public class TestParser extends TestBase { @Test - public void testQuick() { + public void quick() { GetPTF("substring('Test', 1 add 2)").aSerialized("{substring('Test',{1 add 2})}"); } @Test - public void testOrderBy() { + public void orderBy() { - GetPTO("sven").aSerialized("{oc({o(sven, asc)})}"); - GetPTO("sven asc").aSerialized("{oc({o(sven, asc)})}"); - GetPTO("sven desc").aSerialized("{oc({o(sven, desc)})}"); - GetPTO("sven asc").aSerialized("{oc({o(sven, asc)})}"); - GetPTO("sven desc").aSerialized("{oc({o(sven, desc)})}"); + GetPTO("name").aSerialized("{oc({o(name, asc)})}"); + GetPTO("name asc").aSerialized("{oc({o(name, asc)})}"); + GetPTO("name desc").aSerialized("{oc({o(name, desc)})}"); + GetPTO("name asc").aSerialized("{oc({o(name, asc)})}"); + GetPTO("name desc").aSerialized("{oc({o(name, desc)})}"); - GetPTO("sven, test").aSerialized("{oc({o(sven, asc)},{o(test, asc)})}"); - GetPTO("sven , test").aSerialized("{oc({o(sven, asc)},{o(test, asc)})}"); + GetPTO("name, test").aSerialized("{oc({o(name, asc)},{o(test, asc)})}"); + GetPTO("name , test").aSerialized("{oc({o(name, asc)},{o(test, asc)})}"); - GetPTO("sven, test asc").aSerialized("{oc({o(sven, asc)},{o(test, asc)})}"); + GetPTO("name, test asc").aSerialized("{oc({o(name, asc)},{o(test, asc)})}"); - GetPTO("sven asc, test").aSerialized("{oc({o(sven, asc)},{o(test, asc)})}"); + GetPTO("name asc, test").aSerialized("{oc({o(name, asc)},{o(test, asc)})}"); - GetPTO("sven asc, test asc").aSerialized("{oc({o(sven, asc)},{o(test, asc)})}"); - GetPTO("sven, test desc").aSerialized("{oc({o(sven, asc)},{o(test, desc)})}"); - GetPTO("sven desc, test").aSerialized("{oc({o(sven, desc)},{o(test, asc)})}"); - GetPTO("sven desc, test desc").aSerialized("{oc({o(sven, desc)},{o(test, desc)})}"); + GetPTO("name asc, test asc").aSerialized("{oc({o(name, asc)},{o(test, asc)})}"); + GetPTO("name, test desc").aSerialized("{oc({o(name, asc)},{o(test, desc)})}"); + GetPTO("name desc, test").aSerialized("{oc({o(name, desc)},{o(test, asc)})}"); + GetPTO("name desc, test desc").aSerialized("{oc({o(name, desc)},{o(test, desc)})}"); - GetPTO("'sven', 77").order(1).aSortOrder(SortOrder.asc); - GetPTO("'sven', 77 desc").root().order(0).aSortOrder(SortOrder.asc).aExpr().aEdmType(EdmString.getInstance()) + GetPTO("'name', 77").order(1).aSortOrder(SortOrder.asc); + GetPTO("'name', 77 desc").root().order(0).aSortOrder(SortOrder.asc).aExpr().aEdmType(EdmString.getInstance()) .root().order(1).aSortOrder(SortOrder.desc).aExpr().aEdmType(Uint7.getInstance()); } @Test - public void testPromotion() { + public void promotion() { // SByte <--> SByte GetPTF("-10").aEdmType(EdmSByte.getInstance()); GetPTF("-10 add -10").aEdmType(EdmSByte.getInstance()); @@ -126,17 +120,16 @@ public class TestParser extends TestBase { GetPTF("concat('a','b')").aEdmType(EdmString.getInstance()); GetPTF("concat('a','b','c')").aEdmType(EdmString.getInstance()); } - - @Test - public void testProperties() { - // GetPTF("sven").aSerialized("sven").aKind(ExpressionKind.PROPERTY); - GetPTF("sven1 add sven2").aSerialized("{sven1 add sven2}").aKind(ExpressionKind.BINARY).root().left().aKind( - ExpressionKind.PROPERTY).aUriLiteral("sven1").root().right().aKind(ExpressionKind.PROPERTY) - .aUriLiteral("sven2"); + + @Test + public void properties() { + GetPTF("name1 add name2").aSerialized("{name1 add name2}").aKind(ExpressionKind.BINARY).root().left().aKind( + ExpressionKind.PROPERTY).aUriLiteral("name1").root().right().aKind(ExpressionKind.PROPERTY) + .aUriLiteral("name2"); } @Test - public void testDeepProperties() { + public void deepProperties() { GetPTF("a/b").aSerialized("{a/b}").aKind(ExpressionKind.MEMBER); GetPTF("a/b/c").aSerialized("{{a/b}/c}").root().aKind(ExpressionKind.MEMBER).root().left().aKind( ExpressionKind.MEMBER).root().left().left().aKind(ExpressionKind.PROPERTY).aUriLiteral("a").root().left() @@ -145,88 +138,79 @@ public class TestParser extends TestBase { } @Test - public void testPropertiesWithEdm() { - try { - EdmEntityType edmEtAllTypes = edmInfo.getTypeEtAllTypes(); - EdmProperty string = (EdmProperty) edmEtAllTypes.getProperty("String"); - EdmSimpleType stringType = (EdmSimpleType) string.getType(); - EdmComplexPropertyImplProv complex = (EdmComplexPropertyImplProv) edmEtAllTypes.getProperty("Complex"); - EdmComplexType complexType = (EdmComplexType) complex.getType(); - EdmProperty complexString = (EdmProperty) complexType.getProperty("String"); - EdmSimpleType complexStringType = (EdmSimpleType) complexString.getType(); - EdmComplexPropertyImplProv complexAddress = (EdmComplexPropertyImplProv) complexType.getProperty("Address"); - EdmComplexType complexAddressType = (EdmComplexType) complexAddress.getType(); - EdmProperty complexAddressCity = (EdmProperty) complexAddressType.getProperty("City"); - EdmSimpleType complexAddressCityType = (EdmSimpleType) complexAddressCity.getType(); - - GetPTF(edmEtAllTypes, "String").aEdmProperty(string).aEdmType(stringType); - - GetPTF(edmEtAllTypes, "'text' eq String").root().aKind(ExpressionKind.BINARY); - - GetPTF(edmEtAllTypes, "Complex/String").root().left().aEdmProperty(complex).aEdmType(complexType).root().right() - .aEdmProperty(complexString).aEdmType(complexStringType).root().aKind(ExpressionKind.MEMBER).aEdmType( - complexStringType); - - GetPTF(edmEtAllTypes, "Complex/Address/City").root().aKind(ExpressionKind.MEMBER).root().left().aKind( - ExpressionKind.MEMBER).root().left().left().aKind(ExpressionKind.PROPERTY).aEdmProperty(complex).aEdmType( - complexType).root().left().right().aKind(ExpressionKind.PROPERTY).aEdmProperty(complexAddress).aEdmType( - complexAddressType).root().left().aEdmType(complexAddressType).root().right().aKind(ExpressionKind.PROPERTY) - .aEdmProperty(complexAddressCity).aEdmType(complexAddressCityType).root().aEdmType(complexAddressCityType); - - EdmProperty boolean_ = (EdmProperty) edmEtAllTypes.getProperty("Boolean"); - EdmSimpleType boolean_Type = (EdmSimpleType) boolean_.getType(); - - GetPTF(edmEtAllTypes, "not Boolean").aKind(ExpressionKind.UNARY).aEdmType(boolean_Type).right().aEdmProperty( - boolean_).aEdmType(boolean_Type); - - } catch (EdmException e) { - fail("Error in testPropertiesWithEdm:" + e.getLocalizedMessage()); - e.printStackTrace(); - } + public void propertiesWithEdm() throws Exception { + EdmEntityType edmEtAllTypes = edmInfo.getTypeEtAllTypes(); + EdmProperty string = (EdmProperty) edmEtAllTypes.getProperty("String"); + EdmSimpleType stringType = (EdmSimpleType) string.getType(); + EdmComplexPropertyImplProv complex = (EdmComplexPropertyImplProv) edmEtAllTypes.getProperty("Complex"); + EdmComplexType complexType = (EdmComplexType) complex.getType(); + EdmProperty complexString = (EdmProperty) complexType.getProperty("String"); + EdmSimpleType complexStringType = (EdmSimpleType) complexString.getType(); + EdmComplexPropertyImplProv complexAddress = (EdmComplexPropertyImplProv) complexType.getProperty("Address"); + EdmComplexType complexAddressType = (EdmComplexType) complexAddress.getType(); + EdmProperty complexAddressCity = (EdmProperty) complexAddressType.getProperty("City"); + EdmSimpleType complexAddressCityType = (EdmSimpleType) complexAddressCity.getType(); + + GetPTF(edmEtAllTypes, "String").aEdmProperty(string).aEdmType(stringType); + + GetPTF(edmEtAllTypes, "'text' eq String").root().aKind(ExpressionKind.BINARY); + + GetPTF(edmEtAllTypes, "Complex/String").root().left().aEdmProperty(complex).aEdmType(complexType).root().right() + .aEdmProperty(complexString).aEdmType(complexStringType).root().aKind(ExpressionKind.MEMBER).aEdmType( + complexStringType); + + GetPTF(edmEtAllTypes, "Complex/Address/City").root().aKind(ExpressionKind.MEMBER).root().left().aKind( + ExpressionKind.MEMBER).root().left().left().aKind(ExpressionKind.PROPERTY).aEdmProperty(complex).aEdmType( + complexType) + .root().left().right().aKind(ExpressionKind.PROPERTY).aEdmProperty(complexAddress).aEdmType( + complexAddressType) + .root().left().aEdmType(complexAddressType).root().right().aKind(ExpressionKind.PROPERTY) + .aEdmProperty(complexAddressCity).aEdmType(complexAddressCityType).root().aEdmType(complexAddressCityType); + + EdmProperty boolean_ = (EdmProperty) edmEtAllTypes.getProperty("Boolean"); + EdmSimpleType boolean_Type = (EdmSimpleType) boolean_.getType(); + + GetPTF(edmEtAllTypes, "not Boolean").aKind(ExpressionKind.UNARY).aEdmType(boolean_Type).right().aEdmProperty( + boolean_).aEdmType(boolean_Type); } @Test - public void testSimpleMethod() { + public void simpleMethod() { GetPTF("startswith('Test','Te')").aSerialized("{startswith('Test','Te')}"); - - GetPTF("startswith('Test','Te')").aSerialized("{startswith('Test','Te')}"); - GetPTF("startswith('Test', concat('A','B'))").aSerialized("{startswith('Test',{concat('A','B')})}"); - GetPTF("substring('Test', 1 add 2)").aSerialized("{substring('Test',{1 add 2})}"); } @Test - public void testMethodVariableParameters() { + public void methodVariableParameters() { GetPTF("concat('Test', 'A' )").aSerialized("{concat('Test','A')}"); GetPTF("concat('Test', 'A', 'B' )").aSerialized("{concat('Test','A','B')}"); GetPTF("concat('Test', 'A', 'B', 'C' )").aSerialized("{concat('Test','A','B','C')}"); } @Test - public void testSimpleSameBinary() { + public void simpleSameBinary() { GetPTF("1d add 2d").aSerialized("{1d add 2d}"); GetPTF("1d div 2d").aSerialized("{1d div 2d}"); GetPTF("1d add 2d").aSerialized("{1d add 2d}").aKind(ExpressionKind.BINARY).root().left().aKind( ExpressionKind.LITERAL).root().right().aKind(ExpressionKind.LITERAL); - } @Test - public void testSimpleSameBinaryBinary() { + public void simpleSameBinaryBinary() { GetPTF("1d add 2d add 3d").aSerialized("{{1d add 2d} add 3d}"); GetPTF("1d div 2d div 3d").aSerialized("{{1d div 2d} div 3d}"); } @Test - public void testSimpleSameBinaryBinaryPriority() { + public void simpleSameBinaryBinaryPriority() { GetPTF("1d add 2d div 3d").aSerialized("{1d add {2d div 3d}}"); GetPTF("1d div 2d add 3d").aSerialized("{{1d div 2d} add 3d}"); } @Test - public void testSimpleSameBinaryBinaryBinaryPriority() { + public void simpleSameBinaryBinaryBinaryPriority() { GetPTF("1d add 2d add 3d add 4d").aSerialized("{{{1d add 2d} add 3d} add 4d}"); GetPTF("1d add 2d add 3d div 4d").aSerialized("{{1d add 2d} add {3d div 4d}}"); GetPTF("1d add 2d div 3d add 4d").aSerialized("{{1d add {2d div 3d}} add 4d}"); @@ -238,7 +222,7 @@ public class TestParser extends TestBase { } @Test - public void testComplexMixedPriority() { + public void complexMixedPriority() { GetPTF("a or c and e ").aSerializedCompr("{ a or { c and e }}"); GetPTF("a or c and e eq f").aSerializedCompr("{ a or { c and {e eq f}}}"); GetPTF("a or c eq d and e ").aSerializedCompr("{ a or {{c eq d} and e }}"); @@ -253,7 +237,7 @@ public class TestParser extends TestBase { } @Test - public void testDeepParenthesis() { + public void deepParenthesis() { GetPTF("2d").aSerialized("2d"); GetPTF("(2d)").aSerialized("2d"); GetPTF("((2d))").aSerialized("2d"); @@ -261,7 +245,7 @@ public class TestParser extends TestBase { } @Test - public void testParenthesisWithBinaryBinary() { + public void parenthesisWithBinaryBinary() { GetPTF("1d add 2d add 3d").aSerialized("{{1d add 2d} add 3d}"); GetPTF("1d add (2d add 3d)").aSerialized("{1d add {2d add 3d}}"); GetPTF("(1d add 2d) add 3d").aSerialized("{{1d add 2d} add 3d}"); @@ -279,7 +263,7 @@ public class TestParser extends TestBase { } @Test - public void testSimpleUnaryOperator() { + public void simpleUnaryOperator() { GetPTF("not true").aSerialized("{not true}"); GetPTF("- 2d").aSerialized("{- 2d}"); @@ -291,7 +275,7 @@ public class TestParser extends TestBase { } @Test - public void testDeepUnaryOperator() { + public void deepUnaryOperator() { GetPTF("not not true").aSerialized("{not {not true}}"); GetPTF("not not not true").aSerialized("{not {not {not true}}}"); GetPTF("-- 2d").aSerialized("{- {- 2d}}"); @@ -304,19 +288,19 @@ public class TestParser extends TestBase { } @Test - public void testMixedUnaryOperators() { + public void mixedUnaryOperators() { GetPTF("not - true").aSerialized("{not {- true}}"); GetPTF("- not true").aSerialized("{- {not true}}"); } @Test - public void testDeepMixedUnaryOperators() { + public void deepMixedUnaryOperators() { GetPTF("- not - true").aSerialized("{- {not {- true}}}"); GetPTF("not - not true").aSerialized("{not {- {not true}}}"); } @Test - public void testString() { + public void strings() { GetPTF("'TEST'").aSerialized("'TEST'"); //old GetPTF("'TE''ST'").aSerialized("'TE'ST'"); GetPTF("'TE''ST'").aSerialized("'TE''ST'"); @@ -325,7 +309,7 @@ public class TestParser extends TestBase { } @Test - public void testSinglePlainLiterals() { + public void singlePlainLiterals() { // assertEquals("Hier", 44, 33); // --- // Checks from EdmSimpleType test @@ -398,53 +382,28 @@ public class TestParser extends TestBase { GetPTF("'abc'").aUriLiteral("'abc'").aKind(ExpressionKind.LITERAL).aEdmType(stringInst); GetPTF("time'PT120S'").aUriLiteral("time'PT120S'").aKind(ExpressionKind.LITERAL).aEdmType(timeInst); - - // The EdmSimpleTypeSamples contains a well formatted list of all - // possible - // UriLiterals for SimpleTypes, instances for their Type classes and - // their Values in java notation - /* - * for ( EdmSimpleTypeSamples.UriTypeValueSet [] utvSetSet : - * EdmSimpleTypeSamples.someAll ) { for( - * EdmSimpleTypeSamples.UriTypeValueSet utvSet : utvSetSet) { - * GetPTF(utvSet - * .uri).aKind(ExpressionKind.LITERAL).aEdmType(utvSet.type) - * .aUriLiteral(utvSet.uri); } } - */ - - } - - ExpressionParserException GetException() { - ExpressionParserException ex = new ExpressionParserException(ExpressionParserException.COMMON_ERROR); - List<StackTraceElement> stack = new ArrayList<StackTraceElement>(Arrays.asList(ex.getStackTrace())); - stack.remove(0); - ex.setStackTrace(stack.toArray(new StackTraceElement[stack.size()])); - return ex; - } - - void LevelB() throws ExpressionParserException { - ExpressionParserException ex = GetException(); - throw ex; - } - - void LevelA() throws ExpressionParserException { - try { - LevelB(); - } catch (ExpressionParserException e) { - e.printStackTrace(); - throw e; - // throw new - // ExceptionParseExpression(ExceptionParseExpression.COMMON); - } } - // @Test - public void testExceptionStack() { - try { - LevelA(); - } catch (ExpressionParserException e) { - e.printStackTrace(); - } + @Test + public void navigationProperties() { + final EdmEntityType entityType = edmInfo.getTypeEtKeyTypeInteger(); + final EdmEntityType entityType2 = edmInfo.getTypeEtKeyTypeString(); + GetPTF_noTEST(entityType, "navProperty").aExKey(ExpressionParserException.TYPE_EXPECTED_AT); + GetPTF_noTEST(entityType, "navProperty/navProperty").aExKey(ExpressionParserException.INVALID_MULTIPLICITY); + GetPTF_noTEST(entityType, "navProperty/KeyString eq 'a'") + .root().left().left().aEdmType(entityType2) + .root().left().right().aEdmType(EdmString.getInstance()); + GetPTF_noTEST(entityType2, "navProperty/KeyInteger eq 1").aExKey(ExpressionParserException.INVALID_MULTIPLICITY); + GetPTF_noTEST(entityType, "navProperty ne null").root().left().aEdmType(entityType2); + GetPTF_noTEST(entityType, "navProperty ne null and not (navProperty eq null)") + .root().aKind(ExpressionKind.BINARY) + .left().aKind(ExpressionKind.BINARY).left().aEdmType(entityType2) + .root().left().right().aEdmType(EdmNull.getInstance()) + .root().right().aKind(ExpressionKind.UNARY).left().aKind(ExpressionKind.BINARY) + .left().aEdmType(entityType2) + .root().right().left().right().aEdmType(EdmNull.getInstance()); + GetPTF_noTEST(entityType2, "navProperty eq null").aExKey(ExpressionParserException.INVALID_MULTIPLICITY); + GetPTF_noTEST(entityType, "navProperty lt null") + .aExKey(ExpressionParserException.INVALID_TYPES_FOR_BINARY_OPERATOR); } - } http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/919d4ac0/odata2-lib/odata-ref/src/main/java/org/apache/olingo/odata2/ref/processor/ListsProcessor.java ---------------------------------------------------------------------- diff --git a/odata2-lib/odata-ref/src/main/java/org/apache/olingo/odata2/ref/processor/ListsProcessor.java b/odata2-lib/odata-ref/src/main/java/org/apache/olingo/odata2/ref/processor/ListsProcessor.java index fb48d5f..a64ab9a 100644 --- a/odata2-lib/odata-ref/src/main/java/org/apache/olingo/odata2/ref/processor/ListsProcessor.java +++ b/odata2-lib/odata-ref/src/main/java/org/apache/olingo/odata2/ref/processor/ListsProcessor.java @@ -317,17 +317,16 @@ public class ListsProcessor extends ODataSingleProcessor { mapFunctionParameters(uriInfo.getFunctionImportParameters()), uriInfo.getNavigationSegments()); - if (!appliesFilter(data, uriInfo.getFilter())) { + final EdmEntitySet entitySet = uriInfo.getTargetEntitySet(); + if (!appliesFilter(entitySet, data, uriInfo.getFilter())) { throw new ODataNotFoundException(ODataNotFoundException.ENTITY); } final ExpandSelectTreeNode expandSelectTreeNode = UriParser.createExpandSelectTree(uriInfo.getSelect(), uriInfo.getExpand()); - ODataResponse odr = - ODataResponse.fromResponse(writeEntry(uriInfo.getTargetEntitySet(), expandSelectTreeNode, data, contentType)) - .build(); - return odr; + return ODataResponse.fromResponse(writeEntry(entitySet, expandSelectTreeNode, data, contentType)) + .build(); } @Override @@ -340,7 +339,8 @@ public class ListsProcessor extends ODataSingleProcessor { mapFunctionParameters(uriInfo.getFunctionImportParameters()), uriInfo.getNavigationSegments()); - return ODataResponse.fromResponse(EntityProvider.writeText(appliesFilter(data, uriInfo.getFilter()) ? "1" : "0")) + return ODataResponse.fromResponse(EntityProvider.writeText( + appliesFilter(uriInfo.getTargetEntitySet(), data, uriInfo.getFilter()) ? "1" : "0")) .build(); } @@ -411,11 +411,11 @@ public class ListsProcessor extends ODataSingleProcessor { mapFunctionParameters(uriInfo.getFunctionImportParameters()), uriInfo.getNavigationSegments()); - if (!appliesFilter(data, uriInfo.getFilter())) { + final EdmEntitySet entitySet = uriInfo.getTargetEntitySet(); + if (!appliesFilter(entitySet, data, uriInfo.getFilter())) { throw new ODataNotFoundException(ODataNotFoundException.ENTITY); } - final EdmEntitySet entitySet = uriInfo.getTargetEntitySet(); final EdmEntityType entityType = entitySet.getEntityType(); final EntityProviderReadProperties properties = EntityProviderReadProperties.init() .mergeSemantic(merge) @@ -543,7 +543,7 @@ public class ListsProcessor extends ODataSingleProcessor { final Object targetData = dataSource.readRelatedData(entitySet, sourceData, targetEntitySet, keys); - if (!appliesFilter(targetData, uriInfo.getFilter())) { + if (!appliesFilter(targetEntitySet, targetData, uriInfo.getFilter())) { throw new ODataNotFoundException(ODataNotFoundException.ENTITY); } @@ -652,7 +652,7 @@ public class ListsProcessor extends ODataSingleProcessor { mapFunctionParameters(uriInfo.getFunctionImportParameters()), uriInfo.getNavigationSegments()); - if (!appliesFilter(data, uriInfo.getFilter())) { + if (!appliesFilter(uriInfo.getTargetEntitySet(), data, uriInfo.getFilter())) { throw new ODataNotFoundException(ODataNotFoundException.ENTITY); } @@ -704,7 +704,7 @@ public class ListsProcessor extends ODataSingleProcessor { mapFunctionParameters(uriInfo.getFunctionImportParameters()), uriInfo.getNavigationSegments()); - if (!appliesFilter(data, uriInfo.getFilter())) { + if (!appliesFilter(uriInfo.getTargetEntitySet(), data, uriInfo.getFilter())) { throw new ODataNotFoundException(ODataNotFoundException.ENTITY); } @@ -741,11 +741,11 @@ public class ListsProcessor extends ODataSingleProcessor { mapFunctionParameters(uriInfo.getFunctionImportParameters()), uriInfo.getNavigationSegments()); - if (!appliesFilter(data, uriInfo.getFilter())) { + final EdmEntitySet entitySet = uriInfo.getTargetEntitySet(); + if (!appliesFilter(entitySet, data, uriInfo.getFilter())) { throw new ODataNotFoundException(ODataNotFoundException.ENTITY); } - final EdmEntitySet entitySet = uriInfo.getTargetEntitySet(); final BinaryData binaryData = dataSource.readBinaryData(entitySet, data); if (binaryData == null) { throw new ODataNotFoundException(ODataNotFoundException.ENTITY); @@ -786,7 +786,8 @@ public class ListsProcessor extends ODataSingleProcessor { mapFunctionParameters(uriInfo.getFunctionImportParameters()), uriInfo.getNavigationSegments()); - if (!appliesFilter(data, uriInfo.getFilter())) { + final EdmEntitySet entitySet = uriInfo.getTargetEntitySet(); + if (!appliesFilter(entitySet, data, uriInfo.getFilter())) { throw new ODataNotFoundException(ODataNotFoundException.ENTITY); } @@ -797,7 +798,6 @@ public class ListsProcessor extends ODataSingleProcessor { context.stopRuntimeMeasurement(timingHandle); - final EdmEntitySet entitySet = uriInfo.getTargetEntitySet(); dataSource.writeBinaryData(entitySet, data, new BinaryData(value, requestContentType)); return ODataResponse.newBuilder().eTag(constructETag(entitySet, data)).build(); @@ -1184,7 +1184,7 @@ public class ListsProcessor extends ODataSingleProcessor { // Remove all elements the filter does not apply for. // A for-each loop would not work with "remove", see Java documentation. for (Iterator<T> iterator = data.iterator(); iterator.hasNext();) { - if (!appliesFilter(iterator.next(), filter)) { + if (!appliesFilter(entitySet, iterator.next(), filter)) { iterator.remove(); } } @@ -1193,7 +1193,7 @@ public class ListsProcessor extends ODataSingleProcessor { final Integer count = inlineCount == InlineCount.ALLPAGES ? data.size() : null; if (orderBy != null) { - sort(data, orderBy); + sort(entitySet, data, orderBy); } else if (skipToken != null || skip != null || top != null) { sortInDefaultOrder(entitySet, data); } @@ -1225,15 +1225,15 @@ public class ListsProcessor extends ODataSingleProcessor { return count; } - private <T> void sort(final List<T> data, final OrderByExpression orderBy) { + private <T> void sort(final EdmEntitySet entitySet, final List<T> data, final OrderByExpression orderBy) { Collections.sort(data, new Comparator<T>() { @Override public int compare(final T entity1, final T entity2) { try { int result = 0; for (final OrderExpression expression : orderBy.getOrders()) { - String first = evaluateExpression(entity1, expression.getExpression()); - String second = evaluateExpression(entity2, expression.getExpression()); + String first = evaluateExpression(entitySet, entity1, expression.getExpression()); + String second = evaluateExpression(entitySet, entity2, expression.getExpression()); if (first != null && second != null) { result = first.compareTo(second); @@ -1272,12 +1272,14 @@ public class ListsProcessor extends ODataSingleProcessor { }); } - private <T> boolean appliesFilter(final T data, final FilterExpression filter) throws ODataException { + private <T> boolean appliesFilter(final EdmEntitySet entitySet, final T data, final FilterExpression filter) + throws ODataException { ODataContext context = getContext(); final int timingHandle = context.startRuntimeMeasurement(getClass().getSimpleName(), "appliesFilter"); try { - return data != null && (filter == null || evaluateExpression(data, filter.getExpression()).equals("true")); + return data != null + && (filter == null || evaluateExpression(entitySet, data, filter.getExpression()).equals("true")); } catch (final RuntimeException e) { return false; } finally { @@ -1285,11 +1287,12 @@ public class ListsProcessor extends ODataSingleProcessor { } } - private <T> String evaluateExpression(final T data, final CommonExpression expression) throws ODataException { + private <T> String evaluateExpression(final EdmEntitySet entitySet, final T data, final CommonExpression expression) + throws ODataException { switch (expression.getKind()) { case UNARY: final UnaryExpression unaryExpression = (UnaryExpression) expression; - final String operand = evaluateExpression(data, unaryExpression.getOperand()); + final String operand = evaluateExpression(entitySet, data, unaryExpression.getOperand()); switch (unaryExpression.getOperator()) { case NOT: @@ -1302,9 +1305,9 @@ public class ListsProcessor extends ODataSingleProcessor { case BINARY: final BinaryExpression binaryExpression = (BinaryExpression) expression; - final EdmSimpleType type = (EdmSimpleType) binaryExpression.getLeftOperand().getEdmType(); - final String left = evaluateExpression(data, binaryExpression.getLeftOperand()); - final String right = evaluateExpression(data, binaryExpression.getRightOperand()); + final EdmType type = binaryExpression.getLeftOperand().getEdmType(); + final String left = evaluateExpression(entitySet, data, binaryExpression.getLeftOperand()); + final String right = evaluateExpression(entitySet, data, binaryExpression.getRightOperand()); switch (binaryExpression.getOperator()) { case ADD: @@ -1347,9 +1350,9 @@ public class ListsProcessor extends ODataSingleProcessor { case OR: return Boolean.toString(left.equals("true") || right.equals("true")); case EQ: - return Boolean.toString(left.equals(right)); + return Boolean.toString(left == null && right == null || left.equals(right)); case NE: - return Boolean.toString(!left.equals(right)); + return Boolean.toString(!(left == null && right == null || left.equals(right))); case LT: if (type == EdmSimpleTypeKind.String.getEdmSimpleTypeInstance() || type == EdmSimpleTypeKind.DateTime.getEdmSimpleTypeInstance() @@ -1397,10 +1400,19 @@ public class ListsProcessor extends ODataSingleProcessor { } case PROPERTY: - final EdmProperty property = (EdmProperty) ((PropertyExpression) expression).getEdmProperty(); - final EdmSimpleType propertyType = (EdmSimpleType) property.getType(); - return propertyType.valueToString(valueAccess.getPropertyValue(data, property), EdmLiteralKind.DEFAULT, - property.getFacets()); + final EdmTyped property = ((PropertyExpression) expression).getEdmProperty(); + final EdmType propertyType = property.getType(); + if (propertyType.getKind() == EdmTypeKind.ENTITY) { + try { + dataSource.readRelatedData(entitySet, data, + entitySet.getRelatedEntitySet((EdmNavigationProperty) property), null); + } catch (final ODataNotFoundException e) { + return null; + } + return property.getName(); + } + return ((EdmSimpleType) propertyType).valueToString(valueAccess.getPropertyValue(data, (EdmProperty) property), + EdmLiteralKind.DEFAULT, ((EdmProperty) property).getFacets()); case MEMBER: final MemberExpression memberExpression = (MemberExpression) expression; @@ -1436,11 +1448,11 @@ public class ListsProcessor extends ODataSingleProcessor { case METHOD: final MethodExpression methodExpression = (MethodExpression) expression; - final String first = evaluateExpression(data, methodExpression.getParameters().get(0)); + final String first = evaluateExpression(entitySet, data, methodExpression.getParameters().get(0)); final String second = methodExpression.getParameterCount() > 1 ? - evaluateExpression(data, methodExpression.getParameters().get(1)) : ""; + evaluateExpression(entitySet, data, methodExpression.getParameters().get(1)) : ""; final String third = methodExpression.getParameterCount() > 2 ? - evaluateExpression(data, methodExpression.getParameters().get(2)) : ""; + evaluateExpression(entitySet, data, methodExpression.getParameters().get(2)) : ""; switch (methodExpression.getMethod()) { case ENDSWITH: http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/919d4ac0/odata2-lib/odata-testutil/src/main/java/org/apache/olingo/odata2/testutil/mock/TecEdmInfo.java ---------------------------------------------------------------------- diff --git a/odata2-lib/odata-testutil/src/main/java/org/apache/olingo/odata2/testutil/mock/TecEdmInfo.java b/odata2-lib/odata-testutil/src/main/java/org/apache/olingo/odata2/testutil/mock/TecEdmInfo.java index 4592ee3..e3da2dd 100644 --- a/odata2-lib/odata-testutil/src/main/java/org/apache/olingo/odata2/testutil/mock/TecEdmInfo.java +++ b/odata2-lib/odata-testutil/src/main/java/org/apache/olingo/odata2/testutil/mock/TecEdmInfo.java @@ -23,6 +23,7 @@ import static org.junit.Assert.fail; import org.apache.olingo.odata2.api.edm.Edm; import org.apache.olingo.odata2.api.edm.EdmEntityType; import org.apache.olingo.odata2.api.edm.EdmException; +import org.apache.olingo.odata2.api.edm.FullQualifiedName; /** * Helper for the entity data model used as technical reference scenario. @@ -36,14 +37,23 @@ public class TecEdmInfo { } public EdmEntityType getTypeEtAllTypes() { + return getEntityType(TechnicalScenarioEdmProvider.ET_ALL_TYPES); + } + + public EdmEntityType getTypeEtKeyTypeInteger() { + return getEntityType(TechnicalScenarioEdmProvider.ET_KEY_IS_INTEGER); + } + + public EdmEntityType getTypeEtKeyTypeString() { + return getEntityType(TechnicalScenarioEdmProvider.ET_KEY_IS_STRING); + } + + private EdmEntityType getEntityType(final FullQualifiedName name) { try { - return edm - .getEntityContainer(TechnicalScenarioEdmProvider.ENTITY_CONTAINER_1) - .getEntitySet(TechnicalScenarioEdmProvider.ES_ALL_TYPES) - .getEntityType(); + return edm.getEntityType(name.getNamespace(), name.getName()); } catch (final EdmException e) { - fail("Error in test setup" + e.getLocalizedMessage()); + fail("Error in test setup: " + e.getLocalizedMessage()); + return null; } - return null; } } http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/919d4ac0/odata2-lib/odata-testutil/src/main/java/org/apache/olingo/odata2/testutil/mock/TechnicalScenarioEdmProvider.java ---------------------------------------------------------------------- diff --git a/odata2-lib/odata-testutil/src/main/java/org/apache/olingo/odata2/testutil/mock/TechnicalScenarioEdmProvider.java b/odata2-lib/odata-testutil/src/main/java/org/apache/olingo/odata2/testutil/mock/TechnicalScenarioEdmProvider.java index 0b8b4d7..755f48f 100644 --- a/odata2-lib/odata-testutil/src/main/java/org/apache/olingo/odata2/testutil/mock/TechnicalScenarioEdmProvider.java +++ b/odata2-lib/odata-testutil/src/main/java/org/apache/olingo/odata2/testutil/mock/TechnicalScenarioEdmProvider.java @@ -223,17 +223,18 @@ public class TechnicalScenarioEdmProvider extends EdmProvider { } @Override - public Association getAssociation(final FullQualifiedName edmFQName) throws ODataMessageException { - if (NAMESPACE_1.equals(edmFQName.getNamespace())) { - if (ASSOCIATION_ET1_ET2.getName().equals(edmFQName.getName())) { - final AssociationEnd end1 = - new AssociationEnd().setMultiplicity(EdmMultiplicity.ONE).setRole(ROLE_1).setType(ET_KEY_IS_STRING); - final AssociationEnd end2 = - new AssociationEnd().setMultiplicity(EdmMultiplicity.ONE).setRole(ROLE_2).setType(ET_KEY_IS_INTEGER); - return new Association().setName("Association").setEnd1(end1).setEnd2(end2); - } + public Association getAssociation(final FullQualifiedName association) throws ODataMessageException { + if (ASSOCIATION_ET1_ET2.equals(association)) { + return new Association().setName(ASSOCIATION_ET1_ET2.getName()) + .setEnd1(new AssociationEnd() + .setMultiplicity(EdmMultiplicity.ZERO_TO_ONE) + .setRole(ROLE_1) + .setType(ET_KEY_IS_STRING)) + .setEnd2(new AssociationEnd() + .setMultiplicity(EdmMultiplicity.MANY) + .setRole(ROLE_2) + .setType(ET_KEY_IS_INTEGER)); } - return null; }