refactored to use templates