package rocks.inspectit.ui.rcp.ci.form.part.business;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.Viewer;
import org.springframework.util.CollectionUtils;
import rocks.inspectit.shared.cs.ci.business.expression.AbstractExpression;
import rocks.inspectit.shared.cs.ci.business.expression.IContainerExpression;
/**
* Content provider for the tree viewer that displays the expression tree.
*
* @author Alexander Wert
*
*/
public final class OperandTreeContentProvider implements ITreeContentProvider {
/**
* This map holds the child parent relationship.
*/
private final Map<Object, Object> parentMap = new HashMap<>();
/**
* root expression.
*/
private AbstractExpression rootExpression;
/**
* {@inheritDoc}
*/
@Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
parentMap.clear();
if (newInput instanceof TreeInput) {
rootExpression = ((TreeInput) newInput).getExpression();
}
}
/**
* {@inheritDoc}
*/
@Override
public Object[] getElements(Object inputElement) {
if (inputElement instanceof TreeInput) {
AbstractExpression expression = ((TreeInput) inputElement).getExpression();
if (null != expression) {
return new Object[] { expression };
}
}
return new Object[0];
}
/**
* {@inheritDoc}
*/
@Override
public Object[] getChildren(Object parentElement) {
if (parentElement instanceof IContainerExpression) {
return ((IContainerExpression) parentElement).getOperands().toArray();
}
return new Object[0];
}
/**
* {@inheritDoc}
*/
@Override
public Object getParent(Object element) {
// needed for direct expansion of the elements
Object parent = null;
if (element instanceof AbstractExpression) {
if (element.equals(rootExpression)) {
return null;
}
parent = parentMap.get(element);
if (null == parent) {
parent = searchParent(rootExpression, (AbstractExpression) element);
parentMap.put(element, parent);
}
}
return parent;
}
/**
* {@inheritDoc}
*/
@Override
public boolean hasChildren(Object element) {
if (element instanceof IContainerExpression) {
return !((IContainerExpression) element).getOperands().isEmpty();
}
return false;
}
/**
* Searches parent for the target {@link AbstractExpression} beginning from the root element.
* This is a recursive method.
*
* @param parentCandidate
* parent candidate to check
* @param target
* target {@link AbstractExpression} instance
* @return the parent of the target {@link AbstractExpression} instance or null, if target is a
* root element.
*/
private AbstractExpression searchParent(AbstractExpression parentCandidate, AbstractExpression target) {
if (null == parentCandidate || parentCandidate.equals(target)) {
return null;
}
List<? extends AbstractExpression> children = null;
if (parentCandidate instanceof IContainerExpression) {
children = ((IContainerExpression) parentCandidate).getOperands();
}
if (CollectionUtils.isEmpty(children)) {
return null;
}
for (AbstractExpression child : children) {
if (target.equals(child)) {
return parentCandidate;
} else {
AbstractExpression childResult = searchParent(child, target);
if (null != childResult) {
return childResult;
}
}
}
return null;
}
/**
* {@inheritDoc}
*/
@Override
public void dispose() {
}
/**
* Wrapper class for the tree input to avoid infinite recursion that may occur when using the
* same class for the input and the tree elements.
*
* @author Alexander Wert
*
*/
public static class TreeInput {
/**
* Root expression.
*/
private final AbstractExpression expression;
/**
* Constructor.
*
* @param expression
* root expression.
*/
TreeInput(AbstractExpression expression) {
this.expression = expression;
}
/**
* Gets {@link #expression}.
*
* @return {@link #expression}
*/
public AbstractExpression getExpression() {
return expression;
}
}
}