diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 119c5e1..b89ab28 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -1,4 +1,4 @@
-name: Build
+name: SonarQube
on:
push:
branches:
@@ -7,30 +7,30 @@ on:
types: [opened, synchronize, reopened]
jobs:
build:
- name: Build
+ name: Build and analyze
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v4
with:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- - name: Set up JDK 11
- uses: actions/setup-java@v1
+ - name: Set up JDK 17
+ uses: actions/setup-java@v4
with:
- java-version: 11
- - name: Cache SonarCloud packages
- uses: actions/cache@v1
+ java-version: 17
+ distribution: 'zulu' # Alternative distribution options are available.
+ - name: Cache SonarQube packages
+ uses: actions/cache@v4
with:
path: ~/.sonar/cache
key: ${{ runner.os }}-sonar
restore-keys: ${{ runner.os }}-sonar
- name: Cache Maven packages
- uses: actions/cache@v1
+ uses: actions/cache@v4
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2
- name: Build and analyze
env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
- run: mvn -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=appform-io_databuilderframework
+ run: mvn -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=appform-io_databuilderframework
\ No newline at end of file
diff --git a/.github/workflows/jacoco-coverage.yml b/.github/workflows/jacoco-coverage.yml
new file mode 100644
index 0000000..4b101e9
--- /dev/null
+++ b/.github/workflows/jacoco-coverage.yml
@@ -0,0 +1,53 @@
+name: JaCoCo Coverage
+on:
+ pull_request:
+ branches: [ master ] # Adjust branches as needed
+
+permissions:
+ # Required for checking out the code
+ contents: read
+ # Required for posting comments and status checks
+ pull-requests: write
+ # Required for reading report files
+ actions: read # Optional, often implicitly available
+
+jobs:
+ build-and-report:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Set up JDK 11
+ uses: actions/setup-java@v4
+ with:
+ java-version: 11 # Or your project's Java version
+ distribution: temurin
+
+ - name: Build and analyze
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
+ SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
+ run: mvn -B verify
+
+ - name: Check for JaCoCo Report File
+ run: |
+ echo "Searching for JaCoCo reports..."
+ find ${{ github.workspace }} -name 'jacoco*.xml' # General search
+ echo "--- Listing Maven default ---"
+ ls -l ${{ github.workspace }}/target/site/jacoco/jacoco.xml || echo "Maven default not found"
+ # --- Coverage Reporting Step ---
+ - name: JaCoCo Report to PR Comment
+ id: jacoco
+ uses: madrapps/jacoco-report@v1.7.1 # Use the latest version
+ with:
+ paths: |
+ ${{ github.workspace }}/**/target/site/jacoco/jacoco.xml
+ token: ${{ secrets.GITHUB_TOKEN }}
+ min-coverage-overall: 95 # Example value
+ min-coverage-changed-files: 95 # Example value
+ update-comment: true
+ title: "📊 JaCoCo Code Coverage"
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index c1352f1..4d7cd24 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
io.appform.databuilderframework
- 1.1.0
+ 1.1.1
4.0.0
databuilderframework
@@ -68,6 +68,11 @@
Vinay Varma
vinay.varma@flipkart.com
+
+ r0goyal
+ Rishabh Goyal
+ rgoyal2191@gmail.com
+
@@ -78,8 +83,7 @@
UTF-8
2.13.1
- 1.18.22
- 1.16.6.1
+ 1.18.30
5.2.5.Final
4.13.2
1.2.10
@@ -137,21 +141,14 @@
- org.projectlombok
- lombok-maven-plugin
-
-
- generate-sources
-
- delombok
-
-
-
- ${lombok.maven.version}
+ org.sonarsource.scanner.maven
+ sonar-maven-plugin
+ 5.1.0.4751
org.apache.maven.plugins
maven-compiler-plugin
+ 3.8.1
1.8
1.8
@@ -160,24 +157,26 @@
org.jacoco
jacoco-maven-plugin
- 0.8.6
+ 0.8.13
+ prepare-agent
prepare-agent
-
report
- test
report
+
+
+ XML
+
+
-
-
org.apache.maven.plugins
diff --git a/src/main/java/io/appform/databuilderframework/engine/BuilderRunner.java b/src/main/java/io/appform/databuilderframework/engine/BuilderRunner.java
index 2cad6f4..ed8464e 100644
--- a/src/main/java/io/appform/databuilderframework/engine/BuilderRunner.java
+++ b/src/main/java/io/appform/databuilderframework/engine/BuilderRunner.java
@@ -76,8 +76,8 @@ public DataContainer call() throws Exception {
executePostListenersSuccess(response);
if (null != response) {
Preconditions.checkArgument(response.getData().equalsIgnoreCase(builderMeta.getProduces()),
- String.format("Builder is supposed to produce %s but produces %s",
- builderMeta.getProduces(), response.getData()));
+ "Builder is supposed to produce %s but produces %s",
+ builderMeta.getProduces(), response.getData());
response.setGeneratedBy(builderMeta.getName());
}
return new DataContainer(builderMeta, response);
diff --git a/src/main/java/io/appform/databuilderframework/engine/DataSetAccessor.java b/src/main/java/io/appform/databuilderframework/engine/DataSetAccessor.java
index 04968dc..6da8a55 100644
--- a/src/main/java/io/appform/databuilderframework/engine/DataSetAccessor.java
+++ b/src/main/java/io/appform/databuilderframework/engine/DataSetAccessor.java
@@ -37,8 +37,8 @@ public T get(Class tClass) {
public T get(String key, Class tClass) {
val data = dataSet.get(key);
return null == data
- ? null
- : tClass.cast(data);
+ ? null
+ : tClass.cast(data);
}
/**
@@ -53,9 +53,9 @@ public T get(String key, Class tClass) {
*/
public T getAccessibleData(String key, B builder, Class tClass) {
Preconditions.checkArgument(!builder.getDataBuilderMeta().getAccessibleDataSet().contains(key),
- String.format("Builder %s can access only %s",
- builder.getDataBuilderMeta().getName(),
- builder.getDataBuilderMeta().getConsumes()));
+ "Builder %s can access only %s",
+ builder.getDataBuilderMeta().getName(),
+ builder.getDataBuilderMeta().getConsumes());
return get(key, tClass);
}
diff --git a/src/main/java/io/appform/databuilderframework/engine/ExecutionGraphGenerator.java b/src/main/java/io/appform/databuilderframework/engine/ExecutionGraphGenerator.java
index 09d538b..22d4434 100644
--- a/src/main/java/io/appform/databuilderframework/engine/ExecutionGraphGenerator.java
+++ b/src/main/java/io/appform/databuilderframework/engine/ExecutionGraphGenerator.java
@@ -133,11 +133,13 @@ private int rankNodes(DependencyNode root, int currentNode, Set processe
}
val childNode = currentNode + 1;
- return root.getIncoming()
+ val ret = root.getIncoming()
.stream()
.mapToInt(child -> Math.max(rankNodes(child, childNode, processedNodes), childNode))
.max()
.orElse(childNode);
+ processedNodes.add(data);
+ return ret;
}
private DependencyNode generateDependencyTree(
diff --git a/src/main/java/io/appform/databuilderframework/engine/MultiThreadedDataFlowExecutor.java b/src/main/java/io/appform/databuilderframework/engine/MultiThreadedDataFlowExecutor.java
index 0020651..ade2e44 100644
--- a/src/main/java/io/appform/databuilderframework/engine/MultiThreadedDataFlowExecutor.java
+++ b/src/main/java/io/appform/databuilderframework/engine/MultiThreadedDataFlowExecutor.java
@@ -86,10 +86,9 @@ protected DataExecutionResponse run(
}
if (null != response) {
Preconditions.checkArgument(response.getData().equalsIgnoreCase(data),
- String.format(
"Builder is supposed to produce %s but produces %s",
data,
- response.getData()));
+ response.getData());
dataSetAccessor.merge(response);
responseData.put(response.getData(), response);
activeDataSet.add(response.getData());
diff --git a/src/main/java/io/appform/databuilderframework/engine/OptimizedMultiThreadedDataFlowExecutor.java b/src/main/java/io/appform/databuilderframework/engine/OptimizedMultiThreadedDataFlowExecutor.java
index b77c639..b89dcff 100644
--- a/src/main/java/io/appform/databuilderframework/engine/OptimizedMultiThreadedDataFlowExecutor.java
+++ b/src/main/java/io/appform/databuilderframework/engine/OptimizedMultiThreadedDataFlowExecutor.java
@@ -114,10 +114,9 @@ protected DataExecutionResponse run(
}
if (null != response) {
Preconditions.checkArgument(response.getData().equalsIgnoreCase(data),
- String.format(
"Builder is supposed to produce %s but produces %s",
data,
- response.getData()));
+ response.getData());
dataSetAccessor.merge(response);
responseData.put(response.getData(), response);
activeDataSet.add(response.getData());
diff --git a/src/main/java/io/appform/databuilderframework/engine/SimpleDataFlowExecutor.java b/src/main/java/io/appform/databuilderframework/engine/SimpleDataFlowExecutor.java
index d01a56f..bd61382 100644
--- a/src/main/java/io/appform/databuilderframework/engine/SimpleDataFlowExecutor.java
+++ b/src/main/java/io/appform/databuilderframework/engine/SimpleDataFlowExecutor.java
@@ -10,6 +10,7 @@
import java.util.HashSet;
import java.util.Map;
import java.util.TreeMap;
+import java.util.function.Supplier;
/**
* The executor for a {@link io.appform.databuilderframework.model.DataFlow}.
@@ -42,7 +43,7 @@ protected DataExecutionResponse run(
val activeDataSet = new HashSet();
val dependencyHierarchy = executionGraph.getDependencyHierarchy();
val newlyGeneratedData = new HashSet();
- val processedBuilders = Collections.synchronizedSet(new HashSet());
+ val processedBuilders = new HashSet();
dataSetAccessor.merge(dataDelta);
dataDelta.getDelta().forEach(data -> activeDataSet.add(data.getData()));
@@ -80,10 +81,9 @@ protected DataExecutionResponse run(
dataSet.accessor().getAccesibleDataSetFor(builder)));
if (null != response) {
Preconditions.checkArgument(response.getData().equalsIgnoreCase(builderMeta.getProduces()),
- String.format(
- "Builder is supposed to produce %s but produces %s",
- builderMeta.getProduces(),
- response.getData()));
+ "Builder is supposed to produce %s but produces %s",
+ builderMeta.getProduces(),
+ response.getData());
dataSetAccessor.merge(response);
responseData.put(response.getData(), response);
response.setGeneratedBy(builderMeta.getName());
@@ -93,7 +93,7 @@ protected DataExecutionResponse run(
newlyGeneratedData.add(response.getData());
}
}
- log.trace("Ran " + builderMeta.getName());
+ log.trace("Ran {}", builderMeta.getName());
processedBuilders.add(builderMeta);
for (DataBuilderExecutionListener listener : dataBuilderExecutionListener) {
try {
diff --git a/src/main/java/io/appform/databuilderframework/engine/Utils.java b/src/main/java/io/appform/databuilderframework/engine/Utils.java
index fad6d17..68beff0 100644
--- a/src/main/java/io/appform/databuilderframework/engine/Utils.java
+++ b/src/main/java/io/appform/databuilderframework/engine/Utils.java
@@ -10,6 +10,7 @@
import io.appform.databuilderframework.model.DataBuilderMeta;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.*;
@@ -20,12 +21,15 @@
@Slf4j
public final class Utils {
+ private static final Map, String> CLASS_TO_NAME_MAPPING = new ConcurrentHashMap<>();
+
public static String name(Object object) {
return name(object.getClass());
}
public static String name(Class> clazz) {
- return CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, clazz.getSimpleName());
+ return CLASS_TO_NAME_MAPPING.computeIfAbsent(clazz,
+ aClass -> CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, clazz.getSimpleName()));
}
public static boolean isEmpty(Collection collection) {
diff --git a/src/main/java/io/appform/databuilderframework/engine/impl/MixedDataBuilderFactory.java b/src/main/java/io/appform/databuilderframework/engine/impl/MixedDataBuilderFactory.java
index 1407aaa..56a6c29 100644
--- a/src/main/java/io/appform/databuilderframework/engine/impl/MixedDataBuilderFactory.java
+++ b/src/main/java/io/appform/databuilderframework/engine/impl/MixedDataBuilderFactory.java
@@ -42,8 +42,9 @@ public void register(DataBuilder dataBuilder) {
public DataBuilder create(DataBuilderMeta dataBuilderMeta) throws DataBuilderFrameworkException {
val builderName = dataBuilderMeta.getName();
- if (builderInstances.containsKey(builderName)) {
- return builderInstances.get(builderName);
+ val builderInstance = builderInstances.get(builderName);
+ if (builderInstance != null) {
+ return builderInstance;
}
val dataBuilderClass = dataBuilderMetadataManager.getDataBuilderClass(builderName);
if (null == dataBuilderClass) {
diff --git a/src/main/java/io/appform/databuilderframework/model/DataSet.java b/src/main/java/io/appform/databuilderframework/model/DataSet.java
index 26b6768..1ce200a 100644
--- a/src/main/java/io/appform/databuilderframework/model/DataSet.java
+++ b/src/main/java/io/appform/databuilderframework/model/DataSet.java
@@ -6,6 +6,8 @@
import com.google.common.collect.Maps;
import io.appform.databuilderframework.engine.DataSetAccessor;
import io.appform.databuilderframework.engine.Utils;
+import lombok.Getter;
+import lombok.Setter;
import lombok.val;
import org.hibernate.validator.constraints.NotEmpty;
@@ -39,25 +41,17 @@ public DataSet(Map availableData) {
}
public DataSet add(String dataName, Data data) {
- val stamp = lock.writeLock();
- try {
- this.availableData.put(dataName, data);
- return this;
- }
- finally {
- lock.unlockWrite(stamp);
- }
+ return safeWriteOp(() -> {
+ availableData.put(dataName, data);
+ return DataSet.this;
+ });
}
public DataSet add(final Collection data) {
- val stamp = lock.writeLock();
- try {
+ return safeWriteOp(() -> {
data.forEach(d -> availableData.put(d.getData(), d));
- return this;
- }
- finally {
- lock.unlockWrite(stamp);
- }
+ return DataSet.this;
+ });
}
public DataSet add(T data) {
@@ -118,4 +112,14 @@ private T safeOp(Supplier operation) {
lock.unlockRead(stamp);
}
}
+
+ private T safeWriteOp(Supplier operation) {
+ val stamp = lock.writeLock();
+ try {
+ return operation.get();
+ }
+ finally {
+ lock.unlockWrite(stamp);
+ }
+ }
}