class SerecoFalsePositiveCodeScanStrategy {

    public boolean isFalsePositive(SerecoVulnerability vulnerability, FalsePositiveMetaData metaData) {
        notNull(vulnerability, " vulnerability may not be null");
        notNull(metaData, " metaData may not be null");

        if (metaData.getScanType() != ScanType.CODE_SCAN) {
            return false;
        }

        FalsePositiveCodeMetaData metaDataCode = metaData.getCode();
        if (metaDataCode == null) {
            LOG.error("Cannot check code vulnerability for false positives when meta data has no code parts!");
            return false;
        }

        /* ---------------------------------------------------- */
        /* -------------------CWE ID--------------------------- */
        /* ---------------------------------------------------- */

        /* for code scans we only use CWE as wellknown common identifier */
        Integer cweId = metaData.getCweId();
        if (cweId == null) {
            LOG.error("Cannot check code vulnerability for false positives when code meta data has no CWE id set!");
            return false;
        }

        SerecoClassification serecoClassification = vulnerability.getClassification();
        String serecoCWE = serecoClassification.getCwe();
        if (serecoCWE == null || serecoCWE.isEmpty()) {
            LOG.error("Code scan sereco vulnerability type:{} found without CWE! Cannot determin false positive! Classification was:{}",
                    vulnerability.getType(), serecoClassification);
            return false;
        }
        try {
            int serecoCWEint = Integer.parseInt(serecoCWE);
            if (cweId.intValue()!=serecoCWEint) {
                /* not same type of common vulnerability enumeration - so skip */
                return false;
            }

        } catch (NumberFormatException e) {
            LOG.error("Code scan sereco vulnerability type:{} found CWE:{} but not expected integer format!", vulnerability.getType(), serecoCWE);
            return false;

        }

        /* ------------------------------------------------------- */
        /* -------------------Location---------------------------- */
        /* ------------------------------------------------------- */
        SerecoCodeCallStackElement serecoFirstElement = vulnerability.getCode();
        if (serecoFirstElement == null) {
            /* strange - canot be investigated */
            LOG.warn("Cannot check code vulnerability for false positives when no first code element is found!");
            return false;
        }
        FalsePositiveCodePartMetaData start = metaDataCode.getStart();
        if (start == null) {
            LOG.warn("Cannot check code vulnerability for false positives when no start code meta data is found!");
            return false;
        }
        if (isLocationDifferent(start, serecoFirstElement)) {
            return false;
        }
        FalsePositiveCodePartMetaData end = metaDataCode.getEnd();
        SerecoCodeCallStackElement serecoLastElement = findLastElement(serecoFirstElement);
        if (isLocationDifferent(end, serecoLastElement)) {
            return false;
        }
        /* ------------------------------------------------------- */
        /* -------------------RELEVANT parts---------------------- */
        /* ------------------------------------------------------- */
        String relevant1 = start.getRelevantPart();
        String relevant2 = serecoFirstElement.getRelevantPart();

        if (relevant1 == null || relevant1.isEmpty()) {
            relevant1 = createRelevantReplacment(start);
        }
        if (relevant2 == null || relevant2.isEmpty()) {
            relevant2 = createRelevantReplacment(serecoFirstElement);
        }
        if (!relevant1.equals(relevant2)) {
            return false;
        }
        String relevant3 = "";
        String relevant4 = "";
        if (end != null) {
            relevant3 = end.getRelevantPart();
            if (relevant3 == null || relevant3.isEmpty()) {
                relevant3 = createRelevantReplacment(end);
            }
        }
        if (serecoLastElement != null) {
            relevant4 = serecoLastElement.getRelevantPart();
            if (relevant4 == null || relevant4.isEmpty()) {
                relevant4 = createRelevantReplacment(serecoLastElement);
            }
        }
        if (!relevant3.equals(relevant4)) {
            return false;
        }
        return true;
    }

}