use of org.apache.commons.jexl3.parser.ASTIdentifier in project datawave by NationalSecurityAgency.
the class WhindexTerm method createWhindexNode.
public JexlNode createWhindexNode() {
JexlNode copiedNode = RebuildingVisitor.copy(mappableNode);
List<ASTIdentifier> identifiers = JexlASTHelper.getIdentifiers(copiedNode);
Set<String> fieldNames = new HashSet<>();
identifiers.forEach(x -> fieldNames.add(JexlASTHelper.getIdentifier(x)));
if (fieldNames.size() == 1) {
for (ASTIdentifier identifier : identifiers) {
JexlNodes.replaceChild(identifier.jjtGetParent(), identifier, JexlNodes.makeIdentifierWithImage(newFieldName));
}
} else {
throw new RuntimeException("Cannot create a Whindex term using multiple identifiers.");
}
return copiedNode;
}
use of org.apache.commons.jexl3.parser.ASTIdentifier in project datawave by NationalSecurityAgency.
the class TLDEventDataFilter method extractQueryFieldsFromScript.
/**
* Extract the query fields from the script and sort them
*
* @param script
*/
private void extractQueryFieldsFromScript(ASTJexlScript script) {
queryFields = new ArrayList<>();
String field;
List<ASTIdentifier> identifiers = JexlASTHelper.getIdentifiers(script);
for (ASTIdentifier identifier : identifiers) {
field = JexlASTHelper.deconstructIdentifier(identifier);
if (!queryFields.contains(field)) {
queryFields.add(field);
}
}
// sort the queryFields
Collections.sort(queryFields);
queryFields = Collections.unmodifiableList(queryFields);
}
use of org.apache.commons.jexl3.parser.ASTIdentifier in project datawave by NationalSecurityAgency.
the class QueryModelVisitor method expandBinaryNodeFromModel.
/**
* Applies the forward mapping from the QueryModel to a node, expanding the node into an Or if needed.
*
* @param node
* @param data
* @return
*/
protected JexlNode expandBinaryNodeFromModel(JexlNode node, Object data) {
String field = JexlASTHelper.getIdentifier(node);
if (isFieldExcluded(field)) {
return node;
}
// Count the immediate children:
int childCount = node.jjtGetNumChildren();
if (childCount != 2) {
QueryException qe = new QueryException(DatawaveErrorCode.BINARY_NODE_TOO_MANY_CHILDREN, MessageFormat.format("Node: {0}", PrintingVisitor.formattedQueryString(node)));
throw new DatawaveFatalQueryException(qe);
}
// Find identifiers
List<ASTIdentifier> allidentifiers = JexlASTHelper.getIdentifiers(node);
// If we don't have any identifiers, we have nothing to expand
if (allidentifiers.isEmpty()) {
return node;
}
JexlNode leftNode = node.jjtGetChild(0);
JexlNode rightNode = node.jjtGetChild(1);
if (log.isTraceEnabled()) {
log.trace("leftNode:" + PrintingVisitor.formattedQueryString(leftNode));
log.trace("leftNodeQuery:" + JexlStringBuildingVisitor.buildQuery(leftNode));
log.trace("rightNode:" + PrintingVisitor.formattedQueryString(rightNode));
log.trace("rightNodeQuery:" + JexlStringBuildingVisitor.buildQuery(rightNode));
}
// this will expand identifiers that have a method connected to them
boolean leftState = JexlASTHelper.HasMethodVisitor.hasMethod(leftNode);
if (leftState) {
// there is a method under leftNode
leftNode = (JexlNode) leftNode.jjtAccept(this.simpleQueryModelVisitor, null);
}
boolean rightState = JexlASTHelper.HasMethodVisitor.hasMethod(rightNode);
if (rightState) {
// there is a method under rightNode
rightNode = (JexlNode) rightNode.jjtAccept(this.simpleQueryModelVisitor, null);
}
// expand any identifiers inside of methods/functions in the left and right nodes
leftNode = (JexlNode) leftNode.jjtAccept(this, null);
rightNode = (JexlNode) rightNode.jjtAccept(this, null);
if (log.isTraceEnabled()) {
log.trace("after expansion, leftNode:" + PrintingVisitor.formattedQueryString(leftNode));
log.trace("after expansion, leftNodeQuery:" + JexlStringBuildingVisitor.buildQuery(leftNode));
log.trace("after expansion, rightNode:" + PrintingVisitor.formattedQueryString(rightNode));
log.trace("after expansion, rightNodeQuery:" + JexlStringBuildingVisitor.buildQuery(rightNode));
}
// if state == true on either side, then there is a method on one side and we are done applying the model
if (leftState || rightState) {
JexlNode toReturn = JexlNodeFactory.buildUntypedBinaryNode(node, leftNode, rightNode);
if (log.isTraceEnabled()) {
log.trace("done early. returning:" + JexlStringBuildingVisitor.buildQuery(toReturn));
}
return toReturn;
}
JexlNode leftSeed, rightSeed;
Set<JexlNode> left = Sets.newHashSet(), right = Sets.newHashSet();
boolean isNullEquality = false;
if (node instanceof ASTEQNode && (leftNode instanceof ASTNullLiteral || rightNode instanceof ASTNullLiteral)) {
isNullEquality = true;
}
// the query has been previously groomed so that identifiers are on the left and literals are on the right
// an identifier with a method attached will have already been substituted above (and will return null for the IdentifierOpLiteral)
// The normal case of `IDENTIFIER op 'literal'`
JexlASTHelper.IdentifierOpLiteral op = JexlASTHelper.getIdentifierOpLiteral(node);
if (op != null) {
// One identifier
leftSeed = op.getIdentifier();
rightSeed = op.getLiteral();
if (rightSeed instanceof ASTNullLiteral && node instanceof ASTEQNode) {
isNullEquality = true;
}
} else {
// We know from above that childCount == 2. We may have a reference on both sides of the expression
leftSeed = node.jjtGetChild(0);
rightSeed = node.jjtGetChild(1);
}
if (leftSeed instanceof ASTReference) {
// String fieldName = JexlASTHelper.getIdentifier((JexlNode)leftSeed);
List<ASTIdentifier> identifiers = JexlASTHelper.getIdentifiers(leftSeed);
if (identifiers.size() > 1) {
log.warn("I did not expect to see more than one Identifier here for " + JexlStringBuildingVisitor.buildQuery(leftSeed) + " from " + JexlStringBuildingVisitor.buildQuery(leftNode));
}
for (ASTIdentifier identifier : identifiers) {
for (String fieldName : getAliasesForField(JexlASTHelper.deconstructIdentifier(identifier))) {
left.add(JexlNodeFactory.buildIdentifier(fieldName));
}
}
} else if (leftSeed instanceof ASTIdentifier) {
for (String fieldName : getAliasesForField(JexlASTHelper.deconstructIdentifier((ASTIdentifier) leftSeed))) {
left.add(JexlNodeFactory.buildIdentifier(fieldName));
}
} else {
// Not an identifier, therefore it's probably a literal
left.add(leftSeed);
}
if (rightSeed instanceof ASTReference) {
List<ASTIdentifier> identifiers = JexlASTHelper.getIdentifiers(rightSeed);
if (identifiers.size() > 1) {
log.warn("I did not expect to see more than one Identifier here for " + JexlStringBuildingVisitor.buildQuery(rightSeed) + " from " + JexlStringBuildingVisitor.buildQuery(rightNode));
}
for (ASTIdentifier identifier : identifiers) {
for (String fieldName : getAliasesForField(JexlASTHelper.deconstructIdentifier(identifier))) {
right.add(JexlNodeFactory.buildIdentifier(fieldName));
}
}
} else if (rightSeed instanceof ASTIdentifier) {
for (String fieldName : getAliasesForField(JexlASTHelper.deconstructIdentifier((ASTIdentifier) rightSeed))) {
right.add(JexlNodeFactory.buildIdentifier(fieldName));
}
} else {
// Not an identifier, therefore it's probably a literal
right.add(rightSeed);
}
boolean requiresAnd = isNullEquality || node instanceof ASTNENode;
@SuppressWarnings("unchecked") Set<List<JexlNode>> // retrieve the cartesian product
product = Sets.cartesianProduct(left, right);
/**
* use the product transformer to shallow copy the jexl nodes. We've created new nodes that will be embedded within an ast reference. As a result, we
* need to ensure that if we create a logical structure ( such as an or ) -- each literal references a unique identifier from the right. Otherwise,
* subsequent visitors will reference incorrection sub trees, and potentially negate the activity of the query model visitor
*/
Set<List<JexlNode>> newSet = product.stream().map(list -> list.stream().map(RebuildingVisitor::copy).collect(Collectors.toList())).collect(Collectors.toSet());
if (product.size() > 1) {
JexlNode expanded;
if (requiresAnd) {
expanded = JexlNodeFactory.createNodeTreeFromPairs(ContainerType.AND_NODE, node, newSet);
} else {
expanded = JexlNodeFactory.createNodeTreeFromPairs(ContainerType.OR_NODE, node, newSet);
}
if (log.isTraceEnabled())
log.trace("expanded:" + PrintingVisitor.formattedQueryString(expanded));
return expanded;
} else if (1 == product.size()) {
List<JexlNode> pair = product.iterator().next();
JexlNode expanded = JexlNodeFactory.buildUntypedBinaryNode(node, pair.get(0), pair.get(1));
if (log.isTraceEnabled())
log.trace("expanded:" + PrintingVisitor.formattedQueryString(expanded));
return expanded;
}
// If we couldn't map anything, return a copy
if (log.isTraceEnabled())
log.trace("just returning the original:" + PrintingVisitor.formattedQueryString(node));
return node;
}
use of org.apache.commons.jexl3.parser.ASTIdentifier in project datawave by NationalSecurityAgency.
the class JexlControlledQueryParser method checkIfQueryAllowed.
private void checkIfQueryAllowed(String query) throws ParseException {
JexlNode node;
try {
node = JexlASTHelper.parseJexlQuery(query);
} catch (Throwable e) {
throw new ParseException(e.getMessage());
}
Set<String> fields = new TreeSet<>();
List<ASTIdentifier> idList = JexlASTHelper.getIdentifiers(node);
for (ASTIdentifier id : idList) {
String fieldName = id.image;
if (!StringUtils.isEmpty(fieldName)) {
fieldName = fieldName.trim().toUpperCase();
if (fieldName.charAt(0) == '$') {
fields.add(fieldName.substring(1));
} else {
fields.add(fieldName);
}
}
}
fields.removeAll(allowedFields);
if (!fields.isEmpty()) {
throw new ParseException("Unallowed field(s) '" + fields + "' for this type of query");
}
}
use of org.apache.commons.jexl3.parser.ASTIdentifier in project datawave by NationalSecurityAgency.
the class RangeStream method containsIndexOnlyFields.
protected boolean containsIndexOnlyFields(JexlNode node) throws TableNotFoundException {
List<ASTIdentifier> identifiers = JexlASTHelper.getIdentifiers(node);
Set<String> indexOnlyFields = metadataHelper.getIndexOnlyFields(config.getDatatypeFilter());
// Hack to get around the extra ASTIdentifier left in the AST by the threshold marker node
Iterator<ASTIdentifier> iter = identifiers.iterator();
while (iter.hasNext()) {
ASTIdentifier id = iter.next();
if (ExceededValueThresholdMarkerJexlNode.label().equals(id.image) || ExceededTermThresholdMarkerJexlNode.label().equals(id.image) || ExceededOrThresholdMarkerJexlNode.label().equals(id.image)) {
iter.remove();
}
}
for (ASTIdentifier identifier : identifiers) {
String fieldName = JexlASTHelper.deconstructIdentifier(identifier);
if (indexOnlyFields.contains(fieldName)) {
return true;
}
}
return false;
}
Aggregations