How to deal with a huge number of query params' if/else statement (e.g. filter)

selem mn :

A Java's web service is intended to be developed that should deal with 10 @QueryParam at least. That is to say, assuming I have 10 query param, I will end up with 90 if-else statements (I think, minimally) trying to construct all possible compilations.

e.g:

public Response getMethod(
        @QueryParam("a") List<String> a,
        @QueryParam("b") List<String> b,
        @QueryParam("c") List<String> c,
        @QueryParam("d") List<String> d,
        @QueryParam("e") List<String> e

       // ... etc
){

 if (a != null && b == null && c == null ...)
 {
    // bla bla bla - 1
 } 

 else if (a != null && b != null && c == null ...) 
 {
    // bla bla bla - 2
 }

....

My question is how to deal with such situations ? i.e. is there any shortcuts / patterns to minimize the work load here ?

Andy :

General idea would be to build a mapping function: input permutations => outcome processor.

To do this use the 10+ boolean conditions (a != null, b != null...) as bit fields to build a 10-bit key.

// assume a,b,c,d...j are in scope and null or not-null
int inK = ((((a != null) ? 1 : 0) << 0 |
            ((b != null) ? 1 : 0) << 1 |
             ...
            ((j != null) ? 1 : 0) << 9))

// so now inK is a 10-bit number where each bit represents whether the
// corresponding parameter is present.

Next...assume a map is built where a single entry's value is an object representing an "outcome processor" for any key. Let's say this object implements OutcomeProcessor.

HashMap<Integer,OutcomeProcessor> ourMap;

Each outcome processor value has a key value which is a mask. So for example a key value of 0x14 would indicate that parameter 'c' (the 4) and 'e' (the 0x10) must be present to invoke the processor.

An OutcomeProcessor would need access to whichever parameters it requires but the interface is general so provide the parameters as a list (of lists in this case) or more generally a collection.

So to build the ourMap, assume you know the mappings and processor implementations:

// first outcome processor (an instance of `OutcomeProcessor1` needs 'a' and 'c' input parameters
ourMap.put(0x5, new OutcomeProcessor1());

// second outcome processor (needs 'a' and 'd')
ourMap.put(0x9, new OutcomeProcessor2());

// so you'll see that if the input is 'a','c' and 'd' then both processors
// are invoked.

// repeat for all possible outcome processors

Next apply the mask to the map

for (Map.Entry<Integer, OutcomeProcessor> entry : ourMap.entrySet()) {
   int mask = entry.getKey();
   if ((mask & inK) == mask) {
      // invoke processor
      entry.getValue().method(<list of parameters>);
   }
}

Pretty simple really.:)

A few properties of this approach:

  • a single instance of the input permutation (e.g. a & f & h present) can (if desired) yield multiple outcomes.
  • a single outcome can be invoked from multiple input permutations (e.g. an outcome processor may require b & c (0x6) and inputs are (a,b,c,d) or (b,c,f) - both input cases may invoked this processor.)
  • you could get more complicated and have the OutcomeProcessor return a result which clears the bits it serviced. And continue looping until all parameters serviced.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=4332&siteId=1