public OpenAPI filter(OpenAPI openAPI, OpenAPISpecFilter filter, Map<String, List<String>> params, Map<String, String> cookies, Map<String, List<String>> headers) {
        OpenAPI filteredOpenAPI = filterOpenAPI(filter, openAPI, params, cookies, headers);
        if (filteredOpenAPI == null) {
            return filteredOpenAPI;
        }

        OpenAPI clone = new OpenAPI();
        clone.info(filteredOpenAPI.getInfo());
        clone.openapi(filteredOpenAPI.getOpenapi());
        clone.jsonSchemaDialect(filteredOpenAPI.getJsonSchemaDialect());
        clone.setSpecVersion(filteredOpenAPI.getSpecVersion());
        clone.setExtensions(filteredOpenAPI.getExtensions());
        clone.setExternalDocs(filteredOpenAPI.getExternalDocs());
        clone.setSecurity(filteredOpenAPI.getSecurity());
        clone.setServers(filteredOpenAPI.getServers());
        clone.tags(filteredOpenAPI.getTags() == null ? null : new ArrayList<>(openAPI.getTags()));

        final Set<String> allowedTags = new HashSet<>();
        final Set<String> filteredTags = new HashSet<>();

        Paths clonedPaths = new Paths();
        if (filteredOpenAPI.getPaths() != null) {
            for (String resourcePath : filteredOpenAPI.getPaths().keySet()) {
                PathItem pathItem = filteredOpenAPI.getPaths().get(resourcePath);

                PathItem filteredPathItem = filterPathItem(filter, pathItem, resourcePath, params, cookies, headers);
                PathItem clonedPathItem = cloneFilteredPathItem(filter,filteredPathItem, resourcePath, params, cookies, headers, allowedTags, filteredTags);

                if (clonedPathItem != null) {
                    if (!clonedPathItem.readOperations().isEmpty()) {
                        clonedPaths.addPathItem(resourcePath, clonedPathItem);
                    }
                }
            }
            clone.paths(clonedPaths);
        }

        filteredTags.removeAll(allowedTags);

        final List<Tag> tags = clone.getTags();
        if (tags != null && !filteredTags.isEmpty()) {
            tags.removeIf(tag -> filteredTags.contains(tag.getName()));
            if (clone.getTags().isEmpty()) {
                clone.setTags(null);
            }
        }

        if (filteredOpenAPI.getWebhooks() != null) {
            for (String resourcePath : filteredOpenAPI.getWebhooks().keySet()) {
                PathItem pathItem = filteredOpenAPI.getPaths().get(resourcePath);

                PathItem filteredPathItem = filterPathItem(filter, pathItem, resourcePath, params, cookies, headers);
                PathItem clonedPathItem = cloneFilteredPathItem(filter,filteredPathItem, resourcePath, params, cookies, headers, allowedTags, filteredTags);

                if (clonedPathItem != null) {
                    if (!clonedPathItem.readOperations().isEmpty()) {
                        clone.addWebhooks(resourcePath, clonedPathItem);
                    }
                }
            }
        }

        if (filteredOpenAPI.getComponents() != null) {
            clone.components(new Components());
            clone.getComponents().setSchemas(filterComponentsSchema(filter, filteredOpenAPI.getComponents().getSchemas(), params, cookies, headers));
            clone.getComponents().setSecuritySchemes(filteredOpenAPI.getComponents().getSecuritySchemes());
            clone.getComponents().setCallbacks(filteredOpenAPI.getComponents().getCallbacks());
            clone.getComponents().setExamples(filteredOpenAPI.getComponents().getExamples());
            clone.getComponents().setExtensions(filteredOpenAPI.getComponents().getExtensions());
            clone.getComponents().setHeaders(filteredOpenAPI.getComponents().getHeaders());
            clone.getComponents().setLinks(filteredOpenAPI.getComponents().getLinks());
            clone.getComponents().setParameters(filteredOpenAPI.getComponents().getParameters());
            clone.getComponents().setRequestBodies(filteredOpenAPI.getComponents().getRequestBodies());
            clone.getComponents().setResponses(filteredOpenAPI.getComponents().getResponses());
            clone.getComponents().setPathItems(filteredOpenAPI.getComponents().getPathItems());
        }

        if (filter.isRemovingUnreferencedDefinitions()) {
            clone = removeBrokenReferenceDefinitions(clone);
        }

        return clone;
    }
@Test(description = "it should filter with null definitions")
    public void filterWithNullDefinitions() throws IOException {
        final OpenAPI openAPI = getOpenAPI(RESOURCE_PATH);
        openAPI.getComponents().setSchemas(null);

        final InternalModelPropertiesRemoverFilter filter = new InternalModelPropertiesRemoverFilter();
        final OpenAPI filtered = new SpecFilter().filter(openAPI, filter, null, null, null);
        assertNotNull(filtered);
    }