--- /dev/null
+package jalview.datamodel.features;
+
+import jalview.datamodel.SequenceFeature;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class FeatureMatcherSet implements FeatureMatcherSetI
+{
+ List<FeatureMatcherI> matchConditions;
+
+ boolean andConditions;
+
+ /**
+ * Constructor
+ */
+ public FeatureMatcherSet()
+ {
+ matchConditions = new ArrayList<>();
+ }
+
+ @Override
+ public boolean matches(SequenceFeature feature)
+ {
+ /*
+ * no conditions matches anything
+ */
+ if (matchConditions.isEmpty())
+ {
+ return true;
+ }
+
+ /*
+ * AND until failure
+ */
+ if (andConditions)
+ {
+ for (FeatureMatcherI m : matchConditions)
+ {
+ if (!m.matches(feature))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /*
+ * OR until match
+ */
+ for (FeatureMatcherI m : matchConditions)
+ {
+ if (m.matches(feature))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public FeatureMatcherSetI and(FeatureMatcherI m)
+ {
+ if (!andConditions && matchConditions.size() > 1)
+ {
+ throw new IllegalStateException("Can't add an AND to OR conditions");
+ }
+ matchConditions.add(m);
+ andConditions = true;
+
+ return this;
+ }
+
+ @Override
+ public FeatureMatcherSetI or(FeatureMatcherI m)
+ {
+ if (andConditions && matchConditions.size() > 1)
+ {
+ throw new IllegalStateException("Can't add an OR to AND conditions");
+ }
+ matchConditions.add(m);
+ andConditions = false;
+
+ return this;
+ }
+
+ @Override
+ public boolean isAnded()
+ {
+ return andConditions;
+ }
+
+ @Override
+ public Iterable<FeatureMatcherI> getMatchers()
+ {
+ return matchConditions;
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+ boolean first = true;
+ for (FeatureMatcherI matcher : matchConditions)
+ {
+ if (!first)
+ {
+ sb.append(andConditions ? " AND " : " OR ");
+ }
+ first = false;
+ sb.append("(").append(matcher.toString()).append(")");
+ }
+ return sb.toString();
+ }
+
+ @Override
+ public boolean isEmpty()
+ {
+ return matchConditions == null || matchConditions.isEmpty();
+ }
+
+}