Java imitate and, or for concatenate rule - java

I have a Java class like below
class MyClass {
public boolean rule1() {...}
public boolean rule2() {...}
public boolean rule3() {...}
}
now for instance I want to check the rule of above class in many ways such as :
MyClass myClass = new MyClass();
if (myClass.rule1() && myClass.rule2 || myClass.rule3) {}
and Now I am wondering that how can I implement above line with like this one?
if (myClass.rule1().and().rule2().or().rule3().accept()) {}

The cleaner way would be to use the functional interface Predicate:
Type Parameters:
T - the type of the input to the predicate Functional
Interface: This is a functional interface and can therefore be used as
the assignment target for a lambda expression or method reference.
public class A {
public Predicate rule1() {
return //some operation that returns a boolean;
}
public Predicate rule2() {
return //some operation that returns a boolean;
}
public Predicate rule3() {
return //some operation that returns a boolean;
}
}
But the if chain of method calls would not look like you are looking for, namely:
if (myClass.rule1().and().rule2().or().rule3().accept()) {}
Otherwise, you would have to implement the Builder pattern, and implement the and(), or(), and accept methods. For instance:
public class BooleanEvaluator {
List<String> rules = new ArrayList<>();
public BooleanEvaluator and() {
rules.add("&&");
return this;
}
public BooleanEvaluator or() {
rules.add("or");
return this;
}
public boolean accept() {
int i = 0;
boolean result = Boolean.parseBoolean(rules.get(0));
while (i < rules.size() - 1) {
if(rules.get(i).equals("&&")){
result = result && Boolean.parseBoolean(rules.get(i + 1));
i+=2;
}
else if(rules.get(i).equals("||")){
result = result || Boolean.parseBoolean(rules.get(i + 1));
i+=2;
}
}
return false;
}
public BooleanEvaluator rule1() {
boolean result = // apply the rule 1
rules.add(String.valueOf(result));
return this;
}
public BooleanEvaluator rule2() {
boolean result = // apply the rule 2
rules.add(String.valueOf(result));
return this;
}
public BooleanEvaluator rule3() {
boolean result = // apply the rule 3
rules.add(String.valueOf(result));
return this;
}
void some_method(){
if (this.rule1().and().rule2().or().rule3().accept()) {
// ...
}
}
}
Naturally, the accept method would have to be much more robust, this is just to show what would the design look like.

Have a look at Predicate<T> and its and or or.
MyClass instance = new MyClass();
Predicate<MyClass> predicate = MyClass::rule1;
if (predicate.and(MyClass::rule2).or(MyClass::rule3).test(instance)) {
// todo
}
It might look less readable than the version you mentioned, renaming MyClass to something more meaningful would help. If it doesn't work for you, consider writing a Builder. Good complex examples of which can be found in, let's say, dynamic SQL builders (for example, jooq).

Related

Graceful alternative to nested Optional.map?

I have multiple Optionals that must be mapped to a POJO. Is there a better alternative than the following?
class SimplePojo {
private String stringField;
private Integer integerField;
// All args. constructor, getter, setter
}
Optional<String> stringOptional = ...
Optional<Integer> integerOptional = ...
Optional<SimplePojo> simplePojoOptional = stringOptional.flatMap(
string -> integerOptional.map(integer -> new SimplePojo(string, integer)))
I have reduced the problem to 2 Optionals in the above example to keep it short. But I actually have 3 Optionals with more on the way. I am afraid the last line can easily become unwieldy soon.
Please note: Use of functional frameworks like Vavr or Functional Java is not an option for me.
How about using a Builder ?
class SimplePojo {
public static class Builder {
private String stringField;
public Builder withStringField(String str) {
this.stringField = str;
return this;
}
// and other "with" methods...
public Optional<SimplePojo> build() {
if (stringField == null || anotherField == null /* and so forth */) {
return Optional.empty();
} else {
return Optional.of(new SimplePojo(this));
}
}
}
private final String stringField;
/* private constructor, so client code has to go through the Builder */
private SimplePojo(Builder builder) {
this.stringField = builder.stringField;
// etc.
}
}
Then you could use it as follows:
SimplePojo.Builder builder = new SimplePojo.builder();
optionalStringField.ifPresent(builder::withStringField);
// etc.
return builder.build();
I do not see any advantage from pursuing the functional style this way here. see three options:
ONE: If you can alter the SimplePojo class and if this scenario is a common one, you might consider to add a factory method to the SimplePojo:
class SimplePojo {
public static Optional<SimplePojo> of(final Optional<String> stringField, final Optional<Integer> integerField) {
if (stringField.isPresent() && integerField.isPresent()) {
return new SimplePojo(stringField.get(), integerField.get());
else
return Optional.empty();
}
}
TWO: If you cannot alter the SimplePojo, you might want to create this as a utility method somewhere else. If you need this pattern only in one class, make the method private in this class!
THREE: If you need to do this only once or twice, I would prefer the if...then construction from the first option over the functional notation you used for the sake of readability:
final Optional<SimplePojo> simplePojoOptional;
if (stringField.isPresent() && integerField.isPresent()) {
simplePojoOptional = new SimplePojo(stringField.get(), integerField.get());
else
simplePojoOptional = Optional.empty();

creating a custom argument matcher confusing implementation

I have seen someone creating a custom argument matcher like the following. However, I am having difficulty understanding how it works.
What I can understand its a method that takes a parameter and returns a ArgumentMatcher which is an interface that has a type of List<Person>. And the overriden method is the matcher that uses a lambda. I think the body part is the most confusing, if anyone can explain that.
private ArgumentMatcher<List<Person> personListSize(final int size) {
return argument -> argument.personList().size() == size;
}
This is the way I would normally do something like this, which to me is easier to understand, just wondering how can I get the following to look like the above?
public class CustomArgumentMatcher implements ArgumentMatcher<List<Person>> {
#Override
public boolean matches(List<Person> argument) {
return argument.size() == size;
}
}
Just starting to understand, this works:
private ArgumentMatcher<String> stringMatcher = new ArgumentMatcher<String>() {
#Override
public boolean matches(String argument) {
return argument.contains("");
}
};
However, If I add a parameter to pass in like this:
private ArgumentMatcher<String> stringMatcherArgs(final String name) = new ArgumentMatcher<String>() {
}
I get a error message saying unexpected token just wondering to pass in a parameter in the above?
You should read this document about Lambda Expressions
Here are your examples:
private ArgumentMatcher<List<Person>> customArgumentMatcher(final int size) {
return argument -> argument.size() == size;
}
private ArgumentMatcher<List<Person>> stringMatcherArgs(final String name) {
return argument -> argument.contains(name);
}
You got it all correct just connect the dots...
private ArgumentMatcher<List<Person> personListSize(final int size) {
return new ArgumentMatcher<List<Person>>() {
#Override
public boolean matches(List<Person> argument) {
return argument.size() == size;
}
};
}
and use it with argThat
Mockito.verify(mockClass).foo(argThat(personListSize(5));
If your still looking for the kotlin equivalent of Gustavo`s answer
(note that you should have created another question instead),
try the following:
fun customArgumentMatcher(size : Int) : ArgumentMatcher<List<Person>> {
return object : ArgumentMatcher<List<Person>> {
override fun matches(argument : List<Person>) = argument.size == size;
}
}
See also:
Setting anonymous interface in Kotlin

Java Generics Type DSL with Builder Pattern

I try to create a DSL Java API with the Builder Pattern on Generics Type.
I have the following class:
public class Rule<T> {
private Predicate<T> condition;
public ConditionBuilder<T> when() {
return new ConditionBuilder<>(this);
}
//setter and getter
}
and the following ConditionBuilder class:
public class ConditionBuilder<T> {
private Rule<T> parent;
public ConditionBuilder(Rule<T> parent) {
this.parent = parent;
}
public ConditionBuilder<T> condition1() {
parent.setCondition(l -> l == 0); // I would like an Integer
return this;
}
public ConditionBuilder<T> condition2() {
parent.setCondition(l -> l.length() > 3); // I would like a String
return this;
}
}
I try to find a solution to set the Generic Type on the fly as an Integer (resp. String) for the condition1 (resp. condition2).
Is there any Pattern or solution to avoid doing instanceof checking ?
You can't do this with member methods on ConditionBuilder<T>, since you've already constructed parent before you invoke either of the conditionX methods. As such, you can't constrain the instance "after the fact".
The way I'd do this is by making the Rule<T> a parameter of a static method. Then you can use something like:
static ConditionBuilder<Integer> condition1(ConditionBuilder<Integer> parent) {
parent.setCondition(l -> l == 0);
return parent;
}
static ConditionBuilder<String> condition2(ConditionBuilder<String> parent) {
parent.setCondition(l -> l.length() > 3);
return parent;
}
I would use a factory pattern instead, because the builder pattern does not fit this situation. Using generics implies that you will accept any type, and so making condition require a specific type is a waste of the generics.
public class Rule<T> {
private Predicate<T> condition;
//setter and getter
}
class ConditionFactory {
public static Rule<Integer> intCondition() {
Rule<Integer> rule = new Rule<>();
rule.setCondition(l -> l == 0);
return rule;
}
public static Rule<String> strCondition() {
Rule<Integer> rule = new Rule<>();
rule.setCondition(l -> l.length() > 3);
return rule;
}
}

Creating array of methods returning boolean and iterating through for-each loop

Okay so I have a batch of methods returning boolean values of true/false.
private void saveChangesOnEditButtonActionPerformed(java.awt.event.ActionEvent evt) {
updateMainTabsAccess();
updateUserPaymentTabPermissions();
updateUserRegistrationTabPermissions();
updateUserStudentsTabPermissions();
updateUserFacultyTabPermissions();
updateUserHomePermissions(); //saves any update made on existing user settings/permissions
updateUserInformation(); // sasve any update made on existing user information such as username
}
I would like to know if it's possible for me to check each of the methods' return value through a for-each loop.
I'm thinking of creating a private boolean isUpdateSuccessful() method.
Say like,
private boolean isUpdateSuccessful(){
Boolean a = updateMainTabsAccess();
Boolean b = updateUserPaymentTabPermissions();
//........so on....
Boolean result = (a && b &&...)
return result;
}
Problem is, I don't know if it's possible to put them in an arraylist or component array like
ArrayList<Boolean> listOfMethods = new ArrayList<Boolean>(method1,method2..);
So that I can then check each through a for-each loop
for(Boolean b:listOfMethods){
Boolean successful=true;
successful = (successful && b)
}
My questions are:
1.) How do I extract the return values of these methods and use the methods to initialize the Arraylist.
2.) Using for-each loop, is there any possibility of what I'm trying to do? I none, then what do you suggest I do?
I'd appreciate any answer or suggestion. I simply want to check if every method was successful. I thought of using ?1:0:
Thanks in advance.
If I am you, I would do this. Just a sample code:
private void saveChangesOnEditButtonActionPerformed(java.awt.event.ActionEvent evt) {
if (updateMainTabsAccess()) {
if (updateUserPaymentTabPermissions()) {
if (updateUserRegistrationTabPermissions()) {
...
} else {
// error on update registration
}
} else {
// error on update payment
}
}
With the above style:
You don't execute other methods when the before one fails.
Can have detailed error messages for each error.
You need not to main a collection and iteration.
Why not use a Stream to check the results:
Stream.<Boolean>of(updateMainTabsAccess(),
updateUserPaymentTabPermissions(),
updateUserRegistrationTabPermissions(),
updateUserStudentsTabPermissions(),
updateUserFacultyTabPermissions(),
updateUserHomePermissions(),
updateUserInformation()).allMatch(b -> b);
this way you get rid of short circuit evaluation and also don't need to create method references for each method.
method references
List<Supplier<Boolean>> methods = Arrays.asList(this::updateMainTabsAccess,
this::updateUserPaymentTabPermissions,
...
);
for (Supplier<Boolean> supplier : methods) {
boolean methodResult = supplier.get();
...
}
This can hardly be considered an improvement though...
this will find all method in side your class which is return Boolean after automatically invoke method one by one and store response to successful variable
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
public class Test {
public static void main(String[] args) {
Test test = new Test();
Class c = test.getClass();
boolean successful = true;
for (Method method : c.getDeclaredMethods()) {
if (method.getReturnType().toString().equals("boolean")) {
try {
String mname = method.getName();
Object o = method.invoke(test, null);
System.out.format("%s() returned %b%n", mname, (Boolean) o);
successful = successful && (Boolean) o;
} catch (Exception e) {
e.printStackTrace();
}
}
}
System.out.println("final answer : " + successful);
}
public boolean a() {
return true;
}
public boolean b() {
return false;
}
public boolean c() {
return false;
}
}
Hope its help to you.
If you want every method to be executed and check if every method scucceded you could simply write
boolean success = updateMainTabsAccess() &
updateUserPaymentTabPermissions() &
updateUserRegistrationTabPermissions() &
updateUserStudentsTabPermissions() &
updateUserFacultyTabPermissions() &
updateUserHomePermissions() &
updateUserInformation();
You have already received some answers.
Fabian's is a good one if you are using java 8.
But to answer directly your points
1.) How do I extract the return values of these methods and use the methods to initialize the Arraylist.
ArrayList<Boolean> resultsList = new ArrayList<Boolean>();
resultsList.add(updateMainTabsAccess());
...
2.) Using for-each loop, is there any possibility of what I'm trying to do? I none, then what do you suggest I do?
boolean res = true;
for (Boolean singleResult : resultsList) {
res = res && singleResult;
}
Here is the old style way to acheive your goal when Lambdas weren't introduced by Java 8.
public class TestMethodsListCall {
public abstract class Checker {
public abstract boolean check();
}
public static void main(String[] args) {
new TestMethodsListCall();
}
public TestMethodsListCall() {
final TestMethodsListCall that = this;
List<Checker> checkers = Arrays.asList( //
new Checker() { public boolean check() { return that.methodA(); } }, //
new Checker() { public boolean check() { return that.methodB(); } } //
// , ...
);
boolean res = true;
for (Checker c : checkers) {
res = res & c.check();
if (!res) {
// Break, display some message or all together
}
}
}
public boolean methodA() {
return true;
}
public boolean methodB() {
return false;
}
}

Java Subclassing Generic Arguments

I'm sorry if this question has been asked before, but I don't really know what to search for.
Anyway, I'm making a math package, and many of the classes extend Function:
package CustomMath;
#SuppressWarnings("rawtypes")
public abstract class Function <T extends Function> {
public abstract Function getDerivative();
public abstract String toString();
public abstract Function simplify();
public abstract boolean equals(T comparison);
}
I want to compare functions to see if they're equal. If they're from the same class, I want to use its specific compare method, but if they're of different classes, I want to return false. Here is one of the classes I have currently:
package CustomMath;
public class Product extends Function <Product> {
public Function multiplicand1;
public Function multiplicand2;
public Product(Function multiplicand1, Function multiplicand2)
{
this.multiplicand1 = multiplicand1;
this.multiplicand2 = multiplicand2;
}
public Function getDerivative() {
return new Sum(new Product(multiplicand1, multiplicand2.getDerivative()), new Product(multiplicand2, multiplicand1.getDerivative()));
}
public String toString() {
if(multiplicand1.equals(new RationalLong(-1, 1)))
return String.format("-(%s)", multiplicand2.toString());
return String.format("(%s)*(%s)", multiplicand1.toString(), multiplicand2.toString());
}
public Function simplify() {
multiplicand1 = multiplicand1.simplify();
multiplicand2 = multiplicand2.simplify();
if(multiplicand1.equals(new One()))
return multiplicand2;
if(multiplicand2.equals(new One()))
return multiplicand1;
if(multiplicand1.equals(new Zero()) || multiplicand2.equals(new Zero()))
return new Zero();
if(multiplicand2.equals(new RationalLong(-1, 1))) //if one of the multiplicands is -1, make it first, so that we can print "-" instead of "-1"
{
if(!multiplicand1.equals(new RationalLong(-1, 1))) // if they're both -1, don't bother switching
{
Function temp = multiplicand1;
multiplicand1 = multiplicand2;
multiplicand2 = temp;
}
}
return this;
}
public boolean equals(Product comparison) {
if((multiplicand1.equals(comparison.multiplicand1) && multiplicand2.equals(comparison.multiplicand2)) ||
(multiplicand1.equals(comparison.multiplicand2) && multiplicand2.equals(comparison.multiplicand1)))
return true;
return false;
}
}
How can I do this?
With generic you have the guarantee that the equals method is only apply with the type 'T', in this case 'Product'. You can't passe another class type.
Another possibility would be in classe Function define:
public abstract boolean equals(Function comparison);
And in classe Product the object comparison whith a comparison instanceof Product
Override Object.equals(Object) method. You don't need to use generics here. Its body will look something like this
if (other instanceof Product) {
Product product = (Product) other;
// Do your magic here
}
return false;

Categories

Resources