package jalview.datamodel.features;
import jalview.datamodel.SequenceFeature;
import jalview.util.matcher.Condition;
import jalview.util.matcher.Matcher;
import jalview.util.matcher.MatcherI;
/**
* An immutable class that models one or more match conditions, each of which is
* applied to the value obtained by lookup given the match key.
*
* For example, the value provider could be a SequenceFeature's attributes map,
* and the conditions might be
*
* - CSQ contains "pathological"
* - AND
* - AF <= 1.0e-5
*
*
* @author gmcarstairs
*
*/
public class FeatureMatcher implements FeatureMatcherI
{
private static final String COLON = ":";
/*
* if true, match is against feature description
*/
final private boolean byLabel;
/*
* if true, match is against feature score
*/
final private boolean byScore;
/*
* if not null, match is against feature attribute [sub-attribute]
*/
final private String[] key;
final private MatcherI matcher;
/**
* A factory constructor method for a matcher that applies its match condition
* to the feature label (description)
*
* @param cond
* @param pattern
* @return
*/
public static FeatureMatcher byLabel(Condition cond, String pattern)
{
return new FeatureMatcher(new Matcher(cond, pattern), true, false,
null);
}
/**
* A factory constructor method for a matcher that applies its match condition
* to the feature score
*
* @param cond
* @param pattern
* @return
*/
public static FeatureMatcher byScore(Condition cond, String pattern)
{
return new FeatureMatcher(new Matcher(cond, pattern), false, true,
null);
}
/**
* A factory constructor method for a matcher that applies its match condition
* to the named feature attribute [and optional sub-attribute]
*
* @param cond
* @param pattern
* @param attName
* @return
*/
public static FeatureMatcher byAttribute(Condition cond, String pattern,
String... attName)
{
return new FeatureMatcher(new Matcher(cond, pattern), false, false,
attName);
}
private FeatureMatcher(Matcher m, boolean forLabel, boolean forScore,
String[] theKey)
{
key = theKey;
matcher = m;
byLabel = forLabel;
byScore = forScore;
}
@Override
public boolean matches(SequenceFeature feature)
{
String value = byLabel ? feature.getDescription()
: (byScore ? String.valueOf(feature.getScore())
: feature.getValueAsString(key));
return matcher.matches(value);
}
@Override
public String[] getKey()
{
return key;
}
@Override
public MatcherI getMatcher()
{
return matcher;
}
/**
* Answers a string description of this matcher, suitable for display, debugging
* or logging. The format may change in future.
*/
@Override
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append(String.join(COLON, key)).append(" ")
.append(matcher.getCondition().toString());
Condition condition = matcher.getCondition();
if (condition.isNumeric())
{
sb.append(" ").append(matcher.getPattern());
}
else if (condition.needsAPattern())
{
sb.append(" '").append(matcher.getPattern()).append("'");
}
return sb.toString();
}
}