factor out common functionality