All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.wildfly.swarm.microprofile.openapi.api.OpenApiDocument Maven / Gradle / Ivy

/*
 * Copyright 2018 Red Hat, Inc, and individual contributors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.wildfly.swarm.microprofile.openapi.api;

import org.eclipse.microprofile.openapi.OASFilter;
import org.eclipse.microprofile.openapi.models.OpenAPI;
import org.jboss.logging.Logger;
import org.wildfly.swarm.microprofile.openapi.api.models.OpenAPIImpl;
import org.wildfly.swarm.microprofile.openapi.api.models.PathsImpl;
import org.wildfly.swarm.microprofile.openapi.api.models.info.InfoImpl;
import org.wildfly.swarm.microprofile.openapi.api.util.FilterUtil;
import org.wildfly.swarm.microprofile.openapi.api.util.MergeUtil;
import org.wildfly.swarm.microprofile.openapi.api.util.ServersUtil;
import org.wildfly.swarm.microprofile.openapi.runtime.OpenApiConstants;

/**
 * Holds the final OpenAPI document produced during the startup of the app.
 *
 * 

* Note that the model must be initialized first! *

* * @author Martin Kouba */ public class OpenApiDocument { public static final OpenApiDocument INSTANCE = new OpenApiDocument(); private static final Logger LOGGER = Logger.getLogger(OpenApiDocument.class); // These are used during init only private transient OpenApiConfig config; private transient OpenAPI annotationsModel; private transient OpenAPI readerModel; private transient OpenAPI staticFileModel; private transient OASFilter filter; private transient String archiveName; private transient OpenAPI model; private OpenApiDocument() { } /** * * @return the final OpenAPI document produced during the startup of the app * @throws IllegalStateException If the final model is not initialized yet */ public OpenAPI get() { synchronized (INSTANCE) { if (model == null) { throw new IllegalStateException("Model not initialized yet"); } return model; } } /** * Set the final OpenAPI document. This method should only be used for testing. * * @param model */ public void set(OpenAPI model) { synchronized (INSTANCE) { this.model = model; LOGGER.info("OpenAPI document set: " + model); } } /** * Reset the holder. */ public void reset() { synchronized (INSTANCE) { model = null; clear(); } } public synchronized void config(OpenApiConfig config) { set(() -> this.config = config); } public void modelFromAnnotations(OpenAPI model) { set(() -> this.annotationsModel = model); } public void modelFromReader(OpenAPI model) { set(() -> this.readerModel = model); } public void modelFromStaticFile(OpenAPI model) { set(() -> this.staticFileModel = model); } public void filter(OASFilter filter) { set(() -> this.filter = filter); } public void archiveName(String archiveName) { set(() -> this.archiveName = archiveName); } public void initialize() { synchronized (INSTANCE) { if (model != null) { modelAlreadyInitialized(); } // Check all the required parts are set if (config == null) { throw new IllegalStateException("OpenApiConfig must be set before init"); } // Phase 1: Use OASModelReader OpenAPI merged = readerModel; // Phase 2: Merge any static OpenAPI file packaged in the app merged = MergeUtil.mergeObjects(merged, staticFileModel); // Phase 3: Merge annotations merged = MergeUtil.mergeObjects(merged, annotationsModel); // Phase 4: Filter model via OASFilter merged = filterModel(merged); // Phase 5: Default empty document if model == null if (merged == null) { merged = new OpenAPIImpl(); merged.setOpenapi(OpenApiConstants.OPEN_API_VERSION); } // Phase 6: Provide missing required elements if (merged.getPaths() == null) { merged.setPaths(new PathsImpl()); } if (merged.getInfo() == null) { merged.setInfo(new InfoImpl()); } if (merged.getInfo().getTitle() == null) { merged.getInfo().setTitle((archiveName == null ? "Generated" : archiveName) + " API"); } if (merged.getInfo().getVersion() == null) { merged.getInfo().setVersion("1.0"); } // Phase 7: Use Config values to add Servers (global, pathItem, operation) ServersUtil.configureServers(config, merged); model = merged; LOGGER.info("OpenAPI document initialized: " + model); clear(); } } /** * Filter the final model using a {@link OASFilter} configured by the app. If no filter has been configured, this will simply return the model unchanged. * * @param model */ private OpenAPI filterModel(OpenAPI model) { if (model == null || filter == null) { return model; } LOGGER.info("Filtering OpenAPI model using: " + filter); return FilterUtil.applyFilter(filter, model); } private void set(Runnable action) { synchronized (INSTANCE) { if (model != null) { modelAlreadyInitialized(); } action.run(); } } private void modelAlreadyInitialized() { throw new IllegalStateException("Model already initialized"); } private void clear() { config = null; annotationsModel = null; readerModel = null; staticFileModel = null; filter = null; archiveName = null; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy