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 ? " \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) + " ", 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) + "" + elementType + ">";
else
return "<" + elementType + getFirstOrLastClass(isFirstOrLast) + getCellIdClickEvent(row, identifier) + " style=\"background-color:#" + getColorForText(text) + "\">" + text + "" + elementType + ">";
}
return "<" + elementType + getFirstOrLastClass(isFirstOrLast) + getCellIdClickEvent(row, identifier) + ">" + text + "" + elementType + ">";
}
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