Sunday, 29 July 2018

A Human Readable Predicate with ObjectLab Kit

Recently, I have been working with Predicates.

I'm modelling some stuff for a bank but I needed to present updates and changes to the handwritten rules regularly. I don't know about you but wouldn't be nice if we could print the Predicate and not getting something like:

net.objectlab.kit.util.excel.ExcelWorkbookTest$$Lambda$1/868693306@13221655

Therefore, here comes the PrintablePredicate class in the next release of ObjectLab Kit.

See PrintablePredicate.java

The idea is to create an implementation of a Predicate and allow you to give it a name and the values it is comparing against.  We also support AND, OR and NEGATE as per a Predicate.

Let's imagine a small model, a financial Instrument 'Asset' and some basic Predicates.  Imagine that we create a predicate that detects instruments that are either Bonds or Commodities but that they should also be Active.

Using PrintablePredicate, I can combine 2 predicates and when I print the predicate (in an Excel spreadsheet that I generate automatically, more on that later) I can see a nice string "AssetClass in (Bond, Commodities) AND Active".  Here is the code for it:



This tiny class will come with ObjectLab Kit 1.4.1. Enjoy!
package net.objectlab.kit.util.predicate;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
import lombok.AllArgsConstructor;
import lombok.Data;
import net.objectlab.kit.util.StringUtil;
/**
* Example for the PrintablePredicate.
* Note that the example uses Lombok (highly recommended).
* @author Benoit Xhenseval
*/
public class PrintablePredicateExample {
@Data
@AllArgsConstructor
private static class Asset { // Using Lombok, replaces Get/Set and Constructor
private String assetClass;
private String assetType;
private boolean active;
}
/** Predicate that tests for values Asset Class. */
public static Predicate<Asset> hasAssetClass(String... assetClass) {
return new PrintablePredicate<>("AssetClass",
t -> StringUtil.equalsAnyIgnoreCase(t.getAssetClass(), assetClass),
assetClass);
}
/** Predicate that tests if asset is active. */
public static Predicate<Asset> isActive() {
return new PrintablePredicate<>("Active", t -> t.isActive());
}
private static List<Asset> buildUniverse() {
List<Asset> assets = new ArrayList<>();
assets.add(new Asset("Equity", "Stock", true));
assets.add(new Asset("Bond", "Government Bond", true));
assets.add(new Asset("Bond", "Corporate Bond", true));
assets.add(new Asset("Commodities", "Corn", true));
assets.add(new Asset("Commodities", "Oil", false));
return assets;
}
public static void main(String[] args) {
List<Asset> assets = buildUniverse();
final Predicate<Asset> activeBondOrCommidities = hasAssetClass("Bond", "Commodities").and(isActive());
final long count = assets.stream().filter(activeBondOrCommidities).count(); // 3
System.out.println(activeBondOrCommidities + " Returns " + count);
// Prints "AssetClass in (Bond, Commodities) AND Active Returns 3"
}
}

No comments :