public final void traverse() throws SchemaCrawlerException {

    final Collection<ColumnDataType> columnDataTypes = catalog.getColumnDataTypes();
    final Collection<Table> tables = catalog.getTables();
    final Collection<Routine> routines = catalog.getRoutines();
    final Collection<Synonym> synonyms = catalog.getSynonyms();
    final Collection<Sequence> sequences = catalog.getSequences();

    handler.begin();

    handler.handleHeaderStart();
    handler.handle(catalog.getCrawlInfo());
    handler.handleHeaderEnd();

    if (!tables.isEmpty()) {

      handler.handleTablesStart();

      final List<? extends Table> tablesList = new ArrayList<>(tables);
      Collections.sort(tablesList, tablesComparator);
      for (final Table table : tablesList) {
        handler.handle(table);
      }

      handler.handleTablesEnd();
    }

    if (!routines.isEmpty()) {
      handler.handleRoutinesStart();

      final List<? extends Routine> routinesList = new ArrayList<>(routines);
      Collections.sort(routinesList, routinesComparator);
      for (final Routine routine : routinesList) {
        handler.handle(routine);
      }

      handler.handleRoutinesEnd();
    }

    if (!sequences.isEmpty()) {
      handler.handleSequencesStart();
      for (final Sequence sequence : sequences) {
        handler.handle(sequence);
      }
      handler.handleSequencesEnd();
    }

    if (!synonyms.isEmpty()) {
      handler.handleSynonymsStart();
      for (final Synonym synonym : synonyms) {
        handler.handle(synonym);
      }
      handler.handleSynonymsEnd();
    }

    if (!columnDataTypes.isEmpty()) {
      handler.handleColumnDataTypesStart();
      for (final ColumnDataType columnDataType : columnDataTypes) {
        handler.handle(columnDataType);
      }
      handler.handleColumnDataTypesEnd();
    }

    handler.handleInfoStart();
    handler.handle(catalog.getSchemaCrawlerInfo());
    handler.handle(catalog.getDatabaseInfo());
    handler.handle(catalog.getJdbcDriverInfo());
    handler.handleInfoEnd();

    handler.end();
  }