All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.metaeffekt.artifact.analysis.report.CoverityReport Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2021-2024 the original author or authors.
 *
 * 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.
 */
package com.metaeffekt.artifact.analysis.report;

import com.metaeffekt.artifact.analysis.utils.FileUtils;
import com.metaeffekt.artifact.analysis.utils.SvgCreator;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.geom.AffineTransform;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.*;
import java.util.stream.IntStream;

import static org.apache.commons.lang.StringUtils.capitalize;

public class CoverityReport {

    private final Logger LOG = LoggerFactory.getLogger(getClass());

    private int offset, totalRows;
    private final HashMap columnIdentifiers = new HashMap<>();
    private final ArrayList sortedColumnIdentifiers = new ArrayList<>();
    private final ArrayList rows = new ArrayList<>();

    public CoverityReport(File file, File tempDir) throws IOException, JSONException {
        initializeColors();
        List lines = FileUtils.readLines(file, StandardCharsets.UTF_8);
        parseData(lines.get(0));
        labelDirectory = new File(tempDir, "labels").toString();
    }

    private void parseData(String json) throws JSONException {
        JSONObject mainObject = new JSONObject(json);
        JSONObject viewContentsV1 = mainObject.getJSONObject("viewContentsV1");
        offset = viewContentsV1.getInt("offset");
        totalRows = viewContentsV1.getInt("totalRows");
        JSONArray columns = viewContentsV1.getJSONArray("columns");
        JSONArray rows = viewContentsV1.getJSONArray("rows");

        for (int i = 0; i < columns.length(); i++) {
            JSONObject column = columns.getJSONObject(i);
            columnIdentifiers.put(column.getString("name"), column.getString("label"));
            sortedColumnIdentifiers.add(column.getString("name"));
        }

        for (int i = 0; i < rows.length(); i++) {
            JSONObject row = rows.getJSONObject(i);
            Row addRow = new Row(row);
            addRow.setReport(this);
            this.rows.add(addRow);
        }
    }

    public Row getRowWithCID(int cid) {
        String c = "" + cid;
        for (Row row : rows) {
            if (row.get("cid").equals(c)) return row;
        }
        return null;
    }

    public String getLabelForIdentifier(String identifier) {
        return columnIdentifiers.getOrDefault(identifier, null);
    }

    public String getIdentifierForlabel(String label) {
        if (columnIdentifiers.containsValue(label))
            for (Map.Entry entry : columnIdentifiers.entrySet()) {
                String i = entry.getKey();
                String l = entry.getValue();
                if (l.equals(label)) return i;
            }
        return null;
    }

    public int[] getRowCIDs() {
        int[] cids = new int[rows.size()];
        for (int i = 0; i < rows.size(); i++)
            cids[i] = rows.get(i).getCid();
        return cids;
    }

    public ArrayList getRows() {
        return rows;
    }

    public HashMap getColumnIdentifiers() {
        return columnIdentifiers;
    }

    public int getOffset() {
        return offset;
    }

    public int getTotalRows() {
        return totalRows;
    }

    public static class Row {

        private final Logger LOG = LoggerFactory.getLogger(getClass());

        private final HashMap entries = new HashMap<>();
        private CoverityReport report;
        private final int cid;

        public Row(JSONObject row) throws JSONException {
            JSONArray rowIdentifiers = row.names();
            for (int i = 0; i < rowIdentifiers.length(); i++) {
                Object value = row.get(rowIdentifiers.getString(i));
                entries.put(rowIdentifiers.getString(i), value.toString());
            }
            cid = Integer.parseInt(entries.getOrDefault("cid", "-1"));
        }

        public int getCid() {
            return cid;
        }

        public String get(String identifier) {
            return entries.getOrDefault(identifier, null);
        }

        public void setReport(CoverityReport report) {
            this.report = report;
        }

        public void print() {
            LOG.info("Row with cid: [{}]", entries.get("cid"));
            for (Map.Entry entry : entries.entrySet()) {
                String identifier = entry.getKey();
                String value = entry.getValue();
                LOG.info("\t[{}] = [{}]", identifier, value);
            }
        }

        public String getEntryAsString(String identifier) {
            String label = report.getLabelForIdentifier(identifier);
            String value = get(identifier);
            if (label == null || value == null) {
                return identifier + " not found";
            } else {
                return label + " = " + value;
            }
        }

        public String getJsObjectParameters() {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(cid).append(", '");
            for (Map.Entry entry : entries.entrySet()) {
                String identifier = entry.getKey();
                String value = entry.getValue();
                stringBuilder.append(identifier).append(":").append(value.replace("'", "\\'")).append(",");
            }
            stringBuilder.append("', '");
            for (Map.Entry entry : entries.entrySet()) {
                String identifier = entry.getKey();
                String value = entry.getValue();
                stringBuilder.append(identifier).append(":").append(value.replace("'", "\\'").toUpperCase()).append(",");
            }
            stringBuilder.append("'");
            return stringBuilder.toString();
        }
    }

    public void print() {
        LOG.info("General data:");
        LOG.info("offset = [{}]", offset);
        LOG.info("rows = [{}]", rows);
        LOG.info("\nPrinting all rows:");
        this.rows.forEach(Row::print);
    }

    public void generateHtmlReport(File outFile, File css, File tableSort, File upDownArrow, File replaceContents, File jsUpdateFile, File jsCreateFile) throws IOException {
        if (!asLabel && !new File(labelDirectory).exists()) {
            new File(labelDirectory).mkdirs();
        }
        ArrayList lines = new ArrayList<>();

        lines.add("\n" +
                "\n" +
                "\n" +
                "Coverity Report\n" +
                "\n" +
                "\n" +
                "\n" +
                "\n" +
                (allLabels != null ? "
" + allLabels + "
\n" : "") + "

Coverity Report

\n" + "Displaying " + rows.size() + " row" + (rows.size() == 1 ? "" : "s") + " and " + sortedColumnIdentifiers.size() + " column" + (sortedColumnIdentifiers.size() == 1 ? "" : "s") + ". Click on column header to sort alphabetically.\n"); lines.add("\n"); lines.add("\n"); for (int i = 0, sortedColumnIdentifiersSize = sortedColumnIdentifiers.size(); i < sortedColumnIdentifiersSize; i++) { String identifier = sortedColumnIdentifiers.get(i); int isFirstOrLast = 0; if (i == 0) isFirstOrLast = 1; if (i == sortedColumnIdentifiersSize - 1) isFirstOrLast = 2; if (asOneFile) lines.add(createHTMLtableCell(getLabelForIdentifier(identifier) + " " + loadFile(upDownArrow.toString()), TH, isFirstOrLast, null, null)); else lines.add(createHTMLtableCell(getLabelForIdentifier(identifier) + " \"Sort\"", TH, isFirstOrLast, null, null)); } lines.add("\n\n\n"); for (Row row : rows) { lines.add(""); for (String identifier : sortedColumnIdentifiers) { lines.add(createHTMLtableCell(row.get(identifier), TD, -1, row, identifier)); } lines.add(""); } lines.add("\n" + "
\n"); lines.add(createSvgPieCharts(jsUpdateFile, jsCreateFile)); lines.add("\n" + ""); FileUtils.writeLines(outFile, FileUtils.ENCODING_UTF_8, lines); } private final static HashMap CELL_TEXT_TO_COLORS = new HashMap<>(); private final static HashMap COLOR_NAME_TO_HEX = new HashMap<>(); private boolean asLabel = true, asOneFile = true; private String labelDirectory; private void initializeColors() { if (CELL_TEXT_TO_COLORS.size() > 0 && COLOR_NAME_TO_HEX.size() > 0) return; CELL_TEXT_TO_COLORS.put("none", "gray"); CELL_TEXT_TO_COLORS.put("other", "gray"); CELL_TEXT_TO_COLORS.put("untargeted", "gray"); CELL_TEXT_TO_COLORS.put("undecided", "gray"); CELL_TEXT_TO_COLORS.put("unspecified", "gray"); CELL_TEXT_TO_COLORS.put("unclassified", "gray"); CELL_TEXT_TO_COLORS.put("unassigned", "gray"); CELL_TEXT_TO_COLORS.put("medium", "orange"); CELL_TEXT_TO_COLORS.put("moderate", "orange"); CELL_TEXT_TO_COLORS.put("high", "red"); CELL_TEXT_TO_COLORS.put("fix required", "red"); CELL_TEXT_TO_COLORS.put("low", "yellow"); CELL_TEXT_TO_COLORS.put("pending", "yellow"); CELL_TEXT_TO_COLORS.put("new", "light_blue"); CELL_TEXT_TO_COLORS.put("triaged", "green"); CELL_TEXT_TO_COLORS.put("true", "green"); CELL_TEXT_TO_COLORS.put("false", "blue"); CELL_TEXT_TO_COLORS.put("c++", "yellow"); CELL_TEXT_TO_COLORS.put("c", "orange"); CELL_TEXT_TO_COLORS.put("java", "light_blue"); CELL_TEXT_TO_COLORS.put("javascript", "blue"); CELL_TEXT_TO_COLORS.put("php", "green"); CELL_TEXT_TO_COLORS.put("python", "yellow"); CELL_TEXT_TO_COLORS.put("ruby", "red"); CELL_TEXT_TO_COLORS.put("various", "gray"); CELL_TEXT_TO_COLORS.put("quality", "blue"); CELL_TEXT_TO_COLORS.put("cat i", "red"); CELL_TEXT_TO_COLORS.put("cat ii", "orange"); CELL_TEXT_TO_COLORS.put("cat iii", "green"); CELL_TEXT_TO_COLORS.put("m1", "orange"); CELL_TEXT_TO_COLORS.put("m2", "orange"); CELL_TEXT_TO_COLORS.put("m3", "orange"); CELL_TEXT_TO_COLORS.put("m4", "orange"); CELL_TEXT_TO_COLORS.put("m5", "orange"); CELL_TEXT_TO_COLORS.put("m6", "orange"); CELL_TEXT_TO_COLORS.put("m7", "orange"); CELL_TEXT_TO_COLORS.put("m8", "orange"); CELL_TEXT_TO_COLORS.put("m9", "orange"); CELL_TEXT_TO_COLORS.put("m10", "orange"); CELL_TEXT_TO_COLORS.put("a1", "orange"); CELL_TEXT_TO_COLORS.put("a2", "orange"); CELL_TEXT_TO_COLORS.put("a3", "orange"); CELL_TEXT_TO_COLORS.put("a4", "orange"); CELL_TEXT_TO_COLORS.put("a5", "orange"); CELL_TEXT_TO_COLORS.put("a6", "orange"); CELL_TEXT_TO_COLORS.put("a7", "orange"); CELL_TEXT_TO_COLORS.put("a8", "orange"); CELL_TEXT_TO_COLORS.put("a9", "orange"); CELL_TEXT_TO_COLORS.put("a10", "orange"); CELL_TEXT_TO_COLORS.put("absent", "orange"); CELL_TEXT_TO_COLORS.put("admin", "green"); if (!asLabel) { COLOR_NAME_TO_HEX.put("gray", "dbdbdb"); COLOR_NAME_TO_HEX.put("orange", "ffbd24"); COLOR_NAME_TO_HEX.put("red", "ff2e2e"); COLOR_NAME_TO_HEX.put("yellow", "fffc63"); COLOR_NAME_TO_HEX.put("light_blue", "d9fdff"); COLOR_NAME_TO_HEX.put("green", "8affad"); COLOR_NAME_TO_HEX.put("light_green", "AFE35B"); COLOR_NAME_TO_HEX.put("dark_green", "5FB97F"); COLOR_NAME_TO_HEX.put("blue", "8A9FFF"); } else { COLOR_NAME_TO_HEX.put("gray", "535353"); COLOR_NAME_TO_HEX.put("orange", "DC8F00"); COLOR_NAME_TO_HEX.put("red", "E30A0A"); COLOR_NAME_TO_HEX.put("yellow", "F5DE00"); COLOR_NAME_TO_HEX.put("light_blue", "00ADB7"); COLOR_NAME_TO_HEX.put("green", "00E650"); COLOR_NAME_TO_HEX.put("light_green", "80CF00"); COLOR_NAME_TO_HEX.put("dark_green", "00B840"); COLOR_NAME_TO_HEX.put("blue", "0047F5"); } if (asLabel && asOneFile) for (String text : CELL_TEXT_TO_COLORS.keySet()) { allLabels += generateTextLabel(text, getColorForText(text), new Color(0, 0, 0, 0), getColorForText(text), 2, 17); } } private String allLabels = null; private String getColorForText(String text) { if (CELL_TEXT_TO_COLORS.containsKey(text)) return COLOR_NAME_TO_HEX.get(CELL_TEXT_TO_COLORS.get(text.toLowerCase())); Random rand = new Random(text.hashCode()); int red = rand.nextInt(255); int green = rand.nextInt(255); int blue = rand.nextInt(255); Color c = makeMoreSaturated(red, green, blue, 0.4); return String.format("%02x%02x%02x", c.getRed(), c.getGreen(), c.getBlue()); } private Color makeMoreSaturated(int r, int g, int b, double factor) { if (r < 127) r = (int) Math.max(r * (1 - factor), 0); else r = (int) Math.min(r * (1 + factor), 255); if (g < 127) g = (int) Math.max(g * (1 - factor), 0); else g = (int) Math.min(g * (1 + factor), 255); if (b < 127) b = (int) Math.max(b * (1 - factor), 0); else b = (int) Math.min(b * (1 + factor), 255); if (r + g + b > 600) { if (r < g && r < b) r = (int) Math.max(r * (1 - factor), 0); else if (g < r && g < b) g = (int) Math.max(g * (1 - factor), 0); else b = (int) Math.max(b * (1 - factor), 0); } return new Color(r, g, b); } private final static String TD = "td"; private final static String TH = "th"; private String createHTMLtableCell(String text, String elementType, int isFirstOrLast, Row row, String identifier) { if (CELL_TEXT_TO_COLORS.containsKey(text.toLowerCase())) { if (asLabel) return "<" + elementType + getFirstOrLastClass(isFirstOrLast) + getCellIdClickEvent(row, identifier) + ">" + text + "" + generateTextLabel(text, getColorForText(text), new Color(0, 0, 0, 0), getColorForText(text), 2, 17) + ""; else return "<" + elementType + getFirstOrLastClass(isFirstOrLast) + getCellIdClickEvent(row, identifier) + " style=\"background-color:#" + getColorForText(text) + "\">" + text + ""; } return "<" + elementType + getFirstOrLastClass(isFirstOrLast) + getCellIdClickEvent(row, identifier) + ">" + text + ""; } private String getCellIdClickEvent(Row row, String identifier) { if (row == null) return ""; //return " id=\"" + row.getCid() + "_" + identifier + "\" onClick=\"clicked(this.id)\""; return " id=\"" + row.getCid() + "_" + identifier + "\""; } private String getFirstOrLastClass(int isFirstOrLast) { if (isFirstOrLast <= 0) return ""; else if (isFirstOrLast == 1) return " class=\"firstTitle\""; else if (isFirstOrLast == 2) return " class=\"lastTitle\""; return ""; } private ArrayList labelGenerated = new ArrayList<>(); private String generateTextLabel(String text, String textColor, Color backgroundColor, String borderColor, int borderSize, int size) { int offsetX = 10 + borderSize, offsetY = borderSize; AffineTransform affinetransform = new AffineTransform(); FontRenderContext frc = new FontRenderContext(affinetransform, true, true); Font font = new Font("Arial", Font.PLAIN, size); int textwidth = (int) (font.getStringBounds(text, frc).getWidth()); int textheight = (int) (font.getStringBounds(text, frc).getHeight()); if (labelGenerated.contains(text.toLowerCase())) { return "" + "" + "" + ""; } SvgCreator svg = new SvgCreator(); svg.setViewBox(0, 0, textwidth + (offsetX * 2), textheight + (offsetY * 2)); if (asOneFile) svg.setSvgParameters("height=\"" + (size + 4) + "px\""); int random = getRandomNumber(0, 134217727); svg.createFont("font" + random, size + "px Arial, sans-serif", textColor); svg.createRoundedRectangle("textFrame" + text.toLowerCase(), borderSize, borderSize, textwidth + (offsetX * 2) - (borderSize * 2), textheight + (offsetY * 2) - (borderSize * 2), (textheight + (offsetY * 2)) / 2, (textheight + (offsetY * 2))); if (backgroundColor.getAlpha() == 0) svg.setShapeFillOpacity("textFrame" + text.toLowerCase(), 0); else svg.setShapeFillColor("textFrame" + text.toLowerCase(), toHex(backgroundColor)); svg.setShapeBorder("textFrame" + text.toLowerCase(), borderSize, borderColor); svg.createText("text" + text.toLowerCase(), (textwidth + (offsetX * 2)) / 2, (textheight + (offsetY * 2)) / 2, text, "font" + random); svg.setShapeParameter("text" + text.toLowerCase(), "text-anchor=middle", "alignment-baseline=central"); if (!asOneFile) { try { svg.generate(new File(labelDirectory + text.toLowerCase() + ".svg")); } catch (IOException e) { LOG.error("Unable to write SVG file [" + labelDirectory + text.toLowerCase() + ".svg]", e); } if (new File(labelDirectory + text.toLowerCase() + ".svg").exists()) { return ""; } } labelGenerated.add(text.toLowerCase()); return arrayListToString(svg.generateSVG()); } private static String toHex(Color c) { return String.format("#%02x%02x%02x", c.getRed(), c.getGreen(), c.getBlue()); } private static int getRandomNumber(int min, int max) { return (int) ((Math.random() * (max - min)) + min); } private static String arrayListToString(ArrayList list) { StringBuilder sb = new StringBuilder(); for (Object o : list) if (list.size() != 0) sb.append(o.toString()); else sb.append("\n").append(o.toString()); return sb.toString(); } private String loadFile(String file) { try { List input = FileUtils.readLines(new File(file), StandardCharsets.UTF_8); StringBuilder sb = new StringBuilder(); boolean isComment = false; for (String s : input) { if (s.trim().startsWith("//")) { if (s.trim().equals("//CREATE CID ROWS")) s = getJsRowEntries(); else continue; } if (s.trim().startsWith("/*")) isComment = true; if (isComment) { if (s.trim().startsWith("*/") || s.endsWith("*/")) isComment = false; continue; } if (sb.length() > 0) sb.append("\n"); sb.append(s); } return sb.toString(); } catch (IOException e) { throw new RuntimeException("Unable to load file string from file [" + file + "]", e); } } private ArrayList loadFileAsList(String file) { try { List input = FileUtils.readLines(new File(file), StandardCharsets.UTF_8); return new ArrayList<>(input); } catch (IOException e) { throw new RuntimeException("Unable to load file from [" + file + "]", e); } } private String getJsRowEntries() { StringBuilder sb = new StringBuilder(); for (int i = 0; i < rows.size(); i++) { if (sb.length() > 0) sb.append("\n").append("rows[").append(i).append("] = new Row(").append(rows.get(i).getJsObjectParameters()).append(");"); else sb.append("rows[").append(i).append("] = new Row(").append(rows.get(i).getJsObjectParameters()).append(");"); } return sb.toString(); } private String createSvgPieCharts(File jsUpdateFile, File jsCreateFile) { StringBuilder output = new StringBuilder(); ArrayList createChartsFor = new ArrayList<>(); createChartsFor.add(STATUS); createChartsFor.add(DISPLAY_IMPACT); createChartsFor.add(CWE); HashMap identifiers = getColumnIdentifiers(); output.append("\n"); output.append("\n"); for (Map.Entry identifier : identifiers.entrySet()) { String ident = identifier.getKey(); output.append("
").append("
"); ArrayList rowValueCount = new ArrayList<>(); ArrayList rowValueText = new ArrayList<>(); ArrayList rowValueColor = new ArrayList<>(); for (Row row : rows) { String value = row.get(ident).toLowerCase(); if (rowValueText.contains(value)) { int index = rowValueText.indexOf(value); rowValueCount.set(index, rowValueCount.get(index) + 1); } else { rowValueText.add(value); rowValueCount.add(1.0); rowValueColor.add("#" + getColorForText(value)); } } output.append(makePieChartFromAbsoluteData(rowValueCount.toArray(new Double[0]), rowValueColor.toArray(new String[0]), rowValueText.toArray(new String[0]), 400, jsCreateFile)); output.append("
"); } output.append("








"); return output.toString(); } private String makePieChartFromAbsoluteData(Double[] data, String[] colors, String[] labels, int size, File jsCreateFile) { double total = Arrays.stream(data).mapToDouble(dat -> dat).sum(); IntStream.range(0, data.length).forEach(i -> data[i] = (100 / total) * data[i]); return makePieChart(data, colors, labels, size, jsCreateFile); } private String makePieChart(Double[] data, String[] colors, String[] labels, int size, File jsCreateFile) { ArrayList input = loadFileAsList(jsCreateFile.toString()); int randomId = getRandomNumber(0, 9999999); String[] makeUniqueID = new String[]{"#pie", "svgEl", "slices", "cumulativePercent"}; for (int i = 0; i < input.size(); i++) { for (String s : makeUniqueID) { if (input.get(i).contains(s)) { input.set(i, input.get(i).replace(s, s + randomId)); } } if (input.get(i).trim().equals("//CREATE PIE ELEMENTS")) { StringBuilder elements = new StringBuilder(); for (int j = 0, dataLength = data.length; j < dataLength; j++) { double dat = data[j]; String color = colors[j]; String label = labels[j]; elements.append("{ percent: ").append(dat / 100).append(", color: '").append(color).append("', hoverText: '").append(capitalize(label)).append("' },"); } input.set(i, elements.toString()); } } StringBuilder returnValue = new StringBuilder(); returnValue.append(""); for (String s : input) returnValue.append("\n").append(s); return returnValue.toString(); } //identifiers public static final String CID = "cid"; public static final String DISPLAY_TYPE = "displayType"; public static final String DISPLAY_IMPACT = "displayImpact"; public static final String STATUS = "status"; public static final String FIRST_DETECTED = "firstDetected"; public static final String OWNER = "owner"; public static final String CLASSIFICATION = "classification"; public static final String SEVERITY = "severity"; public static final String ACTION = "action"; public static final String DISPLAY_COMPONENT = "displayComponent"; public static final String DISPLAY_CATEGORY = "displayCategory"; public static final String DISPLAY_FILE = "displayFile"; public static final String DISPLAY_FUNCTION = "displayFunction"; public static final String CWE = "cwe"; public static final String EXTERNAL_REFERENCE = "externalReference"; public static final String FIX_TARGET = "fixTarget"; public static final String LAST_TRIAGE_COMMENT = "lastTriageComment"; public static final String LAST_TRIAGED = "lastTriaged"; public static final String RULE_STRENGTH = "ruleStrength"; public static final String CHECKER = "checker"; public static final String DISPLAY_COMPARISON = "displayComparison"; public static final String OCCURRENCE_COUNT = "occurrenceCount"; public static final String FIRST_SNAPSHOT_ID = "firstSnapshotId"; public static final String FIRST_SNAPSHOT_DATE = "firstSnapshotDate"; public static final String FIRST_SNAPSHOT_DESCRIPTION = "firstSnapshotDescription"; public static final String FIRST_SNAPSHOT_STREAM = "firstSnapshotStream"; public static final String FIRST_SNAPSHOT_TARGET = "firstSnapshotTarget"; public static final String FIRST_SNAPSHOT_VERSION = "firstSnapshotVersion"; public static final String FUNCTION_MERGE_NAME = "functionMergeName"; public static final String DISPLAY_ISSUE_KIND = "displayIssueKind"; public static final String FILE_LANGUAGE = "fileLanguage"; public static final String LAST_DETECTED_ID = "lastDetectedId"; public static final String LAST_DETECTED = "lastDetected"; public static final String LAST_DETECTED_DESCRIPTION = "lastDetectedDescription"; public static final String LAST_DETECTED_STREAM = "lastDetectedStream"; public static final String LAST_DETECTED_TARGET = "lastDetectedTarget"; public static final String LAST_DETECTED_VERSION = "lastDetectedVersion"; public static final String LAST_TRIAGED_USER = "lastTriagedUser"; public static final String LEGACY = "legacy"; public static final String LINE_NUMBER = "lineNumber"; public static final String MERGE_EXTRA = "mergeExtra"; public static final String MERGE_KEY = "mergeKey"; public static final String OWNER_FULL_NAME = "ownerFullName"; public static final String SCORE = "score"; public static final String SA_10001 = "SA_10001"; public static final String SA_10002 = "SA_10002"; public static final String SA_10003 = "SA_10003"; public static final String SA_10004 = "SA_10004"; public static final String SA_10005 = "SA_10005"; public static final String SA_10006 = "SA_10006"; public static final String SA_10007 = "SA_10007"; public static final String SA_10008 = "SA_10008"; public static final String SA_10009 = "SA_10009"; public static final String SA_10010 = "SA_10010"; public static final String SA_10011 = "SA_10011"; }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy