Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/main/antlr4/com/aerospike/dsl/Condition.g4
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ operand
| listConstant
| orderedMapConstant
| variable
| placeholder
| '$.' pathOrMetadata
| '(' expression ')'
;
Expand Down Expand Up @@ -118,6 +119,10 @@ fragment STRING_VARIABLE_NAME
: [a-zA-Z_][a-zA-Z0-9_]*
;

placeholder: PLACEHOLDER;

PLACEHOLDER: '?' [0-9]+;

pathOrMetadata: path | metadata;

path: basePath ('.' pathFunction)?;
Expand Down
24 changes: 24 additions & 0 deletions src/main/java/com/aerospike/dsl/ExpressionContext.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.aerospike.dsl;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

/**
* This class stores input string and optional values for placeholders (if they are used)
*/
@AllArgsConstructor(staticName = "of")
@RequiredArgsConstructor(staticName = "of")
@Getter
public class ExpressionContext {

/**
* Input string. If placeholders are used, they should be matched with {@code values}
*/
private final String expression;
/**
* {@link PlaceholderValues} to be matched with placeholders in the {@code input} string.
* Optional (needed only if there are placeholders)
*/
private PlaceholderValues values;
}
2 changes: 1 addition & 1 deletion src/main/java/com/aerospike/dsl/IndexContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import java.util.Collection;

/**
* This class stores namespace and indexes required to build secondary index {@link Filter}.
* This class stores namespace and indexes required to build secondary index {@link Filter}
*/
@AllArgsConstructor(staticName = "of")
@Getter
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/aerospike/dsl/ParseResult.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import lombok.Getter;

/**
* This class stores result of parsing DSL expression using {@link DSLParserImpl#parseExpression}
* This class stores result of parsing DSL expression using {@link ParsedExpression#getResult()}
* in form of Java client's secondary index {@link Filter} and filter {@link Exp}.
*/
@AllArgsConstructor
Expand Down
30 changes: 21 additions & 9 deletions src/main/java/com/aerospike/dsl/ParsedExpression.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,38 +15,50 @@


/**
* A class to build and store the results of DSL expression parsing: {@link ParseResult} that holds
* a potential secondary index {@link Filter} and a potential filter {@link Exp}, and parsed {@code expressionTree}.
* A class to build and store the results of DSL expression parsing: parsed {@code expressionTree}, {@code indexesMap}
* of given indexes, {@code placeholderValues} to match with placeholders and {@link ParseResult} that holds
* a potential secondary index {@link Filter} and a potential {@link Exp}.
*/
@Beta
@Getter
public class ParsedExpression {

private final AbstractPart expressionTree;
private final Map<String, List<Index>> indexesMap;
private final PlaceholderValues placeholderValues;
private ParseResult result;

public ParsedExpression(AbstractPart expressionTree, Map<String, List<Index>> indexesMap) {
this.expressionTree = expressionTree;
public ParsedExpression(AbstractPart exprTree, PlaceholderValues placeholderValues,
Map<String, List<Index>> indexesMap) {
this.expressionTree = exprTree;
this.placeholderValues = placeholderValues;
this.indexesMap = indexesMap;
}

/**
* @return Pair of secondary index {@link Filter} and filter {@link Exp}. Each can be null in case of invalid or
* unsupported DSL string
* @return {@link ParseResult} containing secondary index {@link Filter} and/or filter {@link Exp}.
* Each can be null in case of invalid or unsupported DSL string
* @throws DslParseException If there was an error
*/
public ParseResult getResult() {
if (result == null) {
result = getParseResult();
result = getResult(placeholderValues);
}
return result;
}

private ParseResult getParseResult() {
/**
* Traverse expression tree using the given placeholder values
*
* @param placeholderValues {@link PlaceholderValues} to match with placeholders by index
* @return {@link ParseResult} containing secondary index {@link Filter} and/or {@link Exp}.
* Each can be null in case of invalid or unsupported DSL string
* @throws DslParseException If there was an error
*/
public ParseResult getResult(PlaceholderValues placeholderValues) {
if (expressionTree != null) {
if (expressionTree.getPartType() == EXPRESSION_CONTAINER) {
AbstractPart resultPart = buildExpr((ExpressionContainer) expressionTree, indexesMap);
AbstractPart resultPart = buildExpr((ExpressionContainer) expressionTree, placeholderValues, indexesMap);
return new ParseResult(resultPart.getFilter(), resultPart.getExp());
} else {
Filter filter = expressionTree.getFilter();
Expand Down
41 changes: 41 additions & 0 deletions src/main/java/com/aerospike/dsl/PlaceholderValues.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.aerospike.dsl;

/**
* This class stores values to be matched with placeholders by indexes
*/
public class PlaceholderValues {

private final Object[] values;

private PlaceholderValues(Object... values) {
this.values = values != null ? values : new Object[0];
}

/**
* Create a new {@link PlaceholderValues} object with
*/
public static PlaceholderValues of(Object... values) {
return new PlaceholderValues(values);
}

/**
* Get value of the placeholder with the particular index
*
* @param index Index of the placeholder
* @return Value of the placeholder with the given index
* @throws IllegalArgumentException if placeholder index is out of bounds (fewer values than placeholders)
*/
public Object getValue(int index) {
if (index < 0 || index >= values.length) {
throw new IllegalArgumentException("Missing value for placeholder ?" + index);
}
return values[index];
}

/**
* Get overall amount of the given values
*/
public int size() {
return values.length;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
package com.aerospike.dsl;
package com.aerospike.dsl.api;

import com.aerospike.client.query.Filter;
import com.aerospike.dsl.DslParseException;
import com.aerospike.dsl.ExpressionContext;
import com.aerospike.dsl.Index;
import com.aerospike.dsl.IndexContext;
import com.aerospike.dsl.ParsedExpression;

/**
* Contains API to convert dot separated String path into an Aerospike filter -
Expand All @@ -17,7 +22,7 @@
public interface DSLParser {

/**
* Parse String DSL path into Aerospike filter Expression.
* Parse DSL path into Aerospike filter Expression.
* <br><br>
* Examples:
* <table border="1">
Expand Down Expand Up @@ -82,11 +87,12 @@ public interface DSLParser {
* </tr>
* </table>
*
* @param dslString String consisting of dot separated elements, typically bin name and optional context
* @param input {@link ExpressionContext} containing input string of dot separated elements. If the input string has
* placeholders, matching values must be provided within {@code input} too
* @return {@link ParsedExpression} object
* @throws DslParseException in case of invalid syntax
*/
ParsedExpression parseExpression(String dslString);
ParsedExpression parseExpression(ExpressionContext input);

/**
* Parse String DSL path into Aerospike filter Expression.
Expand Down Expand Up @@ -154,11 +160,12 @@ public interface DSLParser {
* </tr>
* </table>
*
* @param dslString String consisting of dot separated elements, typically bin name and optional context
* @param input {@link ExpressionContext} containing input string of dot separated elements. If the input string has
* placeholders, matching values must be provided within {@code input} too
* @param indexContext Class containing namespace and collection of {@link Index} objects that represent
* existing secondary indexes. Required for creating {@link Filter}. Can be null
* @return {@link ParsedExpression} object
* @throws DslParseException in case of invalid syntax
*/
ParsedExpression parseExpression(String dslString, IndexContext indexContext);
ParsedExpression parseExpression(ExpressionContext input, IndexContext indexContext);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
package com.aerospike.dsl;
package com.aerospike.dsl.impl;

import com.aerospike.dsl.ConditionLexer;
import com.aerospike.dsl.ConditionParser;
import com.aerospike.dsl.DslParseException;
import com.aerospike.dsl.ExpressionContext;
import com.aerospike.dsl.Index;
import com.aerospike.dsl.IndexContext;
import com.aerospike.dsl.ParsedExpression;
import com.aerospike.dsl.PlaceholderValues;
import com.aerospike.dsl.annotation.Beta;
import com.aerospike.dsl.api.DSLParser;
import com.aerospike.dsl.parts.AbstractPart;
import com.aerospike.dsl.visitor.ExpressionConditionVisitor;
import org.antlr.v4.runtime.CharStreams;
Expand All @@ -17,15 +26,15 @@
public class DSLParserImpl implements DSLParser {

@Beta
public ParsedExpression parseExpression(String dslString) {
ParseTree parseTree = getParseTree(dslString);
return getParsedExpression(parseTree, null);
public ParsedExpression parseExpression(ExpressionContext expressionContext) {
ParseTree parseTree = getParseTree(expressionContext.getExpression());
return getParsedExpression(parseTree, expressionContext.getValues(), null);
}

@Beta
public ParsedExpression parseExpression(String input, IndexContext indexContext) {
ParseTree parseTree = getParseTree(input);
return getParsedExpression(parseTree, indexContext);
public ParsedExpression parseExpression(ExpressionContext expressionContext, IndexContext indexContext) {
ParseTree parseTree = getParseTree(expressionContext.getExpression());
return getParsedExpression(parseTree, expressionContext.getValues(), indexContext);
}

private ParseTree getParseTree(String input) {
Expand All @@ -34,7 +43,8 @@ private ParseTree getParseTree(String input) {
return parser.parse();
}

private ParsedExpression getParsedExpression(ParseTree parseTree, IndexContext indexContext) {
private ParsedExpression getParsedExpression(ParseTree parseTree, PlaceholderValues placeholderValues,
IndexContext indexContext) {
final String namespace = Optional.ofNullable(indexContext)
.map(IndexContext::getNamespace)
.orElse(null);
Expand All @@ -54,7 +64,8 @@ private ParsedExpression getParsedExpression(ParseTree parseTree, IndexContext i
if (resultingPart == null) {
throw new DslParseException("Could not parse given DSL expression input");
}

// Return the parsed tree along with indexes Map
return new ParsedExpression(resultingPart, indexesMap);
return new ParsedExpression(resultingPart, placeholderValues, indexesMap);
}
}
9 changes: 3 additions & 6 deletions src/main/java/com/aerospike/dsl/parts/AbstractPart.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,13 @@ public abstract class AbstractPart {
protected PartType partType;
protected Exp exp;
protected Filter filter;
protected boolean isPlaceholder;

protected AbstractPart(PartType partType) {
this.partType = partType;
this.exp = null;
}

protected AbstractPart(PartType partType, Filter filter) {
this.partType = partType;
this.filter = filter;
}

public enum PartType {
INT_OPERAND,
FLOAT_OPERAND,
Expand All @@ -45,6 +41,7 @@ public enum PartType {
PATH_FUNCTION,
METADATA_OPERAND,
EXPRESSION_CONTAINER,
VARIABLE_OPERAND
VARIABLE_OPERAND,
PLACEHOLDER_OPERAND
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
@Getter
public class ExpressionContainer extends AbstractPart {

protected final AbstractPart left;
protected final AbstractPart right;
@Setter
protected AbstractPart left;
@Setter
protected AbstractPart right;
private final boolean isUnary;
private final ExprPartsOperation operationType;
@Setter()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@

import com.aerospike.dsl.parts.AbstractPart;
import lombok.Getter;
import lombok.Setter;

import java.util.List;

@Getter
@Setter
public class WhenStructure extends AbstractPart {

private final List<AbstractPart> operands;
private List<AbstractPart> operands;

public WhenStructure(List<AbstractPart> operands) {
super(PartType.WHEN_STRUCTURE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@
import com.aerospike.dsl.parts.AbstractPart;
import lombok.Getter;

import static com.aerospike.dsl.parts.AbstractPart.PartType.BOOL_OPERAND;

@Getter
public class BooleanOperand extends AbstractPart implements ParsedValueOperand {

// Keeping the boxed type for interface compatibility
private final Boolean value;

public BooleanOperand(Boolean value) {
super(PartType.BOOL_OPERAND);
// Setting parent type
super(BOOL_OPERAND);
this.value = value;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
@Getter
public class FloatOperand extends AbstractPart implements ParsedValueOperand {

// Keeping the boxed type for interface compatibility
private final Double value;

public FloatOperand(Double value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
@Getter
public class IntOperand extends AbstractPart implements ParsedValueOperand {

// Keeping the boxed type for interface compatibility
private final Long value;

public IntOperand(Long value) {
Expand Down
Loading
Loading