001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.bean.openapi3;
018
019import static org.apache.juneau.commons.utils.AssertionUtils.*;
020import static org.apache.juneau.commons.utils.CollectionUtils.*;
021import static org.apache.juneau.commons.utils.Utils.*;
022import static org.apache.juneau.internal.ConverterUtils.*;
023
024import java.util.*;
025
026import org.apache.juneau.commons.collections.*;
027
028/**
029 * Lists the required security schemes for this operation.
030 *
031 * <h5 class='section'>See Also:</h5><ul>
032 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauBeanOpenApi3">juneau-bean-openapi-v3</a>
033 * </ul>
034 */
035public class SecurityRequirement extends OpenApiElement {
036
037   private Map<String,List<String>> requirements;
038
039   /**
040    * Default constructor.
041    */
042   public SecurityRequirement() {}
043
044   /**
045    * Copy constructor.
046    *
047    * @param copyFrom The object to copy.
048    */
049   public SecurityRequirement(SecurityRequirement copyFrom) {
050      super(copyFrom);
051      this.requirements = copyOf(copyFrom.requirements);
052   }
053
054   /**
055    * Adds a security requirement.
056    *
057    * @param schemeName The security scheme name.  Must not be <jk>null</jk>.
058    * @param scopes The required scopes.  Must not be <jk>null</jk>.
059    * @return This object.
060    */
061   public SecurityRequirement addRequirement(String schemeName, String...scopes) {
062      assertArgNotNull("schemeName", schemeName);
063      assertArgNoNulls("scopes", scopes);
064      if (requirements == null)
065         requirements = new LinkedHashMap<>();
066      requirements.put(schemeName, l(scopes));
067      return this;
068   }
069
070   /**
071    * Makes a copy of this object.
072    *
073    * @return A new copy of this object.
074    */
075   public SecurityRequirement copy() {
076      return new SecurityRequirement(this);
077   }
078
079   @Override /* Overridden from OpenApiElement */
080   public <T> T get(String property, Class<T> type) {
081      assertArgNotNull("property", property);
082      return switch (property) {
083         case "requirements" -> toType(getRequirements(), type);
084         default -> super.get(property, type);
085      };
086   }
087
088   /**
089    * Returns the security requirements map.
090    *
091    * @return The security requirements map.
092    */
093   public Map<String,List<String>> getRequirements() { return requirements; }
094
095   @Override /* Overridden from OpenApiElement */
096   public Set<String> keySet() {
097      // @formatter:off
098      var s = setb(String.class)
099         .addIf(nn(requirements), "requirements")
100         .build();
101      // @formatter:on
102      return new MultiSet<>(s, super.keySet());
103   }
104
105   @SuppressWarnings("unchecked")
106   @Override /* Overridden from OpenApiElement */
107   public SecurityRequirement set(String property, Object value) {
108      assertArgNotNull("property", property);
109      return switch (property) {
110         case "requirements" -> setRequirements((Map<String,List<String>>)value);
111         default -> {
112            super.set(property, value);
113            yield this;
114         }
115      };
116   }
117
118   /**
119    * Adds a security requirement for a scheme that doesn't use scopes.
120    *
121    * <p>
122    * This is a convenience method for adding security schemes that don't use scopes, such as API keys,
123    * HTTP Basic authentication, or HTTP Bearer tokens. According to the OpenAPI specification, security
124    * schemes that don't use scopes should have an empty array as the value.
125    *
126    * <p>
127    * This method is equivalent to calling <c>addRequirement(schemeName)</c> with no scopes.
128    *
129    * <h5 class='section'>Example:</h5>
130    * <p class='bjava'>
131    *    <jc>// Add API key authentication requirement</jc>
132    *    SecurityRequirement <jv>requirement</jv> = <jk>new</jk> SecurityRequirement()
133    *       .setApiKeyAuth(<js>"api_key"</js>);
134    *    <jc>// Results in: { "api_key": [] }</jc>
135    * </p>
136    *
137    * <h5 class='section'>See Also:</h5><ul>
138    *    <li class='link'><a class="doclink" href="https://spec.openapis.org/oas/v3.0.0#security-requirement-object">OpenAPI Specification &gt; Security Requirement Object</a>
139    *    <li class='link'><a class="doclink" href="https://swagger.io/docs/specification/authentication/">OpenAPI Authentication</a>
140    * </ul>
141    *
142    * @param schemeName The security scheme name.  Must not be <jk>null</jk>.
143    * @return This object.
144    */
145   public SecurityRequirement setApiKeyAuth(String schemeName) {
146      return addRequirement(schemeName);
147   }
148
149   /**
150    * Sets the security requirements map.
151    *
152    * @param value The new value for this property.
153    * @return This object.
154    */
155   public SecurityRequirement setRequirements(Map<String,List<String>> value) {
156      requirements = value;
157      return this;
158   }
159
160   @Override /* Overridden from OpenApiElement */
161   public SecurityRequirement strict() {
162      super.strict();
163      return this;
164   }
165
166   @Override /* Overridden from OpenApiElement */
167   public SecurityRequirement strict(Object value) {
168      super.strict(value);
169      return this;
170   }
171}