private boolean isValidQualifiedId(@Nullable Token node) { if (node == null || node.kind == TokenKind.LITERAL_STRING) { return false; } if (node.kind == TokenKind.DOT || node.kind == TokenKind.IDENTIFIER) { return true; } String value = node.stringValue(); return (StringUtils.hasLength(value) && VALID_QUALIFIED_ID_PATTERN.matcher(value).matches()); }
private boolean peekIdentifierToken(String identifierString) { Token t = peekToken(); if (t == null) { return false; } return (t.kind == TokenKind.IDENTIFIER && identifierString.equalsIgnoreCase(t.stringValue())); }
public String toString(@Nullable Token t) { if (t == null) { return ""; } if (t.getKind().hasPayload()) { return t.stringValue(); } return t.kind.toString().toLowerCase(); }
private boolean isValidQualifiedId(@Nullable Token node) { if (node == null || node.kind == TokenKind.LITERAL_STRING) { return false; } if (node.kind == TokenKind.DOT || node.kind == TokenKind.IDENTIFIER) { return true; } String value = node.stringValue(); return (StringUtils.hasLength(value) && VALID_QUALIFIED_ID_PATTERN.matcher(value).matches()); }
private boolean maybeEatNullReference() { if (peekToken(TokenKind.IDENTIFIER)) { Token nullToken = peekToken(); Assert.state(nullToken != null, "Expected token"); if (!"null".equalsIgnoreCase(nullToken.stringValue())) { return false; } nextToken(); this.constructedNodes.push(new NullLiteral(nullToken.startPos, nullToken.endPos)); return true; } return false; }
private boolean peekIdentifierToken(String identifierString) { Token t = peekToken(); if (t == null) { return false; } return (t.kind == TokenKind.IDENTIFIER && identifierString.equalsIgnoreCase(t.stringValue())); }
@Nullable private Token maybeEatRelationalOperator() { Token t = peekToken(); if (t == null) { return null; } if (t.isNumericRelationalOperator()) { return t; } if (t.isIdentifier()) { String idString = t.stringValue(); if (idString.equalsIgnoreCase("instanceof")) { return t.asInstanceOfToken(); } if (idString.equalsIgnoreCase("matches")) { return t.asMatchesToken(); } if (idString.equalsIgnoreCase("between")) { return t.asBetweenToken(); } } return null; }
push(Literal.getIntLiteral(t.stringValue(), t.startPos, t.endPos, 10)); push(Literal.getLongLiteral(t.stringValue(), t.startPos, t.endPos, 10)); push(Literal.getIntLiteral(t.stringValue(), t.startPos, t.endPos, 16)); push(Literal.getLongLiteral(t.stringValue(), t.startPos, t.endPos, 16)); push(Literal.getRealLiteral(t.stringValue(), t.startPos, t.endPos, false)); push(Literal.getRealLiteral(t.stringValue(), t.startPos, t.endPos, true)); push(new BooleanLiteral(t.stringValue(), t.startPos, t.endPos, true)); push(new BooleanLiteral(t.stringValue(), t.startPos, t.endPos, false)); push(new StringLiteral(t.stringValue(), t.startPos, t.endPos, t.stringValue()));
private boolean maybeEatMethodOrProperty(boolean nullSafeNavigation) { if (peekToken(TokenKind.IDENTIFIER)) { Token methodOrPropertyName = takeToken(); SpelNodeImpl[] args = maybeEatMethodArgs(); if (args == null) { // property push(new PropertyOrFieldReference(nullSafeNavigation, methodOrPropertyName.stringValue(), methodOrPropertyName.startPos, methodOrPropertyName.endPos)); return true; } // method reference push(new MethodReference(nullSafeNavigation, methodOrPropertyName.stringValue(), methodOrPropertyName.startPos, methodOrPropertyName.endPos, args)); // TODO what is the end position for a method reference? the name or the last arg? return true; } return false; }
public String toString(@Nullable Token t) { if (t == null) { return ""; } if (t.getKind().hasPayload()) { return t.stringValue(); } return t.kind.toString().toLowerCase(); }
private boolean maybeEatFunctionOrVar() { if (!peekToken(TokenKind.HASH)) { return false; } Token t = takeToken(); Token functionOrVariableName = eatToken(TokenKind.IDENTIFIER); SpelNodeImpl[] args = maybeEatMethodArgs(); if (args == null) { push(new VariableReference(functionOrVariableName.stringValue(), t.startPos, functionOrVariableName.endPos)); return true; } push(new FunctionReference(functionOrVariableName.stringValue(), t.startPos, functionOrVariableName.endPos, args)); return true; }
private boolean maybeEatBeanReference() { if (peekToken(TokenKind.BEAN_REF) || peekToken(TokenKind.FACTORY_BEAN_REF)) { Token beanRefToken = takeToken(); Token beanNameToken = null; String beanName = null; if (peekToken(TokenKind.IDENTIFIER)) { beanNameToken = eatToken(TokenKind.IDENTIFIER); beanName = beanNameToken.stringValue(); } else if (peekToken(TokenKind.LITERAL_STRING)) { beanNameToken = eatToken(TokenKind.LITERAL_STRING); beanName = beanNameToken.stringValue(); beanName = beanName.substring(1, beanName.length() - 1); } else { throw internalException(beanRefToken.startPos, SpelMessage.INVALID_BEAN_REFERENCE); } BeanReference beanReference; if (beanRefToken.getKind() == TokenKind.FACTORY_BEAN_REF) { String beanNameString = String.valueOf(TokenKind.FACTORY_BEAN_REF.tokenChars) + beanName; beanReference = new BeanReference(beanRefToken.startPos, beanNameToken.endPos, beanNameString); } else { beanReference = new BeanReference(beanNameToken.startPos, beanNameToken.endPos, beanName); } this.constructedNodes.push(beanReference); return true; } return false; }
/** * Eat an identifier, possibly qualified (meaning that it is dotted). * TODO AndyC Could create complete identifiers (a.b.c) here rather than a sequence of them? (a, b, c) */ private SpelNodeImpl eatPossiblyQualifiedId() { Deque<SpelNodeImpl> qualifiedIdPieces = new ArrayDeque<>(); Token node = peekToken(); while (isValidQualifiedId(node)) { nextToken(); if (node.kind != TokenKind.DOT) { qualifiedIdPieces.add(new Identifier(node.stringValue(), node.startPos, node.endPos)); } node = peekToken(); } if (qualifiedIdPieces.isEmpty()) { if (node == null) { throw internalException( this.expressionString.length(), SpelMessage.OOD); } throw internalException(node.startPos, SpelMessage.NOT_EXPECTED_TOKEN, "qualified ID", node.getKind().toString().toLowerCase()); } return new QualifiedIdentifier(qualifiedIdPieces.getFirst().getStartPosition(), qualifiedIdPieces.getLast().getEndPosition(), qualifiedIdPieces.toArray(new SpelNodeImpl[0])); }
private boolean maybeEatNullReference() { if (peekToken(TokenKind.IDENTIFIER)) { Token nullToken = peekToken(); Assert.state(nullToken != null, "Expected token"); if (!"null".equalsIgnoreCase(nullToken.stringValue())) { return false; } nextToken(); this.constructedNodes.push(new NullLiteral(toPos(nullToken))); return true; } return false; }
private boolean maybeEatTypeReference() { if (peekToken(TokenKind.IDENTIFIER)) { Token typeName = peekToken(); Assert.state(typeName != null, "Expected token"); if (!"T".equals(typeName.stringValue())) { return false; } // It looks like a type reference but is T being used as a map key? Token t = takeToken(); if (peekToken(TokenKind.RSQUARE)) { // looks like 'T]' (T is map key) push(new PropertyOrFieldReference(false, t.stringValue(), t.startPos, t.endPos)); return true; } eatToken(TokenKind.LPAREN); SpelNodeImpl node = eatPossiblyQualifiedId(); // dotted qualified id // Are there array dimensions? int dims = 0; while (peekToken(TokenKind.LSQUARE, true)) { eatToken(TokenKind.RSQUARE); dims++; } eatToken(TokenKind.RPAREN); this.constructedNodes.push(new TypeReference(typeName.startPos, typeName.endPos, node, dims)); return true; } return false; }
push(new PropertyOrFieldReference(false, newToken.stringValue(), newToken.startPos, newToken.endPos)); return true;
@Nullable private Token maybeEatRelationalOperator() { Token t = peekToken(); if (t == null) { return null; } if (t.isNumericRelationalOperator()) { return t; } if (t.isIdentifier()) { String idString = t.stringValue(); if (idString.equalsIgnoreCase("instanceof")) { return t.asInstanceOfToken(); } if (idString.equalsIgnoreCase("matches")) { return t.asMatchesToken(); } if (idString.equalsIgnoreCase("between")) { return t.asBetweenToken(); } } return null; }
private boolean maybeEatFunctionOrVar() { if (!peekToken(TokenKind.HASH)) { return false; } Token t = takeToken(); Token functionOrVariableName = eatToken(TokenKind.IDENTIFIER); SpelNodeImpl[] args = maybeEatMethodArgs(); if (args == null) { push(new VariableReference(functionOrVariableName.stringValue(), toPos(t.startPos, functionOrVariableName.endPos))); return true; } push(new FunctionReference(functionOrVariableName.stringValue(), toPos(t.startPos, functionOrVariableName.endPos), args)); return true; }
private boolean maybeEatMethodOrProperty(boolean nullSafeNavigation) { if (peekToken(TokenKind.IDENTIFIER)) { Token methodOrPropertyName = takeToken(); SpelNodeImpl[] args = maybeEatMethodArgs(); if (args == null) { // property push(new PropertyOrFieldReference(nullSafeNavigation, methodOrPropertyName.stringValue(), toPos(methodOrPropertyName))); return true; } // method reference push(new MethodReference(nullSafeNavigation, methodOrPropertyName.stringValue(), toPos(methodOrPropertyName), args)); // TODO what is the end position for a method reference? the name or the last arg? return true; } return false; }
/** * Eat an identifier, possibly qualified (meaning that it is dotted). * TODO AndyC Could create complete identifiers (a.b.c) here rather than a sequence of them? (a, b, c) */ private SpelNodeImpl eatPossiblyQualifiedId() { Deque<SpelNodeImpl> qualifiedIdPieces = new ArrayDeque<>(); Token node = peekToken(); while (isValidQualifiedId(node)) { nextToken(); if (node.kind != TokenKind.DOT) { qualifiedIdPieces.add(new Identifier(node.stringValue(), toPos(node))); } node = peekToken(); } if (qualifiedIdPieces.isEmpty()) { if (node == null) { throw internalException( this.expressionString.length(), SpelMessage.OOD); } throw internalException(node.startPos, SpelMessage.NOT_EXPECTED_TOKEN, "qualified ID", node.getKind().toString().toLowerCase()); } int pos = toPos(qualifiedIdPieces.getFirst().getStartPosition(), qualifiedIdPieces.getLast().getEndPosition()); return new QualifiedIdentifier(pos, qualifiedIdPieces.toArray(new SpelNodeImpl[0])); }