refactor to make more extensible