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/artifact-copy-plugin/pom.xml b/openecomp-be/tools/artifact-copy-plugin/pom.xml
new file mode 100644
index 0000000..03301a7
--- /dev/null
+++ b/openecomp-be/tools/artifact-copy-plugin/pom.xml
@@ -0,0 +1,45 @@
+<?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>artifact-copy-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>
+        <skipTestRun>true</skipTestRun>
+    </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/artifact-copy-plugin/src/main/java/org/openecomp/sdc/onboarding/util/ArtifactHelper.java b/openecomp-be/tools/artifact-copy-plugin/src/main/java/org/openecomp/sdc/onboarding/util/ArtifactHelper.java
new file mode 100644
index 0000000..e7ad5da
--- /dev/null
+++ b/openecomp-be/tools/artifact-copy-plugin/src/main/java/org/openecomp/sdc/onboarding/util/ArtifactHelper.java
@@ -0,0 +1,56 @@
+package org.openecomp.sdc.onboarding.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Scanner;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.project.MavenProject;
+
+public class ArtifactHelper {
+
+    private MavenProject project;
+
+    List<ArtifactRepository> getRepositories(boolean snapshotRepo) {
+        List<ArtifactRepository> list = new ArrayList<>();
+        for (ArtifactRepository artRepo : project.getRemoteArtifactRepositories()) {
+            if (snapshotRepo) {
+                if (artRepo.getSnapshots().isEnabled()) {
+                    list.add(artRepo);
+                }
+            } else {
+                if (artRepo.getReleases().isEnabled()) {
+                    list.add(artRepo);
+                }
+            }
+        }
+        return list;
+    }
+
+    String getContents(URL path) throws IOException {
+        try (InputStream is = path.openStream(); Scanner scnr = new Scanner(is).useDelimiter("\\A")) {
+            return scnr.hasNext() ? scnr.next() : "";
+        }
+    }
+
+    String getChecksum(String filePath, String hashType) throws NoSuchAlgorithmException, IOException {
+        MessageDigest md = MessageDigest.getInstance(hashType);
+        md.update(Files.readAllBytes(Paths.get(filePath)));
+        byte[] hashBytes = md.digest();
+
+        StringBuffer buffer = new StringBuffer();
+        for (byte hashByte : hashBytes) {
+            buffer.append(Integer.toString((hashByte & 0xff) + 0x100, 16).substring(1));
+        }
+        return buffer.toString();
+    }
+
+}
+
+
diff --git a/openecomp-be/tools/artifact-copy-plugin/src/main/java/org/openecomp/sdc/onboarding/util/CalibrateArtifactPlugin.java b/openecomp-be/tools/artifact-copy-plugin/src/main/java/org/openecomp/sdc/onboarding/util/CalibrateArtifactPlugin.java
new file mode 100644
index 0000000..4838608
--- /dev/null
+++ b/openecomp-be/tools/artifact-copy-plugin/src/main/java/org/openecomp/sdc/onboarding/util/CalibrateArtifactPlugin.java
@@ -0,0 +1,82 @@
+package org.openecomp.sdc.onboarding.util;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+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.Component;
+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;
+import org.apache.maven.project.MavenProjectHelper;
+
+@Mojo(name = "calibrate-artifact-helper", threadSafe = true, defaultPhase = LifecyclePhase.INSTALL,
+        requiresDependencyResolution = ResolutionScope.TEST)
+public class CalibrateArtifactPlugin extends AbstractMojo {
+
+    private static final String ARTIFACT_COPY_PATH = "artifactPathToCopy";
+
+    @Parameter(defaultValue = "${session}")
+    private MavenSession session;
+    @Parameter(defaultValue = "${project}", readonly = true)
+    private MavenProject project;
+    @Component
+    private MavenProjectHelper projectHelper;
+    @Parameter
+    private String groupId;
+    @Parameter
+    private String artifactId;
+    @Parameter
+    private String version;
+    @Parameter
+    private String targetLocation;
+    @Parameter
+    private String name;
+    @Parameter
+    private String excludePackaging;
+    @Parameter
+    private ArtifactHelper artifactHelper;
+
+    public void execute() throws MojoExecutionException, MojoFailureException {
+        if (project.getPackaging().equals(excludePackaging)) {
+            return;
+        }
+        if (project.getProperties().containsKey(ARTIFACT_COPY_PATH)
+                    && project.getProperties().getProperty(ARTIFACT_COPY_PATH) != null) {
+            File f = null;
+            String artifactPath = project.getProperties().getProperty(ARTIFACT_COPY_PATH)
+                                         .startsWith(session.getLocalRepository().getBasedir()) ?
+                                          project.getProperties().getProperty(ARTIFACT_COPY_PATH) :
+                                          project.getProperties().getProperty(ARTIFACT_COPY_PATH)
+                                                 .replace(groupId, groupId.replace('.', '/'));
+            if (artifactPath.startsWith(session.getLocalRepository().getBasedir())) {
+                f = new File(artifactPath);
+            } else {
+                f = new File(session.getLocalRepository().getBasedir(), artifactPath);
+            }
+            if (f.exists()) {
+                project.getArtifact().setFile(f);
+            }
+        }
+        File file = new File(project.getBuild().getDirectory(), project.getBuild().getFinalName() + ".unicorn");
+        if (file.exists()) {
+            try {
+                Files.copy(file.toPath(), Paths.get(
+                        session.getLocalRepository().getBasedir() + File.separator + project.getGroupId().replace(".",
+                                File.separator) + File.separator + project.getArtifactId() + File.separator
+                                + project.getVersion(), project.getBuild().getFinalName() + ".unicorn"),
+                        StandardCopyOption.REPLACE_EXISTING);
+            } catch (IOException e) {
+                throw new UncheckedIOException(e);
+            }
+        }
+    }
+}
diff --git a/openecomp-be/tools/artifact-copy-plugin/src/main/java/org/openecomp/sdc/onboarding/util/CopyArtifactPlugin.java b/openecomp-be/tools/artifact-copy-plugin/src/main/java/org/openecomp/sdc/onboarding/util/CopyArtifactPlugin.java
new file mode 100644
index 0000000..20b1a7c
--- /dev/null
+++ b/openecomp-be/tools/artifact-copy-plugin/src/main/java/org/openecomp/sdc/onboarding/util/CopyArtifactPlugin.java
@@ -0,0 +1,141 @@
+package org.openecomp.sdc.onboarding.util;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.nio.file.StandardOpenOption;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+import java.util.List;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+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 = "copy-helper", threadSafe = true, defaultPhase = LifecyclePhase.CLEAN,
+        requiresDependencyResolution = ResolutionScope.NONE)
+public class CopyArtifactPlugin extends AbstractMojo {
+
+    @Parameter(defaultValue = "${session}")
+    private MavenSession session;
+    @Parameter(defaultValue = "${project}", readonly = true)
+    private MavenProject project;
+    @Parameter
+    private String groupId;
+    @Parameter
+    private String artifactId;
+    @Parameter
+    private String version;
+    @Parameter
+    private String targetLocation;
+    @Parameter
+    private String name;
+    @Parameter
+    private ArtifactHelper artifactHelper;
+
+    public void execute() throws MojoExecutionException, MojoFailureException {
+        if (!project.getProperties().containsKey("resolvedVersion")) {
+            return;
+        }
+        boolean isSnapshot = version.contains("SNAPSHOT");
+        List<ArtifactRepository> artRepoList = artifactHelper.getRepositories(isSnapshot);
+        String resolvedVersion =
+                project.getProperties().getProperty("resolvedVersion");
+        try {
+            if (!version.equals(resolvedVersion)) {
+                if(copyResolvedArtifact(artRepoList, resolvedVersion) && getLog().isInfoEnabled()){
+                    getLog().info("Data Artifact Copied with "+resolvedVersion);
+                }
+
+            }
+            File orgFile = new File(
+                    session.getLocalRepository().getBasedir() + File.separator + (groupId.replace(".", File.separator))
+                            + File.separator + artifactId + File.separator + version);
+            if (!orgFile.exists()) {
+                return;
+            }
+            File[] list = orgFile.listFiles(t -> t.getName().equals(artifactId + "-" + version + ".jar"));
+            if (list != null && list.length > 0) {
+                String directory = session.getLocalRepository().getBasedir() + File.separator + (groupId.replace(".",
+                        File.separator)) + File.separator + targetLocation + File.separator + version;
+                if (!Paths.get(directory, name).toFile().exists()) {
+                    return;
+                }
+                Files.copy(list[0].toPath(), Paths.get(directory, name), StandardCopyOption.REPLACE_EXISTING);
+                copyTargetArtifact(directory, list[0]);
+            }
+        } catch (IOException | NoSuchAlgorithmException e) {
+            throw new MojoFailureException(e.getMessage());
+        }
+    }
+
+    private void copyTargetArtifact(String directory, File source) throws IOException, NoSuchAlgorithmException {
+        File[] files = new File(directory).listFiles(
+                f -> f.getName().endsWith(".jar") && !f.getName().equals(name) && f.getName().startsWith(
+                        name.substring(0, name.lastIndexOf('-'))));
+        if (files == null || files.length == 0) {
+            return;
+        }
+        Arrays.sort(files, this::compare);
+        File tgtFile = files[files.length - 1];
+        Files.copy(source.toPath(), tgtFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
+        for (String checksumType : Arrays.asList("sha1", "md5")) {
+            File potentialFile = new File(tgtFile.getAbsolutePath() + "." + checksumType);
+            if (potentialFile.exists()) {
+                Files.write(potentialFile.toPath(),
+                        artifactHelper.getChecksum(source.getAbsolutePath(), checksumType).getBytes(),
+                        StandardOpenOption.CREATE);
+            }
+        }
+    }
+
+
+    private boolean copyResolvedArtifact(List<ArtifactRepository> list, String resolvedVersion){
+        for (ArtifactRepository repo : list) {
+            try {
+                writeContents(
+                        new URL(repo.getUrl() + (groupId.replace('.', '/')) + '/' + artifactId + '/' + version + '/'
+                                        + artifactId + "-" + (version.equals(resolvedVersion) ? version :
+                                                                      version.replace("SNAPSHOT", resolvedVersion))
+                                        + ".jar"));
+                return true;
+            } catch (IOException e) {
+                getLog().warn(e);
+            }
+        }
+        return false;
+    }
+
+
+    private void writeContents(URL path) throws IOException {
+        String directory =
+                session.getLocalRepository().getBasedir() + File.separator + (groupId.replace(".", File.separator))
+                        + File.separator + artifactId + File.separator + version;
+        try (InputStream is = path.openStream()) {
+            Files.copy(is, Paths.get(directory, artifactId + "-" + version + ".jar"),
+                    StandardCopyOption.REPLACE_EXISTING);
+        }
+
+    }
+
+    private int compare(File file1, File file2) {
+        if (file1.lastModified() > file2.lastModified()) {
+            return 1;
+        }
+        if (file1.lastModified() < file2.lastModified()) {
+            return -1;
+        }
+        return 0;
+    }
+
+}
diff --git a/openecomp-be/tools/artifact-copy-plugin/src/main/java/org/openecomp/sdc/onboarding/util/InitializationHelperMojo.java b/openecomp-be/tools/artifact-copy-plugin/src/main/java/org/openecomp/sdc/onboarding/util/InitializationHelperMojo.java
new file mode 100644
index 0000000..0675175
--- /dev/null
+++ b/openecomp-be/tools/artifact-copy-plugin/src/main/java/org/openecomp/sdc/onboarding/util/InitializationHelperMojo.java
@@ -0,0 +1,88 @@
+package org.openecomp.sdc.onboarding.util;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+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 = "init-artifact-helper", threadSafe = true, defaultPhase = LifecyclePhase.PRE_CLEAN,
+        requiresDependencyResolution = ResolutionScope.NONE)
+public class InitializationHelperMojo extends AbstractMojo {
+
+    private static final String SKIP_GET = "skipGet";
+
+    @Parameter(defaultValue = "${session}")
+    private MavenSession session;
+    @Parameter(defaultValue = "${project}", readonly = true)
+    private MavenProject project;
+    @Parameter
+    private String groupId;
+    @Parameter
+    private String artifactId;
+    @Parameter
+    private String version;
+    @Parameter
+    private String targetLocation;
+    @Parameter
+    private String name;
+    @Parameter
+    private String excludePackaging;
+    @Parameter
+    private ArtifactHelper artifactHelper;
+
+    public void execute() throws MojoExecutionException, MojoFailureException {
+        if (System.getProperties().containsKey(SKIP_GET)) {
+            project.getProperties()
+                   .setProperty(SKIP_GET, Boolean.valueOf(System.getProperties().containsKey(SKIP_GET)).toString());
+            return;
+        } else {
+            File orgFile = new File(
+                    session.getLocalRepository().getBasedir() + File.separator + (groupId.replace(".", File.separator))
+                            + File.separator + artifactId + File.separator + version);
+            String resolvedVersion = getResolvedVersion(artifactHelper.getRepositories(version.contains("SNAPSHOT")));
+            project.getProperties().setProperty("resolvedVersion", resolvedVersion);
+            System.getProperties().setProperty(SKIP_GET, Boolean.TRUE.toString());
+            if (resolvedVersion.equals(version) && !orgFile.exists()) {
+                project.getProperties().setProperty(SKIP_GET, Boolean.TRUE.toString());
+            }
+        }
+    }
+
+    private String getResolvedVersion(List<ArtifactRepository> list) {
+        Pattern timestampPattern = Pattern.compile(".*<timestamp>(.*)</timestamp>.*");
+        Pattern buildNumberPattern = Pattern.compile(".*<buildNumber>(.*)</buildNumber>.*");
+        String timestamp = null;
+        String buildNumber = null;
+        for (ArtifactRepository repo : list) {
+            try {
+                String content = artifactHelper.getContents(
+                        new URL(repo.getUrl() + (groupId.replace('.', '/')) + '/' + artifactId + '/' + version
+                                        + "/maven-metadata.xml"));
+                Matcher m = timestampPattern.matcher(content);
+                if (m.find()) {
+                    timestamp = m.group(1);
+                }
+                m = buildNumberPattern.matcher(content);
+                if (m.find()) {
+                    buildNumber = m.group(1);
+                }
+            } catch (IOException e) {
+                continue;
+            }
+        }
+        return timestamp != null && buildNumber != null ? timestamp + "-" + buildNumber : version;
+    }
+
+}
diff --git a/openecomp-be/tools/build-data-helper/pom.xml b/openecomp-be/tools/build-data-helper/pom.xml
new file mode 100644
index 0000000..a5f55c3
--- /dev/null
+++ b/openecomp-be/tools/build-data-helper/pom.xml
@@ -0,0 +1,88 @@
+<?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</groupId>
+    <artifactId>build-data-helper</artifactId>
+
+    <parent>
+        <artifactId>sdc-onboarding</artifactId>
+        <groupId>org.openecomp.sdc</groupId>
+        <version>1.2.0-SNAPSHOT</version>
+        <relativePath>../../../onboarding</relativePath>
+    </parent>
+    <properties>
+        <skipPMD>true</skipPMD>
+        <artifactPathToCopy>${project.groupId}/${project.artifactId}/${project.version}/${project.artifactId}-${project.version}.jar</artifactPathToCopy>
+    </properties>
+<build>
+    <plugins>
+        <plugin>
+            <groupId>org.openecomp.sdc.onboarding</groupId>
+            <artifactId>artifact-copy-plugin</artifactId>
+            <version>${project.version}</version>
+            <executions>
+                <execution>
+                    <id>id3</id>
+                    <goals>
+                        <goal>copy-helper</goal>
+                        <goal>calibrate-artifact-helper</goal>
+                    </goals>
+                    <phase>install</phase>
+                </execution>
+                <execution>
+                    <id>id4</id>
+                    <goals>
+                        <goal>init-artifact-helper</goal>
+                    </goals>
+                </execution>
+            </executions>
+            <configuration>
+                <groupId>org.openecomp.sdc</groupId>
+                <artifactId>build-data-installer</artifactId>
+                <version>${project.version}</version>
+                <targetLocation>build-data-helper</targetLocation>
+                <name>build-data-helper-${project.version}.jar</name>
+                <artifactHelper>
+                    <project>${project}</project>
+                </artifactHelper>
+            </configuration>
+        </plugin>
+        <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-dependency-plugin</artifactId>
+            <version>3.1.0</version>
+            <executions>
+                <execution>
+                    <id>id1</id>
+                    <goals>
+                        <goal>get</goal>
+                    </goals>
+                    <phase>clean</phase>
+                    <configuration>
+                        <artifactId>build-data-helper</artifactId>
+                    </configuration>
+                </execution>
+                <execution>
+                    <id>id2</id>
+                    <goals>
+                        <goal>get</goal>
+                    </goals>
+                    <phase>clean</phase>
+                    <configuration>
+                        <artifactId>build-data-installer</artifactId>
+                    </configuration>
+                </execution>
+            </executions>
+            <configuration>
+                <groupId>org.openecomp.sdc</groupId>
+                <version>${project.version}</version>
+                <skip>${skipGet}</skip>
+            </configuration>
+        </plugin>
+    </plugins>
+</build>
+
+</project>
\ No newline at end of file
diff --git a/openecomp-be/tools/build-data-installer/pom.xml b/openecomp-be/tools/build-data-installer/pom.xml
new file mode 100644
index 0000000..94121b5
--- /dev/null
+++ b/openecomp-be/tools/build-data-installer/pom.xml
@@ -0,0 +1,52 @@
+<?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</groupId>
+    <artifactId>build-data-installer</artifactId>
+
+    <parent>
+        <artifactId>sdc-onboarding</artifactId>
+        <groupId>org.openecomp.sdc</groupId>
+        <version>1.2.0-SNAPSHOT</version>
+        <relativePath>../../../onboarding</relativePath>
+    </parent>
+    <properties>
+        <skipPMD>true</skipPMD>
+    </properties>
+    <build>
+    <plugins>
+        <plugin>
+            <groupId>org.openecomp.sdc.onboarding</groupId>
+            <artifactId>pmd-helper-plugin</artifactId>
+            <version>${project.version}</version>
+            <dependencies>
+                <dependency>
+                    <groupId>org.openecomp.sdc</groupId>
+                    <artifactId>build-data-helper</artifactId>
+                    <version>${project.version}</version>
+                </dependency>
+            </dependencies>
+            <executions>
+                <execution>
+                    <goals>
+                        <goal>init-pmd-helper</goal>
+                        <goal>post-verify-helper</goal>
+                    </goals>
+                </execution>
+            </executions>
+            <configuration>
+                <excludePackaging>pom</excludePackaging>
+                <pmdTargetLocation>${project.build.directory}/pmd/pmd.xml</pmdTargetLocation>
+                <pmdReportFile>${project.build.directory}/pmd/pmd.csv</pmdReportFile>
+                <pmdFailureReportLocation>${project.build.directory}/pmd.txt</pmdFailureReportLocation>
+                <persistingModuleCoordinates>org.openecomp.sdc:build-data-installer</persistingModuleCoordinates>
+                <pmdCurrentStateFilePath>org.openecomp.sdc:sdc-onboarding/target/build-data/pmdState.dat</pmdCurrentStateFilePath>
+                <pmdStateFile>${project.build.outputDirectory}/pmd.dat</pmdStateFile>
+            </configuration>
+        </plugin>
+    </plugins>
+    </build>
+</project>
\ No newline at end of file
diff --git a/openecomp-be/tools/compile-helper-plugin/pom.xml b/openecomp-be/tools/compile-helper-plugin/pom.xml
index 3891558..73513f6 100644
--- a/openecomp-be/tools/compile-helper-plugin/pom.xml
+++ b/openecomp-be/tools/compile-helper-plugin/pom.xml
@@ -14,7 +14,12 @@
         <version>1.2.0-SNAPSHOT</version>
         <relativePath>../../../onboarding</relativePath>
     </parent>
-
+    <properties>
+        <skipPMD>true</skipPMD>
+        <classes>classes/**/*.class</classes>
+        <mavenStatus>maven-status/**</mavenStatus>
+        <skipTestRun>true</skipTestRun>
+    </properties>
     <dependencies>
         <dependency>
             <groupId>org.apache.maven</groupId>
diff --git a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/BuildHelper.java b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/BuildHelper.java
new file mode 100644
index 0000000..42f3166
--- /dev/null
+++ b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/BuildHelper.java
@@ -0,0 +1,182 @@
+/*
+ * 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;
+
+import static org.openecomp.sdc.onboarding.Constants.JAVA_EXT;
+import static org.openecomp.sdc.onboarding.Constants.UNICORN;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.UncheckedIOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.ForkJoinPool;
+import java.util.concurrent.RecursiveTask;
+import java.util.stream.Collectors;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.project.MavenProject;
+
+class BuildHelper {
+
+    private BuildHelper() {
+        // donot remove.
+    }
+
+    static long getChecksum(File file, String fileType) {
+        try {
+            return readSources(file, fileType).hashCode();
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+
+    static String getSourceChecksum(String data, String hashType) throws NoSuchAlgorithmException {
+        MessageDigest md = MessageDigest.getInstance(hashType);
+        md.update(data.getBytes());
+        byte[] hashBytes = md.digest();
+
+        StringBuffer buffer = new StringBuffer();
+        for (byte hashByte : hashBytes) {
+            buffer.append(Integer.toString((hashByte & 0xff) + 0x100, 16).substring(1));
+        }
+        return buffer.toString();
+    }
+
+
+    private static Map<String, String> readSources(File file, String fileType) throws IOException {
+        Map<String, String> source = new HashMap<>();
+        if (file.exists()) {
+            List<File> list = Files.walk(Paths.get(file.getAbsolutePath()))
+                                   .filter(JAVA_EXT.equals(fileType) ? BuildHelper::isRegularJavaFile :
+                                                   Files::isRegularFile).map(p -> p.toFile())
+                                   .collect(Collectors.toList());
+            source.putAll(ForkJoinPool.commonPool()
+                                      .invoke(new FileReadTask(list.toArray(new File[0]), file.getAbsolutePath())));
+        }
+        return source;
+    }
+
+    private static boolean isRegularJavaFile(Path path) {
+        File file = path.toFile();
+        return file.isFile() && file.getName().endsWith(JAVA_EXT);
+    }
+
+    private static String getData(File file, byte[] buffer) {
+        try (FileInputStream fis = new FileInputStream(file);
+             BufferedInputStream bis = new BufferedInputStream(fis, 64 * 1024)) {
+            bis.read(buffer, 0, ((int) file.length()));
+            if (file.getAbsolutePath().contains(File.separator + "generated-sources" + File.separator)) {
+                StringBuffer sb = new StringBuffer();
+                List<String> coll = Files.readAllLines(file.toPath());
+                for (String s : coll) {
+                    if (s != null && !s.trim().startsWith("/") && !s.trim().startsWith("*")) {
+                        sb.append(s);
+                    }
+                }
+                return sb.toString();
+            }
+        } catch (IOException ioe) {
+            throw new UncheckedIOException(ioe);
+        }
+        return new String(buffer, 0, ((int) file.length()));
+    }
+
+
+    private static class FileReadTask extends RecursiveTask<Map<String, String>> {
+
+        Map<String, String> store = new HashMap<>();
+        private byte[] buffer = new byte[1024 * 1024];
+        File[] files;
+        String pathPrefix;
+        private final int MAX_FILES = 10;
+
+        FileReadTask(File[] files, String pathPrefix) {
+            this.files = files;
+            this.pathPrefix = pathPrefix;
+        }
+
+        @Override
+        protected Map<String, String> compute() {
+            if (files.length > MAX_FILES) {
+                FileReadTask task1 = new FileReadTask(Arrays.copyOfRange(files, 0, files.length / 2), pathPrefix);
+                FileReadTask task2 =
+                        new FileReadTask(Arrays.copyOfRange(files, files.length / 2, files.length), pathPrefix);
+                task1.fork();
+                task2.fork();
+                store.putAll(task1.join());
+                store.putAll(task2.join());
+            } else {
+                for (File toRead : files) {
+                    store.put(toRead.getAbsolutePath().substring(pathPrefix.length()), getData(toRead, buffer));
+                }
+            }
+
+            return store;
+        }
+    }
+
+    static Optional<String> getArtifactPathInLocalRepo(String repoPath, MavenProject project, byte[] sourceChecksum)
+            throws MojoFailureException {
+
+        URI uri = null;
+        try {
+            uri = new URI(repoPath + (project.getGroupId().replace('.', '/')) + '/' + project.getArtifactId() + '/'
+                                  + project.getVersion());
+        } catch (URISyntaxException e) {
+            throw new MojoFailureException(e.getMessage());
+        }
+        File f = new File(uri);
+        File[] list = f.listFiles(t -> t.getName().equals(project.getArtifactId() + "-" + project.getVersion() + "."
+                                                                  + project.getPackaging()));
+        if (list != null && list.length > 0) {
+            File checksumFile = new File(list[0].getParentFile(), project.getBuild().getFinalName() + "." + UNICORN);
+            try {
+                if (checksumFile.exists() && Arrays.equals(sourceChecksum, Files.readAllBytes(checksumFile.toPath()))) {
+                    return Optional.of(list[0].getAbsolutePath());
+                }
+            } catch (IOException e) {
+                throw new UncheckedIOException(e);
+            }
+        }
+        return Optional.empty();
+    }
+
+    static <T> Optional<T> readState(String fileName, Class<T> clazz) {
+        try (InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName);
+             ObjectInputStream ois = new ObjectInputStream(is)) {
+            return Optional.of(clazz.cast(ois.readObject()));
+        } catch (Exception ignored) {
+            //ignore. it is taken care.
+            return Optional.empty();
+        }
+    }
+
+}
diff --git a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/BuildState.java b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/BuildState.java
index 888622f..17ff7c9 100644
--- a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/BuildState.java
+++ b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/BuildState.java
@@ -16,7 +16,16 @@
 
 package org.openecomp.sdc.onboarding;
 
+import static org.openecomp.sdc.onboarding.BuildHelper.readState;
+import static org.openecomp.sdc.onboarding.Constants.ANSI_COLOR_RESET;
+import static org.openecomp.sdc.onboarding.Constants.ANSI_YELLOW;
+import static org.openecomp.sdc.onboarding.Constants.FULL_BUILD_DATA;
+import static org.openecomp.sdc.onboarding.Constants.FULL_RESOURCE_BUILD_DATA;
+import static org.openecomp.sdc.onboarding.Constants.JAR;
+import static org.openecomp.sdc.onboarding.Constants.MODULE_BUILD_DATA;
 import static org.openecomp.sdc.onboarding.Constants.RESOURCES_CHANGED;
+import static org.openecomp.sdc.onboarding.Constants.RESOURCE_BUILD_DATA;
+import static org.openecomp.sdc.onboarding.Constants.SKIP_MAIN_SOURCE_COMPILE;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -24,64 +33,65 @@
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.util.Collection;
 import java.util.HashMap;
-import java.util.Iterator;
+import java.util.HashSet;
 import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
 import java.util.function.BiFunction;
 import java.util.function.Function;
-import java.util.stream.Stream;
+import org.apache.maven.artifact.Artifact;
 import org.apache.maven.project.MavenProject;
 
 public class BuildState {
 
-    private static Map<String, Long> fullBuildData = new HashMap<>();
-    private static Map<String, Long> fullResourceBuildData = new HashMap<>();
+    private static Map<String, Map> compileDataStore = new HashMap<>();
     private static Map<String, Object> moduleBuildData = new HashMap<>();
     private static Map<String, Object> resourceBuildData = new HashMap<>();
+    private static Map<String, Artifact> artifacts = new HashMap<>();
+    private static Set<String> executeTestsIfDependsOnStore = new HashSet<>();
+    private static Set<String> pmdExecutedInRun = new HashSet<>();
 
-    private static File buildStateFile;
-    private static File resourceStateFile;
-    private File moduleBuildDataFile;
-    private File resourceBuildDataFile;
+    private static File compileStateFile;
     private MavenProject project;
-    private String buildStateFilePath;
-    private String resourceStateFilePath;
+    private String compileStateFilePath;
 
-    private void readFullBuildState() {
-        buildStateFile = initialize(this::getBuildStateFile, fullBuildData,
-                buildStateFilePath.substring(0, buildStateFilePath.indexOf('/')), project);
+    static {
+        initializeStore();
+        Optional<HashMap> masterStore = readState("compile.dat", HashMap.class);
+        compileDataStore = masterStore.isPresent() ? masterStore.get() : compileDataStore;
     }
 
-    private void readResourceBuildState() {
-        resourceStateFile = initialize(this::getResourceStateFile, fullResourceBuildData,
-                resourceStateFilePath.substring(0, resourceStateFilePath.indexOf('/')), project);
-
-    }
-
-    private File initialize(BiFunction<String, MavenProject, File> funct, Map store, String moduleCoordinate,
-            MavenProject proj) {
-        File file = funct.apply(moduleCoordinate, proj);
-        file.getParentFile().mkdirs();
-        try (FileInputStream fis = new FileInputStream(file); ObjectInputStream ois = new ObjectInputStream(fis);) {
-            if (store.isEmpty()) {
-                store.putAll(HashMap.class.cast(ois.readObject()));
+    void init() {
+        artifacts.clear();
+        for (Artifact artifact : project.getArtifacts()) {
+            if (artifact.isSnapshot() && JAR.equals(artifact.getType())) {
+                artifacts.put(artifact.getGroupId() + ":" + artifact.getArtifactId(), artifact);
             }
-        } catch (Exception e) {
-            store.clear();
         }
-        return file;
+        compileStateFile =
+                getCompileStateFile(compileStateFilePath.substring(0, compileStateFilePath.indexOf('/')), project);
     }
 
-    private void writeFullBuildState() throws IOException {
-        writeState(buildStateFile, fullBuildData);
+    static void initializeStore() {
+        compileDataStore.put(FULL_BUILD_DATA, new HashMap<>());
+        compileDataStore.put(FULL_RESOURCE_BUILD_DATA, new HashMap<>());
+        compileDataStore.put(MODULE_BUILD_DATA, new HashMap<>());
+        compileDataStore.put(RESOURCE_BUILD_DATA, new HashMap<>());
     }
 
-    private void writeFullResourceBuildState() throws IOException {
-        writeState(resourceStateFile, fullResourceBuildData);
+
+    static void recordPMDRun(String moduleCoordinates) {
+        pmdExecutedInRun.add(moduleCoordinates);
+    }
+
+    static boolean isPMDRun(String moduleCoordintes) {
+        return pmdExecutedInRun.contains(moduleCoordintes);
+    }
+
+    private void writeCompileState() throws IOException {
+        writeState(compileStateFile, compileDataStore);
     }
 
     private void writeState(File file, Map store) throws IOException {
@@ -90,20 +100,18 @@
         }
     }
 
-    private File getBuildStateFile(String moduleCoordinate, MavenProject proj) {
-        return getStateFile(moduleCoordinate, proj, buildStateFilePath);
+
+    private File getCompileStateFile(String moduleCoordinate, MavenProject proj) {
+        return getStateFile(moduleCoordinate, proj, compileStateFilePath);
     }
 
-    private File getResourceStateFile(String moduleCoordinate, MavenProject proj) {
-        return getStateFile(moduleCoordinate, proj, resourceStateFilePath);
-    }
 
     private File getStateFile(String moduleCoordinate, MavenProject proj, String filePath) {
         return new File(getTopParentProject(moduleCoordinate, proj).getBasedir(),
                 filePath.substring(filePath.indexOf('/') + 1));
     }
 
-    private MavenProject getTopParentProject(String moduleCoordinate, MavenProject proj) {
+    MavenProject getTopParentProject(String moduleCoordinate, MavenProject proj) {
         if (getModuleCoordinate(proj).equals(moduleCoordinate) || proj.getParent() == null) {
             return proj;
         } else {
@@ -116,10 +124,12 @@
     }
 
     void addModuleBuildTime(String moduleCoordinates, Long buildTime) {
-        Long lastTime = fullBuildData.put(moduleCoordinates, buildTime);
+        Long lastTime = Long.class.cast(compileDataStore.get(FULL_BUILD_DATA).put(moduleCoordinates, buildTime));
         try {
             if (lastTime == null || !lastTime.equals(buildTime)) {
-                writeFullBuildState();
+                if (!project.getProperties().containsKey(SKIP_MAIN_SOURCE_COMPILE)) {
+                    writeCompileState();
+                }
             }
         } catch (IOException ignored) {
             // ignored. No need to handle. System will take care.
@@ -127,10 +137,11 @@
     }
 
     void addResourceBuildTime(String moduleCoordinates, Long buildTime) {
-        if (project.getProperties().containsKey(RESOURCES_CHANGED)) {
-            Long lastTime = fullResourceBuildData.put(moduleCoordinates, buildTime);
+        if (project.getProperties().containsKey(RESOURCES_CHANGED)
+                    || compileDataStore.get(FULL_RESOURCE_BUILD_DATA).get(moduleCoordinates) == null) {
             try {
-                writeFullResourceBuildState();
+                compileDataStore.get(FULL_RESOURCE_BUILD_DATA).put(moduleCoordinates, buildTime);
+                writeCompileState();
             } catch (IOException ignored) {
                 // ignored. No need to handle. System will take care.
             }
@@ -142,15 +153,29 @@
     }
 
     Map<String, Object> readModuleBuildData() {
-        return readBuildData(moduleBuildDataFile);
+        return HashMap.class.cast(compileDataStore.get(MODULE_BUILD_DATA).get(getModuleCoordinate(project)));
     }
 
     void saveModuleBuildData(String moduleCoordinate) {
-        saveBuildData(moduleBuildDataFile, moduleBuildData.get(moduleCoordinate));
+        if (moduleBuildData.get(moduleCoordinate) != null) {
+            compileDataStore.get(MODULE_BUILD_DATA).put(moduleCoordinate, moduleBuildData.get(moduleCoordinate));
+        }
+        saveCompileData();
     }
 
     void saveResourceBuildData(String moduleCoordinate) {
-        saveBuildData(resourceBuildDataFile, resourceBuildData.get(moduleCoordinate));
+        if (resourceBuildData.get(moduleCoordinate) != null) {
+            compileDataStore.get(RESOURCE_BUILD_DATA).put(moduleCoordinate, resourceBuildData.get(moduleCoordinate));
+        }
+        saveCompileData();
+    }
+
+    void saveCompileData() {
+        saveBuildData(compileStateFile, compileDataStore);
+    }
+
+    void markTestsMandatoryModule(String moduleCoordinates) {
+        executeTestsIfDependsOnStore.add(moduleCoordinates);
     }
 
     private void saveBuildData(File file, Object dataToSave) {
@@ -166,41 +191,50 @@
     }
 
     Map<String, Object> readResourceBuildData() {
-        return readBuildData(resourceBuildDataFile);
+        return HashMap.class.cast(compileDataStore.get(RESOURCE_BUILD_DATA).get(getModuleCoordinate(project)));
     }
 
-    private Map<String, Object> readBuildData(File file) {
-        try (FileInputStream fis = new FileInputStream(file); ObjectInputStream ois = new ObjectInputStream(fis)) {
-            return HashMap.class.cast(ois.readObject());
-        } catch (Exception e) {
-            return new HashMap<>();
-        }
-    }
 
     void addResourceBuildData(String moduleCoordinates, Map currentModuleResourceBuildData) {
         resourceBuildData.put(moduleCoordinates, currentModuleResourceBuildData);
     }
 
     Long getBuildTime(String moduleCoordinates) {
-        if (fullBuildData.isEmpty()) {
-            readFullBuildState();
-            readResourceBuildState();
-        }
-        Long buildTime = fullBuildData.get(moduleCoordinates);
+        Long buildTime = Long.class.cast(compileDataStore.get(FULL_BUILD_DATA).get(moduleCoordinates));
         return buildTime == null ? 0 : buildTime;
     }
 
     Long getResourceBuildTime(String moduleCoordinates) {
-        Long resourceBuildTime = fullResourceBuildData.get(moduleCoordinates);
+        Long resourceBuildTime = Long.class.cast(compileDataStore.get(FULL_RESOURCE_BUILD_DATA).get(moduleCoordinates));
         return resourceBuildTime == null ? 0 : resourceBuildTime;
     }
 
     boolean isCompileMust(String moduleCoordinates, Collection<String> dependencies) {
+        for (String d : dependencies) {
+            if (artifacts.containsKey(d) && JAR.equals(artifacts.get(d).getType())) {
+                if (artifacts.get(d).getVersion().equals(project.getVersion()) && getBuildTime(d) == 0) {
+                    System.out.println(ANSI_YELLOW + "[WARNING:]" + "You have module[" + d
+                                               + "] not locally compiled even once, please compile your project once daily from root to have reliable build results."
+                                               + ANSI_COLOR_RESET);
+                    return true;
+                }
+            }
+        }
         return isMust(this::getBuildTime, moduleCoordinates, dependencies);
     }
 
-    boolean isTestMust(String moduleCoordinates, Collection<String> dependencies) {
-        return isMust(this::getResourceBuildTime, moduleCoordinates, dependencies);
+    boolean isTestExecutionMandatory() {
+        for (String d : artifacts.keySet()) {
+            if (executeTestsIfDependsOnStore.contains(d)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    boolean isTestMust(String moduleCoordinates) {
+        return getBuildTime(moduleCoordinates) > getResourceBuildTime(moduleCoordinates) || isMust(
+                this::getResourceBuildTime, moduleCoordinates, artifacts.keySet());
     }
 
     private boolean isMust(Function<String, Long> funct, String moduleCoordinates, Collection<String> dependencies) {
@@ -217,22 +251,4 @@
         return false;
     }
 
-    void markModuleDirty(File file) throws IOException {
-        if (file.exists()) {
-            Stream<String> lines = Files.lines(file.toPath());
-            Iterator<String> itr = lines.iterator();
-            while (itr.hasNext()) {
-                String line = itr.next();
-                Path path = Paths.get(line);
-                if (path.toFile().exists()) {
-                    if (path.toFile().setLastModified(System.currentTimeMillis())) {
-                        break;
-                    } else {
-                        continue;
-                    }
-                }
-            }
-        }
-    }
-
 }
diff --git a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/Constants.java b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/Constants.java
index 96abc47..c639c6d 100644
--- a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/Constants.java
+++ b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/Constants.java
@@ -2,14 +2,44 @@
 
 public class Constants {
 
+    private Constants() {
+    }
+
     public static final String JACOCO_SKIP = "jacoco.skip";
     public static final String FORK_COUNT = "fork.count";
+    public static final String FORK_MODE = "fork.mode";
+    public static final String SKIP_PMD = "skipPMD";
     public static final String JAVA_EXT = ".java";
-    public static final String CLASS_EXT = ".class";
+    public static final String ANY_EXT = "*";
     public static final String SKIP_TEST_RUN = "skipTestRun";
+    public static final String SKIP_TESTS = "skipTests";
     public static final String MAIN = "main";
     public static final String TEST = "test";
-    public static final String JAVA = "java";
     public static final String RESOURCES_CHANGED = "resourcesChanged";
     public static final String UNICORN = "unicorn";
+    public static final String ANSI_YELLOW = "\u001B[43m";
+    public static final String ANSI_COLOR_RESET = "\u001B[0m";
+    public static final String SKIP_MAIN_SOURCE_COMPILE = "skipMainSourceCompile";
+    public static final String SKIP_TEST_SOURCE_COMPILE = "skipTestSourceCompile";
+    public static final String MAIN_CHECKSUM = "mainChecksum";
+    public static final String TEST_CHECKSUM = "testChecksum";
+    public static final String RESOURCE_CHECKSUM = "resourceChecksum";
+    public static final String MAIN_SOURCE_CHECKSUM = "mainSourceChecksum";
+    public static final String TEST_SOURCE_CHECKSUM = "testSourceChecksum";
+    public static final String GENERATED_SOURCE_CHECKSUM = "generatedSourceChecksum";
+    public static final String EMPTY_JAR = "emptyJAR";
+    public static final String JAR = "jar";
+    public static final String SHA1 = "sha1";
+    public static final String COLON = ":";
+    public static final String DOT = ".";
+    public static final String FULL_BUILD_DATA = "fullBuildData";
+    public static final String FULL_RESOURCE_BUILD_DATA = "fullResourceBuildData";
+    public static final String MODULE_BUILD_DATA = "moduleBuildData";
+    public static final String RESOURCE_BUILD_DATA = "resourceBuildData";
+    public static final String RESOURCE_ONLY = "resourceOnly";
+    public static final String TEST_RESOURCE_ONLY = "testResourceOnly";
+    public static final String INSTRUMENT_WITH_TEST_ONLY = "instrumentWithTestOnly";
+    public static final String RESOURCE_WITH_TEST_ONLY = "resourceWithTestOnly";
+    public static final String INSTRUMENT_ONLY = "instrumentOnly";
+    public static final String TEST_ONLY = "testOnly";
 }
diff --git a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/InitializationHelperMojo.java b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/InitializationHelperMojo.java
index cbf6f69..8b0ff0e 100644
--- a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/InitializationHelperMojo.java
+++ b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/InitializationHelperMojo.java
@@ -17,7 +17,9 @@
 package org.openecomp.sdc.onboarding;
 
 import static org.openecomp.sdc.onboarding.Constants.FORK_COUNT;
+import static org.openecomp.sdc.onboarding.Constants.FORK_MODE;
 import static org.openecomp.sdc.onboarding.Constants.JACOCO_SKIP;
+import static org.openecomp.sdc.onboarding.Constants.SKIP_PMD;
 import static org.openecomp.sdc.onboarding.Constants.UNICORN;
 
 import org.apache.maven.plugin.AbstractMojo;
@@ -29,29 +31,39 @@
 import org.apache.maven.plugins.annotations.ResolutionScope;
 import org.apache.maven.project.MavenProject;
 
-@Mojo(name = "init-helper", threadSafe = true, defaultPhase = LifecyclePhase.PRE_CLEAN,
-        requiresDependencyResolution = ResolutionScope.NONE)
+@Mojo(name = "init-helper", threadSafe = true, defaultPhase = LifecyclePhase.GENERATE_RESOURCES,
+        requiresDependencyResolution = ResolutionScope.TEST)
 public class InitializationHelperMojo extends AbstractMojo {
 
     @Parameter(defaultValue = "${project}", readonly = true)
     private MavenProject project;
+    @Parameter
+    private BuildState buildState;
+    @Parameter
+    private String excludePackaging;
 
     public void execute() throws MojoExecutionException, MojoFailureException {
 
+        if (project.getPackaging().equals(excludePackaging)) {
+            return;
+        }
+        project.getProperties().setProperty("skipGet", "false");
         if (System.getProperties().containsKey(JACOCO_SKIP) && Boolean.FALSE.equals(Boolean.valueOf(
                 System.getProperties().getProperty(JACOCO_SKIP)))) {
             project.getProperties().setProperty(FORK_COUNT, "1");
+            project.getProperties().setProperty(FORK_MODE, "once");
         } else {
             project.getProperties().setProperty(FORK_COUNT, "0");
+            project.getProperties().setProperty(FORK_MODE, "never");
         }
 
-        if (System.getProperties().containsKey(UNICORN)) {
-            project.getProperties().setProperty("classes", "classes/**/*.class");
-            project.getProperties().setProperty("testClasses", "test-classes/**/*.class");
-            project.getProperties().setProperty("mavenStatus", "maven-status/**");
-            project.getProperties().setProperty("pmd", "pmd/**");
-            project.getProperties().setProperty("customGeneratedSources", "generated-sources/custom/**");
+        project.getProperties().setProperty(SKIP_PMD, Boolean.TRUE.toString());
 
+        if (System.getProperties().containsKey(UNICORN)) {
+            buildState.init();
+        } else {
+            project.getProperties().setProperty("skipMainSourceCompile", "false");
+            project.getProperties().setProperty("skipTestSourceCompile", "false");
         }
 
     }
diff --git a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PostCompileHelperMojo.java b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PostCompileHelperMojo.java
index 9ab3735..04e0ca8 100644
--- a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PostCompileHelperMojo.java
+++ b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PostCompileHelperMojo.java
@@ -16,26 +16,18 @@
 
 package org.openecomp.sdc.onboarding;
 
-import static org.openecomp.sdc.onboarding.Constants.CLASS_EXT;
-import static org.openecomp.sdc.onboarding.Constants.JAVA_EXT;
-import static org.openecomp.sdc.onboarding.Constants.MAIN;
-import static org.openecomp.sdc.onboarding.Constants.RESOURCES_CHANGED;
-import static org.openecomp.sdc.onboarding.Constants.SKIP_TEST_RUN;
+import static org.openecomp.sdc.onboarding.Constants.INSTRUMENT_ONLY;
+import static org.openecomp.sdc.onboarding.Constants.INSTRUMENT_WITH_TEST_ONLY;
+import static org.openecomp.sdc.onboarding.Constants.RESOURCE_ONLY;
+import static org.openecomp.sdc.onboarding.Constants.RESOURCE_WITH_TEST_ONLY;
+import static org.openecomp.sdc.onboarding.Constants.SKIP_MAIN_SOURCE_COMPILE;
+import static org.openecomp.sdc.onboarding.Constants.SKIP_PMD;
+import static org.openecomp.sdc.onboarding.Constants.SKIP_TEST_SOURCE_COMPILE;
+import static org.openecomp.sdc.onboarding.Constants.TEST_ONLY;
+import static org.openecomp.sdc.onboarding.Constants.TEST_RESOURCE_ONLY;
 import static org.openecomp.sdc.onboarding.Constants.UNICORN;
 
 import java.io.File;
-import java.io.IOException;
-import java.io.UncheckedIOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-import org.apache.maven.artifact.Artifact;
 import org.apache.maven.plugin.AbstractMojo;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugins.annotations.LifecyclePhase;
@@ -44,7 +36,7 @@
 import org.apache.maven.plugins.annotations.ResolutionScope;
 import org.apache.maven.project.MavenProject;
 
-@Mojo(name = "post-compile-helper", threadSafe = true, defaultPhase = LifecyclePhase.PROCESS_TEST_CLASSES,
+@Mojo(name = "post-compile-helper", threadSafe = true, defaultPhase = LifecyclePhase.TEST_COMPILE,
         requiresDependencyResolution = ResolutionScope.TEST)
 public class PostCompileHelperMojo extends AbstractMojo {
 
@@ -53,89 +45,15 @@
     @Parameter(defaultValue = "${project.artifact.groupId}:${project.artifact.artifactId}")
     private String moduleCoordinates;
     @Parameter
-    private Long staleThreshold;
-    @Parameter
     private String excludePackaging;
     @Parameter
-    private List<String> excludeDependencies;
-    @Parameter
-    private File mainSourceLocation;
-    @Parameter
-    private File testSourceLocation;
-    @Parameter
-    private File mainCompiledLocation;
-    @Parameter
-    private File testCompiledLocation;
-    @Parameter
-    private File inputSourceFilesList;
-    @Parameter
-    private File inputTestFilesList;
-    @Parameter
     private BuildState buildState;
     @Parameter
     private File mainResourceLocation;
     @Parameter
     private File testResourceLocation;
-    @Parameter
-    private File compiledTestFilesList;
 
 
-    private File[] getCompiledClasses(File compiledFiles) {
-        if (!compiledFiles.exists()) {
-            return new File[0];
-        }
-        File[] list = null;
-        try {
-            list = Files.walk(Paths.get(compiledFiles.getAbsolutePath()))
-                        .filter(p -> p.toFile().getAbsolutePath().endsWith(CLASS_EXT)).map(p -> p.toFile())
-                        .sorted(this::compare).collect(Collectors.toList()).toArray(new File[0]);
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-        if (list == null || list.length == 0) {
-            return new File[0];
-        }
-        return list;
-    }
-
-    private int compare(File file1, File file2) {
-        if (file1.lastModified() > file2.lastModified()) {
-            return 1;
-        }
-        if (file1.lastModified() < file2.lastModified()) {
-            return -1;
-        }
-        return 0;
-    }
-
-    private File[] getStaleCompiledClasses(File[] compiledClasses, File javaSourceLocation) {
-        List<File> staleFiles = new ArrayList<>();
-        for (File file : compiledClasses) {
-            String classLocation = file.getAbsolutePath().replace(
-                    project.getBasedir().getAbsolutePath() + File.separator + "target" + File.separator, "");
-            String classLocationWithPackageOnly =
-                    classLocation.substring(classLocation.indexOf(File.separatorChar) + 1);
-            String sourceFilePath = javaSourceLocation.getAbsolutePath() + File.separator + classLocationWithPackageOnly
-                                                                                                    .replace(CLASS_EXT,
-                                                                                                            JAVA_EXT);
-            if (Paths.get(sourceFilePath).toFile().exists()) {
-                return staleFiles.toArray(new File[0]);
-            } else {
-                staleFiles.add(file);
-            }
-        }
-        return staleFiles.toArray(new File[0]);
-    }
-
-    private boolean deleteAll(File[] files) {
-        for (File file : files) {
-            if (!file.delete()) {
-                return false;
-            }
-        }
-        return true;
-    }
-
     public void execute() throws MojoExecutionException {
         if (!System.getProperties().containsKey(UNICORN)) {
             return;
@@ -143,93 +61,40 @@
         if (project.getPackaging().equals(excludePackaging)) {
             return;
         }
-        String moduleLocation = project.getBasedir().getAbsolutePath();
-
-        File[] mainClasses = getCompiledClasses(mainCompiledLocation);
-        processStaleClassesIfAny(mainClasses, mainSourceLocation, inputSourceFilesList);
-
-        File[] testClasses = getCompiledClasses(testCompiledLocation);
-        processStaleClassesIfAny(testClasses, testSourceLocation, inputTestFilesList);
-
-        if (mainClasses.length == 0 && testClasses.length == 0) {
-            return;
+        if (project.getProperties().containsKey(TEST_ONLY)) {
+            project.getProperties().setProperty(SKIP_MAIN_SOURCE_COMPILE, Boolean.TRUE.toString());
+            project.getProperties().remove(TEST_ONLY);
         }
-        buildState.addModuleBuildTime(project.getGroupId() + ":" + project.getArtifactId(),
-                mainClasses.length > 0 ? mainClasses[mainClasses.length - 1].lastModified() :
-                        testClasses.length > 0 ? testClasses[testClasses.length - 1].lastModified() : 0);
+        if (project.getProperties().containsKey(INSTRUMENT_ONLY)) {
+            project.getProperties().setProperty(SKIP_MAIN_SOURCE_COMPILE, Boolean.TRUE.toString());
+            project.getProperties().setProperty(SKIP_TEST_SOURCE_COMPILE, Boolean.TRUE.toString());
+            project.getProperties().remove(INSTRUMENT_ONLY);
+        }
+        if (project.getProperties().containsKey(INSTRUMENT_WITH_TEST_ONLY)) {
+            project.getProperties().setProperty(SKIP_MAIN_SOURCE_COMPILE, Boolean.TRUE.toString());
+            project.getProperties().remove(INSTRUMENT_WITH_TEST_ONLY);
+        }
+        if (project.getProperties().containsKey(RESOURCE_WITH_TEST_ONLY)) {
+            project.getProperties().setProperty(SKIP_MAIN_SOURCE_COMPILE, Boolean.TRUE.toString());
+            project.getProperties().remove(RESOURCE_WITH_TEST_ONLY);
+        }
+        if (project.getProperties().containsKey(RESOURCE_ONLY)) {
+            project.getProperties().setProperty(SKIP_MAIN_SOURCE_COMPILE, Boolean.TRUE.toString());
+            project.getProperties().setProperty(SKIP_TEST_SOURCE_COMPILE, Boolean.TRUE.toString());
+            project.getProperties().remove(RESOURCE_ONLY);
+        }
+        if (project.getProperties().containsKey(TEST_RESOURCE_ONLY)) {
+            project.getProperties().setProperty(SKIP_MAIN_SOURCE_COMPILE, Boolean.TRUE.toString());
+            project.getProperties().setProperty(SKIP_TEST_SOURCE_COMPILE, Boolean.TRUE.toString());
+            project.getProperties().remove(TEST_RESOURCE_ONLY);
+        }
+        if (!project.getProperties().containsKey(SKIP_MAIN_SOURCE_COMPILE)) {
+            buildState.addModuleBuildTime(moduleCoordinates, System.currentTimeMillis());
+            project.getProperties().setProperty(SKIP_PMD, Boolean.FALSE.toString());
+        }
+        if (!project.getProperties().containsKey(SKIP_TEST_SOURCE_COMPILE)) {
+            project.getProperties().setProperty(SKIP_PMD, Boolean.FALSE.toString());
+        }
         buildState.saveModuleBuildData(moduleCoordinates);
-        Map<String, Object> resourceBuildData = getCurrentResourceBuildData();
-        Map<String, Object> lastTimeResourceBuildData = buildState.readResourceBuildData();
-        boolean resourceDataSame = resourceBuildData.equals(lastTimeResourceBuildData);
-        if (!resourceDataSame) {
-            buildState.addResourceBuildData(moduleCoordinates, resourceBuildData);
-            project.getProperties().setProperty(SKIP_TEST_RUN, Boolean.FALSE.toString());
-        }
-        boolean resourceMainBuildDataSameWithPreviousBuild =
-                lastTimeResourceBuildData.get(MAIN) != null && resourceBuildData.get(MAIN)
-                                                                                .equals(lastTimeResourceBuildData
-                                                                                                .get(MAIN));
-        if (!resourceMainBuildDataSameWithPreviousBuild) {
-            project.getProperties().setProperty(RESOURCES_CHANGED, Boolean.TRUE.toString());
-        }
-        if (!project.getProperties().containsKey(SKIP_TEST_RUN)) {
-            if (compiledTestFilesList.exists()
-                        && compiledTestFilesList.lastModified() > System.currentTimeMillis() - staleThreshold) {
-                project.getProperties().setProperty(SKIP_TEST_RUN, Boolean.FALSE.toString());
-            }
-        }
-    }
-
-    private void processStaleClassesIfAny(File[] classes, File sourceLocation, File listFile)
-            throws MojoExecutionException {
-        if (classes.length > 0) {
-            List<File> list = new ArrayList<>(Arrays.asList(classes));
-            File[] staleClasses = null;
-            boolean allStale = listFile.isFile() && listFile.length() == 0;
-            if (allStale) {
-                staleClasses = classes;
-                listFile.delete();
-            } else {
-                list.removeIf(f -> f.lastModified() > classes[classes.length - 1].lastModified() - staleThreshold);
-                staleClasses = getStaleCompiledClasses(list.toArray(new File[0]), sourceLocation);
-            }
-            if (!deleteAll(staleClasses)) {
-                throw new MojoExecutionException(
-                        "****** Please remove 'target' directory manually under path " + project.getBasedir()
-                                                                                                .getAbsolutePath());
-            }
-        }
-    }
-
-    private Map<String, Object> getCurrentResourceBuildData() {
-        HashMap<String, Object> resourceBuildStateData = new HashMap<>();
-        try {
-            resourceBuildStateData.put("main", readResources(mainResourceLocation));
-            resourceBuildStateData.put("test", readResources(testResourceLocation));
-            resourceBuildStateData.put("dependency", getDependencies());
-        } catch (IOException ioException) {
-            throw new UncheckedIOException(ioException);
-        }
-        return resourceBuildStateData;
-    }
-
-    private Map<String, Long> readResources(File file) throws IOException {
-        Map<String, Long> resources = new HashMap<>();
-        if (file.exists()) {
-            List<Path> list = Files.walk(Paths.get(file.getAbsolutePath())).filter(Files::isRegularFile)
-                                   .collect(Collectors.toList());
-            for (Path path : list) {
-                resources.put(path.toFile().getAbsolutePath(), path.toFile().lastModified());
-            }
-        }
-        return resources;
-    }
-
-    private Map<String, String> getDependencies() {
-        Map<String, String> dependencies = new HashMap<>();
-        for (Artifact d : project.getArtifacts()) {
-            dependencies.put(d.getGroupId() + ":" + d.getArtifactId(), d.getVersion());
-        }
-        return dependencies;
     }
 }
diff --git a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PostSourceGeneratorMojo.java b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PostSourceGeneratorMojo.java
new file mode 100644
index 0000000..36e5f8a
--- /dev/null
+++ b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PostSourceGeneratorMojo.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;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.stream.Collectors;
+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.ResolutionScope;
+
+
+@Mojo(name = "post-source-generator-helper", threadSafe = true, defaultPhase = LifecyclePhase.GENERATE_RESOURCES,
+        requiresDependencyResolution = ResolutionScope.TEST)
+public class PostSourceGeneratorMojo extends PreCompileHelperMojo {
+
+    public void execute() throws MojoExecutionException, MojoFailureException {
+        if (isCodeGenerator()) {
+            super.execute();
+        }
+    }
+
+    //    @Override
+    void deleteAllClasses(File file) {
+        if (!file.exists()) {
+            return;
+        }
+        try {
+            List<File> list =
+                    Files.walk(Paths.get(file.getAbsolutePath())).filter(Files::isRegularFile).map(p -> p.toFile())
+                         .collect(Collectors.toList());
+            for (File f : list) {
+                f.delete();
+            }
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+
+    }
+}
diff --git a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PostTestRunHelperMojo.java b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PostTestRunHelperMojo.java
index 5b326f3..c2816db 100644
--- a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PostTestRunHelperMojo.java
+++ b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PostTestRunHelperMojo.java
@@ -16,6 +16,7 @@
 
 package org.openecomp.sdc.onboarding;
 
+import static org.openecomp.sdc.onboarding.Constants.SKIP_TESTS;
 import static org.openecomp.sdc.onboarding.Constants.SKIP_TEST_RUN;
 import static org.openecomp.sdc.onboarding.Constants.UNICORN;
 
@@ -49,11 +50,13 @@
         if (project.getPackaging().equals(excludePackaging)) {
             return;
         }
-        buildState.saveResourceBuildData(moduleCoordinates);
+
         if (project.getProperties().containsKey(SKIP_TEST_RUN) && !Boolean.valueOf(
                 project.getProperties().getProperty(SKIP_TEST_RUN))) {
-            if (!System.getProperties().containsKey("skipTests")) {
+            if (!System.getProperties().containsKey(SKIP_TESTS)) {
+                buildState.saveResourceBuildData(moduleCoordinates);
                 buildState.addResourceBuildTime(moduleCoordinates, System.currentTimeMillis());
+
             }
         }
 
diff --git a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PreCompileHelperMojo.java b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PreCompileHelperMojo.java
index faa3167..854ef7f 100644
--- a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PreCompileHelperMojo.java
+++ b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PreCompileHelperMojo.java
@@ -16,127 +16,417 @@
 
 package org.openecomp.sdc.onboarding;
 
+import static org.openecomp.sdc.onboarding.BuildHelper.getArtifactPathInLocalRepo;
+import static org.openecomp.sdc.onboarding.BuildHelper.getChecksum;
+import static org.openecomp.sdc.onboarding.BuildHelper.getSourceChecksum;
+import static org.openecomp.sdc.onboarding.BuildHelper.readState;
+import static org.openecomp.sdc.onboarding.Constants.ANY_EXT;
+import static org.openecomp.sdc.onboarding.Constants.COLON;
+import static org.openecomp.sdc.onboarding.Constants.DOT;
+import static org.openecomp.sdc.onboarding.Constants.EMPTY_JAR;
+import static org.openecomp.sdc.onboarding.Constants.GENERATED_SOURCE_CHECKSUM;
+import static org.openecomp.sdc.onboarding.Constants.INSTRUMENT_ONLY;
+import static org.openecomp.sdc.onboarding.Constants.INSTRUMENT_WITH_TEST_ONLY;
+import static org.openecomp.sdc.onboarding.Constants.JAR;
+import static org.openecomp.sdc.onboarding.Constants.JAVA_EXT;
 import static org.openecomp.sdc.onboarding.Constants.MAIN;
+import static org.openecomp.sdc.onboarding.Constants.MAIN_CHECKSUM;
+import static org.openecomp.sdc.onboarding.Constants.MAIN_SOURCE_CHECKSUM;
+import static org.openecomp.sdc.onboarding.Constants.RESOURCES_CHANGED;
+import static org.openecomp.sdc.onboarding.Constants.RESOURCE_CHECKSUM;
+import static org.openecomp.sdc.onboarding.Constants.RESOURCE_ONLY;
+import static org.openecomp.sdc.onboarding.Constants.RESOURCE_WITH_TEST_ONLY;
+import static org.openecomp.sdc.onboarding.Constants.SHA1;
+import static org.openecomp.sdc.onboarding.Constants.SKIP_MAIN_SOURCE_COMPILE;
+import static org.openecomp.sdc.onboarding.Constants.SKIP_PMD;
 import static org.openecomp.sdc.onboarding.Constants.SKIP_TEST_RUN;
+import static org.openecomp.sdc.onboarding.Constants.SKIP_TEST_SOURCE_COMPILE;
 import static org.openecomp.sdc.onboarding.Constants.TEST;
+import static org.openecomp.sdc.onboarding.Constants.TEST_CHECKSUM;
+import static org.openecomp.sdc.onboarding.Constants.TEST_ONLY;
+import static org.openecomp.sdc.onboarding.Constants.TEST_RESOURCE_ONLY;
+import static org.openecomp.sdc.onboarding.Constants.TEST_SOURCE_CHECKSUM;
 import static org.openecomp.sdc.onboarding.Constants.UNICORN;
 
 import java.io.File;
 import java.io.IOException;
 import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
 import org.apache.maven.artifact.Artifact;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.model.Plugin;
+import org.apache.maven.model.PluginExecution;
 import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.InvalidPluginDescriptorException;
+import org.apache.maven.plugin.MavenPluginManager;
 import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugin.MojoNotFoundException;
+import org.apache.maven.plugin.PluginDescriptorParsingException;
+import org.apache.maven.plugin.PluginResolutionException;
+import org.apache.maven.plugin.descriptor.MojoDescriptor;
+import org.apache.maven.plugins.annotations.Component;
 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 = "pre-compile-helper", threadSafe = true, defaultPhase = LifecyclePhase.GENERATE_SOURCES,
+
+@Mojo(name = "pre-compile-helper", threadSafe = true, defaultPhase = LifecyclePhase.GENERATE_RESOURCES,
         requiresDependencyResolution = ResolutionScope.TEST)
 public class PreCompileHelperMojo extends AbstractMojo {
 
-    @Parameter(defaultValue = "${project}", readonly = true)
+    @Parameter(defaultValue = "${project}")
     private MavenProject project;
     @Parameter(defaultValue = "${project.artifact.groupId}:${project.artifact.artifactId}")
     private String moduleCoordinates;
+    @Parameter(defaultValue = "${session}")
+    private MavenSession session;
     @Parameter
     private String excludePackaging;
     @Parameter
     private List<String> excludeDependencies;
     @Parameter
-    private File mainCompiledLocation;
-    @Parameter
-    private File testCompiledLocation;
-    @Parameter
-    private File inputSourceFilesList;
-    @Parameter
-    private File inputTestFilesList;
-    @Parameter
     private BuildState buildState;
+    @Parameter
+    private File mainSourceLocation;
+    @Parameter
+    private File testSourceLocation;
+    @Parameter
+    private File generatedSourceLocation;
+    @Component
+    private MavenPluginManager pluginManager;
+    @Parameter
+    private File mainResourceLocation;
+    @Parameter
+    private File testResourceLocation;
+    private Map<String, Object> resourceBuildData;
 
-    public void execute() throws MojoExecutionException {
-        if (!System.getProperties().containsKey(UNICORN)) {
-            return;
-        }
+    private static Map<String, String> checksumMap;
+
+    static {
+        checksumMap = readCurrentPMDState("pmd.dat");
+    }
+
+    public void execute() throws MojoExecutionException, MojoFailureException {
+
+        long mainChecksum = 0, testChecksum = 0, resourceChecksum = 0;
+        Optional<String> artifactPath;
+
         if (project.getPackaging().equals(excludePackaging)) {
             return;
         }
+        init();
+        project.getProperties()
+               .setProperty(MAIN_CHECKSUM, String.valueOf(mainChecksum = getChecksum(mainSourceLocation, JAVA_EXT)));
+        project.getProperties()
+               .setProperty(TEST_CHECKSUM, String.valueOf(testChecksum = getChecksum(testSourceLocation, JAVA_EXT)));
+        String checksum = mainChecksum + COLON + testChecksum;
+        if (!checksum.equals(checksumMap.get(moduleCoordinates)) || isPMDMandatory(project.getArtifacts())) {
+            project.getProperties().setProperty(SKIP_PMD, Boolean.FALSE.toString());
+            buildState.recordPMDRun(moduleCoordinates);
+        }
+        project.getProperties().setProperty(EMPTY_JAR, "");
+        if (!System.getProperties().containsKey(UNICORN)) {
+            return;
+        }
+
+        project.getProperties().setProperty(RESOURCE_CHECKSUM,
+                String.valueOf(resourceChecksum = getChecksum(mainResourceLocation, ANY_EXT)));
+        byte[] sourceChecksum = calculateChecksum(mainChecksum, resourceChecksum).getBytes();
+        boolean instrumented = isCurrentModuleInstrumented();
+        artifactPath = getArtifactPathInLocalRepo(session.getLocalRepository().getUrl(), project, sourceChecksum);
+
+        boolean isFirstBuild = buildState.getBuildTime(moduleCoordinates) == 0 || !artifactPath.isPresent();
 
         Map<String, Object> moduleBuildData = getCurrentModuleBuildData();
         Map<String, Object> lastTimeModuleBuildData = buildState.readModuleBuildData();
+        resourceBuildData = getCurrentResourceBuildData();
+        Map<String, Object> lastTimeResourceBuildData = buildState.readResourceBuildData();
 
-        boolean buildDataSameWithPreviousBuild = lastTimeModuleBuildData.get(MAIN) != null && moduleBuildData.get(MAIN)
-                                                                                                             .equals(lastTimeModuleBuildData
-                                                                                                                             .get(MAIN));
-        boolean isFirstBuild = buildState.getBuildTime(moduleCoordinates) == 0;
+        boolean buildDataSameWithPreviousBuild =
+                isBuildDataSameWithPreviousBuild(lastTimeModuleBuildData, moduleBuildData);
+        boolean resourceMainBuildDataSameWithPreviousBuild =
+                isResourceMainBuildDataSameWithPreviousBuild(lastTimeResourceBuildData);
 
-        if (isCompileNeeded(HashMap.class.cast(moduleBuildData.get(MAIN)).keySet(), isFirstBuild,
-                buildDataSameWithPreviousBuild)) {
-            try {
-                buildState.markModuleDirty(inputSourceFilesList);
-                buildState.markModuleDirty(inputTestFilesList);
-                project.getProperties().setProperty(SKIP_TEST_RUN, "false");
-            } catch (IOException e) {
-                throw new UncheckedIOException(e);
-            }
-        }
+        boolean mainToBeCompiled = isCompileNeeded(HashMap.class.cast(moduleBuildData.get(MAIN)).keySet(), isFirstBuild,
+                buildDataSameWithPreviousBuild);
 
-        if (!moduleBuildData.get(TEST).equals(lastTimeModuleBuildData.get(TEST))) {
-            try {
-                buildState.markModuleDirty(inputTestFilesList);
-                project.getProperties().setProperty(SKIP_TEST_RUN, Boolean.FALSE.toString());
-            } catch (IOException e) {
-                throw new UncheckedIOException(e);
-            }
-        }
+        boolean resourceDataSame = resourceBuildData.equals(lastTimeResourceBuildData);
 
-        if (!moduleBuildData.equals(lastTimeModuleBuildData)) {
+        boolean testToBeCompiled =
+                lastTimeModuleBuildData == null || !moduleBuildData.get(TEST).equals(lastTimeModuleBuildData.get(TEST));
+        setMainBuildAttribute(mainToBeCompiled, testToBeCompiled);
+        generateSignature(sourceChecksum);
+        setTestBuild(resourceDataSame, resourceMainBuildDataSameWithPreviousBuild, testToBeCompiled, mainToBeCompiled);
+        setInstrumentedBuild(testToBeCompiled, mainToBeCompiled, instrumented);
+
+        if (!moduleBuildData.equals(lastTimeModuleBuildData) || isFirstBuild) {
             buildState.addModuleBuildData(moduleCoordinates, moduleBuildData);
         }
+        setResourceBuild(resourceMainBuildDataSameWithPreviousBuild, mainToBeCompiled, testToBeCompiled);
+        setJarFlags(mainToBeCompiled, instrumented, !resourceMainBuildDataSameWithPreviousBuild);
+        setInstallFlags(mainToBeCompiled, instrumented, project.getPackaging(),
+                !resourceMainBuildDataSameWithPreviousBuild);
 
-        if (inputSourceFilesList.isFile() && inputSourceFilesList.length() == 0) {
-            if (!inputSourceFilesList.delete()) {
-                throw new MojoExecutionException(
-                        "****** Please remove 'target' directory manually under path " + project.getBasedir()
-                                                                                                .getAbsolutePath());
-            }
+        if (!mainToBeCompiled && !instrumented && JAR.equals(project.getPackaging())
+                    && resourceMainBuildDataSameWithPreviousBuild) {
+            project.getProperties().setProperty("artifactPathToCopy", artifactPath.orElse(null));
         }
-        if (inputTestFilesList.isFile() && inputTestFilesList.length() == 0) {
-            if (!inputTestFilesList.delete()) {
-                throw new MojoExecutionException(
-                        "****** Please remove 'target' directory manually under path " + project.getBasedir()
-                                                                                                .getAbsolutePath());
+    }
+
+    private void generateSignature(byte[] sourceChecksum) {
+        try {
+            Files.write(Paths.get(project.getBuild().getDirectory(), project.getBuild().getFinalName() + DOT + UNICORN),
+                    sourceChecksum, StandardOpenOption.CREATE);
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+
+    private String calculateChecksum(long mainChecksum, long resourceChecksum) throws MojoExecutionException {
+        try {
+            return getSourceChecksum(mainChecksum + COLON + resourceChecksum, SHA1);
+        } catch (NoSuchAlgorithmException e) {
+            throw new MojoExecutionException(e.getMessage(), e);
+        }
+    }
+
+    private boolean isResourceMainBuildDataSameWithPreviousBuild(Map<String, Object> lastTimeResourceBuildData) {
+        return lastTimeResourceBuildData != null && (lastTimeResourceBuildData.get(MAIN) != null && resourceBuildData
+                                                                                                            .get(MAIN)
+                                                                                                            .equals(lastTimeResourceBuildData
+                                                                                                                            .get(MAIN)));
+    }
+
+    private boolean isBuildDataSameWithPreviousBuild(Map<String, Object> lastTimeModuleBuildData,
+            Map<String, Object> moduleBuildData) {
+        return lastTimeModuleBuildData != null && (lastTimeModuleBuildData.get(MAIN) != null && moduleBuildData
+                                                                                                        .get(MAIN)
+                                                                                                        .equals(lastTimeModuleBuildData
+                                                                                                                        .get(MAIN)));
+    }
+
+    private void setInstrumentedBuild(boolean testToBeCompiled, boolean mainToBeCompiled, boolean instrumented) {
+        if (!testToBeCompiled && !mainToBeCompiled && instrumented) {
+            project.getProperties().setProperty(INSTRUMENT_ONLY, Boolean.TRUE.toString());
+            project.getProperties().remove(SKIP_MAIN_SOURCE_COMPILE);
+            project.getProperties().remove(SKIP_TEST_SOURCE_COMPILE);
+        }
+        if (testToBeCompiled && !mainToBeCompiled && instrumented) {
+            project.getProperties().setProperty(INSTRUMENT_WITH_TEST_ONLY, Boolean.TRUE.toString());
+            project.getProperties().remove(SKIP_MAIN_SOURCE_COMPILE);
+        }
+        if (instrumented) {
+            buildState.markTestsMandatoryModule(moduleCoordinates);
+            project.getProperties().setProperty(SKIP_TEST_RUN, Boolean.FALSE.toString());
+        }
+    }
+
+    private void setResourceBuild(boolean resourceMainBuildDataSameWithPreviousBuild, boolean mainToBeCompiled,
+            boolean testToBeCompiled) {
+        if (resourceMainBuildDataSameWithPreviousBuild) {
+            project.getProperties().setProperty("skipResourceCollection", Boolean.TRUE.toString());
+        } else {
+            project.getProperties().setProperty(RESOURCES_CHANGED, Boolean.TRUE.toString());
+        }
+        if (!resourceMainBuildDataSameWithPreviousBuild && !mainToBeCompiled) {
+            project.getProperties().remove(SKIP_MAIN_SOURCE_COMPILE);
+            if (!testToBeCompiled) {
+                project.getProperties().remove(SKIP_TEST_SOURCE_COMPILE);
+                project.getProperties().setProperty(RESOURCE_ONLY, Boolean.TRUE.toString());
+            } else {
+                project.getProperties().setProperty(RESOURCE_WITH_TEST_ONLY, Boolean.TRUE.toString());
             }
         }
     }
 
+    private void setTestBuild(boolean resourceDataSame, boolean resourceMainBuildDataSameWithPreviousBuild,
+            boolean testToBeCompiled, boolean mainToBeCompiled) {
+        if (!resourceDataSame) {
+            buildState.addResourceBuildData(moduleCoordinates, resourceBuildData);
+            project.getProperties().setProperty(SKIP_TEST_RUN, Boolean.FALSE.toString());
+            if (resourceMainBuildDataSameWithPreviousBuild && !testToBeCompiled && !mainToBeCompiled) {
+                project.getProperties().setProperty(TEST_RESOURCE_ONLY, Boolean.TRUE.toString());
+                project.getProperties().remove(SKIP_MAIN_SOURCE_COMPILE);
+                project.getProperties().remove(SKIP_TEST_SOURCE_COMPILE);
+            }
+        }
+    }
+
+    private void setMainBuildAttribute(boolean mainToBeCompiled, boolean testToBeCompiled) {
+        if (!mainToBeCompiled) {
+            project.getProperties().setProperty(SKIP_MAIN_SOURCE_COMPILE, Boolean.TRUE.toString());
+        }
+        if (testToBeCompiled && !mainToBeCompiled) {
+            project.getProperties().setProperty(TEST_ONLY, Boolean.TRUE.toString());
+            project.getProperties().remove(SKIP_MAIN_SOURCE_COMPILE);
+        }
+
+        if (mainToBeCompiled || testToBeCompiled) {
+            project.getProperties().setProperty(SKIP_TEST_RUN, Boolean.FALSE.toString());
+        } else {
+            project.getProperties().setProperty(SKIP_TEST_SOURCE_COMPILE, Boolean.TRUE.toString());
+        }
+    }
+
+    private void setJarFlags(boolean compile, boolean instrumented, boolean resourceChanged) {
+        if (compile || instrumented || resourceChanged) {
+            project.getProperties().setProperty(EMPTY_JAR, "");
+        } else {
+            project.getProperties().setProperty(EMPTY_JAR, "**/*");
+            project.getProperties().setProperty("mvnDsc", "false");
+        }
+    }
+
+    private void setInstallFlags(boolean compile, boolean instrumented, String packaging, boolean resourceChanged) {
+        if (!compile && !instrumented && !resourceChanged && JAR.equals(packaging)) {
+            project.getProperties().setProperty("skipInstall", Boolean.TRUE.toString());
+        }
+    }
+
     private boolean isCompileNeeded(Collection<String> dependencyCoordinates, boolean isFirstBuild,
-            boolean buildDataSame) {
+            boolean buildDataSame) throws MojoFailureException {
         return isFirstBuild || !buildDataSame || buildState.isCompileMust(moduleCoordinates, dependencyCoordinates);
     }
 
+    private boolean isCurrentModuleInstrumented() {
+        try {
+            return scanModuleFor(LifecyclePhase.PROCESS_CLASSES.id(), LifecyclePhase.PROCESS_TEST_CLASSES.id(),
+                    LifecyclePhase.COMPILE.id(), LifecyclePhase.TEST_COMPILE.id());
+        } catch (Exception e) {
+            return true;
+        }
+    }
+
+    boolean isCodeGenerator() {
+        try {
+            return scanModuleFor(LifecyclePhase.GENERATE_RESOURCES.id(), LifecyclePhase.GENERATE_SOURCES.id(),
+                    LifecyclePhase.GENERATE_TEST_RESOURCES.id(), LifecyclePhase.GENERATE_TEST_SOURCES.id());
+        } catch (Exception e) {
+            return true;
+        }
+    }
+
     private Map<String, Object> getCurrentModuleBuildData() {
         Map<String, Object> moduleBuildData = new HashMap<>();
         moduleBuildData.put(MAIN, new HashMap<String, String>());
         moduleBuildData.put(TEST, new HashMap<String, String>());
+        HashMap.class.cast(moduleBuildData.get(MAIN))
+                     .put(MAIN_SOURCE_CHECKSUM, project.getProperties().getProperty(MAIN_CHECKSUM));
+        HashMap.class.cast(moduleBuildData.get(TEST))
+                     .put(TEST_SOURCE_CHECKSUM, project.getProperties().getProperty(TEST_CHECKSUM));
+        if (isCodeGenerator()) {
+            HashMap.class.cast(moduleBuildData.get(MAIN))
+                         .put(GENERATED_SOURCE_CHECKSUM, getChecksum(generatedSourceLocation, JAVA_EXT));
+        }
         if (project.getArtifacts() == null || project.getArtifacts().isEmpty()) {
             return moduleBuildData;
         }
         for (Artifact dependency : project.getArtifacts()) {
+            String fileNme = dependency.getFile().getName();
             if (excludeDependencies.contains(dependency.getScope())) {
                 HashMap.class.cast(moduleBuildData.get(TEST))
-                             .put(dependency.getGroupId() + ":" + dependency.getArtifactId(), dependency.getVersion());
+                             .put(dependency.getGroupId() + COLON + dependency.getArtifactId(),
+                                     fileNme.endsWith(dependency.getVersion() + DOT + JAR) ? dependency.getVersion() :
+                                             fileNme);
                 continue;
             }
             HashMap.class.cast(moduleBuildData.get(MAIN))
-                         .put(dependency.getGroupId() + ":" + dependency.getArtifactId(), dependency.getVersion());
+                         .put(dependency.getGroupId() + COLON + dependency.getArtifactId(),
+                                 fileNme.endsWith(dependency.getVersion() + DOT + JAR) ? dependency.getVersion() :
+                                         fileNme);
         }
         return moduleBuildData;
     }
+
+    private static Map<String, String> readCurrentPMDState(String fileName) {
+        Optional<HashMap> val = readState(fileName, HashMap.class);
+        return val.orElseGet(HashMap::new);
+    }
+
+    private boolean isPMDMandatory(Set<Artifact> dependencies) {
+        for (Artifact artifact : dependencies) {
+            if (buildState.isPMDRun(artifact.getGroupId() + COLON + artifact.getArtifactId())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean scanModuleFor(String... types)
+            throws InvalidPluginDescriptorException, PluginResolutionException, MojoNotFoundException,
+                           PluginDescriptorParsingException {
+        for (Plugin plugin : project.getBuildPlugins()) {
+            if (!(plugin.getGroupId().equals("org.apache.maven.plugins") && plugin.getArtifactId().startsWith("maven"))
+                        && !plugin.getGroupId().startsWith("org.openecomp.sdc")) {
+                if (scanPlugin(plugin, types)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    private boolean scanPlugin(Plugin plugin, String... types)
+            throws InvalidPluginDescriptorException, PluginDescriptorParsingException, MojoNotFoundException,
+                           PluginResolutionException {
+        for (PluginExecution pluginExecution : plugin.getExecutions()) {
+            if (pluginExecution.getPhase() != null) {
+                if (Arrays.asList(types).contains(pluginExecution.getPhase())) {
+                    return true;
+                }
+            }
+            for (String goal : pluginExecution.getGoals()) {
+                MojoDescriptor md = pluginManager.getMojoDescriptor(plugin, goal, project.getRemotePluginRepositories(),
+                        session.getRepositorySession());
+                if (Arrays.asList(types).contains(md.getPhase())) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    private Map<String, Object> getCurrentResourceBuildData() {
+        HashMap<String, Object> resourceBuildStateData = new HashMap<>();
+        resourceBuildStateData.put(MAIN, project.getProperties().getProperty(RESOURCE_CHECKSUM));
+        resourceBuildStateData.put(TEST, getChecksum(testResourceLocation, ANY_EXT));
+        resourceBuildStateData.put("dependency", getDependencies().hashCode());
+        return resourceBuildStateData;
+    }
+
+    private Map<String, String> getDependencies() {
+        Map<String, String> dependencies = new HashMap<>();
+        for (Artifact d : project.getArtifacts()) {
+            dependencies.put(d.getGroupId() + COLON + d.getArtifactId(), d.getVersion());
+        }
+        return dependencies;
+    }
+
+    private void init() {
+        if (mainSourceLocation == null) {
+            mainSourceLocation = Paths.get(project.getBuild().getSourceDirectory()).toFile();
+        }
+        if (testSourceLocation == null) {
+            testSourceLocation = Paths.get(project.getBuild().getTestSourceDirectory()).toFile();
+        }
+        if (mainResourceLocation == null) {
+            mainResourceLocation = Paths.get(project.getBuild().getResources().get(0).getDirectory()).toFile();
+        }
+        if (testResourceLocation == null) {
+            testResourceLocation = Paths.get(project.getBuild().getTestResources().get(0).getDirectory()).toFile();
+        }
+    }
 }
diff --git a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PreTestCompileHelperMojo.java b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PreTestCompileHelperMojo.java
index e711cb0..a11d796 100644
--- a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PreTestCompileHelperMojo.java
+++ b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PreTestCompileHelperMojo.java
@@ -17,14 +17,13 @@
 package org.openecomp.sdc.onboarding;
 
 import static org.openecomp.sdc.onboarding.Constants.JACOCO_SKIP;
-import static org.openecomp.sdc.onboarding.Constants.SKIP_TEST_RUN;
 import static org.openecomp.sdc.onboarding.Constants.RESOURCES_CHANGED;
+import static org.openecomp.sdc.onboarding.Constants.SKIP_TESTS;
+import static org.openecomp.sdc.onboarding.Constants.SKIP_TEST_RUN;
 import static org.openecomp.sdc.onboarding.Constants.UNICORN;
 
-import java.io.File;
-import java.io.IOException;
-import java.io.UncheckedIOException;
-import java.util.stream.Collectors;
+import java.util.List;
+import org.apache.maven.model.Plugin;
 import org.apache.maven.plugin.AbstractMojo;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.MojoFailureException;
@@ -33,23 +32,20 @@
 import org.apache.maven.plugins.annotations.Parameter;
 import org.apache.maven.plugins.annotations.ResolutionScope;
 import org.apache.maven.project.MavenProject;
+import org.codehaus.plexus.util.xml.Xpp3Dom;
 
-@Mojo(name = "pre-test-compile-helper", threadSafe = true, defaultPhase = LifecyclePhase.GENERATE_TEST_RESOURCES,
+@Mojo(name = "pre-test-compile-helper", threadSafe = true, defaultPhase = LifecyclePhase.PROCESS_TEST_CLASSES,
         requiresDependencyResolution = ResolutionScope.TEST)
 public class PreTestCompileHelperMojo extends AbstractMojo {
 
     @Parameter
-    private File compiledFilesList;
-    @Parameter
-    private Long staleThreshold;
-    @Parameter
-    private File inputTestFilesList;
-    @Parameter
     private BuildState buildState;
     @Parameter(defaultValue = "${project}", readonly = true)
     private MavenProject project;
     @Parameter(defaultValue = "${project.artifact.groupId}:${project.artifact.artifactId}")
     private String moduleCoordinates;
+    @Parameter(defaultValue = "${project.buildPlugins}", readonly = true)
+    private List<Plugin> plugins;
     @Parameter
     private String excludePackaging;
 
@@ -61,25 +57,17 @@
         if (project.getPackaging().equals(excludePackaging)) {
             return;
         }
-        if (compiledFilesList.exists()
-                    && compiledFilesList.lastModified() > System.currentTimeMillis() - staleThreshold) {
-            try {
-                buildState.markModuleDirty(inputTestFilesList);
-                project.getProperties().setProperty(SKIP_TEST_RUN, Boolean.FALSE.toString());
-            } catch (IOException e) {
-                throw new UncheckedIOException(e);
-            }
+        if (buildState.isTestExecutionMandatory()) {
+            project.getProperties().setProperty(SKIP_TEST_RUN, Boolean.FALSE.toString());
         }
-        boolean isTestMust = buildState.isTestMust(moduleCoordinates,
-                project.getDependencies().stream().map(d -> d.getGroupId() + ":" + d.getArtifactId())
-                       .collect(Collectors.toList()));
+        boolean isTestMust = buildState.isTestMust(moduleCoordinates);
         if (isTestMust) {
             project.getProperties().setProperty(RESOURCES_CHANGED, Boolean.TRUE.toString());
             if (!project.getProperties().containsKey(SKIP_TEST_RUN)) {
                 project.getProperties().setProperty(SKIP_TEST_RUN, Boolean.FALSE.toString());
             }
         }
-        if (!project.getProperties().containsKey(SKIP_TEST_RUN)) {
+        if (!project.getProperties().containsKey(SKIP_TEST_RUN) || isTestSkippedExplicitly()) {
             project.getProperties().setProperty(SKIP_TEST_RUN, Boolean.TRUE.toString());
         }
         if (System.getProperties().containsKey(JACOCO_SKIP) && Boolean.FALSE.equals(Boolean.valueOf(
@@ -87,4 +75,17 @@
             project.getProperties().setProperty(SKIP_TEST_RUN, Boolean.FALSE.toString());
         }
     }
+
+
+    private boolean isTestSkippedExplicitly() {
+        for (Plugin p : plugins) {
+            if ("org.apache.maven.plugins:maven-surefire-plugin".equals(p.getKey())) {
+                Xpp3Dom dom = Xpp3Dom.class.cast(p.getConfiguration());
+                if (dom.getChild(SKIP_TESTS) != null) {
+                    return Boolean.TRUE.equals(Boolean.valueOf(dom.getValue()));
+                }
+            }
+        }
+        return false;
+    }
 }
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>