The current BaseIteratingStage is a bit strange: it iterates across the collection of items, applying the template execution method to each one and then optionally removes items from the collection.
There are very few (ultimate) subclasses which don't fall into one of the two patterns:
- Iterating: Execute some function on each item, or
- Filtering: Look at each item, and remove items if some condition is true.
We should refactor this so that those two cases have independent base classes.
This would also allow us to add a template method to the pure iterating case to say whether the item is appropriate to have the execution method applied to it. This could be used in the abstract class for iterations to allow a Predicate<Item<T>> to be plugged in to determinate this: this would allow much simpler conditional execution on the basis of, say, ItemID item metadata than is possible at present.
There are a couple of stages which don't fall into this new bifurcation: for example, there's a SAML-specific stage that works with an item which may have EntitiesDescriptor elements, removing those elements or the entire item as appropriate. I don't think I'd have written that to start with (I think it would be better to smash down to individual items for each entity, then filter the individual entities) and might want to deprecate it at some point, but we might need to keep the current BaseIteratingStage around to support that kind of use case.
So, two options: add a new BaseExecutingStage and keep BaseIteratingStage but maybe deprecate it, or use BaseIteratingStage for the plain iterating case. In each case, add a BaseFilteringStage with the filtering pattern as well and migrate our filtering stages across to that.