/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.netbeans.modules.cloud.oracle.adm;

import com.oracle.bmc.adm.ApplicationDependencyManagementClient;
import com.oracle.bmc.adm.model.ApplicationDependency;
import com.oracle.bmc.adm.model.ApplicationDependencyVulnerabilitySummary;
import com.oracle.bmc.adm.model.CreateVulnerabilityAuditDetails;
import com.oracle.bmc.adm.model.SortOrder;
import com.oracle.bmc.adm.model.Vulnerability;
import com.oracle.bmc.adm.model.VulnerabilityAudit;
import com.oracle.bmc.adm.model.VulnerabilityAudit.LifecycleState;
import com.oracle.bmc.adm.model.VulnerabilityAuditConfiguration;
import com.oracle.bmc.adm.model.VulnerabilityAuditSummary;
import com.oracle.bmc.adm.requests.CreateVulnerabilityAuditRequest;
import com.oracle.bmc.adm.requests.ListApplicationDependencyVulnerabilitiesRequest;
import com.oracle.bmc.adm.requests.ListVulnerabilityAuditsRequest;
import com.oracle.bmc.adm.responses.CreateVulnerabilityAuditResponse;
import com.oracle.bmc.adm.responses.ListApplicationDependencyVulnerabilitiesResponse;
import com.oracle.bmc.adm.responses.ListVulnerabilityAuditsResponse;
import com.oracle.bmc.model.BmcException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.netbeans.api.editor.mimelookup.MimeRegistration;
import org.netbeans.api.editor.mimelookup.MimeRegistrations;
import org.netbeans.api.lsp.Diagnostic;
import org.netbeans.api.progress.ProgressHandle;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectUtils;
import org.netbeans.modules.cloud.oracle.OCIManager;
import org.netbeans.modules.project.dependency.ArtifactSpec;
import org.netbeans.modules.project.dependency.Dependency;
import org.netbeans.modules.project.dependency.DependencyResult;
import org.netbeans.modules.project.dependency.ProjectDependencies;
import org.netbeans.modules.project.dependency.Scopes;
import org.netbeans.modules.project.dependency.SourceLocation;
import org.netbeans.spi.lsp.ErrorProvider;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.filesystems.FileObject;
import org.openide.util.Exceptions;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.RequestProcessor;

/**
 *
 * @author Petr Pisl
 */
@NbBundle.Messages({
    "# {0} - project name",
    "MSG_Audit_Pass=Vulnerability audit for project {0} is done.\nNo vulnerability was found.",
    "# {0} - project name",
    "MSG_Audit_Failed_One=Vulnerability audit for project {0} is done.\nOne vulnerability was found.\nThe vulnerability is listed in Problems window.",
    "# {0} - project name",
    "# {1} - number of vulnerabilities",
    "MSG_Audit_Failed_More=Vulnerability audit for project {0} is done.\n{1} vulnerabilities were found.\nThe vulnerabilities are listed in Problems window.",
    "# {0} - project name",
    "MSG_CreatingAuditFailed=Creating Vulnerablity audit for project {0} failed.",
    "# {0} - project name",
    "MSG_ListingAuditFailed=Obtaining newly created vulnerablity audit for project {0} failed.",
    "MSG_ListingVulnerabilitiesFailed=Obtaining vulnerabilities for newly created audit failed.",
    "# {0} - project name",
    "MSG_AuditIsRunning=Audit of {0} project is running ...",
    "MSG_NotAvailable=Not available",
    "MSG_Diagnostic=Vulnerability\n"
            + "  Cvss V2 Score: %s\n"
            + "  Cvss V3 Score: %s\n"
            + "  Caused by dependence: %s"
})
 
@MimeRegistrations({
    @MimeRegistration(mimeType = "text/x-maven-pom+xml", service = ErrorProvider.class),
    @MimeRegistration(mimeType = "text/x-gradle+x-groovy", service = ErrorProvider.class)  
})

public class VulnerabilityWorker implements ErrorProvider{
    private static final RequestProcessor SOURCE_REFRESH_PROCESSOR = new RequestProcessor(VulnerabilityWorker.class.getName());
    
    private static final Logger LOG = Logger.getLogger(VulnerabilityWorker.class.getName());
    
    // PENDING: should be customizable from project configuration somehow.
    private static final String GOV_DETAIL_URL = "https://nvd.nist.gov/vuln/detail/";
    
    // @GuardedBy(self)
    private static final HashMap<Project, CacheItem> cache = new HashMap();
    
    // @GuardedBy(class)
    private static VulnerabilityWorker instance;

    /**
     * Cached information + watcher over the project file data. Will watch for dependency change event,
     * that is fired e.g. after project reload, and will REPLACE ITSELF in the cache + fire
     * event that causes LSP to re-evaluate errors for the affected project file(s).
     */
    static class CacheItem {
        private final Project project;
        private final DependencyResult dependencyResult;
        private final VulnerabilityReport report;

        /**
         * Maps GAV -> dependency.
         */
        private Map<String, Dependency> dependencyMap;
        
        // @GuardedBy(this)
        private ChangeListener depChange;
        
        // @GuardedBy(this)
        private RequestProcessor.Task pendingRefresh;

        public CacheItem(Project project, DependencyResult dependency, VulnerabilityReport report) {
            this.project = project;
            this.dependencyResult = dependency;
            this.report = report;
        }

        public DependencyResult getDependency() {
            return dependencyResult;
        }

        public VulnerabilityAuditSummary getAudit() {
            return report.summary;
        }

        public List<ApplicationDependencyVulnerabilitySummary> getVulnerabilities() {
            return report.items;
        }

        public Map<String, Dependency> getDependencyMap() {
            if (dependencyMap == null) {
                dependencyMap = new HashMap();
                buildDependecyMap(dependencyResult.getRoot(), dependencyMap);
            }
            return dependencyMap;
        }
        
        private void buildDependecyMap(Dependency dependency, Map<String, Dependency> result) {
            String gav = createGAV(dependency.getArtifact());
            if (result.putIfAbsent(gav, dependency) == null) {
                dependency.getChildren().forEach((childDependency) -> {
                    buildDependecyMap(childDependency, result);
                });
            }
        }
        
        public Set<FileObject> getProblematicFiles() {
            if (getAudit().getIsSuccess()) {
                return Collections.EMPTY_SET;
            }
            Set<FileObject> result = new HashSet();
            for (ApplicationDependencyVulnerabilitySummary v: getVulnerabilities()){
                List<Vulnerability> vulnerabilities = v.getVulnerabilities();
                if (!vulnerabilities.isEmpty()) {
                    Dependency dep = getDependencyMap().get(v.getGav());
                    if (dep != null) {
                        try {
                            SourceLocation declarationRange = this.dependencyResult.getDeclarationRange(dep, null);
                            if (declarationRange == null) {
                                declarationRange = this.dependencyResult.getDeclarationRange(dep, DependencyResult.PART_CONTAINER);
                            }
                            if(declarationRange != null  && declarationRange.getFile() != null) {
                                result.add(declarationRange.getFile());
                            }
                        } catch (IOException ex) {
                            // expected, ignore.
                        }
                    }
                }
            }
            return result;
        }
        
        void refreshDependencies(RequestProcessor.Task t) {
            DependencyResult dr = ProjectDependencies.findDependencies(project, ProjectDependencies.newQuery(Scopes.RUNTIME));
            LOG.log(Level.FINER, "{0} - dependencies refreshed", this);
            synchronized (this) {
                if (pendingRefresh != t) {
                    return;
                }
            }
            synchronized (this) {
                if (depChange != null) {
                    dependencyResult.removeChangeListener(depChange);
                }
            }
            CacheItem novy = new CacheItem( project, dr, report);
            if (LOG.isLoggable(Level.FINER)) {
                LOG.log(Level.FINER, "{0} - trying to replace for {1}", new Object[] { this, novy });
            }
            if (replaceCacheItem(this, novy)) {
                novy.startListening();
                Diagnostic.ReporterControl reporter = Diagnostic.findReporterControl(Lookup.getDefault(), project.getProjectDirectory());
                Set<FileObject> allFiles = new HashSet<>();
                allFiles.addAll(getProblematicFiles());
                allFiles.addAll(novy.getProblematicFiles());
                if (LOG.isLoggable(Level.FINER)) {
                    LOG.log(Level.FINER, "{0} - refreshing files: {1}", new Object[] { this, allFiles });
                }
                reporter.diagnosticChanged(novy.getProblematicFiles(), null);
            }
        }
        
        void scheduleDependencyRefresh(ChangeEvent e) {
            synchronized (this) {
                if (pendingRefresh != null) {
                    pendingRefresh.cancel();
                }
                
                RequestProcessor.Task[] task = new RequestProcessor.Task[1];
                if (LOG.isLoggable(Level.FINER)) {
                    LOG.log(Level.FINER, "{0} - scheduling refresh for {1}", new Object[] { this, project });
                }
                pendingRefresh = task[0] = SOURCE_REFRESH_PROCESSOR.post(() -> {
                    synchronized (this) {
                        refreshDependencies(task[0]);
                    }
                });
            }
        }
        
        SourceLocation getDependencyRange(Dependency d) throws IOException {
            return getDependencyRange(d, null);
        }
        
        void startListening() {
            synchronized (this) {
                if (depChange == null) {
                    dependencyResult.addChangeListener(depChange = this::scheduleDependencyRefresh);
                    LOG.log(Level.FINER, "{0} - start listen for dependencies", this);
                }
            }
        }
        
        SourceLocation getDependencyRange(Dependency d, String part) throws IOException {
            startListening();
            return dependencyResult.getDeclarationRange(d, part);
        }
        
        public List<Diagnostic> getDiagnosticsForFile(FileObject file) {
            if (LOG.isLoggable(Level.FINER)) {
                LOG.log(Level.FINER, "{0} getDiagnostics called for {1}", new Object[] { this, file });
            }
            if (getVulnerabilities() == null || getVulnerabilities().isEmpty()) {
                return null;
            }
            
            List<Diagnostic> result = new ArrayList();
            for (ApplicationDependencyVulnerabilitySummary v: getVulnerabilities()){
                List<Vulnerability> vulnerabilities = v.getVulnerabilities();
                if (!vulnerabilities.isEmpty()) {
                    startListening();
                    Dependency dependency = getDependencyMap().get(v.getGav());
                    SourceLocation declarationRange = null;
                    
                    if (dependency != null) {
                        try {
                            declarationRange = getDependencyRange(dependency);
                        } catch (IOException ex) {
                            Exceptions.printStackTrace(ex);
                        }
                    }
                    // display the vulnerabilities that were never mapped on the dependency container's line.
                    // also display the vulnerabilities that we KNOW about, but do can not map them back to the project file, i.e.
                    // plugin-introduced dependencies (gradle).
                    if (declarationRange == null && (dependency != null || !report.mappedVulnerabilities.contains(v.getGav()))) {
                        try {
                            if (LOG.isLoggable(Level.FINER)) {
                                LOG.log(Level.FINER, "{0} getDiagnostics called for {1}", new Object[] { this, file });
                            }

                            declarationRange = getDependencyRange(dependency, DependencyResult.PART_CONTAINER);
                            if (declarationRange != null) {
                                // discard end location, since it could span a whole section
                                declarationRange = new SourceLocation(declarationRange.getFile(), 
                                        declarationRange.getStartOffset(), declarationRange.getStartOffset(), null);
                            }
                        } catch (IOException ex) {
                            // ignore
                        }                            
                    }

                    if (declarationRange != null && declarationRange.hasPosition() && declarationRange.getFile().equals(file)) {
                        final SourceLocation fDeclarationRange = declarationRange;
                        for(Vulnerability vulnerability: vulnerabilities) {
                            String message = String.format(Bundle.MSG_Diagnostic(), 
                                    formatCvssScore(vulnerability.getCvssV2Score()), 
                                    formatCvssScore(vulnerability.getCvssV3Score()), 
                                    createGAV(dependency.getArtifact()));
                            Diagnostic.Builder builder = Diagnostic.Builder.create(() -> fDeclarationRange.getStartOffset(), () -> fDeclarationRange.getEndOffset(), message);
                            builder.setSeverity(Diagnostic.Severity.Warning).setCode(vulnerability.getId());
                            try {
                                builder.setCodeDescription(new URL(GOV_DETAIL_URL + vulnerability.getId()));
                            } catch (MalformedURLException ex) {
                                // perhaps should not happen at all
                                LOG.log(Level.INFO, "Could not link to vulnerability: {0}", vulnerability.getId());
                            }
                            result.add(builder.build());
                        }
                    }
                }
            }
            return result;
        }
        
        private String formatCvssScore(Float value) {
            if (value != null) {
                return String.format("%.2f", value);
            }
            return Bundle.MSG_NotAvailable();
        }
    }
    
    private static boolean replaceCacheItem(CacheItem old, CacheItem novy) {
        synchronized (cache) {
            CacheItem registered = cache.get(old.project);
            if (registered != old) {
                return false;
            }
            cache.put(novy.project, novy);
        }
        return true;
    }
    
    private VulnerabilityWorker() {
    }

    public static VulnerabilityWorker getInstance() {
        synchronized (VulnerabilityWorker.class) {
            if (instance == null) {
                instance = new VulnerabilityWorker();

            }
        }
        return instance;
    }

    public void findVulnerability(Project project, boolean forceAudit) {
        LOG.log(Level.FINER, "Trying to obtain audit for project {0}, force:{1}", new Object[] { project, forceAudit });
        final String projectDisplayName = ProjectUtils.getInformation(project).getDisplayName();
        KnowledgeBaseItem kbItem = getKnowledgeBaseForProject(project);
        if (kbItem == null) {
            return;
        }
        
        // remove from the cache old values
        ProgressHandle progressHandle = ProgressHandle.createHandle(Bundle.MSG_AuditIsRunning(projectDisplayName));
        progressHandle.start();
        try {
            doFindVulnerability(project, kbItem.compartmentId, kbItem.getKey().getValue(), 
                    projectDisplayName, progressHandle, forceAudit);
        } finally {
            progressHandle.finish();
            kbItem.refresh();
        }
    }

    public void doFindVulnerability(Project project, String compartmentId, String knowledgeBaseId, String projectDisplayName,
            ProgressHandle progressHandle, boolean forceAudit) {
        DependencyResult dr = ProjectDependencies.findDependencies(project, ProjectDependencies.newQuery(Scopes.RUNTIME));
        List<ApplicationDependency> result = new ArrayList();
        convert(dr.getRoot(), new HashMap<>(), result);
        
        CacheItem cacheItem = null;
        VulnerabilityReport savedAudit = null;
        
        if (!forceAudit) {
            try {
                savedAudit = AuditCache.getInstance().loadAudit(knowledgeBaseId);
            } catch (IOException ex) {
                LOG.log(Level.WARNING, "Could not load cached audit data", ex);
            }
        }
        
        boolean auditDone = false;
        
        if (!forceAudit && savedAudit == null) {
            // attempt to find an active most recent audit:
            try (ApplicationDependencyManagementClient admClient
                    = new ApplicationDependencyManagementClient(OCIManager.getDefault().getConfigProvider())) {
                ListVulnerabilityAuditsRequest request = ListVulnerabilityAuditsRequest
                        .builder()
                        .compartmentId(compartmentId)
                        .knowledgeBaseId(knowledgeBaseId)
                        .lifecycleState(LifecycleState.Active)
                        .sortBy(ListVulnerabilityAuditsRequest.SortBy.TimeCreated)
                        .sortOrder(SortOrder.Desc).build();
                ListVulnerabilityAuditsResponse response = admClient.listVulnerabilityAudits(request);
                if (!response.getVulnerabilityAuditCollection().getItems().isEmpty()) {
                    VulnerabilityAuditSummary summary = response.getVulnerabilityAuditCollection().getItems().get(0);
                    cacheItem = fetchVulnerabilityItems(project, admClient, dr, summary, projectDisplayName);
                    savedAudit = new VulnerabilityReport(cacheItem.getAudit(), cacheItem.getVulnerabilities());
                }
            } catch (BmcException ex) {
                LOG.log(Level.FINE, "Unable to list newest audit for knowledgebase {0}, compartment {1}", new Object[] {
                    knowledgeBaseId, compartmentId
                });
            }
        }
        
        if (savedAudit == null && forceAudit) {
            try (ApplicationDependencyManagementClient admClient
                    = new ApplicationDependencyManagementClient(OCIManager.getDefault().getConfigProvider())) {
                final VulnerabilityAuditConfiguration auditConfiguration = VulnerabilityAuditConfiguration
                        .builder()
                        .maxPermissibleCvssV2Score(1f)
                        .maxPermissibleCvssV3Score(1f)
                        .exclusions(Collections.unmodifiableList(Collections.EMPTY_LIST))
                        .build();
                final CreateVulnerabilityAuditDetails auditDetails = CreateVulnerabilityAuditDetails
                        .builder()
                        .compartmentId(compartmentId)
                        .knowledgeBaseId(knowledgeBaseId)
                        .displayName(projectDisplayName.replaceAll("[^A-Za-z0-9-_]", "_")) // remove offending characters
                        .buildType(VulnerabilityAudit.BuildType.Maven)
                        .configuration(auditConfiguration)
                        .applicationDependencies(result)
                        .build();
                CreateVulnerabilityAuditResponse response = admClient.createVulnerabilityAudit(CreateVulnerabilityAuditRequest
                        .builder()
                        .createVulnerabilityAuditDetails(auditDetails)
                        .build());
                if (response.get__httpStatusCode__() != 201 && response.get__httpStatusCode__() != 200) {
                    ErrorUtils.processError(response, Bundle.MSG_CreatingAuditFailed(projectDisplayName));
                    return;
                }
                // audit is ok
                cacheItem = waitToAuditFinish(project, admClient, dr, response.getVulnerabilityAudit(), projectDisplayName);
                auditDone = true;
            } catch (BmcException exc) {
                ErrorUtils.processError(exc, compartmentId);
                return;
            } finally {
                progressHandle.finish();
            }
        } else if (savedAudit != null) {
            cacheItem = new CacheItem(project, dr, savedAudit);
        }

        if (cacheItem != null) {
            synchronized (cache) {
                cache.put(project, cacheItem);
            }

            Set<FileObject> problematicFiles = new HashSet();
            problematicFiles.addAll(cacheItem.getProblematicFiles());

            String message;
            if (cacheItem.getAudit().getIsSuccess()) {
                message = Bundle.MSG_Audit_Pass(projectDisplayName);
                problematicFiles.addAll(dr.getDependencyFiles());
            } else if(cacheItem.getAudit().getVulnerableArtifactsCount() == 1) {
                message = Bundle.MSG_Audit_Failed_One(projectDisplayName);
            } else {
                message = Bundle.MSG_Audit_Failed_More(projectDisplayName, cacheItem.getAudit().getVulnerableArtifactsCount());
            }
            if (auditDone) {
                DialogDisplayer.getDefault().notifyLater(
                                new NotifyDescriptor.Message(message));
            }
            Diagnostic.ReporterControl reporter = Diagnostic.findReporterControl(Lookup.getDefault(), project.getProjectDirectory());
            reporter.diagnosticChanged(problematicFiles, null);
        }
    }
    
    public static KnowledgeBaseItem getKnowledgeBaseForProject(Project project) {
        ProjectVulnerability vs = project.getLookup().lookup(ProjectVulnerability.class);
        return vs != null ? vs.getProjectKnowledgeBase() : null;
    }
    
    private int convert(Dependency dependency, Map<String, Integer> gavIndex, List<ApplicationDependency> result) {
        String gav = createGAV(dependency.getArtifact());
        Integer n = gavIndex.get(gav);
        if (n != null) {
            return n;
        }
        gavIndex.put(gav, n = gavIndex.size() + 1);
        ApplicationDependency.Builder builder = ApplicationDependency.builder();
        builder.gav(gav);
        builder.nodeId(Integer.toString(n));
        
        List<String> childrenNodeIds = new ArrayList(dependency.getChildren().size());
        for (Dependency childDependency : dependency.getChildren()) {
            int cid = convert(childDependency, gavIndex, result);
            childrenNodeIds.add(Integer.toString(cid));
        }
        builder.applicationDependencyNodeIds(childrenNodeIds);
        result.add(builder.build());
        return n;
    }

    private static String createGAV(ArtifactSpec artifact) {
        StringBuffer sb = new StringBuffer();
        sb.append(artifact.getGroupId()).append(':');
        sb.append(artifact.getArtifactId()).append(':');
        sb.append(artifact.getVersionSpec());
        return sb.toString();
    }

    private CacheItem waitToAuditFinish(Project project, ApplicationDependencyManagementClient client, 
            DependencyResult dr, VulnerabilityAudit audit, String projectName) {                
        ListVulnerabilityAuditsRequest request = ListVulnerabilityAuditsRequest.builder()
                .knowledgeBaseId(audit.getKnowledgeBaseId()).id(audit.getId()).build();
        VulnerabilityAuditSummary auditSummary;
        boolean first = true;
        do {
            if (first) {
                first = false;
            } else {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException ex) {
                    Exceptions.printStackTrace(ex);
                }
            }
            ListVulnerabilityAuditsResponse response = client.listVulnerabilityAudits(request);
            if (response.get__httpStatusCode__() != 200) {
                ErrorUtils.processError(response, Bundle.MSG_ListingAuditFailed(projectName));
                return null;
            }
            List<VulnerabilityAuditSummary> items = response.getVulnerabilityAuditCollection().getItems();
            auditSummary = items.get(0);
        } while (auditSummary.getLifecycleState() == VulnerabilityAudit.LifecycleState.Creating);
        return fetchVulnerabilityItems(project, client, dr, auditSummary, projectName);
    }
    
    private CacheItem fetchVulnerabilityItems(Project project, ApplicationDependencyManagementClient client, 
            DependencyResult dr, VulnerabilityAuditSummary auditSummary, String projectName) {
        List<ApplicationDependencyVulnerabilitySummary> items = new ArrayList<>();
        if (auditSummary.getVulnerableArtifactsCount() > 0) {
            String nextPage = null;
            do {
                ListApplicationDependencyVulnerabilitiesRequest.Builder b = ListApplicationDependencyVulnerabilitiesRequest.builder().vulnerabilityAuditId(auditSummary.getId());
                if (nextPage != null) {
                    b.page(nextPage);
                }
                ListApplicationDependencyVulnerabilitiesRequest advRequest = b.build();
                ListApplicationDependencyVulnerabilitiesResponse vulners = client.listApplicationDependencyVulnerabilities(advRequest);
                if (vulners.get__httpStatusCode__() == 200) {
                    vulners.getApplicationDependencyVulnerabilityCollection().getItems().stream().filter(v -> !v.getVulnerabilities().isEmpty())
                            .forEach(v -> items.add(v));
                } else {
                    ErrorUtils.processError(vulners, Bundle.MSG_ListingVulnerabilitiesFailed());
                    return null;
                }
                nextPage = vulners.getOpcNextPage();
            } while (nextPage != null);
        }
        // Make an initial scan for the dependency locations in the Dependency report. 
        Set<String> mapped = new HashSet<>();
        VulnerabilityReport report = new VulnerabilityReport(auditSummary, items);
        CacheItem cache = new CacheItem(project, dr, report);
        for (ApplicationDependencyVulnerabilitySummary v : items) {
            List<Vulnerability> vulnerabilities = v.getVulnerabilities();
            if (!vulnerabilities.isEmpty()) {
                Dependency dependency = cache.getDependencyMap().get(v.getGav());
                if (dependency != null) {
                    mapped.add(v.getGav());
                }
            }
        }
        report.setMappedVulnerabilities(mapped);
        
        try {
            AuditCache.getInstance().cacheAuditResults(report);
        } catch (IOException ex) {
            LOG.log(Level.WARNING, "Could not cache audit results for knowledgebase {0}, compartment {1}, project {2}", new Object[] {
                auditSummary.getKnowledgeBaseId(), auditSummary.getCompartmentId(),
                projectName
            });
            LOG.log(Level.WARNING, "The exception was: ", ex);
        }
        return cache;
    }
    
    @Override
    public List<? extends Diagnostic> computeErrors(Context context) {
        List<Diagnostic> result = new ArrayList();
        Collection<CacheItem> items;
        
        synchronized (cache) {
            items = new ArrayList<>(cache.values());
        }
        for (CacheItem cacheItem : items) {
            List<Diagnostic> diagnostics = cacheItem.getDiagnosticsForFile(context.file());
            if (diagnostics != null) {
                result.addAll(cacheItem.getDiagnosticsForFile(context.file()));
            }
        }
        return result;
    }
}
