http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java index 2a994d3..118c649 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java @@ -46,29 +46,22 @@ import org.apache.olingo.server.api.uri.UriResourceRef; import org.apache.olingo.server.api.uri.UriResourceValue; import org.apache.olingo.server.api.uri.queryoption.AliasQueryOption; import org.apache.olingo.server.api.uri.queryoption.CustomQueryOption; -import org.apache.olingo.server.api.uri.queryoption.FilterOption; import org.apache.olingo.server.api.uri.queryoption.QueryOption; import org.apache.olingo.server.api.uri.queryoption.SystemQueryOption; import org.apache.olingo.server.api.uri.queryoption.SystemQueryOptionKind; import org.apache.olingo.server.api.uri.queryoption.expression.Expression; import org.apache.olingo.server.core.uri.UriInfoImpl; import org.apache.olingo.server.core.uri.UriResourceStartingTypeFilterImpl; -import org.apache.olingo.server.core.uri.UriResourceTypedImpl; -import org.apache.olingo.server.core.uri.UriResourceWithKeysImpl; import org.apache.olingo.server.core.uri.antlr.UriLexer; import org.apache.olingo.server.core.uri.antlr.UriParserParser; import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandItemsEOFContext; -import org.apache.olingo.server.core.uri.antlr.UriParserParser.FilterExpressionEOFContext; -import org.apache.olingo.server.core.uri.antlr.UriParserParser.OrderByEOFContext; import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind; import org.apache.olingo.server.core.uri.parser.search.SearchParser; import org.apache.olingo.server.core.uri.queryoption.AliasQueryOptionImpl; import org.apache.olingo.server.core.uri.queryoption.CountOptionImpl; import org.apache.olingo.server.core.uri.queryoption.ExpandOptionImpl; -import org.apache.olingo.server.core.uri.queryoption.FilterOptionImpl; import org.apache.olingo.server.core.uri.queryoption.FormatOptionImpl; import org.apache.olingo.server.core.uri.queryoption.IdOptionImpl; -import org.apache.olingo.server.core.uri.queryoption.OrderByOptionImpl; import org.apache.olingo.server.core.uri.queryoption.SkipOptionImpl; import org.apache.olingo.server.core.uri.queryoption.SkipTokenOptionImpl; import org.apache.olingo.server.core.uri.queryoption.TopOptionImpl; @@ -84,9 +77,7 @@ public class Parser { private final Edm edm; private final OData odata; - private enum ParserEntryRules { - ExpandItems, FilterExpression, Orderby - } + private enum ParserEntryRules { ExpandItems } public Parser(final Edm edm, final OData odata) { this.edm = edm; @@ -131,7 +122,7 @@ public class Parser { if (numberOfSegments > 1) { final String typeCastSegment = pathSegmentsDecoded.get(1); ensureLastSegment(typeCastSegment, 2, numberOfSegments); - context.contextUriInfo = new ResourcePathParser(edm, odata).parseDollarEntityTypeCast(typeCastSegment); + context.contextUriInfo = new ResourcePathParser(edm).parseDollarEntityTypeCast(typeCastSegment); context.contextTypes.push(context.contextUriInfo.getEntityTypeCast()); } else { context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.entityId); @@ -141,7 +132,7 @@ public class Parser { } else if (firstSegment.startsWith("$crossjoin")) { ensureLastSegment(firstSegment, 1, numberOfSegments); - context.contextUriInfo = new ResourcePathParser(edm, odata).parseCrossjoinSegment(firstSegment); + context.contextUriInfo = new ResourcePathParser(edm).parseCrossjoinSegment(firstSegment); final EdmEntityContainer container = edm.getEntityContainer(); for (final String name : context.contextUriInfo.getEntitySetNames()) { context.contextTypes.push(container.getEntitySet(name).getEntityType()); @@ -150,7 +141,7 @@ public class Parser { } else { context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.resource); - final ResourcePathParser resourcePathParser = new ResourcePathParser(edm, odata); + final ResourcePathParser resourcePathParser = new ResourcePathParser(edm); int count = 0; UriResource lastSegment = null; for (final String pathSegment : pathSegmentsDecoded) { @@ -183,7 +174,7 @@ public class Parser { if (lastSegment instanceof UriResourcePartTyped) { final UriResourcePartTyped typed = (UriResourcePartTyped) lastSegment; - final EdmType type = getTypeInformation(typed); + final EdmType type = ParserHelper.getTypeInformation(typed); if (type != null) { // could be null for, e.g., actions without return type context.contextTypes.push(type); } @@ -199,23 +190,13 @@ public class Parser { if (optionName.startsWith("$")) { SystemQueryOption systemOption = null; if (optionName.equals(SystemQueryOptionKind.FILTER.toString())) { - try { - FilterExpressionEOFContext ctxFilterExpression = - (FilterExpressionEOFContext) parseRule(optionValue, ParserEntryRules.FilterExpression); - systemOption = (FilterOptionImpl) uriParseTreeVisitor.visitFilterExpressionEOF(ctxFilterExpression); - } catch (final ParseCancellationException e) { - throw e.getCause() instanceof UriParserException ? - (UriParserException) e.getCause() : - new UriParserSyntaxException("Syntax error", e, UriParserSyntaxException.MessageKeys.SYNTAX); - } -// UriTokenizer filterTokenizer = new UriTokenizer(optionValue); -// systemOption = new FilterOptionImpl().setExpression( -// new ExpressionParser().parse(filterTokenizer)); -// if (!filterTokenizer.next(TokenKind.EOF)) { -// throw new UriParserSyntaxException("Illegal value of $filter option!", -// UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION, -// optionName, optionValue); -// } + UriTokenizer filterTokenizer = new UriTokenizer(optionValue); + systemOption = new FilterParser(edm, odata).parse(filterTokenizer, + context.contextTypes.peek() instanceof EdmStructuredType ? + (EdmStructuredType) context.contextTypes.peek() : + null, + context.contextUriInfo.getEntitySetNames()); + checkOptionEOF(filterTokenizer, optionName, optionValue); } else if (optionName.equals(SystemQueryOptionKind.FORMAT.toString())) { FormatOptionImpl formatOption = new FormatOptionImpl(); @@ -253,15 +234,13 @@ public class Parser { UriParserSyntaxException.MessageKeys.SYSTEM_QUERY_OPTION_LEVELS_NOT_ALLOWED_HERE); } else if (optionName.equals(SystemQueryOptionKind.ORDERBY.toString())) { - try { - OrderByEOFContext ctxOrderByExpression = - (OrderByEOFContext) parseRule(optionValue, ParserEntryRules.Orderby); - systemOption = (OrderByOptionImpl) uriParseTreeVisitor.visitOrderByEOF(ctxOrderByExpression); - } catch (final ParseCancellationException e) { - throw e.getCause() instanceof UriParserException ? - (UriParserException) e.getCause() : - new UriParserSyntaxException("Syntax error", e, UriParserSyntaxException.MessageKeys.SYNTAX); - } + UriTokenizer orderByTokenizer = new UriTokenizer(optionValue); + systemOption = new OrderByParser(edm, odata).parse(orderByTokenizer, + context.contextTypes.peek() instanceof EdmStructuredType ? + (EdmStructuredType) context.contextTypes.peek() : + null, + context.contextUriInfo.getEntitySetNames()); + checkOptionEOF(orderByTokenizer, optionName, optionValue); } else if (optionName.equals(SystemQueryOptionKind.SEARCH.toString())) { systemOption = new SearchParser().parse(optionValue); @@ -273,11 +252,7 @@ public class Parser { (EdmStructuredType) context.contextTypes.peek() : null, context.isCollection); - if (!selectTokenizer.next(TokenKind.EOF)) { - throw new UriParserSyntaxException("Illegal value of $select option!", - UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION, - optionName, optionValue); - } + checkOptionEOF(selectTokenizer, optionName, optionValue); } else if (optionName.equals(SystemQueryOptionKind.SKIP.toString())) { SkipOptionImpl skipOption = new SkipOptionImpl(); @@ -343,15 +318,12 @@ public class Parser { UriParserSyntaxException.MessageKeys.SYNTAX); } } else { - try { - final FilterExpressionEOFContext filterExpCtx = - (FilterExpressionEOFContext) parseRule(optionValue, ParserEntryRules.FilterExpression); - expression = ((FilterOption) uriParseTreeVisitor.visitFilterExpressionEOF(filterExpCtx)) - .getExpression(); - } catch (final ParseCancellationException e) { - throw e.getCause() instanceof UriParserException ? - (UriParserException) e.getCause() : - new UriParserSyntaxException("Syntax error", e, UriParserSyntaxException.MessageKeys.SYNTAX); + UriTokenizer aliasValueTokenizer = new UriTokenizer(optionValue); + expression = new ExpressionParser(edm, odata).parse(aliasValueTokenizer, null, + context.contextUriInfo.getEntitySetNames()); + if (!aliasValueTokenizer.next(TokenKind.EOF)) { + throw new UriParserSyntaxException("Illegal value for alias '" + optionName + "'.", + UriParserSyntaxException.MessageKeys.SYNTAX); } } context.contextUriInfo.addAlias((AliasQueryOption) new AliasQueryOptionImpl() @@ -384,28 +356,13 @@ public class Parser { return index > 0 && index < value.length() - 1 && index == value.lastIndexOf('/'); } - protected static EdmType getTypeInformation(final UriResourcePartTyped resourcePart) { - EdmType type = null; - if (resourcePart instanceof UriResourceWithKeysImpl) { - final UriResourceWithKeysImpl lastPartWithKeys = (UriResourceWithKeysImpl) resourcePart; - if (lastPartWithKeys.getTypeFilterOnEntry() != null) { - type = lastPartWithKeys.getTypeFilterOnEntry(); - } else if (lastPartWithKeys.getTypeFilterOnCollection() != null) { - type = lastPartWithKeys.getTypeFilterOnCollection(); - } else { - type = lastPartWithKeys.getType(); - } - - } else if (resourcePart instanceof UriResourceTypedImpl) { - final UriResourceTypedImpl lastPartTyped = (UriResourceTypedImpl) resourcePart; - type = lastPartTyped.getTypeFilter() == null ? - lastPartTyped.getType() : - lastPartTyped.getTypeFilter(); - } else { - type = resourcePart.getType(); + private void checkOptionEOF(UriTokenizer tokenizer, final String optionName, final String optionValue) + throws UriParserException { + if (!tokenizer.next(TokenKind.EOF)) { + throw new UriParserSyntaxException("Illegal value of '" + optionName + "' option!", + UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION, + optionName, optionValue); } - - return type; } private ParserRuleContext parseRule(final String input, final ParserEntryRules entryPoint) @@ -435,14 +392,6 @@ public class Parser { // parse switch (entryPoint) { - case FilterExpression: - lexer.mode(Lexer.DEFAULT_MODE); - ret = parser.filterExpressionEOF(); - break; - case Orderby: - lexer.mode(Lexer.DEFAULT_MODE); - ret = parser.orderByEOF(); - break; case ExpandItems: lexer.mode(Lexer.DEFAULT_MODE); ret = parser.expandItemsEOF(); @@ -471,14 +420,6 @@ public class Parser { // parse switch (entryPoint) { - case FilterExpression: - lexer.mode(Lexer.DEFAULT_MODE); - ret = parser.filterExpressionEOF(); - break; - case Orderby: - lexer.mode(Lexer.DEFAULT_MODE); - ret = parser.orderByEOF(); - break; case ExpandItems: lexer.mode(Lexer.DEFAULT_MODE); ret = parser.expandItemsEOF();
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java index e811575..65ee461 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java @@ -18,10 +18,35 @@ */ package org.apache.olingo.server.core.uri.parser; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.olingo.commons.api.edm.EdmEntityType; +import org.apache.olingo.commons.api.edm.EdmKeyPropertyRef; +import org.apache.olingo.commons.api.edm.EdmNavigationProperty; +import org.apache.olingo.commons.api.edm.EdmPrimitiveType; +import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException; +import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind; +import org.apache.olingo.commons.api.edm.EdmProperty; +import org.apache.olingo.commons.api.edm.EdmType; +import org.apache.olingo.commons.api.edm.EdmTypeDefinition; +import org.apache.olingo.commons.api.edm.constants.EdmTypeKind; +import org.apache.olingo.server.api.OData; +import org.apache.olingo.server.api.uri.UriParameter; +import org.apache.olingo.server.api.uri.UriResourcePartTyped; +import org.apache.olingo.server.core.ODataImpl; +import org.apache.olingo.server.core.uri.UriParameterImpl; +import org.apache.olingo.server.core.uri.UriResourceTypedImpl; +import org.apache.olingo.server.core.uri.UriResourceWithKeysImpl; import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind; +import org.apache.olingo.server.core.uri.validator.UriValidationException; public class ParserHelper { + private static final OData odata = new ODataImpl(); + public static void requireNext(UriTokenizer tokenizer, final TokenKind required) throws UriParserException { if (!tokenizer.next(required)) { throw new UriParserSyntaxException("Expected token '" + required.toString() + "' not found.", @@ -33,16 +58,16 @@ public class ParserHelper { requireNext(tokenizer, TokenKind.EOF); } - public static TokenKind next(UriTokenizer tokenizer, final TokenKind... kind) { - for (int i = 0; i < kind.length; i++) { - if (tokenizer.next(kind[i])) { - return kind[i]; + public static TokenKind next(UriTokenizer tokenizer, final TokenKind... kinds) { + for (final TokenKind kind : kinds) { + if (tokenizer.next(kind)) { + return kind; } } return null; } - public static TokenKind nextPrimitive(UriTokenizer tokenizer) { + public static TokenKind nextPrimitiveValue(UriTokenizer tokenizer) { return next(tokenizer, TokenKind.NULL, TokenKind.BooleanValue, @@ -62,4 +87,304 @@ public class ParserHelper { TokenKind.BinaryValue, TokenKind.EnumValue); } + + protected static List<UriParameter> parseFunctionParameters(UriTokenizer tokenizer, final boolean withComplex) + throws UriParserException { + List<UriParameter> parameters = new ArrayList<UriParameter>(); + ParserHelper.requireNext(tokenizer, TokenKind.OPEN); + if (tokenizer.next(TokenKind.CLOSE)) { + return parameters; + } + do { + ParserHelper.requireNext(tokenizer, TokenKind.ODataIdentifier); + final String name = tokenizer.getText(); + if (parameters.contains(name)) { + throw new UriParserSemanticException("Duplicated function parameter " + name, + UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, name); + } + ParserHelper.requireNext(tokenizer, TokenKind.EQ); + if (tokenizer.next(TokenKind.COMMA) || tokenizer.next(TokenKind.CLOSE) || tokenizer.next(TokenKind.EOF)) { + throw new UriParserSyntaxException("Parameter value expected.", UriParserSyntaxException.MessageKeys.SYNTAX); + } + if (tokenizer.next(TokenKind.ParameterAliasName)) { + parameters.add(new UriParameterImpl().setName(name).setAlias(tokenizer.getText())); + } else if (tokenizer.next(TokenKind.jsonArrayOrObject)) { + if (withComplex) { + parameters.add(new UriParameterImpl().setName(name).setText(tokenizer.getText())); + } else { + throw new UriParserSemanticException("A JSON array or object is not allowed as parameter value.", + UriParserSemanticException.MessageKeys.COMPLEX_PARAMETER_IN_RESOURCE_PATH, tokenizer.getText()); + } + } else if (nextPrimitiveValue(tokenizer) == null) { + throw new UriParserSemanticException("Wrong parameter value.", + UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, ""); + } else { + final String literalValue = tokenizer.getText(); + parameters.add(new UriParameterImpl().setName(name) + .setText("null".equals(literalValue) ? null : literalValue)); + } + } while (tokenizer.next(TokenKind.COMMA)); + ParserHelper.requireNext(tokenizer, TokenKind.CLOSE); + return parameters; + } + + protected static List<UriParameter> parseNavigationKeyPredicate(UriTokenizer tokenizer, + final EdmNavigationProperty navigationProperty) throws UriParserException, UriValidationException { + if (tokenizer.next(TokenKind.OPEN)) { + if (navigationProperty.isCollection()) { + return parseKeyPredicate(tokenizer, navigationProperty.getType(), navigationProperty.getPartner()); + } else { + throw new UriParserSemanticException("A key is not allowed on non-collection navigation properties.", + UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED); + } + } + return null; + } + + protected static List<UriParameter> parseKeyPredicate(UriTokenizer tokenizer, final EdmEntityType edmEntityType, + final EdmNavigationProperty partner) throws UriParserException, UriValidationException { + final List<EdmKeyPropertyRef> keyPropertyRefs = edmEntityType.getKeyPropertyRefs(); + if (tokenizer.next(TokenKind.CLOSE)) { + throw new UriParserSemanticException( + "Expected " + keyPropertyRefs.size() + " key predicates but none.", + UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES, + Integer.toString(keyPropertyRefs.size()), "0"); + } + List<UriParameter> keys = new ArrayList<UriParameter>(); + Map<String, String> referencedNames = new HashMap<String, String>(); + + if (partner != null) { + // Prepare list of potentially missing keys to be filled from referential constraints. + for (final String name : edmEntityType.getKeyPredicateNames()) { + final String referencedName = partner.getReferencingPropertyName(name); + if (referencedName != null) { + referencedNames.put(name, referencedName); + } + } + } + + if (tokenizer.next(TokenKind.ODataIdentifier)) { + keys.addAll(compoundKey(tokenizer, edmEntityType)); + } else if (keyPropertyRefs.size() - referencedNames.size() == 1) { + for (final EdmKeyPropertyRef candidate : keyPropertyRefs) { + if (referencedNames.get(candidate.getName()) == null) { + keys.add(simpleKey(tokenizer, candidate)); + break; + } + } + } else { + throw new UriParserSemanticException( + "Expected " + (keyPropertyRefs.size() -referencedNames.size()) + " key predicates but found one.", + UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES, + Integer.toString(keyPropertyRefs.size() - referencedNames.size()), "1"); + } + + if (keys.size() < keyPropertyRefs.size() && partner != null) { + // Fill missing keys from referential constraints. + for (final String name : edmEntityType.getKeyPredicateNames()) { + boolean found = false; + for (final UriParameter key : keys) { + if (name.equals(key.getName())) { + found = true; + break; + } + } + if (!found && referencedNames.get(name) != null) { + keys.add(0, new UriParameterImpl().setName(name).setReferencedProperty(referencedNames.get(name))); + } + } + } + + // Check that all key predicates are filled from the URI. + if (keys.size() < keyPropertyRefs.size()) { + throw new UriParserSemanticException( + "Expected " + keyPropertyRefs.size() + " key predicates but found " + keys.size() + ".", + UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES, + Integer.toString(keyPropertyRefs.size()), Integer.toString(keys.size())); + } else { + return keys; + } + } + + private static UriParameter simpleKey(UriTokenizer tokenizer, final EdmKeyPropertyRef edmKeyPropertyRef) + throws UriParserException, UriValidationException { + final EdmProperty edmProperty = edmKeyPropertyRef == null ? null : edmKeyPropertyRef.getProperty(); + if (nextPrimitiveTypeValue(tokenizer, + edmProperty == null ? null : (EdmPrimitiveType) edmProperty.getType(), + edmProperty == null ? false : edmProperty.isNullable())) { + final String literalValue = tokenizer.getText(); + ParserHelper.requireNext(tokenizer, TokenKind.CLOSE); + return createUriParameter(edmProperty, edmKeyPropertyRef.getName(), literalValue); + } else { + throw new UriParserSemanticException("The key value is not valid.", + UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, edmKeyPropertyRef.getName()); + } + } + + private static List<UriParameter> compoundKey(UriTokenizer tokenizer, final EdmEntityType edmEntityType) + throws UriParserException, UriValidationException { + + List<UriParameter> parameters = new ArrayList<UriParameter>(); + List<String> parameterNames = new ArrayList<String>(); + + // To validate that each key predicate is exactly specified once, we use a list to pick from. + List<String> remainingKeyNames = new ArrayList<String>(edmEntityType.getKeyPredicateNames()); + + // At least one key predicate is mandatory. Try to fetch all. + boolean hasComma = false; + do { + final String keyPredicateName = tokenizer.getText(); + if (parameterNames.contains(keyPredicateName)) { + throw new UriValidationException("Duplicated key property " + keyPredicateName, + UriValidationException.MessageKeys.DOUBLE_KEY_PROPERTY, keyPredicateName); + } + if (remainingKeyNames.isEmpty()) { + throw new UriParserSemanticException("Too many key properties.", + UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES, + Integer.toString(parameters.size()), Integer.toString(parameters.size() + 1)); + } + if (!remainingKeyNames.remove(keyPredicateName)) { + throw new UriValidationException("Unknown key property " + keyPredicateName, + UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, keyPredicateName); + } + parameters.add(keyValuePair(tokenizer, keyPredicateName, edmEntityType)); + parameterNames.add(keyPredicateName); + hasComma = tokenizer.next(TokenKind.COMMA); + if (hasComma) { + ParserHelper.requireNext(tokenizer, TokenKind.ODataIdentifier); + } + } while (hasComma); + ParserHelper.requireNext(tokenizer, TokenKind.CLOSE); + + return parameters; + } + + protected static UriParameter keyValuePair(UriTokenizer tokenizer, + final String keyPredicateName, final EdmEntityType edmEntityType) + throws UriParserException, UriValidationException { + final EdmKeyPropertyRef keyPropertyRef = edmEntityType.getKeyPropertyRef(keyPredicateName); + final EdmProperty edmProperty = keyPropertyRef == null ? null : keyPropertyRef.getProperty(); + if (edmProperty == null) { + throw new UriValidationException(keyPredicateName + " is not a valid key property name.", + UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, keyPredicateName); + } + ParserHelper.requireNext(tokenizer, TokenKind.EQ); + if (tokenizer.next(TokenKind.COMMA) || tokenizer.next(TokenKind.CLOSE) || tokenizer.next(TokenKind.EOF)) { + throw new UriParserSyntaxException("Key value expected.", UriParserSyntaxException.MessageKeys.SYNTAX); + } + if (nextPrimitiveTypeValue(tokenizer, (EdmPrimitiveType) edmProperty.getType(), edmProperty.isNullable())) { + return createUriParameter(edmProperty, keyPredicateName, tokenizer.getText()); + } else { + throw new UriParserSemanticException(keyPredicateName + " has not a valid key value.", + UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, keyPredicateName); + } + } + + private static UriParameter createUriParameter(final EdmProperty edmProperty, final String parameterName, + final String literalValue) throws UriParserException, UriValidationException { + if (literalValue.startsWith("@")) { + return new UriParameterImpl() + .setName(parameterName) + .setAlias(literalValue); + } + + final EdmPrimitiveType primitiveType = (EdmPrimitiveType) edmProperty.getType(); + try { + if (!(primitiveType.validate(primitiveType.fromUriLiteral(literalValue), edmProperty.isNullable(), + edmProperty.getMaxLength(), edmProperty.getPrecision(), edmProperty.getScale(), edmProperty.isUnicode()))) { + throw new UriValidationException("Invalid key property", + UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, parameterName); + } + } catch (final EdmPrimitiveTypeException e) { + throw new UriValidationException("Invalid key property", + UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, parameterName); + } + + return new UriParameterImpl() + .setName(parameterName) + .setText("null".equals(literalValue) ? null : literalValue); + } + + private static boolean nextPrimitiveTypeValue(UriTokenizer tokenizer, + final EdmPrimitiveType primitiveType, final boolean nullable) { + final EdmPrimitiveType type = primitiveType instanceof EdmTypeDefinition ? + ((EdmTypeDefinition) primitiveType).getUnderlyingType() : + primitiveType; + if (tokenizer.next(TokenKind.ParameterAliasName)) { + return true; + } else if (nullable && tokenizer.next(TokenKind.NULL)) { + return true; + + } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Boolean).equals(type)) { + return tokenizer.next(TokenKind.BooleanValue); + } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.String).equals(type)) { + return tokenizer.next(TokenKind.StringValue); + } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.SByte).equals(type) + || odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Byte).equals(type) + || odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int16).equals(type) + || odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int32).equals(type) + || odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int64).equals(type)) { + return tokenizer.next(TokenKind.IntegerValue); + } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Guid).equals(type)) { + return tokenizer.next(TokenKind.GuidValue); + } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Date).equals(type)) { + return tokenizer.next(TokenKind.DateValue); + } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.DateTimeOffset).equals(type)) { + return tokenizer.next(TokenKind.DateTimeOffsetValue); + } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.TimeOfDay).equals(type)) { + return tokenizer.next(TokenKind.TimeOfDayValue); + } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Decimal).equals(type)) { + // The order is important. + // A decimal value should not be parsed as integer and let the tokenizer stop at the decimal point. + return tokenizer.next(TokenKind.DecimalValue) + || tokenizer.next(TokenKind.IntegerValue); + } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Double).equals(type)) { + // The order is important. + // A floating-point value should not be parsed as decimal and let the tokenizer stop at 'E'. + // A decimal value should not be parsed as integer and let the tokenizer stop at the decimal point. + return tokenizer.next(TokenKind.DoubleValue) + || tokenizer.next(TokenKind.DecimalValue) + || tokenizer.next(TokenKind.IntegerValue); + } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Duration).equals(type)) { + return tokenizer.next(TokenKind.DurationValue); + } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Binary).equals(type)) { + return tokenizer.next(TokenKind.BinaryValue); + } else if (type.getKind() == EdmTypeKind.ENUM) { + return tokenizer.next(TokenKind.EnumValue); + } else { + return false; + } + } + + protected static List<String> getParameterNames(final List<UriParameter> parameters) { + List<String> names = new ArrayList<String>(); + for (final UriParameter parameter : parameters) { + names.add(parameter.getName()); + } + return names; + } + + protected static EdmType getTypeInformation(final UriResourcePartTyped resourcePart) { + EdmType type = null; + if (resourcePart instanceof UriResourceWithKeysImpl) { + final UriResourceWithKeysImpl lastPartWithKeys = (UriResourceWithKeysImpl) resourcePart; + if (lastPartWithKeys.getTypeFilterOnEntry() != null) { + type = lastPartWithKeys.getTypeFilterOnEntry(); + } else if (lastPartWithKeys.getTypeFilterOnCollection() != null) { + type = lastPartWithKeys.getTypeFilterOnCollection(); + } else { + type = lastPartWithKeys.getType(); + } + + } else if (resourcePart instanceof UriResourceTypedImpl) { + final UriResourceTypedImpl lastPartTyped = (UriResourceTypedImpl) resourcePart; + type = lastPartTyped.getTypeFilter() == null ? + lastPartTyped.getType() : + lastPartTyped.getTypeFilter(); + } else { + type = resourcePart.getType(); + } + + return type; + } } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ResourcePathParser.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ResourcePathParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ResourcePathParser.java index 5d2fbde..1cd4d7a 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ResourcePathParser.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ResourcePathParser.java @@ -18,10 +18,7 @@ */ package org.apache.olingo.server.core.uri.parser; -import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.apache.olingo.commons.api.edm.Edm; import org.apache.olingo.commons.api.edm.EdmAction; @@ -31,25 +28,18 @@ import org.apache.olingo.commons.api.edm.EdmEntitySet; import org.apache.olingo.commons.api.edm.EdmEntityType; import org.apache.olingo.commons.api.edm.EdmFunction; import org.apache.olingo.commons.api.edm.EdmFunctionImport; -import org.apache.olingo.commons.api.edm.EdmKeyPropertyRef; import org.apache.olingo.commons.api.edm.EdmNavigationProperty; -import org.apache.olingo.commons.api.edm.EdmPrimitiveType; -import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException; -import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind; import org.apache.olingo.commons.api.edm.EdmProperty; import org.apache.olingo.commons.api.edm.EdmSingleton; import org.apache.olingo.commons.api.edm.EdmStructuredType; import org.apache.olingo.commons.api.edm.EdmType; -import org.apache.olingo.commons.api.edm.EdmTypeDefinition; import org.apache.olingo.commons.api.edm.FullQualifiedName; import org.apache.olingo.commons.api.edm.constants.EdmTypeKind; -import org.apache.olingo.server.api.OData; import org.apache.olingo.server.api.uri.UriInfoKind; import org.apache.olingo.server.api.uri.UriParameter; import org.apache.olingo.server.api.uri.UriResource; import org.apache.olingo.server.api.uri.UriResourcePartTyped; import org.apache.olingo.server.core.uri.UriInfoImpl; -import org.apache.olingo.server.core.uri.UriParameterImpl; import org.apache.olingo.server.core.uri.UriResourceActionImpl; import org.apache.olingo.server.core.uri.UriResourceComplexPropertyImpl; import org.apache.olingo.server.core.uri.UriResourceCountImpl; @@ -69,13 +59,11 @@ public class ResourcePathParser { private final Edm edm; private final EdmEntityContainer edmEntityContainer; - private final OData odata; private UriTokenizer tokenizer; - public ResourcePathParser(final Edm edm, final OData odata) { + public ResourcePathParser(final Edm edm) { this.edm = edm; edmEntityContainer = edm.getEntityContainer(); - this.odata = odata; } public UriResource parsePathSegment(final String pathSegment, UriResource previous) @@ -188,10 +176,11 @@ public class ResourcePathParser { final EdmEntitySet edmEntitySet = edmEntityContainer.getEntitySet(oDataIdentifier); if (edmEntitySet != null) { - final UriResourceEntitySetImpl entitySetResource = new UriResourceEntitySetImpl().setEntitSet(edmEntitySet); + final UriResourceEntitySetImpl entitySetResource = new UriResourceEntitySetImpl(edmEntitySet); if (tokenizer.next(TokenKind.OPEN)) { - final List<UriParameter> keyPredicates = keyPredicate(entitySetResource.getEntityType(), null); + final List<UriParameter> keyPredicates = + ParserHelper.parseKeyPredicate(tokenizer, entitySetResource.getEntityType(), null); entitySetResource.setKeyPredicates(keyPredicates); } @@ -202,13 +191,13 @@ public class ResourcePathParser { final EdmSingleton edmSingleton = edmEntityContainer.getSingleton(oDataIdentifier); if (edmSingleton != null) { ParserHelper.requireTokenEnd(tokenizer); - return new UriResourceSingletonImpl().setSingleton(edmSingleton); + return new UriResourceSingletonImpl(edmSingleton); } final EdmActionImport edmActionImport = edmEntityContainer.getActionImport(oDataIdentifier); if (edmActionImport != null) { ParserHelper.requireTokenEnd(tokenizer); - return new UriResourceActionImpl().setActionImport(edmActionImport); + return new UriResourceActionImpl(edmActionImport); } final EdmFunctionImport edmFunctionImport = edmEntityContainer.getFunctionImport(oDataIdentifier); @@ -252,8 +241,8 @@ public class ResourcePathParser { return property.isPrimitive() || property.getType().getKind() == EdmTypeKind.ENUM || property.getType().getKind() == EdmTypeKind.DEFINITION ? - new UriResourcePrimitivePropertyImpl().setProperty(property) : - new UriResourceComplexPropertyImpl().setProperty(property); + new UriResourcePrimitivePropertyImpl(property) : + new UriResourceComplexPropertyImpl(property); } final EdmNavigationProperty navigationProperty = structType.getNavigationProperty(name); if (navigationProperty == null) { @@ -262,18 +251,9 @@ public class ResourcePathParser { UriParserSemanticException.MessageKeys.PROPERTY_NOT_IN_TYPE, structType.getFullQualifiedName().getFullQualifiedNameAsString(), name); } - List<UriParameter> keyPredicate = null; - if (tokenizer.next(TokenKind.OPEN)) { - if (navigationProperty.isCollection()) { - keyPredicate = keyPredicate(navigationProperty.getType(), navigationProperty.getPartner()); - } else { - throw new UriParserSemanticException("A key is not allowed on non-collection navigation properties.", - UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED); - } - } + List<UriParameter> keyPredicate = ParserHelper.parseNavigationKeyPredicate(tokenizer, navigationProperty); ParserHelper.requireTokenEnd(tokenizer); - return new UriResourceNavigationPropertyImpl() - .setNavigationProperty(navigationProperty) + return new UriResourceNavigationPropertyImpl(navigationProperty) .setKeyPredicates(keyPredicate); } @@ -289,7 +269,7 @@ public class ResourcePathParser { previousTyped.isCollection()); if (boundAction != null) { ParserHelper.requireTokenEnd(tokenizer); - return new UriResourceActionImpl().setAction(boundAction); + return new UriResourceActionImpl(boundAction); } EdmStructuredType type = edm.getEntityType(name); if (type == null) { @@ -314,169 +294,6 @@ public class ResourcePathParser { } } - private List<UriParameter> keyPredicate(final EdmEntityType edmEntityType, final EdmNavigationProperty partner) - throws UriParserException, UriValidationException { - final List<EdmKeyPropertyRef> keyPropertyRefs = edmEntityType.getKeyPropertyRefs(); - if (tokenizer.next(TokenKind.CLOSE)) { - throw new UriParserSemanticException( - "Expected " + keyPropertyRefs.size() + " key predicates but none.", - UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES, - Integer.toString(keyPropertyRefs.size()), "0"); - } - List<UriParameter> keys = new ArrayList<UriParameter>(); - Map<String, String> referencedNames = new HashMap<String, String>(); - - if (partner != null) { - // Prepare list of potentially missing keys to be filled from referential constraints. - for (final String name : edmEntityType.getKeyPredicateNames()) { - final String referencedName = partner.getReferencingPropertyName(name); - if (referencedName != null) { - referencedNames.put(name, referencedName); - } - } - } - - if (tokenizer.next(TokenKind.ODataIdentifier)) { - keys.addAll(compoundKey(edmEntityType)); - } else if (keyPropertyRefs.size() - referencedNames.size() == 1) { - for (final EdmKeyPropertyRef candidate : keyPropertyRefs) { - if (referencedNames.get(candidate.getName()) == null) { - keys.add(simpleKey(candidate)); - break; - } - } - } else { - throw new UriParserSemanticException( - "Expected " + (keyPropertyRefs.size() -referencedNames.size()) + " key predicates but found one.", - UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES, - Integer.toString(keyPropertyRefs.size() - referencedNames.size()), "1"); - } - - if (keys.size() < keyPropertyRefs.size() && partner != null) { - // Fill missing keys from referential constraints. - for (final String name : edmEntityType.getKeyPredicateNames()) { - boolean found = false; - for (final UriParameter key : keys) { - if (name.equals(key.getName())) { - found = true; - break; - } - } - if (!found && referencedNames.get(name) != null) { - keys.add(0, new UriParameterImpl().setName(name).setReferencedProperty(referencedNames.get(name))); - } - } - } - - // Check that all key predicates are filled from the URI. - if (keys.size() < keyPropertyRefs.size()) { - throw new UriParserSemanticException( - "Expected " + keyPropertyRefs.size() + " key predicates but found " + keys.size() + ".", - UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES, - Integer.toString(keyPropertyRefs.size()), Integer.toString(keys.size())); - } else { - return keys; - } - } - - private UriParameter simpleKey(final EdmKeyPropertyRef edmKeyPropertyRef) - throws UriParserException, UriValidationException { - final EdmProperty edmProperty = edmKeyPropertyRef == null ? null : edmKeyPropertyRef.getProperty(); - if (nextPrimitiveTypeValue( - edmProperty == null ? null : (EdmPrimitiveType) edmProperty.getType(), - edmProperty == null ? false : edmProperty.isNullable())) { - final String literalValue = tokenizer.getText(); - ParserHelper.requireNext(tokenizer, TokenKind.CLOSE); - return createUriParameter(edmProperty, edmKeyPropertyRef.getName(), literalValue); - } else { - throw new UriParserSemanticException("The key value is not valid.", - UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, edmKeyPropertyRef.getName()); - } - } - - private List<UriParameter> compoundKey(final EdmEntityType edmEntityType) - throws UriParserException, UriValidationException { - - List<UriParameter> parameters = new ArrayList<UriParameter>(); - List<String> parameterNames = new ArrayList<String>(); - - // To validate that each key predicate is exactly specified once, we use a list to pick from. - List<String> remainingKeyNames = new ArrayList<String>(edmEntityType.getKeyPredicateNames()); - - // At least one key predicate is mandatory. Try to fetch all. - boolean hasComma = false; - do { - final String keyPredicateName = tokenizer.getText(); - if (parameterNames.contains(keyPredicateName)) { - throw new UriValidationException("Duplicated key property " + keyPredicateName, - UriValidationException.MessageKeys.DOUBLE_KEY_PROPERTY, keyPredicateName); - } - if (remainingKeyNames.isEmpty()) { - throw new UriParserSemanticException("Too many key properties.", - UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES, - Integer.toString(parameters.size()), Integer.toString(parameters.size() + 1)); - } - if (!remainingKeyNames.remove(keyPredicateName)) { - throw new UriValidationException("Unknown key property " + keyPredicateName, - UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, keyPredicateName); - } - parameters.add(keyValuePair(keyPredicateName, edmEntityType)); - parameterNames.add(keyPredicateName); - hasComma = tokenizer.next(TokenKind.COMMA); - if (hasComma) { - ParserHelper.requireNext(tokenizer, TokenKind.ODataIdentifier); - } - } while (hasComma); - ParserHelper.requireNext(tokenizer, TokenKind.CLOSE); - - return parameters; - } - - private UriParameter keyValuePair(final String keyPredicateName, final EdmEntityType edmEntityType) - throws UriParserException, UriValidationException { - final EdmKeyPropertyRef keyPropertyRef = edmEntityType.getKeyPropertyRef(keyPredicateName); - final EdmProperty edmProperty = keyPropertyRef == null ? null : keyPropertyRef.getProperty(); - if (edmProperty == null) { - throw new UriValidationException(keyPredicateName + " is not a valid key property name.", - UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, keyPredicateName); - } - ParserHelper.requireNext(tokenizer, TokenKind.EQ); - if (tokenizer.next(TokenKind.COMMA) || tokenizer.next(TokenKind.CLOSE) || tokenizer.next(TokenKind.EOF)) { - throw new UriParserSyntaxException("Key value expected.", UriParserSyntaxException.MessageKeys.SYNTAX); - } - if (nextPrimitiveTypeValue((EdmPrimitiveType) edmProperty.getType(), edmProperty.isNullable())) { - return createUriParameter(edmProperty, keyPredicateName, tokenizer.getText()); - } else { - throw new UriParserSemanticException(keyPredicateName + " has not a valid key value.", - UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, keyPredicateName); - } - } - - private UriParameter createUriParameter(final EdmProperty edmProperty, final String parameterName, - final String literalValue) throws UriParserException, UriValidationException { - if (literalValue.startsWith("@")) { - return new UriParameterImpl() - .setName(parameterName) - .setAlias(literalValue); - } - - final EdmPrimitiveType primitiveType = (EdmPrimitiveType) edmProperty.getType(); - try { - if (!(primitiveType.validate(primitiveType.fromUriLiteral(literalValue), edmProperty.isNullable(), - edmProperty.getMaxLength(), edmProperty.getPrecision(), edmProperty.getScale(), edmProperty.isUnicode()))) { - throw new UriValidationException("Invalid key property", - UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, parameterName); - } - } catch (final EdmPrimitiveTypeException e) { - throw new UriValidationException("Invalid key property", - UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, parameterName); - } - - return new UriParameterImpl() - .setName(parameterName) - .setText("null".equals(literalValue) ? null : literalValue); - } - private UriResource typeCast(final FullQualifiedName name, final EdmStructuredType type, final UriResourcePartTyped previousTyped) throws UriParserException, UriValidationException { if (type.compatibleTo(previousTyped.getType())) { @@ -501,7 +318,7 @@ public class ResourcePathParser { } if (tokenizer.next(TokenKind.OPEN)) { ((UriResourceWithKeysImpl) previousTyped).setKeyPredicates( - keyPredicate((EdmEntityType) type, null)); + ParserHelper.parseKeyPredicate(tokenizer, (EdmEntityType) type, null)); } } else { previousTypeFilter = ((UriResourceTypedImpl) previousTyped).getTypeFilter(); @@ -534,11 +351,8 @@ public class ResourcePathParser { private UriResource functionCall(final EdmFunctionImport edmFunctionImport, final FullQualifiedName boundFunctionName, final FullQualifiedName bindingParameterTypeName, final boolean isBindingParameterCollection) throws UriParserException, UriValidationException { - final List<UriParameter> parameters = functionParameters(); - List<String> names = new ArrayList<String>(); - for (final UriParameter parameter : parameters) { - names.add(parameter.getName()); - } + final List<UriParameter> parameters = ParserHelper.parseFunctionParameters(tokenizer, false); + final List<String> names = ParserHelper.getParameterNames(parameters); EdmFunction function = null; if (edmFunctionImport != null) { function = edmFunctionImport.getUnboundFunction(names); @@ -557,16 +371,13 @@ public class ResourcePathParser { UriParserSemanticException.MessageKeys.UNKNOWN_PART, boundFunctionName.getFullQualifiedNameAsString()); } } - UriResourceFunctionImpl resource = new UriResourceFunctionImpl() - .setFunctionImport(edmFunctionImport, null) - .setFunction(function) - .setParameters(parameters); + UriResourceFunctionImpl resource = new UriResourceFunctionImpl(edmFunctionImport, function, parameters); if (tokenizer.next(TokenKind.OPEN)) { if (function.getReturnType() != null && function.getReturnType().getType().getKind() == EdmTypeKind.ENTITY && function.getReturnType().isCollection()) { resource.setKeyPredicates( - keyPredicate((EdmEntityType) function.getReturnType().getType(), null)); + ParserHelper.parseKeyPredicate(tokenizer, (EdmEntityType) function.getReturnType().getType(), null)); } else { throw new UriParserSemanticException("A key is not allowed.", UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED); @@ -575,106 +386,4 @@ public class ResourcePathParser { ParserHelper.requireTokenEnd(tokenizer); return resource; } - - private List<UriParameter> functionParameters() throws UriParserException { - List<UriParameter> parameters = new ArrayList<UriParameter>(); - ParserHelper.requireNext(tokenizer, TokenKind.OPEN); - if (tokenizer.next(TokenKind.CLOSE)) { - return parameters; - } - do { - ParserHelper.requireNext(tokenizer, TokenKind.ODataIdentifier); - final String name = tokenizer.getText(); - if (parameters.contains(name)) { - throw new UriParserSemanticException("Duplicated function parameter " + name, - UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, name); - } - ParserHelper.requireNext(tokenizer, TokenKind.EQ); - if (tokenizer.next(TokenKind.COMMA) || tokenizer.next(TokenKind.CLOSE) || tokenizer.next(TokenKind.EOF)) { - throw new UriParserSyntaxException("Parameter value expected.", UriParserSyntaxException.MessageKeys.SYNTAX); - } - if (tokenizer.next(TokenKind.ParameterAliasName)) { - parameters.add(new UriParameterImpl().setName(name).setAlias(tokenizer.getText())); - } else if (nextPrimitiveValue()) { - final String literalValue = tokenizer.getText(); - parameters.add(new UriParameterImpl().setName(name) - .setText("null".equals(literalValue) ? null : literalValue)); - } else { - throw new UriParserSemanticException("Wrong parameter value.", - UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, ""); - } - } while (tokenizer.next(TokenKind.COMMA)); - ParserHelper.requireNext(tokenizer, TokenKind.CLOSE); - return parameters; - } - - private boolean nextPrimitiveTypeValue(final EdmPrimitiveType primitiveType, final boolean nullable) { - final EdmPrimitiveType type = primitiveType instanceof EdmTypeDefinition ? - ((EdmTypeDefinition) primitiveType).getUnderlyingType() : - primitiveType; - if (tokenizer.next(TokenKind.ParameterAliasName)) { - return true; - } else if (nullable && tokenizer.next(TokenKind.NULL)) { - return true; - - } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Boolean).equals(type)) { - return tokenizer.next(TokenKind.BooleanValue); - } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.String).equals(type)) { - return tokenizer.next(TokenKind.StringValue); - } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.SByte).equals(type) - || odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Byte).equals(type) - || odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int16).equals(type) - || odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int32).equals(type) - || odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int64).equals(type)) { - return tokenizer.next(TokenKind.IntegerValue); - } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Guid).equals(type)) { - return tokenizer.next(TokenKind.GuidValue); - } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Date).equals(type)) { - return tokenizer.next(TokenKind.DateValue); - } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.DateTimeOffset).equals(type)) { - return tokenizer.next(TokenKind.DateTimeOffsetValue); - } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.TimeOfDay).equals(type)) { - return tokenizer.next(TokenKind.TimeOfDayValue); - } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Decimal).equals(type)) { - // The order is important. - // A decimal value should not be parsed as integer and let the tokenizer stop at the decimal point. - return tokenizer.next(TokenKind.DecimalValue) - || tokenizer.next(TokenKind.IntegerValue); - } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Double).equals(type)) { - // The order is important. - // A floating-point value should not be parsed as decimal and let the tokenizer stop at 'E'. - // A decimal value should not be parsed as integer and let the tokenizer stop at the decimal point. - return tokenizer.next(TokenKind.DoubleValue) - || tokenizer.next(TokenKind.DecimalValue) - || tokenizer.next(TokenKind.IntegerValue); - } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Duration).equals(type)) { - return tokenizer.next(TokenKind.DurationValue); - } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Binary).equals(type)) { - return tokenizer.next(TokenKind.BinaryValue); - } else if (type.getKind() == EdmTypeKind.ENUM) { - return tokenizer.next(TokenKind.EnumValue); - } else { - return false; - } - } - - private boolean nextPrimitiveValue() { - return tokenizer.next(TokenKind.NULL) - || tokenizer.next(TokenKind.BooleanValue) - || tokenizer.next(TokenKind.StringValue) - - // The order of the next seven expressions is important in order to avoid - // finding partly parsed tokens (counter-intuitive as it may be, even a GUID may start with digits ...). - || tokenizer.next(TokenKind.DoubleValue) - || tokenizer.next(TokenKind.DecimalValue) - || tokenizer.next(TokenKind.GuidValue) - || tokenizer.next(TokenKind.DateTimeOffsetValue) - || tokenizer.next(TokenKind.DateValue) - || tokenizer.next(TokenKind.TimeOfDayValue) - || tokenizer.next(TokenKind.IntegerValue) - - || tokenizer.next(TokenKind.DurationValue) - || tokenizer.next(TokenKind.BinaryValue) - || tokenizer.next(TokenKind.EnumValue); - } } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/SelectParser.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/SelectParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/SelectParser.java index b257e68..00f3673 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/SelectParser.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/SelectParser.java @@ -156,10 +156,10 @@ public class SelectParser { throw new UriParserSemanticException("Function not found.", UriParserSemanticException.MessageKeys.UNKNOWN_PART, qualifiedName.getFullQualifiedNameAsString()); } else { - return new UriResourceFunctionImpl().setFunction(boundFunction); + return new UriResourceFunctionImpl(null, boundFunction, null); } } else { - return new UriResourceActionImpl().setAction(boundAction); + return new UriResourceActionImpl(boundAction); } } @@ -187,16 +187,16 @@ public class SelectParser { UriParserSemanticException.MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE, referencedType.getName(), name); } else { - resource.addResourcePart(new UriResourceNavigationPropertyImpl().setNavigationProperty(navigationProperty)); + resource.addResourcePart(new UriResourceNavigationPropertyImpl(navigationProperty)); } } else if (property.isPrimitive() || property.getType().getKind() == EdmTypeKind.ENUM || property.getType().getKind() == EdmTypeKind.DEFINITION) { - resource.addResourcePart(new UriResourcePrimitivePropertyImpl().setProperty(property)); + resource.addResourcePart(new UriResourcePrimitivePropertyImpl(property)); } else { - UriResourceComplexPropertyImpl complexPart = new UriResourceComplexPropertyImpl().setProperty(property); + UriResourceComplexPropertyImpl complexPart = new UriResourceComplexPropertyImpl(property); resource.addResourcePart(complexPart); if (tokenizer.next(TokenKind.SLASH)) { if (tokenizer.next(TokenKind.QualifiedName)) { http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriContext.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriContext.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriContext.java index c0db85b..36a0887 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriContext.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriContext.java @@ -32,10 +32,9 @@ import org.apache.olingo.server.core.uri.queryoption.SelectItemImpl; */ public class UriContext { - public static class LambdaVariables { + public static class LambdaVariable { public String name; public EdmType type; - public boolean isCollection; } /** @@ -43,7 +42,7 @@ public class UriContext { * As lambda functions can be nested there may be more than one allowed lambda variables at a time while parsing a * $filter or $orderby expressions. */ - public Deque<LambdaVariables> allowedLambdaVariables; + public Deque<LambdaVariable> allowedLambdaVariables; /** * Used to stack type information for nested $expand, $filter query options and other cases. */ @@ -110,7 +109,7 @@ public class UriContext { contextReadingFunctionParameters = false; contextSelectItem = null; contextTypes = new ArrayDeque<EdmType>(); - allowedLambdaVariables = new ArrayDeque<UriContext.LambdaVariables>(); + allowedLambdaVariables = new ArrayDeque<UriContext.LambdaVariable>(); } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java index 9d29ab2..1bab218 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java @@ -252,8 +252,8 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> { return new FullQualifiedName(namespace, odi); } - private UriContext.LambdaVariables getLambdaVar(final String odi) { - for (UriContext.LambdaVariables item : context.allowedLambdaVariables) { + private UriContext.LambdaVariable getLambdaVar(final String odi) { + for (UriContext.LambdaVariable item : context.allowedLambdaVariables) { if (item.name.equals(odi)) { return item; } @@ -292,7 +292,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> { || parts.get(0) instanceof UriResourceRoot)) { ensureNamespaceIsNull(ctx.vNS); context.contextUriInfo.addResourcePart( - new UriResourceEntitySetImpl().setEntitSet(edmEntitySet)); + new UriResourceEntitySetImpl(edmEntitySet)); return null; } @@ -303,7 +303,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> { || parts.get(0) instanceof UriResourceRoot)) { ensureNamespaceIsNull(ctx.vNS); context.contextUriInfo.addResourcePart( - new UriResourceSingletonImpl().setSingleton(edmSingleton)); + new UriResourceSingletonImpl(edmSingleton)); return null; } @@ -314,7 +314,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> { || parts.get(0) instanceof UriResourceRoot)) { ensureNamespaceIsNull(ctx.vNS); context.contextUriInfo.addResourcePart( - new UriResourceActionImpl().setActionImport(edmActionImport)); + new UriResourceActionImpl(edmActionImport)); return null; } @@ -344,9 +344,6 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> { // mark parameters as consumed ctx.vlNVO.remove(0); - UriResourceFunctionImpl uriResource = new UriResourceFunctionImpl() - .setFunctionImport(edmFunctionImport, parameters); - // collect parameter names List<String> names = new ArrayList<String>(); for (UriParameter item : parameters) { @@ -366,7 +363,9 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> { } ensureNamespaceIsNull(ctx.vNS); - uriResource.setFunction(edmFunctionImport.getUnboundFunction(names)); + UriResourceFunctionImpl uriResource = new UriResourceFunctionImpl(edmFunctionImport, + edmFunctionImport.getUnboundFunction(names), + parameters); context.contextUriInfo.addResourcePart(uriResource); return null; } @@ -390,7 +389,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> { sourceType = context.contextTypes.peek(); sourceIsCollection = context.isCollection; } else if (lastResourcePart instanceof UriResourcePartTyped) { - sourceType = Parser.getTypeInformation((UriResourcePartTyped) lastResourcePart); + sourceType = ParserHelper.getTypeInformation((UriResourcePartTyped) lastResourcePart); sourceIsCollection = ((UriResourcePartTyped) lastResourcePart).isCollection(); } else { throw wrap(new UriParserSemanticException( @@ -401,12 +400,9 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> { if (ctx.vNS == null) { // without namespace // first check for lambda variable because a newly add property should not shadow a long used lambda variable - UriContext.LambdaVariables lVar = getLambdaVar(odi); + UriContext.LambdaVariable lVar = getLambdaVar(odi); if (lVar != null) { - UriResourceLambdaVarImpl lambdaResource = new UriResourceLambdaVarImpl(); - lambdaResource.setVariableText(lVar.name); - lambdaResource.setType(lVar.type); - lambdaResource.setCollection(lVar.isCollection); + UriResourceLambdaVarImpl lambdaResource = new UriResourceLambdaVarImpl(lVar.name, lVar.type); context.contextUriInfo.addResourcePart(lambdaResource); return null; } @@ -442,14 +438,13 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> { || property.getType().getKind() == EdmTypeKind.ENUM || property.getType().getKind() == EdmTypeKind.DEFINITION) { // create simple property - UriResourcePrimitivePropertyImpl simpleResource = new UriResourcePrimitivePropertyImpl() - .setProperty((EdmProperty) property); + UriResourcePrimitivePropertyImpl simpleResource = + new UriResourcePrimitivePropertyImpl((EdmProperty) property); context.contextUriInfo.addResourcePart(simpleResource); return null; } else { // create complex property - UriResourceComplexPropertyImpl complexResource = new UriResourceComplexPropertyImpl() - .setProperty((EdmProperty) property); + UriResourceComplexPropertyImpl complexResource = new UriResourceComplexPropertyImpl((EdmProperty) property); context.contextUriInfo.addResourcePart(complexResource); return null; } @@ -461,8 +456,8 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> { UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED)); } - UriResourceNavigationPropertyImpl navigationResource = new UriResourceNavigationPropertyImpl() - .setNavigationProperty((EdmNavigationProperty) property); + UriResourceNavigationPropertyImpl navigationResource = + new UriResourceNavigationPropertyImpl((EdmNavigationProperty) property); context.contextUriInfo.addResourcePart(navigationResource); return null; } else { @@ -488,9 +483,9 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> { if (lastResourcePart == null) { // this may be the case if a member expression within a filter starts with a typeCast - UriResourceStartingTypeFilterImpl uriResource = new UriResourceStartingTypeFilterImpl() - .setType(filterEntityType) - .setCollection(sourceIsCollection); + UriResourceStartingTypeFilterImpl uriResource = new UriResourceStartingTypeFilterImpl( + filterEntityType, + sourceIsCollection); if (sourceIsCollection) { uriResource.setCollectionTypeFilter(filterEntityType); } else { @@ -562,9 +557,8 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> { // is simple complex type cast if (lastResourcePart == null) { // this may be the case if a member expression within a filter starts with a typeCast - UriResourceStartingTypeFilterImpl uriResource = new UriResourceStartingTypeFilterImpl() - .setType(filterComplexType) - .setCollection(sourceIsCollection); + UriResourceStartingTypeFilterImpl uriResource = + new UriResourceStartingTypeFilterImpl(filterComplexType, sourceIsCollection); if (sourceIsCollection) { uriResource.setCollectionTypeFilter(filterComplexType); @@ -626,8 +620,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> { // check for action EdmAction action = edm.getBoundAction(fullFilterName, fullBindingTypeName, sourceIsCollection); if (action != null) { - UriResourceActionImpl pathInfoAction = new UriResourceActionImpl(); - pathInfoAction.setAction(action); + UriResourceActionImpl pathInfoAction = new UriResourceActionImpl(action); context.contextUriInfo.addResourcePart(pathInfoAction); return null; } @@ -652,9 +645,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> { EdmFunction function = edm.getBoundFunction(fullFilterName, fullBindingTypeName, sourceIsCollection, names); if (function != null) { - UriResourceFunctionImpl pathInfoFunction = new UriResourceFunctionImpl() - .setFunction(function) - .setParameters(parameters); + UriResourceFunctionImpl pathInfoFunction = new UriResourceFunctionImpl(null, function, parameters); context.contextUriInfo.addResourcePart(pathInfoFunction); // mark parameters as consumed @@ -666,9 +657,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> { function = edm.getUnboundFunction(fullFilterName, names); if (function != null) { - UriResourceFunctionImpl pathInfoFunction = new UriResourceFunctionImpl() - .setFunction(function) - .setParameters(parameters); + UriResourceFunctionImpl pathInfoFunction = new UriResourceFunctionImpl(null, function, parameters); context.contextUriInfo.addResourcePart(pathInfoFunction); // mark parameters as consumed @@ -706,8 +695,6 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> { @Override public Object visitAllExpr(final AllExprContext ctx) { - UriResourceLambdaAllImpl all = new UriResourceLambdaAllImpl(); - UriResource obj = context.contextUriInfo.getLastResourcePart(); if (!(obj instanceof UriResourcePartTyped)) { throw wrap(new UriParserSemanticException("all only allowed on typed path segments", @@ -720,16 +707,14 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> { } } - UriContext.LambdaVariables var = new UriContext.LambdaVariables(); + UriContext.LambdaVariable var = new UriContext.LambdaVariable(); var.name = ctx.vLV.getText(); - var.type = Parser.getTypeInformation((UriResourcePartTyped) obj); - var.isCollection = false; + var.type = ParserHelper.getTypeInformation((UriResourcePartTyped) obj); - all.setLamdaVariable(ctx.vLV.getText()); context.allowedLambdaVariables.push(var); - all.setExpression((Expression) ctx.vLE.accept(this)); + Expression expression = (Expression) ctx.vLE.accept(this); context.allowedLambdaVariables.pop(); - return all; + return new UriResourceLambdaAllImpl(var.name, expression); } @Override @@ -895,7 +880,6 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> { @Override public Object visitAnyExpr(final AnyExprContext ctx) { - UriResourceLambdaAnyImpl any = new UriResourceLambdaAnyImpl(); if (ctx.vLV != null) { UriResourceImpl lastResourcePart = (UriResourceImpl) context.contextUriInfo.getLastResourcePart(); if (!(lastResourcePart instanceof UriResourcePartTyped)) { @@ -909,17 +893,16 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> { } } - UriContext.LambdaVariables var = new UriContext.LambdaVariables(); + UriContext.LambdaVariable var = new UriContext.LambdaVariable(); var.name = ctx.vLV.getText(); - var.type = Parser.getTypeInformation((UriResourcePartTyped) lastResourcePart); - var.isCollection = false; + var.type = ParserHelper.getTypeInformation((UriResourcePartTyped) lastResourcePart); - any.setLamdaVariable(ctx.vLV.getText()); context.allowedLambdaVariables.push(var); - any.setExpression((Expression) ctx.vLE.accept(this)); + Expression expression = (Expression) ctx.vLE.accept(this); context.allowedLambdaVariables.pop(); + return new UriResourceLambdaAnyImpl(var.name, expression); } - return any; + return null; } @Override @@ -1238,18 +1221,18 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> { if (context.contextExpandItemPath == null) { // use the type of the last resource path segement UriResourceTypedImpl lastSegment = (UriResourceTypedImpl) context.contextUriInfo.getLastResourcePart(); - targetType = Parser.getTypeInformation(lastSegment); + targetType = ParserHelper.getTypeInformation(lastSegment); isColl = lastSegment.isCollection(); } else { if (context.contextExpandItemPath.getResourcePath() == null) { // use the type of the last resource path segement UriResourceTypedImpl lastSegment = (UriResourceTypedImpl) context.contextUriInfo.getLastResourcePart(); - targetType = Parser.getTypeInformation(lastSegment); + targetType = ParserHelper.getTypeInformation(lastSegment); isColl = lastSegment.isCollection(); } else { // use the type of the last ''expand'' path segement UriInfoImpl info = (UriInfoImpl) context.contextExpandItemPath.getResourcePath(); - targetType = Parser.getTypeInformation((UriResourcePartTyped) info.getLastResourcePart()); + targetType = ParserHelper.getTypeInformation((UriResourcePartTyped) info.getLastResourcePart()); isColl = ((UriResourcePartTyped) info.getLastResourcePart()).isCollection(); } } @@ -1400,10 +1383,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> { } if (ctx.vIt != null || ctx.vIts != null) { - UriResourceItImpl pathInfoIT = new UriResourceItImpl(); - pathInfoIT.setType(context.contextTypes.peek()); - pathInfoIT.setCollection(context.isCollection); - uriInfoImplpath.addResourcePart(pathInfoIT); + uriInfoImplpath.addResourcePart(new UriResourceItImpl(context.contextTypes.peek(), context.isCollection)); } if (ctx.vPs != null) { @@ -1915,9 +1895,9 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> { UriResourcePartTyped lastType = (UriResourcePartTyped) lastResource; - UriResourceRootImpl pathInfoRoot = new UriResourceRootImpl(); - pathInfoRoot.setCollection(lastType.isCollection()); - pathInfoRoot.setType(Parser.getTypeInformation(lastType)); + UriResourceRootImpl pathInfoRoot = new UriResourceRootImpl( + ParserHelper.getTypeInformation(lastType), + lastType.isCollection()); UriInfoImpl uriInfoImplpath = new UriInfoImpl().setKind(UriInfoKind.resource); uriInfoImplpath.addResourcePart(pathInfoRoot); @@ -2010,7 +1990,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> { UriInfoImpl uriInfo = (UriInfoImpl) context.contextSelectItem.getResourcePath(); UriResource last = uriInfo.getLastResourcePart(); - prevType = Parser.getTypeInformation((UriResourcePartTyped) last); + prevType = ParserHelper.getTypeInformation((UriResourcePartTyped) last); if (prevType == null) { throw wrap(new UriParserSemanticException("prev segment not typed", UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PARTS, "select")); @@ -2038,8 +2018,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> { || property.getType().getKind() == EdmTypeKind.ENUM || property.getType().getKind() == EdmTypeKind.DEFINITION) { - UriResourcePrimitivePropertyImpl simple = new UriResourcePrimitivePropertyImpl(); - simple.setProperty(property); + UriResourcePrimitivePropertyImpl simple = new UriResourcePrimitivePropertyImpl(property); UriInfoImpl uriInfo = (UriInfoImpl) context.contextSelectItem.getResourcePath(); if (uriInfo == null) { @@ -2059,8 +2038,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> { } else { UriInfoImpl uriInfo = (UriInfoImpl) context.contextSelectItem.getResourcePath(); - UriResourceComplexPropertyImpl complex = new UriResourceComplexPropertyImpl(); - complex.setProperty(property); + UriResourceComplexPropertyImpl complex = new UriResourceComplexPropertyImpl(property); if (uriInfo == null) { uriInfo = new UriInfoImpl().setKind(UriInfoKind.resource); @@ -2096,7 +2074,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> { EdmComplexType ct = edm.getComplexType(fullName); if (ct != null) { if ((ct.compatibleTo(prevType))) { - UriResourceStartingTypeFilterImpl resourcePart = new UriResourceStartingTypeFilterImpl(); + UriResourceStartingTypeFilterImpl resourcePart = new UriResourceStartingTypeFilterImpl(null, false); resourcePart.setCollectionTypeFilter(ct); UriInfoImpl uriInfo = new UriInfoImpl().setKind(UriInfoKind.resource); @@ -2115,7 +2093,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> { EdmEntityType et = edm.getEntityType(fullName); if (et != null) { if ((et.compatibleTo(prevType))) { - UriResourceStartingTypeFilterImpl resourcePart = new UriResourceStartingTypeFilterImpl(); + UriResourceStartingTypeFilterImpl resourcePart = new UriResourceStartingTypeFilterImpl(null, false); resourcePart.setCollectionTypeFilter(et); UriInfoImpl uriInfo = new UriInfoImpl().setKind(UriInfoKind.resource); @@ -2142,13 +2120,13 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> { throw wrap(new UriParserSemanticException("prev segment typed", UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PARTS, "select")); } - EdmType prevType = Parser.getTypeInformation((UriResourcePartTyped) last); + EdmType prevType = ParserHelper.getTypeInformation((UriResourcePartTyped) last); if (prevType instanceof EdmComplexType) { EdmComplexType ct = edm.getComplexType(fullName); if (ct != null) { if ((ct.compatibleTo(prevType))) { - UriResourceStartingTypeFilterImpl resourcePart = new UriResourceStartingTypeFilterImpl(); + UriResourceStartingTypeFilterImpl resourcePart = new UriResourceStartingTypeFilterImpl(null, false); resourcePart.setCollectionTypeFilter(ct); uriInfo.addResourcePart(resourcePart); @@ -2186,7 +2164,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> { throw wrap(new UriParserSemanticException("prev segment typed", UriParserSemanticException.MessageKeys.PREVIOUS_PART_TYPED)); } - prevType = Parser.getTypeInformation((UriResourcePartTyped) last); + prevType = ParserHelper.getTypeInformation((UriResourcePartTyped) last); } final FullQualifiedName finalTypeName = prevType.getFullQualifiedName(); @@ -2195,8 +2173,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> { EdmAction action = edm.getBoundAction(fullName, finalTypeName, null); if (action != null) { - UriResourceActionImpl uriAction = new UriResourceActionImpl(); - uriAction.setAction(action); + UriResourceActionImpl uriAction = new UriResourceActionImpl(action); UriInfoImpl resourcePath = (UriInfoImpl) context.contextSelectItem.getResourcePath(); resourcePath.addResourcePart(uriAction); @@ -2206,8 +2183,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> { EdmFunction function = edm.getBoundFunction(fullName, finalTypeName, null, null); if (function != null) { - UriResourceFunctionImpl uriFunction = new UriResourceFunctionImpl(); - uriFunction.setFunction(function); + UriResourceFunctionImpl uriFunction = new UriResourceFunctionImpl(null, function, null); UriInfoImpl resourcePath = (UriInfoImpl) context.contextSelectItem.getResourcePath(); resourcePath.addResourcePart(uriFunction); http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java index 4b43cd9..37f1b76 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java @@ -40,10 +40,14 @@ public class UriTokenizer { ROOT, IT, + ANY, + ALL, + OPEN, CLOSE, COMMA, SEMI, + COLON, DOT, SLASH, EQ, @@ -119,7 +123,10 @@ public class UriTokenizer { TotalsecondsMethod, ToupperMethod, TrimMethod, - YearMethod + YearMethod, + + AscSuffix, + DescSuffix } private final String parseString; @@ -174,6 +181,13 @@ public class UriTokenizer { found = nextConstant("$it"); break; + case ANY: + found = nextConstant("any"); + break; + case ALL: + found = nextConstant("all"); + break; + case OPEN: found = nextCharacter('('); break; @@ -186,6 +200,9 @@ public class UriTokenizer { case SEMI: found = nextCharacter(';'); break; + case COLON: + found = nextCharacter(':'); + break; case DOT: found = nextCharacter('.'); break; @@ -409,6 +426,14 @@ public class UriTokenizer { case YearMethod: found = nextMethod("year"); break; + + // Suffixes + case AscSuffix: + found = nextSuffix("asc"); + break; + case DescSuffix: + found = nextSuffix("desc"); + break; } if (found) { @@ -543,6 +568,15 @@ public class UriTokenizer { } /** + * Moves past (required) whitespace and the given suffix name if found; + * otherwise leaves the index unchanged. + * @return whether the suffix has been found at the current index + */ + private boolean nextSuffix(final String suffixName) { + return nextWhitespace() && nextConstant(suffixName); + } + + /** * Moves past an OData identifier if found; otherwise leaves the index unchanged. * @return whether an OData identifier has been found at the current index */ http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/MemberImpl.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/MemberImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/MemberImpl.java index a71e382..6ef37e4 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/MemberImpl.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/MemberImpl.java @@ -94,4 +94,9 @@ public class MemberImpl implements Member { } return false; } + + @Override + public String toString() { + return path.getUriResourceParts().toString() + (startTypeFilter == null ? "" : startTypeFilter); + } } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/UriInfoImplTest.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/UriInfoImplTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/UriInfoImplTest.java index 4c76e96..68e6637 100644 --- a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/UriInfoImplTest.java +++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/UriInfoImplTest.java @@ -25,6 +25,7 @@ import static org.junit.Assert.assertTrue; import java.util.Arrays; +import org.apache.olingo.commons.api.edm.EdmAction; import org.apache.olingo.commons.api.edm.EdmEntityType; import org.apache.olingo.commons.api.ex.ODataRuntimeException; import org.apache.olingo.server.api.uri.UriInfo; @@ -33,9 +34,6 @@ import org.apache.olingo.server.api.uri.UriResourceAction; import org.apache.olingo.server.api.uri.UriResourceEntitySet; import org.apache.olingo.server.api.uri.queryoption.AliasQueryOption; import org.apache.olingo.server.api.uri.queryoption.QueryOption; -import org.apache.olingo.server.core.uri.UriInfoImpl; -import org.apache.olingo.server.core.uri.UriResourceActionImpl; -import org.apache.olingo.server.core.uri.UriResourceEntitySetImpl; import org.apache.olingo.server.core.uri.queryoption.AliasQueryOptionImpl; import org.apache.olingo.server.core.uri.queryoption.CountOptionImpl; import org.apache.olingo.server.core.uri.queryoption.CustomQueryOptionImpl; @@ -86,9 +84,9 @@ public class UriInfoImplTest { public void resourceParts() { UriInfoImpl uriInfo = new UriInfoImpl(); - final UriResourceAction action = new UriResourceActionImpl(); - final UriResourceEntitySet entitySet0 = new UriResourceEntitySetImpl(); - final UriResourceEntitySet entitySet1 = new UriResourceEntitySetImpl(); + final UriResourceAction action = new UriResourceActionImpl((EdmAction) null); + final UriResourceEntitySet entitySet0 = new UriResourceEntitySetImpl(null); + final UriResourceEntitySet entitySet1 = new UriResourceEntitySetImpl(null); uriInfo.addResourcePart(action); uriInfo.addResourcePart(entitySet0); http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8091658/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java index 183ff22..4ab7fce 100644 --- a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java +++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java @@ -28,6 +28,7 @@ import java.util.Locale; import org.apache.olingo.server.api.OData; import org.apache.olingo.server.api.uri.queryoption.expression.Expression; import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind; +import org.apache.olingo.server.core.uri.validator.UriValidationException; import org.junit.Test; public class ExpressionParserTest { @@ -127,7 +128,7 @@ public class ExpressionParserTest { @Test public void unary() throws Exception { Expression expression = parseExpression("-5"); - assertEquals("{MINUS 5}", expression.toString()); + assertEquals("-5", expression.toString()); assertEquals("{MINUS -1}", parseExpression("--1").toString()); assertEquals("{MINUS duration'PT1M'}", parseExpression("-duration'PT1M'").toString()); @@ -135,13 +136,13 @@ public class ExpressionParserTest { expression = parseExpression("not false"); assertEquals("{NOT false}", expression.toString()); - wrongExpression("-11:12:13"); + wrongExpression("not 11:12:13"); } @Test public void grouping() throws Exception { Expression expression = parseExpression("-5 add 5"); - assertEquals("{{MINUS 5} ADD 5}", expression.toString()); + assertEquals("{-5 ADD 5}", expression.toString()); expression = parseExpression("-(5 add 5)"); assertEquals("{MINUS {5 ADD 5}}", expression.toString()); @@ -149,7 +150,7 @@ public class ExpressionParserTest { @Test public void precedence() throws Exception { - assertEquals("{{MINUS 1} ADD {2 DIV 3}}", parseExpression("-1 add 2 div 3").toString()); + assertEquals("{-1 ADD {2 DIV 3}}", parseExpression("-1 add 2 div 3").toString()); assertEquals("{true OR {{NOT false} AND true}}", parseExpression("true or not false and true").toString()); } @@ -264,7 +265,8 @@ public class ExpressionParserTest { wrongExpression("substring(1,2)"); } - private Expression parseMethod(TokenKind kind, String... parameters) throws UriParserException { + private Expression parseMethod(TokenKind kind, String... parameters) + throws UriParserException, UriValidationException { String expressionString = kind.name().substring(0, kind.name().indexOf("Method")) .toLowerCase(Locale.ROOT).replace("geo", "geo.") + '('; boolean first = true; @@ -283,9 +285,10 @@ public class ExpressionParserTest { return expression; } - private Expression parseExpression(final String expressionString) throws UriParserException { + private Expression parseExpression(final String expressionString) + throws UriParserException, UriValidationException { UriTokenizer tokenizer = new UriTokenizer(expressionString); - Expression expression = new ExpressionParser(null, odata).parse(tokenizer); + Expression expression = new ExpressionParser(null, odata).parse(tokenizer, null, null); assertNotNull(expression); assertTrue(tokenizer.next(TokenKind.EOF)); return expression; @@ -293,10 +296,12 @@ public class ExpressionParserTest { private void wrongExpression(final String expressionString) { try { - new ExpressionParser(null, odata).parse(new UriTokenizer(expressionString)); + new ExpressionParser(null, odata).parse(new UriTokenizer(expressionString), null, null); fail("Expected exception not thrown."); } catch (final UriParserException e) { assertNotNull(e); + } catch (final UriValidationException e) { + assertNotNull(e); } } }
