b/163024265 Define Security Requirement Traversal

Change-Id: I8c0127c9d946310d4350c3e6b25308d7bd3df13e
diff --git a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/BaseTraversalHelper.java b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/BaseTraversalHelper.java
index 71e3a01..701ba8a 100644
--- a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/BaseTraversalHelper.java
+++ b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/BaseTraversalHelper.java
@@ -16,6 +16,7 @@
 import org.openapi4j.parser.model.v3.Operation;
 import org.openapi4j.parser.model.v3.Parameter;
 import org.openapi4j.parser.model.v3.Response;
+import org.openapi4j.parser.model.v3.SecurityRequirement;
 import org.openapi4j.parser.model.v3.Server;
 import org.openapi4j.parser.model.v3.ServerVariable;
 import org.openapi4j.parser.model.v3.Tag;
@@ -126,6 +127,18 @@
   }
 
   @Override
+  public void sendSecurityRequirementTraversals(
+      ImmutableList<SecurityRequirement> securityRequirementList) {
+    Optional.ofNullable(securityRequirementList)
+        .ifPresent(
+            securityRequirements ->
+                securityRequirements.forEach(
+                    securityRequirement ->
+                        coordinator.handleTraversalCommand(
+                            factory.create(securityRequirement, traversalPath))));
+  }
+
+  @Override
   public void sendServerTraversals(ImmutableList<Server> serversList) {
     Optional.ofNullable(serversList)
         .ifPresent(
diff --git a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/OperationTraversal.java b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/OperationTraversal.java
index 6fd6f9f..22ed41d 100644
--- a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/OperationTraversal.java
+++ b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/OperationTraversal.java
@@ -41,6 +41,7 @@
         Immutables.toImmutableList(openApiSchemaObj.getParameters()));
     traversalHelper.sendResponseTraversals(
         Immutables.toImmutableMap(openApiSchemaObj.getResponses()));
-    // TODO(b/163024265): Send Security Requirement Traversals.
+    traversalHelper.sendSecurityRequirementTraversals(
+        Immutables.toImmutableList(openApiSchemaObj.getSecurityRequirements()));
   }
 }
diff --git a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/SecurityRequirementTraversal.java b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/SecurityRequirementTraversal.java
new file mode 100644
index 0000000..78f614e
--- /dev/null
+++ b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/SecurityRequirementTraversal.java
@@ -0,0 +1,28 @@
+package com.apigee.security.oas.extendedvalidator;
+
+import com.google.common.collect.ImmutableList;
+import com.google.inject.assistedinject.Assisted;
+import java.util.Map;
+import java.util.Optional;
+import javax.inject.Inject;
+import org.openapi4j.parser.model.OpenApiSchema;
+import org.openapi4j.parser.model.v3.SecurityRequirement;
+
+/** A {@link Traversal} that traverses a {@link SecurityRequirement} object. */
+final class SecurityRequirementTraversal extends Traversal<SecurityRequirement>
+    implements SecurityRequirementTraversalCommand {
+  @Inject
+  SecurityRequirementTraversal(
+      TraversalHelperFactory traversalHelperFactory,
+      ExtensionValidationIntegrator extensionValidationIntegrator,
+      @Assisted
+          ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>> traversalPath,
+      @Assisted SecurityRequirement openApiSchemaObj) {
+    super(traversalHelperFactory, extensionValidationIntegrator, traversalPath, openApiSchemaObj);
+  }
+
+  @Override
+  public void traverse() {
+    // TODO(b/161441872): Process extensions.
+  }
+}
diff --git a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/SecurityRequirementTraversalCommand.java b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/SecurityRequirementTraversalCommand.java
new file mode 100644
index 0000000..508850b
--- /dev/null
+++ b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/SecurityRequirementTraversalCommand.java
@@ -0,0 +1,4 @@
+package com.apigee.security.oas.extendedvalidator;
+
+/** A {@link TraversalCommand} interface for {@link SecurityRequirementTraversal}. */
+public interface SecurityRequirementTraversalCommand extends TraversalCommand {}
diff --git a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/TraversalCommandFactory.java b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/TraversalCommandFactory.java
index 5d7f241..2167c17 100644
--- a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/TraversalCommandFactory.java
+++ b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/TraversalCommandFactory.java
@@ -13,6 +13,7 @@
 import org.openapi4j.parser.model.v3.Operation;
 import org.openapi4j.parser.model.v3.Parameter;
 import org.openapi4j.parser.model.v3.Response;
+import org.openapi4j.parser.model.v3.SecurityRequirement;
 import org.openapi4j.parser.model.v3.Server;
 import org.openapi4j.parser.model.v3.ServerVariable;
 import org.openapi4j.parser.model.v3.Tag;
@@ -60,6 +61,10 @@
       ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>> traversalPath,
       String name);
 
+  SecurityRequirementTraversalCommand create(
+      SecurityRequirement securityRequirement,
+      ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>> traversalPath);
+
   ServerTraversalCommand create(
       Server server,
       ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>> traversalPath);
diff --git a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/TraversalCommandFactoryModule.java b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/TraversalCommandFactoryModule.java
index dfc7cb9..fb3d8a7 100644
--- a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/TraversalCommandFactoryModule.java
+++ b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/TraversalCommandFactoryModule.java
@@ -19,6 +19,8 @@
             .implement(OperationTraversalCommand.class, OperationTraversal.class)
             .implement(ParameterTraversalCommand.class, ParameterTraversal.class)
             .implement(ResponseTraversalCommand.class, ResponseTraversal.class)
+            .implement(
+                SecurityRequirementTraversalCommand.class, SecurityRequirementTraversal.class)
             .implement(ServerTraversalCommand.class, ServerTraversal.class)
             .implement(ServerVariableTraversalCommand.class, ServerVariableTraversal.class)
             .implement(TagTraversalCommand.class, TagTraversal.class)
diff --git a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/TraversalHelper.java b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/TraversalHelper.java
index 776c07d..c2c6c94 100644
--- a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/TraversalHelper.java
+++ b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/TraversalHelper.java
@@ -11,6 +11,7 @@
 import org.openapi4j.parser.model.v3.Operation;
 import org.openapi4j.parser.model.v3.Parameter;
 import org.openapi4j.parser.model.v3.Response;
+import org.openapi4j.parser.model.v3.SecurityRequirement;
 import org.openapi4j.parser.model.v3.Server;
 import org.openapi4j.parser.model.v3.ServerVariable;
 import org.openapi4j.parser.model.v3.Tag;
@@ -36,6 +37,8 @@
 
   void sendResponseTraversals(ImmutableMap<String, Response> responses);
 
+  void sendSecurityRequirementTraversals(ImmutableList<SecurityRequirement> securityRequirements);
+
   void sendServerTraversals(ImmutableList<Server> serversList);
 
   void sendServerVariableTraversals(ImmutableMap<String, ServerVariable> serverVariables);
diff --git a/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/BaseTraversalHelperTest.java b/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/BaseTraversalHelperTest.java
index 4a5e6c5..397f545 100644
--- a/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/BaseTraversalHelperTest.java
+++ b/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/BaseTraversalHelperTest.java
@@ -24,6 +24,7 @@
 import org.openapi4j.parser.model.v3.OpenApi3;
 import org.openapi4j.parser.model.v3.Operation;
 import org.openapi4j.parser.model.v3.Parameter;
+import org.openapi4j.parser.model.v3.SecurityRequirement;
 import org.openapi4j.parser.model.v3.Server;
 import org.openapi4j.parser.model.v3.ServerVariable;
 import org.openapi4j.parser.model.v3.Tag;
@@ -39,6 +40,9 @@
 
   private final ImmutableList<Parameter> parameters =
       ImmutableList.of(new Parameter(), new Parameter(), new Parameter(), new Parameter());
+  private final ImmutableList<SecurityRequirement> securityRequirements =
+      ImmutableList.of(
+          new SecurityRequirement(), new SecurityRequirement(), new SecurityRequirement());
   private final ImmutableList<Server> servers =
       ImmutableList.of(new Server(), new Server(), new Server());
   private final ImmutableList<Tag> tags =
@@ -89,7 +93,7 @@
   }
 
   @Test
-  public void sendContactTraversals_nullParameter_doesNotFail() {
+  public void sendContactTraversal_nullParameter_doesNotFail() {
     traversalHelper.sendContactTraversal(null);
   }
 
@@ -169,6 +173,20 @@
   }
 
   @Test
+  public void
+      sendSecurityRequirementTraversals_sendsSecurityRequirementTraversalCommandsToCoordinator() {
+    traversalHelper.sendSecurityRequirementTraversals(securityRequirements);
+
+    verify(traversalCoordinator, times(securityRequirements.size()))
+        .handleTraversalCommand(any(SecurityRequirementTraversalCommand.class));
+  }
+
+  @Test
+  public void sendSecurityRequirementTraversals_nullParameter_doesNotFail() {
+    traversalHelper.sendSecurityRequirementTraversals(null);
+  }
+
+  @Test
   public void sendServerTraversals_sendsServerTraversalCommandsToCoordinator() {
     traversalHelper.sendServerTraversals(servers);
 
diff --git a/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/OperationTraversalTest.java b/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/OperationTraversalTest.java
index 6a5c9af..5e4436e 100644
--- a/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/OperationTraversalTest.java
+++ b/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/OperationTraversalTest.java
@@ -21,6 +21,7 @@
 import org.openapi4j.parser.model.v3.Operation;
 import org.openapi4j.parser.model.v3.Parameter;
 import org.openapi4j.parser.model.v3.Response;
+import org.openapi4j.parser.model.v3.SecurityRequirement;
 import org.openapi4j.parser.model.v3.Server;
 
 @RunWith(JUnit4.class)
@@ -35,6 +36,9 @@
 
   private final ExternalDocs externalDocs = new ExternalDocs();
 
+  private final ImmutableList securityRequirements =
+      ImmutableList.of(
+          new SecurityRequirement(), new SecurityRequirement(), new SecurityRequirement());
   private final ImmutableList servers = ImmutableList.of(new Server(), new Server(), new Server());
 
   private final ImmutableList parameters =
@@ -55,6 +59,7 @@
     when(operation.getParameters()).thenReturn(parameters);
     when(operation.getResponses()).thenReturn(responses);
     when(operation.getCallbacks()).thenReturn(callbacks);
+    when(operation.getSecurityRequirements()).thenReturn(securityRequirements);
 
     operationTraversal =
         new OperationTraversal(
@@ -68,6 +73,22 @@
   }
 
   @Test
+  public void traverse_sendsCallbacksToTraversalHelper() {
+    operationTraversal.traverse();
+
+    verify(traversalHelper).sendCallbackTraversals(callbacks);
+  }
+
+  @Test
+  public void traverse_nullCallbacksMember_doesNotFail() {
+    when(operation.getCallbacks()).thenReturn(null);
+
+    operationTraversal.traverse();
+
+    verify(traversalHelper, atLeastOnce()).sendCallbackTraversals(any());
+  }
+
+  @Test
   public void traverse_sendsExternalDocsToTraversalHelper() {
     operationTraversal.traverse();
 
@@ -107,6 +128,22 @@
   }
 
   @Test
+  public void traverse_sendsSecurityRequirementsToTraversalHelper() {
+    operationTraversal.traverse();
+
+    verify(traversalHelper).sendSecurityRequirementTraversals(securityRequirements);
+  }
+
+  @Test
+  public void traverse_nullSecurityRequirementsMember_doesNotFail() {
+    when(operation.getSecurityRequirements()).thenReturn(null);
+
+    operationTraversal.traverse();
+
+    verify(traversalHelper, atLeastOnce()).sendSecurityRequirementTraversals(any());
+  }
+
+  @Test
   public void traverse_sendsServersToTraversalHelper() {
     operationTraversal.traverse();
 
@@ -121,20 +158,4 @@
 
     verify(traversalHelper, atLeastOnce()).sendServerTraversals(any());
   }
-
-  @Test
-  public void traverse_sendsCallbacksToTraversalHelper() {
-    operationTraversal.traverse();
-
-    verify(traversalHelper).sendCallbackTraversals(callbacks);
-  }
-
-  @Test
-  public void traverse_nullCallbacksMember_doesNotFail() {
-    when(operation.getCallbacks()).thenReturn(null);
-
-    operationTraversal.traverse();
-
-    verify(traversalHelper, atLeastOnce()).sendCallbackTraversals(any());
-  }
 }
diff --git a/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/TraversalCommandFactoryTest.java b/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/TraversalCommandFactoryTest.java
index 3a31349..9f8e177 100644
--- a/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/TraversalCommandFactoryTest.java
+++ b/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/TraversalCommandFactoryTest.java
@@ -20,6 +20,7 @@
 import org.openapi4j.parser.model.v3.Operation;
 import org.openapi4j.parser.model.v3.Parameter;
 import org.openapi4j.parser.model.v3.Response;
+import org.openapi4j.parser.model.v3.SecurityRequirement;
 import org.openapi4j.parser.model.v3.Server;
 import org.openapi4j.parser.model.v3.ServerVariable;
 import org.openapi4j.parser.model.v3.Tag;
@@ -79,6 +80,12 @@
   }
 
   @Test
+  public void create_securityRequirementPassed_returnsNonNullObject() {
+    assertThat(traversalCommandFactory.create(new SecurityRequirement(), traversalPath))
+        .isNotNull();
+  }
+
+  @Test
   public void create_serverPassed_returnsNonNullObject() {
     assertThat(traversalCommandFactory.create(new Server(), traversalPath)).isNotNull();
   }