package org.jboss.windup.rules.apps.java.condition.annotation;
import java.util.ArrayList;
import java.util.List;
import org.jboss.windup.config.GraphRewrite;
import org.jboss.windup.config.condition.EvaluationStrategy;
import org.jboss.windup.rules.apps.java.scan.ast.annotations.JavaAnnotationListTypeValueModel;
import org.jboss.windup.rules.apps.java.scan.ast.annotations.JavaAnnotationTypeValueModel;
import org.ocpsoft.rewrite.context.EvaluationContext;
import com.google.common.collect.Iterables;
/**
* <p>
* Matches on an item in an array within an annotation.
* </p>
*
* <p>
* For example, given the following annotation:
* </p>
*
* <pre>
* @Foo(value = { 1, 2, 3, 4 })
* </pre>
*
* <p>
* This could be created with an index and a literal condition like this:
*
* <pre>
* new AnnotationListCondition(1).addCondition(new AnnotationLiteralCondition("2"));
* </pre>
* </p>
*
* <p>
* If the "index" parameter is not specified, then all array entries will be searched. As long as at least one matches,
* then the condition will return true. This is useful in cases where the search is for a particular item that may
* occur at any point within an array.
* </p>
*
* @author <a href="mailto:jesse.sightler@gmail.com">Jesse Sightler</a>
*/
public class AnnotationListCondition extends AnnotationCondition
{
private static final int ANY = -1;
private final int index;
private List<AnnotationCondition> conditions = new ArrayList<>();
/**
* Creates a condition that will search all locations within the array.
*/
public AnnotationListCondition()
{
this(ANY);
}
/**
* Creates a condition that will search the given position within the array.
*/
public AnnotationListCondition(int index)
{
this.index = index;
}
/**
* Adds a condition that will be matched on the value in the array.
*/
public AnnotationListCondition addCondition(AnnotationCondition condition)
{
this.conditions.add(condition);
return this;
}
@Override
public String toString()
{
return "AnnotationListCondition{" +
"index=" + index +
", conditions=" + conditions +
'}';
}
@Override
public boolean evaluate(GraphRewrite event, EvaluationContext context, EvaluationStrategy strategy, JavaAnnotationTypeValueModel value)
{
if (!(value instanceof JavaAnnotationListTypeValueModel))
return false;
JavaAnnotationListTypeValueModel listTypeValueModel = (JavaAnnotationListTypeValueModel) value;
List<JavaAnnotationTypeValueModel> selectedValues = getSelectedValues(listTypeValueModel);
if (selectedValues == null)
return false;
boolean matched = false;
for (AnnotationCondition condition : conditions)
{
for (JavaAnnotationTypeValueModel subValue : listTypeValueModel)
{
if (condition.evaluate(event, context, strategy, subValue))
{
matched = true;
break;
}
}
if (matched)
break;
}
return matched;
}
private List<JavaAnnotationTypeValueModel> getSelectedValues(JavaAnnotationListTypeValueModel listTypeValueModel)
{
List<JavaAnnotationTypeValueModel> selectedValues = new ArrayList<>();
if (index == -1)
{
for (JavaAnnotationTypeValueModel listItem : listTypeValueModel)
{
selectedValues.add(listItem);
}
}
else
{
try
{
selectedValues.add(Iterables.get(listTypeValueModel, index));
}
catch (IndexOutOfBoundsException e)
{
return null;
}
}
return selectedValues;
}
}