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

org.apache.juneau.dto.swagger.Swagger Maven / Gradle / Ivy

// ***************************************************************************************************************************
// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
// * to you 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.apache.juneau.dto.swagger;

import static org.apache.juneau.common.internal.StringUtils.*;
import static org.apache.juneau.internal.ClassUtils.*;
import static org.apache.juneau.internal.CollectionUtils.*;
import static org.apache.juneau.internal.ConverterUtils.*;

import java.util.*;

import org.apache.juneau.*;
import org.apache.juneau.annotation.*;
import org.apache.juneau.collections.*;
import org.apache.juneau.internal.*;
import org.apache.juneau.json.*;
import org.apache.juneau.objecttools.*;

/**
 * This is the root document object for the API specification.
 *
 * 
See Also:
*/ @Bean(properties="swagger,info,tags,externalDocs,basePath,schemes,consumes,produces,paths,definitions,parameters,responses,securityDefinitions,security,*") @FluentSetters public class Swagger extends SwaggerElement { /** Represents a null swagger */ public static final Swagger NULL = new Swagger(); private static final Comparator PATH_COMPARATOR = (o1, o2) -> o1.replace('{', '@').compareTo(o2.replace('{', '@')); private String swagger = "2.0", host, basePath; private Info info; private ExternalDocumentation externalDocs; private Set schemes; private Set consumes, produces; private Set tags; private List>> security; private Map definitions; private Map parameters; private Map responses; private Map securityDefinitions; private Map paths; /** * Default constructor. */ public Swagger() {} /** * Copy constructor. * * @param copyFrom The object to copy. */ public Swagger(Swagger copyFrom) { super(copyFrom); this.basePath = copyFrom.basePath; this.consumes = copyOf(copyFrom.consumes); this.externalDocs = copyFrom.externalDocs == null ? null : copyFrom.externalDocs.copy(); this.host = copyFrom.host; this.info = copyFrom.info == null ? null : copyFrom.info.copy(); this.produces = copyOf(copyFrom.produces); this.schemes = copyOf(copyFrom.schemes); this.swagger = copyFrom.swagger; // TODO - Definitions are not deep copied, so they should not contain references. if (copyFrom.definitions == null) { this.definitions = null; } else { this.definitions = map(); copyFrom.definitions.forEach((k,v) -> this.definitions.put(k, new JsonMap(v))); } if (copyFrom.paths == null) { this.paths = null; } else { this.paths = map(); copyFrom.paths.forEach((k,v) -> { OperationMap m = new OperationMap(); v.forEach((k2,v2) -> m.put(k2, v2.copy())); this.paths.put(k, m); }); } if (copyFrom.parameters == null) { this.parameters = null; } else { this.parameters = map(); copyFrom.parameters.forEach((k,v) -> this.parameters.put(k, v.copy())); } if (copyFrom.responses == null) { this.responses = null; } else { this.responses = map(); copyFrom.responses.forEach((k,v) -> this.responses.put(k, v.copy())); } if (copyFrom.security == null) { this.security = null; } else { this.security = list(); copyFrom.security.forEach(x -> { Map> m2 = map(); x.forEach((k,v) -> m2.put(k, copyOf(v))); this.security.add(m2); }); } if (copyFrom.securityDefinitions == null) { this.securityDefinitions = null; } else { this.securityDefinitions = map(); copyFrom.securityDefinitions.forEach((k,v) -> this.securityDefinitions.put(k, v.copy())); } if (copyFrom.tags == null) { this.tags = null; } else { this.tags = CollectionUtils.set(); copyFrom.tags.forEach(x -> this.tags.add(x.copy())); } } /** * Make a deep copy of this object. * * @return A deep copy of this object. */ public Swagger copy() { return new Swagger(this); } //----------------------------------------------------------------------------------------------------------------- // Properties //----------------------------------------------------------------------------------------------------------------- /** * Bean property getter: basePath. * *

* The base path on which the API is served, which is relative to the host. * * @return The property value, or null if it is not set. */ public String getBasePath() { return basePath; } /** * Bean property setter: basePath. * *

* The base path on which the API is served, which is relative to the host. * * @param value * The new value for this property. *
If it is not included, the API is served directly under the host. *
The value MUST start with a leading slash (/). *
The basePath does not support path templating. *
Can be null to unset the property. * @return This object. */ public Swagger setBasePath(String value) { basePath = value; return this; } /** * Bean property getter: consumes. * *

* A list of MIME types the APIs can consume. * * @return The property value, or null if it is not set. */ public Set getConsumes() { return consumes; } /** * Bean property setter: consumes. * *

* A list of MIME types the APIs can consume. * * @param value * The new value for this property. *
Value MUST be as described under Swagger Mime Types. *
Can be null to unset the property. * @return This object. */ public Swagger setConsumes(Collection value) { consumes = setFrom(value); return this; } /** * Bean property appender: consumes. * *

* A list of MIME types the APIs can consume. * * @param values * The values to add to this property. *
Values MUST be as described under Swagger Mime Types. *
Ignored if null. * @return This object. */ public Swagger addConsumes(MediaType...values) { consumes = setBuilder(consumes).sparse().add(values).build(); return this; } /** * Bean property fluent setter: consumes. * *

* A list of MIME types the APIs can consume. * * @param value * The values to set on this property. * @return This object. */ public Swagger setConsumes(MediaType...value) { setConsumes(setBuilder(MediaType.class).sparse().add(value).build()); return this; } /** * Bean property getter: definitions. * *

* An object to hold data types produced and consumed by operations. * * @return The property value, or null if it is not set. */ public Map getDefinitions() { return definitions; } /** * Bean property setter: definitions. * *

* An object to hold data types produced and consumed by operations. * * @param value * The new value for this property. *
Can be null to unset the property. * @return This object. */ public Swagger setDefinitions(Map value) { definitions = copyOf(value); return this; } /** * Bean property appender: definitions. * *

* Adds a single value to the definitions property. * * @param name A definition name. * @param schema The schema that the name defines. * @return This object. */ public Swagger addDefinition(String name, JsonMap schema) { definitions = mapBuilder(definitions).sparse().add(name, schema).build(); return this; } /** * Bean property getter: externalDocs. * *

* Additional external documentation. * * @return The property value, or null if it is not set. */ public ExternalDocumentation getExternalDocs() { return externalDocs; } /** * Bean property setter: externalDocs. * *

* Additional external documentation. * * @param value * The new value for this property. *
Can be null to unset the property. * @return This object. */ public Swagger setExternalDocs(ExternalDocumentation value) { externalDocs = value; return this; } /** * Bean property getter: host. * *

* The host (name or IP) serving the API. * * @return The property value, or null if it is not set. */ public String getHost() { return host; } /** * Bean property setter: host. * *

* The host (name or IP) serving the API. * * @param value * The new value for this property. *
This MUST be the host only and does not include the scheme nor sub-paths. *
It MAY include a port. *
If the host is not included, the host serving the documentation is to be used (including the port). *
The host does not support path templating *
Can be null to unset the property. * @return This object. */ public Swagger setHost(String value) { host = value; return this; } /** * Bean property getter: info. * *

* Provides metadata about the API. * * @return The property value, or null if it is not set. */ public Info getInfo() { return info; } /** * Bean property setter: info. * *

* Provides metadata about the API. * * @param value * The new value for this property. *
Property value is required. * @return This object. */ public Swagger setInfo(Info value) { info = value; return this; } /** * Bean property getter: parameters. * *

* An object to hold parameters that can be used across operations. * * @return The property value, or null if it is not set. */ public Map getParameters() { return parameters; } /** * Bean property setter: parameters. * *

* An object to hold parameters that can be used across operations. * * @param value * The new value for this property. *
Can be null to unset the property. * @return This object. */ public Swagger setParameters(Map value) { parameters = copyOf(value); return this; } /** * Bean property appender: parameters. * *

* Adds a single value to the parameter property. * * @param name The parameter name. * @param parameter The parameter definition. * @return This object. */ public Swagger addParameter(String name, ParameterInfo parameter) { parameters = mapBuilder(parameters).sparse().add(name, parameter).build(); return this; } /** * Bean property getter: paths. * *

* The available paths and operations for the API. * * @return The property value, or null if it is not set. */ public Map getPaths() { return paths; } /** * Bean property setter: paths. * *

* The available paths and operations for the API. * * @param value * The new value for this property. *
Property value is required. * @return This object. */ public Swagger setPaths(Map value) { paths = mapBuilder(String.class,OperationMap.class).sparse().sorted(PATH_COMPARATOR).addAll(value).build(); return this; } /** * Bean property appender: paths. * *

* Adds a single value to the paths property. * * @param path The path template. * @param methodName The HTTP method name. * @param operation The operation that describes the path. * @return This object. */ public Swagger addPath(String path, String methodName, Operation operation) { if (paths == null) paths = new TreeMap<>(PATH_COMPARATOR); OperationMap p = paths.get(path); if (p == null) { p = new OperationMap(); paths.put(path, p); } p.put(methodName, operation); return this; } /** * Bean property getter: produces. * *

* A list of MIME types the APIs can produce. * * @return The property value, or null if it is not set. */ public Set getProduces() { return produces; } /** * Bean property setter: produces. * *

* A list of MIME types the APIs can produce. * * @param value * The new value for this property. *
Value MUST be as described under Swagger Mime Types. *
Can be null to unset the property. * @return This object. */ public Swagger setProduces(Collection value) { produces = setFrom(value); return this; } /** * Adds one or more values to the produces property. * *

* A list of MIME types the APIs can produce. * * @param values * The values to add to this property. *
Value MUST be as described under Swagger Mime Types. *
Can be null to unset the property. * @return This object. */ public Swagger addProduces(MediaType...values) { produces = setBuilder(produces).sparse().add(values).build(); return this; } /** * Bean property fluent setter: produces. * *

* A list of MIME types the APIs can produce. * * @param value * The new value for this property. * @return This object. */ public Swagger setProduces(MediaType...value) { setProduces(setBuilder(MediaType.class).sparse().add(value).build()); return this; } /** * Bean property getter: responses. * *

* An object to hold responses that can be used across operations. * * @return The property value, or null if it is not set. */ public Map getResponses() { return responses; } /** * Bean property setter: responses. * *

* An object to hold responses that can be used across operations. * * @param value * The new value for this property. *
Can be null to unset the property. * @return This object. */ public Swagger setResponses(Map value) { responses = copyOf(value); return this; } /** * Bean property appender: responses. * *

* Adds a single value to the responses property. * * @param name The response name. * @param response The response definition. * @return This object. */ public Swagger addResponse(String name, ResponseInfo response) { responses = mapBuilder(responses).sparse().add(name, response).build(); return this; } /** * Bean property getter: schemes. * *

* The transfer protocol of the API. * * @return The property value, or null if it is not set. */ public Set getSchemes() { return schemes; } /** * Bean property setter: schemes. * *

* The transfer protocol of the API. * * @param value * The new value for this property. *
Valid values: *

    *
  • "http" *
  • "https" *
  • "ws" *
  • "wss" *
*
Can be null to unset the property. * @return This object. */ public Swagger setSchemes(Collection value) { schemes = setFrom(value); return this; } /** * Bean property appender: schemes. * *

* The transfer protocol of the API. * * @param values * The values to add to this property. *
Valid values: *

    *
  • "http" *
  • "https" *
  • "ws" *
  • "wss" *
*
Ignored if null. * @return This object. */ public Swagger addSchemes(String...values) { schemes = setBuilder(schemes).sparse().add(values).build(); return this; } /** * Bean property fluent setter: schemes. * *

* The transfer protocol of the API. * * @param value * The new value for this property. *
Strings can be JSON arrays. * @return This object. */ public Swagger setSchemes(String...value) { setSchemes(setBuilder(String.class).sparse().addJson(value).build()); return this; } /** * Bean property getter: security. * *

* A declaration of which security schemes are applied for the API as a whole. * * @return The property value, or null if it is not set. */ public List>> getSecurity() { return security; } /** * Bean property setter: security. * *

* A declaration of which security schemes are applied for the API as a whole. * * @param value * The new value for this property. *
Can be null to unset the property. * @return This object. */ public Swagger setSecurity(Collection>> value) { security = listFrom(value); return this; } /** * Bean property appender: security. * *

* Adds a single value to the securityDefinitions property. * * @param scheme The security scheme that applies to this operation * @param alternatives * The list of values describes alternative security schemes that can be used (that is, there is a logical OR between the security requirements). * @return This object. */ public Swagger addSecurity(String scheme, String...alternatives) { Map> m = map(); m.put(scheme, alist(alternatives)); security = listBuilder(security).sparse().addAll(Collections.singleton(m)).build(); return this; } /** * Bean property getter: securityDefinitions. * *

* Security scheme definitions that can be used across the specification. * * @return The property value, or null if it is not set. */ public Map getSecurityDefinitions() { return securityDefinitions; } /** * Bean property setter: securityDefinitions. * *

* Security scheme definitions that can be used across the specification. * * @param value * The new value for this property. *
Can be null to unset the property. * @return This object. */ public Swagger setSecurityDefinitions(Map value) { securityDefinitions = copyOf(value); return this; } /** * Bean property appender: securityDefinitions. * *

* Adds a single value to the securityDefinitions property. * * @param name A security name. * @param securityScheme A security schema. * @return This object. */ public Swagger addSecurityDefinition(String name, SecurityScheme securityScheme) { securityDefinitions = mapBuilder(securityDefinitions).sparse().add(name, securityScheme).build(); return this; } /** * Bean property getter: swagger. * *

* Specifies the Swagger Specification version being used. * * @return The property value, or null if it is not set. */ public String getSwagger() { return swagger; } /** * Bean property setter: swagger. * *

* Specifies the Swagger Specification version being used. * * @param value * The new value for this property. *
Property value is required. * @return This object. */ public Swagger setSwagger(String value) { swagger = value; return this; } /** * Bean property getter: tags. * *

* A list of tags used by the specification with additional metadata. * * @return The property value, or null if it is not set. */ public Set getTags() { return tags; } /** * Bean property setter: tags. * *

* A list of tags used by the specification with additional metadata. * * @param value * The new value for this property. *
The order of the tags can be used to reflect on their order by the parsing tools. *
Not all tags that are used by the Operation Object must be declared. *
The tags that are not declared may be organized randomly or based on the tools' logic. *
Each tag name in the list MUST be unique. *
Can be null to unset the property. * @return This object. */ public Swagger setTags(Collection value) { tags = setFrom(value); return this; } /** * Bean property appender: tags. * *

* A list of tags used by the specification with additional metadata. * * @param values * The values to add to this property. *
The order of the tags can be used to reflect on their order by the parsing tools. *
Not all tags that are used by the Operation Object must be declared. *
The tags that are not declared may be organized randomly or based on the tools' logic. *
Each tag name in the list MUST be unique. *
Ignored if null. * @return This object. */ public Swagger addTags(Tag...values) { tags = setBuilder(tags).sparse().add(values).build(); return this; } //----------------------------------------------------------------------------------------------------------------- // Convenience methods //----------------------------------------------------------------------------------------------------------------- /** * Shortcut for calling getPaths().get(path); * * @param path The path (e.g. "/foo"). * @return The operation map for the specified path, or null if it doesn't exist. */ public OperationMap getPath(String path) { return getPaths().get(path); } /** * Shortcut for calling getPaths().get(path).get(operation); * * @param path The path (e.g. "/foo"). * @param operation The HTTP operation (e.g. "get"). * @return The operation for the specified path and operation id, or null if it doesn't exist. */ public Operation getOperation(String path, String operation) { OperationMap om = getPath(path); if (om == null) return null; return om.get(operation); } /** * Shortcut for calling getPaths().get(path).get(operation).getResponse(status); * * @param path The path (e.g. "/foo"). * @param operation The HTTP operation (e.g. "get"). * @param status The HTTP response status (e.g. "200"). * @return The operation for the specified path and operation id, or null if it doesn't exist. */ public ResponseInfo getResponseInfo(String path, String operation, String status) { OperationMap om = getPath(path); if (om == null) return null; Operation op = om.get(operation); if (op == null) return null; return op.getResponse(status); } /** * Shortcut for calling getPaths().get(path).get(operation).getResponse(status); * * @param path The path (e.g. "/foo"). * @param operation The HTTP operation (e.g. "get"). * @param status The HTTP response status (e.g. "200"). * @return The operation for the specified path and operation id, or null if it doesn't exist. */ public ResponseInfo getResponseInfo(String path, String operation, int status) { return getResponseInfo(path, operation, String.valueOf(status)); } /** * Convenience method for calling getPath(path).get(method).getParameter(in,name); * * @param path The HTTP path. * @param method The HTTP method. * @param in The parameter type. * @param name The parameter name. * @return The parameter information or null if not found. */ public ParameterInfo getParameterInfo(String path, String method, String in, String name) { OperationMap om = getPath(path); if (om != null) { Operation o = om.get(method); if (o != null) { return o.getParameter(in, name); } } return null; } // // @Override /* SwaggerElement */ public T get(String property, Class type) { if (property == null) return null; switch (property) { case "basePath": return toType(getBasePath(), type); case "consumes": return toType(getConsumes(), type); case "definitions": return toType(getDefinitions(), type); case "externalDocs": return toType(getExternalDocs(), type); case "host": return toType(getHost(), type); case "info": return toType(getInfo(), type); case "parameters": return toType(getParameters(), type); case "paths": return toType(getPaths(), type); case "produces": return toType(getProduces(), type); case "responses": return toType(getResponses(), type); case "schemes": return toType(getSchemes(), type); case "security": return toType(getSecurity(), type); case "securityDefinitions": return toType(getSecurityDefinitions(), type); case "swagger": return toType(getSwagger(), type); case "tags": return toType(getTags(), type); default: return super.get(property, type); } } @SuppressWarnings({ "unchecked", "rawtypes" }) @Override /* SwaggerElement */ public Swagger set(String property, Object value) { if (property == null) return this; switch (property) { case "basePath": return setBasePath(stringify(value)); case "consumes": return setConsumes(listBuilder(MediaType.class).sparse().addAny(value).build()); case "definitions": return setDefinitions(mapBuilder(String.class,JsonMap.class).sparse().addAny(value).build()); case "externalDocs": return setExternalDocs(toType(value, ExternalDocumentation.class)); case "host": return setHost(stringify(value)); case "info": return setInfo(toType(value, Info.class)); case "parameters": return setParameters(mapBuilder(String.class,ParameterInfo.class).sparse().addAny(value).build()); case "paths": return setPaths(mapBuilder(String.class,OperationMap.class).sparse().addAny(value).build()); case "produces": return setProduces(listBuilder(MediaType.class).sparse().addAny(value).build()); case "responses": return setResponses(mapBuilder(String.class,ResponseInfo.class).sparse().addAny(value).build()); case "schemes": return setSchemes(listBuilder(String.class).sparse().addAny(value).build()); case "security": return setSecurity((List)listBuilder(Map.class,String.class,List.class,String.class).sparse().addAny(value).build()); case "securityDefinitions": return setSecurityDefinitions(mapBuilder(String.class,SecurityScheme.class).sparse().addAny(value).build()); case "swagger": return setSwagger(stringify(value)); case "tags": return setTags(listBuilder(Tag.class).sparse().addAny(value).build()); default: super.set(property, value); return this; } } @Override /* SwaggerElement */ public Set keySet() { Set s = setBuilder(String.class) .addIf(basePath != null, "basePath") .addIf(consumes != null, "consumes") .addIf(definitions != null, "definitions") .addIf(externalDocs != null, "externalDocs") .addIf(host != null, "host") .addIf(info != null, "info") .addIf(parameters != null, "parameters") .addIf(paths != null, "paths") .addIf(produces != null, "produces") .addIf(responses != null, "responses") .addIf(schemes != null, "schemes") .addIf(security != null, "security") .addIf(securityDefinitions != null, "securityDefinitions") .addIf(swagger != null, "swagger") .addIf(tags != null, "tags") .build(); return new MultiSet<>(s, super.keySet()); } /** * A synonym of {@link #toString()}. * @return This object serialized as JSON. */ public String asJson() { return toString(); } @Override /* Object */ public String toString() { return JsonSerializer.DEFAULT.toString(this); } /** * Resolves a "$ref" tags to nodes in this swagger document. * * @param The class to convert the reference to. * @param ref The ref tag value. * @param c The class to convert the reference to. * @return The referenced node, or null if the ref was null or empty or not found. */ public T findRef(String ref, Class c) { if (isEmpty(ref)) return null; if (! ref.startsWith("#/")) throw new BasicRuntimeException("Unsupported reference: ''{0}''", ref); try { return new ObjectRest(this).get(ref.substring(1), c); } catch (Exception e) { throw new BeanRuntimeException(e, c, "Reference ''{0}'' could not be converted to type ''{1}''.", ref, className(c)); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy