/**
   * Creates an array of JPA predicates for networks list query. Add filter predicates for name and
   * principal if required. 1) if name is specified adds 'name = ?' predicate 2) if name pattern is
   * specified adds 'name like ?' predicate 3) if principal is user of key without ADMIN role adds
   * predicate for filtering not assigned networks 4) if principal is key which has permissions only
   * to specific networks adds 'network.id in (allowed_networks)' predicates
   *
   * @return array of above predicates
   * @see {@link com.devicehive.service.NetworkService#list(String, String, String, boolean,
   *     Integer, Integer, HivePrincipal)}
   */
  public static Predicate[] networkListPredicates(
      CriteriaBuilder cb,
      Root<Network> from,
      Optional<String> nameOpt,
      Optional<String> namePatternOpt,
      Optional<HivePrincipal> principalOpt) {
    List<Predicate> predicates = new LinkedList<>();

    nameOpt.ifPresent(name -> predicates.add(cb.equal(from.get("name"), name)));

    namePatternOpt.ifPresent(pattern -> predicates.add(cb.like(from.get("name"), pattern)));

    principalOpt
        .flatMap(
            principal -> {
              User user = principal.getUser();
              if (user == null && principal.getKey() != null) {
                user = principal.getKey().getUser();
              }
              return ofNullable(user);
            })
        .ifPresent(
            user -> {
              if (!user.isAdmin()) {
                predicates.add(from.join("users").in(user));
              }
            });

    principalOpt
        .map(HivePrincipal::getKey)
        .ifPresent(
            key ->
                predicates.add(
                    cb.or(networkPermissionsPredicates(cb, from, key.getPermissions()))));

    return predicates.toArray(new Predicate[predicates.size()]);
  }