class ResourceKey {
    private final String kind;
    private final String path;
    private final String group;
    private final String version;

    public ResourceKey(String kind, String path, String group, String version) {
      this.kind = kind;
      this.path = path;
      this.group = group;
      this.version = version;
    }

    public String getKind() {
      return kind;
    }

    public String getPath() {
      return path;
    }

    public String getGroup() {
      return group;
    }

    public String getVersion() {
      return version;
    }

    @Override
    public boolean equals(Object o) {
      if (this == o)
        return true;
      if (o == null || getClass() != o.getClass())
        return false;
      ResourceKey key = (ResourceKey) o;
      return Objects.equals(path, key.path) &&
          Objects.equals(group, key.group) &&
          Objects.equals(version, key.version);
    }

    @Override
    public int hashCode() {

      return Objects.hash(path, group, version);
    }
  }

  static {
    notFoundTransformations.put(new ResourceKey("Deployment", "deployments", "apps", "v1"),
        new ResourceKey("Deployment", "deployments", "extensions", "v1beta1"));
    notFoundTransformations.put(new ResourceKey("StatefulSet", "statefulsets", "apps", "v1"),
        new ResourceKey("StatefulSet", "statefulsets", "apps", "v1beta1"));
    notFoundTransformations.put(new ResourceKey("DaemonSets", "daemonsets", "apps", "v1"),
        new ResourceKey("DaemonSet", "daemonsets", "extensions", "v1beta1"));
    notFoundTransformations.put(new ResourceKey("ReplicaSets", "replicasets", "apps", "v1"),
        new ResourceKey("ReplicaSet", "replicasets", "extensions", "v1beta1"));
    notFoundTransformations
        .put(new ResourceKey("NetworkPolicy", "networkpolicies", "networking.k8s.io", "v1"),
            new ResourceKey("NetworkPolicy", "networkpolicies", "extensions", "v1beta1"));
    notFoundTransformations
        .put(new ResourceKey("StorageClass", "storageclasses", "storage.k8s.io", "v1"),
            new ResourceKey("StorageClass", "storageclasses", "extensions", "v1beta1"));
    notFoundTransformations.put(new ResourceKey("RoleBinding", "rolebindings", "rbac.authorization.k8s.io", "v1"),
        new ResourceKey("RoleBinding", "rolebindings", "rbac.authorization.k8s.io", "v1beta1"));
    notFoundTransformations.put(new ResourceKey("Role", "roles", "rbac.authorization.k8s.io", "v1"),
        new ResourceKey("Role", "roles", "rbac.authorization.k8s.io", "v1beta1"));
    notFoundTransformations.put(new ResourceKey("ClusterRoleBinding", "clusterrolebindings", "rbac.authorization.k8s.io", "v1"),
        new ResourceKey("ClusterRoleBinding", "clusterrolebindings", "rbac.authorization.k8s.io", "v1beta1"));
    notFoundTransformations.put(new ResourceKey("ClusterRole", "clusterroles", "rbac.authorization.k8s.io", "v1"),
        new ResourceKey("ClusterRole", "clusterroles", "rbac.authorization.k8s.io", "v1beta1"));
    notFoundTransformations.put(new ResourceKey("CronJob", "cronjobs", "batch", "v1"),
        new ResourceKey("CronJob", "cronjobs", "batch", "v1beta1"));
    notFoundTransformations.put(new ResourceKey("CronJob", "cronjobs", "batch", "v1beta1"),
        new ResourceKey("CronJob", "cronjobs", "batch", "v2alpha1"));
    notFoundTransformations.put(new ResourceKey("Template", "template", "", "v1"),
        new ResourceKey("Template", "template", "template.openshift.io", "v1"));

    badRequestTransformations.put(new ResourceKey("Deployment", "deployments", "apps", "v1beta1"),
        new ResourceKey("Deployment", "deployments", "extensions", "v1beta1"));

    responseCodeToTransformations.put(400, badRequestTransformations);
    responseCodeToTransformations.put(404, notFoundTransformations);

    /**
     * OpenShift versions prior to 3.10 use the /oapi endpoint for Openshift specific resources.
     * However, since 3.10 /apis/{group} is being used. This has been removed completely in 4.x
     * versions of OpenShift. Hence, this code is to handle those cases.
     */
    openshiftOAPITransformations.put("routes", new ResourceKey("Route", "routes", "route.openshift.io", "v1"));
    openshiftOAPITransformations.put("templates", new ResourceKey("Template", "templates", "template.openshift.io", "v1"));
    openshiftOAPITransformations.put("buildconfigs",
        new ResourceKey("BuildConfig", "buildconfigs", "build.openshift.io", "v1"));
    openshiftOAPITransformations.put("deploymentconfigs",
        new ResourceKey("DeploymentConfig", "deploymentconfigs", "apps.openshift.io", "v1"));
    openshiftOAPITransformations.put("imagestreams",
        new ResourceKey("ImageStream", "imagestreams", "image.openshift.io", "v1"));
    openshiftOAPITransformations.put("imagestreamtags",
        new ResourceKey("ImageStream", "imagestreamtags", "image.openshift.io", "v1"));
    openshiftOAPITransformations.put("securitycontextconstraints",
        new ResourceKey("SecurityContextConstraints", "securitycontextconstraints", "security.openshift.io", "v1"));
  }

  @Override
  public CompletableFuture<Boolean> afterFailure(Builder builder, HttpResponse<?> response, RequestTags tags) {<FILL_FUNCTION_BODY>

    ResourceKey target = findNewTarget(builder, response);
    if (target == null) {
      return CompletableFuture.completedFuture(false);
    }

    HttpRequest request = response.request();
    if (request.bodyString() != null && !request.method().equalsIgnoreCase(PATCH)) {
      JsonNode object = Serialization.unmarshal(request.bodyString(), JsonNode.class);
      if (object.get("apiVersion") != null) {
        ((ObjectNode) object).put("apiVersion", target.group + "/" + target.version);
        switch (request.method()) {
          case "POST":
            builder.post(JSON, Serialization.asJson(object));
            break;
          case "PUT":
            builder.put(JSON, Serialization.asJson(object));
            break;
          case "DELETE":
            builder.delete(JSON, Serialization.asJson(object));
            break;
          default:
            return CompletableFuture.completedFuture(false);
        }
      }
    }

    return CompletableFuture.completedFuture(true);
  
<no_super_class>