/*
 * This file is part of Dependency-Track.
 *
 * Licensed 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.
 *
 * SPDX-License-Identifier: Apache-2.0
 * Copyright (c) Steve Springett. All Rights Reserved.
 */
package org.dependencytrack.persistence;

import junitparams.JUnitParamsRunner;
import junitparams.Parameters;
import org.dependencytrack.PersistenceCapableTest;
import org.dependencytrack.model.VulnerabilityAlias;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;

import javax.jdo.Query;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;

import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.dependencytrack.persistence.VulnerabilityQueryManagerTest.SynchronizeVulnerabilityAliasTest.VulnerabilityAliasBuilder.anAlias;

@RunWith(Suite.class)
@SuiteClasses(VulnerabilityQueryManagerTest.SynchronizeVulnerabilityAliasTest.class)
public class VulnerabilityQueryManagerTest {

    @RunWith(JUnitParamsRunner.class)
    public static class SynchronizeVulnerabilityAliasTest extends PersistenceCapableTest {

        @Test
        @SuppressWarnings({"unchecked", "resource", "JUnitMalformedDeclaration"})
        @Parameters(method = "synchronizeVulnerabilityAliasTestParams")
        public void synchronizeVulnerabilityAliasTest(final String description,
                                                      final List<VulnerabilityAlias> reportedAliases,
                                                      final List<VulnerabilityAlias> expectedAliases) {
            for (final VulnerabilityAlias reportedAlias : reportedAliases) {
                qm.synchronizeVulnerabilityAlias(reportedAlias);
            }

            final var aliasAsserts = new ArrayList<Consumer<VulnerabilityAlias>>();
            for (final VulnerabilityAlias expectedAlias : expectedAliases) {
                aliasAsserts.add(alias -> {
                    assertThat(alias.getCveId()).isEqualTo(expectedAlias.getCveId());
                    assertThat(alias.getGhsaId()).isEqualTo(expectedAlias.getGhsaId());
                    assertThat(alias.getGsdId()).isEqualTo(expectedAlias.getGsdId());
                    assertThat(alias.getInternalId()).isEqualTo(expectedAlias.getInternalId());
                    assertThat(alias.getOsvId()).isEqualTo(expectedAlias.getOsvId());
                    assertThat(alias.getSnykId()).isEqualTo(expectedAlias.getSnykId());
                    assertThat(alias.getSonatypeId()).isEqualTo(expectedAlias.getSonatypeId());
                    assertThat(alias.getVulnDbId()).isEqualTo(expectedAlias.getVulnDbId());
                });
            }

            final Query<VulnerabilityAlias> query = qm.getPersistenceManager().newQuery(VulnerabilityAlias.class);
            final List<VulnerabilityAlias> aliases = query.executeList();

            assertThat(aliases).as(description).satisfiesExactlyInAnyOrder(aliasAsserts.toArray(new Consumer[0]));
        }

        @SuppressWarnings("unused")
        private Object[] synchronizeVulnerabilityAliasTestParams() {
            return new Object[]{
                    new Object[]{
                            "Aliases must not be merged when identifiers do not match",
                            // Reported
                            Arrays.asList(
                                    anAlias()
                                            .withGhsaId("GHSA-1000")
                                            .withSnykId("SNYK-2000")
                                            .build(),
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withSnykId("SNYK-1000")
                                            .build()),
                            // Expected
                            Arrays.asList(
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withSnykId("SNYK-1000")
                                            .build(),
                                    anAlias()
                                            .withGhsaId("GHSA-1000")
                                            .withSnykId("SNYK-2000")
                                            .build())
                    },
                    new Object[]{
                            "Must merge with best match among existing aliases",
                            // Reported
                            Arrays.asList(
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withOsvId("GO-1000")
                                            .build(),
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withOsvId("GO-2000")
                                            .build(),
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withOsvId("GO-2000")
                                            .withSnykId("SNYK-1000")
                                            .build()),
                            // Expected
                            Arrays.asList(
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withOsvId("GO-1000")
                                            .build(),
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withOsvId("GO-2000")
                                            .withSnykId("SNYK-1000")
                                            .build())
                    },
                    new Object[]{
                            "Aliases with disjoint sets of identifiers must not be merged",
                            // Reported
                            Arrays.asList(
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withSnykId("SNYK-1000")
                                            .build(),
                                    anAlias()
                                            .withGhsaId("GHSA-1000")
                                            .withOsvId("GO-1000")
                                            .build()),
                            // Expected
                            Arrays.asList(
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withSnykId("SNYK-1000")
                                            .build(),
                                    anAlias()
                                            .withGhsaId("GHSA-1000")
                                            .withOsvId("GO-1000")
                                            .build()),
                    },
                    new Object[]{
                            "Aliases with disjoint sets of identifiers must not be merged when arriving in reverse order",
                            // Reported
                            Arrays.asList(
                                    anAlias()
                                            .withGhsaId("GHSA-1000")
                                            .withOsvId("GO-1000")
                                            .build(),
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withSnykId("SNYK-1000")
                                            .build()),
                            // Expected
                            Arrays.asList(
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withSnykId("SNYK-1000")
                                            .build(),
                                    anAlias()
                                            .withGhsaId("GHSA-1000")
                                            .withOsvId("GO-1000")
                                            .build()),
                    },
                    new Object[]{
                            "Aliases with one matching identifier must be merged",
                            // Reported
                            Arrays.asList(
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withOsvId("GO-1000")
                                            .build(),
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withSnykId("SNYK-1000")
                                            .build()),
                            // Expected
                            singletonList(
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withSnykId("SNYK-1000")
                                            .withOsvId("GO-1000")
                                            .build())
                    },
                    new Object[]{
                            "Aliases with one matching identifier must be merged when arriving in reverse order",
                            // Reported
                            Arrays.asList(
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withSnykId("SNYK-1000")
                                            .build(),
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withOsvId("GO-1000")
                                            .build()),
                            // Expected
                            singletonList(
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withSnykId("SNYK-1000")
                                            .withOsvId("GO-1000")
                                            .build())
                    },
                    new Object[]{
                            "Aliases with one matching identifier and multiple additional identifiers must be merged",
                            // Reported
                            Arrays.asList(
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withSnykId("SNYK-1000")
                                            .build(),
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withGhsaId("GHSA-1000")
                                            .withOsvId("GO-1000")
                                            .build()),
                            // Expected
                            singletonList(
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withGhsaId("GHSA-1000")
                                            .withSnykId("SNYK-1000")
                                            .withOsvId("GO-1000")
                                            .build())
                    },
                    new Object[]{
                            "Aliases with one matching identifier and multiple additional identifiers must be merged when arriving in reverse order",
                            // Reported
                            Arrays.asList(
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withGhsaId("GHSA-1000")
                                            .withOsvId("GO-1000")
                                            .build(),
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withSnykId("SNYK-1000")
                                            .build()),
                            // Expected
                            singletonList(
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withGhsaId("GHSA-1000")
                                            .withSnykId("SNYK-1000")
                                            .withOsvId("GO-1000")
                                            .build())
                    },
                    new Object[]{
                            "Aliases with two matching identifiers must be merged",
                            // Reported
                            Arrays.asList(
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withGhsaId("GHSA-1000")
                                            .withSnykId("SNYK-1000")
                                            .build(),
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withGhsaId("GHSA-1000")
                                            .withOsvId("GO-1000")
                                            .build()),
                            // Expected
                            singletonList(
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withGhsaId("GHSA-1000")
                                            .withSnykId("SNYK-1000")
                                            .withOsvId("GO-1000")
                                            .build())
                    },
                    new Object[]{
                            "Aliases with two matching identifiers must be merged when arriving in reverse order",
                            // Reported
                            Arrays.asList(
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withGhsaId("GHSA-1000")
                                            .withOsvId("GO-1000")
                                            .build(),
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withGhsaId("GHSA-1000")
                                            .withSnykId("SNYK-1000")
                                            .build()),
                            // Expected
                            singletonList(
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withGhsaId("GHSA-1000")
                                            .withSnykId("SNYK-1000")
                                            .withOsvId("GO-1000")
                                            .build())
                    },
                    new Object[]{
                            "Aliases with one matching and one conflicting identifier must not be merged",
                            // Reported
                            Arrays.asList(
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withOsvId("GO-1000")
                                            .build(),
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withOsvId("GO-2000")
                                            .build()),
                            // Expected
                            Arrays.asList(
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withOsvId("GO-1000")
                                            .build(),
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withOsvId("GO-2000")
                                            .build())
                    },
                    new Object[]{
                            "In-the-wild example: GO-2022-0586",
                            // Reported
                            Arrays.asList(
                                    anAlias()
                                            .withCveId("CVE-2022-26945")
                                            .withOsvId("GO-2022-0586")
                                            .build(),
                                    anAlias()
                                            .withCveId("CVE-2022-30321")
                                            .withOsvId("GO-2022-0586")
                                            .build(),
                                    anAlias()
                                            .withCveId("CVE-2022-30322")
                                            .withOsvId("GO-2022-0586")
                                            .build(),
                                    anAlias()
                                            .withCveId("CVE-2022-30323")
                                            .withOsvId("GO-2022-0586")
                                            .build(),
                                    anAlias()
                                            .withGhsaId("GHSA-28r2-q6m8-9hpx")
                                            .withOsvId("GO-2022-0586")
                                            .build(),
                                    anAlias()
                                            .withGhsaId("GHSA-cjr4-fv6c-f3mv")
                                            .withOsvId("GO-2022-0586")
                                            .build(),
                                    anAlias()
                                            .withGhsaId("GHSA-fcgg-rvwg-jv58")
                                            .withOsvId("GO-2022-0586")
                                            .build(),
                                    anAlias()
                                            .withGhsaId("GHSA-x24g-9w7v-vprh")
                                            .withOsvId("GO-2022-0586")
                                            .build()),
                            // Expected
                            Arrays.asList(
                                    anAlias()
                                            .withCveId("CVE-2022-26945")
                                            .withOsvId("GO-2022-0586")
                                            .withGhsaId("GHSA-28r2-q6m8-9hpx")
                                            .build(),
                                    anAlias()
                                            .withCveId("CVE-2022-30321")
                                            .withGhsaId("GHSA-cjr4-fv6c-f3mv")
                                            .withOsvId("GO-2022-0586")
                                            .build(),
                                    anAlias()
                                            .withCveId("CVE-2022-30322")
                                            .withGhsaId("GHSA-fcgg-rvwg-jv58")
                                            .withOsvId("GO-2022-0586")
                                            .build(),
                                    anAlias()
                                            .withCveId("CVE-2022-30323")
                                            .withGhsaId("GHSA-x24g-9w7v-vprh")
                                            .withOsvId("GO-2022-0586")
                                            .build())
                    },
                    new Object[]{
                            "Aliases with identical identifiers must not create duplicates",
                            // Reported
                            Arrays.asList(
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withSnykId("SNYK-1000")
                                            .build(),
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withSnykId("SNYK-1000")
                                            .build()),
                            // Expected
                            singletonList(
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withSnykId("SNYK-1000")
                                            .build()),
                    },
                    new Object[]{
                            "In-the-wild example: SNYK-JAVA-ORGECLIPSEJETTY-2945452 and SNYK-JAVA-ORGECLIPSEJETTY-2945453",
                            // Reported
                            Arrays.asList(
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withSnykId("SNYK-1000")
                                            .build(),
                                    anAlias()
                                            .withGhsaId("GHSA-1000")
                                            .withSnykId("SNYK-1000")
                                            .build(),
                                    anAlias()
                                            .withGhsaId("GHSA-1000")
                                            .withSnykId("SNYK-2000")
                                            .build(),
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withSnykId("SNYK-2000")
                                            .build()),
                            // Expected
                            Arrays.asList(
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withGhsaId("GHSA-1000")
                                            .withSnykId("SNYK-1000")
                                            .build(),
                                    anAlias()
                                            .withCveId("CVE-1000")
                                            .withGhsaId("GHSA-1000")
                                            .withSnykId("SNYK-2000")
                                            .build())
                    },
                    // NOTE: This test is meant to act as documentation of the solution's behavior
                    // in case ambiguous data is being reported by vulnerability sources.
                    // In this case, one Snyk vulnerability refers to multiple CVEs and GHSAs.
                    // We have no way of knowing which CVEs and GHSAs alias each other.
                    // Synchronization may cause unrelated CVEs and GHSAs to be correlated.
                    new Object[]{
                            "In-the-wild example: SNYK-JAVA-COMFASTERXMLWOODSTOX-3091135",
                            // Reported
                            Arrays.asList(
                                    // Snyk reports various GHSAs and one CVE as aliases of SNYK-JAVA-COMFASTERXMLWOODSTOX-3091135.
                                    anAlias()
                                            .withGhsaId("GHSA-9fwf-46g9-45rx")
                                            .withSnykId("SNYK-JAVA-COMFASTERXMLWOODSTOX-3091135")
                                            .build(),
                                    anAlias()
                                            .withGhsaId("GHSA-3f7h-mf4q-vrm4")
                                            .withSnykId("SNYK-JAVA-COMFASTERXMLWOODSTOX-3091135")
                                            .build(),
                                    anAlias()
                                            .withGhsaId("GHSA-5hc5-c3m9-8vcj")
                                            .withSnykId("SNYK-JAVA-COMFASTERXMLWOODSTOX-3091135")
                                            .build(),
                                    anAlias()
                                            .withGhsaId("GHSA-fv22-xp26-mm9w")
                                            .withSnykId("SNYK-JAVA-COMFASTERXMLWOODSTOX-3091135")
                                            .build(),
                                    anAlias()
                                            .withGhsaId("GHSA-4rv7-wj6m-6c6r")
                                            .withSnykId("SNYK-JAVA-COMFASTERXMLWOODSTOX-3091135")
                                            .build(),
                                    anAlias()
                                            .withCveId("CVE-2022-40152")
                                            .withSnykId("SNYK-JAVA-COMFASTERXMLWOODSTOX-3091135")
                                            .build(),
                                    // GitHub Advisories and / or OSV report relationships between CVEs and GHSAs.
                                    anAlias()
                                            .withCveId("CVE-2022-40152")
                                            .withGhsaId("GHSA-3f7h-mf4q-vrm4")
                                            .build(),
                                    anAlias()
                                            .withCveId("CVE-2022-40154")
                                            .withGhsaId("GHSA-9fwf-46g9-45rx")
                                            .build(),
                                    anAlias()
                                            .withCveId("CVE-2022-40156")
                                            .withGhsaId("GHSA-4rv7-wj6m-6c6r")
                                            .build(),
                                    anAlias()
                                            .withCveId("CVE-2022-40153")
                                            .withGhsaId("GHSA-fv22-xp26-mm9w")
                                            .build(),
                                    anAlias()
                                            .withCveId("CVE-2022-40155")
                                            .withGhsaId("GHSA-5hc5-c3m9-8vcj")
                                            .build()),
                            // Expected (what it should be)
//                            Arrays.asList(
//                                    anAlias()
//                                            .withCveId("CVE-2022-40152")
//                                            .withGhsaId("GHSA-3f7h-mf4q-vrm4")
//                                            .withSnykId("SNYK-JAVA-COMFASTERXMLWOODSTOX-3091135")
//                                            .build(),
//                                    anAlias()
//                                            .withCveId("CVE-2022-40153")
//                                            .withGhsaId("GHSA-fv22-xp26-mm9w")
//                                            .withSnykId("SNYK-JAVA-COMFASTERXMLWOODSTOX-3091135")
//                                            .build(),
//                                    anAlias()
//                                            .withCveId("CVE-2022-40154")
//                                            .withGhsaId("GHSA-9fwf-46g9-45rx")
//                                            .withSnykId("SNYK-JAVA-COMFASTERXMLWOODSTOX-3091135")
//                                            .build(),
//                                    anAlias()
//                                            .withCveId("CVE-2022-40155")
//                                            .withGhsaId("GHSA-5hc5-c3m9-8vcj")
//                                            .withSnykId("SNYK-JAVA-COMFASTERXMLWOODSTOX-3091135")
//                                            .build(),
//                                    anAlias()
//                                            .withCveId("CVE-2022-40156")
//                                            .withGhsaId("GHSA-4rv7-wj6m-6c6r")
//                                            .withSnykId("SNYK-JAVA-COMFASTERXMLWOODSTOX-3091135")
//                                            .build())
                            // Expected (what it is)
                            Arrays.asList(
                                    anAlias()
                                            .withCveId("CVE-2022-40152")
                                            .withGhsaId("GHSA-9fwf-46g9-45rx") // MISMATCH: Should be GHSA-3f7h-mf4q-vrm4
                                            .withSnykId("SNYK-JAVA-COMFASTERXMLWOODSTOX-3091135")
                                            .build(),
                                    anAlias()
                                            .withCveId("CVE-2022-40152")
                                            .withGhsaId("GHSA-3f7h-mf4q-vrm4")
                                            .withSnykId("SNYK-JAVA-COMFASTERXMLWOODSTOX-3091135")
                                            .build(),
                                    anAlias()
                                            .withCveId("CVE-2022-40155")
                                            .withGhsaId("GHSA-5hc5-c3m9-8vcj")
                                            .withSnykId("SNYK-JAVA-COMFASTERXMLWOODSTOX-3091135")
                                            .build(),
                                    anAlias()
                                            .withCveId("CVE-2022-40153")
                                            .withGhsaId("GHSA-fv22-xp26-mm9w")
                                            .withSnykId("SNYK-JAVA-COMFASTERXMLWOODSTOX-3091135")
                                            .build(),
                                    anAlias()
                                            .withCveId("CVE-2022-40156")
                                            .withGhsaId("GHSA-4rv7-wj6m-6c6r")
                                            .withSnykId("SNYK-JAVA-COMFASTERXMLWOODSTOX-3091135")
                                            .build(),
                                    anAlias()
                                            .withCveId("CVE-2022-40154")
                                            .withGhsaId("GHSA-9fwf-46g9-45rx")
                                            // Should have SNYK-JAVA-COMFASTERXMLWOODSTOX-3091135
                                            .build())
                    },
                    new Object[]{
                            "In-the-wild example: SNYK-JAVA-IONETTY-10822*",
                            // Reported
                            Arrays.asList(
                                    // Multiple SNYK vulnerabilities refer to the same CVE and GHSA pair.
                                    anAlias()
                                            .withCveId("CVE-2021-21290")
                                            .withSnykId("SNYK-JAVA-IONETTY-1082234")
                                            .build(),
                                    anAlias()
                                            .withGhsaId("GHSA-5mcr-gq6c-3hq2")
                                            .withSnykId("SNYK-JAVA-IONETTY-1082234")
                                            .build(),
                                    anAlias()
                                            .withCveId("CVE-2021-21290")
                                            .withSnykId("SNYK-JAVA-IONETTY-1082235")
                                            .build(),
                                    anAlias()
                                            .withGhsaId("GHSA-5mcr-gq6c-3hq2")
                                            .withSnykId("SNYK-JAVA-IONETTY-1082235")
                                            .build(),
                                    anAlias()
                                            .withCveId("CVE-2021-21290")
                                            .withSnykId("SNYK-JAVA-IONETTY-1082236")
                                            .build(),
                                    anAlias()
                                            .withGhsaId("GHSA-5mcr-gq6c-3hq2")
                                            .withSnykId("SNYK-JAVA-IONETTY-1082236")
                                            .build(),
                                    anAlias()
                                            .withCveId("CVE-2021-21290")
                                            .withSnykId("SNYK-JAVA-IONETTY-1082238")
                                            .build(),
                                    anAlias()
                                            .withGhsaId("GHSA-5mcr-gq6c-3hq2")
                                            .withSnykId("SNYK-JAVA-IONETTY-1082238")
                                            .build(),
                                    // GitHub Advisories and / or OSV report the CVE and GHSA to be aliases.
                                    anAlias()
                                            .withCveId("CVE-2021-21290")
                                            .withGhsaId("GHSA-5mcr-gq6c-3hq2")
                                            .build()),
                            // Expected
                            Arrays.asList(
                                    anAlias()
                                            .withCveId("CVE-2021-21290")
                                            .withGhsaId("GHSA-5mcr-gq6c-3hq2")
                                            .withSnykId("SNYK-JAVA-IONETTY-1082234")
                                            .build(),
                                    anAlias()
                                            .withCveId("CVE-2021-21290")
                                            .withGhsaId("GHSA-5mcr-gq6c-3hq2")
                                            .withSnykId("SNYK-JAVA-IONETTY-1082235")
                                            .build(),
                                    anAlias()
                                            .withCveId("CVE-2021-21290")
                                            .withGhsaId("GHSA-5mcr-gq6c-3hq2")
                                            .withSnykId("SNYK-JAVA-IONETTY-1082236")
                                            .build(),
                                    anAlias()
                                            .withCveId("CVE-2021-21290")
                                            .withGhsaId("GHSA-5mcr-gq6c-3hq2")
                                            .withSnykId("SNYK-JAVA-IONETTY-1082238")
                                            .build())
                    }
            };
        }

        static class VulnerabilityAliasBuilder {
            private final VulnerabilityAlias alias = new VulnerabilityAlias();

            static VulnerabilityAliasBuilder anAlias() {
                return new VulnerabilityAliasBuilder();
            }

            VulnerabilityAlias build() {
                return alias;
            }

            VulnerabilityAliasBuilder withCveId(final String cveId) {
                this.alias.setCveId(cveId);
                return this;
            }

            VulnerabilityAliasBuilder withGhsaId(final String ghsaId) {
                this.alias.setGhsaId(ghsaId);
                return this;
            }

            VulnerabilityAliasBuilder withOsvId(final String osvId) {
                this.alias.setOsvId(osvId);
                return this;
            }

            VulnerabilityAliasBuilder withSnykId(final String snykId) {
                this.alias.setSnykId(snykId);
                return this;
            }
        }

    }

}