docs: public <R> Predicate createPredicate(QueryCriteria criteria, CriteriaQuery<R> query, CriteriaBuilder builder) {
          // subquery and root
          Root<TaskImpl> taskRoot = getRoot(query, TaskImpl.class);
          Subquery<Long> subQuery = query.subquery(Long.class);
          Root<TaskVariableImpl> taskVarRoot = subQuery.from(TaskVariableImpl.class);
          subQuery.select(taskVarRoot.get(TaskVariableImpl_.taskId));
  
          // task variable predicate (in subquery)
          Predicate taskVariablePredicate = null;
          String listId = criteria.getListId();
          if( TASK_VARIABLE_COMBINED_ID.equals(listId) ) {
              List<QueryCriteria> taskVarSubCriteriaList = criteria.getCriteria();
              int size = taskVarSubCriteriaList.size();
              Predicate[] taskVarSubPredicates = new Predicate[size];
              for( int i = 0; i < size; ++i ) {
                  taskVarSubPredicates[i] = createSingleTaskVariableCriteriaPredicate(
                          builder, taskVarRoot, taskVarSubCriteriaList.get(i));
              }
              taskVariablePredicate = builder.and(taskVarSubPredicates);
          } else {
              taskVariablePredicate = createSingleTaskVariableCriteriaPredicate(builder, taskVarRoot, criteria);
          }
  
          // add predicate to subquery
          subQuery.where(taskVariablePredicate);
  
          // create predicate for actual query that references subquery
          return taskRoot.get(TaskImpl_.id).in(subQuery);
      }