• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

burningwave / reflection / #59

07 Sep 2023 08:55AM UTC coverage: 69.107% (-0.2%) from 69.31%
#59

push

Roberto-Gentili
Releasing new version

944 of 1366 relevant lines covered (69.11%)

0.69 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

39.13
/src/main/java/org/burningwave/Criteria.java
1
/*
2
 * This file is part of Burningwave Reflection.
3
 *
4
 * Author: Roberto Gentili
5
 *
6
 * Hosted at: https://github.com/burningwave/reflection
7
 *
8
 * --
9
 *
10
 * The MIT License (MIT)
11
 *
12
 * Copyright (c) 2022 Roberto Gentili
13
 *
14
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
15
 * documentation files (the "Software"), to deal in the Software without restriction, including without
16
 * limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
17
 * the Software, and to permit persons to whom the Software is furnished to do so, subject to the following
18
 * conditions:
19
 *
20
 * The above copyright notice and this permission notice shall be included in all copies or substantial
21
 * portions of the Software.
22
 *
23
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
24
 * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
25
 * EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
27
 * OR OTHER DEALINGS IN THE SOFTWARE.
28
 */
29
package org.burningwave;
30

31

32
import java.util.Optional;
33
import java.util.function.BiFunction;
34
import java.util.function.BiPredicate;
35
import java.util.function.Function;
36
import java.util.function.Predicate;
37

38
import org.burningwave.function.TriPredicate;
39
import org.burningwave.reflection.Constructors;
40

41
@SuppressWarnings("unchecked")
42
public class Criteria<E, C extends Criteria<E, C, T>, T extends Criteria.TestContext<E, C>> {
1✔
43

44
        protected Function<BiPredicate<T, E>, BiPredicate<T, E>> logicalOperator;
45

46
        protected BiPredicate<T, E> predicate;
47

48
        public final static <E, C extends Criteria<E, C, T>, T extends Criteria.TestContext<E, C>> Criteria<E, C, T> of(final BiPredicate<T, E> predicate) {
49
                return new Criteria<E, C, T>().allThoseThatMatch(predicate);
×
50
        }
51

52
        public final static <E, C extends Criteria<E, C, T>, T extends Criteria.TestContext<E, C>> Criteria<E, C, T> of(final Predicate<E> predicate) {
53
                return new Criteria<E, C, T>().allThoseThatMatch(predicate);
×
54
        }
55

56
        public C allThoseThatMatch(final BiPredicate<T, E> predicate) {
57
                this.predicate = concat(
1✔
58
                        this.predicate,
59
                        (context, entity) -> predicate.test(context, entity)
1✔
60
                );
61
                return (C)this;
1✔
62
        }
63

64
        public C allThoseThatMatch(final Predicate<E> predicate) {
65
                return allThoseThatMatch((context, entity) -> predicate.test(entity)) ;
1✔
66
        }
67

68
        public C and(){
69
                logicalOperator = (predicate) -> this.predicate.and(predicate);
1✔
70
                return (C)this;
1✔
71
        }
72

73
        public C and(C criteria) {
74
                return logicOperation(this.createCopy(), criteria.createCopy(), (predicate) -> predicate::and, newInstance());
×
75
        }
76

77

78
        public C createCopy() {
79
                C copy = newInstance();
1✔
80
                copy.predicate = this.predicate;
1✔
81
                copy.logicalOperator = this.logicalOperator;
1✔
82
                return copy;
1✔
83
        }
84

85

86
        public Predicate<E> getPredicateOrFalsePredicateIfPredicateIsNull() {
87
                return getPredicate(createTestContext(), false);
×
88
        }
89

90
        public Predicate<E> getPredicateOrTruePredicateIfPredicateIsNull() {
91
                return getPredicate(createTestContext(), true);
1✔
92
        }
93

94
        public boolean hasNoPredicate() {
95
                return this.predicate == null;
×
96
        }
97

98
        public C or(){
99
                logicalOperator = (predicate) -> this.predicate.or(predicate);
1✔
100
                return (C)this;
1✔
101
        }
102

103
        public C or(C criteria) {
104
                return logicOperation(this.createCopy(), criteria.createCopy(), (predicate) -> predicate::or, newInstance());
1✔
105
        }
106

107
        public C negate() {
108
                predicate = predicate.negate();
×
109
                return (C)this;
×
110
        }
111

112
        public T testWithFalseResultForNullEntityOrFalseResultForNullPredicate(E entity) {
113
                T context = createTestContext();
×
114
                testWithFalseResultForNullEntityOrFalseResultForNullPredicate(context, entity);
×
115
                return context;
×
116
        }
117

118
        public T testWithFalseResultForNullEntityOrTrueResultForNullPredicate(E entity) {
119
                T context = createTestContext();
×
120
                testWithFalseResultForNullEntityOrTrueResultForNullPredicate(context, entity);
×
121
                return context;
×
122
        }
123

124
        public T testWithTrueResultForNullEntityOrFalseResultForNullPredicate(E entity) {
125
                T context = createTestContext();
×
126
                testWithTrueResultForNullEntityOrFalseResultForNullPredicate(context, entity);
×
127
                return context;
×
128
        }
129

130
        public T testWithTrueResultForNullEntityOrTrueResultForNullPredicate(E entity) {
131
                T context = createTestContext();
×
132
                testWithTrueResultForNullEntityOrTrueResultForNullPredicate(context, entity);
×
133
                return context;
×
134
        }
135

136
        protected BiPredicate<T, E> concat(
137
                BiPredicate<T, E> mainPredicate,
138
                BiPredicate<T, E> otherPredicate
139
        ) {
140
                BiPredicate<T, E> predicate = concat(mainPredicate, this.logicalOperator, otherPredicate);
1✔
141
                this.logicalOperator = null;
1✔
142
                return predicate;
1✔
143
        }
144

145
        @SuppressWarnings("hiding")
146
        protected <E, C extends Criteria<E, C, T>, T extends Criteria.TestContext<E, C>> BiPredicate<T, E> concat(
147
                BiPredicate<T, E> mainPredicate,
148
                Function<BiPredicate<T, E>, BiPredicate<T, E>> logicalOperator,
149
                BiPredicate<T, E> otherPredicate
150
        ) {
151
                return Optional.ofNullable(otherPredicate).map(othPred ->
1✔
152
                        Optional.ofNullable(mainPredicate).map(mainPred ->
1✔
153
                                consumeLogicalOperator(othPred, logicalOperator)
1✔
154
                        ).orElse(othPred)
1✔
155
                ).orElse(mainPredicate);
1✔
156
        }
157

158
        protected T createTestContext() {
159
                return (T)TestContext.<E, C, T>create((C)this);
1✔
160
        }
161

162
        protected T getContextWithFalsePredicateForNullPredicate() {
163
                T context = createTestContext();
×
164
                getPredicate(context, false);
×
165
                return context;
×
166
        }
167

168
        protected T getContextWithTruePredicateForNullPredicate() {
169
                T context = createTestContext();
×
170
                getPredicate(context, true);
×
171
                return context;
×
172
        }
173

174
        protected <V> BiPredicate<T, E> getPredicateWrapper(
175
                final BiFunction<T, E, V[]> valueSupplier,
176
                final TriPredicate<T, V[], Integer> predicate
177
        ) {
178
                return getPredicateWrapper((criteria, entity) -> {
1✔
179
                        V[] array = valueSupplier.apply(criteria, entity);
1✔
180
                        boolean result = false;
1✔
181
                        for (int i = 0; i < array.length; i++) {
1✔
182
                                if (result = predicate.test(criteria, array, i)) {
1✔
183
                                        break;
1✔
184
                                }
185
                        }
186
                        //logDebug("test for {} return {}", entity, result);
187
                        return result;
1✔
188
                });
189
        }
190

191
        protected C logicOperation(C leftCriteria, C rightCriteria,
192
                Function<BiPredicate<T, E>, Function<BiPredicate<? super T, ? super E>, BiPredicate<T, E>>> binaryOperator,
193
                C targetCriteria
194
        ) {
195
                targetCriteria.predicate =
1✔
196
                        leftCriteria.predicate != null?
197
                                (rightCriteria.predicate != null?
198
                                        binaryOperator.apply(leftCriteria.predicate).apply(rightCriteria.predicate) :
1✔
199
                                        leftCriteria.predicate):
200
                                rightCriteria.predicate;
201
                return targetCriteria;
1✔
202
        }
203

204
        protected C newInstance() {
205
                return (C)Constructors.INSTANCE.newInstanceOf(this.getClass());
1✔
206
        }
207

208
        @SuppressWarnings("hiding")
209
        <E, C extends Criteria<E, C, T>, T extends Criteria.TestContext<E, C>> BiPredicate<T,E> consumeLogicalOperator(
210
                BiPredicate<T, E> input,
211
                Function<BiPredicate<T, E>,
212
                BiPredicate<T, E>> logicalOperator
213
        ) {
214
                return Optional.ofNullable(logicalOperator).map(logOp -> {
1✔
215
                        return logicalOperator.apply(input);
1✔
216
                }).orElseGet(() ->
1✔
217
                        Throwables.INSTANCE.throwException(
×
218
                                "A call to and/or method is necessary before calling {} at {}",
219
                                Thread.currentThread().getStackTrace()[10].getMethodName(),
×
220
                                Thread.currentThread().getStackTrace()[11]
×
221
                        )
222
                );
223
        }
224

225
        BiPredicate<T, E> getPredicateWrapper(
226
                BiPredicate<T, E> function
227
        ) {
228
                return Optional.ofNullable(function).map(innPredWrap ->
1✔
229
                        (BiPredicate<T, E>) (criteria, entity) -> innPredWrap.test(criteria, entity)
1✔
230
                ).orElse(null);
1✔
231
        }
232

233
        private Predicate<E> getPredicate(T context, boolean defaultResult) {
234
                return context.setPredicate(
1✔
235
                        this.predicate != null?
236
                                (entity) -> {
237
                                return context.setEntity(entity).setResult(this.predicate.test(
1✔
238
                                        context,
239
                                        entity
240
                                )).getResult();
1✔
241
                        } :
242
                        (entity) -> {
243
                                return context.setEntity(entity).setResult(defaultResult).getResult();
1✔
244
                        }
245
                ).getPredicate();
1✔
246
        }
247

248

249
        private boolean testWithFalseResultForNullEntityOrFalseResultForNullPredicate(T context, E entity) {
250
                return Optional.ofNullable(entity).map(ent -> getPredicate(context, false).test(ent)).orElseGet(() ->
×
251
                        context.setEntity(entity).setResult(false).getResult()
×
252
                );
253
        }
254

255

256
        private boolean testWithFalseResultForNullEntityOrTrueResultForNullPredicate(T context, E entity) {
257
                return Optional.ofNullable(entity).map(ent -> getPredicate(context, true).test(ent)).orElseGet(() ->
×
258
                        context.setEntity(entity).setResult(false).getResult()
×
259
                );
260
        }
261

262

263
        private boolean testWithTrueResultForNullEntityOrFalseResultForNullPredicate(T context, E entity) {
264
                return Optional.ofNullable(entity).map(ent -> getPredicate(context, false).test(ent)).orElseGet(() ->
×
265
                        context.setEntity(entity).setResult(true).getResult()
×
266
                );
267
        }
268

269
        private boolean testWithTrueResultForNullEntityOrTrueResultForNullPredicate(T context, E entity) {
270
                return Optional.ofNullable(entity).map(ent -> getPredicate(context, true).test(ent)).orElseGet(() ->
×
271
                        context.setEntity(entity).setResult(true).getResult()
×
272
                );
273
        }
274

275
        public static class Simple<E, C extends Simple<E, C>> {
×
276

277
                protected Function<Predicate<E>, Predicate<E>> logicalOperator;
278
                protected Predicate<E> predicate;
279

280
                public C allThoseThatMatch(final Predicate<E> predicate) {
281
                        this.predicate = concat(
×
282
                                this.predicate,
283
                                (entity) -> predicate.test(entity)
×
284
                        );
285
                        return (C)this;
×
286
                }
287

288
                public C and(){
289
                        logicalOperator = (predicate) -> this.predicate.and(predicate);
×
290
                        return (C)this;
×
291
                }
292

293
                public C and(C criteria) {
294
                        return logicOperation(this.createCopy(), criteria.createCopy(), (predicate) -> predicate::and, newInstance());
×
295
                }
296

297
                public C createCopy() {
298
                        C copy = newInstance();
×
299
                        copy.predicate = this.predicate;
×
300
                        copy.logicalOperator = this.logicalOperator;
×
301
                        return copy;
×
302
                }
303

304
                public Predicate<E> getPredicateOrFalsePredicateIfPredicateIsNull() {
305
                        return getPredicate(false);
×
306
                }
307

308

309
                public Predicate<E> getPredicateOrTruePredicateIfPredicateIsNull() {
310
                        return getPredicate(true);
×
311
                }
312

313
                public boolean hasNoPredicate() {
314
                        return this.predicate == null;
×
315
                }
316

317
                public C or(){
318
                        logicalOperator = (predicate) -> this.predicate.or(predicate);
×
319
                        return (C)this;
×
320
                }
321

322
                public C or(C criteria) {
323
                        return logicOperation(this.createCopy(), criteria.createCopy(), (predicate) -> predicate::or, newInstance());
×
324
                }
325

326
                public C negate() {
327
                        predicate = predicate.negate();
×
328
                        return (C)this;
×
329
                }
330

331
                public boolean testWithFalseResultForNullEntityOrFalseResultForNullPredicate(E entity) {
332
                        return Optional.ofNullable(entity).map(ent -> getPredicateOrFalsePredicateIfPredicateIsNull().test(ent)).orElseGet(() ->
×
333
                                false
×
334
                        );
335
                }
336

337

338
                public boolean testWithFalseResultForNullEntityOrTrueResultForNullPredicate(E entity) {
339
                        return Optional.ofNullable(entity).map(ent -> getPredicateOrTruePredicateIfPredicateIsNull().test(ent)).orElseGet(() ->
×
340
                                false
×
341
                        );
342
                }
343

344
                public boolean testWithFalseResultForNullPredicate(E entity) {
345
                        return getPredicateOrFalsePredicateIfPredicateIsNull().test(entity);
×
346
                }
347

348
                public boolean testWithTrueResultForNullEntityOrFalseResultForNullPredicate(E entity) {
349
                        return Optional.ofNullable(entity).map(ent -> getPredicateOrFalsePredicateIfPredicateIsNull().test(ent)).orElseGet(() ->
×
350
                                true
×
351
                        );
352
                }
353

354
                public boolean testWithTrueResultForNullEntityOrTrueResultForNullPredicate(E entity) {
355
                        return Optional.ofNullable(entity).map(ent -> getPredicateOrTruePredicateIfPredicateIsNull().test(ent)).orElseGet(() ->
×
356
                                true
×
357
                        );
358
                }
359

360
                public boolean testWithTrueResultForNullPredicate(E entity) {
361
                        return getPredicateOrTruePredicateIfPredicateIsNull().test(entity);
×
362
                }
363

364
                @SuppressWarnings("hiding")
365
                protected <E, C extends Simple<E, C>> Predicate<E> concat(
366
                        Predicate<E> mainPredicate,
367
                        Function<Predicate<E>, Predicate<E>> logicalOperator,
368
                        Predicate<E> otherPredicate
369
                ) {
370
                        return Optional.ofNullable(otherPredicate).map(othPred ->
×
371
                                Optional.ofNullable(mainPredicate).map(mainPred ->
×
372
                                        consumeLogicalOperator(othPred, logicalOperator)
×
373
                                ).orElse(othPred)
×
374
                        ).orElse(mainPredicate);
×
375
                }
376

377
                protected Predicate<E> concat(
378
                        Predicate<E> mainPredicate,
379
                        Predicate<E> otherPredicate
380
                ) {
381
                        Predicate<E> predicate = concat(mainPredicate, this.logicalOperator, otherPredicate);
×
382
                        this.logicalOperator = null;
×
383
                        return predicate;
×
384
                }
385

386
                protected <V> Predicate<E> getPredicateWrapper(
387
                        final Function<E, V[]> valueSupplier,
388
                        final BiPredicate<V[], Integer> predicate
389
                ) {
390
                        return getPredicateWrapper((entity) -> {
×
391
                                V[] array = valueSupplier.apply(entity);
×
392
                                boolean result = false;
×
393
                                for (int i = 0; i < array.length; i++) {
×
394
                                        if (result = predicate.test(array, i)) {
×
395
                                                break;
×
396
                                        }
397
                                }
398
                                //logDebug("test for {} return {}", entity, result);
399
                                return result;
×
400
                        });
401
                }
402

403
                protected C logicOperation(C leftCriteria, C rightCriteria,
404
                        Function<Predicate<E>, Function<Predicate< ? super E>, Predicate<E>>> binaryOperator,
405
                        C targetCriteria
406
                ) {
407
                        targetCriteria.predicate =
×
408
                                leftCriteria.predicate != null?
409
                                        (rightCriteria.predicate != null?
410
                                                binaryOperator.apply(leftCriteria.predicate).apply(rightCriteria.predicate) :
×
411
                                                leftCriteria.predicate):
412
                                        rightCriteria.predicate;
413
                        return targetCriteria;
×
414
                }
415

416
                protected C newInstance() {
417
                        return (C)Constructors.INSTANCE.newInstanceOf(this.getClass());
×
418
                }
419

420
                @SuppressWarnings("hiding")
421
                <E, C extends Simple<E, C>> Predicate<E> consumeLogicalOperator (
422
                        Predicate<E> input,
423
                        Function<Predicate<E>,
424
                        Predicate<E>> logicalOperator
425
                ) {
426
                        return Optional.ofNullable(logicalOperator).map(logOp -> {
×
427
                                return logicalOperator.apply(input);
×
428
                        }).orElseGet(() ->
×
429
                                Throwables.INSTANCE.throwException(
×
430
                                        "A call to and/or method is necessary before calling {} at {}",
431
                                        Thread.currentThread().getStackTrace()[10].getMethodName(),
×
432
                                        Thread.currentThread().getStackTrace()[11]
×
433
                                )
434
                        );
435
                }
436

437
                Predicate<E> getPredicateWrapper(
438
                        Predicate<E> function
439
                ) {
440
                        return Optional.ofNullable(function).map(innPredWrap ->
×
441
                                (Predicate<E>) (entity) -> innPredWrap.test(entity)
×
442
                        ).orElse(null);
×
443
                }
444

445
                private Predicate<E> getPredicate(boolean defaultResult) {
446
                        return this.predicate != null?
×
447
                                        (entity) -> {
448
                                                return this.predicate.test(entity);
×
449
                                } :
450
                                (entity) -> {
451
                                        return defaultResult;
×
452
                                };
453
                }
454
        }
455

456
        public static class TestContext<E, C extends Criteria<E, C, ?>> extends Context {
457
                private enum Elements {
1✔
458
                        ENTITY,
1✔
459
                        PREDICATE,
1✔
460
                        TEST_RESULT,
1✔
461
                        THIS_CRITERIA
1✔
462
                }
463

464
                protected TestContext(C criteria) {
465
                        super();
1✔
466
                        put(Elements.THIS_CRITERIA, criteria);
1✔
467
                }
1✔
468

469
                public static <E, C extends Criteria<E, C, T>, T extends Criteria.TestContext<E, C>> TestContext<E, C> create(C criteria) {
470
                        return new TestContext<>(criteria);
1✔
471
                }
472

473
                public C getCriteria() {
474
                        return get(Elements.THIS_CRITERIA);
×
475
                }
476

477
                public E getEntity() {
478
                        return get(Elements.ENTITY);
×
479
                }
480

481
                public Predicate<E> getPredicate() {
482
                        return get(Elements.PREDICATE);
1✔
483
                }
484

485
                public Boolean getResult() {
486
                        return super.get(Elements.TEST_RESULT);
1✔
487
                }
488

489
                <T extends Criteria.TestContext<E, C>> T setEntity(E entity) {
490
                        put(Elements.ENTITY, entity);
1✔
491
                        return (T) this;
1✔
492
                }
493

494
                <T extends Criteria.TestContext<E, C>> T setPredicate(Predicate<E> predicate) {
495
                        put(Elements.PREDICATE, predicate);
1✔
496
                        return (T)this;
1✔
497
                }
498

499
                <T extends Criteria.TestContext<E, C>> T setResult(Boolean result) {
500
                        put(Elements.TEST_RESULT, result);
1✔
501
                        return (T) this;
1✔
502
                }
503
        }
504

505
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc