Refactored for generality.