refactored to use generics