1 package org.openecomp.sdc.onboarding.pmd;
3 import org.apache.maven.plugin.logging.Log;
4 import org.apache.maven.project.MavenProject;
7 import java.io.FileInputStream;
8 import java.io.FileOutputStream;
9 import java.io.IOException;
10 import java.io.InputStream;
11 import java.io.ObjectInputStream;
12 import java.io.ObjectOutputStream;
13 import java.io.OutputStream;
14 import java.io.UncheckedIOException;
15 import java.nio.file.Files;
16 import java.nio.file.StandardOpenOption;
17 import java.util.ArrayList;
18 import java.util.HashMap;
19 import java.util.List;
21 import java.util.Scanner;
23 import java.util.concurrent.atomic.AtomicInteger;
24 import java.util.regex.Matcher;
25 import java.util.regex.Pattern;
27 public class PMDHelperUtils {
29 private PMDHelperUtils() {
30 // default constructor. donot remove.
33 private static Map<String, String> pmdLink = new HashMap<>();
36 pmdLink.put("one", "errorprone");
37 pmdLink.put("ign", "design");
38 pmdLink.put("ing", "multithreading");
39 pmdLink.put("nce", "performance");
40 pmdLink.put("ity", "security");
41 pmdLink.put("yle", "codestyle");
42 pmdLink.put("ces", "bestpractices");
45 static String readInputStream(InputStream is) {
46 try (Scanner s = new Scanner(is).useDelimiter("\\A")) {
47 return s.hasNext() ? s.next() : "";
51 static File getStateFile(String moduleCoordinate, MavenProject proj, String filePath) {
52 return new File(getTopParentProject(moduleCoordinate, proj).getBasedir(),
53 filePath.substring(filePath.indexOf('/') + 1));
56 private static MavenProject getTopParentProject(String moduleCoordinate, MavenProject proj) {
57 if (getModuleCoordinate(proj).equals(moduleCoordinate) || proj.getParent() == null) {
60 return getTopParentProject(moduleCoordinate, proj.getParent());
64 private static String getModuleCoordinate(MavenProject project) {
65 return project.getGroupId() + ":" + project.getArtifactId();
68 private static <T> T readState(String fileName, Class<T> clazz) {
69 try (InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName);
70 ObjectInputStream ois = new ObjectInputStream(is)) {
71 return clazz.cast(ois.readObject());
72 } catch (Exception ioe) {
77 static <T> T readState(File file, Class<T> clazz) {
78 try (InputStream is = new FileInputStream(file); ObjectInputStream ois = new ObjectInputStream(is)) {
79 return clazz.cast(ois.readObject());
80 } catch (Exception ioe) {
85 static boolean evaluateCodeQuality(Map<String, List<Violation>> stats, Map<String, List<Violation>> current,
86 File file, Log logger) {
87 boolean qualityCheckPassed = true;
88 Map<String, String> table = new HashMap<>();
89 Set<String> classes = current.keySet();
91 for (String clazz : classes) {
92 List<Violation> orgViolation = stats.get(clazz) == null ? new ArrayList<>() : stats.get(clazz);
93 List<Violation> currViolation = current.get(clazz) == null ? new ArrayList<>() : current.get(clazz);
94 if (diffViolation(orgViolation, currViolation) > 0) {
95 Map<String, Integer> lDetails = diffCategory(orgViolation, currViolation);
96 for (String cat : lDetails.keySet()) {
97 String lineNo = getLineNumbers(currViolation, cat);
98 table.put(++counter + clazz, cat + ":" + lDetails.get(cat) + ":" + lineNo);
102 if (!table.isEmpty()) {
103 qualityCheckPassed = false;
105 Files.write(file.toPath(),
106 new Table(getTableHeaders(true), getContents(table, true)).drawTable().getBytes(),
107 StandardOpenOption.CREATE);
108 } catch (IOException e) {
109 throw new UncheckedIOException(e);
111 logger.error(new Table(getTableHeaders(false), getContents(table, false)).drawTable());
113 return qualityCheckPassed;
116 private static ArrayList<String> getTableHeaders(boolean addLink) {
117 ArrayList<String> list = new ArrayList<>();
118 list.add("Class Name");
119 list.add("Rule Category");
120 list.add("Rule Name");
122 list.add("Source Line No");
124 list.add("Help Link");
129 private static ArrayList<ArrayList<String>> getContents(Map<String, String> data, boolean addLink) {
130 ArrayList<ArrayList<String>> list = new ArrayList<>();
131 Pattern p = Pattern.compile("(.*):(.*):(.*):(.*)");
132 for (String s : data.keySet()) {
133 ArrayList<String> l = new ArrayList<>();
134 l.add(s.substring(s.indexOf("::") + 2));
135 Matcher m = p.matcher(data.get(s));
139 l.add(m.group(3) + " at least");
142 l.add("http://pmd.sourceforge.net/snapshot/pmd_rules_java_" + getLinkCategory(m.group(1)) + ".html#"
143 + m.group(2).toLowerCase());
151 private static String getLinkCategory(String cat) {
152 for (String category : pmdLink.keySet()) {
153 if (cat.contains(category)) {
154 return pmdLink.get(category);
160 private static int diffViolation(List<Violation> org, List<Violation> curr) {
162 if (org == null || org.isEmpty()) {
163 if (curr != null && !curr.isEmpty()) {
167 if (curr != null && !curr.isEmpty()) {
168 diff = curr.size() - org.size();
174 private static Map<String, Integer> diffCategory(List<Violation> org, List<Violation> curr) {
175 Map<String, AtomicInteger> currData = new HashMap<>();
176 Map<String, AtomicInteger> orgData = new HashMap<>();
177 countViolations(curr, currData);
178 countViolations(org, orgData);
179 Map<String, Integer> val = new HashMap<>();
180 for (String cat : currData.keySet()) {
181 if (orgData.get(cat) == null) {
182 val.put(cat, currData.get(cat).intValue());
183 } else if (currData.get(cat).intValue() > orgData.get(cat).intValue()) {
184 val.put(cat, currData.get(cat).intValue() - orgData.get(cat).intValue());
190 private static void countViolations(List<Violation> violations, Map<String, AtomicInteger> store){
191 for (Violation v : violations) {
192 if (store.get(v.getCategory() + ":" + v.getRule()) == null) {
193 store.put(v.getCategory() + ":" + v.getRule(), new AtomicInteger(1));
195 store.get(v.getCategory() + ":" + v.getRule()).incrementAndGet();
200 private static void processOriginalViolations(List<Violation> org){
203 private static String getLineNumbers(List<Violation> vList, String category) {
205 boolean firstOver = false;
206 for (Violation v : vList) {
207 if (category.equals(v.getCategory() + ":" + v.getRule())) {
218 static Map<String, List<Violation>> readCurrentPMDState(String fileName) {
219 Map<String, List<Violation>> val = readState(fileName, HashMap.class);
220 return val == null ? new HashMap<>() : val;
223 static Map<String, List<Violation>> readCurrentPMDState(File file) {
224 Map<String, List<Violation>> val = readState(file, HashMap.class);
225 return val == null ? new HashMap<>() : val;
228 static void writeCurrentPMDState(File file, Map<String, List<Violation>> data) {
229 try (OutputStream os = new FileOutputStream(file); ObjectOutputStream oos = new ObjectOutputStream(os)) {
230 oos.writeObject(data);
231 } catch (IOException ioe) {
232 throw new UncheckedIOException(ioe);
236 static boolean isReportEmpty(File reportFile){
238 return !reportFile.exists() || Files.readAllLines(reportFile.toPath()).size()<=1;
239 } catch (IOException e) {
240 throw new UncheckedIOException(e);