title: Reduce the Cyclomatic complexity of a function
body: <p>I have a function which uses the JPA Criteria API to retrieve data from the database depending on some params I pass to it.
  The params are passed using the object <code>gridParams</code>, as following :</p>
  
  <pre><code>public List&lt;MyObjectDTO&gt; find(final GridParamsDTO gridParams) {
  
          final CriteriaBuilder builder = getCriteriaBuilder();
          final List&lt;Predicate&gt; predicates = new ArrayList&lt;&gt;();
  
          final CriteriaQuery&lt;MyObjectDTO&gt; criteriaQuery = builder.createQuery(MyObjectDTO.class);
  
          final Root&lt;MyObject&gt; from = criteriaQuery.from(MyObject.class);
  
          Join&lt;MyObject, AnotherObject&gt; join = from.join(MyObject_.anotherObject, JoinType.LEFT);
  
          if ((gridParams.getFilter() != null) &amp;&amp; (gridParams.getFilter().length &gt; 0)) {
  
              for (final GridFilterDTO filter : gridParams.getFilter()) {
                  if ("fieldX".equals(filter.getField())) {
                      final List&lt;Predicate&gt; sqPredicates = new ArrayList&lt;&gt;();
                      Subquery&lt;Long&gt; sq = criteriaQuery.subquery(Long.class);
                      Root&lt;ObjectX&gt; sqFrom = sq.from(ObjectX.class);
                      sqPredicates
                              .add(builder.equal(sqFrom.get(ObjectX_.organismeIDE), filter.getFilterSingleValue()));
                      sq.select(sqFrom.get(ObjectX_.referentielID).get(MyObject_.objectX));
                      sq.where(builder.and(sqPredicates.toArray(new Predicate[sqPredicates.size()])));
                      predicates.add(builder.in(from.get(MyObject_.objectX)).value(sq));
                  }
                  if ("fieldA".equals(filter.getField()) || "fieldB".equals(filter.getField())) {
                      final GridFilterOperatorEnum gridFilterEnumValues = GridFilterOperatorEnum.values()[filter.getOperator().ordinal()];
                      switch (gridFilterEnumValues) {
                      case TEXT_CONTAINS:
                          predicates.add(builder.like(builder.upper(from.get(filter.getField())), "%" + filter.getFilterSingleValue().toUpperCase() + "%"));
                          break;
                      case TEXT_START_WITH:
                          predicates.add(builder.like(builder.upper(from.get(filter.getField())), filter.getFilterSingleValue().toUpperCase() + "%"));
                          break;
                      case TEXT_DIFFERENT:
                          predicates.add(builder.notEqual(from.get(filter.getField()), filter.getFilterSingleValue()));
                          break;
                      case TEXT_END_WITH:
                          predicates.add(builder.like(builder.upper(from.get(filter.getField())), "%" + filter.getFilterSingleValue().toUpperCase()));
                          break;
                      case TEXT_EQUALS:
                          predicates.add(builder.equal(builder.upper(from.get(filter.getField())), filter.getFilterSingleValue().toUpperCase()));
                          break;
                      default:
                          break;
                      }
                  }
                  if ("dateField1".equals(filter.getField()) || "dateField2".equals(filter.getField())) {
                      final GridFilterOperatorEnum gridFilterEnumValues = GridFilterOperatorEnum.values()[filter.getOperator().ordinal()];
                      switch (gridFilterEnumValues) {
                      case DATE_EQUALS:
                          predicates.add(builder.equal(from.&lt;LocalDate&gt; get(filter.getField()), LocalDate.parse(filter.getFilterSingleValue())));
                          break;
                      case DATE_BEFORE:
                          predicates.add(builder.lessThan(from.&lt;LocalDate&gt; get(filter.getField()), LocalDate.parse(filter.getFilterSingleValue())));
                          break;
                      case DATE_AFTER:
                          predicates.add(builder.greaterThan(from.&lt;LocalDate&gt; get(filter.getField()), LocalDate.parse(filter.getFilterSingleValue())));
                          break;
                      case DATE_BETWEEN:
                          predicates.add(
                                  builder.between(from.&lt;LocalDate&gt; get(filter.getField()), LocalDate.parse(filter.getFilterSetValues()[0]),
                                          LocalDate.parse(filter.getFilterSetValues()[1])));
                          break;
                      default:
                          break;
                      }
                  }
                  if ("anotherField".equals(filter.getField())) {
                      if (filter.getFilterSetValues().length &gt; 0) {
                          predicates
                                  .add(builder.isTrue(join.get(AnotherObject_.lib).in((Object[]) filter.getFilterSetValues())));
                      } else {
                          predicates.add(join.get(AnotherObject_.lib).isNull());
                      }
  
                  }
              }
  
          }
  
          if (gridParams.hasSort()) {
              List&lt;Order&gt; orderList = new ArrayList&lt;&gt;();
              for (IGridSort gridSort : gridParams.getSort()) {
                  if (ArrayUtils.contains(new String[] { "fieldA", "dateField1", "dateField2", "fieldB" }, gridSort.getField())) {
                      if (gridSort.getSort().equalsIgnoreCase(GridSortDTO.ASC)) {
                          orderList.add(builder.asc(from.get(gridSort.getField())));
                      } else if (gridSort.getSort().equalsIgnoreCase(GridSortDTO.DESC)) {
                          orderList.add(builder.desc(from.get(gridSort.getField())));
                      }
                  }
                  if (gridSort.getField().equalsIgnoreCase("anotherField")) {
                      if (gridSort.getSort().equalsIgnoreCase(GridSortDTO.ASC)) {
                          orderList.add(builder.asc(join.get(AnotherObject_.lib)));
                      } else if (gridSort.getSort().equalsIgnoreCase(GridSortDTO.DESC)) {
                          orderList.add(builder.desc(join.get(AnotherObject_.lib)));
                      }
                  }
              }
              if (!orderList.isEmpty()) {
                  criteriaQuery.orderBy(orderList);
              }
          }
  
          predicates.add(builder.between(builder.literal(LocalDate.now()), from.get(MyObject_.dateDebut),
                  from.get(MyObject_.dateFin)));
  
          criteriaQuery.multiselect(from.get(MyObject_.objectX), from.get(MyObject_.dateDebut), from.get(MyObject_.dateFin),
                  from.get(MyObject_.lib), from.get(MyObject_.coleur), join,
                  from.get(MyObject_.refExterne));
          criteriaQuery.where(builder.and(predicates.toArray(new Predicate[predicates.size()])));
          criteriaQuery.distinct(true);
  
          final TypedQuery&lt;MyObjectDTO&gt; typedQuery = getEntityManager().createQuery(criteriaQuery);
  
          if (gridParams.hasStart()) {
              typedQuery.setFirstResult(gridParams.getStartRow());
          }
          if (gridParams.hasEnd()) {
              typedQuery.setMaxResults(gridParams.getEndRow() - Math.max(0, gridParams.getStartRow()));
          }
  
          return typedQuery.getResultList();
      }
  }
  </code></pre>
  
  <p>The problem is that SonarQube complains that The Cyclomatic Complexity of this method "find" is 31 which is greater than 30 authorized, I did some researches and I found that I have to refactor my function in order to reduce the Cyclomatic Complexity.</p>
  
  <p>In this function I have to test if the <code>gridParams</code> has 4 fields  defined : (start, end, sort and filter), the sort and filter are object arrays so I have to iterate over them.</p>
  
  <p>Ultimately I need to check a lot of fields and I cannot see how this can be done without lots of checks :/</p>
  
  <p>How can I solve this in my case ?</p>