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

burningwave / reflection / #67

03 Oct 2023 02:53PM UTC coverage: 69.107%. Remained the same
#67

push

Roberto-Gentili
Dependency update. 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
        public C or(){
78
                logicalOperator = (predicate) -> this.predicate.or(predicate);
1✔
79
                return (C)this;
1✔
80
        }
81

82
        public C or(C criteria) {
83
                return logicOperation(this.createCopy(), criteria.createCopy(), (predicate) -> predicate::or, newInstance());
1✔
84
        }
85

86
        public C negate() {
87
                predicate = predicate.negate();
×
88
                return (C)this;
×
89
        }
90

91
        public C createCopy() {
92
                C copy = newInstance();
1✔
93
                copy.predicate = this.predicate;
1✔
94
                copy.logicalOperator = this.logicalOperator;
1✔
95
                return copy;
1✔
96
        }
97

98
        public Predicate<E> getPredicateOrFalsePredicateIfPredicateIsNull() {
99
                return getPredicate(createTestContext(), false);
×
100
        }
101

102
        public Predicate<E> getPredicateOrTruePredicateIfPredicateIsNull() {
103
                return getPredicate(createTestContext(), true);
1✔
104
        }
105

106
        public boolean hasNoPredicate() {
107
                return this.predicate == null;
×
108
        }
109

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

246

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

253

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

260

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

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

273
        public static class Simple<E, C extends Simple<E, C>> {
×
274

275
                protected Function<Predicate<E>, Predicate<E>> logicalOperator;
276
                protected Predicate<E> predicate;
277

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

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

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

295
                public C or(){
296
                        logicalOperator = (predicate) -> this.predicate.or(predicate);
×
297
                        return (C)this;
×
298
                }
299

300
                public C or(C criteria) {
301
                        return logicOperation(this.createCopy(), criteria.createCopy(), (predicate) -> predicate::or, newInstance());
×
302
                }
303

304
                public C negate() {
305
                        predicate = predicate.negate();
×
306
                        return (C)this;
×
307
                }
308

309
                public C createCopy() {
310
                        C copy = newInstance();
×
311
                        copy.predicate = this.predicate;
×
312
                        copy.logicalOperator = this.logicalOperator;
×
313
                        return copy;
×
314
                }
315

316
                public Predicate<E> getPredicateOrFalsePredicateIfPredicateIsNull() {
317
                        return getPredicate(false);
×
318
                }
319

320

321
                public Predicate<E> getPredicateOrTruePredicateIfPredicateIsNull() {
322
                        return getPredicate(true);
×
323
                }
324

325
                public boolean hasNoPredicate() {
326
                        return this.predicate == null;
×
327
                }
328

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

335

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

503
}
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