b/161637388 Add path tracking capability

Change-Id: I045e27a94514f44d3230a640b5b8b55b3c443731
diff --git a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/ContactTraversal.java b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/ContactTraversal.java
index 9685618..da66b71 100644
--- a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/ContactTraversal.java
+++ b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/ContactTraversal.java
@@ -1,7 +1,11 @@
 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.Contact;
 
 /** A {@link Traversal} that traverses a {@link Contact} object. */
@@ -12,11 +16,14 @@
       TraversalCoordinator traversalCoordinator,
       ExtensionValidationIntegrator extensionValidationIntegrator,
       TraversalCommandFactory traversalCommandFactory,
+      @Assisted
+          ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>> traversalPath,
       @Assisted Contact openApiSchemaObj) {
     super(
         traversalCoordinator,
         extensionValidationIntegrator,
         traversalCommandFactory,
+        traversalPath,
         openApiSchemaObj);
   }
 
diff --git a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/DistinctTraversal.java b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/DistinctTraversal.java
deleted file mode 100644
index 5faf34a..0000000
--- a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/DistinctTraversal.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.apigee.security.oas.extendedvalidator;
-
-import org.openapi4j.parser.model.OpenApiSchema;
-
-/**
- * A {@link Traversal} extension that adds naming capability for {@link OpenApiSchema} objects that
- * carry a distinct name.
- */
-abstract class DistinctTraversal<T extends OpenApiSchema> extends Traversal<T> {
-
-  private final String name;
-
-  DistinctTraversal(
-      TraversalCoordinator traversalCoordinator,
-      ExtensionValidationIntegrator extensionValidationIntegrator,
-      TraversalCommandFactory traversalCommandFactory,
-      T openApiSchemaObj,
-      String name) {
-    super(
-        traversalCoordinator,
-        extensionValidationIntegrator,
-        traversalCommandFactory,
-        openApiSchemaObj);
-    this.name = name;
-  }
-
-  protected String getName() {
-    return name;
-  }
-}
diff --git a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/ExternalDocsTraversal.java b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/ExternalDocsTraversal.java
index 59a9440..c3ff914 100644
--- a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/ExternalDocsTraversal.java
+++ b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/ExternalDocsTraversal.java
@@ -1,7 +1,11 @@
 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.ExternalDocs;
 
 /** A {@link Traversal} that traverses a {@link ExternalDocs} object. */
@@ -13,11 +17,15 @@
       TraversalCoordinator traversalCoordinator,
       ExtensionValidationIntegrator extensionValidationIntegrator,
       TraversalCommandFactory traversalCommandFactory,
-      @Assisted ExternalDocs openApiSchemaObj) {
+      @Assisted ExternalDocs openApiSchemaObj,
+      @Assisted
+          ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>>
+              traversalPath) {
     super(
         traversalCoordinator,
         extensionValidationIntegrator,
         traversalCommandFactory,
+        traversalPath,
         openApiSchemaObj);
   }
 
diff --git a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/InfoTraversal.java b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/InfoTraversal.java
index 18d3974..23134ba 100644
--- a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/InfoTraversal.java
+++ b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/InfoTraversal.java
@@ -1,8 +1,11 @@
 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.Info;
 
 /** A {@link Traversal} that traverses an {@link Info} object. */
@@ -13,11 +16,14 @@
       TraversalCoordinator traversalCoordinator,
       ExtensionValidationIntegrator extensionValidationIntegrator,
       TraversalCommandFactory traversalCommandFactory,
+      @Assisted
+          ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>> traversalPath,
       @Assisted Info openApiSchemaObj) {
     super(
         traversalCoordinator,
         extensionValidationIntegrator,
         traversalCommandFactory,
+        traversalPath,
         openApiSchemaObj);
   }
 
@@ -25,23 +31,28 @@
   public void traverse() {
     // TODO(b/161441872): Process extensions.
 
-    traverseContact();
-    traverseLicense();
+    ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>> traversalPath =
+        getUpdatedTraversalPath();
+
+    traverseContact(traversalPath);
+    traverseLicense(traversalPath);
   }
 
-  private void traverseContact() {
+  private void traverseContact(
+      ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>> traversalPath) {
     Optional.ofNullable(openApiSchemaObj.getContact())
         .ifPresent(
             contact ->
                 traversalCoordinator.handleTraversalCommand(
-                    traversalCommandFactory.create(contact)));
+                    traversalCommandFactory.create(contact, traversalPath)));
   }
 
-  private void traverseLicense() {
+  private void traverseLicense(
+      ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>> traversalPath) {
     Optional.ofNullable(openApiSchemaObj.getLicense())
         .ifPresent(
             license ->
                 traversalCoordinator.handleTraversalCommand(
-                    traversalCommandFactory.create(license)));
+                    traversalCommandFactory.create(license, traversalPath)));
   }
 }
diff --git a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/LicenseTraversal.java b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/LicenseTraversal.java
index ba5722d..1f84a6c 100644
--- a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/LicenseTraversal.java
+++ b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/LicenseTraversal.java
@@ -1,7 +1,11 @@
 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.License;
 
 /** A {@link Traversal} that traverses a {@link License} object. */
@@ -12,11 +16,14 @@
       TraversalCoordinator traversalCoordinator,
       ExtensionValidationIntegrator extensionValidationIntegrator,
       TraversalCommandFactory traversalCommandFactory,
+      @Assisted
+          ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>> traversalPath,
       @Assisted License openApiSchemaObj) {
     super(
         traversalCoordinator,
         extensionValidationIntegrator,
         traversalCommandFactory,
+        traversalPath,
         openApiSchemaObj);
   }
 
diff --git a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/OpenApiSpecificationTraversal.java b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/OpenApiSpecificationTraversal.java
index 793c773..159acb1 100644
--- a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/OpenApiSpecificationTraversal.java
+++ b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/OpenApiSpecificationTraversal.java
@@ -1,8 +1,11 @@
 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.OpenApi3;
 
 /** A {@link Traversal} that traverses an {@link OpenApi3} object. */
@@ -19,6 +22,7 @@
         traversalCoordinator,
         extensionValidationIntegrator,
         traversalCommandFactory,
+        ImmutableList.of(),
         openApiSchemaObj);
   }
 
@@ -26,44 +30,52 @@
   public void traverse() {
     // TODO(b/161441872): Process extensions.
 
-    traverseInfo();
-    traverseServers();
-    traverseTags();
-    traverseExternalDocs();
+    ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>>
+        updatedTraversalPath = getUpdatedTraversalPath();
+
+    traverseInfo(updatedTraversalPath);
+    traverseServers(updatedTraversalPath);
+    traverseTags(updatedTraversalPath);
+    traverseExternalDocs(updatedTraversalPath);
   }
 
-  private void traverseExternalDocs() {
+  private void traverseExternalDocs(
+      ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>> traversalPath) {
     Optional.ofNullable(openApiSchemaObj.getExternalDocs())
         .ifPresent(
             externalDocs ->
                 traversalCoordinator.handleTraversalCommand(
-                    traversalCommandFactory.create(externalDocs)));
+                    traversalCommandFactory.create(externalDocs, traversalPath)));
   }
 
-  private void traverseInfo() {
+  private void traverseInfo(
+      ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>> traversalPath) {
     Optional.ofNullable(openApiSchemaObj.getInfo())
         .ifPresent(
             info ->
-                traversalCoordinator.handleTraversalCommand(traversalCommandFactory.create(info)));
+                traversalCoordinator.handleTraversalCommand(
+                    traversalCommandFactory.create(info, traversalPath)));
   }
 
-  private void traverseServers() {
+  private void traverseServers(
+      ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>> traversalPath) {
     Optional.ofNullable(openApiSchemaObj.getServers())
         .ifPresent(
             servers ->
                 servers.forEach(
                     server ->
                         traversalCoordinator.handleTraversalCommand(
-                            traversalCommandFactory.create(server))));
+                            traversalCommandFactory.create(server, traversalPath))));
   }
 
-  private void traverseTags() {
+  private void traverseTags(
+      ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>> traversalPath) {
     Optional.ofNullable(openApiSchemaObj.getTags())
         .ifPresent(
             tags ->
                 tags.forEach(
                     tag ->
                         traversalCoordinator.handleTraversalCommand(
-                            traversalCommandFactory.create(tag))));
+                            traversalCommandFactory.create(tag, traversalPath))));
   }
 }
diff --git a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/ServerTraversal.java b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/ServerTraversal.java
index 36dea34..0d4f381 100644
--- a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/ServerTraversal.java
+++ b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/ServerTraversal.java
@@ -1,8 +1,11 @@
 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.Server;
 
 /** A {@link Traversal} that traverses a {@link Server} object. */
@@ -13,11 +16,14 @@
       TraversalCoordinator traversalCoordinator,
       ExtensionValidationIntegrator extensionValidationIntegrator,
       TraversalCommandFactory traversalCommandFactory,
+      @Assisted
+          ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>> traversalPath,
       @Assisted Server openApiSchemaObj) {
     super(
         traversalCoordinator,
         extensionValidationIntegrator,
         traversalCommandFactory,
+        traversalPath,
         openApiSchemaObj);
   }
 
@@ -35,7 +41,8 @@
               serverVariables.forEach(
                   (name, serverVariable) -> {
                     traversalCoordinator.handleTraversalCommand(
-                        traversalCommandFactory.create(serverVariable, name));
+                        traversalCommandFactory.create(
+                            serverVariable, name, getUpdatedTraversalPath()));
                   });
             });
   }
diff --git a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/ServerVariableTraversal.java b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/ServerVariableTraversal.java
index 255557c..408e38c 100644
--- a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/ServerVariableTraversal.java
+++ b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/ServerVariableTraversal.java
@@ -1,11 +1,15 @@
 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.ServerVariable;
 
-/** A {@link DistinctTraversal} that traverses a {@link ServerVariable} object. */
-final class ServerVariableTraversal extends DistinctTraversal<ServerVariable>
+/** A {@link Traversal} that traverses a {@link ServerVariable} object. */
+final class ServerVariableTraversal extends Traversal<ServerVariable>
     implements ServerVariableTraversalCommand {
 
   @Inject
@@ -13,12 +17,15 @@
       TraversalCoordinator traversalCoordinator,
       ExtensionValidationIntegrator extensionValidationIntegrator,
       TraversalCommandFactory traversalCommandFactory,
+      @Assisted
+          ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>> traversalPath,
       @Assisted ServerVariable openApiSchemaObj,
       @Assisted String name) {
     super(
         traversalCoordinator,
         extensionValidationIntegrator,
         traversalCommandFactory,
+        traversalPath,
         openApiSchemaObj,
         name);
   }
diff --git a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/TagTraversal.java b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/TagTraversal.java
index 52ecd34..755de96 100644
--- a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/TagTraversal.java
+++ b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/TagTraversal.java
@@ -1,8 +1,11 @@
 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.Tag;
 
 /** A {@link Traversal} that traverses a {@link Tag} object. */
@@ -13,11 +16,14 @@
       TraversalCoordinator traversalCoordinator,
       ExtensionValidationIntegrator extensionValidationIntegrator,
       TraversalCommandFactory traversalCommandFactory,
+      @Assisted
+          ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>> traversalPath,
       @Assisted Tag openApiSchemaObj) {
     super(
         traversalCoordinator,
         extensionValidationIntegrator,
         traversalCommandFactory,
+        traversalPath,
         openApiSchemaObj);
   }
 
@@ -25,10 +31,14 @@
   public void traverse() {
     // TODO(b/161441872): Add call to process extensions.
 
+    traverseExternalDocs();
+  }
+
+  private void traverseExternalDocs() {
     Optional.ofNullable(openApiSchemaObj.getExternalDocs())
         .ifPresent(
             externalDocs ->
                 traversalCoordinator.handleTraversalCommand(
-                    traversalCommandFactory.create(externalDocs)));
+                    traversalCommandFactory.create(externalDocs, getUpdatedTraversalPath())));
   }
 }
diff --git a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/Traversal.java b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/Traversal.java
index 7211dfb..c9c51d7 100644
--- a/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/Traversal.java
+++ b/oas-core/src/main/java/com/apigee/security/oas/extendedvalidator/Traversal.java
@@ -1,5 +1,10 @@
 package com.apigee.security.oas.extendedvalidator;
 
+import com.google.common.collect.ImmutableList;
+import java.util.AbstractMap;
+import java.util.ArrayDeque;
+import java.util.Map;
+import java.util.Optional;
 import org.openapi4j.parser.model.OpenApiSchema;
 
 /** Superclass field skeleton for traversing an {@link OpenApiSchema} object. */
@@ -9,15 +14,45 @@
   protected final TraversalCoordinator traversalCoordinator;
   protected final ExtensionValidationIntegrator extensionValidationIntegrator;
   protected final TraversalCommandFactory traversalCommandFactory;
+  private final ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>>
+      traversalPath;
+  private final Optional<String> name;
 
   Traversal(
       TraversalCoordinator traversalCoordinator,
       ExtensionValidationIntegrator extensionValidationIntegrator,
       TraversalCommandFactory traversalCommandFactory,
+      ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>> traversalPath,
       T openApiSchemaObj) {
     this.traversalCoordinator = traversalCoordinator;
     this.extensionValidationIntegrator = extensionValidationIntegrator;
     this.traversalCommandFactory = traversalCommandFactory;
+    this.traversalPath = traversalPath;
     this.openApiSchemaObj = openApiSchemaObj;
+    this.name = Optional.empty();
+  }
+
+  Traversal(
+      TraversalCoordinator traversalCoordinator,
+      ExtensionValidationIntegrator extensionValidationIntegrator,
+      TraversalCommandFactory traversalCommandFactory,
+      ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>> traversalPath,
+      T openApiSchemaObj,
+      String name) {
+    this.traversalCoordinator = traversalCoordinator;
+    this.extensionValidationIntegrator = extensionValidationIntegrator;
+    this.traversalCommandFactory = traversalCommandFactory;
+    this.traversalPath = traversalPath;
+    this.openApiSchemaObj = openApiSchemaObj;
+    this.name = Optional.of(name);
+  }
+
+  protected ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>>
+      getUpdatedTraversalPath() {
+    ArrayDeque<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>> updatedTraversalPath =
+        new ArrayDeque<>(traversalPath);
+    updatedTraversalPath.add(
+        new AbstractMap.SimpleImmutableEntry<>(openApiSchemaObj.getClass(), name));
+    return ImmutableList.copyOf(updatedTraversalPath);
   }
 }
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 e7d0ad4..54ea11a 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
@@ -1,5 +1,9 @@
 package com.apigee.security.oas.extendedvalidator;
 
+import com.google.common.collect.ImmutableList;
+import java.util.Map;
+import java.util.Optional;
+import org.openapi4j.parser.model.OpenApiSchema;
 import org.openapi4j.parser.model.v3.Contact;
 import org.openapi4j.parser.model.v3.ExternalDocs;
 import org.openapi4j.parser.model.v3.Info;
@@ -15,19 +19,34 @@
  */
 interface TraversalCommandFactory {
 
-  ContactTraversalCommand create(Contact contact);
+  ContactTraversalCommand create(
+      Contact contact,
+      ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>> traversalPath);
 
-  ExternalDocsTraversalCommand create(ExternalDocs externalDocs);
+  ExternalDocsTraversalCommand create(
+      ExternalDocs externalDocs,
+      ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>> traversalPath);
 
-  InfoTraversalCommand create(Info info);
+  InfoTraversalCommand create(
+      Info info,
+      ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>> traversalPath);
 
-  LicenseTraversalCommand create(License license);
+  LicenseTraversalCommand create(
+      License license,
+      ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>> traversalPath);
 
   OpenApiSpecificationTraversalCommand create(OpenApi3 openApiSpec);
 
-  ServerTraversalCommand create(Server server);
+  ServerTraversalCommand create(
+      Server server,
+      ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>> traversalPath);
 
-  ServerVariableTraversalCommand create(ServerVariable serverVariable, String name);
+  ServerVariableTraversalCommand create(
+      ServerVariable serverVariable,
+      String name,
+      ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>> traversalPath);
 
-  TagTraversalCommand create(Tag tag);
+  TagTraversalCommand create(
+      Tag tag,
+      ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>> traversalPath);
 }
diff --git a/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/BaseTraversalCoordinatorTest.java b/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/BaseTraversalCoordinatorTest.java
index 4a51d28..5a2ca2c 100644
--- a/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/BaseTraversalCoordinatorTest.java
+++ b/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/BaseTraversalCoordinatorTest.java
@@ -5,7 +5,6 @@
 
 import com.google.inject.Guice;
 import com.google.inject.Injector;
-import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -27,20 +26,14 @@
   @Mock private InfoTraversalCommand infoTraversalChildThree;
   @Mock private InfoTraversalCommand infoTraversalChildFour;
 
-  private TraversalCoordinator traversalCoordinator;
-
-  /** Sets up main module {@link Injector} and live {@link BaseTraversalCoordinator}. */
-  @Before
-  public void setUp() {
-    Injector injector = Guice.createInjector(new ExtendedValidatorMainModule());
-    traversalCoordinator = injector.getInstance(TraversalCoordinator.class);
-  }
+  private final Injector injector = Guice.createInjector(new ExtendedValidatorMainModule());
+  private final TraversalCoordinator traversalCoordinator =
+      injector.getInstance(TraversalCoordinator.class);
 
   /** Ensures a right to left depth first traversal is taking place. */
   @Test
   public void
       traverse_traversalCommandWithChildren_traversesAllChildrenRightToLeftBeforeMovingToNextParent() {
-
     doAnswer(
             invocationOnMock -> {
               traversalCoordinator.handleTraversalCommand(infoTraversalChildOne);
diff --git a/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/InfoTraversalTest.java b/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/InfoTraversalTest.java
index ffc56cd..8f47f1e 100644
--- a/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/InfoTraversalTest.java
+++ b/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/InfoTraversalTest.java
@@ -4,6 +4,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import com.google.common.collect.ImmutableList;
 import com.google.inject.Guice;
 import org.junit.Before;
 import org.junit.Rule;
@@ -38,7 +39,11 @@
 
     infoTraversal =
         new InfoTraversal(
-            traversalCoordinator, extensionValidationIntegrator, traversalCommandFactory, info);
+            traversalCoordinator,
+            extensionValidationIntegrator,
+            traversalCommandFactory,
+            ImmutableList.of(),
+            info);
 
     when(info.getContact()).thenReturn(new Contact());
     when(info.getLicense()).thenReturn(new License());
diff --git a/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/OpenApiSpecificationTraversalTest.java b/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/OpenApiSpecificationTraversalTest.java
index 4eab574..2ed7df8 100644
--- a/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/OpenApiSpecificationTraversalTest.java
+++ b/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/OpenApiSpecificationTraversalTest.java
@@ -7,6 +7,7 @@
 
 import com.google.common.collect.ImmutableList;
 import com.google.inject.Guice;
+import com.google.inject.Injector;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -38,9 +39,10 @@
   /** Sets up live and mocked instances for testing. */
   @Before
   public void setup() {
+    Injector injector = Guice.createInjector(new ExtendedValidatorMainModule());
+
     TraversalCommandFactory traversalCommandFactory =
-        Guice.createInjector(new ExtendedValidatorMainModule())
-            .getInstance(TraversalCommandFactory.class);
+        injector.getInstance(TraversalCommandFactory.class);
 
     openApiSpecificationTraversal =
         new OpenApiSpecificationTraversal(
diff --git a/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/ServerTraversalTest.java b/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/ServerTraversalTest.java
index 635b3fc..c031d72 100644
--- a/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/ServerTraversalTest.java
+++ b/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/ServerTraversalTest.java
@@ -5,6 +5,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.inject.Guice;
 import org.junit.Before;
@@ -41,7 +42,11 @@
 
     serverTraversal =
         new ServerTraversal(
-            traversalCoordinator, extensionValidationIntegrator, traversalCommandFactory, server);
+            traversalCoordinator,
+            extensionValidationIntegrator,
+            traversalCommandFactory,
+            ImmutableList.of(),
+            server);
 
     serverVariables =
         ImmutableMap.of(
diff --git a/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/TagTraversalTest.java b/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/TagTraversalTest.java
index bf3db6f..9c5a6ee 100644
--- a/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/TagTraversalTest.java
+++ b/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/TagTraversalTest.java
@@ -4,6 +4,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import com.google.common.collect.ImmutableList;
 import com.google.inject.Guice;
 import org.junit.Before;
 import org.junit.Rule;
@@ -37,7 +38,11 @@
 
     tagTraversal =
         new TagTraversal(
-            traversalCoordinator, extensionValidationIntegrator, traversalCommandFactory, tag);
+            traversalCoordinator,
+            extensionValidationIntegrator,
+            traversalCommandFactory,
+            ImmutableList.of(),
+            tag);
   }
 
   @Test
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 25920ac..585ee28 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
@@ -2,11 +2,15 @@
 
 import static org.assertj.core.api.Assertions.assertThat;
 
+import com.google.common.collect.ImmutableList;
 import com.google.inject.Guice;
-import org.junit.Before;
+import java.util.ArrayDeque;
+import java.util.Map;
+import java.util.Optional;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
+import org.openapi4j.parser.model.OpenApiSchema;
 import org.openapi4j.parser.model.v3.Contact;
 import org.openapi4j.parser.model.v3.ExternalDocs;
 import org.openapi4j.parser.model.v3.Info;
@@ -19,15 +23,11 @@
 @RunWith(JUnit4.class)
 public class TraversalCommandFactoryTest {
 
-  private TraversalCommandFactory traversalCommandFactory;
-
-  /** Sets up live {@link TraversalCommandFactory} instance. */
-  @Before
-  public void setUp() {
-    traversalCommandFactory =
-        Guice.createInjector(new ExtendedValidatorMainModule())
-            .getInstance(TraversalCommandFactory.class);
-  }
+  private static final TraversalCommandFactory traversalCommandFactory =
+      Guice.createInjector(new ExtendedValidatorMainModule())
+          .getInstance(TraversalCommandFactory.class);
+  private static final ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>>
+      traversalPath = ImmutableList.copyOf(new ArrayDeque<>());
 
   @Test
   public void
@@ -38,43 +38,45 @@
 
   @Test
   public void create_infoObjectPassed_returnsInfoTraversalCommand() {
-    assertThat(traversalCommandFactory.create(new Info())).isInstanceOf(InfoTraversalCommand.class);
+    assertThat(traversalCommandFactory.create(new Info(), traversalPath))
+        .isInstanceOf(InfoTraversalCommand.class);
   }
 
   @Test
   public void create_contactObjectPassed_returnsContactTraversalCommand() {
-    assertThat(traversalCommandFactory.create(new Contact()))
+    assertThat(traversalCommandFactory.create(new Contact(), traversalPath))
         .isInstanceOf(ContactTraversalCommand.class);
   }
 
   @Test
   public void create_licenseObjectPassed_returnsLicenseTraversalCommand() {
-    assertThat(traversalCommandFactory.create(new License()))
+    assertThat(traversalCommandFactory.create(new License(), traversalPath))
         .isInstanceOf(LicenseTraversalCommand.class);
   }
 
   @Test
   public void create_serverObjectPassed_returnsServerTraversalCommand() {
-    assertThat(traversalCommandFactory.create(new Server()))
+    assertThat(traversalCommandFactory.create(new Server(), traversalPath))
         .isInstanceOf(ServerTraversalCommand.class);
   }
 
   @Test
   public void create_nameAndServerVariableObjectPassed_returnsServerVariableTraversalCommand() {
     ServerVariableTraversalCommand traversal =
-        traversalCommandFactory.create(new ServerVariable(), "serverVariableName");
+        traversalCommandFactory.create(new ServerVariable(), "serverVariableName", traversalPath);
 
     assertThat(traversal).isInstanceOf(ServerVariableTraversalCommand.class);
   }
 
   @Test
   public void create_tagObjectPassed_returnsTagTraversalCommand() {
-    assertThat(traversalCommandFactory.create(new Tag())).isInstanceOf(TagTraversalCommand.class);
+    assertThat(traversalCommandFactory.create(new Tag(), traversalPath))
+        .isInstanceOf(TagTraversalCommand.class);
   }
 
   @Test
   public void create_externalDocsObjectPassed_returnsExternalDocsTraversalCommand() {
-    assertThat(traversalCommandFactory.create(new ExternalDocs()))
+    assertThat(traversalCommandFactory.create(new ExternalDocs(), traversalPath))
         .isInstanceOf(ExternalDocsTraversalCommand.class);
   }
 }
diff --git a/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/TraversalTest.java b/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/TraversalTest.java
new file mode 100644
index 0000000..c33087f
--- /dev/null
+++ b/oas-core/src/test/java/com/apigee/security/oas/extendedvalidator/TraversalTest.java
@@ -0,0 +1,50 @@
+package com.apigee.security.oas.extendedvalidator;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.google.common.collect.ImmutableList;
+import java.util.ArrayDeque;
+import java.util.Map;
+import java.util.Optional;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.mockito.quality.Strictness;
+import org.openapi4j.parser.model.OpenApiSchema;
+import org.openapi4j.parser.model.v3.Info;
+
+@RunWith(JUnit4.class)
+public class TraversalTest {
+
+  @Rule public MockitoRule rule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);
+
+  @Mock private TraversalCoordinator baseTraversalCoordinator;
+  @Mock private ExtensionValidationIntegrator baseExtensionValidationIntegrator;
+  @Mock private TraversalCommandFactory traversalCommandFactory;
+
+  @Test
+  public void instantiate_traversal_addsTraversalsOpenApiObjClassToTraversalPath() {
+
+    ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>> prevTraversalPath =
+        ImmutableList.copyOf(new ArrayDeque<>());
+    InfoTraversal traversal =
+        new InfoTraversal(
+            baseTraversalCoordinator,
+            baseExtensionValidationIntegrator,
+            traversalCommandFactory,
+            prevTraversalPath,
+            new Info());
+
+    ImmutableList<Map.Entry<Class<? extends OpenApiSchema>, Optional<String>>>
+        updatedTraversalPath = traversal.getUpdatedTraversalPath();
+
+    int expectedNewPathLength = prevTraversalPath.size() + 1;
+    assertThat(traversal.getUpdatedTraversalPath().size()).isEqualTo(expectedNewPathLength);
+    assertThat(updatedTraversalPath.asList().get(expectedNewPathLength - 1).getKey())
+        .isEqualTo(Info.class);
+  }
+}