@Override
    public CompletableFuture<Project> readSchemaMetadata(
            final Dbms dbms,
            final ProgressMeasure progress,
            final Predicate<String> filterCriteria) {

        requireNonNulls(filterCriteria, progress);

        // Create a deep copy of the project document.
        final Project projectCopy = DocumentUtil.deepCopy(
            projectComponent.getProject(), Project::create
        );

        // Make sure there are not multiple dbmses with the same id
        final Set<String> ids = new HashSet<>();
        if (!projectCopy.dbmses().map(Dbms::getId).allMatch(ids::add)) {
            final Set<String> duplicates = new HashSet<>();
            ids.clear();

            projectCopy.dbmses()
                .map(Dbms::getId)
                .forEach(s -> {
                    if (!ids.add(s)) {
                        duplicates.add(s);
                    }
                });

            throw new SpeedmentException(
                "The following dbmses have duplicates in the config document: "
                + duplicates
            );
        }

        // Locate the dbms in the copy.
        final Dbms dbmsCopy = projectCopy.dbmses()
            .filter(d -> d.getId().equals(dbms.getId()))
            .findAny().orElseThrow(() -> new SpeedmentException(
                "Could not find Dbms document in copy."
            ));

        return readSchemaMetadata(
            projectCopy, dbmsCopy, filterCriteria, progress
        ).whenCompleteAsync((project, ex) -> {
            progress.setProgress(ProgressMeasureUtil.DONE);
            if (ex != null) {
                progress.setCurrentAction("Error!");
                throw new SpeedmentException("Unable to read schema metadata.", ex);
            } else {
                progress.setCurrentAction("Done!");
            }
            LOGGER.info("Aggregate duration of metadata retrieval [ms]: " +
                timers.entrySet().stream()
                    .map(e -> String.format("%s=%,d", e.getKey().getSimpleName(), e.getValue().get()))
                .collect(joining(", "))
            );
        });
    }
@author  Emil Forslund
@author  Per Minborg
@since   3.0.0
runtime-parent/runtime-core/src/main/java/com/speedment/runtime/core/abstracts/AbstractDbmsMetadataHandler.java