b/163024263 Define Response Traversal

Change-Id: I9789ddd59d3be76bc9b4d8c519a46ed4eae08919
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 cefbaa1..265431f 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
@@ -14,6 +14,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.Response;
 import org.openapi4j.parser.model.v3.Server;
 import org.openapi4j.parser.model.v3.ServerVariable;
 import org.openapi4j.parser.model.v3.Tag;
@@ -102,6 +103,17 @@
   }
 
   @Override
+  public void sendResponseTraversals(ImmutableMap<String, Response> responses) {
+    Optional.ofNullable(responses)
+        .ifPresent(
+            responsesObj ->
+                responsesObj.forEach(
+                    (name, response) ->
+                        coordinator.handleTraversalCommand(
+                            factory.create(response, traversalPath, name))));
+  }
+
+  @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 428e7ef..c929fa8 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
@@ -36,9 +36,10 @@
     traversalHelper.sendExternalDocsTraversal(openApiSchemaObj.getExternalDocs());
     // TODO(b/162949100): Send Callback Traversals.
     traversalHelper.sendServerTraversals(Immutables.toImmutableList(openApiSchemaObj.getServers()));
-    // TODO(b/163024263): Send Response Traversals.
-    // TODO(b/163024265): Send Security Requirement Traversals.
     traversalHelper.sendParameterTraversals(
         Immutables.toImmutableList(openApiSchemaObj.getParameters()));
+    traversalHelper.sendResponseTraversals(
+        Immutables.toImmutableMap(openApiSchemaObj.getResponses()));
+    // TODO(b/163024265): Send Security Requirement Traversals.
   }
 }
diff --git a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/ResponseTraversal.java b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/ResponseTraversal.java
new file mode 100644
index 0000000..d214ada
--- /dev/null
+++ b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/ResponseTraversal.java
@@ -0,0 +1,36 @@
+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.Response;
+
+/** A {@link Traversal} that traverses a {@link Response} object. */
+final class ResponseTraversal extends Traversal<Response> implements ResponseTraversalCommand {
+
+  @Inject
+  ResponseTraversal(
+      TraversalHelperFactory traversalHelperFactory,
+      ExtensionValidationIntegrator extensionValidationIntegrator,
+      @Assisted
+          ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>> traversalPath,
+      @Assisted Response openApiSchemaObj,
+      @Assisted String name) {
+    super(
+        traversalHelperFactory,
+        extensionValidationIntegrator,
+        traversalPath,
+        openApiSchemaObj,
+        name);
+  }
+
+  @Override
+  public void traverse() {
+    // TODO(b/162897637): Send MediaType Traversals.
+    // TODO(b/162949105): Send Header Traversals.
+    // TODO(b/162949106): Send Link Traversals.
+  }
+}
diff --git a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/ResponseTraversalCommand.java b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/ResponseTraversalCommand.java
new file mode 100644
index 0000000..44e235d
--- /dev/null
+++ b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/ResponseTraversalCommand.java
@@ -0,0 +1,4 @@
+package com.apigee.security.oas.extendedvalidator;
+
+/** A {@link TraversalCommand} interface for {@link ResponseTraversal}. */
+public interface ResponseTraversalCommand 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 e857632..ac98888 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
@@ -11,6 +11,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.Response;
 import org.openapi4j.parser.model.v3.Server;
 import org.openapi4j.parser.model.v3.ServerVariable;
 import org.openapi4j.parser.model.v3.Tag;
@@ -48,6 +49,11 @@
       Parameter parameter,
       ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>> traversalPath);
 
+  ResponseTraversalCommand create(
+      Response response,
+      ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>> traversalPath,
+      String name);
+
   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 d69d230..b0e6c56 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
@@ -17,6 +17,7 @@
                 OpenApiSpecificationTraversalCommand.class, OpenApiSpecificationTraversal.class)
             .implement(OperationTraversalCommand.class, OperationTraversal.class)
             .implement(ParameterTraversalCommand.class, ParameterTraversal.class)
+            .implement(ResponseTraversalCommand.class, ResponseTraversal.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 3351ad1..ca55a12 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
@@ -9,6 +9,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.Response;
 import org.openapi4j.parser.model.v3.Server;
 import org.openapi4j.parser.model.v3.ServerVariable;
 import org.openapi4j.parser.model.v3.Tag;
@@ -30,6 +31,8 @@
 
   void sendParameterTraversals(ImmutableList<Parameter> parameters);
 
+  void sendResponseTraversals(ImmutableMap<String, Response> responses);
+
   void sendServerTraversals(ImmutableList<Server> serversList);
 
   void sendServerVariableTraversals(ImmutableMap<String, ServerVariable> serverVariables);
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 05ea8f3..eca900f 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
@@ -6,6 +6,7 @@
 import static org.mockito.Mockito.when;
 
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -18,6 +19,7 @@
 import org.openapi4j.parser.model.v3.ExternalDocs;
 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.Server;
 
 @RunWith(JUnit4.class)
@@ -35,6 +37,8 @@
 
   private final ImmutableList parameters =
       ImmutableList.of(new Parameter(), new Parameter(), new Parameter(), new Parameter());
+  private final ImmutableMap responses =
+      ImmutableMap.of("one", new Response(), "two", new Response());
 
   private OperationTraversal operationTraversal;
 
@@ -45,6 +49,7 @@
     when(operation.getExternalDocs()).thenReturn(externalDocs);
     when(operation.getServers()).thenReturn(servers);
     when(operation.getParameters()).thenReturn(parameters);
+    when(operation.getResponses()).thenReturn(responses);
 
     operationTraversal =
         new OperationTraversal(
@@ -81,6 +86,22 @@
   }
 
   @Test
+  public void traverse_sendsResponsesToTraversalHelper() {
+    operationTraversal.traverse();
+
+    verify(traversalHelper).sendResponseTraversals(responses);
+  }
+
+  @Test
+  public void traverse_nullResponsesMember_doesNotFail() {
+    when(operation.getResponses()).thenReturn(null);
+
+    operationTraversal.traverse();
+
+    verify(traversalHelper, atLeastOnce()).sendResponseTraversals(any());
+  }
+
+  @Test
   public void traverse_sendsServersToTraversalHelper() {
     operationTraversal.traverse();
 
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 17450af..baa2e8b 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
@@ -18,6 +18,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.Response;
 import org.openapi4j.parser.model.v3.Server;
 import org.openapi4j.parser.model.v3.ServerVariable;
 import org.openapi4j.parser.model.v3.Tag;
@@ -67,6 +68,11 @@
   }
 
   @Test
+  public void create_responseAndNamePassed_returnsNonNullObject() {
+    assertThat(traversalCommandFactory.create(new Response(), traversalPath, "name")).isNotNull();
+  }
+
+  @Test
   public void create_serverPassed_returnsNonNullObject() {
     assertThat(traversalCommandFactory.create(new Server(), traversalPath)).isNotNull();
   }