Onboarding build optimization incl Qual Control

Sonar fixes, incremental build enhancements and Quality control mechanism integration.

Change-Id: I118d7fc0cc50c1eddb94137310c00afaaa3aaffb
Issue-ID: SDC-1189
Signed-off-by: GAUTAMS <gautams@amdocs.com>
diff --git a/openecomp-be/tools/pmd-helper-plugin/pom.xml b/openecomp-be/tools/pmd-helper-plugin/pom.xml
new file mode 100644
index 0000000..75ab1f8
--- /dev/null
+++ b/openecomp-be/tools/pmd-helper-plugin/pom.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>org.openecomp.sdc.onboarding</groupId>
+    <artifactId>pmd-helper-plugin</artifactId>
+    <packaging>maven-plugin</packaging>
+
+    <parent>
+        <artifactId>sdc-onboarding</artifactId>
+        <groupId>org.openecomp.sdc</groupId>
+        <version>1.2.0-SNAPSHOT</version>
+        <relativePath>../../../onboarding</relativePath>
+    </parent>
+    <properties>
+        <skipPMD>true</skipPMD>
+        <classes>classes/**/*.class</classes>
+        <mavenStatus>maven-status/**</mavenStatus>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.maven</groupId>
+            <artifactId>maven-core</artifactId>
+            <version>${maven-core.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.maven.plugin-tools</groupId>
+            <artifactId>maven-plugin-annotations</artifactId>
+            <version>${maven-plugin-annotations.version}</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-plugin-plugin</artifactId>
+                <version>${maven-plugin-plugin.version}</version>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
\ No newline at end of file
diff --git a/openecomp-be/tools/pmd-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/pmd/InitializationHelperMojo.java b/openecomp-be/tools/pmd-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/pmd/InitializationHelperMojo.java
new file mode 100644
index 0000000..4102a1b
--- /dev/null
+++ b/openecomp-be/tools/pmd-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/pmd/InitializationHelperMojo.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright © 2018 European Support Limited
+ *
+ * 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 a "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 org.openecomp.sdc.onboarding.pmd;
+
+import static org.openecomp.sdc.onboarding.pmd.PMDHelperUtils.getStateFile;
+import static org.openecomp.sdc.onboarding.pmd.PMDHelperUtils.readCurrentPMDState;
+import static org.openecomp.sdc.onboarding.pmd.PMDHelperUtils.readInputStream;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.util.List;
+import java.util.Map;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.plugins.annotations.ResolutionScope;
+import org.apache.maven.project.MavenProject;
+
+@Mojo(name = "init-pmd-helper", threadSafe = true, defaultPhase = LifecyclePhase.PREPARE_PACKAGE,
+        requiresDependencyResolution = ResolutionScope.NONE)
+public class InitializationHelperMojo extends AbstractMojo {
+
+    private static final String SKIP_PMD = "skipPMD";
+
+    @Parameter(defaultValue = "${project}", readonly = true)
+    private MavenProject project;
+    @Parameter(defaultValue = "${project.artifact.groupId}:${project.artifact.artifactId}")
+    private String moduleCoordinates;
+    @Parameter
+    private File pmdTargetLocation;
+    @Parameter
+    private File pmdReportFile;
+    @Parameter
+    private String persistingModuleCoordinates;
+    @Parameter
+    private File pmdStateFile;
+    @Parameter
+    private String pmdCurrentStateFilePath;
+    @Parameter
+    private String excludePackaging;
+
+    static {
+        PMDState.setHistoricState(readCurrentPMDState("pmd.dat"));
+    }
+
+    public void execute() throws MojoExecutionException, MojoFailureException {
+        if (project.getPackaging().equals(excludePackaging)) {
+            return;
+        }
+        if (moduleCoordinates.equals(persistingModuleCoordinates)) {
+            pmdStateFile.getParentFile().mkdirs();
+            try (OutputStream os = new FileOutputStream(pmdStateFile);
+                 ObjectOutputStream oos = new ObjectOutputStream(os)) {
+                File f = getStateFile(pmdCurrentStateFilePath.substring(0, pmdCurrentStateFilePath.indexOf('/')),
+                        project, pmdCurrentStateFilePath);
+                Map<String, List<Violation>> data = readCurrentPMDState(f);
+                if (PMDState.getHistoricState() != null) {
+                    PMDState.getHistoricState().putAll(data);
+                    oos.writeObject(PMDState.getHistoricState());
+                } else {
+                    oos.writeObject(data);
+                }
+                if (Paths.get(f.getParentFile().getAbsolutePath(), "compileState.dat").toFile().exists()) {
+                    Files.copy(Paths.get(f.getParentFile().getAbsolutePath(), "compileState.dat"),
+                            Paths.get(pmdStateFile.getParentFile().getAbsolutePath(), "compile.dat"),
+                            StandardCopyOption.REPLACE_EXISTING);
+                }
+            } catch (IOException e) {
+                throw new UncheckedIOException(e);
+            }
+            return;
+        }
+        if (project.getProperties().containsKey(SKIP_PMD) && Boolean.TRUE.equals(Boolean.valueOf(
+                project.getProperties().getProperty(SKIP_PMD)))) {
+            return;
+        }
+        pmdTargetLocation.getParentFile().mkdirs();
+        try (InputStream is = this.getClass().getResourceAsStream("/pmd-empty.xml");
+             OutputStream os = new FileOutputStream(pmdTargetLocation)) {
+            String text = readInputStream(is);
+            os.write(text.getBytes());
+        } catch (IOException ioe) {
+            throw new UncheckedIOException(ioe);
+        }
+    }
+
+}
diff --git a/openecomp-be/tools/pmd-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/pmd/PMDHelperUtils.java b/openecomp-be/tools/pmd-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/pmd/PMDHelperUtils.java
new file mode 100644
index 0000000..38dde12
--- /dev/null
+++ b/openecomp-be/tools/pmd-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/pmd/PMDHelperUtils.java
@@ -0,0 +1,242 @@
+package org.openecomp.sdc.onboarding.pmd;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.nio.file.StandardOpenOption;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Scanner;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.apache.maven.plugin.logging.Log;
+import org.apache.maven.project.MavenProject;
+
+public class PMDHelperUtils {
+
+    private PMDHelperUtils() {
+        // default constructor. donot remove.
+    }
+
+    private static Map<String, String> pmdLink = new HashMap<>();
+
+    static {
+        pmdLink.put("one", "errorprone");
+        pmdLink.put("ign", "design");
+        pmdLink.put("ing", "multithreading");
+        pmdLink.put("nce", "performance");
+        pmdLink.put("ity", "security");
+        pmdLink.put("yle", "codestyle");
+        pmdLink.put("ces", "bestpractices");
+    }
+
+    static String readInputStream(InputStream is) {
+        try (Scanner s = new Scanner(is).useDelimiter("\\A")) {
+            return s.hasNext() ? s.next() : "";
+        }
+    }
+
+    static File getStateFile(String moduleCoordinate, MavenProject proj, String filePath) {
+        return new File(getTopParentProject(moduleCoordinate, proj).getBasedir(),
+                filePath.substring(filePath.indexOf('/') + 1));
+    }
+
+    private static MavenProject getTopParentProject(String moduleCoordinate, MavenProject proj) {
+        if (getModuleCoordinate(proj).equals(moduleCoordinate) || proj.getParent() == null) {
+            return proj;
+        } else {
+            return getTopParentProject(moduleCoordinate, proj.getParent());
+        }
+    }
+
+    private static String getModuleCoordinate(MavenProject project) {
+        return project.getGroupId() + ":" + project.getArtifactId();
+    }
+
+    private static <T> T readState(String fileName, Class<T> clazz) {
+        try (InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName);
+             ObjectInputStream ois = new ObjectInputStream(is)) {
+            return clazz.cast(ois.readObject());
+        } catch (Exception ioe) {
+            return null;
+        }
+    }
+
+    static <T> T readState(File file, Class<T> clazz) {
+        try (InputStream is = new FileInputStream(file); ObjectInputStream ois = new ObjectInputStream(is)) {
+            return clazz.cast(ois.readObject());
+        } catch (Exception ioe) {
+            return null;
+        }
+    }
+
+    static boolean evaluateCodeQuality(Map<String, List<Violation>> stats, Map<String, List<Violation>> current,
+            File file, Log logger) {
+        boolean qualityCheckPassed = true;
+        Map<String, String> table = new HashMap<>();
+        Set<String> classes = current.keySet();
+        int counter = 0;
+        for (String clazz : classes) {
+            List<Violation> orgViolation = stats.get(clazz) == null ? new ArrayList<>() : stats.get(clazz);
+            List<Violation> currViolation = current.get(clazz) == null ? new ArrayList<>() : current.get(clazz);
+            if (diffViolation(orgViolation, currViolation) > 0) {
+                Map<String, Integer> lDetails = diffCategory(orgViolation, currViolation);
+                for (String cat : lDetails.keySet()) {
+                    String lineNo = getLineNumbers(currViolation, cat);
+                    table.put(++counter + clazz, cat + ":" + lDetails.get(cat) + ":" + lineNo);
+                }
+            }
+        }
+        if (!table.isEmpty()) {
+            qualityCheckPassed = false;
+            try {
+                Files.write(file.toPath(),
+                        new Table(getTableHeaders(true), getContents(table, true)).drawTable().getBytes(),
+                        StandardOpenOption.CREATE);
+            } catch (IOException e) {
+                throw new UncheckedIOException(e);
+            }
+            logger.error(new Table(getTableHeaders(false), getContents(table, false)).drawTable());
+        }
+        return qualityCheckPassed;
+    }
+
+    private static ArrayList<String> getTableHeaders(boolean addLink) {
+        ArrayList<String> list = new ArrayList<>();
+        list.add("Class Name");
+        list.add("Rule Category");
+        list.add("Rule Name");
+        list.add("Fix");
+        list.add("Source Line No");
+        if (addLink) {
+            list.add("Help Link");
+        }
+        return list;
+    }
+
+    private static ArrayList<ArrayList<String>> getContents(Map<String, String> data, boolean addLink) {
+        ArrayList<ArrayList<String>> list = new ArrayList<>();
+        Pattern p = Pattern.compile("(.*):(.*):(.*):(.*)");
+        for (String s : data.keySet()) {
+            ArrayList<String> l = new ArrayList<>();
+            l.add(s.substring(s.indexOf("::") + 2));
+            Matcher m = p.matcher(data.get(s));
+            if (m.find()) {
+                l.add(m.group(1));
+                l.add(m.group(2));
+                l.add(m.group(3) + " at least");
+                l.add(m.group(4));
+                if (addLink) {
+                    l.add("http://pmd.sourceforge.net/snapshot/pmd_rules_java_" + getLinkCategory(m.group(1)) + ".html#"
+                                  + m.group(2).toLowerCase());
+                }
+            }
+            list.add(l);
+        }
+        return list;
+    }
+
+    private static String getLinkCategory(String cat) {
+        for (String category : pmdLink.keySet()) {
+            if (cat.contains(category)) {
+                return pmdLink.get(category);
+            }
+        }
+        return "ERROR";
+    }
+
+    private static int diffViolation(List<Violation> org, List<Violation> curr) {
+        int diff = 0;
+        if (org == null || org.isEmpty()) {
+            if (curr != null && !curr.isEmpty()) {
+                diff = curr.size();
+            }
+        } else {
+            if (curr != null && !curr.isEmpty()) {
+                diff = curr.size() - org.size();
+            }
+        }
+        return diff;
+    }
+
+    private static Map<String, Integer> diffCategory(List<Violation> org, List<Violation> curr) {
+        Map<String, AtomicInteger> currData = new HashMap<>();
+        Map<String, AtomicInteger> orgData = new HashMap<>();
+        countViolations(curr, currData);
+        countViolations(org, orgData);
+        Map<String, Integer> val = new HashMap<>();
+        for (String cat : currData.keySet()) {
+            if (orgData.get(cat) == null) {
+                val.put(cat, currData.get(cat).intValue());
+            } else if (currData.get(cat).intValue() > orgData.get(cat).intValue()) {
+                val.put(cat, currData.get(cat).intValue() - orgData.get(cat).intValue());
+            }
+        }
+        return val;
+    }
+
+    private static void countViolations(List<Violation> violations,  Map<String, AtomicInteger> store){
+        for (Violation v : violations) {
+            if (store.get(v.getCategory() + ":" + v.getRule()) == null) {
+                store.put(v.getCategory() + ":" + v.getRule(), new AtomicInteger(1));
+            } else {
+                store.get(v.getCategory() + ":" + v.getRule()).incrementAndGet();
+            }
+        }
+    }
+
+    private static void processOriginalViolations(List<Violation> org){
+
+    }
+    private static String getLineNumbers(List<Violation> vList, String category) {
+        String val = "";
+        boolean firstOver = false;
+        for (Violation v : vList) {
+            if (category.equals(v.getCategory() + ":" + v.getRule())) {
+                if (firstOver) {
+                    val += ",";
+                }
+                val += v.getLine();
+                firstOver = true;
+            }
+        }
+        return val;
+    }
+
+    static Map<String, List<Violation>> readCurrentPMDState(String fileName) {
+        Map<String, List<Violation>> val = readState(fileName, HashMap.class);
+        return val == null ? new HashMap<>() : val;
+    }
+
+    static Map<String, List<Violation>> readCurrentPMDState(File file) {
+        Map<String, List<Violation>> val = readState(file, HashMap.class);
+        return val == null ? new HashMap<>() : val;
+    }
+
+    static void writeCurrentPMDState(File file, Map<String, List<Violation>> data) {
+        try (OutputStream os = new FileOutputStream(file); ObjectOutputStream oos = new ObjectOutputStream(os)) {
+            oos.writeObject(data);
+        } catch (IOException ioe) {
+            throw new UncheckedIOException(ioe);
+        }
+    }
+
+    static boolean isReportEmpty(File reportFile){
+        try {
+            return !reportFile.exists() || Files.readAllLines(reportFile.toPath()).size()<=1;
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+}
diff --git a/openecomp-be/tools/pmd-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/pmd/PMDState.java b/openecomp-be/tools/pmd-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/pmd/PMDState.java
new file mode 100644
index 0000000..2602fff
--- /dev/null
+++ b/openecomp-be/tools/pmd-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/pmd/PMDState.java
@@ -0,0 +1,74 @@
+package org.openecomp.sdc.onboarding.pmd;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class PMDState {
+
+    private static Map<String, List<Violation>> data = new HashMap<>();
+    private static Map<String, List<Violation>> historicState = null;
+    private static Pattern p =
+            Pattern.compile("\"(.*)\",\"(.*)\",\"(.*)\",\"(.*)\",\"(.*)\",\"(.*)\",\"(.*)\",\"(.*)\"");
+
+    public static boolean addViolation(String line, String fileLocation) {
+        Matcher m = p.matcher(line);
+        if (m.find()) {
+            if (m.group(3).indexOf("generated-sources") != -1) {
+                return true;
+            }
+            String mainOrTest =
+                    m.group(3).indexOf(File.separator + "test" + File.separator) == -1 ? "[MAIN] " : "[TEST] ";
+            List<Violation> list = data.get(fileLocation + "::" + mainOrTest + m.group(2) + "." + m.group(3).substring(
+                    m.group(3).lastIndexOf(File.separatorChar) + 1));
+            if (list == null) {
+                list = new LinkedList<>();
+                data.put(fileLocation + "::" + mainOrTest + m.group(2) + "." + m.group(3).substring(
+                        m.group(3).lastIndexOf(File.separatorChar) + 1), list);
+            }
+
+            list.add(new Violation(m.group(7), m.group(8), m.group(6), Integer.parseInt(m.group(4)),
+                    Integer.parseInt(m.group(5))));
+            return true;
+        }
+        return false;
+    }
+
+    public static void reset(File mainFile, File testFile, String moduleCoordinates) throws IOException {
+        data.clear();
+        init(mainFile, moduleCoordinates, "[MAIN] ");
+        init(testFile, moduleCoordinates, "[TEST] ");
+    }
+
+    private static void init(File file, String moduleCoordinates, String maiOrTest) throws IOException {
+        if (file.exists()) {
+            List<String> coll = Files.readAllLines(file.toPath());
+            for (String line : coll) {
+                if (line.indexOf("$") == -1) {
+                    data.put(moduleCoordinates + "::" + maiOrTest + line.substring(0, line.indexOf('.'))
+                                                                        .replace(File.separator, ".") + ".java",
+                            new LinkedList<>());
+                }
+            }
+        }
+    }
+
+    public static Map<String, List<Violation>> getState() {
+        return data;
+    }
+
+    public static void setHistoricState(Map<String, List<Violation>> data) {
+        historicState = data;
+    }
+
+    public static Map<String, List<Violation>> getHistoricState() {
+        return historicState;
+    }
+
+}
diff --git a/openecomp-be/tools/pmd-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/pmd/Table.java b/openecomp-be/tools/pmd-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/pmd/Table.java
new file mode 100644
index 0000000..68eafd0
--- /dev/null
+++ b/openecomp-be/tools/pmd-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/pmd/Table.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright © 2018 European Support Limited
+ *
+ * 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 a "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 org.openecomp.sdc.onboarding.pmd;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Table {
+
+    private final int TABLEPADDING = 1;
+    private final char SEPERATOR_CHAR = '-';
+
+    private ArrayList<String> headers;
+    private ArrayList<ArrayList<String>> table;
+    private ArrayList<Integer> maxLength;
+
+    public Table(ArrayList<String> headersIn, ArrayList<ArrayList<String>> content) {
+        this.headers = headersIn;
+        this.maxLength = new ArrayList<Integer>();
+        for (int i = 0; i < headers.size(); i++) {
+            maxLength.add(headers.get(i).length());
+        }
+        this.table = content;
+        calcMaxLengthAll();
+    }
+
+    public String drawTable() {
+        StringBuilder sb = new StringBuilder();
+        StringBuilder sbRowSep = new StringBuilder();
+        StringBuffer padder = new StringBuffer();
+        String rowSeperator = "";
+
+        for (int i = 0; i < TABLEPADDING; i++) {
+            padder.append(" ");
+        }
+
+        for (int i = 0; i < maxLength.size(); i++) {
+            sbRowSep.append("|");
+            for (int j = 0; j < maxLength.get(i) + (TABLEPADDING * 2); j++) {
+                sbRowSep.append(SEPERATOR_CHAR);
+            }
+        }
+        sbRowSep.append("|");
+        rowSeperator = sbRowSep.toString();
+
+        sb.append(rowSeperator);
+        sb.append("\n");
+        sb.append("|");
+        for (int i = 0; i < headers.size(); i++) {
+            sb.append(padder);
+            sb.append(headers.get(i));
+            for (int k = 0; k < (maxLength.get(i) - headers.get(i).length()); k++) {
+                sb.append(" ");
+            }
+            sb.append(padder);
+            sb.append("|");
+        }
+        sb.append("\n");
+        sb.append(rowSeperator);
+        sb.append("\n");
+
+        for (int i = 0; i < table.size(); i++) {
+            ArrayList<String> tempRow = table.get(i);
+            sb.append("|");
+            for (int j = 0; j < tempRow.size(); j++) {
+                sb.append(padder);
+                sb.append(tempRow.get(j));
+                for (int k = 0; k < (maxLength.get(j) - tempRow.get(j).length()); k++) {
+                    sb.append(" ");
+                }
+                sb.append(padder);
+                sb.append("|");
+            }
+            sb.append("\n");
+            sb.append(rowSeperator);
+            sb.append("\n");
+        }
+        return sb.toString();
+    }
+
+    private void calcMaxLengthAll() {
+        for (int i = 0; i < table.size(); i++) {
+            List<String> temp = table.get(i);
+            for (int j = 0; j < temp.size(); j++) {
+                if (temp.get(j).length() > maxLength.get(j)) {
+                    maxLength.set(j, temp.get(j).length());
+                }
+            }
+        }
+    }
+
+}
+
diff --git a/openecomp-be/tools/pmd-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/pmd/VerifyHelperMojo.java b/openecomp-be/tools/pmd-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/pmd/VerifyHelperMojo.java
new file mode 100644
index 0000000..87c9ca5
--- /dev/null
+++ b/openecomp-be/tools/pmd-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/pmd/VerifyHelperMojo.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright © 2018 European Support Limited
+ *
+ * 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 a "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 org.openecomp.sdc.onboarding.pmd;
+
+import static org.openecomp.sdc.onboarding.pmd.PMDHelperUtils.getStateFile;
+import static org.openecomp.sdc.onboarding.pmd.PMDHelperUtils.readCurrentPMDState;
+import static org.openecomp.sdc.onboarding.pmd.PMDHelperUtils.writeCurrentPMDState;
+import static org.openecomp.sdc.onboarding.pmd.PMDHelperUtils.isReportEmpty;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.plugins.annotations.ResolutionScope;
+import org.apache.maven.project.MavenProject;
+
+@Mojo(name = "post-verify-helper", threadSafe = true, defaultPhase = LifecyclePhase.VERIFY,
+        requiresDependencyResolution = ResolutionScope.NONE)
+public class VerifyHelperMojo extends AbstractMojo {
+
+    private static final String SKIP_PMD = "skipPMD";
+
+    @Parameter(defaultValue = "${project}", readonly = true)
+    private MavenProject project;
+    @Parameter(defaultValue = "${project.artifact.groupId}:${project.artifact.artifactId}")
+    private String moduleCoordinates;
+    @Parameter(defaultValue = "${session}")
+    private MavenSession session;
+    @Parameter
+    private File pmdTargetLocation;
+    @Parameter
+    private File pmdReportFile;
+    @Parameter
+    private File pmdStateFile;
+    @Parameter
+    private String pmdCurrentStateFilePath;
+    @Parameter
+    private String excludePackaging;
+    @Parameter
+    private Boolean validatePMDReport = Boolean.FALSE;
+    @Parameter
+    private String persistingModuleCoordinates;
+    @Parameter
+    private File pmdFailureReportLocation;
+    @Parameter
+    private File compiledFilesList;
+    @Parameter
+    private File compiledTestFilesList;
+
+    private static File pmdCurrentStateFile;
+
+    public void execute() throws MojoExecutionException, MojoFailureException {
+        if (project.getPackaging().equals(excludePackaging)) {
+            return;
+        }
+        if (moduleCoordinates.equals(persistingModuleCoordinates)) {
+            if (pmdStateFile.exists()) {
+                pmdStateFile.delete();
+            }
+        }
+        if (pmdCurrentStateFile == null) {
+            pmdCurrentStateFile =
+                    getStateFile(pmdCurrentStateFilePath.substring(0, pmdCurrentStateFilePath.indexOf('/')), project,
+                            pmdCurrentStateFilePath);
+            pmdCurrentStateFile.getParentFile().mkdirs();
+            pmdReportFile.getParentFile().mkdirs();
+        }
+        if (PMDState.getHistoricState() != null && PMDState.getHistoricState().isEmpty()) {
+            getLog().error("PMD Check is skipped. problem while loading data.");
+        }
+        if (Boolean.FALSE.equals(Boolean.valueOf(project.getProperties().getProperty(SKIP_PMD))) && !isReportEmpty(pmdReportFile)) {
+            Map<String, List<Violation>> data = readCurrentPMDState(pmdCurrentStateFile);
+            Map<String, List<Violation>> cv = readCurrentModulePMDReport();
+            data.putAll(cv);
+            if (!PMDState.getHistoricState().isEmpty() && !PMDHelperUtils
+                                                                   .evaluateCodeQuality(PMDState.getHistoricState(), cv,
+                                                                           pmdFailureReportLocation, getLog())) {
+                if (validatePMDReport) {
+                    throw new MojoFailureException(
+                            "PMD Failures encountered. Build halted. For details refer " + pmdFailureReportLocation
+                                                                                                   .getAbsolutePath());
+                } else {
+                    getLog().error(
+                            "\u001B[31m\u001B[1m Code Quality concerns raised by Quality Management System. For details refer "
+                                    + pmdFailureReportLocation.getAbsolutePath()
+                                    + " and address them before committing this code in Version Control System. \u001B[0m");
+                }
+            }
+            Map<String, Object> checksumStore = HashMap.class.cast(data);
+            checksumStore.put(moduleCoordinates,
+                    project.getProperties().getProperty("mainChecksum") + ":" + project.getProperties()
+                                                                                       .getProperty("testChecksum"));
+            writeCurrentPMDState(pmdCurrentStateFile, data);
+        }
+        if (Boolean.FALSE.equals(Boolean.valueOf(project.getProperties().getProperty(SKIP_PMD)))) {
+            if (isReportEmpty(pmdReportFile)){
+                HashMap data = HashMap.class.cast(readCurrentPMDState(pmdCurrentStateFile));
+                data.put(moduleCoordinates,
+                        project.getProperties().getProperty("mainChecksum") + ":" + project.getProperties()
+                                                                                           .getProperty("testChecksum"));
+                writeCurrentPMDState(pmdCurrentStateFile, data);
+            }
+            pmdReportFile.delete();
+        }
+        if (pmdTargetLocation.exists()) {
+            pmdTargetLocation.delete();
+        }
+
+    }
+
+    private Map<String, List<Violation>> readCurrentModulePMDReport() {
+        try {
+            PMDState.reset(compiledFilesList, compiledTestFilesList, moduleCoordinates);
+            if (pmdReportFile.exists()) {
+                boolean isFirst = true;
+                for (String line : Files.lines(pmdReportFile.toPath()).collect(Collectors.toList())) {
+                    if (isFirst) {
+                        isFirst = false;
+                    } else {
+                        PMDState.addViolation(line, moduleCoordinates);
+                    }
+                }
+            }
+        } catch (IOException ioe) {
+            throw new UncheckedIOException(ioe);
+        }
+        return PMDState.getState();
+    }
+
+}
diff --git a/openecomp-be/tools/pmd-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/pmd/Violation.java b/openecomp-be/tools/pmd-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/pmd/Violation.java
new file mode 100644
index 0000000..4bfbee1
--- /dev/null
+++ b/openecomp-be/tools/pmd-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/pmd/Violation.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright © 2018 European Support Limited
+ *
+ * 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 a "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 org.openecomp.sdc.onboarding.pmd;
+
+import java.io.File;
+import java.io.Serializable;
+import java.util.jar.JarFile;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class Violation implements Serializable {
+
+    private final String category;
+    private final String rule;
+    private final String description;
+    private final int priority;
+    private final int line;
+
+    public String getCategory() {
+        return category;
+    }
+
+    public String getRule() {
+        return rule;
+    }
+
+    public int getPriority() {
+        return priority;
+    }
+
+    public int getLine() {
+        return line;
+    }
+
+    public Violation(String category, String rule, String description, int priority, int line) {
+        this.category = category;
+        this.rule = rule;
+        this.description = description;
+        this.priority = priority;
+        this.line = line;
+    }
+
+    public String toString() {
+        return category + ":" + rule + ":" + getPriority() + description + ":" + line;
+    }
+}
diff --git a/openecomp-be/tools/pmd-helper-plugin/src/main/resources/pmd-empty.xml b/openecomp-be/tools/pmd-helper-plugin/src/main/resources/pmd-empty.xml
new file mode 100644
index 0000000..c23b533
--- /dev/null
+++ b/openecomp-be/tools/pmd-helper-plugin/src/main/resources/pmd-empty.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<pmd xmlns="http://pmd.sourceforge.net/report/2.0.0"
+     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+     xsi:schemaLocation="http://pmd.sourceforge.net/report/2.0.0 http://pmd.sourceforge.net/report_2_0_0.xsd"
+     version="6.0.1" timestamp="2018-04-29T23:06:21.384">
+</pmd>