How to write a jqwik generator method with nested generators - java

Using jqwik.net, trying to generate a Rule class with a a nested RuleConfig class inside it.
The RuleConfig class has a nested ruleProps which is a Map
The statusReturnedFromApplyingRule method always returns an initialized Rule instead of using the #provide method values ??
Returned Rule:
rule:Rule{ruleId='null', inputMetricSelector=null, ruleConfig='RuleConfig{ruleType='null', ruleProps={}}'}, elements:[{}]
Here is my code:
public class RangeMatchRuleTest {
#Property
#Report(Reporting.GENERATED)
boolean statusReturnedFromApplyingRule(#ForAll("generateRule") Rule rule,
#ForAll("generateInputMapElements") Iterable<Map<String, Object>> elements) {
RangeMatchRule rangeMatchRule = new RangeMatchRule();
final RuleIF.Status status = rangeMatchRule.applyRule(rule, elements);
return RuleIF.getEnums().contains(status.toString());
}
#Provide
Arbitrary<Rule> generateRule() {
Rule rule = new Rule();
RuleConfig ruleConfig = new RuleConfig();
Map<String, Object> ruleProps = new HashMap<>();
Arbitrary<Double> lowThresholdArb = Arbitraries.doubles()
.between(0.0, 29.0);
lowThresholdArb.allValues().ifPresent(doubleStream -> ruleProps.put(Utils.LOW_THRESHOLD, doubleStream.findFirst().get()));
//lowThresholdArb.map(lowThreshold -> ruleProps.put(Utils.LOW_THRESHOLD, lowThreshold) );
Arbitrary<Double> highThresholdArb = Arbitraries.doubles()
.between(30.0, 50.0);
highThresholdArb.map(highThreshold -> ruleProps.put(Utils.HIGH_THRESHOLD, highThreshold));
ruleConfig.setRuleProps(ruleProps);
rule.setRuleConfig(ruleConfig);
return Arbitraries.create(() -> rule);
}
#Provide
Arbitrary<Iterable<Map<String, Object>>> generateInputMapElements() {
Arbitrary<Double> metricValueArb = Arbitraries.doubles()
.between(0, 50.0);
Map<String, Object> inputMap = new HashMap<>();
metricValueArb.map(metricValue -> inputMap.put(Utils.METRIC_VALUE, metricValue));
List<Map<String, Object>> inputMapLst = new ArrayList<>();
inputMapLst.add(inputMap);
return Arbitraries.create(() -> inputMapLst);
}
}
TIA

You are building the generateRule method on the wrong assumption that an arbitrary's map method performed any real action when called. This is not the case. The fact that map returns another arbitrary instance gives a strong hint.
The underlying idea you have to grasp is that a provider method - the method annotated with #Provide - is nothing but a "description" of the generation process; it will only be called once. The actual object generation happens afterwards and is controlled by the framework.
Here's a reworked generateRule method that should do what you intended:
#Provide
Arbitrary<Rule> generateRule() {
Arbitrary<Double> lowThresholdArb = Arbitraries.doubles()
.between(0.0, 29.0);
Arbitrary<Double> highThresholdArb = Arbitraries.doubles()
.between(30.0, 50.0);
Arbitrary<RuleConfig> configArb =
Combinators.combine(lowThresholdArb, highThresholdArb)
.as((low, high) -> {
Map<String, Object> ruleProps = new HashMap<>();
ruleProps.put(Utils.LOW_THRESHOLD, low);
ruleProps.put(Utils.HIGH_THRESHOLD, high);
RuleConfig ruleConfig = new RuleConfig();
ruleConfig.setRuleProps(ruleProps);
return ruleConfig;
});
return configArb.map(config -> {
Rule rule = new Rule();
rule.setRuleConfig(config);
return rule;
});
}
What you can hopefully see is that creating a generator is like dataflow programming: Starting from some base arbitraries - lowThresholdArb and highThresholdArb - you combine, map and filter those. In the end a single instance of Arbitrary must be returned.
BTW: If you want this generator to be applied each time when you need a Rule, you could write the following class:
public class RuleArbitraryProvider implements ArbitraryProvider {
#Override
public boolean canProvideFor(TypeUsage targetType) {
return targetType.isOfType(Rule.class);
}
#Override
public Set<Arbitrary<?>> provideFor(TypeUsage targetType, SubtypeProvider subtypeProvider) {
return Collections.singleton(generateRule());
}
private Arbitrary<Rule> generateRule() {
// Put here the code from above
...
}
}
and register it as a default provider.

Additional example for the Map above based on the provided answer:
#Provide
Arbitrary<Iterable<Map<String, Object>>> generateInputMapElements() {
Arbitrary<Double> metricValueArb = Arbitraries.doubles()
.between(0, 50.0);
Arbitrary<Map<String, Object>> inputMapArb =
metricValueArb.map(metricsValue -> {
Map<String, Object> inputMap = new HashMap<>();
inputMap.put(Utils.METRIC_VALUE, metricsValue);
return inputMap;
});
return inputMapArb.map(inputMap -> {
List<Map<String, Object>> inputMapLst = new ArrayList<>();
inputMapLst.add(inputMap);
return inputMapLst;
});
}

Related

Mapping Lambda Expressions that return Booleans

I'm trying to map a String to Lambda Expressions. The expressions take a variable(map) and either return false or run a getOrDefault on the given map variable. But for some reason, I am getting errors.
Map<String, Runnable> order_function = new HashMap<>();
order_function.put("AlternativesValues", (Map x) -> { return false; });
order_function.put("AlternativesConstituent", (Map x) -> { x.getOrDefault("orderCloseCons", false); });
The Runnable doesn't return anything. If you expand the lambda to the anonymous class implementation, you will see the void is the return type:
Runnable runnable = new Runnable() {
#Override
public void run() {
// implementation
}
};
This is in conflict with your lambda> (Map x) -> { return false; }.
Since you need an expression which takes a Map and returns a boolean, then you need Predicate<Map<? ,Boolean>> (keep the wildcard ? or replace it with whatever is needed):
Map<String, Predicate<Map<? ,Boolean>>> order_function = new HashMap<>();
order_function.put("AlternativesValues", x -> false);
order_function.put("AlternativesConstituent", map -> map.getOrDefault("orderCloseCons", false));
perhaps you wanted to use Function instead of Runnable:
Map<String, Function<Map<String, Boolean>, Boolean>> order_function = new HashMap<>();
order_function.put("AlternativesValues", x -> false);
order_function.put("AlternativesConstituent", map -> map.getOrDefault("orderCloseCons", false));
//...
boolean alternativesValues = order_function.get("AlternativesValues").apply(someMap);
If they mean to be constants, you can use enum like below.
enum OrderFunctions {
ALTERNATIVES_VALUES("AlternativesValues", map -> false),
ALTERNATIVES_CONSTITUENT("AlternativesConstituent", map -> map.getOrDefault("orderCloseCons", false));
private final String name;
private final Function<Map<String, Boolean>, Boolean> orderFunction;
OrderFunctions(String name, Function<Map<String, Boolean>, Boolean> orderFunction) {
this.name = name;
this.orderFunction = orderFunction;
}
public String getName() {
return name;
}
public Function<Map<String, Boolean>, Boolean> getOrderFunction() {
return orderFunction;
}
}
and you can use it like below.
OrderFunctions.ALTERNATIVES_CONSTITUENT.getOrderFunction().apply(someMap);

Java 8 List to Map conversion

I have a problem with conversion List Object to Map String, List Object. I'm looking for Map with a keys name of all components in cars, and a value is represented by cars with this component
public class Car {
private String model;
private List<String> components;
// getters and setters
}
I write a solution but looking for a better stream solution.
public Map<String, List<Car>> componentsInCar() {
HashSet<String> components = new HashSet<>();
cars.stream().forEach(x -> x.getComponents().stream().forEachOrdered(components::add));
Map<String, List<Car>> mapCarsComponents = new HashMap<>();
for (String keys : components) {
mapCarsComponents.put(keys,
cars.stream().filter(c -> c.getComponents().contains(keys)).collect(Collectors.toList()));
}
return mapCarsComponents;
}
You could do it with streams too, but I find this a bit more readable:
public static Map<String, List<Car>> componentsInCar(List<Car> cars) {
Map<String, List<Car>> result = new HashMap<>();
cars.forEach(car -> {
car.getComponents().forEach(comp -> {
result.computeIfAbsent(comp, ignoreMe -> new ArrayList<>()).add(car);
});
});
return result;
}
Or using stream:
public static Map<String, List<Car>> componentsInCar(List<Car> cars) {
return cars.stream()
.flatMap(car -> car.getComponents().stream().distinct().map(comp -> new SimpleEntry<>(comp, car)))
.collect(Collectors.groupingBy(
Entry::getKey,
Collectors.mapping(Entry::getValue, Collectors.toList())
));
}
I know this is a Java question, and there is already a Java answer. However, I would like to add that Kotlin, which is a JVM language and perfectly interoperable with Java, you can do things like this very easily and cleanly:
val carsByComponent = cars
.flatMap { it.components }
.distinct()
.map { component -> component to cars.filter { car -> component in car.components } }
.toMap()
or even more concise, allthough less readable:
val carsByComponent = cars
.flatMap { car -> car.components.map { it to car } }
.groupBy { it.first }
.mapValues {it.value.map { it.second }}

Design pattern for multiples methods using same argument

I have this class on which I have a method and will return a map, using dozens of methods inside it using the same arguments.
My class has thousand of lines and it will increase even more.
I can create several classes and inside create methods, but I´m asking if there is a special design for this scenario
Actual Scenario:
public Map<String, Object> transformMapOnAnotherMap(Map<String, Object> firstMap) {
Map<String, Object> lastMap = new HashMap<String, Object>(firstMap);
lastMap = do1(firstMap, lastMap);
lastMap = do2(firstMap, lastMap);
lastMap = do3(firstMap, lastMap);
lastMap = do4(firstMap, lastMap);
//more 20 methods
return lastMap;
}
Try without design:
public Map<String, Object> transformMapOnAnotherMap(Map<String, Object> firstMap) {
Map<String, Object> lastMap = new HashMap<String, Object>(firstMap);
Do1 do1 = new Do1();
lastMap = do1.do1(firstMap, lastMap);
Do2 do2 = new Do2();
lastMap = do2.do2(firstMap, lastMap);
// more 20 methods
return lastMap;
}
If do1, etc., are just implementation, not part of the public interface of your class, it would probably make sense to create a private class (perhaps even a nested one) with a constructor accepting the two maps which it retains as instance variables:
private static class Worker {
Worker(Map firstMap, Map secondMap) {
this.firstMap = firstMap;
this.secondMap = secondMap;
}
void do1() {
// ...update `this.lastMap` if appropriate...
}
void do2() {
// ...update `this.lastMap` if appropriate...
}
}
There I've made Worker static so it's a static nested class, not an inner class, but it could be an inner class instead (no static) if you need access to the internals of the surrounding class.
Then
public Map<String, Object> transformMapOnAnotherMap(Map<String, Object> firstMap) {
Worker worker = new Worker(firstMap, new HashMap<String, Object>(firstMap));
worker.do1();
worker.do2();
worker.do3();
worker.do4();
//more 20 methods
return worker.lastMap;
}
You can use interface and make every "do" an implementation of functional interface.
interface Do {
Map<String, Object> apply(Map<String, Object> firstMap, Map<String, Object> lastMap);
}
Then you can initialize static dos:
static Do[] allDos = {
(firstMap, lastMap) -> {
// do0
},
(firstMap, lastMap) -> {
// do1
},
// ...do2, do3, ...
};
If you need to invoke do0 -> do2 -> do4 for example:
public Map<String, Object> transformMapOnAnotherMap(Map<String, Object> firstMap) {
Map<String, Object> lastMap = new HashMap<String, Object>(firstMap);
int[] ids = { 0, 2, 4 };
for (int id : ids)
lastMap = allDos[id].apply(firstMap, lastMap);
return lastMap;
}
Why don't take more functional approach?
define interface
interface MapTransformation{
void transformation(Map<String, Object> first, Map<String, Object> last);
}
then during class creation, class which has definition of transformMapOnAnotherMap takes list of transformations as parameter then you could do
class SomeClass {
final private List<MapTransformation> transformations;
//constructor omitted
public Map<String, Object> transformMapOnAnotherMap(Map<String, Object> firstMap) {
Map<String, Object> lastMap = new HashMap<String, Object>(firstMap);
transformations.forEach(t->t.transformation(firstMap,lastMap);
return lastMap;
}
}

How to convert this sorted map method from java to Kotlin

How do I convert the following Java to Kotlin?
private Map<String, Map<String, String>> example(List<Dto> dtos) {
if (dtos.isEmpty()) {
return ImmutableMap.of();
}
final Map<String, Map<String, String>> outerMapByField1 = new TreeMap<>();
dtos.forEach(dto -> {
final String field1 = dto.getField1();
final Map<String, String> innerMapByField2 = outerMapByField1.computeIfAbsent(field1, (key) -> new TreeMap<>());
innerMapByField2.put(dto.getField2(), dto.getField3());
});
return outerMapByField1;
}
The IntelliJ conversion gives me something to work with and my attempt to refactor it has ended up with the following, which does not compile.
private fun example(dtos: List<Dto>): Map<String, Map<String, String>> {
if (dtos.isEmpty()) {
return ImmutableMap.of()
}
val outerMapByField1 = sortedMapOf<String, Map<String, String>>()
dtos.forEach { dto ->
val field1 = dto.field1
val innerMapByField2 = outerMapByField1.getOrPut(field1) { key -> TreeMap() }
innerMapByField2.put(dto.field2, dto.field3)
}
return outerMapByField1
}
First, the values in your outerMapByField1 are Map instances, which is a read-only interface. To modify these maps, you need to store them as MutableMaps (as per #Heinrisch's answer).
Kotlin offers an emptyMap() function that you might consider using instead of ImmutableMap.of().
The lamda passed to getOrPut doesn't take an argument, so you have to remove key ->.
Here's all these applied:
private fun example(dtos: List<Dto>): Map<String, Map<String, String>> {
if (dtos.isEmpty()) {
return emptyMap()
}
val outerMapByField1 = sortedMapOf<String, MutableMap<String, String>>()
dtos.forEach { dto ->
val field1 = dto.field1
val innerMapByField2 = outerMapByField1.getOrPut(field1) { TreeMap() }
innerMapByField2.put(dto.field2, dto.field3)
}
return outerMapByField1
}
Maps are not mutable by default in Kotlin, so adding some mutability will make it compile:
private fun example(dtos: List<Dto>): Map<String, Map<String, String>> {
if (dtos.isEmpty()) {
return emptyMap()
}
val outerMapByField1 = sortedMapOf<String, MutableMap<String, String>>()
dtos.forEach { dto ->
val field1 = dto.field1
val innerMapByField2 = outerMapByField1.getOrPut(field1) { mutableMapOf() }
innerMapByField2.put(dto.field2, dto.field3)
}
return outerMapByField1
}
Maybe something like this:
private fun example(dtos: List<Dto>) = dtos.groupBy { it.field1 }.map { entry ->
entry.key to entry.value.associateBy { it.field2 }.mapValues { it.value.field3 }.toSortedMap()
}.toMap().toSortedMap()

How to properly lazy initialize Map of Map of Map?

It may be a bad practice, but I haven't been able to figure out any better solution for my problem. So I have this map
// Map<state, Map<transition, Map<property, value>>>
private Map<String, Map<String, Map<String, String>>> properties;
and I want to initialize it so I don't get NullPointerException with this
properties.get("a").get("b").get("c");
I tried this one but I didn't work (obviously)
properties = new HashMap<String, Map<String, Map<String,String>>>();
Other things I tried didn't compile.
Also if you have any ideas how to avoid this nested maps, I would appreciate it.
It seems to me that you need to create your own Key class:
public class Key {
private final String a;
private final String b;
private final String c;
public Key(String a, String b, String c) {
// initialize all fields here
}
// you need to implement equals and hashcode. Eclipse and IntelliJ can do that for you
}
If you implement your own key class, your map will look like this:
Map<Key, String> map = new HashMap<Key, String>();
And when looking for something in the map you can use:
map.get(new Key("a", "b", "c"));
The method above will not throw a NullPointerException.
Please remember that for this solution to work, you need to override equals and hashcode in the Key class. There is help here. If you don't override equals and hashcode, then a new key with the same elements won't match an existing key in the map.
There are other possible solutions but implementing your own key is a pretty clean one in my opinion. If you don't want to use the constructor you can initialize your key with a static method and use something like:
Key.build(a, b, c)
It is up to you.
You need to put maps in your maps in your map. Literally:
properties = new HashMap<String, Map<String, Map<String,String>>>();
properties.put("a", new HashMap<String, Map<String,String>>());
properites.get("a").put("b", new HashMap<String,String>());
If your target is lazy initialization without NPE you have to create your own map:
private static abstract class MyMap<K, V> extends HashMap<K, V> {
#Override
public V get(Object key) {
V val = super.get(key);
if (val == null && key instanceof K) {
put((K)key, val = create());
}
return val;
}
protected abstract V create();
}
public void initialize() {
properties = new MyMap<String, Map<String, Map<String, String>>>() {
#Override
protected Map<String, Map<String, String>> create() {
return new MyMap<String, Map<String, String>>() {
#Override
protected Map<String, String> create() {
return new HashMap<String, String>();
}
};
}
};
}
You could use a utility method:
public static <T> T get(Map<?, ?> properties, Object... keys) {
Map<?, ?> nestedMap = properties;
for (int i = 0; i < keys.length; i++) {
if (i == keys.length - 1) {
#SuppressWarnings("unchecked")
T value = (T) nestedMap.get(keys[i]);
return value;
} else {
nestedMap = (Map<?, ?>) nestedMap.get(keys[i]);
if(nestedMap == null) {
return null;
}
}
}
return null;
}
This can be invoked like this:
String result = get(properties, "a", "b", "c");
Note that care is required when using this as it is not type-safe.
The only way to do it with this structure is to pre-initialise the 1st and 2nd level maps with ALL possible keys. If this is not possible to do you can't achieve what you are asking with plain Maps.
As an alternative you can build a custom data structure that is more forgiving. For example a common trick is for a failed key lookup to return an "empty" structure rather than null, allowing nested access.
You can't initialize this in one go, since you normally don't know what keys you'll have in advance.
Thus you'd have to check whether the submap for a key is null and if so you might add an empty map for that. Preferably you'd only do that when adding entries to the map and upon retrieving entries you return null if one of the submaps in the path doesn't exist. You could wrap that in your own map implementation for ease of use.
As an alternative, apache commons collections' MultiKeyMap might provide what you want.
It's impossible to use properties.get("a").get("b").get("c"); and be sure to avoid null unless you make your own Map. In fact, you can't predict that your map will contains "b" key.
So try to make your own class to handle nested get.
I think a better solution is using an object as the only key to the map of values. The key will be composed of three fields, state, transition and property.
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
public class Key {
private String state;
private String transition;
private String property;
public Key(String state, String transition, String property) {
this.state = state;
this.transition = transition;
this.property = property;
}
#Override
public boolean equals(Object other) {
return EqualsBuilder.reflectionEquals(this, other);
}
#Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
}
When you check for a value, the map will return null for a key that is not associated with a value
Map<Key, String> values = new HashMap<Key, String>();
assert values.get(new Key("a", "b", "c")) == null;
values.put(new Key("a", "b", "c"), "value");
assert values.get(new Key("a", "b", "c")) != null;
assert values.get(new Key("a", "b", "c")).equals("value");
To efficiently and correctly use an object as a key in a Map you should override the methods equals() and hashCode(). I have built thos methods using the reflective functionalities of the Commons Lang library.
I think, following is the easier way:
public static final Map<Integer, Map<Integer, Map<Integer, Double>>> A_Map = new HashMap<Integer, Map<Integer, Map<Integer, Double>>>()
{
{
put(0, new HashMap<Integer, Map<Integer, Double>>()
{
{
put(0, new HashMap<Integer, Double>()
{
{
put(0, 1 / 60.0);
put(1, 1 / 3600.0);
}
});
put(1, new HashMap<Integer, Double>()
{
{
put(0, 1 / 160.0);
put(1, 1 / 13600.0);
}
});
}
});
put(1, new HashMap<Integer, Map<Integer, Double>>()
{
{
put(0, new HashMap<Integer, Double>()
{
{
put(0, 1 / 260.0);
put(1, 1 / 3600.0);
}
});
put(1, new HashMap<Integer, Double>()
{
{
put(0, 1 / 560.0);
put(1, 1 / 1300.0);
}
});
}
});
}
};
Using computeIfAbsent/putIfAbsent makes it simple:
private <T> void addValueToMap(String keyA, String keyB, String keyC, String value) {
map.computeIfAbsent(keyA, k -> new HashMap<>())
.computeIfAbsent(keyB, k -> new HashMap<>())
.putIfAbsent(keyC, value);
}

Categories