[OLINGO-834] ExpressionParser uses UriTokenizer
Signed-off-by: Christian Amend <christian.amend@sap.com>
This commit is contained in:
parent
208f26c746
commit
2f3bc2866b
|
@ -32,6 +32,7 @@ import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
|
|||
import org.apache.olingo.server.api.uri.queryoption.expression.Method;
|
||||
import org.apache.olingo.server.api.uri.queryoption.expression.MethodKind;
|
||||
import org.apache.olingo.server.api.uri.queryoption.expression.UnaryOperatorKind;
|
||||
import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind;
|
||||
import org.apache.olingo.server.core.uri.queryoption.expression.AliasImpl;
|
||||
import org.apache.olingo.server.core.uri.queryoption.expression.BinaryImpl;
|
||||
import org.apache.olingo.server.core.uri.queryoption.expression.LiteralImpl;
|
||||
|
@ -39,75 +40,73 @@ import org.apache.olingo.server.core.uri.queryoption.expression.MethodImpl;
|
|||
import org.apache.olingo.server.core.uri.queryoption.expression.UnaryImpl;
|
||||
|
||||
public class ExpressionParser {
|
||||
private Tokenizer tokenizer;
|
||||
|
||||
private static final Map<TokenKind, BinaryOperatorKind> tokenToBinaryOperator;
|
||||
static {
|
||||
Map<TokenKind, BinaryOperatorKind> temp = new HashMap<ExpressionParser.TokenKind, BinaryOperatorKind>();
|
||||
temp.put(TokenKind.OR_OP, BinaryOperatorKind.OR);
|
||||
temp.put(TokenKind.AND_OP, BinaryOperatorKind.AND);
|
||||
Map<TokenKind, BinaryOperatorKind> temp = new HashMap<TokenKind, BinaryOperatorKind>();
|
||||
temp.put(TokenKind.OrOperator, BinaryOperatorKind.OR);
|
||||
temp.put(TokenKind.AndOperator, BinaryOperatorKind.AND);
|
||||
|
||||
temp.put(TokenKind.EQ_OP, BinaryOperatorKind.EQ);
|
||||
temp.put(TokenKind.NE_OP, BinaryOperatorKind.NE);
|
||||
temp.put(TokenKind.EqualsOperator, BinaryOperatorKind.EQ);
|
||||
temp.put(TokenKind.NotEqualsOperator, BinaryOperatorKind.NE);
|
||||
|
||||
temp.put(TokenKind.GT_OP, BinaryOperatorKind.GT);
|
||||
temp.put(TokenKind.GE_OP, BinaryOperatorKind.GE);
|
||||
temp.put(TokenKind.LT_OP, BinaryOperatorKind.LT);
|
||||
temp.put(TokenKind.LE_OP, BinaryOperatorKind.LE);
|
||||
temp.put(TokenKind.GreaterThanOperator, BinaryOperatorKind.GT);
|
||||
temp.put(TokenKind.GreaterThanOrEqualsOperator, BinaryOperatorKind.GE);
|
||||
temp.put(TokenKind.LessThanOperator, BinaryOperatorKind.LT);
|
||||
temp.put(TokenKind.LessThanOrEqualsOperator, BinaryOperatorKind.LE);
|
||||
|
||||
temp.put(TokenKind.ADD_OP, BinaryOperatorKind.ADD);
|
||||
temp.put(TokenKind.SUB_OP, BinaryOperatorKind.SUB);
|
||||
temp.put(TokenKind.AddOperator, BinaryOperatorKind.ADD);
|
||||
temp.put(TokenKind.SubOperator, BinaryOperatorKind.SUB);
|
||||
|
||||
temp.put(TokenKind.MUL_OP, BinaryOperatorKind.MUL);
|
||||
temp.put(TokenKind.DIV_OP, BinaryOperatorKind.DIV);
|
||||
temp.put(TokenKind.MOD_OP, BinaryOperatorKind.MOD);
|
||||
temp.put(TokenKind.MulOperator, BinaryOperatorKind.MUL);
|
||||
temp.put(TokenKind.DivOperator, BinaryOperatorKind.DIV);
|
||||
temp.put(TokenKind.ModOperator, BinaryOperatorKind.MOD);
|
||||
|
||||
tokenToBinaryOperator = Collections.unmodifiableMap(temp);
|
||||
}
|
||||
|
||||
private static final Map<TokenKind, UnaryOperatorKind> tokenToUnaryOperator;
|
||||
static {
|
||||
Map<TokenKind, UnaryOperatorKind> temp = new HashMap<ExpressionParser.TokenKind, UnaryOperatorKind>();
|
||||
Map<TokenKind, UnaryOperatorKind> temp = new HashMap<TokenKind, UnaryOperatorKind>();
|
||||
temp.put(TokenKind.MINUS, UnaryOperatorKind.MINUS);
|
||||
temp.put(TokenKind.NOT, UnaryOperatorKind.NOT);
|
||||
temp.put(TokenKind.NotOperator, UnaryOperatorKind.NOT);
|
||||
tokenToUnaryOperator = Collections.unmodifiableMap(temp);
|
||||
}
|
||||
|
||||
private static final Map<TokenKind, MethodKind> tokenToMethod;
|
||||
static {
|
||||
Map<TokenKind, MethodKind> temp = new HashMap<ExpressionParser.TokenKind, MethodKind>();
|
||||
temp.put(TokenKind.Cast, MethodKind.CAST);
|
||||
temp.put(TokenKind.Ceiling, MethodKind.CEILING);
|
||||
temp.put(TokenKind.Concat, MethodKind.CONCAT);
|
||||
temp.put(TokenKind.Contains, MethodKind.CONTAINS);
|
||||
temp.put(TokenKind.Date, MethodKind.DATE);
|
||||
temp.put(TokenKind.Day, MethodKind.DAY);
|
||||
temp.put(TokenKind.Endswith, MethodKind.ENDSWITH);
|
||||
temp.put(TokenKind.Floor, MethodKind.FLOOR);
|
||||
temp.put(TokenKind.Fractionalseconds, MethodKind.FRACTIONALSECONDS);
|
||||
temp.put(TokenKind.GeoDistance, MethodKind.GEODISTANCE);
|
||||
temp.put(TokenKind.GeoIntersects, MethodKind.GEOINTERSECTS);
|
||||
temp.put(TokenKind.GeoLength, MethodKind.GEOLENGTH);
|
||||
temp.put(TokenKind.Hour, MethodKind.HOUR);
|
||||
temp.put(TokenKind.Indexof, MethodKind.INDEXOF);
|
||||
temp.put(TokenKind.Isof, MethodKind.ISOF);
|
||||
temp.put(TokenKind.Length, MethodKind.LENGTH);
|
||||
temp.put(TokenKind.Maxdatetime, MethodKind.MAXDATETIME);
|
||||
temp.put(TokenKind.Mindatetime, MethodKind.MINDATETIME);
|
||||
temp.put(TokenKind.Minute, MethodKind.MINUTE);
|
||||
temp.put(TokenKind.Month, MethodKind.MONTH);
|
||||
temp.put(TokenKind.Now, MethodKind.NOW);
|
||||
temp.put(TokenKind.Round, MethodKind.ROUND);
|
||||
temp.put(TokenKind.Second, MethodKind.SECOND);
|
||||
temp.put(TokenKind.Startswith, MethodKind.STARTSWITH);
|
||||
temp.put(TokenKind.Substring, MethodKind.SUBSTRING);
|
||||
temp.put(TokenKind.Time, MethodKind.TIME);
|
||||
temp.put(TokenKind.Tolower, MethodKind.TOLOWER);
|
||||
temp.put(TokenKind.Totaloffsetminutes, MethodKind.TOTALOFFSETMINUTES);
|
||||
temp.put(TokenKind.Totalseconds, MethodKind.TOTALSECONDS);
|
||||
temp.put(TokenKind.Toupper, MethodKind.TOUPPER);
|
||||
temp.put(TokenKind.Trim, MethodKind.TRIM);
|
||||
temp.put(TokenKind.Year, MethodKind.YEAR);
|
||||
Map<TokenKind, MethodKind> temp = new HashMap<TokenKind, MethodKind>();
|
||||
temp.put(TokenKind.CastMethod, MethodKind.CAST);
|
||||
temp.put(TokenKind.CeilingMethod, MethodKind.CEILING);
|
||||
temp.put(TokenKind.ConcatMethod, MethodKind.CONCAT);
|
||||
temp.put(TokenKind.ContainsMethod, MethodKind.CONTAINS);
|
||||
temp.put(TokenKind.DateMethod, MethodKind.DATE);
|
||||
temp.put(TokenKind.DayMethod, MethodKind.DAY);
|
||||
temp.put(TokenKind.EndswithMethod, MethodKind.ENDSWITH);
|
||||
temp.put(TokenKind.FloorMethod, MethodKind.FLOOR);
|
||||
temp.put(TokenKind.FractionalsecondsMethod, MethodKind.FRACTIONALSECONDS);
|
||||
temp.put(TokenKind.GeoDistanceMethod, MethodKind.GEODISTANCE);
|
||||
temp.put(TokenKind.GeoIntersectsMethod, MethodKind.GEOINTERSECTS);
|
||||
temp.put(TokenKind.GeoLengthMethod, MethodKind.GEOLENGTH);
|
||||
temp.put(TokenKind.HourMethod, MethodKind.HOUR);
|
||||
temp.put(TokenKind.IndexofMethod, MethodKind.INDEXOF);
|
||||
temp.put(TokenKind.IsofMethod, MethodKind.ISOF);
|
||||
temp.put(TokenKind.LengthMethod, MethodKind.LENGTH);
|
||||
temp.put(TokenKind.MaxdatetimeMethod, MethodKind.MAXDATETIME);
|
||||
temp.put(TokenKind.MindatetimeMethod, MethodKind.MINDATETIME);
|
||||
temp.put(TokenKind.MinuteMethod, MethodKind.MINUTE);
|
||||
temp.put(TokenKind.MonthMethod, MethodKind.MONTH);
|
||||
temp.put(TokenKind.NowMethod, MethodKind.NOW);
|
||||
temp.put(TokenKind.RoundMethod, MethodKind.ROUND);
|
||||
temp.put(TokenKind.SecondMethod, MethodKind.SECOND);
|
||||
temp.put(TokenKind.StartswithMethod, MethodKind.STARTSWITH);
|
||||
temp.put(TokenKind.SubstringMethod, MethodKind.SUBSTRING);
|
||||
temp.put(TokenKind.TimeMethod, MethodKind.TIME);
|
||||
temp.put(TokenKind.TolowerMethod, MethodKind.TOLOWER);
|
||||
temp.put(TokenKind.TotaloffsetminutesMethod, MethodKind.TOTALOFFSETMINUTES);
|
||||
temp.put(TokenKind.TotalsecondsMethod, MethodKind.TOTALSECONDS);
|
||||
temp.put(TokenKind.ToupperMethod, MethodKind.TOUPPER);
|
||||
temp.put(TokenKind.TrimMethod, MethodKind.TRIM);
|
||||
temp.put(TokenKind.YearMethod, MethodKind.YEAR);
|
||||
|
||||
tokenToMethod = Collections.unmodifiableMap(temp);
|
||||
}
|
||||
|
@ -115,24 +114,26 @@ public class ExpressionParser {
|
|||
private static final Map<TokenKind, EdmPrimitiveTypeKind> tokenToPrimitiveType;
|
||||
static {
|
||||
/* Enum and null are not present in the map. These have to be handled differently */
|
||||
Map<TokenKind, EdmPrimitiveTypeKind> temp = new HashMap<ExpressionParser.TokenKind, EdmPrimitiveTypeKind>();
|
||||
temp.put(TokenKind.PrimitiveBooleanValue, EdmPrimitiveTypeKind.Boolean);
|
||||
temp.put(TokenKind.PrimitiveStringValue, EdmPrimitiveTypeKind.String);
|
||||
Map<TokenKind, EdmPrimitiveTypeKind> temp = new HashMap<TokenKind, EdmPrimitiveTypeKind>();
|
||||
temp.put(TokenKind.BooleanValue, EdmPrimitiveTypeKind.Boolean);
|
||||
temp.put(TokenKind.StringValue, EdmPrimitiveTypeKind.String);
|
||||
// TODO:Check if int64 is correct here or if it has to be single instead
|
||||
temp.put(TokenKind.PrimitiveIntegerValue, EdmPrimitiveTypeKind.Int64);
|
||||
temp.put(TokenKind.PrimitiveGuidValue, EdmPrimitiveTypeKind.Guid);
|
||||
temp.put(TokenKind.PrimitiveDateValue, EdmPrimitiveTypeKind.Date);
|
||||
temp.put(TokenKind.PrimitiveDateTimeOffsetValue, EdmPrimitiveTypeKind.DateTimeOffset);
|
||||
temp.put(TokenKind.PrimitiveTimeOfDayValue, EdmPrimitiveTypeKind.TimeOfDay);
|
||||
temp.put(TokenKind.PrimitiveDecimalValue, EdmPrimitiveTypeKind.Decimal);
|
||||
temp.put(TokenKind.PrimitiveDoubleValue, EdmPrimitiveTypeKind.Double);
|
||||
temp.put(TokenKind.PrimitiveDurationValue, EdmPrimitiveTypeKind.Duration);
|
||||
temp.put(TokenKind.PrimitiveBinaryValue, EdmPrimitiveTypeKind.Binary);
|
||||
temp.put(TokenKind.IntegerValue, EdmPrimitiveTypeKind.Int64);
|
||||
temp.put(TokenKind.GuidValue, EdmPrimitiveTypeKind.Guid);
|
||||
temp.put(TokenKind.DateValue, EdmPrimitiveTypeKind.Date);
|
||||
temp.put(TokenKind.DateTimeOffsetValue, EdmPrimitiveTypeKind.DateTimeOffset);
|
||||
temp.put(TokenKind.TimeOfDayValue, EdmPrimitiveTypeKind.TimeOfDay);
|
||||
temp.put(TokenKind.DecimalValue, EdmPrimitiveTypeKind.Decimal);
|
||||
temp.put(TokenKind.DoubleValue, EdmPrimitiveTypeKind.Double);
|
||||
temp.put(TokenKind.DurationValue, EdmPrimitiveTypeKind.Duration);
|
||||
temp.put(TokenKind.BinaryValue, EdmPrimitiveTypeKind.Binary);
|
||||
|
||||
tokenToPrimitiveType = Collections.unmodifiableMap(temp);
|
||||
}
|
||||
|
||||
public Expression parse(Tokenizer tokenizer) throws UriParserException {
|
||||
private UriTokenizer tokenizer;
|
||||
|
||||
public Expression parse(UriTokenizer tokenizer) throws UriParserException {
|
||||
// Initialize tokenizer.
|
||||
this.tokenizer = tokenizer;
|
||||
|
||||
|
@ -141,23 +142,17 @@ public class ExpressionParser {
|
|||
|
||||
private Expression parseExpression() throws UriParserException {
|
||||
Expression left = parseAnd();
|
||||
|
||||
while (is(TokenKind.OR_OP) != null) {
|
||||
tokenizer.getText();
|
||||
|
||||
Expression right = parseAnd();
|
||||
while (tokenizer.next(TokenKind.OrOperator)) {
|
||||
final Expression right = parseAnd();
|
||||
left = new BinaryImpl(left, BinaryOperatorKind.OR, right);
|
||||
}
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
private Expression parseAnd() throws UriParserException {
|
||||
Expression left = parseExprEquality();
|
||||
while (is(TokenKind.AND_OP) != null) {
|
||||
tokenizer.getText();
|
||||
|
||||
Expression right = parseExprEquality();
|
||||
while (tokenizer.next(TokenKind.AndOperator)) {
|
||||
final Expression right = parseExprEquality();
|
||||
left = new BinaryImpl(left, BinaryOperatorKind.AND, right);
|
||||
}
|
||||
return left;
|
||||
|
@ -165,110 +160,107 @@ public class ExpressionParser {
|
|||
|
||||
private Expression parseExprEquality() throws UriParserException {
|
||||
Expression left = parseExprRel();
|
||||
|
||||
TokenKind nextTokenKind = is(TokenKind.EQ_OP, TokenKind.NE_OP);
|
||||
TokenKind operatorTokenKind = ParserHelper.next(tokenizer, TokenKind.EqualsOperator, TokenKind.NotEqualsOperator);
|
||||
// Null for everything other than EQ or NE
|
||||
while (nextTokenKind != null) {
|
||||
tokenizer.getText();
|
||||
|
||||
Expression right = parseExprEquality();
|
||||
left = new BinaryImpl(left, tokenToBinaryOperator.get(nextTokenKind), right);
|
||||
nextTokenKind = is(TokenKind.EQ_OP, TokenKind.NE_OP);
|
||||
while (operatorTokenKind != null) {
|
||||
final Expression right = parseExprEquality();
|
||||
left = new BinaryImpl(left, tokenToBinaryOperator.get(operatorTokenKind), right);
|
||||
operatorTokenKind = ParserHelper.next(tokenizer, TokenKind.EqualsOperator, TokenKind.NotEqualsOperator);
|
||||
}
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
private Expression parseExprRel() throws UriParserException {
|
||||
Expression left = parseExprAdd();
|
||||
|
||||
TokenKind nextTokenKind = is(TokenKind.GT_OP, TokenKind.GE_OP, TokenKind.LT_OP, TokenKind.LE_OP);
|
||||
TokenKind operatorTokenKind = ParserHelper.next(tokenizer,
|
||||
TokenKind.GreaterThanOperator, TokenKind.GreaterThanOrEqualsOperator,
|
||||
TokenKind.LessThanOperator, TokenKind.LessThanOrEqualsOperator);
|
||||
// Null for everything other than GT or GE or LT or LE
|
||||
while (nextTokenKind != null) {
|
||||
tokenizer.getText();
|
||||
|
||||
Expression right = parseExprAdd();
|
||||
left = new BinaryImpl(left, tokenToBinaryOperator.get(nextTokenKind), right);
|
||||
nextTokenKind = is(TokenKind.GT_OP, TokenKind.GE_OP, TokenKind.LT_OP, TokenKind.LE_OP);
|
||||
while (operatorTokenKind != null) {
|
||||
final Expression right = parseExprAdd();
|
||||
left = new BinaryImpl(left, tokenToBinaryOperator.get(operatorTokenKind), right);
|
||||
operatorTokenKind = ParserHelper.next(tokenizer,
|
||||
TokenKind.GreaterThanOperator, TokenKind.GreaterThanOrEqualsOperator,
|
||||
TokenKind.LessThanOperator, TokenKind.LessThanOrEqualsOperator);
|
||||
}
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
private Expression parseExprAdd() throws UriParserException {
|
||||
Expression left = parseExprMul();
|
||||
|
||||
TokenKind nextTokenKind = is(TokenKind.ADD_OP, TokenKind.SUB_OP);
|
||||
TokenKind operatorTokenKind = ParserHelper.next(tokenizer, TokenKind.AddOperator, TokenKind.SubOperator);
|
||||
// Null for everything other than ADD or SUB
|
||||
while (nextTokenKind != null) {
|
||||
tokenizer.getText();
|
||||
|
||||
Expression right = parseExprMul();
|
||||
left = new BinaryImpl(left, tokenToBinaryOperator.get(nextTokenKind), right);
|
||||
nextTokenKind = is(TokenKind.ADD_OP, TokenKind.SUB_OP);
|
||||
while (operatorTokenKind != null) {
|
||||
final Expression right = parseExprMul();
|
||||
left = new BinaryImpl(left, tokenToBinaryOperator.get(operatorTokenKind), right);
|
||||
operatorTokenKind = ParserHelper.next(tokenizer, TokenKind.AddOperator, TokenKind.SubOperator);
|
||||
}
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
private Expression parseExprMul() throws UriParserException {
|
||||
Expression left = parseExprUnary();
|
||||
|
||||
TokenKind nextTokenKind = is(TokenKind.MUL_OP, TokenKind.DIV_OP, TokenKind.MOD_OP);
|
||||
TokenKind operatorTokenKind = ParserHelper.next(tokenizer,
|
||||
TokenKind.MulOperator, TokenKind.DivOperator, TokenKind.ModOperator);
|
||||
// Null for everything other than MUL or DIV or MOD
|
||||
while (nextTokenKind != null) {
|
||||
tokenizer.getText();
|
||||
|
||||
Expression right = parseExprUnary();
|
||||
left = new BinaryImpl(left, tokenToBinaryOperator.get(nextTokenKind), right);
|
||||
nextTokenKind = is(TokenKind.MUL_OP, TokenKind.DIV_OP, TokenKind.MOD_OP);
|
||||
while (operatorTokenKind != null) {
|
||||
final Expression right = parseExprUnary();
|
||||
left = new BinaryImpl(left, tokenToBinaryOperator.get(operatorTokenKind), right);
|
||||
operatorTokenKind = ParserHelper.next(tokenizer,
|
||||
TokenKind.MulOperator, TokenKind.DivOperator, TokenKind.ModOperator);
|
||||
}
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
private Expression parseExprUnary() throws UriParserException {
|
||||
Expression left = null;
|
||||
TokenKind nextTokenKind = is(TokenKind.MINUS, TokenKind.NOT);
|
||||
TokenKind operatorTokenKind = ParserHelper.next(tokenizer, TokenKind.MINUS, TokenKind.NotOperator);
|
||||
// Null for everything other than - or NOT
|
||||
while (nextTokenKind != null) {
|
||||
tokenizer.getText();
|
||||
|
||||
Expression exp = parseExprValue();
|
||||
left = new UnaryImpl(tokenToUnaryOperator.get(nextTokenKind), exp);
|
||||
nextTokenKind = is(TokenKind.MINUS, TokenKind.NOT);
|
||||
while (operatorTokenKind != null) {
|
||||
final Expression expression = parseExprValue();
|
||||
left = new UnaryImpl(tokenToUnaryOperator.get(operatorTokenKind), expression);
|
||||
operatorTokenKind = ParserHelper.next(tokenizer, TokenKind.MINUS, TokenKind.NotOperator);
|
||||
}
|
||||
|
||||
if (left == null) {
|
||||
left = parseExprValue();
|
||||
}
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
private Expression parseExprValue() throws UriParserException {
|
||||
if (is(TokenKind.OPEN) != null) {
|
||||
tokenizer.getText();
|
||||
Expression exp = parseExpression();
|
||||
require(TokenKind.CLOSE);
|
||||
return exp;
|
||||
if (tokenizer.next(TokenKind.OPEN)) {
|
||||
final Expression expression = parseExpression();
|
||||
ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
|
||||
return expression;
|
||||
}
|
||||
|
||||
if (is(TokenKind.ParameterAlias) != null) {
|
||||
if (tokenizer.next(TokenKind.ParameterAliasName)) {
|
||||
return new AliasImpl(tokenizer.getText());
|
||||
}
|
||||
|
||||
if (is(TokenKind.RootExpr) != null) {
|
||||
tokenizer.getText();
|
||||
// TODO: Consume $root Expression.
|
||||
if (tokenizer.next(TokenKind.jsonArrayOrObject)) {
|
||||
// TODO: Can the type be determined?
|
||||
return new LiteralImpl(tokenizer.getText(), null);
|
||||
}
|
||||
|
||||
TokenKind nextPrimitive = isPrimitive();
|
||||
if (tokenizer.next(TokenKind.ROOT)) {
|
||||
// TODO: Consume $root expression.
|
||||
}
|
||||
|
||||
if (tokenizer.next(TokenKind.IT)) {
|
||||
// TODO: Consume $it expression.
|
||||
}
|
||||
|
||||
if (tokenizer.next(TokenKind.QualifiedName)) {
|
||||
// TODO: Consume typecast or bound-function expression.
|
||||
}
|
||||
|
||||
TokenKind nextPrimitive = ParserHelper.nextPrimitive(tokenizer);
|
||||
if (nextPrimitive != null) {
|
||||
EdmPrimitiveTypeKind primitiveTypeKind = tokenToPrimitiveType.get(nextPrimitive);
|
||||
final EdmPrimitiveTypeKind primitiveTypeKind = tokenToPrimitiveType.get(nextPrimitive);
|
||||
EdmPrimitiveType type;
|
||||
if (primitiveTypeKind == null) {
|
||||
if (nextPrimitive == TokenKind.PrimitiveEnumValue) {
|
||||
if (nextPrimitive == TokenKind.EnumValue) {
|
||||
// TODO: Get enum type.
|
||||
type = null;
|
||||
} else {
|
||||
|
@ -281,22 +273,16 @@ public class ExpressionParser {
|
|||
return new LiteralImpl(tokenizer.getText(), type);
|
||||
}
|
||||
|
||||
TokenKind nextMethod = isMethod();
|
||||
TokenKind nextMethod = nextMethod();
|
||||
if (nextMethod != null) {
|
||||
MethodKind methodKind = tokenToMethod.get(nextMethod);
|
||||
List<Expression> parameters = new ArrayList<Expression>();
|
||||
// Consume Method name.
|
||||
tokenizer.getText();
|
||||
if (is(TokenKind.CLOSE) != null) {
|
||||
// Consume closing parenthesis.
|
||||
tokenizer.getText();
|
||||
} else {
|
||||
parameters.add(parseExpression());
|
||||
while (is(TokenKind.COMMA) != null) {
|
||||
tokenizer.getText();
|
||||
// The method token text includes the opening parenthesis!
|
||||
if (!tokenizer.next(TokenKind.CLOSE)) {
|
||||
do {
|
||||
parameters.add(parseExpression());
|
||||
}
|
||||
require(TokenKind.CLOSE);
|
||||
} while (tokenizer.next(TokenKind.COMMA));
|
||||
ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
|
||||
}
|
||||
|
||||
MethodImpl methodImpl = new MethodImpl(methodKind, parameters);
|
||||
|
@ -305,6 +291,10 @@ public class ExpressionParser {
|
|||
return methodImpl;
|
||||
}
|
||||
|
||||
if (tokenizer.next(TokenKind.ODataIdentifier)) {
|
||||
// TODO: Consume property-path or lambda-variable expression.
|
||||
}
|
||||
|
||||
throw new UriParserSyntaxException("Unexpected token", UriParserSyntaxException.MessageKeys.SYNTAX);
|
||||
}
|
||||
|
||||
|
@ -356,7 +346,7 @@ public class ExpressionParser {
|
|||
case NOW:
|
||||
case MAXDATETIME:
|
||||
case MINDATETIME:
|
||||
if (size != 0) {
|
||||
if (size > 0) {
|
||||
throw new UriParserSemanticException("The method '" + method.getMethod() + "' must have no parameters.",
|
||||
null); // TODO: message key
|
||||
}
|
||||
|
@ -384,192 +374,39 @@ public class ExpressionParser {
|
|||
}
|
||||
}
|
||||
|
||||
private String require(TokenKind required) throws UriParserException {
|
||||
if (is(required) == null) {
|
||||
throw new UriParserSyntaxException("Required token: " + required,
|
||||
UriParserSyntaxException.MessageKeys.SYNTAX);
|
||||
}
|
||||
return tokenizer.getText();
|
||||
private TokenKind nextMethod() {
|
||||
return ParserHelper.next(tokenizer,
|
||||
TokenKind.CastMethod,
|
||||
TokenKind.CeilingMethod,
|
||||
TokenKind.ConcatMethod,
|
||||
TokenKind.ContainsMethod,
|
||||
TokenKind.DateMethod,
|
||||
TokenKind.DayMethod,
|
||||
TokenKind.EndswithMethod,
|
||||
TokenKind.FloorMethod,
|
||||
TokenKind.FractionalsecondsMethod,
|
||||
TokenKind.GeoDistanceMethod,
|
||||
TokenKind.GeoIntersectsMethod,
|
||||
TokenKind.GeoLengthMethod,
|
||||
TokenKind.HourMethod,
|
||||
TokenKind.IndexofMethod,
|
||||
TokenKind.IsofMethod,
|
||||
TokenKind.LengthMethod,
|
||||
TokenKind.MaxdatetimeMethod,
|
||||
TokenKind.MindatetimeMethod,
|
||||
TokenKind.MinuteMethod,
|
||||
TokenKind.MonthMethod,
|
||||
TokenKind.NowMethod,
|
||||
TokenKind.RoundMethod,
|
||||
TokenKind.SecondMethod,
|
||||
TokenKind.StartswithMethod,
|
||||
TokenKind.SubstringMethod,
|
||||
TokenKind.TimeMethod,
|
||||
TokenKind.TolowerMethod,
|
||||
TokenKind.TotaloffsetminutesMethod,
|
||||
TokenKind.TotalsecondsMethod,
|
||||
TokenKind.ToupperMethod,
|
||||
TokenKind.TrimMethod,
|
||||
TokenKind.YearMethod);
|
||||
}
|
||||
|
||||
private TokenKind is(TokenKind... kind) {
|
||||
for (int i = 0; i < kind.length; i++) {
|
||||
if (tokenizer.next(kind[i])) {
|
||||
return kind[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private TokenKind isMethod() {
|
||||
return is(TokenKind.Cast,
|
||||
TokenKind.Ceiling,
|
||||
TokenKind.Concat,
|
||||
TokenKind.Contains,
|
||||
TokenKind.Date,
|
||||
TokenKind.Day,
|
||||
TokenKind.Endswith,
|
||||
TokenKind.Floor,
|
||||
TokenKind.Fractionalseconds,
|
||||
TokenKind.GeoDistance,
|
||||
TokenKind.GeoIntersects,
|
||||
TokenKind.GeoLength,
|
||||
TokenKind.Hour,
|
||||
TokenKind.Indexof,
|
||||
TokenKind.Isof,
|
||||
TokenKind.Length,
|
||||
TokenKind.Maxdatetime,
|
||||
TokenKind.Mindatetime,
|
||||
TokenKind.Minute,
|
||||
TokenKind.Month,
|
||||
TokenKind.Now,
|
||||
TokenKind.Round,
|
||||
TokenKind.Second,
|
||||
TokenKind.Startswith,
|
||||
TokenKind.Substring,
|
||||
TokenKind.Time,
|
||||
TokenKind.Tolower,
|
||||
TokenKind.Totaloffsetminutes,
|
||||
TokenKind.Totalseconds,
|
||||
TokenKind.Toupper,
|
||||
TokenKind.Trim,
|
||||
TokenKind.Year);
|
||||
}
|
||||
|
||||
private TokenKind isPrimitive() {
|
||||
return is(TokenKind.PrimitiveNullValue,
|
||||
TokenKind.PrimitiveBooleanValue,
|
||||
TokenKind.PrimitiveStringValue,
|
||||
|
||||
// The order of the next seven expressions is important in order to avoid
|
||||
// finding partly parsed tokens (counter-intuitive as it may be, even a GUID may start with digits ...).
|
||||
TokenKind.PrimitiveDoubleValue,
|
||||
TokenKind.PrimitiveDecimalValue,
|
||||
TokenKind.PrimitiveGuidValue,
|
||||
TokenKind.PrimitiveDateTimeOffsetValue,
|
||||
TokenKind.PrimitiveDateValue,
|
||||
TokenKind.PrimitiveTimeOfDayValue,
|
||||
TokenKind.PrimitiveIntegerValue,
|
||||
TokenKind.PrimitiveDurationValue,
|
||||
TokenKind.PrimitiveBinaryValue,
|
||||
TokenKind.PrimitiveEnumValue);
|
||||
}
|
||||
|
||||
public enum TokenKind {
|
||||
// BINARY
|
||||
OR_OP,
|
||||
AND_OP,
|
||||
|
||||
EQ_OP,
|
||||
NE_OP,
|
||||
|
||||
GT_OP,
|
||||
GE_OP,
|
||||
LT_OP,
|
||||
LE_OP,
|
||||
|
||||
ADD_OP,
|
||||
SUB_OP,
|
||||
|
||||
MUL_OP,
|
||||
DIV_OP,
|
||||
MOD_OP,
|
||||
|
||||
MINUS,
|
||||
NOT,
|
||||
|
||||
// Grouping
|
||||
OPEN,
|
||||
CLOSE,
|
||||
|
||||
// PrimitiveValues
|
||||
PrimitiveNullValue,
|
||||
PrimitiveBooleanValue,
|
||||
|
||||
PrimitiveStringValue,
|
||||
PrimitiveIntegerValue,
|
||||
PrimitiveGuidValue,
|
||||
PrimitiveDateValue,
|
||||
PrimitiveDateTimeOffsetValue,
|
||||
PrimitiveTimeOfDayValue,
|
||||
PrimitiveDecimalValue,
|
||||
PrimitiveDoubleValue,
|
||||
PrimitiveDurationValue,
|
||||
PrimitiveBinaryValue,
|
||||
PrimitiveEnumValue,
|
||||
|
||||
// ExpressionValues
|
||||
ParameterAlias,
|
||||
ArrayOrObject,
|
||||
RootExpr,
|
||||
IT,
|
||||
|
||||
// BuiltInMethods
|
||||
Cast,
|
||||
Ceiling,
|
||||
Concat,
|
||||
Contains,
|
||||
Date,
|
||||
Day,
|
||||
Endswith,
|
||||
Floor,
|
||||
Fractionalseconds,
|
||||
GeoDistance,
|
||||
GeoIntersects,
|
||||
GeoLength,
|
||||
Hour,
|
||||
Indexof,
|
||||
Isof,
|
||||
Length,
|
||||
Maxdatetime,
|
||||
Mindatetime,
|
||||
Minute,
|
||||
Month,
|
||||
Now,
|
||||
Round,
|
||||
Second,
|
||||
Startswith,
|
||||
Substring,
|
||||
Time,
|
||||
Tolower,
|
||||
Totaloffsetminutes,
|
||||
Totalseconds,
|
||||
Toupper,
|
||||
Trim,
|
||||
Year,
|
||||
COMMA
|
||||
}
|
||||
|
||||
public static class Token {
|
||||
TokenKind kind;
|
||||
String text;
|
||||
|
||||
public Token(TokenKind kind, String text) {
|
||||
this.kind = kind;
|
||||
this.text = text;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Tokenizer {
|
||||
private List<Token> tokens;
|
||||
int counter = 0;
|
||||
|
||||
public Tokenizer(List<Token> tokens) {
|
||||
this.tokens = tokens;
|
||||
}
|
||||
|
||||
public boolean next(TokenKind expectedKind) {
|
||||
if (counter < tokens.size() && expectedKind == tokens.get(counter).kind) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
String text = tokens.get(counter).text;
|
||||
counter++;
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -208,6 +208,14 @@ public class Parser {
|
|||
(UriParserException) e.getCause() :
|
||||
new UriParserSyntaxException("Syntax error", e, UriParserSyntaxException.MessageKeys.SYNTAX);
|
||||
}
|
||||
// UriTokenizer filterTokenizer = new UriTokenizer(optionValue);
|
||||
// systemOption = new FilterOptionImpl().setExpression(
|
||||
// new ExpressionParser().parse(filterTokenizer));
|
||||
// if (!filterTokenizer.next(TokenKind.EOF)) {
|
||||
// throw new UriParserSyntaxException("Illegal value of $filter option!",
|
||||
// UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION,
|
||||
// optionName, optionValue);
|
||||
// }
|
||||
|
||||
} else if (optionName.equals(SystemQueryOptionKind.FORMAT.toString())) {
|
||||
FormatOptionImpl formatOption = new FormatOptionImpl();
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.olingo.server.core.uri.parser;
|
||||
|
||||
import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind;
|
||||
|
||||
public class ParserHelper {
|
||||
|
||||
public static void requireNext(UriTokenizer tokenizer, final TokenKind required) throws UriParserException {
|
||||
if (!tokenizer.next(required)) {
|
||||
throw new UriParserSyntaxException("Expected token '" + required.toString() + "' not found.",
|
||||
UriParserSyntaxException.MessageKeys.SYNTAX);
|
||||
}
|
||||
}
|
||||
|
||||
public static void requireTokenEnd(UriTokenizer tokenizer) throws UriParserException {
|
||||
requireNext(tokenizer, TokenKind.EOF);
|
||||
}
|
||||
|
||||
public static TokenKind next(UriTokenizer tokenizer, final TokenKind... kind) {
|
||||
for (int i = 0; i < kind.length; i++) {
|
||||
if (tokenizer.next(kind[i])) {
|
||||
return kind[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static TokenKind nextPrimitive(UriTokenizer tokenizer) {
|
||||
return next(tokenizer,
|
||||
TokenKind.NULL,
|
||||
TokenKind.BooleanValue,
|
||||
TokenKind.StringValue,
|
||||
|
||||
// The order of the next seven expressions is important in order to avoid
|
||||
// finding partly parsed tokens (counter-intuitive as it may be, even a GUID may start with digits ...).
|
||||
TokenKind.DoubleValue,
|
||||
TokenKind.DecimalValue,
|
||||
TokenKind.GuidValue,
|
||||
TokenKind.DateTimeOffsetValue,
|
||||
TokenKind.DateValue,
|
||||
TokenKind.TimeOfDayValue,
|
||||
TokenKind.IntegerValue,
|
||||
|
||||
TokenKind.DurationValue,
|
||||
TokenKind.BinaryValue,
|
||||
TokenKind.EnumValue);
|
||||
}
|
||||
}
|
|
@ -115,9 +115,9 @@ public class ResourcePathParser {
|
|||
public UriInfoImpl parseDollarEntityTypeCast(final String pathSegment) throws UriParserException {
|
||||
UriInfoImpl uriInfo = new UriInfoImpl().setKind(UriInfoKind.entityId);
|
||||
tokenizer = new UriTokenizer(pathSegment);
|
||||
requireNext(TokenKind.QualifiedName);
|
||||
ParserHelper.requireNext(tokenizer, TokenKind.QualifiedName);
|
||||
final String name = tokenizer.getText();
|
||||
requireTokenEnd();
|
||||
ParserHelper.requireTokenEnd(tokenizer);
|
||||
final EdmEntityType type = edm.getEntityType(new FullQualifiedName(name));
|
||||
if (type == null) {
|
||||
throw new UriParserSemanticException("Type '" + name + "' not found.",
|
||||
|
@ -131,11 +131,11 @@ public class ResourcePathParser {
|
|||
public UriInfoImpl parseCrossjoinSegment(final String pathSegment) throws UriParserException {
|
||||
UriInfoImpl uriInfo = new UriInfoImpl().setKind(UriInfoKind.crossjoin);
|
||||
tokenizer = new UriTokenizer(pathSegment);
|
||||
requireNext(TokenKind.CROSSJOIN);
|
||||
requireNext(TokenKind.OPEN);
|
||||
ParserHelper.requireNext(tokenizer, TokenKind.CROSSJOIN);
|
||||
ParserHelper.requireNext(tokenizer, TokenKind.OPEN);
|
||||
// At least one entity-set name is mandatory. Try to fetch all.
|
||||
do {
|
||||
requireNext(TokenKind.ODataIdentifier);
|
||||
ParserHelper.requireNext(tokenizer, TokenKind.ODataIdentifier);
|
||||
final String name = tokenizer.getText();
|
||||
final EdmEntitySet edmEntitySet = edmEntityContainer.getEntitySet(name);
|
||||
if (edmEntitySet == null) {
|
||||
|
@ -145,13 +145,13 @@ public class ResourcePathParser {
|
|||
uriInfo.addEntitySetName(name);
|
||||
}
|
||||
} while (tokenizer.next(TokenKind.COMMA));
|
||||
requireNext(TokenKind.CLOSE);
|
||||
requireTokenEnd();
|
||||
ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
|
||||
ParserHelper.requireTokenEnd(tokenizer);
|
||||
return uriInfo;
|
||||
}
|
||||
|
||||
private UriResource ref(final UriResource previous) throws UriParserException {
|
||||
requireTokenEnd();
|
||||
ParserHelper.requireTokenEnd(tokenizer);
|
||||
requireTyped(previous, "$ref");
|
||||
if (((UriResourcePartTyped) previous).getType() instanceof EdmEntityType) {
|
||||
return new UriResourceRefImpl();
|
||||
|
@ -162,7 +162,7 @@ public class ResourcePathParser {
|
|||
}
|
||||
|
||||
private UriResource value(final UriResource previous) throws UriParserException {
|
||||
requireTokenEnd();
|
||||
ParserHelper.requireTokenEnd(tokenizer);
|
||||
requireTyped(previous, "$value");
|
||||
if (!((UriResourcePartTyped) previous).isCollection()) {
|
||||
return new UriResourceValueImpl();
|
||||
|
@ -173,7 +173,7 @@ public class ResourcePathParser {
|
|||
}
|
||||
|
||||
private UriResource count(final UriResource previous) throws UriParserException {
|
||||
requireTokenEnd();
|
||||
ParserHelper.requireTokenEnd(tokenizer);
|
||||
requireTyped(previous, "$count");
|
||||
if (((UriResourcePartTyped) previous).isCollection()) {
|
||||
return new UriResourceCountImpl();
|
||||
|
@ -195,19 +195,19 @@ public class ResourcePathParser {
|
|||
entitySetResource.setKeyPredicates(keyPredicates);
|
||||
}
|
||||
|
||||
requireTokenEnd();
|
||||
ParserHelper.requireTokenEnd(tokenizer);
|
||||
return entitySetResource;
|
||||
}
|
||||
|
||||
final EdmSingleton edmSingleton = edmEntityContainer.getSingleton(oDataIdentifier);
|
||||
if (edmSingleton != null) {
|
||||
requireTokenEnd();
|
||||
ParserHelper.requireTokenEnd(tokenizer);
|
||||
return new UriResourceSingletonImpl().setSingleton(edmSingleton);
|
||||
}
|
||||
|
||||
final EdmActionImport edmActionImport = edmEntityContainer.getActionImport(oDataIdentifier);
|
||||
if (edmActionImport != null) {
|
||||
requireTokenEnd();
|
||||
ParserHelper.requireTokenEnd(tokenizer);
|
||||
return new UriResourceActionImpl().setActionImport(edmActionImport);
|
||||
}
|
||||
|
||||
|
@ -271,7 +271,7 @@ public class ResourcePathParser {
|
|||
UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED);
|
||||
}
|
||||
}
|
||||
requireTokenEnd();
|
||||
ParserHelper.requireTokenEnd(tokenizer);
|
||||
return new UriResourceNavigationPropertyImpl()
|
||||
.setNavigationProperty(navigationProperty)
|
||||
.setKeyPredicates(keyPredicate);
|
||||
|
@ -288,7 +288,7 @@ public class ResourcePathParser {
|
|||
previousType.getFullQualifiedName(),
|
||||
previousTyped.isCollection());
|
||||
if (boundAction != null) {
|
||||
requireTokenEnd();
|
||||
ParserHelper.requireTokenEnd(tokenizer);
|
||||
return new UriResourceActionImpl().setAction(boundAction);
|
||||
}
|
||||
EdmStructuredType type = edm.getEntityType(name);
|
||||
|
@ -386,7 +386,7 @@ public class ResourcePathParser {
|
|||
edmProperty == null ? null : (EdmPrimitiveType) edmProperty.getType(),
|
||||
edmProperty == null ? false : edmProperty.isNullable())) {
|
||||
final String literalValue = tokenizer.getText();
|
||||
requireNext(TokenKind.CLOSE);
|
||||
ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
|
||||
return createUriParameter(edmProperty, edmKeyPropertyRef.getName(), literalValue);
|
||||
} else {
|
||||
throw new UriParserSemanticException("The key value is not valid.",
|
||||
|
@ -424,10 +424,10 @@ public class ResourcePathParser {
|
|||
parameterNames.add(keyPredicateName);
|
||||
hasComma = tokenizer.next(TokenKind.COMMA);
|
||||
if (hasComma) {
|
||||
requireNext(TokenKind.ODataIdentifier);
|
||||
ParserHelper.requireNext(tokenizer, TokenKind.ODataIdentifier);
|
||||
}
|
||||
} while (hasComma);
|
||||
requireNext(TokenKind.CLOSE);
|
||||
ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
|
||||
|
||||
return parameters;
|
||||
}
|
||||
|
@ -440,7 +440,7 @@ public class ResourcePathParser {
|
|||
throw new UriValidationException(keyPredicateName + " is not a valid key property name.",
|
||||
UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, keyPredicateName);
|
||||
}
|
||||
requireNext(TokenKind.EQ);
|
||||
ParserHelper.requireNext(tokenizer, TokenKind.EQ);
|
||||
if (tokenizer.next(TokenKind.COMMA) || tokenizer.next(TokenKind.CLOSE) || tokenizer.next(TokenKind.EOF)) {
|
||||
throw new UriParserSyntaxException("Key value expected.", UriParserSyntaxException.MessageKeys.SYNTAX);
|
||||
}
|
||||
|
@ -512,7 +512,7 @@ public class ResourcePathParser {
|
|||
}
|
||||
((UriResourceTypedImpl) previousTyped).setTypeFilter(type);
|
||||
}
|
||||
requireTokenEnd();
|
||||
ParserHelper.requireTokenEnd(tokenizer);
|
||||
return null;
|
||||
} else {
|
||||
throw new UriParserSemanticException(
|
||||
|
@ -572,53 +572,42 @@ public class ResourcePathParser {
|
|||
UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED);
|
||||
}
|
||||
}
|
||||
requireTokenEnd();
|
||||
ParserHelper.requireTokenEnd(tokenizer);
|
||||
return resource;
|
||||
}
|
||||
|
||||
private List<UriParameter> functionParameters() throws UriParserException {
|
||||
List<UriParameter> parameters = new ArrayList<UriParameter>();
|
||||
requireNext(TokenKind.OPEN);
|
||||
ParserHelper.requireNext(tokenizer, TokenKind.OPEN);
|
||||
if (tokenizer.next(TokenKind.CLOSE)) {
|
||||
return parameters;
|
||||
}
|
||||
do {
|
||||
requireNext(TokenKind.ODataIdentifier);
|
||||
ParserHelper.requireNext(tokenizer, TokenKind.ODataIdentifier);
|
||||
final String name = tokenizer.getText();
|
||||
if (parameters.contains(name)) {
|
||||
throw new UriParserSemanticException("Duplicated function parameter " + name,
|
||||
UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, name);
|
||||
}
|
||||
requireNext(TokenKind.EQ);
|
||||
ParserHelper.requireNext(tokenizer, TokenKind.EQ);
|
||||
if (tokenizer.next(TokenKind.COMMA) || tokenizer.next(TokenKind.CLOSE) || tokenizer.next(TokenKind.EOF)) {
|
||||
throw new UriParserSyntaxException("Parameter value expected.", UriParserSyntaxException.MessageKeys.SYNTAX);
|
||||
}
|
||||
if (nextPrimitiveValue()) {
|
||||
if (tokenizer.next(TokenKind.ParameterAliasName)) {
|
||||
parameters.add(new UriParameterImpl().setName(name).setAlias(tokenizer.getText()));
|
||||
} else if (nextPrimitiveValue()) {
|
||||
final String literalValue = tokenizer.getText();
|
||||
UriParameterImpl parameter = new UriParameterImpl().setName(name);
|
||||
parameters.add(literalValue.startsWith("@") ?
|
||||
parameter.setAlias(literalValue) :
|
||||
parameter.setText("null".equals(literalValue) ? null : literalValue));
|
||||
parameters.add(new UriParameterImpl().setName(name)
|
||||
.setText("null".equals(literalValue) ? null : literalValue));
|
||||
} else {
|
||||
throw new UriParserSemanticException("Wrong parameter value.",
|
||||
UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, "");
|
||||
}
|
||||
} while (tokenizer.next(TokenKind.COMMA));
|
||||
requireNext(TokenKind.CLOSE);
|
||||
ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
|
||||
return parameters;
|
||||
}
|
||||
|
||||
private void requireNext(final TokenKind kind) throws UriParserException {
|
||||
if (!tokenizer.next(kind)) {
|
||||
throw new UriParserSyntaxException("Expected token '" + kind.toString() + "' not found.",
|
||||
UriParserSyntaxException.MessageKeys.SYNTAX);
|
||||
}
|
||||
}
|
||||
|
||||
private void requireTokenEnd() throws UriParserException {
|
||||
requireNext(TokenKind.EOF);
|
||||
}
|
||||
|
||||
private boolean nextPrimitiveTypeValue(final EdmPrimitiveType primitiveType, final boolean nullable) {
|
||||
final EdmPrimitiveType type = primitiveType instanceof EdmTypeDefinition ?
|
||||
((EdmTypeDefinition) primitiveType).getUnderlyingType() :
|
||||
|
@ -629,64 +618,63 @@ public class ResourcePathParser {
|
|||
return true;
|
||||
|
||||
} else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Boolean).equals(type)) {
|
||||
return tokenizer.next(TokenKind.PrimitiveBooleanValue);
|
||||
return tokenizer.next(TokenKind.BooleanValue);
|
||||
} else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.String).equals(type)) {
|
||||
return tokenizer.next(TokenKind.PrimitiveStringValue);
|
||||
return tokenizer.next(TokenKind.StringValue);
|
||||
} else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.SByte).equals(type)
|
||||
|| odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Byte).equals(type)
|
||||
|| odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int16).equals(type)
|
||||
|| odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int32).equals(type)
|
||||
|| odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int64).equals(type)) {
|
||||
return tokenizer.next(TokenKind.PrimitiveIntegerValue);
|
||||
return tokenizer.next(TokenKind.IntegerValue);
|
||||
} else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Guid).equals(type)) {
|
||||
return tokenizer.next(TokenKind.PrimitiveGuidValue);
|
||||
return tokenizer.next(TokenKind.GuidValue);
|
||||
} else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Date).equals(type)) {
|
||||
return tokenizer.next(TokenKind.PrimitiveDateValue);
|
||||
return tokenizer.next(TokenKind.DateValue);
|
||||
} else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.DateTimeOffset).equals(type)) {
|
||||
return tokenizer.next(TokenKind.PrimitiveDateTimeOffsetValue);
|
||||
return tokenizer.next(TokenKind.DateTimeOffsetValue);
|
||||
} else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.TimeOfDay).equals(type)) {
|
||||
return tokenizer.next(TokenKind.PrimitiveTimeOfDayValue);
|
||||
return tokenizer.next(TokenKind.TimeOfDayValue);
|
||||
} else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Decimal).equals(type)) {
|
||||
// The order is important.
|
||||
// A decimal value should not be parsed as integer and let the tokenizer stop at the decimal point.
|
||||
return tokenizer.next(TokenKind.PrimitiveDecimalValue)
|
||||
|| tokenizer.next(TokenKind.PrimitiveIntegerValue);
|
||||
return tokenizer.next(TokenKind.DecimalValue)
|
||||
|| tokenizer.next(TokenKind.IntegerValue);
|
||||
} else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Double).equals(type)) {
|
||||
// The order is important.
|
||||
// A floating-point value should not be parsed as decimal and let the tokenizer stop at 'E'.
|
||||
// A decimal value should not be parsed as integer and let the tokenizer stop at the decimal point.
|
||||
return tokenizer.next(TokenKind.PrimitiveDoubleValue)
|
||||
|| tokenizer.next(TokenKind.PrimitiveDecimalValue)
|
||||
|| tokenizer.next(TokenKind.PrimitiveIntegerValue);
|
||||
return tokenizer.next(TokenKind.DoubleValue)
|
||||
|| tokenizer.next(TokenKind.DecimalValue)
|
||||
|| tokenizer.next(TokenKind.IntegerValue);
|
||||
} else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Duration).equals(type)) {
|
||||
return tokenizer.next(TokenKind.PrimitiveDurationValue);
|
||||
return tokenizer.next(TokenKind.DurationValue);
|
||||
} else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Binary).equals(type)) {
|
||||
return tokenizer.next(TokenKind.PrimitiveBinaryValue);
|
||||
return tokenizer.next(TokenKind.BinaryValue);
|
||||
} else if (type.getKind() == EdmTypeKind.ENUM) {
|
||||
return tokenizer.next(TokenKind.PrimitiveEnumValue);
|
||||
return tokenizer.next(TokenKind.EnumValue);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean nextPrimitiveValue() {
|
||||
return tokenizer.next(TokenKind.ParameterAliasName)
|
||||
|| tokenizer.next(TokenKind.NULL)
|
||||
|| tokenizer.next(TokenKind.PrimitiveBooleanValue)
|
||||
|| tokenizer.next(TokenKind.PrimitiveStringValue)
|
||||
return tokenizer.next(TokenKind.NULL)
|
||||
|| tokenizer.next(TokenKind.BooleanValue)
|
||||
|| tokenizer.next(TokenKind.StringValue)
|
||||
|
||||
// The order of the next seven expressions is important in order to avoid
|
||||
// finding partly parsed tokens (counter-intuitive as it may be, even a GUID may start with digits ...).
|
||||
|| tokenizer.next(TokenKind.PrimitiveDoubleValue)
|
||||
|| tokenizer.next(TokenKind.PrimitiveDecimalValue)
|
||||
|| tokenizer.next(TokenKind.PrimitiveGuidValue)
|
||||
|| tokenizer.next(TokenKind.PrimitiveDateTimeOffsetValue)
|
||||
|| tokenizer.next(TokenKind.PrimitiveDateValue)
|
||||
|| tokenizer.next(TokenKind.PrimitiveTimeOfDayValue)
|
||||
|| tokenizer.next(TokenKind.PrimitiveIntegerValue)
|
||||
|| tokenizer.next(TokenKind.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.PrimitiveDurationValue)
|
||||
|| tokenizer.next(TokenKind.PrimitiveBinaryValue)
|
||||
|| tokenizer.next(TokenKind.PrimitiveEnumValue);
|
||||
|| tokenizer.next(TokenKind.DurationValue)
|
||||
|| tokenizer.next(TokenKind.BinaryValue)
|
||||
|| tokenizer.next(TokenKind.EnumValue);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ public class SelectParser {
|
|||
if (type.compatibleTo(referencedType)) {
|
||||
item.setTypeFilter(type);
|
||||
if (tokenizer.next(TokenKind.SLASH)) {
|
||||
requireNext(tokenizer, TokenKind.ODataIdentifier);
|
||||
ParserHelper.requireNext(tokenizer, TokenKind.ODataIdentifier);
|
||||
UriInfoImpl resource = new UriInfoImpl().setKind(UriInfoKind.resource);
|
||||
addSelectPath(tokenizer, type, resource);
|
||||
item.setResourcePath(resource);
|
||||
|
@ -105,7 +105,7 @@ public class SelectParser {
|
|||
}
|
||||
|
||||
} else {
|
||||
requireNext(tokenizer, TokenKind.ODataIdentifier);
|
||||
ParserHelper.requireNext(tokenizer, TokenKind.ODataIdentifier);
|
||||
// The namespace or its alias could be a single OData identifier.
|
||||
final FullQualifiedName allOperationsInSchema = parseAllOperationsInSchema(tokenizer);
|
||||
if (allOperationsInSchema != null) {
|
||||
|
@ -167,10 +167,10 @@ public class SelectParser {
|
|||
List<String> names = new ArrayList<String>();
|
||||
if (tokenizer.next(TokenKind.OPEN)) {
|
||||
do {
|
||||
requireNext(tokenizer, TokenKind.ODataIdentifier);
|
||||
ParserHelper.requireNext(tokenizer, TokenKind.ODataIdentifier);
|
||||
names.add(tokenizer.getText());
|
||||
} while (tokenizer.next(TokenKind.COMMA));
|
||||
requireNext(tokenizer, TokenKind.CLOSE);
|
||||
ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
@ -231,11 +231,4 @@ public class SelectParser {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void requireNext(UriTokenizer tokenizer, final TokenKind kind) throws UriParserSyntaxException {
|
||||
if (!tokenizer.next(kind)) {
|
||||
throw new UriParserSyntaxException("Illegal $select expression.",
|
||||
UriParserSyntaxException.MessageKeys.SYNTAX);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,8 @@ package org.apache.olingo.server.core.uri.parser;
|
|||
* Since only the index is "moved", backing out while parsing a token is easy and used throughout.
|
||||
* There is intentionally no method to push back tokens (although it would be easy to add such a method)
|
||||
* because this tokenizer should behave like a classical token-consuming tokenizer.</p>
|
||||
* <p>Whitespace is not an extra token but consumed with the tokens that require whitespace.
|
||||
* Optional whitespace is not supported.</p>
|
||||
*/
|
||||
public class UriTokenizer {
|
||||
|
||||
|
@ -35,6 +37,9 @@ public class UriTokenizer {
|
|||
VALUE,
|
||||
COUNT,
|
||||
CROSSJOIN,
|
||||
ROOT,
|
||||
IT,
|
||||
|
||||
OPEN,
|
||||
CLOSE,
|
||||
COMMA,
|
||||
|
@ -44,6 +49,7 @@ public class UriTokenizer {
|
|||
EQ,
|
||||
STAR,
|
||||
PLUS,
|
||||
MINUS,
|
||||
NULL,
|
||||
|
||||
// variable-value tokens (convention: mixed case)
|
||||
|
@ -51,20 +57,68 @@ public class UriTokenizer {
|
|||
QualifiedName,
|
||||
ParameterAliasName,
|
||||
|
||||
PrimitiveBooleanValue,
|
||||
PrimitiveStringValue,
|
||||
PrimitiveIntegerValue,
|
||||
PrimitiveGuidValue,
|
||||
PrimitiveDateValue,
|
||||
PrimitiveDateTimeOffsetValue,
|
||||
PrimitiveTimeOfDayValue,
|
||||
PrimitiveDecimalValue,
|
||||
PrimitiveDoubleValue,
|
||||
PrimitiveDurationValue,
|
||||
PrimitiveBinaryValue,
|
||||
PrimitiveEnumValue,
|
||||
BooleanValue,
|
||||
StringValue,
|
||||
IntegerValue,
|
||||
GuidValue,
|
||||
DateValue,
|
||||
DateTimeOffsetValue,
|
||||
TimeOfDayValue,
|
||||
DecimalValue,
|
||||
DoubleValue,
|
||||
DurationValue,
|
||||
BinaryValue,
|
||||
EnumValue,
|
||||
|
||||
jsonArrayOrObject
|
||||
jsonArrayOrObject,
|
||||
|
||||
OrOperator,
|
||||
AndOperator,
|
||||
EqualsOperator,
|
||||
NotEqualsOperator,
|
||||
GreaterThanOperator,
|
||||
GreaterThanOrEqualsOperator,
|
||||
LessThanOperator,
|
||||
LessThanOrEqualsOperator,
|
||||
AddOperator,
|
||||
SubOperator,
|
||||
MulOperator,
|
||||
DivOperator,
|
||||
ModOperator,
|
||||
NotOperator,
|
||||
|
||||
CastMethod,
|
||||
CeilingMethod,
|
||||
ConcatMethod,
|
||||
ContainsMethod,
|
||||
DateMethod,
|
||||
DayMethod,
|
||||
EndswithMethod,
|
||||
FloorMethod,
|
||||
FractionalsecondsMethod,
|
||||
GeoDistanceMethod,
|
||||
GeoIntersectsMethod,
|
||||
GeoLengthMethod,
|
||||
HourMethod,
|
||||
IndexofMethod,
|
||||
IsofMethod,
|
||||
LengthMethod,
|
||||
MaxdatetimeMethod,
|
||||
MindatetimeMethod,
|
||||
MinuteMethod,
|
||||
MonthMethod,
|
||||
NowMethod,
|
||||
RoundMethod,
|
||||
SecondMethod,
|
||||
StartswithMethod,
|
||||
SubstringMethod,
|
||||
TimeMethod,
|
||||
TolowerMethod,
|
||||
TotaloffsetminutesMethod,
|
||||
TotalsecondsMethod,
|
||||
ToupperMethod,
|
||||
TrimMethod,
|
||||
YearMethod
|
||||
}
|
||||
|
||||
private final String parseString;
|
||||
|
@ -111,6 +165,13 @@ public class UriTokenizer {
|
|||
case CROSSJOIN:
|
||||
found = nextConstant("$crossjoin");
|
||||
break;
|
||||
case ROOT:
|
||||
found = nextConstant("$root");
|
||||
break;
|
||||
case IT:
|
||||
found = nextConstant("$it");
|
||||
break;
|
||||
|
||||
case OPEN:
|
||||
found = nextCharacter('(');
|
||||
break;
|
||||
|
@ -138,6 +199,9 @@ public class UriTokenizer {
|
|||
case PLUS:
|
||||
found = nextCharacter('+');
|
||||
break;
|
||||
case MINUS:
|
||||
found = nextCharacter('-');
|
||||
break;
|
||||
case NULL:
|
||||
found = nextConstant("null");
|
||||
break;
|
||||
|
@ -157,47 +221,189 @@ public class UriTokenizer {
|
|||
break;
|
||||
|
||||
// Primitive Values
|
||||
case PrimitiveBooleanValue:
|
||||
case BooleanValue:
|
||||
found = nextBooleanValue();
|
||||
break;
|
||||
case PrimitiveStringValue:
|
||||
case StringValue:
|
||||
found = nextStringValue();
|
||||
break;
|
||||
case PrimitiveIntegerValue:
|
||||
case IntegerValue:
|
||||
found = nextIntegerValue(true);
|
||||
break;
|
||||
case PrimitiveGuidValue:
|
||||
case GuidValue:
|
||||
found = nextGuidValue();
|
||||
break;
|
||||
case PrimitiveDateValue:
|
||||
case DateValue:
|
||||
found = nextDateValue();
|
||||
break;
|
||||
case PrimitiveDateTimeOffsetValue:
|
||||
case DateTimeOffsetValue:
|
||||
found = nextDateTimeOffsetValue();
|
||||
break;
|
||||
case PrimitiveTimeOfDayValue:
|
||||
case TimeOfDayValue:
|
||||
found = nextTimeOfDayValue();
|
||||
break;
|
||||
case PrimitiveDecimalValue:
|
||||
case DecimalValue:
|
||||
found = nextDecimalValue();
|
||||
break;
|
||||
case PrimitiveDoubleValue:
|
||||
case DoubleValue:
|
||||
found = nextDoubleValue();
|
||||
break;
|
||||
case PrimitiveDurationValue:
|
||||
case DurationValue:
|
||||
found = nextDurationValue();
|
||||
break;
|
||||
case PrimitiveBinaryValue:
|
||||
case BinaryValue:
|
||||
found = nextBinaryValue();
|
||||
break;
|
||||
case PrimitiveEnumValue:
|
||||
case EnumValue:
|
||||
found = nextEnumValue();
|
||||
break;
|
||||
|
||||
// Primitive Values
|
||||
// Complex or Collection Value
|
||||
case jsonArrayOrObject:
|
||||
found = nextJsonArrayOrObject();
|
||||
break;
|
||||
|
||||
// Operators
|
||||
case OrOperator:
|
||||
found = nextBinaryOperator("or");
|
||||
break;
|
||||
case AndOperator:
|
||||
found = nextBinaryOperator("and");
|
||||
break;
|
||||
case EqualsOperator:
|
||||
found = nextBinaryOperator("eq");
|
||||
break;
|
||||
case NotEqualsOperator:
|
||||
found = nextBinaryOperator("ne");
|
||||
break;
|
||||
case GreaterThanOperator:
|
||||
found = nextBinaryOperator("gt");
|
||||
break;
|
||||
case GreaterThanOrEqualsOperator:
|
||||
found = nextBinaryOperator("ge");
|
||||
break;
|
||||
case LessThanOperator:
|
||||
found = nextBinaryOperator("lt");
|
||||
break;
|
||||
case LessThanOrEqualsOperator:
|
||||
found = nextBinaryOperator("le");
|
||||
break;
|
||||
case AddOperator:
|
||||
found = nextBinaryOperator("add");
|
||||
break;
|
||||
case SubOperator:
|
||||
found = nextBinaryOperator("sub");
|
||||
break;
|
||||
case MulOperator:
|
||||
found = nextBinaryOperator("mul");
|
||||
break;
|
||||
case DivOperator:
|
||||
found = nextBinaryOperator("div");
|
||||
break;
|
||||
case ModOperator:
|
||||
found = nextBinaryOperator("mod");
|
||||
break;
|
||||
case NotOperator:
|
||||
found = nextConstant("not") && nextWhitespace();
|
||||
break;
|
||||
|
||||
// Methods
|
||||
case CastMethod:
|
||||
found = nextMethod("cast");
|
||||
break;
|
||||
case CeilingMethod:
|
||||
found = nextMethod("ceiling");
|
||||
break;
|
||||
case ConcatMethod:
|
||||
found = nextMethod("concat");
|
||||
break;
|
||||
case ContainsMethod:
|
||||
found = nextMethod("contains");
|
||||
break;
|
||||
case DateMethod:
|
||||
found = nextMethod("date");
|
||||
break;
|
||||
case DayMethod:
|
||||
found = nextMethod("day");
|
||||
break;
|
||||
case EndswithMethod:
|
||||
found = nextMethod("endswith");
|
||||
break;
|
||||
case FloorMethod:
|
||||
found = nextMethod("floor");
|
||||
break;
|
||||
case FractionalsecondsMethod:
|
||||
found = nextMethod("fractionalseconds");
|
||||
break;
|
||||
case GeoDistanceMethod:
|
||||
found = nextMethod("geo.distance");
|
||||
break;
|
||||
case GeoIntersectsMethod:
|
||||
found = nextMethod("geo.intersects");
|
||||
break;
|
||||
case GeoLengthMethod:
|
||||
found = nextMethod("geo.length");
|
||||
break;
|
||||
case HourMethod:
|
||||
found = nextMethod("hour");
|
||||
break;
|
||||
case IndexofMethod:
|
||||
found = nextMethod("indexof");
|
||||
break;
|
||||
case IsofMethod:
|
||||
found = nextMethod("isof");
|
||||
break;
|
||||
case LengthMethod:
|
||||
found = nextMethod("length");
|
||||
break;
|
||||
case MaxdatetimeMethod:
|
||||
found = nextMethod("maxdatetime");
|
||||
break;
|
||||
case MindatetimeMethod:
|
||||
found = nextMethod("mindatetime");
|
||||
break;
|
||||
case MinuteMethod:
|
||||
found = nextMethod("minute");
|
||||
break;
|
||||
case MonthMethod:
|
||||
found = nextMethod("month");
|
||||
break;
|
||||
case NowMethod:
|
||||
found = nextMethod("now");
|
||||
break;
|
||||
case RoundMethod:
|
||||
found = nextMethod("round");
|
||||
break;
|
||||
case SecondMethod:
|
||||
found = nextMethod("second");
|
||||
break;
|
||||
case StartswithMethod:
|
||||
found = nextMethod("startswith");
|
||||
break;
|
||||
case SubstringMethod:
|
||||
found = nextMethod("substring");
|
||||
break;
|
||||
case TimeMethod:
|
||||
found = nextMethod("time");
|
||||
break;
|
||||
case TolowerMethod:
|
||||
found = nextMethod("tolower");
|
||||
break;
|
||||
case TotaloffsetminutesMethod:
|
||||
found = nextMethod("totaloffsetminutes");
|
||||
break;
|
||||
case TotalsecondsMethod:
|
||||
found = nextMethod("totalseconds");
|
||||
break;
|
||||
case ToupperMethod:
|
||||
found = nextMethod("toupper");
|
||||
break;
|
||||
case TrimMethod:
|
||||
found = nextMethod("trim");
|
||||
break;
|
||||
case YearMethod:
|
||||
found = nextMethod("year");
|
||||
break;
|
||||
}
|
||||
|
||||
if (found) {
|
||||
|
@ -300,6 +506,37 @@ public class UriTokenizer {
|
|||
return nextCharacter('+') || nextCharacter('-');
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves past whitespace (space or horizontal tabulator) characters if found;
|
||||
* otherwise leaves the index unchanged.
|
||||
* @return whether whitespace characters have been found at the current index
|
||||
*/
|
||||
private boolean nextWhitespace() {
|
||||
int count = 0;
|
||||
while (nextCharacter(' ') || nextCharacter('\t')) {
|
||||
count++;
|
||||
}
|
||||
return count > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves past the given whitespace-surrounded operator constant if found;
|
||||
* otherwise leaves the index unchanged.
|
||||
* @return whether the operator has been found at the current index
|
||||
*/
|
||||
private boolean nextBinaryOperator(final String operator) {
|
||||
return nextWhitespace() && nextConstant(operator) && nextWhitespace();
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves past the given method name and its immediately following opening parenthesis if found;
|
||||
* otherwise leaves the index unchanged.
|
||||
* @return whether the method has been found at the current index
|
||||
*/
|
||||
private boolean nextMethod(final String methodName) {
|
||||
return nextConstant(methodName) && nextCharacter('(');
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves past an OData identifier if found; otherwise leaves the index unchanged.
|
||||
* @return whether an OData identifier has been found at the current index
|
||||
|
|
|
@ -53,6 +53,6 @@ public class UnaryImpl implements Unary {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{" + operator + " " + expression + '}';
|
||||
return "{" + operator.name() + " " + expression + '}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,191 +20,157 @@ package org.apache.olingo.server.core.uri.parser;
|
|||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
|
||||
import org.apache.olingo.server.core.uri.parser.ExpressionParser.Token;
|
||||
import org.apache.olingo.server.core.uri.parser.ExpressionParser.TokenKind;
|
||||
import org.apache.olingo.server.core.uri.parser.ExpressionParser.Tokenizer;
|
||||
import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ExpressionParserTest {
|
||||
|
||||
@Test
|
||||
public void equality() throws Exception {
|
||||
Expression expression = parseExpression(TokenKind.EQ_OP);
|
||||
Expression expression = parseExpression("5 eq 5");
|
||||
assertEquals("{5 EQ 5}", expression.toString());
|
||||
|
||||
expression = parseExpression(TokenKind.NE_OP);
|
||||
expression = parseExpression("5 ne 5");
|
||||
assertEquals("{5 NE 5}", expression.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void relational() throws Exception {
|
||||
Expression expression = parseExpression(TokenKind.GT_OP);
|
||||
Expression expression = parseExpression("5 gt 5");
|
||||
assertEquals("{5 GT 5}", expression.toString());
|
||||
|
||||
expression = parseExpression(TokenKind.GE_OP);
|
||||
expression = parseExpression("5 ge 5");
|
||||
assertEquals("{5 GE 5}", expression.toString());
|
||||
|
||||
expression = parseExpression(TokenKind.LT_OP);
|
||||
expression = parseExpression("5 lt 5");
|
||||
assertEquals("{5 LT 5}", expression.toString());
|
||||
|
||||
expression = parseExpression(TokenKind.LE_OP);
|
||||
expression = parseExpression("5 le 5");
|
||||
assertEquals("{5 LE 5}", expression.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void additive() throws Exception {
|
||||
Expression expression = parseExpression(TokenKind.ADD_OP);
|
||||
Expression expression = parseExpression("5 add 5");
|
||||
assertEquals("{5 ADD 5}", expression.toString());
|
||||
|
||||
expression = parseExpression(TokenKind.SUB_OP);
|
||||
expression = parseExpression("5 sub 5");
|
||||
assertEquals("{5 SUB 5}", expression.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multiplicative() throws Exception {
|
||||
Expression expression = parseExpression(TokenKind.MUL_OP);
|
||||
Expression expression = parseExpression("5 mul 5");
|
||||
assertEquals("{5 MUL 5}", expression.toString());
|
||||
|
||||
expression = parseExpression(TokenKind.DIV_OP);
|
||||
expression = parseExpression("5 div 5");
|
||||
assertEquals("{5 DIV 5}", expression.toString());
|
||||
|
||||
expression = parseExpression(TokenKind.MOD_OP);
|
||||
expression = parseExpression("5 mod 5");
|
||||
assertEquals("{5 MOD 5}", expression.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unary() throws Exception {
|
||||
ArrayList<Token> tokens = new ArrayList<Token>();
|
||||
tokens.add(new Token(TokenKind.MINUS, ""));
|
||||
tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
|
||||
Tokenizer tokenizer = new Tokenizer(tokens);
|
||||
Expression expression = new ExpressionParser().parse(tokenizer);
|
||||
assertEquals("{- 5}", expression.toString());
|
||||
Expression expression = parseExpression("-5");
|
||||
assertEquals("{MINUS 5}", expression.toString());
|
||||
|
||||
tokens = new ArrayList<Token>();
|
||||
tokens.add(new Token(TokenKind.NOT, ""));
|
||||
tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
|
||||
tokenizer = new Tokenizer(tokens);
|
||||
expression = new ExpressionParser().parse(tokenizer);
|
||||
assertEquals("{not 5}", expression.toString());
|
||||
assertEquals("{MINUS -1}", parseExpression("--1").toString());
|
||||
|
||||
expression = parseExpression("not 5");
|
||||
assertEquals("{NOT 5}", expression.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void grouping() throws Exception {
|
||||
ArrayList<Token> tokens = new ArrayList<Token>();
|
||||
tokens.add(new Token(TokenKind.MINUS, ""));
|
||||
tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
|
||||
tokens.add(new Token(TokenKind.ADD_OP, ""));
|
||||
tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
|
||||
Tokenizer tokenizer = new Tokenizer(tokens);
|
||||
Expression expression = new ExpressionParser().parse(tokenizer);
|
||||
assertEquals("{{- 5} ADD 5}", expression.toString());
|
||||
Expression expression = parseExpression("-5 add 5");
|
||||
assertEquals("{{MINUS 5} ADD 5}", expression.toString());
|
||||
|
||||
tokens = new ArrayList<Token>();
|
||||
tokens.add(new Token(TokenKind.MINUS, ""));
|
||||
tokens.add(new Token(TokenKind.OPEN, ""));
|
||||
tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
|
||||
tokens.add(new Token(TokenKind.ADD_OP, ""));
|
||||
tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
|
||||
tokens.add(new Token(TokenKind.CLOSE, ""));
|
||||
tokenizer = new Tokenizer(tokens);
|
||||
expression = new ExpressionParser().parse(tokenizer);
|
||||
assertEquals("{- {5 ADD 5}}", expression.toString());
|
||||
expression = parseExpression("-(5 add 5)");
|
||||
assertEquals("{MINUS {5 ADD 5}}", expression.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void precedence() throws Exception {
|
||||
assertEquals("{{MINUS 1} ADD {2 DIV 3}}", parseExpression("-1 add 2 div 3").toString());
|
||||
assertEquals("{true OR {{NOT false} AND true}}", parseExpression("true or not false and true").toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noParameterMethods() throws Exception {
|
||||
Expression expression = parseMethod(TokenKind.Now);
|
||||
Expression expression = parseMethod(TokenKind.NowMethod);
|
||||
assertEquals("{now []}", expression.toString());
|
||||
|
||||
expression = parseMethod(TokenKind.Maxdatetime);
|
||||
expression = parseMethod(TokenKind.MaxdatetimeMethod);
|
||||
assertEquals("{maxdatetime []}", expression.toString());
|
||||
|
||||
expression = parseMethod(TokenKind.Mindatetime);
|
||||
expression = parseMethod(TokenKind.MindatetimeMethod);
|
||||
assertEquals("{mindatetime []}", expression.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void oneParameterMethods() throws Exception {
|
||||
Expression expression = parseMethod(TokenKind.Length, TokenKind.PrimitiveStringValue);
|
||||
assertEquals("{length [String1]}", expression.toString());
|
||||
final String stringValue = "'abc'";
|
||||
final String dateValue = "1234-12-25";
|
||||
final String dateTimeOffsetValue = "1234-12-25T11:12:13.456Z";
|
||||
|
||||
expression = parseMethod(TokenKind.Tolower, TokenKind.PrimitiveStringValue);
|
||||
assertEquals("{tolower [String1]}", expression.toString());
|
||||
Expression expression = parseMethod(TokenKind.LengthMethod, stringValue);
|
||||
assertEquals("{length [" + stringValue + "]}", expression.toString());
|
||||
|
||||
expression = parseMethod(TokenKind.Toupper, TokenKind.PrimitiveStringValue);
|
||||
assertEquals("{toupper [String1]}", expression.toString());
|
||||
expression = parseMethod(TokenKind.TolowerMethod, stringValue);
|
||||
assertEquals("{tolower [" + stringValue + "]}", expression.toString());
|
||||
|
||||
expression = parseMethod(TokenKind.Trim, TokenKind.PrimitiveStringValue);
|
||||
assertEquals("{trim [String1]}", expression.toString());
|
||||
expression = parseMethod(TokenKind.ToupperMethod, stringValue);
|
||||
assertEquals("{toupper [" + stringValue + "]}", expression.toString());
|
||||
|
||||
expression = parseMethod(TokenKind.Year, TokenKind.PrimitiveDateValue);
|
||||
assertEquals("{year [Date1]}", expression.toString());
|
||||
expression = parseMethod(TokenKind.TrimMethod, stringValue);
|
||||
assertEquals("{trim [" + stringValue + "]}", expression.toString());
|
||||
|
||||
expression = parseMethod(TokenKind.Month, TokenKind.PrimitiveDateValue);
|
||||
assertEquals("{month [Date1]}", expression.toString());
|
||||
expression = parseMethod(TokenKind.YearMethod, dateValue);
|
||||
assertEquals("{year [" + dateValue + "]}", expression.toString());
|
||||
|
||||
expression = parseMethod(TokenKind.Day, TokenKind.PrimitiveDateValue);
|
||||
assertEquals("{day [Date1]}", expression.toString());
|
||||
expression = parseMethod(TokenKind.MonthMethod, dateValue);
|
||||
assertEquals("{month [" + dateValue + "]}", expression.toString());
|
||||
|
||||
expression = parseMethod(TokenKind.Hour, TokenKind.PrimitiveDateTimeOffsetValue);
|
||||
assertEquals("{hour [DateTimeOffset1]}", expression.toString());
|
||||
expression = parseMethod(TokenKind.DayMethod, dateValue);
|
||||
assertEquals("{day [" + dateValue + "]}", expression.toString());
|
||||
|
||||
expression = parseMethod(TokenKind.Minute, TokenKind.PrimitiveDateTimeOffsetValue);
|
||||
assertEquals("{minute [DateTimeOffset1]}", expression.toString());
|
||||
expression = parseMethod(TokenKind.HourMethod, dateTimeOffsetValue);
|
||||
assertEquals("{hour [" + dateTimeOffsetValue + "]}", expression.toString());
|
||||
|
||||
expression = parseMethod(TokenKind.Second, TokenKind.PrimitiveDateTimeOffsetValue);
|
||||
assertEquals("{second [DateTimeOffset1]}", expression.toString());
|
||||
expression = parseMethod(TokenKind.MinuteMethod, dateTimeOffsetValue);
|
||||
assertEquals("{minute [" + dateTimeOffsetValue + "]}", expression.toString());
|
||||
|
||||
expression = parseMethod(TokenKind.SecondMethod, dateTimeOffsetValue);
|
||||
assertEquals("{second [" + dateTimeOffsetValue + "]}", expression.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void twoParameterMethods() {
|
||||
|
||||
}
|
||||
|
||||
private Expression parseMethod(TokenKind... kind) throws UriParserException {
|
||||
ArrayList<Token> tokens = new ArrayList<Token>();
|
||||
tokens.add(new Token(kind[0], ""));
|
||||
|
||||
for (int i = 1; i < kind.length; i++) {
|
||||
String text = null;
|
||||
switch (kind[i]) {
|
||||
case PrimitiveStringValue:
|
||||
text = "String" + i;
|
||||
break;
|
||||
case PrimitiveDateValue:
|
||||
text = "Date" + i;
|
||||
break;
|
||||
case PrimitiveDateTimeOffsetValue:
|
||||
text = "DateTimeOffset" + i;
|
||||
break;
|
||||
default:
|
||||
text = "" + i;
|
||||
break;
|
||||
private Expression parseMethod(TokenKind kind, String... parameters) throws UriParserException {
|
||||
String expressionString = kind.name().substring(0, kind.name().indexOf("Method"))
|
||||
.toLowerCase(Locale.ROOT).replace("geo", "geo.") + '(';
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
if (i > 0) {
|
||||
expressionString += ',';
|
||||
}
|
||||
tokens.add(new Token(kind[i], text));
|
||||
expressionString += parameters[i];
|
||||
}
|
||||
expressionString += ')';
|
||||
|
||||
tokens.add(new Token(TokenKind.CLOSE, ""));
|
||||
Tokenizer tokenizer = new Tokenizer(tokens);
|
||||
Expression expression = new ExpressionParser().parse(tokenizer);
|
||||
Expression expression = parseExpression(expressionString);
|
||||
assertNotNull(expression);
|
||||
return expression;
|
||||
}
|
||||
|
||||
private Expression parseExpression(TokenKind operator) throws UriParserException {
|
||||
ArrayList<Token> tokens = new ArrayList<Token>();
|
||||
tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
|
||||
tokens.add(new Token(operator, ""));
|
||||
tokens.add(new Token(TokenKind.PrimitiveIntegerValue, "5"));
|
||||
Tokenizer tokenizer = new Tokenizer(tokens);
|
||||
|
||||
private Expression parseExpression(final String expressionString) throws UriParserException {
|
||||
UriTokenizer tokenizer = new UriTokenizer(expressionString);
|
||||
Expression expression = new ExpressionParser().parse(tokenizer);
|
||||
assertNotNull(expression);
|
||||
assertTrue(tokenizer.next(TokenKind.EOF));
|
||||
return expression;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,8 @@ import static org.junit.Assert.assertEquals;
|
|||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -44,6 +46,8 @@ public class UriTokenizerTest {
|
|||
assertTrue(new UriTokenizer("$value").next(TokenKind.VALUE));
|
||||
assertTrue(new UriTokenizer("$count").next(TokenKind.COUNT));
|
||||
assertTrue(new UriTokenizer("$crossjoin").next(TokenKind.CROSSJOIN));
|
||||
assertTrue(new UriTokenizer("$root").next(TokenKind.ROOT));
|
||||
assertTrue(new UriTokenizer("$it").next(TokenKind.IT));
|
||||
assertTrue(new UriTokenizer("null").next(TokenKind.NULL));
|
||||
|
||||
wrongToken(TokenKind.REF, "$ref", 'x');
|
||||
|
@ -51,19 +55,19 @@ public class UriTokenizerTest {
|
|||
|
||||
@Test
|
||||
public void sequence() {
|
||||
final UriTokenizer tokenizer = new UriTokenizer("(A=1,B=2);.*/+");
|
||||
final UriTokenizer tokenizer = new UriTokenizer("(A=1,B=2);.*/+-");
|
||||
assertTrue(tokenizer.next(TokenKind.OPEN));
|
||||
assertFalse(tokenizer.next(TokenKind.OPEN));
|
||||
assertTrue(tokenizer.next(TokenKind.ODataIdentifier));
|
||||
assertEquals("A", tokenizer.getText());
|
||||
assertTrue(tokenizer.next(TokenKind.EQ));
|
||||
assertTrue(tokenizer.next(TokenKind.PrimitiveIntegerValue));
|
||||
assertTrue(tokenizer.next(TokenKind.IntegerValue));
|
||||
assertEquals("1", tokenizer.getText());
|
||||
assertTrue(tokenizer.next(TokenKind.COMMA));
|
||||
assertTrue(tokenizer.next(TokenKind.ODataIdentifier));
|
||||
assertEquals("B", tokenizer.getText());
|
||||
assertTrue(tokenizer.next(TokenKind.EQ));
|
||||
assertTrue(tokenizer.next(TokenKind.PrimitiveIntegerValue));
|
||||
assertTrue(tokenizer.next(TokenKind.IntegerValue));
|
||||
assertEquals("2", tokenizer.getText());
|
||||
assertFalse(tokenizer.next(TokenKind.EOF));
|
||||
assertTrue(tokenizer.next(TokenKind.CLOSE));
|
||||
|
@ -72,6 +76,7 @@ public class UriTokenizerTest {
|
|||
assertTrue(tokenizer.next(TokenKind.STAR));
|
||||
assertTrue(tokenizer.next(TokenKind.SLASH));
|
||||
assertTrue(tokenizer.next(TokenKind.PLUS));
|
||||
assertTrue(tokenizer.next(TokenKind.MINUS));
|
||||
assertTrue(tokenizer.next(TokenKind.EOF));
|
||||
}
|
||||
|
||||
|
@ -107,7 +112,7 @@ public class UriTokenizerTest {
|
|||
final UriTokenizer tokenizer = new UriTokenizer("multi.part.namespace.name.1");
|
||||
assertTrue(tokenizer.next(TokenKind.QualifiedName));
|
||||
assertTrue(tokenizer.next(TokenKind.DOT));
|
||||
assertTrue(tokenizer.next(TokenKind.PrimitiveIntegerValue));
|
||||
assertTrue(tokenizer.next(TokenKind.IntegerValue));
|
||||
assertTrue(tokenizer.next(TokenKind.EOF));
|
||||
|
||||
assertFalse(new UriTokenizer("name").next(TokenKind.QualifiedName));
|
||||
|
@ -127,174 +132,174 @@ public class UriTokenizerTest {
|
|||
|
||||
@Test
|
||||
public void booleanValue() {
|
||||
assertTrue(new UriTokenizer("true").next(TokenKind.PrimitiveBooleanValue));
|
||||
assertTrue(new UriTokenizer("tRuE").next(TokenKind.PrimitiveBooleanValue));
|
||||
assertTrue(new UriTokenizer("false").next(TokenKind.PrimitiveBooleanValue));
|
||||
assertTrue(new UriTokenizer("False").next(TokenKind.PrimitiveBooleanValue));
|
||||
assertTrue(new UriTokenizer("true").next(TokenKind.BooleanValue));
|
||||
assertTrue(new UriTokenizer("tRuE").next(TokenKind.BooleanValue));
|
||||
assertTrue(new UriTokenizer("false").next(TokenKind.BooleanValue));
|
||||
assertTrue(new UriTokenizer("False").next(TokenKind.BooleanValue));
|
||||
|
||||
wrongToken(TokenKind.PrimitiveBooleanValue, "true", 'x');
|
||||
wrongToken(TokenKind.BooleanValue, "true", 'x');
|
||||
}
|
||||
|
||||
@Test
|
||||
public void string() {
|
||||
assertTrue(new UriTokenizer("'ABC'").next(TokenKind.PrimitiveStringValue));
|
||||
assertTrue(new UriTokenizer("'€\uFDFC'").next(TokenKind.PrimitiveStringValue));
|
||||
assertTrue(new UriTokenizer("'ABC'").next(TokenKind.StringValue));
|
||||
assertTrue(new UriTokenizer("'€\uFDFC'").next(TokenKind.StringValue));
|
||||
assertTrue(new UriTokenizer('\'' + String.valueOf(Character.toChars(0x1F603)) + '\'')
|
||||
.next(TokenKind.PrimitiveStringValue));
|
||||
.next(TokenKind.StringValue));
|
||||
|
||||
final UriTokenizer tokenizer = new UriTokenizer("'AB''''C'''D");
|
||||
assertTrue(tokenizer.next(TokenKind.PrimitiveStringValue));
|
||||
assertTrue(tokenizer.next(TokenKind.StringValue));
|
||||
assertEquals("'AB''''C'''", tokenizer.getText());
|
||||
assertTrue(tokenizer.next(TokenKind.ODataIdentifier));
|
||||
assertEquals("D", tokenizer.getText());
|
||||
|
||||
assertFalse(new UriTokenizer("A").next(TokenKind.PrimitiveStringValue));
|
||||
assertFalse(new UriTokenizer("'A").next(TokenKind.PrimitiveStringValue));
|
||||
assertFalse(new UriTokenizer("A").next(TokenKind.StringValue));
|
||||
assertFalse(new UriTokenizer("'A").next(TokenKind.StringValue));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void integer() {
|
||||
assertTrue(new UriTokenizer("1").next(TokenKind.PrimitiveIntegerValue));
|
||||
assertTrue(new UriTokenizer("1.").next(TokenKind.PrimitiveIntegerValue));
|
||||
assertFalse(new UriTokenizer(".1").next(TokenKind.PrimitiveIntegerValue));
|
||||
assertTrue(new UriTokenizer("-1").next(TokenKind.PrimitiveIntegerValue));
|
||||
assertTrue(new UriTokenizer("1234567890").next(TokenKind.PrimitiveIntegerValue));
|
||||
assertTrue(new UriTokenizer("1").next(TokenKind.IntegerValue));
|
||||
assertTrue(new UriTokenizer("1.").next(TokenKind.IntegerValue));
|
||||
assertFalse(new UriTokenizer(".1").next(TokenKind.IntegerValue));
|
||||
assertTrue(new UriTokenizer("-1").next(TokenKind.IntegerValue));
|
||||
assertTrue(new UriTokenizer("1234567890").next(TokenKind.IntegerValue));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void guid() {
|
||||
assertTrue(new UriTokenizer("12345678-abcd-ef12-1234-567890ABCDEF").next(TokenKind.PrimitiveGuidValue));
|
||||
wrongToken(TokenKind.PrimitiveGuidValue, "12345678-1234-1234-1234-123456789ABC", 'G');
|
||||
assertTrue(new UriTokenizer("12345678-abcd-ef12-1234-567890ABCDEF").next(TokenKind.GuidValue));
|
||||
wrongToken(TokenKind.GuidValue, "12345678-1234-1234-1234-123456789ABC", 'G');
|
||||
}
|
||||
|
||||
@Test
|
||||
public void date() {
|
||||
assertTrue(new UriTokenizer("12345-12-25").next(TokenKind.PrimitiveDateValue));
|
||||
assertTrue(new UriTokenizer("-0001-12-24").next(TokenKind.PrimitiveDateValue));
|
||||
assertFalse(new UriTokenizer("1234-13-01").next(TokenKind.PrimitiveDateValue));
|
||||
assertFalse(new UriTokenizer("1234-12-32").next(TokenKind.PrimitiveDateValue));
|
||||
assertFalse(new UriTokenizer("123-01-01").next(TokenKind.PrimitiveDateValue));
|
||||
assertFalse(new UriTokenizer("1234-00-01").next(TokenKind.PrimitiveDateValue));
|
||||
assertFalse(new UriTokenizer("1234-01-00").next(TokenKind.PrimitiveDateValue));
|
||||
wrongToken(TokenKind.PrimitiveDateValue, "2000-12-29", 'A');
|
||||
wrongToken(TokenKind.PrimitiveDateValue, "0001-01-01", 'A');
|
||||
wrongToken(TokenKind.PrimitiveDateValue, "-12345-01-31", 'A');
|
||||
assertTrue(new UriTokenizer("12345-12-25").next(TokenKind.DateValue));
|
||||
assertTrue(new UriTokenizer("-0001-12-24").next(TokenKind.DateValue));
|
||||
assertFalse(new UriTokenizer("1234-13-01").next(TokenKind.DateValue));
|
||||
assertFalse(new UriTokenizer("1234-12-32").next(TokenKind.DateValue));
|
||||
assertFalse(new UriTokenizer("123-01-01").next(TokenKind.DateValue));
|
||||
assertFalse(new UriTokenizer("1234-00-01").next(TokenKind.DateValue));
|
||||
assertFalse(new UriTokenizer("1234-01-00").next(TokenKind.DateValue));
|
||||
wrongToken(TokenKind.DateValue, "2000-12-29", 'A');
|
||||
wrongToken(TokenKind.DateValue, "0001-01-01", 'A');
|
||||
wrongToken(TokenKind.DateValue, "-12345-01-31", 'A');
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dateTimeOffset() {
|
||||
assertTrue(new UriTokenizer("1234-12-25T11:12:13.456Z").next(TokenKind.PrimitiveDateTimeOffsetValue));
|
||||
assertTrue(new UriTokenizer("-1234-12-25t01:12z").next(TokenKind.PrimitiveDateTimeOffsetValue));
|
||||
assertTrue(new UriTokenizer("-1234-12-25T21:22:23+01:00").next(TokenKind.PrimitiveDateTimeOffsetValue));
|
||||
assertTrue(new UriTokenizer("1234-12-25T11:12:13-00:30").next(TokenKind.PrimitiveDateTimeOffsetValue));
|
||||
assertFalse(new UriTokenizer("1234-10-01").next(TokenKind.PrimitiveDateTimeOffsetValue));
|
||||
wrongToken(TokenKind.PrimitiveDateTimeOffsetValue, "-1234-12-25T11:12:13.456+01:00", 'P');
|
||||
assertTrue(new UriTokenizer("1234-12-25T11:12:13.456Z").next(TokenKind.DateTimeOffsetValue));
|
||||
assertTrue(new UriTokenizer("-1234-12-25t01:12z").next(TokenKind.DateTimeOffsetValue));
|
||||
assertTrue(new UriTokenizer("-1234-12-25T21:22:23+01:00").next(TokenKind.DateTimeOffsetValue));
|
||||
assertTrue(new UriTokenizer("1234-12-25T11:12:13-00:30").next(TokenKind.DateTimeOffsetValue));
|
||||
assertFalse(new UriTokenizer("1234-10-01").next(TokenKind.DateTimeOffsetValue));
|
||||
wrongToken(TokenKind.DateTimeOffsetValue, "-1234-12-25T11:12:13.456+01:00", 'P');
|
||||
}
|
||||
|
||||
@Test
|
||||
public void timeOfDay() {
|
||||
assertTrue(new UriTokenizer("11:12:13").next(TokenKind.PrimitiveTimeOfDayValue));
|
||||
assertTrue(new UriTokenizer("11:12:13.456").next(TokenKind.PrimitiveTimeOfDayValue));
|
||||
assertFalse(new UriTokenizer("24:00:00").next(TokenKind.PrimitiveTimeOfDayValue));
|
||||
assertFalse(new UriTokenizer("01:60:00").next(TokenKind.PrimitiveTimeOfDayValue));
|
||||
assertFalse(new UriTokenizer("01:00:60").next(TokenKind.PrimitiveTimeOfDayValue));
|
||||
assertFalse(new UriTokenizer("01:00:00.").next(TokenKind.PrimitiveTimeOfDayValue));
|
||||
assertFalse(new UriTokenizer("0:02:03").next(TokenKind.PrimitiveTimeOfDayValue));
|
||||
assertFalse(new UriTokenizer("01:0:03").next(TokenKind.PrimitiveTimeOfDayValue));
|
||||
assertFalse(new UriTokenizer("01:02:0").next(TokenKind.PrimitiveTimeOfDayValue));
|
||||
wrongToken(TokenKind.PrimitiveTimeOfDayValue, "11:12", '-');
|
||||
assertTrue(new UriTokenizer("11:12:13").next(TokenKind.TimeOfDayValue));
|
||||
assertTrue(new UriTokenizer("11:12:13.456").next(TokenKind.TimeOfDayValue));
|
||||
assertFalse(new UriTokenizer("24:00:00").next(TokenKind.TimeOfDayValue));
|
||||
assertFalse(new UriTokenizer("01:60:00").next(TokenKind.TimeOfDayValue));
|
||||
assertFalse(new UriTokenizer("01:00:60").next(TokenKind.TimeOfDayValue));
|
||||
assertFalse(new UriTokenizer("01:00:00.").next(TokenKind.TimeOfDayValue));
|
||||
assertFalse(new UriTokenizer("0:02:03").next(TokenKind.TimeOfDayValue));
|
||||
assertFalse(new UriTokenizer("01:0:03").next(TokenKind.TimeOfDayValue));
|
||||
assertFalse(new UriTokenizer("01:02:0").next(TokenKind.TimeOfDayValue));
|
||||
wrongToken(TokenKind.TimeOfDayValue, "11:12", '-');
|
||||
}
|
||||
|
||||
@Test
|
||||
public void decimal() {
|
||||
assertTrue(new UriTokenizer("1.2").next(TokenKind.PrimitiveDecimalValue));
|
||||
assertFalse(new UriTokenizer(".1").next(TokenKind.PrimitiveDecimalValue));
|
||||
assertTrue(new UriTokenizer("-12.34").next(TokenKind.PrimitiveDecimalValue));
|
||||
assertTrue(new UriTokenizer("1234567890.0123456789").next(TokenKind.PrimitiveDecimalValue));
|
||||
assertFalse(new UriTokenizer("0,1").next(TokenKind.PrimitiveDecimalValue));
|
||||
assertFalse(new UriTokenizer("0..1").next(TokenKind.PrimitiveDecimalValue));
|
||||
assertTrue(new UriTokenizer("1.2").next(TokenKind.DecimalValue));
|
||||
assertFalse(new UriTokenizer(".1").next(TokenKind.DecimalValue));
|
||||
assertTrue(new UriTokenizer("-12.34").next(TokenKind.DecimalValue));
|
||||
assertTrue(new UriTokenizer("1234567890.0123456789").next(TokenKind.DecimalValue));
|
||||
assertFalse(new UriTokenizer("0,1").next(TokenKind.DecimalValue));
|
||||
assertFalse(new UriTokenizer("0..1").next(TokenKind.DecimalValue));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doubleValue() {
|
||||
assertTrue(new UriTokenizer("NaN").next(TokenKind.PrimitiveDoubleValue));
|
||||
assertTrue(new UriTokenizer("-INF").next(TokenKind.PrimitiveDoubleValue));
|
||||
assertTrue(new UriTokenizer("INF").next(TokenKind.PrimitiveDoubleValue));
|
||||
assertFalse(new UriTokenizer("inf").next(TokenKind.PrimitiveDoubleValue));
|
||||
assertTrue(new UriTokenizer("1.2E3").next(TokenKind.PrimitiveDoubleValue));
|
||||
assertTrue(new UriTokenizer("-12.34e-05").next(TokenKind.PrimitiveDoubleValue));
|
||||
assertTrue(new UriTokenizer("1E2").next(TokenKind.PrimitiveDoubleValue));
|
||||
assertFalse(new UriTokenizer("1.E2").next(TokenKind.PrimitiveDoubleValue));
|
||||
wrongToken(TokenKind.PrimitiveDoubleValue, "-12.34E+5", 'i');
|
||||
assertTrue(new UriTokenizer("NaN").next(TokenKind.DoubleValue));
|
||||
assertTrue(new UriTokenizer("-INF").next(TokenKind.DoubleValue));
|
||||
assertTrue(new UriTokenizer("INF").next(TokenKind.DoubleValue));
|
||||
assertFalse(new UriTokenizer("inf").next(TokenKind.DoubleValue));
|
||||
assertTrue(new UriTokenizer("1.2E3").next(TokenKind.DoubleValue));
|
||||
assertTrue(new UriTokenizer("-12.34e-05").next(TokenKind.DoubleValue));
|
||||
assertTrue(new UriTokenizer("1E2").next(TokenKind.DoubleValue));
|
||||
assertFalse(new UriTokenizer("1.E2").next(TokenKind.DoubleValue));
|
||||
wrongToken(TokenKind.DoubleValue, "-12.34E+5", 'i');
|
||||
}
|
||||
|
||||
@Test
|
||||
public void duration() {
|
||||
assertTrue(new UriTokenizer("duration'P'").next(TokenKind.PrimitiveDurationValue));
|
||||
assertTrue(new UriTokenizer("DURATION'P1D'").next(TokenKind.PrimitiveDurationValue));
|
||||
assertTrue(new UriTokenizer("duration'PT'").next(TokenKind.PrimitiveDurationValue));
|
||||
assertTrue(new UriTokenizer("duration'PT1H'").next(TokenKind.PrimitiveDurationValue));
|
||||
assertTrue(new UriTokenizer("duration'pt1M'").next(TokenKind.PrimitiveDurationValue));
|
||||
assertTrue(new UriTokenizer("duration'PT1S'").next(TokenKind.PrimitiveDurationValue));
|
||||
assertTrue(new UriTokenizer("duration'PT1.2s'").next(TokenKind.PrimitiveDurationValue));
|
||||
assertTrue(new UriTokenizer("duration'-p1dt2h3m4.5s'").next(TokenKind.PrimitiveDurationValue));
|
||||
assertFalse(new UriTokenizer("-p1dt2h3m4.5s").next(TokenKind.PrimitiveDurationValue));
|
||||
assertFalse(new UriTokenizer("duration'-p1dt2h3m4.5s").next(TokenKind.PrimitiveDurationValue));
|
||||
assertFalse(new UriTokenizer("duration'2h3m4s'").next(TokenKind.PrimitiveDurationValue));
|
||||
wrongToken(TokenKind.PrimitiveDurationValue, "duration'P1DT2H3M4.5S'", ':');
|
||||
assertTrue(new UriTokenizer("duration'P'").next(TokenKind.DurationValue));
|
||||
assertTrue(new UriTokenizer("DURATION'P1D'").next(TokenKind.DurationValue));
|
||||
assertTrue(new UriTokenizer("duration'PT'").next(TokenKind.DurationValue));
|
||||
assertTrue(new UriTokenizer("duration'PT1H'").next(TokenKind.DurationValue));
|
||||
assertTrue(new UriTokenizer("duration'pt1M'").next(TokenKind.DurationValue));
|
||||
assertTrue(new UriTokenizer("duration'PT1S'").next(TokenKind.DurationValue));
|
||||
assertTrue(new UriTokenizer("duration'PT1.2s'").next(TokenKind.DurationValue));
|
||||
assertTrue(new UriTokenizer("duration'-p1dt2h3m4.5s'").next(TokenKind.DurationValue));
|
||||
assertFalse(new UriTokenizer("-p1dt2h3m4.5s").next(TokenKind.DurationValue));
|
||||
assertFalse(new UriTokenizer("duration'-p1dt2h3m4.5s").next(TokenKind.DurationValue));
|
||||
assertFalse(new UriTokenizer("duration'2h3m4s'").next(TokenKind.DurationValue));
|
||||
wrongToken(TokenKind.DurationValue, "duration'P1DT2H3M4.5S'", ':');
|
||||
}
|
||||
|
||||
@Test
|
||||
public void binary() {
|
||||
assertTrue(new UriTokenizer("binary''").next(TokenKind.PrimitiveBinaryValue));
|
||||
assertTrue(new UriTokenizer("Binary'bm93'").next(TokenKind.PrimitiveBinaryValue));
|
||||
assertTrue(new UriTokenizer("binary''").next(TokenKind.BinaryValue));
|
||||
assertTrue(new UriTokenizer("Binary'bm93'").next(TokenKind.BinaryValue));
|
||||
|
||||
// all cases with three base64 characters (and one fill character) at the end
|
||||
assertTrue(new UriTokenizer("binary'QUA='").next(TokenKind.PrimitiveBinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'QUE='").next(TokenKind.PrimitiveBinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'QUI='").next(TokenKind.PrimitiveBinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'QUM='").next(TokenKind.PrimitiveBinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'QUQ='").next(TokenKind.PrimitiveBinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'QUU='").next(TokenKind.PrimitiveBinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'QUY='").next(TokenKind.PrimitiveBinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'QUc='").next(TokenKind.PrimitiveBinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'QUg='").next(TokenKind.PrimitiveBinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'QUk='").next(TokenKind.PrimitiveBinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'QUo='").next(TokenKind.PrimitiveBinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'QUs='").next(TokenKind.PrimitiveBinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'QUw='").next(TokenKind.PrimitiveBinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'QU0='").next(TokenKind.PrimitiveBinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'QU4='").next(TokenKind.PrimitiveBinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'QU8='").next(TokenKind.PrimitiveBinaryValue));
|
||||
assertFalse(new UriTokenizer("binary'QUB='").next(TokenKind.PrimitiveBinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'QUA='").next(TokenKind.BinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'QUE='").next(TokenKind.BinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'QUI='").next(TokenKind.BinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'QUM='").next(TokenKind.BinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'QUQ='").next(TokenKind.BinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'QUU='").next(TokenKind.BinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'QUY='").next(TokenKind.BinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'QUc='").next(TokenKind.BinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'QUg='").next(TokenKind.BinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'QUk='").next(TokenKind.BinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'QUo='").next(TokenKind.BinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'QUs='").next(TokenKind.BinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'QUw='").next(TokenKind.BinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'QU0='").next(TokenKind.BinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'QU4='").next(TokenKind.BinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'QU8='").next(TokenKind.BinaryValue));
|
||||
assertFalse(new UriTokenizer("binary'QUB='").next(TokenKind.BinaryValue));
|
||||
|
||||
// all cases with two base64 characters (and two fill characters) at the end
|
||||
assertTrue(new UriTokenizer("BINARY'VGVzdA=='").next(TokenKind.PrimitiveBinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'U-RnZQ=='").next(TokenKind.PrimitiveBinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'Yg=='").next(TokenKind.PrimitiveBinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'Yw=='").next(TokenKind.PrimitiveBinaryValue));
|
||||
assertTrue(new UriTokenizer("BINARY'VGVzdA=='").next(TokenKind.BinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'U-RnZQ=='").next(TokenKind.BinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'Yg=='").next(TokenKind.BinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'Yw=='").next(TokenKind.BinaryValue));
|
||||
|
||||
// without optional fill character
|
||||
assertTrue(new UriTokenizer("binary'T0RhdGE'").next(TokenKind.PrimitiveBinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'T0RhdGE'").next(TokenKind.BinaryValue));
|
||||
|
||||
// special character '_' (the other, '-', already has been used above)
|
||||
assertTrue(new UriTokenizer("binary'V_ZydGVy'").next(TokenKind.PrimitiveBinaryValue));
|
||||
assertTrue(new UriTokenizer("binary'V_ZydGVy'").next(TokenKind.BinaryValue));
|
||||
|
||||
wrongToken(TokenKind.PrimitiveBinaryValue, "binary'VGVzdA=='", '+');
|
||||
wrongToken(TokenKind.BinaryValue, "binary'VGVzdA=='", '+');
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enumValue() {
|
||||
assertTrue(new UriTokenizer("namespace.name'value'").next(TokenKind.PrimitiveEnumValue));
|
||||
assertTrue(new UriTokenizer("namespace.name'flag1,flag2,-3'").next(TokenKind.PrimitiveEnumValue));
|
||||
assertFalse(new UriTokenizer("namespace.name'1flag'").next(TokenKind.PrimitiveEnumValue));
|
||||
assertFalse(new UriTokenizer("namespace.name'flag1,,flag2'").next(TokenKind.PrimitiveEnumValue));
|
||||
assertFalse(new UriTokenizer("namespace.name',value'").next(TokenKind.PrimitiveEnumValue));
|
||||
assertFalse(new UriTokenizer("namespace.name'value,'").next(TokenKind.PrimitiveEnumValue));
|
||||
assertFalse(new UriTokenizer("namespace.name''").next(TokenKind.PrimitiveEnumValue));
|
||||
assertFalse(new UriTokenizer("'1'").next(TokenKind.PrimitiveEnumValue));
|
||||
assertFalse(new UriTokenizer("1").next(TokenKind.PrimitiveEnumValue));
|
||||
wrongToken(TokenKind.PrimitiveEnumValue, "namespace.name'_1,_2,3'", ';');
|
||||
assertTrue(new UriTokenizer("namespace.name'value'").next(TokenKind.EnumValue));
|
||||
assertTrue(new UriTokenizer("namespace.name'flag1,flag2,-3'").next(TokenKind.EnumValue));
|
||||
assertFalse(new UriTokenizer("namespace.name'1flag'").next(TokenKind.EnumValue));
|
||||
assertFalse(new UriTokenizer("namespace.name'flag1,,flag2'").next(TokenKind.EnumValue));
|
||||
assertFalse(new UriTokenizer("namespace.name',value'").next(TokenKind.EnumValue));
|
||||
assertFalse(new UriTokenizer("namespace.name'value,'").next(TokenKind.EnumValue));
|
||||
assertFalse(new UriTokenizer("namespace.name''").next(TokenKind.EnumValue));
|
||||
assertFalse(new UriTokenizer("'1'").next(TokenKind.EnumValue));
|
||||
assertFalse(new UriTokenizer("1").next(TokenKind.EnumValue));
|
||||
wrongToken(TokenKind.EnumValue, "namespace.name'_1,_2,3'", ';');
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -360,6 +365,92 @@ public class UriTokenizerTest {
|
|||
wrongToken(TokenKind.jsonArrayOrObject, "[{\"name\":+123.456},null]", '\\');
|
||||
}
|
||||
|
||||
@Test
|
||||
public void operators() {
|
||||
UriTokenizer tokenizer = new UriTokenizer("1 ne 2");
|
||||
assertTrue(tokenizer.next(TokenKind.IntegerValue));
|
||||
assertFalse(tokenizer.next(TokenKind.EqualsOperator));
|
||||
assertTrue(tokenizer.next(TokenKind.NotEqualsOperator));
|
||||
assertTrue(tokenizer.next(TokenKind.IntegerValue));
|
||||
assertTrue(tokenizer.next(TokenKind.EOF));
|
||||
|
||||
tokenizer = new UriTokenizer("1ne 2");
|
||||
assertTrue(tokenizer.next(TokenKind.IntegerValue));
|
||||
assertFalse(tokenizer.next(TokenKind.NotEqualsOperator));
|
||||
|
||||
tokenizer = new UriTokenizer("1 ne2");
|
||||
assertTrue(tokenizer.next(TokenKind.IntegerValue));
|
||||
assertFalse(tokenizer.next(TokenKind.NotEqualsOperator));
|
||||
|
||||
tokenizer = new UriTokenizer("1 \tle\t\t\t2");
|
||||
assertTrue(tokenizer.next(TokenKind.IntegerValue));
|
||||
assertTrue(tokenizer.next(TokenKind.LessThanOrEqualsOperator));
|
||||
assertTrue(tokenizer.next(TokenKind.IntegerValue));
|
||||
assertTrue(tokenizer.next(TokenKind.EOF));
|
||||
|
||||
assertFalse(new UriTokenizer("nottrue").next(TokenKind.NotOperator));
|
||||
assertFalse(new UriTokenizer("no true").next(TokenKind.NotOperator));
|
||||
|
||||
tokenizer = new UriTokenizer("true or not false and 1 eq 2 add 3 sub 4 mul 5 div 6 mod 7");
|
||||
assertTrue(tokenizer.next(TokenKind.BooleanValue));
|
||||
assertTrue(tokenizer.next(TokenKind.OrOperator));
|
||||
assertTrue(tokenizer.next(TokenKind.NotOperator));
|
||||
assertTrue(tokenizer.next(TokenKind.BooleanValue));
|
||||
assertTrue(tokenizer.next(TokenKind.AndOperator));
|
||||
assertTrue(tokenizer.next(TokenKind.IntegerValue));
|
||||
assertTrue(tokenizer.next(TokenKind.EqualsOperator));
|
||||
assertTrue(tokenizer.next(TokenKind.IntegerValue));
|
||||
assertTrue(tokenizer.next(TokenKind.AddOperator));
|
||||
assertTrue(tokenizer.next(TokenKind.IntegerValue));
|
||||
assertTrue(tokenizer.next(TokenKind.SubOperator));
|
||||
assertTrue(tokenizer.next(TokenKind.IntegerValue));
|
||||
assertTrue(tokenizer.next(TokenKind.MulOperator));
|
||||
assertTrue(tokenizer.next(TokenKind.IntegerValue));
|
||||
assertTrue(tokenizer.next(TokenKind.DivOperator));
|
||||
assertTrue(tokenizer.next(TokenKind.IntegerValue));
|
||||
assertTrue(tokenizer.next(TokenKind.ModOperator));
|
||||
assertTrue(tokenizer.next(TokenKind.IntegerValue));
|
||||
assertTrue(tokenizer.next(TokenKind.EOF));
|
||||
|
||||
tokenizer = new UriTokenizer("1 gt 2 or 3 ge 4 or 5 lt 6");
|
||||
assertTrue(tokenizer.next(TokenKind.IntegerValue));
|
||||
assertTrue(tokenizer.next(TokenKind.GreaterThanOperator));
|
||||
assertTrue(tokenizer.next(TokenKind.IntegerValue));
|
||||
assertTrue(tokenizer.next(TokenKind.OrOperator));
|
||||
assertTrue(tokenizer.next(TokenKind.IntegerValue));
|
||||
assertTrue(tokenizer.next(TokenKind.GreaterThanOrEqualsOperator));
|
||||
assertTrue(tokenizer.next(TokenKind.IntegerValue));
|
||||
assertTrue(tokenizer.next(TokenKind.OrOperator));
|
||||
assertTrue(tokenizer.next(TokenKind.IntegerValue));
|
||||
assertTrue(tokenizer.next(TokenKind.LessThanOperator));
|
||||
assertTrue(tokenizer.next(TokenKind.IntegerValue));
|
||||
assertTrue(tokenizer.next(TokenKind.EOF));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void methods() {
|
||||
UriTokenizer tokenizer = new UriTokenizer("now()");
|
||||
assertTrue(tokenizer.next(TokenKind.NowMethod));
|
||||
assertTrue(tokenizer.next(TokenKind.CLOSE));
|
||||
assertTrue(tokenizer.next(TokenKind.EOF));
|
||||
|
||||
assertFalse(new UriTokenizer("no w()").next(TokenKind.NowMethod));
|
||||
assertFalse(new UriTokenizer("now ()").next(TokenKind.NowMethod));
|
||||
|
||||
assertTrue(new UriTokenizer("maxdatetime()").next(TokenKind.MaxdatetimeMethod));
|
||||
assertTrue(new UriTokenizer("mindatetime()").next(TokenKind.MindatetimeMethod));
|
||||
|
||||
for (final TokenKind tokenKind : TokenKind.values()) {
|
||||
if (tokenKind.name().endsWith("Method")) {
|
||||
assertTrue(tokenKind.name(),
|
||||
new UriTokenizer(
|
||||
tokenKind.name().substring(0, tokenKind.name().indexOf("Method"))
|
||||
.toLowerCase(Locale.ROOT).replace("geo", "geo.") + '(')
|
||||
.next(tokenKind));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void wrongToken(final TokenKind kind, final String value, final char disturbCharacter) {
|
||||
assertFalse(new UriTokenizer(disturbCharacter + value).next(kind));
|
||||
|
||||
|
|
Loading…
Reference in New Issue