AbstractAdoService implements AdoService<ADO> { static Optional<Predicate> reduce(Function<Predicate[], Predicate> op, Stream<Optional<Predicate>> predicates) { Predicate[] cleaned = predicates.filter(Optional::isPresent).map(Optional::get).toArray(Predicate[]::new); switch (cleaned.length) { case 0: return Optional.empty(); case 1: return Optional.of(cleaned[0]); default: return Optional.of(op.apply(cleaned)); } } AbstractAdoService(Class<ADO> elementClass); long count(); Timestamp getLatestChangeDate(); @Override List<ADO> getAll(); List<ADO> getAll(String orderProperty, boolean asc); long countAfter(Date since); List<ADO> getAllAfter(Date since, User user); List<String> getAllUuids(); List<Long> getAllIds(User user); List<ADO> getByUuids(List<String> uuids); @SuppressWarnings("rawtypes") abstract Predicate createUserFilter(CriteriaBuilder cb, CriteriaQuery cq, From<?, ADO> from); Predicate createChangeDateFilter(CriteriaBuilder cb, From<?, ADO> from, Timestamp date); Predicate createChangeDateFilter(CriteriaBuilder cb, From<?, ADO> from, Date date); Predicate recentDateFilter(CriteriaBuilder cb, Date date, Path<Date> datePath, int amountOfDays); @Override ADO getById(long id); ADO getByReferenceDto(ReferenceDto dto); @Override ADO getByUuid(@NotNull String uuid); @Override Boolean exists(@NotNull String uuid); @Override void ensurePersisted(ADO ado); @Override void persist(ADO persistme); @Override void delete(ADO deleteme); @Override void doFlush(); static Predicate and(CriteriaBuilder cb, Predicate... predicates); @SafeVarargs static Optional<Predicate> and(CriteriaBuilder cb, Optional<Predicate>... predicates); static Predicate or(CriteriaBuilder cb, Predicate... predicates); @SafeVarargs static Optional<Predicate> or(CriteriaBuilder cb, Optional<Predicate>... predicates); static Predicate greaterThanAndNotNull(CriteriaBuilder cb, Expression<? extends Timestamp> path, Timestamp date); static StringBuilder appendInFilterValues(
		StringBuilder filterBuilder,
		List<Object> filterBuilderParameters,
		List<T> values,
		Function<T, ?> valueMapper); List<Long> getIdsByReferenceDtos(List<? extends ReferenceDto> references);  }
@Test public void testReduce() { assertThat(AbstractAdoService.reduce(null), nullValue()); assertThat(AbstractAdoService.reduce(null, (Predicate) null), nullValue()); assertThat(AbstractAdoService.reduce(null, null, null), nullValue()); DummyPredicate p0 = new DummyPredicate(); assertThat(AbstractAdoService.reduce(null, p0), sameInstance(p0)); assertThat(AbstractAdoService.reduce(null, p0, null), sameInstance(p0)); assertThat(AbstractAdoService.reduce(null, null, p0), sameInstance(p0)); assertThat(AbstractAdoService.reduce(null, null, null, null, null, p0, null, null, null), sameInstance(p0)); DummyPredicate p1 = new DummyPredicate(); DummyPredicate p2 = new DummyPredicate(); DummyPredicate p3 = new DummyPredicate(); DummyPredicate pr = new DummyPredicate(); List<Predicate> restrictions = new ArrayList<>(); Function<Predicate[], Predicate> op = a -> { restrictions.clear(); restrictions.addAll(Arrays.asList(a)); return pr; }; assertThat(AbstractAdoService.reduce(op, p0, p1), sameInstance(pr)); assertThat(restrictions, Matchers.contains(p0, p1)); assertThat(AbstractAdoService.reduce(op, null, null, p0, null, p1, null, null), sameInstance(pr)); assertThat(restrictions, Matchers.contains(p0, p1)); assertThat(AbstractAdoService.reduce(op, null, null, p0, null, p1, null, p2, p3, null), sameInstance(pr)); assertThat(restrictions, Matchers.contains(p0, p1, p2, p3)); }