class CacheKey implements Key {
        private final Plugin plugin;

        private final WorkspaceRepository workspace;

        private final LocalRepository localRepo;

        private final List<RemoteRepository> repositories;

        private final DependencyFilter filter;

        private final int hashCode;

        public CacheKey(
                Plugin plugin,
                DependencyFilter extensionFilter,
                List<RemoteRepository> repositories,
                RepositorySystemSession session) {
            this.plugin = plugin.clone();
            workspace = RepositoryUtils.getWorkspace(session);
            this.localRepo = session.getLocalRepository();
            this.repositories = new ArrayList<>(repositories.size());
            for (RemoteRepository repository : repositories) {
                if (repository.isRepositoryManager()) {
                    this.repositories.addAll(repository.getMirroredRepositories());
                } else {
                    this.repositories.add(repository);
                }
            }
            this.filter = extensionFilter;

            int hash = 17;
            hash = hash * 31 + CacheUtils.pluginHashCode(plugin);
            hash = hash * 31 + Objects.hashCode(workspace);
            hash = hash * 31 + Objects.hashCode(localRepo);
            hash = hash * 31 + RepositoryUtils.repositoriesHashCode(repositories);
            hash = hash * 31 + Objects.hashCode(extensionFilter);
            this.hashCode = hash;
        }

        @Override
        public String toString() {
            return plugin.getId();
        }

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

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

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

            CacheKey that = (CacheKey) o;

            return CacheUtils.pluginEquals(plugin, that.plugin)
                    && Objects.equals(workspace, that.workspace)
                    && Objects.equals(localRepo, that.localRepo)
                    && RepositoryUtils.repositoriesEquals(repositories, that.repositories)
                    && Objects.equals(filter, that.filter);
        }
    }

    protected final Map<Key, CacheRecord> cache = new ConcurrentHashMap<>();

    public Key createKey(
            Plugin plugin,
            DependencyFilter extensionFilter,
            List<RemoteRepository> repositories,
            RepositorySystemSession session) {
        return new CacheKey(plugin, extensionFilter, repositories, session);
    }

    public CacheRecord get(Key key) throws PluginResolutionException {
        CacheRecord cacheRecord = cache.get(key);

        if (cacheRecord != null && cacheRecord.getException() != null) {
            throw cacheRecord.getException();
        }

        return cacheRecord;
    }

    public CacheRecord put(Key key, List<Artifact> pluginArtifacts) {
        Objects.requireNonNull(pluginArtifacts, "pluginArtifacts cannot be null");

        assertUniqueKey(key);

        CacheRecord record = new CacheRecord(Collections.unmodifiableList(new ArrayList<>(pluginArtifacts)));

        cache.put(key, record);

        return record;
    }

    protected void assertUniqueKey(Key key) {<FILL_FUNCTION_BODY>

        if (cache.containsKey(key)) {
            throw new IllegalStateException("Duplicate artifact resolution result for plugin " + key);
        }
    
<no_super_class>