From ad523fdf9ed7170afaecd8ddbe73caa59b0ed3e4 Mon Sep 17 00:00:00 2001 From: Rishabh Goyal Date: Tue, 15 Apr 2025 00:32:39 +0530 Subject: [PATCH 1/7] Added an optimistic version of safeOp(). Only to be used for suppliers where suppliers don't have side effects --- .../databuilderframework/model/DataSet.java | 37 +++++++++++++++---- .../controller/HomePageControllerTest.java | 2 +- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/main/java/io/appform/databuilderframework/model/DataSet.java b/src/main/java/io/appform/databuilderframework/model/DataSet.java index 26b6768..f9fcdbb 100644 --- a/src/main/java/io/appform/databuilderframework/model/DataSet.java +++ b/src/main/java/io/appform/databuilderframework/model/DataSet.java @@ -10,7 +10,9 @@ import org.hibernate.validator.constraints.NotEmpty; import javax.validation.constraints.NotNull; -import java.util.*; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.StampedLock; import java.util.function.Supplier; @@ -43,8 +45,7 @@ public DataSet add(String dataName, Data data) { try { this.availableData.put(dataName, data); return this; - } - finally { + } finally { lock.unlockWrite(stamp); } } @@ -54,8 +55,7 @@ public DataSet add(final Collection data) { try { data.forEach(d -> availableData.put(d.getData(), d)); return this; - } - finally { + } finally { lock.unlockWrite(stamp); } } @@ -68,21 +68,28 @@ public Map filter(final Collection requiredKeys) { if (null == requiredKeys || requiredKeys.isEmpty()) { return Collections.emptyMap(); } - return safeOp(() -> Maps.filterKeys(Utils.sanitize(availableData), Predicates.in(requiredKeys))); + return safeOpOptimistic(() -> Maps.filterKeys(Utils.sanitize(availableData), Predicates.in(requiredKeys))); } public Data get(final String name) { if (Strings.isNullOrEmpty(name)) { return null; } - return safeOp(() -> availableData.get(name)); + return availableData.get(name); } public boolean containsAll(final Collection requiredKeys) { if (null == requiredKeys || requiredKeys.isEmpty()) { return false; } - return safeOp(() -> availableData.keySet().containsAll(requiredKeys)); + return safeOpOptimistic(() -> { + for (String data : requiredKeys) { + if (!availableData.containsKey(data)) { + return false; + } + } + return true; + }); } public void copyInto(final Map outMap, Collection excludedKeys) { @@ -118,4 +125,18 @@ private T safeOp(Supplier operation) { lock.unlockRead(stamp); } } + + private T safeOpOptimistic(Supplier operation) { + val stamp = lock.tryOptimisticRead(); + // This means a writeLock is already present, fallback to full readLock() + if (stamp == 0) { + return safeOp(operation); + } + T output = operation.get(); + if (!lock.validate(stamp)) { + return safeOp(operation); + } else { + return output; + } + } } diff --git a/src/test/java/examples/bloghomepagebuilder/controller/HomePageControllerTest.java b/src/test/java/examples/bloghomepagebuilder/controller/HomePageControllerTest.java index dda7bd5..04214ee 100644 --- a/src/test/java/examples/bloghomepagebuilder/controller/HomePageControllerTest.java +++ b/src/test/java/examples/bloghomepagebuilder/controller/HomePageControllerTest.java @@ -52,7 +52,7 @@ public void testHomePageMTOpt() throws Exception { private void runHomePageTest(DataFlowExecutor executor) throws Exception { val request = new HomePageRequest("2321312312", "2323454", "Blah".getBytes()); val stopwatch = Stopwatch.createStarted(); - for(long i = 0; i < 100_000; i++) { + for(long i = 0; i < 10000_000; i++) { HomePageResponse response = executor.run(homePageDataFlow, request).get(HomePageResponse.class); Assert.assertNotNull(response); //System.out.println(new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(response)); From 6055291060b5a7ee3462afddfb1dc7d343b922bb Mon Sep 17 00:00:00 2001 From: Rishabh Goyal Date: Tue, 15 Apr 2025 02:12:39 +0530 Subject: [PATCH 2/7] Added concept of data set view --- .../engine/DataBuilderContext.java | 22 ------ .../engine/DataSetAccessor.java | 13 ++-- .../engine/SimpleDataFlowExecutor.java | 7 +- .../engine/impl/MixedDataBuilderFactory.java | 5 +- .../model/DataBuilderMeta.java | 19 +++-- .../databuilderframework/model/DataSet.java | 11 +-- .../model/DataSetView.java | 72 +++++++++++++++++++ 7 files changed, 100 insertions(+), 49 deletions(-) create mode 100644 src/main/java/io/appform/databuilderframework/model/DataSetView.java diff --git a/src/main/java/io/appform/databuilderframework/engine/DataBuilderContext.java b/src/main/java/io/appform/databuilderframework/engine/DataBuilderContext.java index 68cad79..a781ddc 100644 --- a/src/main/java/io/appform/databuilderframework/engine/DataBuilderContext.java +++ b/src/main/java/io/appform/databuilderframework/engine/DataBuilderContext.java @@ -33,24 +33,6 @@ public DataBuilderContext() { this.contextData = contextData; } - /** - * Get only the accessible data for this builder. - * - * @param builder The builder that wants to access this data. - * @return A dataset that contains only the data accessible to the builder. - * @deprecated This method will be removed in the near future. Do not use this in newer projects. - * Reasoning: This is redundant given the set sent to a builder is already filtered - */ - @Deprecated - public DataSet getDataSet(DataBuilder builder) { - Preconditions.checkNotNull(builder.getDataBuilderMeta(), "No metadata present in this builder"); - val allowed = Utils.sanitize(builder.getDataBuilderMeta().getAccessibleDataSet()); - if (allowed.isEmpty()) { - return new DataSet(Collections.emptyMap()); - } - return new DataSet(dataSet.filter(allowed)); - } - /** * Access the data set. Ideally a builder should only access data as declared. * @@ -60,10 +42,6 @@ public DataSet getDataSet() { return dataSet; } - public void setDataSet(DataSet dataSet) { - this.dataSet = dataSet; - } - /** * Some data to be saved in the context. This data is read-only from inside the builder. * diff --git a/src/main/java/io/appform/databuilderframework/engine/DataSetAccessor.java b/src/main/java/io/appform/databuilderframework/engine/DataSetAccessor.java index 04968dc..f817914 100644 --- a/src/main/java/io/appform/databuilderframework/engine/DataSetAccessor.java +++ b/src/main/java/io/appform/databuilderframework/engine/DataSetAccessor.java @@ -4,6 +4,7 @@ import io.appform.databuilderframework.model.Data; import io.appform.databuilderframework.model.DataDelta; import io.appform.databuilderframework.model.DataSet; +import io.appform.databuilderframework.model.DataSetView; import lombok.val; import java.util.Collections; @@ -37,8 +38,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 +54,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())); + String.format("Builder %s can access only %s", + builder.getDataBuilderMeta().getName(), + builder.getDataBuilderMeta().getConsumes())); return get(key, tClass); } @@ -66,7 +67,7 @@ public T getAccessibleData(String key, B * @return */ public DataSet getAccesibleDataSetFor(DataBuilder builder) { - return new DataSet(dataSet.filter(builder.getDataBuilderMeta().getAccessibleDataSet())); + return new DataSetView(dataSet, builder.getDataBuilderMeta().getAccessibleDataSet()); } /** diff --git a/src/main/java/io/appform/databuilderframework/engine/SimpleDataFlowExecutor.java b/src/main/java/io/appform/databuilderframework/engine/SimpleDataFlowExecutor.java index 6c83f97..ab5b833 100644 --- a/src/main/java/io/appform/databuilderframework/engine/SimpleDataFlowExecutor.java +++ b/src/main/java/io/appform/databuilderframework/engine/SimpleDataFlowExecutor.java @@ -8,6 +8,7 @@ import java.util.Collections; import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.Map; import java.util.TreeMap; import java.util.function.Supplier; @@ -38,12 +39,12 @@ protected DataExecutionResponse run( DataBuilderFactory builderFactory) throws DataBuilderFrameworkException, DataValidationException { val executionGraph = dataFlow.getExecutionGraph(); val dataSet = dataFlowInstance.getDataSet().accessor().copy(); //Create own copy to work with - val dataSetAccessor = DataSet.accessor(dataSet); - val responseData = new TreeMap(); + val dataSetAccessor = dataSet.accessor(); + val responseData = new LinkedHashMap(); 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())); 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/DataBuilderMeta.java b/src/main/java/io/appform/databuilderframework/model/DataBuilderMeta.java index 39145b4..5ae60a9 100644 --- a/src/main/java/io/appform/databuilderframework/model/DataBuilderMeta.java +++ b/src/main/java/io/appform/databuilderframework/model/DataBuilderMeta.java @@ -5,6 +5,7 @@ import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; import lombok.Builder; +import lombok.Getter; import org.hibernate.validator.constraints.NotEmpty; import javax.validation.constraints.NotNull; @@ -45,8 +46,8 @@ public class DataBuilderMeta implements Comparable, Serializabl private String name; private int rank; - - + + /** * Set of {@link io.appform.databuilderframework.model.Data} this {@link io.appform.databuilderframework.engine.DataBuilder} * can consume optionally, i.e. this {@link io.appform.databuilderframework.model.Data} @@ -65,21 +66,25 @@ public class DataBuilderMeta implements Comparable, Serializabl @JsonProperty private Set access; + @Getter + private Set accessibleDataSet; + public DataBuilderMeta(Set consumes, String produces, String name) { this(consumes, produces, name, Collections.emptySet(), Collections.emptySet()); } @Builder - public DataBuilderMeta(Set consumes, String produces, String name, + public DataBuilderMeta(Set consumes, String produces, String name, Set optionals, Set access) { this.consumes = consumes; this.produces = produces; this.name = name; this.optionals = optionals; this.access = access; + this.accessibleDataSet = constructAccessibleDataSet(); } - + public DataBuilderMeta() { } @@ -91,9 +96,9 @@ public Set getEffectiveConsumes(){ return consumes; } } - + @JsonIgnore - public Set getAccessibleDataSet(){ + private Set constructAccessibleDataSet() { Set output = consumes; if(optionals != null && !optionals.isEmpty()){ output = Sets.union(optionals, output); @@ -103,7 +108,7 @@ public Set getAccessibleDataSet(){ } return output; } - + public int compareTo(DataBuilderMeta rhs) { return name.compareTo(rhs.getName()); } diff --git a/src/main/java/io/appform/databuilderframework/model/DataSet.java b/src/main/java/io/appform/databuilderframework/model/DataSet.java index f9fcdbb..01cce03 100644 --- a/src/main/java/io/appform/databuilderframework/model/DataSet.java +++ b/src/main/java/io/appform/databuilderframework/model/DataSet.java @@ -64,13 +64,6 @@ public DataSet add(T data) { return add(Utils.name(data.getClass()), data); } - public Map filter(final Collection requiredKeys) { - if (null == requiredKeys || requiredKeys.isEmpty()) { - return Collections.emptyMap(); - } - return safeOpOptimistic(() -> Maps.filterKeys(Utils.sanitize(availableData), Predicates.in(requiredKeys))); - } - public Data get(final String name) { if (Strings.isNullOrEmpty(name)) { return null; @@ -117,12 +110,12 @@ public DataSetAccessor accessor() { } private T safeOp(Supplier operation) { - val stamp = lock.readLock(); +// val stamp = lock.readLock(); try { return operation.get(); } finally { - lock.unlockRead(stamp); +// lock.unlockRead(stamp); } } diff --git a/src/main/java/io/appform/databuilderframework/model/DataSetView.java b/src/main/java/io/appform/databuilderframework/model/DataSetView.java new file mode 100644 index 0000000..f7efaeb --- /dev/null +++ b/src/main/java/io/appform/databuilderframework/model/DataSetView.java @@ -0,0 +1,72 @@ +package io.appform.databuilderframework.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.common.base.Predicates; +import com.google.common.base.Strings; +import com.google.common.collect.Maps; +import io.appform.databuilderframework.engine.DataSetAccessor; +import io.appform.databuilderframework.engine.Utils; +import lombok.val; +import org.hibernate.validator.constraints.NotEmpty; + +import javax.validation.constraints.NotNull; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.StampedLock; +import java.util.function.Supplier; + +/** + * Working set for data + * Contains all the data that has been provided by the system as well as those generated by the system. + */ +public class DataSetView extends DataSet { + + private final DataSet dataSet; + private final Set allowedKeys; + + public DataSetView(final DataSet dataSet, + final Set allowedKeys) { + this.dataSet = dataSet; + this.allowedKeys = allowedKeys; + } + + public DataSetView add(String dataName, Data data) { + throw new UnsupportedOperationException(); + } + + public DataSetView add(final Collection data) { + throw new UnsupportedOperationException(); + } + + public DataSetView add(T data) { + throw new UnsupportedOperationException(); + } + + public Map filter(final Collection requiredKeys) { + throw new UnsupportedOperationException(); + } + + public Data get(final String name) { + if (allowedKeys.contains(name)) { + return dataSet.get(name); + } + return null; + } + + public boolean containsAll(final Collection requiredKeys) { + // TODO Fix this. Should requiredKeys be filtered on allowedKeys ??? + return dataSet.containsAll(requiredKeys); + } + + public void copyInto(final Map outMap, Collection excludedKeys) { + throw new UnsupportedOperationException(); + } + + public DataSetAccessor accessor() { + return accessor(this); + } + +} From f133db511bf55879944d669ad7a8959dc2baf75e Mon Sep 17 00:00:00 2001 From: Rishabh Goyal Date: Tue, 15 Apr 2025 12:20:00 +0530 Subject: [PATCH 3/7] Reverted DataBuilderMeta changes --- .../model/DataBuilderMeta.java | 41 ++++++++----------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/src/main/java/io/appform/databuilderframework/model/DataBuilderMeta.java b/src/main/java/io/appform/databuilderframework/model/DataBuilderMeta.java index 5ae60a9..23f9e0d 100644 --- a/src/main/java/io/appform/databuilderframework/model/DataBuilderMeta.java +++ b/src/main/java/io/appform/databuilderframework/model/DataBuilderMeta.java @@ -5,7 +5,6 @@ import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; import lombok.Builder; -import lombok.Getter; import org.hibernate.validator.constraints.NotEmpty; import javax.validation.constraints.NotNull; @@ -66,22 +65,18 @@ public class DataBuilderMeta implements Comparable, Serializabl @JsonProperty private Set access; - @Getter - private Set accessibleDataSet; - public DataBuilderMeta(Set consumes, String produces, String name) { this(consumes, produces, name, Collections.emptySet(), Collections.emptySet()); } @Builder public DataBuilderMeta(Set consumes, String produces, String name, - Set optionals, Set access) { + Set optionals, Set access) { this.consumes = consumes; this.produces = produces; this.name = name; this.optionals = optionals; this.access = access; - this.accessibleDataSet = constructAccessibleDataSet(); } @@ -90,23 +85,23 @@ public DataBuilderMeta() { @JsonIgnore public Set getEffectiveConsumes(){ - if(optionals != null && !optionals.isEmpty()){ - return Sets.union(optionals, consumes); - }else{ - return consumes; - } + if(optionals != null && !optionals.isEmpty()){ + return Sets.union(optionals, consumes); + }else{ + return consumes; + } } @JsonIgnore - private Set constructAccessibleDataSet() { - Set output = consumes; - if(optionals != null && !optionals.isEmpty()){ - output = Sets.union(optionals, output); - } - if(access != null && !access.isEmpty()){ - output = Sets.union(access, output); - } - return output; + public Set getAccessibleDataSet(){ + Set output = consumes; + if(optionals != null && !optionals.isEmpty()){ + output = Sets.union(optionals, output); + } + if(access != null && !access.isEmpty()){ + output = Sets.union(access, output); + } + return output; } public int compareTo(DataBuilderMeta rhs) { @@ -114,8 +109,8 @@ public int compareTo(DataBuilderMeta rhs) { } public DataBuilderMeta deepCopy() { - Set optionalCopy = (optionals != null) ? ImmutableSet.copyOf(optionals) : null; - Set accessCopy = (access != null) ? ImmutableSet.copyOf(access) : null; + Set optionalCopy = (optionals != null) ? ImmutableSet.copyOf(optionals) : null; + Set accessCopy = (access != null) ? ImmutableSet.copyOf(access) : null; return new DataBuilderMeta(ImmutableSet.copyOf(consumes), produces, name, optionalCopy, accessCopy); } -} +} \ No newline at end of file From 0da7972f34365257a264fe98c76057475921cd06 Mon Sep 17 00:00:00 2001 From: Rishabh Goyal Date: Tue, 15 Apr 2025 12:20:38 +0530 Subject: [PATCH 4/7] Reverted DataBuilderMeta changes --- .../model/DataBuilderMeta.java | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/main/java/io/appform/databuilderframework/model/DataBuilderMeta.java b/src/main/java/io/appform/databuilderframework/model/DataBuilderMeta.java index 23f9e0d..f3deaec 100644 --- a/src/main/java/io/appform/databuilderframework/model/DataBuilderMeta.java +++ b/src/main/java/io/appform/databuilderframework/model/DataBuilderMeta.java @@ -71,7 +71,7 @@ public DataBuilderMeta(Set consumes, String produces, String name) { @Builder public DataBuilderMeta(Set consumes, String produces, String name, - Set optionals, Set access) { + Set optionals, Set access) { this.consumes = consumes; this.produces = produces; this.name = name; @@ -85,23 +85,23 @@ public DataBuilderMeta() { @JsonIgnore public Set getEffectiveConsumes(){ - if(optionals != null && !optionals.isEmpty()){ - return Sets.union(optionals, consumes); - }else{ - return consumes; - } + if(optionals != null && !optionals.isEmpty()){ + return Sets.union(optionals, consumes); + }else{ + return consumes; + } } @JsonIgnore public Set getAccessibleDataSet(){ - Set output = consumes; - if(optionals != null && !optionals.isEmpty()){ - output = Sets.union(optionals, output); - } - if(access != null && !access.isEmpty()){ - output = Sets.union(access, output); - } - return output; + Set output = consumes; + if(optionals != null && !optionals.isEmpty()){ + output = Sets.union(optionals, output); + } + if(access != null && !access.isEmpty()){ + output = Sets.union(access, output); + } + return output; } public int compareTo(DataBuilderMeta rhs) { @@ -109,8 +109,8 @@ public int compareTo(DataBuilderMeta rhs) { } public DataBuilderMeta deepCopy() { - Set optionalCopy = (optionals != null) ? ImmutableSet.copyOf(optionals) : null; - Set accessCopy = (access != null) ? ImmutableSet.copyOf(access) : null; + Set optionalCopy = (optionals != null) ? ImmutableSet.copyOf(optionals) : null; + Set accessCopy = (access != null) ? ImmutableSet.copyOf(access) : null; return new DataBuilderMeta(ImmutableSet.copyOf(consumes), produces, name, optionalCopy, accessCopy); } } \ No newline at end of file From 95c0103ae15725c701c407413073b3d21be1bdad Mon Sep 17 00:00:00 2001 From: Rishabh Goyal Date: Tue, 15 Apr 2025 12:21:48 +0530 Subject: [PATCH 5/7] Reverted safeOp() related changes --- .../databuilderframework/model/DataSet.java | 27 +++---------------- 1 file changed, 3 insertions(+), 24 deletions(-) diff --git a/src/main/java/io/appform/databuilderframework/model/DataSet.java b/src/main/java/io/appform/databuilderframework/model/DataSet.java index 01cce03..d2c2b90 100644 --- a/src/main/java/io/appform/databuilderframework/model/DataSet.java +++ b/src/main/java/io/appform/databuilderframework/model/DataSet.java @@ -75,14 +75,7 @@ public boolean containsAll(final Collection requiredKeys) { if (null == requiredKeys || requiredKeys.isEmpty()) { return false; } - return safeOpOptimistic(() -> { - for (String data : requiredKeys) { - if (!availableData.containsKey(data)) { - return false; - } - } - return true; - }); + return safeOp(() -> availableData.keySet().containsAll(requiredKeys)); } public void copyInto(final Map outMap, Collection excludedKeys) { @@ -110,26 +103,12 @@ public DataSetAccessor accessor() { } private T safeOp(Supplier operation) { -// val stamp = lock.readLock(); + val stamp = lock.readLock(); try { return operation.get(); } finally { -// lock.unlockRead(stamp); - } - } - - private T safeOpOptimistic(Supplier operation) { - val stamp = lock.tryOptimisticRead(); - // This means a writeLock is already present, fallback to full readLock() - if (stamp == 0) { - return safeOp(operation); - } - T output = operation.get(); - if (!lock.validate(stamp)) { - return safeOp(operation); - } else { - return output; + lock.unlockRead(stamp); } } } From 4b088855cec43bae0a83c50735bb84e1e3df60cf Mon Sep 17 00:00:00 2001 From: Rishabh Goyal Date: Tue, 15 Apr 2025 12:22:29 +0530 Subject: [PATCH 6/7] Reverted safeOp() related changes --- .../io/appform/databuilderframework/model/DataSet.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/io/appform/databuilderframework/model/DataSet.java b/src/main/java/io/appform/databuilderframework/model/DataSet.java index d2c2b90..5d8b05b 100644 --- a/src/main/java/io/appform/databuilderframework/model/DataSet.java +++ b/src/main/java/io/appform/databuilderframework/model/DataSet.java @@ -45,7 +45,8 @@ public DataSet add(String dataName, Data data) { try { this.availableData.put(dataName, data); return this; - } finally { + } + finally { lock.unlockWrite(stamp); } } @@ -55,7 +56,8 @@ public DataSet add(final Collection data) { try { data.forEach(d -> availableData.put(d.getData(), d)); return this; - } finally { + } + finally { lock.unlockWrite(stamp); } } @@ -68,7 +70,7 @@ public Data get(final String name) { if (Strings.isNullOrEmpty(name)) { return null; } - return availableData.get(name); + return safeOp(() -> availableData.get(name)); } public boolean containsAll(final Collection requiredKeys) { From 9404a37b7e96847ea5e23520a18c0e35649e35c5 Mon Sep 17 00:00:00 2001 From: Rishabh Goyal Date: Tue, 15 Apr 2025 12:24:17 +0530 Subject: [PATCH 7/7] Reverted to TreeMap() --- .../databuilderframework/engine/SimpleDataFlowExecutor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/appform/databuilderframework/engine/SimpleDataFlowExecutor.java b/src/main/java/io/appform/databuilderframework/engine/SimpleDataFlowExecutor.java index a23cb92..d67bc8f 100644 --- a/src/main/java/io/appform/databuilderframework/engine/SimpleDataFlowExecutor.java +++ b/src/main/java/io/appform/databuilderframework/engine/SimpleDataFlowExecutor.java @@ -40,7 +40,7 @@ protected DataExecutionResponse run( val executionGraph = dataFlow.getExecutionGraph(); val dataSet = dataFlowInstance.getDataSet().accessor().copy(); //Create own copy to work with val dataSetAccessor = dataSet.accessor(); - val responseData = new LinkedHashMap(); + val responseData = new TreeMap(); val activeDataSet = new HashSet(); val dependencyHierarchy = executionGraph.getDependencyHierarchy(); val newlyGeneratedData = new HashSet();