3

I have a validate() method that checks the arguments passed in a rest url. The arguments are linked to a model class like the following

class SearchCriteria {

String regno;
String hostid;
String domid;
String location;
String provider;

/*Getters and Setters*/
}

I have a utility class that checks if the arguments are set or not.

public class SearchCriteriaUtil {

    public static boolean isRegnoSet(SearchCriteria criteria) {
        return null != criteria.getRegno();
    }

    public static boolean isHostIdSet(SearchCriteria criteria) {
        return null != criteria.getHostId();
    }

    /* Similarly for domid, location, provider */
}

I have a predicate that tests based on the conditions provided in the util and generates a Truth Value String

public class ParameterPredicate<T> implements Predicate<T>{

    final Predicate<T> predicate;
    final String sequence;

    public ParameterPredicate(Predicate<T> predicate, String sequence) {
        this.predicate = predicate;
        this.sequence = sequence;
    }

    @Override
    public String toString() {
        return sequence;
    }

    @Override
    public boolean test(T t) {
        return predicate.test(t);
    }
}

Now, based on the arguments set/notset, regno -set, hostid -set, domid - notset, location - notset, provider - set

My Predicate should evaluate based on the conditions in SearchCriteriaUtil and set the sequence to the appropriate Truth Values...in this case "T T F F T"

In my validate method,

public void validateCriteria(SearchCriteria criteria) {
            List<Predicate<SearchCriteria>> SearchCriteriaPredicate = Arrays.asList(SearchCriteriaUtil::isRegnoSet, SearchCriteriaUtil::isHostIdSet,
                    SearchCriteriaUtil::isDomidSet,
                    SearchCriteriaUtil::isLocationSet,
                    SearchCriteriaUtil::isProviderSet,

Collection<String> desired = Arrays.asList("T F F F F", "T F T T F", "T F T T F", "T F F F T", "T F F F T", "F T F F F");

I am not able to proceed beyond this point, I have to set the sequence and check if it exists in the desired list of truth values.

I was refering to a previous post : Filtering with truth tables

As I am new to java 8, any help is appreciated.

Community
  • 1
  • 1
Raskill
  • 175
  • 13
  • 1
    *in this case "T T F F T"* - in which case? Also, is there any reason for the duplicate sequences in `desired`? – shmosel Mar 20 '17 at 08:29
  • For the example I have taken, when regno -set, hostid -set, domid - notset, location - notset, provider - set My predicate shoud set the value - "T T F F T". That was an error, each string is unique – Raskill Mar 20 '17 at 08:32

2 Answers2

2

Instead of using a util class and dealing with Strings in order to check if a combination of criteria is valid, why not just add something like the following inside your SearchCriteria class:

public boolean hasDesiredCombination() {
    return Criterion.DESIRED_COMBINATONS.contains(
            Arrays.stream(Criterion.values())
            .filter(s -> s.predicate.test(this))
            .collect(Collectors.toCollection(
                    () -> EnumSet.noneOf(Criterion.class)))
            );
}

private static enum Criterion {
    REGNO(s -> s.regno != null),
    HOSTID(s -> s.hostid != null),
    DOMID(s -> s.domid != null),
    LOCATION(s -> s.location != null),
    PROVIDER(s -> s.provider != null);

    private static Set<Set<Criterion>> DESIRED_COMBINATONS =
            new HashSet<>(Arrays.asList(
                    EnumSet.of(REGNO),
                    EnumSet.of(REGNO, DOMID, LOCATION),
                    EnumSet.of(REGNO, PROVIDER),
                    EnumSet.of(HOSTID)
                    ));

    private Predicate<SearchCriteria> predicate;

    private Criterion(Predicate<SearchCriteria> predicate) {
        this.predicate = predicate;
    }
}

Advantages:

  • You don't necessarily have to expose getters and setters
  • It's immediately clear from the source code which combinations are desired
  • The logic is where it belongs: (indirectly) inside the SearchCriteria class
Markus Benko
  • 1,507
  • 8
  • 8
  • DESIRED_COMBINATIONS can also be defined as Stream.of(EnumSet.of(REGNO), EnumSet.of(REGNO, DOMID, LOCATION), EnumSet.of(REGNO, PROVIDER), EnumSet.of(HOSTID)).collect(toSet()). – srborlongan Mar 20 '17 at 10:29
  • 1
    Thanks for the suggestion. I'm sure there are further possibilities of optimization, e.g. don't store `Predicate`s for the criteria but value extractors instead, provided that it's always `null`-checks that will be performed. It depends on how the code is used and if it is preferred to use Java 8 features as much as possible. – Markus Benko Mar 20 '17 at 10:41
  • Thanks much for this solution! This worked well for me! – Raskill Mar 21 '17 at 01:35
1

I'm not sure what the purpose of ParameterPredicate is, but if I've understood correctly, you want check whether a combination of validations (SearchCriteriaPredicate) matches one of a predefined set (desired). If so, this should do it:

String sequence = SearchCriteriaPredicate.stream()
        .map(p -> p.test(criteria) ? "T" : "F")
        .collect(Collectors.joining(" "));

return desired.contains(sequence);
shmosel
  • 49,289
  • 6
  • 73
  • 138