use of org.apache.commons.jexl2.parser.ASTReferenceExpression in project datawave by NationalSecurityAgency.
the class ExecutableExpansionVisitor method canExpand.
/**
* Test if the current node should be expanded by this visitor. Update the tracker with the current andChild if expansion is possible
*
* @param node
* the node to test
* @param tracker
* the tracker holding supplementary information about the expansion
* @return true if the expansion should occur, false otherwise
*/
private boolean canExpand(JexlNode node, ExecutableDeterminationVisitor.STATE state, ExpansionTracker tracker) {
// only process if state is ERROR or PARTIAL
if (!(state == ExecutableDeterminationVisitor.STATE.ERROR || state == ExecutableDeterminationVisitor.STATE.PARTIAL)) {
return false;
}
// if deeper down in the tree there was a failed expansion attempt, don't try again
if (tracker.isFailedExpansion()) {
return false;
}
// there must be an andNode further up the tree to distribute into the or
ASTAndNode lastAnd = tracker.getLastAnd();
// as long as there is a lastAnd there is work to do
if (lastAnd == null) {
return false;
}
// verify there is nothing but compatible nodes between the andNode and the orNode
JexlNode current = node.jjtGetParent();
JexlNode last = node;
while (current != lastAnd) {
if (!(current instanceof ASTReference || current instanceof ASTReferenceExpression)) {
return false;
}
last = current;
current = current.jjtGetParent();
}
// if we got here the expansion is good and we should track the andChild for later use
tracker.setAndChild(last);
return true;
}
use of org.apache.commons.jexl2.parser.ASTReferenceExpression 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.ASTReferenceExpression in project datawave by NationalSecurityAgency.
the class JexlStringBuildingVisitor method visit.
public Object visit(ASTAndNode node, Object data) {
StringBuilder sb = (StringBuilder) data;
int numChildren = node.jjtGetNumChildren();
JexlNode parent = node.jjtGetParent();
boolean wrapIt = false;
if (!(parent instanceof ASTReferenceExpression || parent instanceof ASTJexlScript || parent instanceof ASTAndNode || numChildren == 0)) {
wrapIt = true;
sb.append("(");
}
Collection<String> childStrings = (sortDedupeChildren) ? new TreeSet<>() : new ArrayList<>(numChildren);
StringBuilder childSB = new StringBuilder();
for (int i = 0; i < numChildren; i++) {
node.jjtGetChild(i).jjtAccept(this, childSB);
childStrings.add(childSB.toString());
childSB.setLength(0);
}
sb.append(String.join(" && ", childStrings));
if (wrapIt)
sb.append(")");
return data;
}
use of org.apache.commons.jexl2.parser.ASTReferenceExpression in project datawave by NationalSecurityAgency.
the class JexlNodeFactory method shallowCopy.
/**
* A shallow copy of the given JexlNode, creates a new node of the same type with the same parent and image. Children are not copied
*
* @param original
* @return
*/
public static JexlNode shallowCopy(JexlNode original) {
if (null == original) {
throw new IllegalArgumentException();
}
JexlNode copy;
Class<?> clz = original.getClass();
if (ASTAndNode.class.isAssignableFrom(clz)) {
copy = new ASTAndNode(ParserTreeConstants.JJTANDNODE);
} else if (ASTBitwiseAndNode.class.isAssignableFrom(clz)) {
copy = new ASTBitwiseAndNode(ParserTreeConstants.JJTBITWISEANDNODE);
} else if (ASTBitwiseComplNode.class.isAssignableFrom(clz)) {
copy = new ASTBitwiseComplNode(ParserTreeConstants.JJTBITWISECOMPLNODE);
} else if (ASTBitwiseOrNode.class.isAssignableFrom(clz)) {
copy = new ASTBitwiseOrNode(ParserTreeConstants.JJTBITWISEORNODE);
} else if (ASTBitwiseXorNode.class.isAssignableFrom(clz)) {
copy = new ASTBitwiseXorNode(ParserTreeConstants.JJTBITWISEXORNODE);
} else if (ASTEmptyFunction.class.isAssignableFrom(clz)) {
copy = new ASTEmptyFunction(ParserTreeConstants.JJTEMPTYFUNCTION);
} else if (ASTEQNode.class.isAssignableFrom(clz)) {
copy = new ASTEQNode(ParserTreeConstants.JJTEQNODE);
} else if (ASTERNode.class.isAssignableFrom(clz)) {
copy = new ASTERNode(ParserTreeConstants.JJTERNODE);
} else if (ASTFalseNode.class.isAssignableFrom(clz)) {
copy = new ASTFalseNode(ParserTreeConstants.JJTFALSENODE);
} else if (ASTGENode.class.isAssignableFrom(clz)) {
copy = new ASTGENode(ParserTreeConstants.JJTGENODE);
} else if (ASTGTNode.class.isAssignableFrom(clz)) {
copy = new ASTGTNode(ParserTreeConstants.JJTGTNODE);
} else if (ASTIdentifier.class.isAssignableFrom(clz)) {
copy = new ASTIdentifier(ParserTreeConstants.JJTIDENTIFIER);
} else if (ASTLENode.class.isAssignableFrom(clz)) {
copy = new ASTLENode(ParserTreeConstants.JJTLENODE);
} else if (ASTLTNode.class.isAssignableFrom(clz)) {
copy = new ASTLTNode(ParserTreeConstants.JJTLTNODE);
} else if (ASTNENode.class.isAssignableFrom(clz)) {
copy = new ASTNENode(ParserTreeConstants.JJTNENODE);
} else if (ASTNRNode.class.isAssignableFrom(clz)) {
copy = new ASTNRNode(ParserTreeConstants.JJTNRNODE);
} else if (ASTNotNode.class.isAssignableFrom(clz)) {
copy = new ASTNotNode(ParserTreeConstants.JJTNOTNODE);
} else if (ASTNullLiteral.class.isAssignableFrom(clz)) {
copy = new ASTNullLiteral(ParserTreeConstants.JJTNULLLITERAL);
} else if (ASTNumberLiteral.class.isAssignableFrom(clz)) {
copy = new ASTNumberLiteral(ParserTreeConstants.JJTNUMBERLITERAL);
JexlNodes.setLiteral((ASTNumberLiteral) copy, ((ASTNumberLiteral) original).getLiteral());
} else if (ASTOrNode.class.isAssignableFrom(clz)) {
copy = new ASTOrNode(ParserTreeConstants.JJTORNODE);
} else if (ASTStringLiteral.class.isAssignableFrom(clz)) {
copy = new ASTStringLiteral(ParserTreeConstants.JJTSTRINGLITERAL);
JexlNodes.setLiteral((ASTStringLiteral) copy, ((ASTStringLiteral) original).getLiteral());
} else if (ASTTrueNode.class.isAssignableFrom(clz)) {
copy = new ASTTrueNode(ParserTreeConstants.JJTTRUENODE);
} else if (ASTReferenceExpression.class.isAssignableFrom(clz)) {
copy = new ASTReferenceExpression(ParserTreeConstants.JJTREFERENCEEXPRESSION);
} else if (ASTReference.class.isAssignableFrom(clz)) {
copy = new ASTReference(ParserTreeConstants.JJTREFERENCE);
} else if (ASTAdditiveNode.class.isAssignableFrom(clz)) {
copy = new ASTAdditiveNode(ParserTreeConstants.JJTADDITIVENODE);
} else if (ASTMethodNode.class.isAssignableFrom(clz)) {
copy = new ASTMethodNode(ParserTreeConstants.JJTMETHODNODE);
} else if (ASTFunctionNode.class.isAssignableFrom(clz)) {
copy = new ASTFunctionNode(ParserTreeConstants.JJTFUNCTIONNODE);
} else if (ASTMulNode.class.isAssignableFrom(clz)) {
copy = new ASTMulNode(ParserTreeConstants.JJTMULNODE);
} else if (ASTAssignment.class.isAssignableFrom(clz)) {
copy = new ASTAssignment(ParserTreeConstants.JJTASSIGNMENT);
} else {
throw new UnsupportedOperationException();
}
copy.jjtSetParent(original.jjtGetParent());
copy.image = original.image;
return copy;
}
use of org.apache.commons.jexl2.parser.ASTReferenceExpression in project datawave by NationalSecurityAgency.
the class BooleanOptimizationRebuildingVisitor method prune.
/**
* Returns a tuple where the first element is the new node and the second element is the node that was pruned.
*
* @param currentNode
* @param newNode
* @param prunedNode
*/
private Tuple2<JexlNode, JexlNode> prune(JexlNode currentNode, JexlNode newNode, JexlNode prunedNode) {
for (int i = 0; i < currentNode.jjtGetNumChildren(); i++) {
JexlNode child = currentNode.jjtGetChild(i);
if (child instanceof ASTOrNode && child.jjtGetNumChildren() > prunedNode.jjtGetNumChildren()) {
if (prunedNode.jjtGetNumChildren() > 0) {
newNode.jjtAddChild(prunedNode, newNode.jjtGetNumChildren());
prunedNode.jjtSetParent(newNode);
}
prunedNode = child;
} else if (((child instanceof ASTReference) || (child instanceof ASTReferenceExpression) || child.getClass().equals(currentNode.getClass())) && hasChildOr(child)) {
Tuple2<JexlNode, JexlNode> nodes = prune(child, newNode, prunedNode);
newNode = nodes.first();
prunedNode = nodes.second();
} else {
newNode.jjtAddChild(child, newNode.jjtGetNumChildren());
child.jjtSetParent(newNode);
}
}
return new Tuple2<>(newNode, prunedNode);
}
Aggregations