Apply the visitor design pattern. TODO: finish