use of org.apache.commons.jexl2.parser.JexlNodes.children in project datawave by NationalSecurityAgency.
the class DistributeAndedNodesVisitor method visit.
/**
* Checks each of the child nodes, and determines how the anded nodes should be applied.
*
* @param node
* The node that we will be distributing the anded nodes into
* @param data
* The nodes which we will be distributing into the root node
* @return An updated script with the anded nodes distributed throughout
*/
@Override
public Object visit(ASTOrNode node, Object data) {
DistributeAndedNodesVisitor.DistAndData parentData = (DistributeAndedNodesVisitor.DistAndData) data;
if (initialNode == null || initialNode instanceof ASTReference || initialNode instanceof ASTReferenceExpression)
initialNode = node;
// if this node is one of the anded nodes, or a whindex
// comprised of one of the anded nodes, halt recursion
List<JexlNode> usedAndedNodes = usesAndedNodes(node);
if (!usedAndedNodes.isEmpty()) {
parentData.usedAndedNodes.addAll(usedAndedNodes);
return node;
}
// this logic is dependent upon identifying whindex nodes by their address
if (whindexNodes.containsKey(node)) {
return node;
}
boolean rebuildNode = false;
// check each child node
List<JexlNode> nodesMissingEverything = new ArrayList<>();
List<JexlNode> nodesWithEverything = new ArrayList<>();
Map<JexlNode, List<JexlNode>> nodesMissingSomething = new LinkedHashMap<>();
for (JexlNode child : JexlNodes.children(node)) {
DistributeAndedNodesVisitor.DistAndData foundData = new DistributeAndedNodesVisitor.DistAndData();
JexlNode processedChild = (JexlNode) child.jjtAccept(this, foundData);
if (processedChild != child)
rebuildNode = true;
if (foundData.usedAndedNodes.isEmpty())
nodesMissingEverything.add(processedChild);
else if (!foundData.usedAndedNodes.containsAll(andedNodes)) {
List<JexlNode> missingAndedNodes = new ArrayList<>(andedNodes);
missingAndedNodes.removeAll(foundData.usedAndedNodes);
nodesMissingSomething.put(processedChild, missingAndedNodes);
} else
nodesWithEverything.add(processedChild);
}
// if none of the children are missing anything, we're done
if (nodesWithEverything.size() == node.jjtGetNumChildren()) {
parentData.usedAndedNodes.addAll(andedNodes);
if (rebuildNode)
return WhindexVisitor.createUnwrappedOrNode(nodesWithEverything);
else
return node;
} else // are missing everything, it implies that the children were left as-is
if (nodesMissingEverything.size() == node.jjtGetNumChildren()) {
return node;
}
// if we got here, then there are some nodes missing SOMETHING, and we have work to do
List<JexlNode> rebuiltChildren = new ArrayList<>();
// andedNodes
for (Map.Entry<JexlNode, List<JexlNode>> childEntry : nodesMissingSomething.entrySet()) rebuiltChildren.add(DistributeAndedNodesVisitor.distributeAndedNode(childEntry.getKey(), childEntry.getValue(), whindexNodes));
// for children missing everything -> 'or' them together, then 'and' them with the full set of andedNodes
List<JexlNode> nodeList = andedNodes.stream().map(RebuildingVisitor::copy).collect(Collectors.toList());
if (!nodesMissingEverything.isEmpty()) {
nodeList.add(WhindexVisitor.createUnwrappedOrNode(nodesMissingEverything));
}
rebuiltChildren.add(WhindexVisitor.createUnwrappedAndNode(nodeList));
// for children with everything -> keep those as-is
rebuiltChildren.addAll(nodesWithEverything);
parentData.usedAndedNodes.addAll(andedNodes);
return WhindexVisitor.createUnwrappedOrNode(rebuiltChildren);
}
use of org.apache.commons.jexl2.parser.JexlNodes.children in project datawave by NationalSecurityAgency.
the class TreeFlatteningRebuilder method copyTree.
/**
* Iteratively creates a copy of the passed in JexlNode
*
* @param node
* the node to be copied
* @param postOrderDeque
* the post order traversal of the copied tree
* @return the copied tree
*/
private JexlNode copyTree(JexlNode node, Deque<JexlNode> postOrderDeque) {
// add all the nodes to the stack and iterate...
Deque<JexlNode> workingStack = new LinkedList<>();
// create a copy of this node which shares the same children as the original node
JexlNode copiedNode = rebuildNode(node);
workingStack.push(copiedNode);
// compute the post order traversal of all of the nodes, and copy them
while (!workingStack.isEmpty()) {
JexlNode poppedNode = workingStack.pop();
postOrderDeque.push(poppedNode);
// if this node has children, create copies of them
if (poppedNode.jjtGetNumChildren() > 0) {
List<JexlNode> copiedChildren = new ArrayList<>();
List<JexlNode> children = (poppedNode instanceof ASTAndNode || poppedNode instanceof ASTOrNode) ? getAndOrLeaves(poppedNode) : Arrays.asList(children(poppedNode));
for (JexlNode child : children) {
if (child != null) {
// create a copy of this node which shares the same children as the original node
JexlNode copiedChild = rebuildNode(child);
copiedChildren.add(copiedChild);
workingStack.push(copiedChild);
}
}
// Reassign the children for this copied node
JexlNodes.children(poppedNode, copiedChildren.toArray(new JexlNode[0]));
}
}
return copiedNode;
}
use of org.apache.commons.jexl2.parser.JexlNodes.children in project datawave by NationalSecurityAgency.
the class WhindexVisitor method visit.
/**
* Descends into each of the child nodes, and rebuilds the 'or' node with both the unmodified and modified nodes. Ancestor anded nodes are passed down to
* each child, and the foundWhindex flag is passed up from the children.
*
* @param node
* An 'or' node from the original script
* @param data
* ExpandData, containing ancestor anded nodes, used anded nodes, and a flag indicating whether whindexes were found
* @return An expanded version of the 'or' node containing whindex nodes, if found, or the original in node, if not found
*/
@Override
public Object visit(ASTOrNode node, Object data) {
ExpandData parentData = (ExpandData) data;
// this shouldn't ever really happen, but it could
if (node.jjtGetNumChildren() == 1)
return super.visit(node, data);
// iterate over the children and attempt to create whindexes
List<JexlNode> unmodifiedNodes = new ArrayList<>();
List<JexlNode> modifiedNodes = new ArrayList<>();
List<String> modifiedNodesAsString = new ArrayList<>();
for (JexlNode child : JexlNodes.children(node)) {
ExpandData eData = new ExpandData();
// add the anded leaf nodes from our ancestors
eData.andedNodes.putAll(parentData.andedNodes);
JexlNode processedNode = (JexlNode) child.jjtAccept(this, eData);
String processedNodeAsString = JexlStringBuildingVisitor.buildQuery(processedNode);
// and keep track of the used anded nodes
if (eData.foundWhindex) {
// the same final node. use this check to eliminate dupes
if (!modifiedNodesAsString.contains(processedNodeAsString)) {
modifiedNodes.add(processedNode);
modifiedNodesAsString.add(processedNodeAsString);
parentData.foundWhindex = true;
parentData.usedAndedNodes.putAll(eData.usedAndedNodes);
}
} else
unmodifiedNodes.add(child);
}
// otherwise, return the original or node
if (parentData.foundWhindex) {
List<JexlNode> processedNodes = new ArrayList<>();
processedNodes.addAll(unmodifiedNodes);
processedNodes.addAll(modifiedNodes);
return createUnwrappedOrNode(processedNodes);
} else
return copy(node);
}
use of org.apache.commons.jexl2.parser.JexlNodes.children in project datawave by NationalSecurityAgency.
the class FunctionJexlNodeVisitor method makeFunctionFrom.
public static ASTFunctionNode makeFunctionFrom(String ns, String functionName, JexlNode... arguments) {
ASTFunctionNode fn = new ASTFunctionNode(ParserTreeConstants.JJTFUNCTIONNODE);
ASTIdentifier namespace = JexlNodes.makeIdentifierWithImage(ns);
ASTIdentifier function = JexlNodes.makeIdentifierWithImage(functionName);
ArrayList<JexlNode> nodes = Lists.newArrayList();
nodes.add(namespace);
nodes.add(function);
Collections.addAll(nodes, arguments);
return JexlNodes.children(fn, nodes.toArray(new JexlNode[nodes.size()]));
}
use of org.apache.commons.jexl2.parser.JexlNodes.children in project datawave by NationalSecurityAgency.
the class ExpandMultiNormalizedTerms method expandRangeForNormalizers.
private Object expandRangeForNormalizers(LiteralRange<?> range, JexlNode node) {
List<BoundedRange> aliasedBounds = Lists.newArrayList();
String field = range.getFieldName();
// Get all of the indexed or normalized dataTypes for the field name
Set<Type<?>> dataTypes = Sets.newHashSet(config.getQueryFieldsDatatypes().get(field));
dataTypes.addAll(config.getNormalizedFieldsDatatypes().get(field));
for (Type<?> normalizer : dataTypes) {
JexlNode lowerBound = range.getLowerNode(), upperBound = range.getUpperNode();
JexlNode left = null;
try {
left = JexlASTHelper.applyNormalization(copy(lowerBound), normalizer);
} catch (Exception ne) {
if (log.isTraceEnabled()) {
log.trace("Could not normalize " + PrintingVisitor.formattedQueryString(lowerBound) + " using " + normalizer.getClass() + ". " + ne.getMessage());
}
continue;
}
JexlNode right = null;
try {
right = JexlASTHelper.applyNormalization(copy(upperBound), normalizer);
} catch (Exception ne) {
if (log.isTraceEnabled()) {
log.trace("Could not normalize " + PrintingVisitor.formattedQueryString(upperBound) + " using " + normalizer.getClass() + ". " + ne.getMessage());
}
continue;
}
aliasedBounds.add(new BoundedRange(JexlNodes.children(new ASTAndNode(ParserTreeConstants.JJTANDNODE), left, right)));
}
if (aliasedBounds.isEmpty()) {
return node;
} else {
this.expandedNodes.addAll(aliasedBounds);
// Avoid extra parens around the expansion
if (1 == aliasedBounds.size()) {
return aliasedBounds.get(0);
} else {
List<ASTReferenceExpression> var = JexlASTHelper.wrapInParens(aliasedBounds);
return JexlNodes.wrap(JexlNodes.children(new ASTOrNode(ParserTreeConstants.JJTORNODE), var.toArray(new JexlNode[var.size()])));
}
}
}
Aggregations