class CacheKey {
        private final Artifact artifact;
        private final long pomHash;
        private final boolean resolveManagedVersions;
        private final List<ArtifactRepository> repositories = new ArrayList<>();
        private final int hashCode;

        public CacheKey(
                Artifact artifact,
                boolean resolveManagedVersions,
                ArtifactRepository localRepository,
                List<ArtifactRepository> remoteRepositories) {
            File file = artifact.getFile();
            this.artifact = ArtifactUtils.copyArtifact(artifact);
            if ("pom".equals(artifact.getType()) && file != null) {
                pomHash = file.getPath().hashCode() + file.lastModified();
            } else {
                pomHash = 0;
            }
            this.resolveManagedVersions = resolveManagedVersions;
            this.repositories.add(localRepository);
            this.repositories.addAll(remoteRepositories);

            int hash = 17;
            hash = hash * 31 + artifactHashCode(artifact);
            hash = hash * 31 + (resolveManagedVersions ? 1 : 2);
            hash = hash * 31 + repositoriesHashCode(repositories);
            this.hashCode = hash;
        }

        @Override
        public int hashCode() {
            return hashCode;
        }

        @Override
        public boolean equals(Object o) {
            if (o == this) {
                return true;
            }

            if (!(o instanceof CacheKey)) {
                return false;
            }

            CacheKey other = (CacheKey) o;

            return pomHash == other.pomHash
                    && artifactEquals(artifact, other.artifact)
                    && resolveManagedVersions == other.resolveManagedVersions
                    && repositoriesEquals(repositories, other.repositories);
        }
    }

    private static int artifactHashCode(Artifact a) {
        int result = 17;
        result = 31 * result + a.getGroupId().hashCode();
        result = 31 * result + a.getArtifactId().hashCode();
        result = 31 * result + a.getType().hashCode();
        if (a.getVersion() != null) {
            result = 31 * result + a.getVersion().hashCode();
        }
        result = 31 * result + (a.getClassifier() != null ? a.getClassifier().hashCode() : 0);
        result = 31 * result + (a.getScope() != null ? a.getScope().hashCode() : 0);
        result = 31 * result
                + (a.getDependencyFilter() != null ? a.getDependencyFilter().hashCode() : 0);
        result = 31 * result + (a.isOptional() ? 1 : 0);
        return result;
    }

    private static boolean artifactEquals(Artifact a1, Artifact a2) {
        if (a1 == a2) {
            return true;
        }

        return Objects.equals(a1.getGroupId(), a2.getGroupId())
                && Objects.equals(a1.getArtifactId(), a2.getArtifactId())
                && Objects.equals(a1.getType(), a2.getType())
                && Objects.equals(a1.getVersion(), a2.getVersion())
                && Objects.equals(a1.getClassifier(), a2.getClassifier())
                && Objects.equals(a1.getScope(), a2.getScope())
                && Objects.equals(a1.getDependencyFilter(), a2.getDependencyFilter())
                && a1.isOptional() == a2.isOptional();
    }

    private static int repositoryHashCode(ArtifactRepository repository) {
        int result = 17;
        result = 31 * result + (repository.getId() != null ? repository.getId().hashCode() : 0);
        return result;
    }

    private static int repositoriesHashCode(List<ArtifactRepository> repositories) {
        int result = 17;
        for (ArtifactRepository repository : repositories) {
            result = 31 * result + repositoryHashCode(repository);
        }
        return result;
    }

    private static boolean repositoryEquals(ArtifactRepository r1, ArtifactRepository r2) {
        if (r1 == r2) {
            return true;
        }

        return Objects.equals(r1.getId(), r2.getId())
                && Objects.equals(r1.getUrl(), r2.getUrl())
                && repositoryPolicyEquals(r1.getReleases(), r2.getReleases())
                && repositoryPolicyEquals(r1.getSnapshots(), r2.getSnapshots());
    }

    private static boolean repositoryPolicyEquals(ArtifactRepositoryPolicy p1, ArtifactRepositoryPolicy p2) {
        if (p1 == p2) {
            return true;
        }

        return p1.isEnabled() == p2.isEnabled() && Objects.equals(p1.getUpdatePolicy(), p2.getUpdatePolicy());
    }

    private static boolean repositoriesEquals(List<ArtifactRepository> r1, List<ArtifactRepository> r2) {<FILL_FUNCTION_BODY>

        if (r1.size() != r2.size()) {
            return false;
        }

        for (Iterator<ArtifactRepository> it1 = r1.iterator(), it2 = r2.iterator(); it1.hasNext(); ) {
            if (!repositoryEquals(it1.next(), it2.next())) {
                return false;
            }
        }

        return true;
    
<no_super_class>