lots of boilerplate added to make real use cleaner