Remove multiple Conditions joined by OR from IF-statement - java

I want to remove multiple conditions from the if statement.
How can I achieve that?
I think switch is not what I'm looking for. I'm thinking of something that respect the Open close principal or using an interface to call the different boolean method.
Now I'm using :
if (utilisateur.isAdmin() || utilisateur.isWebMaster() || utilisateur.isAdministrateurLiferay() || utilisateur.estResponsableCommercial()) {
Example of a method :
public boolean estResponsableCommercial() {
return roles.stream().anyMatch(Role::isResponsableCommercial);
}

you can try with an Enum:
public enum Role {
public abstract boolean check(User user);
ADMIN {
public boolean check(User user) {
return user.isAdmin();
}
},
WEBMASTER {
public boolean check(User user) {
return user.isWebMaster();
}
};
public boolean checkRoles(User user) {
for(Role role : Role.values()) {
if(role.check(user)) {
return true;
}
}
return false;
}
}

It seems like you're looking for a way to combine predicates in order to use them in operations like anyMatch.
If so, you can achieve this using static method Predicate.or():
#SafeVarargs
public static <T> Predicate<T> combineWithOr(Predicate<T>... predicates) {
return Arrays.stream(predicates).reduce(t -> true, Predicate::or); // if `predicates` is empty then method would return `true`, another way of expressing this: `reduce(Predicate::or).orElse(t -> true)`
}
And that how you can apply it to obtain a composite predicate:
Predicate<UserRole> combinedPredicate = combineWithOr(
UserRole::isAdmin,
UserRole::isWebMaster,
UserRole::isAdministrateurLiferay,
UserRole::estResponsableCommercial
);
public static boolean hasMatchingRole(Collection<UserRole> roles,
Predicate<UserRole> predicate){
return roles.stream().anyMatch(predicate);
}

private static boolean isEstResponsableCommercial(List<String> roles, String roleYouLookingFor) {
return roles.stream().anyMatch(r->r.equals(roleYouLookingFor));
}
Signature of anyMatch is:
boolean anyMatch(Predicate<? super T> predicate)

Related

Java imitate and, or for concatenate rule

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).

Cleanest pattern for filtering objects of unknown type?

I have an application that takes json objects from a queue, deserializes them to a model, applies a list of filters, and sends the objects that pass all filters through to another queue.
The two complicating criteria are:
The set of filters is determined and injected via Spring profile at startup.
The type of object that the json is being deserialized to is also determined the by the Spring profile at startup.
The following solution is ugly because it involves casting:
public class MessageTypeOne {
public int someField;
}
public class MessageTypeTwo {
public int otherField;
}
public interface MessageFilter {
boolean doesFilterPass(Object object);
}
#Component
#Profile("ProfileOne")
public class OneOfMyMessageFilters implements MessageFilter {
public boolean doesFilterPass(Object object) {
MessageTypeOne message = (MessageTypeOne)object;
if (message.someField == something) {
return false;
} else return true;
}
}
#Component
#Profile("ProfileTwo")
public class AnotherOneOfMyMessageFilters implements MessageFilter {
public boolean doesFilterPass(Object object) {
MessageTypeTwo message = (MessageTypeTwo)object;
if (message.otherField == something) {
return false;
} else return true;
}
}
#Service
public class MessageFilterService {
// injected at runtime via Spring profile
private Set<MessageFilter> messageFilters
#AutoWired
public MessageFilterService(Set<MessageFilter> messageFilters) {
this.messageFilters = messageFilters;
}
public boolean passesAllFilters(Object object) throws IOException {
for (MessageFilter filter : messageFilters) {
if (!filter.doesFilterPass(object)) {
return false;
}
}
return true;
}
}
What's the cleanest pattern for cases like these? I've read about the visitor pattern but I'm not sure that's any better than casting like this.
As far as design pattern is concerned, I think it is of type Strategy pattern. I am not talking about Spring way of implementation. You may have n number of filters, but you have to choose based upon the context. So strategy pattern is best fitted here. Others can provide other patterns. You can strategy pattern in the below link.
https://en.wikipedia.org/wiki/Strategy_pattern
What about visitor pattern with Java reflection? Here is an old article:
https://www.javaworld.com/article/2077602/java-tip-98--reflect-on-the-visitor-design-pattern.html
When you want to decouple messages from filters and relation is many to many you can always use Chain of Responsibility.
#Service
public class MessageFiltersAggregator {
private MessageFilter chainEntryNode;
#AutoWired
public MessageFilterService(Set<MessageFilter> messageFilters) {
this.chainEntryNode = buildChain(messageFilters);
}
public boolean passesAllFilters(Object object) throws IOException {
return chainEntryNode.doesFilterPass(object);
}
}
You need to implement buildChain method which creates chain from collection. Of course, each element in chain should have next property. In this case MessageFilter could look like below:
public abstract class MessageFilter {
private MessageFilter next;
//constructors, setters, etc
public boolean doesFilterPass(Object object) {
boolean res = true;
if (canHandle(object)) {
res = validate(object);
}
return res && next.doesFilterPass(object);
}
public abstract boolean validate(Object object);
public abstract boolean canHandle(Object object);
}
Abstract class contains chain logic you just need to implement two methods in each subclass. One of implementation could look like below:
public class AnotherOneOfMyMessageFilters extends MessageFilter {
public boolean canHandle(Object object) {
return object instanceof MessageTypeTwo;
}
public boolean validate(Object object) {
MessageTypeTwo message = (MessageTypeTwo)object;
return message.otherField == something;
}
}
All above classes are just example created without IDE so could have issues in syntax but should give you an idea how it should work.
See also:
Chain of Responsibility in Java
Chain of Responsibility Design Pattern in Java
If I understand your problem correctly, then it's possible to configure your Spring profile in a way that makes your filters throw ClassCastExceptions.
Assuming that you configuration options are the way you want, then it demonstrates the only real problem with your design -- your filters can be applied to any Object, and that's what the interface says -- doesFilterPass( Object ) -- but your filters only really work with certain types of objects.
That's what you need to fix. If the filter is applied to a strange type of object, does it pass or fail? You can decide this on a per-filter basis and then just fix it like this:
public boolean doesFilterPass(Object object) {
if (!(object instanceOf MessageTypeTwo)) {
return true;
}
MessageTypeTwo message = (MessageTypeTwo)object;
if (message.otherField == something) {
return false;
} else return true;
}
Easy peasy.
I know you don't like the cast, but it's a direct result of the configuration options you provide -- the profile can be configured to apply filters to any kind of object. You just need to support that, and that means there has to be casting somewhere.
This became much cleaner with generics. Since I know what type of Object each filter can handle I can just do this, eliminating the casting:
public class MessageTypeOne {
public int someField;
}
public class MessageTypeTwo {
public int otherField;
}
public interface MessageFilter<T> {
boolean doesFilterPass(T message);
}
#Component
#Profile("ProfileOne")
public class OneOfMyMessageFilters<T extends MessageTypeOne> implements MessageFilter<T> {
public boolean doesFilterPass(MessageTypeOne message) {
if (message.someField == something) {
return false;
} else return true;
}
}
#Component
#Profile("ProfileTwo")
public class AnotherOneOfMyMessageFilters<T extends MessageTypeTwo> implements MessageFilter<T> {
public boolean doesFilterPass(MessageTypeTwo message) {
if (message.otherField == something) {
return false;
} else return true;
}
}
#Service
public class MessageFilterServiceImpl<T> implements MessageFilterService<T> {
// injected at runtime via Spring profile
private Set<MessageFilter<T>> messageFilters
#AutoWired
public MessageFilterService(Set<MessageFilter<T>> messageFilters) {
this.messageFilters = messageFilters;
}
public boolean passesAllFilters(T message) throws IOException {
for (MessageFilter filter : messageFilters) {
if (!filter.doesFilterPass(message)) {
return false;
}
}
return true;
}
}
public interface MessageFilterService<T> {
boolean passesAllFilters(T rawEvent) throws IllegalArgumentException;
}

Function with toggle options

I've made a basic function to check a password complies with various business rules. Has an upper case character, has a number etc.
I'd like to make this function more flexible and configurable by toggling these options on and off as desired. The only way I can think of to do this is as so:
public static boolean isPasswordValid(String pwd, boolean checkUpper, boolean checkLower, boolean checkNum) {
boolean hasUppercase = !pwd.equals(pwd.toLowerCase(Locale.getDefault()));
boolean hasLowercase = !pwd.equals(pwd.toUpperCase(Locale.getDefault()));
boolean hasNumeric = pwd.matches(".*\\d+.*");
boolean isValid = false;
if(checkUpper){
if(hasUppercase) {
isValid = true;
}else{
return isValid;
}
}
return isValid;
}
I feel like there is a much better method, using Enums or something. I'd like to be able to pass in the password and just one extra parameter to act as a flag to enable various checks. Inevitably I'll need to add more as time goes on.
If I were to use enums, by my way of thinking, I'd have to define one eNum for every possible case. i.e. upper, upper_and_lower, upper_and_numeric. Which would get very complex if I had to add in more options.
Any ides and suggestions would be most welcome. Thanks.
You can use EnumSet, which is a specialized set for enums.
public static enum Validation {
UPPER, LOWER, DIGIT //etc.
}
public static boolean isPasswordValid(String pwd, EnumSet<Validation> validations) {
//...
}
Then, you can use any combination of validations by adding necessary values to the set. Example:
EnumSet<Validation> validation = EnumSet.of(Validation.UPPER, Validation.LOWER);
if (isPasswordValid(pass, validation)) {
//...
}
You could do it with regex:
^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).*$
You validate for password with all three combinations (number, upper, lower case alphabets)
String pwd = "aaaaaaabbbbCCCC43333333222111";
if (pwd.matches("^(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).*$")) {
System.out.println("It has all three combinations");
} else {
System.out.println("Invalid password");
}
Output:
It has all three combinations
Less Simple, but really flexible, using method chaining:
public abstract class Clause {
public abstract boolean match(string value);
}
public final class UpperCaseClause extends Clause {
#Override
public boolean match(string value) {
return !value.equals(value.toLowerCase(Locale.getDefault()));
}
}
public final class LowerCaseClause extends Clause {
#Override
public override boolean match(string value) {
return !value.equals(value.toUpperCase(Locale.getDefault()));
}
}
public final class NumericClause extends Clause {
#Override
public override boolean match(string value) {
return value.matches(".*\\d+.*");
}
}
public final class Validator {
private List<Clause> clauses;
public Validator() {
clauses = new ArrayList<Clause>();
}
public Validator addClause(Clause toAdd) {
clauses.add(toAdd);
return this;
}
public boolean valid(string value) {
boolean isValid = true;
for(clause in clauses) {
isValid &= clause.match(value);
if (!isValid) {
break;
}
}
return isValid;
}
}
[... you could create this anywhere and cache it]
Validator allValidator = new Validator().addClause(new UpperCaseClause())
.addClause(new LowerCaseClause())
.addClause(new NumericClause());
[...]
public static boolean isPasswordValid(String pwd, Validator validator) {
validator.valid(pwd);
}
[... then pass in the validator you wish to use]
isPasswordValid(pwd, allValidator);
[...]

Dozer mapping is vs get

In the following case:
public class Race {
private Status finished;
public Status getFinished() {
return finsihed;
}
public void setFinished(Status finished) {
this.finsihed = finished;
}
public boolean isFinished() {
return finished == Status.FINISHED;
}
}
public class RaceDTO {
private Status finished;
public Status getFinished() {
return finsihed;
}
public void setFinished(Status finished) {
this.finsihed = finished;
}
}
Dozer is mapping a RaceDTO class with isFinished() method rather than getFinished(). Why is that and how to cope with it? I prefer to use annotations.
If return type is boolean "is" prefix is used instead of "get"
isFinished is a common way to indicate a boolean return type.
if ( race.isFinished() ) {}
vs
if ( race.getFinished() ) {}
the first is abit more clear
According to section "8.3 Design Patterns for Properties" of JavaBens specification, boolean properties may have a "is" acccess method. If has one, this method will be preferential over the "get" if one exists.
I found an answer. I have to add annotation over a field, and then neither method is invoked
public class Race {
#Mapping("finished")
private Status finished;
public Status getFinished() {
return finsihed;
}
public void setFinished(Status finished) {
this.finsihed = finished;
}
public boolean isFinished() {
return finished == Status.FINISHED;
}
}

How to override Tapestry's two-way boolean coercion with three-way one?

Consider this case.
You have a class which you cannot change or extend in any way.
public class Foo {
...
private Boolean bar;
...
}
You need to edit the fields of that class via BeanEditor, but the logic behind that class allows and uses the fact that Boolean can have, so to say, 3 states: null, true and false.
Tapestry will, however, give you a checkbox with only 2 options, true or false.
So, people online suggest that you convert your Boolean type property to BooleanExtendedEnum type property which could represent three way logic.
public enum BooleanExtendedEnum {
UNDEFINED(null),
TRUE(Boolean.TRUE),
FALSE(Boolean.FALSE);
private Boolean booleanValue;
private static Map<Boolean, BooleanExtendedEnum> booleanToExtendedMap = new HashMap<Boolean, BooleanExtendedEnum>();
static {
for (BooleanExtendedEnum be : BooleanExtendedEnum.values()) {
booleanToExtendedMap.put(be.booleanValue, be);
}
}
private BooleanExtendedEnum(Boolean booleanValue) {
this.booleanValue = booleanValue;
}
public Boolean getBooleanValue() {
return booleanValue;
}
public static BooleanExtendedEnum getBooleanExtendedValue(Boolean booleanInput) {
return booleanToExtendedMap.get(booleanInput);
}
}
Since you cannot change your Foo class, you'll need to create a coercer for Boolean <=> BooleanExtendedEnum.
Coercion<Boolean, BooleanExtendedEnum> threeWayBooleanToExtended = new Coercion<Boolean, BooleanExtendedEnum>() {
#Override
public BooleanExtendedEnum coerce(Boolean input) {
if (input == null) {
return BooleanExtendedEnum.UNDEFINED;
} else {
return BooleanExtendedEnum.getBooleanExtendedEnumValue(input);
}
}
};
Coercion<BooleanExtendedEnum, Boolean> threeWayExtendedToBoolean = new Coercion<BooleanExtendedEnum, Boolean>() {
#Override
public Boolean coerce(BooleanExtendedEnum input) {
if (input == null) {
return null;
} else {
return input.getBooleanValue();
}
}
};
configuration.add(new CoercionTuple<Boolean, BooleanExtendedEnum>(Boolean.class, BooleanExtendedEnum.class, threeWayBooleanToExtended));
configuration.add(new CoercionTuple<BooleanExtendedEnum, Boolean>(BooleanExtendedEnum.class, Boolean.class, threeWayExtendedToBoolean));
Let's assume you have done something as simple as this in your BeanEditor in your tml:
<p:bar>
<div class="t-beaneditor-row">
<label>Bar Value</label>
<t:select t:id="fooBar" t:value="foo.bar" t:model="booleanExtendedSelectModel" t:blankOption="NEVER"/>
</div>
</p:bar>
... and provided the SelectModel like this:
public SelectModel getBooleanExtendedSelectModel() {
return new EnumSelectModel(BooleanExtendedEnum.class, messages);
}
Tapestry will create a drop-down list with three options
Undefined
True
False
However, the real Boolean values it will coerce those displayed values to will be
Undefined -> true
True -> true
False -> false
How can one achieve the desired effect (Undefined -> null), with limitations of not changing the class or wrapping it in another class which has Boolean type fields replaced with BooleanExtendedEnum type ones or using any other "hacky" solution?
The "glue" between the BeanEditor and the backing bean is the BeanModel. BeanModels are created by the BeanModelSource which in turn uses PropertyConduitSource.
It's quite simple to decorate the PropertyConduitSource to use Ternary instead of Boolean.
eg
public class MyAppModule {
public PropertyConduitSource decoratePropertyConduitSource(final PropertyConduitSource old) {
return new PropertyConduitSource() {
public PropertyConduit create(Class rootType, String expression) {
PropertyConduit conduit = old.create(rootType, expression);
// you cound also check for conduit.getAnnotation(AllowNull.class)
// and then annotate your bean properties for a more granular approach
if (Boolean.class.equals(conduit.getPropertyType()) {
return new TernaryPropertyConduit(conduit);
}
return conduit;
}
}
}
}
public class TernaryPropertyConduit implements PropertyConduit {
private PropertyConduit delegate;
public getPropertyType() { return Ternary.class };
public set(Object instance, Object value) {
delegate.set(instance, ((Ternary) value).asBoolean());
}
public get(Object) {
Boolean bValue = (Boolean) delegate.get(instance);
return Ternary.valueOf(instance);
}
}
You could add a property to your page and use a custom block.
public enum Ternary {
TRUE(Boolean.TRUE), FALSE(Boolean.FALSE), UNDEFINED(null);
public static Ternary valueOf(Boolean value) { ... }
public Boolean asBoolean() { ... }
}
public class MyPage {
#Property
private Foo foo;
public Ternary getTernaryBar() {
return Ternary.valueOf(foo.getBar());
}
public void setTernaryBar(Ternary tBar) {
foo.setBar(tBar.asBoolean());
}
}
<t:beaneditor t:id="foo" exclude="bar" add="ternaryBar">
<p:ternaryBar>
<t:label for="ternaryBar"/>
<t:select t:id="ternaryBar" />
</p:ternaryBar>
</t:beaneditor>

Categories

Resources