FrequencyTrie.java

1
/*******************************************************************************
2
 * Copyright (C) 2026, Leo Galambos
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright notice,
9
 *    this list of conditions and the following disclaimer.
10
 *
11
 * 2. Redistributions in binary form must reproduce the above copyright notice,
12
 *    this list of conditions and the following disclaimer in the documentation
13
 *    and/or other materials provided with the distribution.
14
 *
15
 * 3. Neither the name of the copyright holder nor the names of its contributors
16
 *    may be used to endorse or promote products derived from this software
17
 *    without specific prior written permission.
18
 *
19
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
 * POSSIBILITY OF SUCH DAMAGE.
30
 ******************************************************************************/
31
package org.egothor.stemmer;
32
33
import java.io.DataInputStream;
34
import java.io.DataOutputStream;
35
import java.io.IOException;
36
import java.io.InputStream;
37
import java.io.OutputStream;
38
import java.nio.charset.StandardCharsets;
39
import java.security.MessageDigest;
40
import java.security.NoSuchAlgorithmException;
41
import java.util.ArrayList;
42
import java.util.Arrays;
43
import java.util.Collections;
44
import java.util.IdentityHashMap;
45
import java.util.LinkedHashMap;
46
import java.util.List;
47
import java.util.Locale;
48
import java.util.Map;
49
import java.util.Objects;
50
import java.util.concurrent.locks.ReentrantLock;
51
import java.util.function.IntFunction;
52
import java.util.logging.Level;
53
import java.util.logging.Logger;
54
55
import org.egothor.stemmer.trie.CompiledNode;
56
import org.egothor.stemmer.trie.LocalValueSummary;
57
import org.egothor.stemmer.trie.MutableNode;
58
import org.egothor.stemmer.trie.ReducedNode;
59
import org.egothor.stemmer.trie.ReductionContext;
60
import org.egothor.stemmer.trie.ReductionSignature;
61
62
/**
63
 * Read-only trie mapping {@link String} keys to one or more values with
64
 * frequency tracking.
65
 *
66
 * <p>
67
 * A key may be associated with multiple values. Each value keeps the number of
68
 * times it was inserted during the build phase. The method {@link #get(String)}
69
 * returns the locally most frequent value stored at the terminal node of the
70
 * supplied key, while {@link #getAll(String)} returns all locally stored values
71
 * ordered by descending frequency.
72
 *
73
 * <p>
74
 * If multiple values have the same local frequency, their ordering is
75
 * deterministic. The preferred value is selected by the following tie-breaking
76
 * rules, in order:
77
 * <ol>
78
 * <li>shorter {@link String} representation wins, based on
79
 * {@code value.toString()}</li>
80
 * <li>if the lengths are equal, lexicographically lower {@link String}
81
 * representation wins</li>
82
 * <li>if the textual representations are still equal, first-seen insertion
83
 * order remains stable</li>
84
 * </ol>
85
 *
86
 * <p>
87
 * Values may be stored at any trie node, including internal nodes and leaf
88
 * nodes. Therefore, reduction and canonicalization always operate on both the
89
 * node-local terminal values and the structure of all descendant edges.
90
 *
91
 * @param <V> value type
92
 */
93
@SuppressWarnings({ "PMD.CyclomaticComplexity", "PMD.CouplingBetweenObjects" })
94
public final class FrequencyTrie<V> {
95
96
    /**
97
     * Logger of this class.
98
     */
99
    private static final Logger LOGGER = Logger.getLogger(FrequencyTrie.class.getName());
100
101
    /**
102
     * Domain separator used by the trie fingerprint canonical input.
103
     */
104
    private static final String FINGERPRINT_DOMAIN = "RADIXOR-FREQUENCY-TRIE-FINGERPRINT";
105
106
    /**
107
     * Version of the canonical fingerprint input format.
108
     */
109
    private static final int FINGERPRINT_FORMAT_VERSION = 2;
110
111
    /**
112
     * Root node of the compiled read-only trie.
113
     */
114
    private final CompiledNode<V> root;
115
116
    /**
117
     * Metadata persisted together with this trie.
118
     */
119
    private final TrieMetadata metadata;
120
121
    /**
122
     * Lazily initialized canonical SHA-256 fingerprint bytes. Every read and write
123
     * is guarded by {@link #fingerprintLock}. The value is assigned only after
124
     * calculation succeeds, so failed initialization leaves the cache empty. The
125
     * internal array is never exposed directly to callers.
126
     */
127
    private byte[] fingerprintBytes;
128
129
    /**
130
     * Guards all access to {@link #fingerprintBytes}. Holding this lock for every
131
     * cache read and write safely publishes successful lazy initialization to
132
     * subsequent callers.
133
     */
134
    private final ReentrantLock fingerprintLock = new ReentrantLock();
135
136
    /**
137
     * Cached traversal direction used for key lookup.
138
     */
139
    private final WordTraversalDirection lookupTraversalDirection;
140
141
    /**
142
     * Whether lookups require lowercase normalization.
143
     */
144
    private final boolean lowercasesLookupKeys;
145
146
    /**
147
     * Whether lookups require diacritic stripping.
148
     */
149
    private final boolean removeDiacritics;
150
151
    /**
152
     * Shared empty array instance for empty lookup results from
153
     * {@link #getAll(String)}.
154
     */
155
    private final V[] emptyValues;
156
157
    /**
158
     * Binary format magic header.
159
     */
160
    private static final int STREAM_MAGIC = 0x45475452;
161
162
    /**
163
     * Minimum supported stream version constant retained for explicit range checks.
164
     */
165
    private static final int MIN_STREAM_VERSION = 1;
166
167
    /**
168
     * Number of stored values for which {@link #getEntries(String)} can return an
169
     * empty result.
170
     */
171
    private static final int NO_VALUE_COUNT = 0;
172
173
    /**
174
     * Number of stored values for which {@link #getEntries(String)} can use a
175
     * one-item immutable list special case.
176
     */
177
    private static final int SINGLE_VALUE_COUNT = 1;
178
179
    /**
180
     * Binary format version.
181
     */
182
    private static final int STREAM_VERSION = 7;
183
184
    /**
185
     * Version where traversal-direction ordinal is persisted.
186
     */
187
    private static final int TRAVERSAL_VERSION = 2;
188
189
    /**
190
     * Version where compact reduction metadata is persisted.
191
     */
192
    private static final int REDUCTION_VERSION = 3;
193
194
    /**
195
     * Version where case-processing mode ordinal is persisted.
196
     */
197
    private static final int CASE_VERSION = 4;
198
199
    /**
200
     * Version where the persisted metadata switched to a text block.
201
     */
202
    private static final int TEXT_METADATA_VERSION = 5;
203
204
    /**
205
     * Version where contracted accepting nodes are persisted.
206
     */
207
    private static final int ACCEPTING_NODE_VERSION = 6;
208
209
    /**
210
     * Version where distinct values are persisted once in a stream-local table.
211
     */
212
    private static final int VALUE_TABLE_VERSION = 7;
213
214
    /**
215
     * Argument name for lookup keys.
216
     */
217
    private static final String ARG_KEY = "key";
218
219
    /**
220
     * Default dense child lookup span in code points used when materializing
221
     * compiled nodes without an explicit override.
222
     * <p>
223
     * Increasing this value increases the chance of direct array indexing for child
224
     * lookup at runtime at the cost of per-node dense table memory for compact
225
     * character spans.
226
     * </p>
227
     */
228
    public static final int DEFAULT_MAX_EXPANDED_INDEX = 512;
229
230
    /**
231
     * Returns the current persisted binary stream format version.
232
     *
233
     * <p>
234
     * This method exists so other components can construct {@link TrieMetadata}
235
     * instances aligned with the currently written binary format without
236
     * duplicating constants.
237
     * </p>
238
     *
239
     * @return current trie stream format version
240
     */
241
    public static int currentFormatVersion() {
242 1 1. currentFormatVersion : replaced int return with 0 for org/egothor/stemmer/FrequencyTrie::currentFormatVersion → KILLED
        return STREAM_VERSION;
243
    }
244
245
    /**
246
     * Returns whether the supplied metadata identifies a stream format with a
247
     * serialized value table.
248
     *
249
     * @param metadata parsed trie metadata
250
     * @return {@code true} when values are stored in a stream-local table
251
     * @throws NullPointerException if {@code metadata} is {@code null}
252
     */
253
    /* default */ static boolean usesValueTableFormat(final TrieMetadata metadata) {
254 3 1. usesValueTableFormat : changed conditional boundary → SURVIVED
2. usesValueTableFormat : negated conditional → KILLED
3. usesValueTableFormat : replaced boolean return with true for org/egothor/stemmer/FrequencyTrie::usesValueTableFormat → KILLED
        return Objects.requireNonNull(metadata, "metadata").formatVersion() >= VALUE_TABLE_VERSION;
255
    }
256
257
    /**
258
     * Receives trie values during visitor-style lookup.
259
     *
260
     * <p>
261
     * Implementations are caller-owned and are not retained by the trie. Returning
262
     * {@code false} stops iteration after the current callback.
263
     * </p>
264
     *
265
     * @param <V> value type
266
     */
267
    @FunctionalInterface
268
    public interface EntrySink<V> {
269
270
        /**
271
         * Accepts one ordered local value.
272
         *
273
         * @param value stored value
274
         * @param count stored local occurrence count
275
         * @param rank  zero-based rank in deterministic local ordering
276
         * @return {@code true} to continue iteration, {@code false} to stop
277
         */
278
        boolean accept(V value, int count, int rank);
279
    }
280
281
    /**
282
     * Creates a new compiled trie instance.
283
     *
284
     * @param arrayFactory array factory
285
     * @param root         compiled root node
286
     * @param metadata     trie metadata describing lookup and persistence semantics
287
     * @throws NullPointerException if any argument is {@code null}
288
     */
289
    private FrequencyTrie(final IntFunction<V[]> arrayFactory, final CompiledNode<V> root,
290
            final TrieMetadata metadata) {
291
        this.root = Objects.requireNonNull(root, "root");
292
        this.metadata = Objects.requireNonNull(metadata, "metadata");
293
        this.lookupTraversalDirection = metadata.traversalDirection();
294 1 1. <init> : negated conditional → KILLED
        this.lowercasesLookupKeys = metadata.caseProcessingMode() == CaseProcessingMode.LOWERCASE_WITH_LOCALE_ROOT;
295 1 1. <init> : negated conditional → KILLED
        this.removeDiacritics = metadata.diacriticProcessingMode() == DiacriticProcessingMode.REMOVE;
296
        this.emptyValues = arrayFactory.apply(0);
297
    }
298
299
    /**
300
     * Creates a trie from an already compiled root.
301
     *
302
     * @param arrayFactory array factory
303
     * @param root         compiled root
304
     * @param metadata     trie metadata
305
     * @param <V>          value type
306
     * @return trie instance
307
     */
308
    /* default */ static <V> FrequencyTrie<V> fromCompiled(final IntFunction<V[]> arrayFactory,
309
            final CompiledNode<V> root,
310
            final TrieMetadata metadata) {
311 1 1. fromCompiled : replaced return value with null for org/egothor/stemmer/FrequencyTrie::fromCompiled → KILLED
        return new FrequencyTrie<>(arrayFactory, root, metadata);
312
    }
313
314
    /**
315
     * Returns the most frequent value stored at the node addressed by the supplied
316
     * key.
317
     *
318
     * <p>
319
     * If multiple values have the same local frequency, the returned value is
320
     * selected deterministically by shorter {@code toString()} value first, then by
321
     * lexicographically lower {@code toString()}, and finally by stable first-seen
322
     * order.
323
     *
324
     * <p>
325
     * The supplied key is normalized according to persisted
326
     * {@link TrieMetadata#caseProcessingMode()} before traversal.
327
     * 
328
     * @param key key to resolve
329
     * @return most frequent value, or {@code null} if the key does not exist or no
330
     *         value is stored at the addressed node
331
     * @throws NullPointerException if {@code key} is {@code null}
332
     */
333
    public V get(final String key) {
334
        Objects.requireNonNull(key, ARG_KEY);
335
        final CompiledNode<V> node = findNode(normalizeLookupKey(key));
336 1 1. get : negated conditional → KILLED
        if (node == null) {
337
            return null;
338
        }
339
        final V[] orderedValues = node.orderedValues();
340 1 1. get : negated conditional → KILLED
        if (orderedValues.length == 0) {
341
            return null;
342
        }
343 1 1. get : replaced return value with null for org/egothor/stemmer/FrequencyTrie::get → KILLED
        return orderedValues[0];
344
    }
345
346
    /**
347
     * Returns the preferred value for an already-normalized key.
348
     *
349
     * <p>
350
     * This method bypasses {@link TrieMetadata#caseProcessingMode()} and
351
     * {@link TrieMetadata#diacriticProcessingMode()}. Callers must supply input
352
     * normalized exactly as required by this trie's metadata. It is intended for
353
     * hot paths where normalization is guaranteed by an upstream tokenizer or
354
     * benchmark corpus and repeated lookup-time normalization would be redundant.
355
     * </p>
356
     *
357
     * @param key already-normalized key to resolve
358
     * @return most frequent value, or {@code null} if the key does not exist or no
359
     *         value is stored at the addressed node
360
     * @throws NullPointerException if {@code key} is {@code null}
361
     */
362
    public V getNormalized(final CharSequence key) {
363
        Objects.requireNonNull(key, ARG_KEY);
364
        final CompiledNode<V> node = findNode(key);
365 1 1. getNormalized : negated conditional → KILLED
        if (node == null) {
366
            return null;
367
        }
368
        final V[] orderedValues = node.orderedValues();
369 1 1. getNormalized : negated conditional → KILLED
        if (orderedValues.length == 0) {
370
            return null;
371
        }
372 1 1. getNormalized : replaced return value with null for org/egothor/stemmer/FrequencyTrie::getNormalized → KILLED
        return orderedValues[0];
373
    }
374
375
    /**
376
     * Returns the preferred value for an already-normalized {@link String} key.
377
     *
378
     * <p>
379
     * This overload keeps high-volume string lookup on a monomorphic path and
380
     * avoids the {@link CharSequence} dispatch used by the general overload.
381
     * Callers must supply input normalized exactly as required by this trie's
382
     * metadata.
383
     * </p>
384
     *
385
     * @param key already-normalized key to resolve
386
     * @return most frequent value, or {@code null} if the key does not exist or no
387
     *         value is stored at the addressed node
388
     * @throws NullPointerException if {@code key} is {@code null}
389
     */
390
    public V getNormalizedString(final String key) {
391
        Objects.requireNonNull(key, ARG_KEY);
392
        final CompiledNode<V> node = findNode(key);
393 1 1. getNormalizedString : negated conditional → KILLED
        if (node == null) {
394
            return null;
395
        }
396
        final V[] orderedValues = node.orderedValues();
397 1 1. getNormalizedString : negated conditional → KILLED
        if (orderedValues.length == 0) {
398
            return null;
399
        }
400 1 1. getNormalizedString : replaced return value with null for org/egothor/stemmer/FrequencyTrie::getNormalizedString → KILLED
        return orderedValues[0];
401
    }
402
403
    /**
404
     * Returns all values stored at the node addressed by the supplied key, ordered
405
     * by descending frequency.
406
     *
407
     * <p>
408
     * If multiple values have the same local frequency, the ordering is
409
     * deterministic by shorter {@code toString()} value first, then by
410
     * lexicographically lower {@code toString()}, and finally by stable first-seen
411
     * order.
412
     *
413
     * <p>
414
     * The returned array is a defensive copy.
415
     *
416
     * <p>
417
     * The supplied key is normalized according to persisted
418
     * {@link TrieMetadata#caseProcessingMode()} before traversal.
419
     *
420
     * @param key key to resolve
421
     * @return all values stored at the addressed node, ordered by descending
422
     *         frequency; returns an empty array if the key does not exist or no
423
     *         value is stored at the addressed node
424
     * @throws NullPointerException if {@code key} is {@code null}
425
     */
426
    @SuppressWarnings("PMD.MethodReturnsInternalArray")
427
    public V[] getAll(final String key) {
428
        Objects.requireNonNull(key, ARG_KEY);
429
        final CompiledNode<V> node = findNode(normalizeLookupKey(key));
430 1 1. getAll : negated conditional → KILLED
        if (node == null) {
431 1 1. getAll : replaced return value with null for org/egothor/stemmer/FrequencyTrie::getAll → KILLED
            return this.emptyValues;
432
        }
433
        final V[] orderedValues = node.orderedValues();
434 1 1. getAll : negated conditional → KILLED
        if (orderedValues.length == 0) {
435 1 1. getAll : replaced return value with null for org/egothor/stemmer/FrequencyTrie::getAll → SURVIVED
            return this.emptyValues;
436
        }
437 1 1. getAll : replaced return value with null for org/egothor/stemmer/FrequencyTrie::getAll → KILLED
        return Arrays.copyOf(orderedValues, orderedValues.length);
438
    }
439
440
    /**
441
     * Returns all values stored at the node addressed by the supplied key together
442
     * with their occurrence counts, ordered by the same rules as
443
     * {@link #getAll(String)}.
444
     *
445
     * <p>
446
     * The returned list is aligned with the arrays returned by
447
     * {@link #getAll(String)} and the internal compiled count representation.
448
     *
449
     * <p>
450
     * The returned list is immutable.
451
     *
452
     * <p>
453
     * In reduction modes that merge semantically equivalent subtrees, the returned
454
     * counts may be aggregated across multiple original build-time nodes that were
455
     * reduced into the same canonical compiled node.
456
     *
457
     * @param key key to resolve
458
     * @return immutable ordered list of value-count entries; returns an empty list
459
     *         if the key does not exist or no value is stored at the addressed node
460
     * @throws NullPointerException if {@code key} is {@code null}
461
     */
462
    public List<ValueCount<V>> getEntries(final String key) {
463
        Objects.requireNonNull(key, ARG_KEY);
464
        final CompiledNode<V> node = findNode(normalizeLookupKey(key));
465 1 1. getEntries : negated conditional → KILLED
        if (node == null) {
466
            return List.of();
467
        }
468
469
        final V[] orderedValues = node.orderedValues();
470
        final int valueCount = orderedValues.length;
471 1 1. getEntries : negated conditional → KILLED
        if (valueCount == NO_VALUE_COUNT) {
472
            return List.of();
473
        }
474
475 1 1. getEntries : negated conditional → KILLED
        if (valueCount == SINGLE_VALUE_COUNT) {
476 1 1. getEntries : replaced return value with Collections.emptyList for org/egothor/stemmer/FrequencyTrie::getEntries → KILLED
            return List.of(new ValueCount<>(orderedValues[0], node.orderedCounts()[0]));
477
        }
478
479
        final int[] orderedCounts = node.orderedCounts();
480
        final List<ValueCount<V>> entries = new ArrayList<>(valueCount);
481 2 1. getEntries : changed conditional boundary → KILLED
2. getEntries : negated conditional → KILLED
        for (int index = 0; index < valueCount; index++) {
482
            entries.add(new ValueCount<>(orderedValues[index], orderedCounts[index]));
483
        }
484 1 1. getEntries : replaced return value with Collections.emptyList for org/egothor/stemmer/FrequencyTrie::getEntries → KILLED
        return Collections.unmodifiableList(entries);
485
    }
486
487
    /**
488
     * Visits all values stored at the node addressed by an already-normalized
489
     * {@code char[]} key slice.
490
     *
491
     * <p>
492
     * This method bypasses {@link TrieMetadata#caseProcessingMode()} and
493
     * {@link TrieMetadata#diacriticProcessingMode()}. The caller must provide input
494
     * normalized exactly as required by this trie's metadata. The trie is immutable
495
     * and thread-safe for concurrent reads; the supplied sink is caller-owned and
496
     * is not retained.
497
     * </p>
498
     *
499
     * @param key        normalized key storage
500
     * @param offset     first character offset
501
     * @param length     number of characters to read
502
     * @param sink       value sink
503
     * @param maxResults maximum number of results to visit
504
     * @return number of visited values
505
     * @throws NullPointerException      if {@code key} or {@code sink} is
506
     *                                   {@code null}
507
     * @throws IndexOutOfBoundsException if the key slice is invalid
508
     * @throws IllegalArgumentException  if {@code maxResults} is negative
509
     */
510
    public int getAllNormalized(final char[] key, final int offset, final int length, final EntrySink<? super V> sink,
511
            final int maxResults) {
512
        Objects.requireNonNull(key, ARG_KEY);
513
        Objects.requireNonNull(sink, "sink");
514
        Objects.checkFromIndexSize(offset, length, key.length);
515 1 1. getAllNormalized : removed call to org/egothor/stemmer/FrequencyTrie::validateMaxResults → SURVIVED
        validateMaxResults(maxResults);
516 1 1. getAllNormalized : negated conditional → KILLED
        if (maxResults == 0) {
517
            return 0;
518
        }
519 1 1. getAllNormalized : replaced int return with 0 for org/egothor/stemmer/FrequencyTrie::getAllNormalized → KILLED
        return visitNode(findNode(key, offset, length), sink, maxResults);
520
    }
521
522
    /**
523
     * Visits all values stored at the node addressed by an already-normalized
524
     * character sequence.
525
     *
526
     * @param key        normalized key
527
     * @param sink       value sink
528
     * @param maxResults maximum number of results to visit
529
     * @return number of visited values
530
     * @throws NullPointerException     if {@code key} or {@code sink} is
531
     *                                  {@code null}
532
     * @throws IllegalArgumentException if {@code maxResults} is negative
533
     * @see #getAllNormalized(char[], int, int, EntrySink, int)
534
     */
535
    public int getAllNormalized(final CharSequence key, final EntrySink<? super V> sink, final int maxResults) {
536
        Objects.requireNonNull(key, ARG_KEY);
537
        Objects.requireNonNull(sink, "sink");
538 1 1. getAllNormalized : removed call to org/egothor/stemmer/FrequencyTrie::validateMaxResults → KILLED
        validateMaxResults(maxResults);
539 1 1. getAllNormalized : negated conditional → KILLED
        if (maxResults == 0) {
540
            return 0;
541
        }
542 1 1. getAllNormalized : replaced int return with 0 for org/egothor/stemmer/FrequencyTrie::getAllNormalized → KILLED
        return visitNode(findNode(key), sink, maxResults);
543
    }
544
545
    /**
546
     * Visits the first value stored at the node addressed by an already-normalized
547
     * {@code char[]} key slice.
548
     *
549
     * @param key    normalized key storage
550
     * @param offset first character offset
551
     * @param length number of characters to read
552
     * @param sink   value sink
553
     * @return {@code true} when a value was visited, otherwise {@code false}
554
     * @see #getAllNormalized(char[], int, int, EntrySink, int)
555
     */
556
    public boolean getFirstNormalized(final char[] key, final int offset, final int length,
557
            final EntrySink<? super V> sink) {
558 2 1. getFirstNormalized : replaced boolean return with true for org/egothor/stemmer/FrequencyTrie::getFirstNormalized → NO_COVERAGE
2. getFirstNormalized : negated conditional → NO_COVERAGE
        return getAllNormalized(key, offset, length, sink, 1) == 1;
559
    }
560
561
    /**
562
     * Visits the first value stored at the node addressed by an already-normalized
563
     * character sequence.
564
     *
565
     * @param key  normalized key
566
     * @param sink value sink
567
     * @return {@code true} when a value was visited, otherwise {@code false}
568
     * @see #getAllNormalized(CharSequence, EntrySink, int)
569
     */
570
    public boolean getFirstNormalized(final CharSequence key, final EntrySink<? super V> sink) {
571 2 1. getFirstNormalized : negated conditional → KILLED
2. getFirstNormalized : replaced boolean return with true for org/egothor/stemmer/FrequencyTrie::getFirstNormalized → KILLED
        return getAllNormalized(key, sink, 1) == 1;
572
    }
573
574
    /**
575
     * Visits all values stored at the node addressed by the supplied key, applying
576
     * metadata-driven lookup normalization when required.
577
     *
578
     * <p>
579
     * This method preserves the same lookup normalization semantics as
580
     * {@link #getAll(String)}. It may allocate when metadata requires lowercase or
581
     * diacritic normalization.
582
     * </p>
583
     *
584
     * @param key        key to resolve
585
     * @param sink       value sink
586
     * @param maxResults maximum number of results to visit
587
     * @return number of visited values
588
     */
589
    public int getAll(final CharSequence key, final EntrySink<? super V> sink, final int maxResults) {
590
        Objects.requireNonNull(key, ARG_KEY);
591
        Objects.requireNonNull(sink, "sink");
592 1 1. getAll : removed call to org/egothor/stemmer/FrequencyTrie::validateMaxResults → KILLED
        validateMaxResults(maxResults);
593 1 1. getAll : negated conditional → KILLED
        if (maxResults == 0) {
594
            return 0;
595
        }
596
        final CharSequence normalized = normalizeLookupKey(key);
597 1 1. getAll : replaced int return with 0 for org/egothor/stemmer/FrequencyTrie::getAll → KILLED
        return visitNode(findNode(normalized), sink, maxResults);
598
    }
599
600
    /**
601
     * Visits the first value stored at the node addressed by the supplied key,
602
     * applying metadata-driven lookup normalization when required.
603
     *
604
     * @param key  key to resolve
605
     * @param sink value sink
606
     * @return {@code true} when a value was visited, otherwise {@code false}
607
     * @see #getAll(CharSequence, EntrySink, int)
608
     */
609
    public boolean getFirst(final CharSequence key, final EntrySink<? super V> sink) {
610 2 1. getFirst : replaced boolean return with true for org/egothor/stemmer/FrequencyTrie::getFirst → SURVIVED
2. getFirst : negated conditional → KILLED
        return getAll(key, sink, 1) == 1;
611
    }
612
613
    /**
614
     * Returns the logical key traversal direction used by this trie.
615
     *
616
     * <p>
617
     * The same direction must be used when reconstructing mutable builders or when
618
     * applying patch commands that were generated against keys stored in this trie.
619
     * </p>
620
     *
621
     * @return logical key traversal direction
622
     */
623
    public WordTraversalDirection traversalDirection() {
624 1 1. traversalDirection : replaced return value with null for org/egothor/stemmer/FrequencyTrie::traversalDirection → KILLED
        return this.metadata.traversalDirection();
625
    }
626
627
    /**
628
     * Returns immutable persisted metadata associated with this trie.
629
     *
630
     * @return trie metadata
631
     */
632
    public TrieMetadata metadata() {
633 1 1. metadata : replaced return value with null for org/egothor/stemmer/FrequencyTrie::metadata → KILLED
        return this.metadata;
634
    }
635
636
    /**
637
     * Returns the deterministic SHA-256 fingerprint of this trie.
638
     *
639
     * <p>
640
     * The fingerprint is a canonical model identity, not a Java object identity. It
641
     * includes a fingerprint-domain marker, the fingerprint input format version,
642
     * persisted metadata, and the complete compiled-node structure reachable from
643
     * the root, including edges, child references, local values, and local counts.
644
     * </p>
645
     *
646
     * <p>
647
     * The returned value is stable across JVM runs for equivalent trie content and
648
     * metadata. It does not include object identity, memory layout, runtime cache
649
     * state, absolute file paths, timestamps, or other process-local state.
650
     * </p>
651
     *
652
     * <p>
653
     * The fingerprint is calculated on first request and reused by later
654
     * fingerprint accessors.
655
     * </p>
656
     *
657
     * @return 64-character lowercase hexadecimal SHA-256 fingerprint
658
     */
659
    public String getFingerprint() {
660 1 1. getFingerprint : replaced return value with "" for org/egothor/stemmer/FrequencyTrie::getFingerprint → KILLED
        return toLowerHex(fingerprintBytes());
661
    }
662
663
    /**
664
     * Returns a defensive copy of the raw SHA-256 fingerprint bytes.
665
     *
666
     * <p>
667
     * The returned array has length {@code 32}. Mutating it does not affect this
668
     * trie.
669
     * </p>
670
     *
671
     * <p>
672
     * The fingerprint is calculated on first request and reused by later
673
     * fingerprint accessors.
674
     * </p>
675
     *
676
     * @return defensive copy of the 32-byte SHA-256 fingerprint
677
     */
678
    public byte[] copyFingerprintBytes() {
679
        final byte[] localFingerprintBytes = fingerprintBytes();
680 1 1. copyFingerprintBytes : replaced return value with null for org/egothor/stemmer/FrequencyTrie::copyFingerprintBytes → KILLED
        return Arrays.copyOf(localFingerprintBytes, localFingerprintBytes.length);
681
    }
682
683
    /**
684
     * Returns the cached raw SHA-256 fingerprint bytes, computing them on the first
685
     * request.
686
     *
687
     * <p>
688
     * Access to the cache is guarded by {@link #fingerprintLock}. Because every read
689
     * and write of the cache occurs while holding the same lock, successful
690
     * initialization is safely published to all subsequent callers. If calculation
691
     * fails, no value is cached and a later call may retry.
692
     * </p>
693
     *
694
     * @return internal cached raw SHA-256 fingerprint bytes
695
     */
696
    private byte[] fingerprintBytes() {
697 1 1. fingerprintBytes : removed call to java/util/concurrent/locks/ReentrantLock::lock → KILLED
        this.fingerprintLock.lock();
698
        try {
699
            byte[] localFingerprintBytes = this.fingerprintBytes;
700 1 1. fingerprintBytes : negated conditional → KILLED
            if (localFingerprintBytes == null) {
701
                localFingerprintBytes = computeFingerprintBytes(this.root, this.metadata);
702
                this.fingerprintBytes = localFingerprintBytes;
703
            }
704 1 1. fingerprintBytes : replaced return value with null for org/egothor/stemmer/FrequencyTrie::fingerprintBytes → KILLED
            return localFingerprintBytes;
705
        } finally {
706 1 1. fingerprintBytes : removed call to java/util/concurrent/locks/ReentrantLock::unlock → TIMED_OUT
            this.fingerprintLock.unlock();
707
        }
708
    }
709
710
    private static <V> byte[] computeFingerprintBytes(final CompiledNode<V> root, final TrieMetadata metadata) {
711
        final MessageDigest messageDigest = newSha256Digest();
712 1 1. computeFingerprintBytes : removed call to org/egothor/stemmer/FrequencyTrie::updateUtf8 → SURVIVED
        updateUtf8(messageDigest, FINGERPRINT_DOMAIN);
713 1 1. computeFingerprintBytes : removed call to org/egothor/stemmer/FrequencyTrie::updateInt → SURVIVED
        updateInt(messageDigest, FINGERPRINT_FORMAT_VERSION);
714 1 1. computeFingerprintBytes : removed call to org/egothor/stemmer/FrequencyTrie::updateUtf8 → SURVIVED
        updateUtf8(messageDigest, metadata.toTextBlock());
715
716
        final Map<CompiledNode<V>, Integer> nodeIds = new IdentityHashMap<>();
717
        final List<CompiledNode<V>> orderedNodes = new ArrayList<>();
718 1 1. computeFingerprintBytes : removed call to org/egothor/stemmer/FrequencyTrie::assignNodeIds → KILLED
        assignNodeIds(root, nodeIds, orderedNodes);
719
720 1 1. computeFingerprintBytes : removed call to org/egothor/stemmer/FrequencyTrie::updateInt → SURVIVED
        updateInt(messageDigest, nodeIds.get(root));
721 1 1. computeFingerprintBytes : removed call to org/egothor/stemmer/FrequencyTrie::updateInt → SURVIVED
        updateInt(messageDigest, orderedNodes.size());
722
        for (CompiledNode<V> node : orderedNodes) {
723 1 1. computeFingerprintBytes : removed call to org/egothor/stemmer/FrequencyTrie::updateNodeFingerprint → KILLED
            updateNodeFingerprint(messageDigest, node, nodeIds);
724
        }
725 1 1. computeFingerprintBytes : replaced return value with null for org/egothor/stemmer/FrequencyTrie::computeFingerprintBytes → KILLED
        return messageDigest.digest();
726
    }
727
728
    /**
729
     * Returns the root node mainly for diagnostics and tests within the package.
730
     *
731
     * @return compiled root node
732
     */
733
    /* default */ CompiledNode<V> root() {
734 1 1. root : replaced return value with null for org/egothor/stemmer/FrequencyTrie::root → KILLED
        return this.root;
735
    }
736
737
    /**
738
     * Writes this compiled trie to the supplied output stream.
739
     *
740
     * <p>
741
     * The binary format is versioned and preserves canonical shared compiled nodes,
742
     * therefore the serialized representation remains compact even for tries
743
     * reduced by subtree merging.
744
     *
745
     * <p>
746
     * The supplied codec is responsible for persisting individual values of type
747
     * {@code V}.
748
     *
749
     * @param outputStream target output stream
750
     * @param valueCodec   codec used to write values
751
     * @throws NullPointerException if any argument is {@code null}
752
     * @throws IOException          if writing fails
753
     */
754
    public void writeTo(final OutputStream outputStream, final ValueStreamCodec<V> valueCodec) throws IOException {
755
        Objects.requireNonNull(outputStream, "outputStream");
756
        Objects.requireNonNull(valueCodec, "valueCodec");
757
758
        final DataOutputStream dataOutput; // NOPMD
759 1 1. writeTo : negated conditional → KILLED
        if (outputStream instanceof DataOutputStream) {
760
            dataOutput = (DataOutputStream) outputStream;
761
        } else {
762
            dataOutput = new DataOutputStream(outputStream);
763
        }
764
765
        final Map<CompiledNode<V>, Integer> nodeIds = new IdentityHashMap<>();
766
        final List<CompiledNode<V>> orderedNodes = new ArrayList<>();
767 1 1. writeTo : removed call to org/egothor/stemmer/FrequencyTrie::assignNodeIds → KILLED
        assignNodeIds(this.root, nodeIds, orderedNodes);
768
        final Map<V, Integer> valueIds = new LinkedHashMap<>();
769
        final List<V> distinctValues = new ArrayList<>();
770 1 1. writeTo : removed call to org/egothor/stemmer/FrequencyTrie::collectDistinctValues → KILLED
        collectDistinctValues(orderedNodes, valueIds, distinctValues);
771
772
        if (LOGGER.isLoggable(Level.FINE)) {
773
            LOGGER.log(Level.FINE, "Writing compiled trie with {0} canonical nodes.", orderedNodes.size());
774
        }
775
776 1 1. writeTo : removed call to java/io/DataOutputStream::writeInt → KILLED
        dataOutput.writeInt(STREAM_MAGIC);
777 1 1. writeTo : removed call to java/io/DataOutputStream::writeInt → KILLED
        dataOutput.writeInt(STREAM_VERSION);
778 1 1. writeTo : removed call to java/io/DataOutputStream::writeInt → KILLED
        dataOutput.writeInt(orderedNodes.size());
779 1 1. writeTo : removed call to java/io/DataOutputStream::writeInt → KILLED
        dataOutput.writeInt(nodeIds.get(this.root));
780 1 1. writeTo : removed call to org/egothor/stemmer/FrequencyTrie::writeMetadata → KILLED
        writeMetadata(dataOutput, metadataForCurrentStream(this.metadata));
781 1 1. writeTo : removed call to org/egothor/stemmer/FrequencyTrie::writeValueTable → KILLED
        writeValueTable(dataOutput, valueCodec, distinctValues);
782
783 2 1. writeTo : negated conditional → KILLED
2. writeTo : changed conditional boundary → KILLED
        for (int nodeId = 0; nodeId < orderedNodes.size(); nodeId++) {
784 1 1. writeTo : removed call to org/egothor/stemmer/FrequencyTrie::writeNode → KILLED
            writeNode(dataOutput, orderedNodes.get(nodeId), nodeId, nodeIds, valueIds);
785
        }
786
787 1 1. writeTo : removed call to java/io/DataOutputStream::flush → SURVIVED
        dataOutput.flush();
788
    }
789
790
    /**
791
     * Reads a compiled trie from the supplied input stream.
792
     *
793
     * <p>
794
     * The caller must provide the same value codec semantics that were used during
795
     * persistence as well as the array factory required for typed result arrays.
796
     *
797
     * @param inputStream  source input stream
798
     * @param arrayFactory factory used to create typed arrays
799
     * @param valueCodec   codec used to read values
800
     * @param <V>          value type
801
     * @return deserialized compiled trie
802
     * @throws NullPointerException if any argument is {@code null}
803
     * @throws IOException          if reading fails or the binary format is invalid
804
     */
805
    public static <V> FrequencyTrie<V> readFrom(final InputStream inputStream, final IntFunction<V[]> arrayFactory,
806
            final ValueStreamCodec<V> valueCodec) throws IOException {
807 1 1. readFrom : replaced return value with null for org/egothor/stemmer/FrequencyTrie::readFrom → KILLED
        return readFrom(inputStream, arrayFactory, valueCodec, -1);
808
    }
809
810
    /**
811
     * Reads a compiled trie from the supplied input stream, optionally overriding
812
     * dense child-index span configuration.
813
     * <p>
814
     * This setting is applied only while materializing the in-memory compiled
815
     * representation during load. It is not serialized in {@link TrieMetadata}, so
816
     * each load can independently choose its own runtime lookup trade-off.
817
     * </p>
818
     *
819
     * @param inputStream      source input stream
820
     * @param arrayFactory     array factory used to create typed arrays
821
     * @param valueCodec       codec used to read values
822
     * @param maxExpandedIndex dense lookup span override; zero disables dense
823
     *                         lookup, negative values use
824
     *                         {@link #DEFAULT_MAX_EXPANDED_INDEX}
825
     * @param <V>              value type
826
     * @return deserialized compiled trie
827
     * @throws NullPointerException if any argument is {@code null}
828
     * @throws IOException          if reading fails or the binary format is invalid
829
     */
830
    public static <V> FrequencyTrie<V> readFrom(final InputStream inputStream, final IntFunction<V[]> arrayFactory,
831
            final ValueStreamCodec<V> valueCodec, final int maxExpandedIndex) throws IOException {
832
        Objects.requireNonNull(valueCodec, "valueCodec");
833 1 1. readFrom : replaced return value with null for org/egothor/stemmer/FrequencyTrie::readFrom → KILLED
        return readFromWithMetadata(inputStream, arrayFactory,
834 1 1. lambda$readFrom$0 : replaced return value with null for org/egothor/stemmer/FrequencyTrie::lambda$readFrom$0 → KILLED
                (dataInput, metadata) -> valueCodec.read(dataInput), maxExpandedIndex);
835
    }
836
837
    /**
838
     * Reads a compiled trie while allowing value decoding to use already parsed
839
     * trie metadata.
840
     *
841
     * <p>
842
     * This package-private path materializes the requested final value type during
843
     * the normal graph read. It does not expose reader state or construct an
844
     * intermediate trie with a different value type.
845
     * </p>
846
     *
847
     * @param inputStream      source input stream
848
     * @param arrayFactory     factory used to create typed value arrays
849
     * @param valueReader      metadata-aware value reader
850
     * @param maxExpandedIndex dense lookup span override; zero disables dense
851
     *                         lookup, negative values use
852
     *                         {@link #DEFAULT_MAX_EXPANDED_INDEX}
853
     * @param <V>              final value type
854
     * @return deserialized compiled trie containing values returned by
855
     *         {@code valueReader}
856
     * @throws NullPointerException if any argument is {@code null}
857
     * @throws IOException          if reading fails or the binary format is invalid
858
     */
859
    /* default */ static <V> FrequencyTrie<V> readFromWithMetadata(final InputStream inputStream,
860
            final IntFunction<V[]> arrayFactory, final MetadataValueStreamReader<V> valueReader,
861
            final int maxExpandedIndex) throws IOException {
862 1 1. readFromWithMetadata : replaced return value with null for org/egothor/stemmer/FrequencyTrie::readFromWithMetadata → KILLED
        return CompiledTrieReader.read(inputStream, arrayFactory, valueReader, maxExpandedIndex);
863
    }
864
865
    /**
866
     * Writes persisted trie metadata.
867
     *
868
     * @param dataOutput output stream
869
     * @param metadata   metadata to serialize
870
     * @throws IOException if writing fails
871
     */
872
    private static void writeMetadata(final DataOutputStream dataOutput, final TrieMetadata metadata)
873
            throws IOException {
874 1 1. writeMetadata : removed call to java/io/DataOutputStream::writeUTF → KILLED
        dataOutput.writeUTF(metadata.toTextBlock());
875
    }
876
877
    /**
878
     * Creates metadata aligned with the stream version emitted by the current
879
     * writer.
880
     *
881
     * <p>
882
     * The returned metadata preserves every semantic setting from the trie while
883
     * reporting the current binary format version. The immutable metadata stored by
884
     * the trie is not modified.
885
     * </p>
886
     *
887
     * @param metadata source trie metadata
888
     * @return metadata aligned with {@link #STREAM_VERSION}
889
     */
890
    private static TrieMetadata metadataForCurrentStream(final TrieMetadata metadata) {
891 1 1. metadataForCurrentStream : replaced return value with null for org/egothor/stemmer/FrequencyTrie::metadataForCurrentStream → KILLED
        return new TrieMetadata(STREAM_VERSION, metadata.traversalDirection(), metadata.reductionSettings(),
892
                metadata.diacriticProcessingMode(), metadata.caseProcessingMode());
893
    }
894
895
    /**
896
     * Returns the number of canonical compiled nodes reachable from the root.
897
     *
898
     * <p>
899
     * The returned value reflects the size of the final reduced immutable trie, not
900
     * the number of mutable build-time nodes inserted before reduction. Shared
901
     * canonical subtrees are counted only once.
902
     *
903
     * @return number of canonical compiled nodes in this trie
904
     */
905
    public int size() {
906
        final Map<CompiledNode<V>, Integer> nodeIds = new IdentityHashMap<>();
907
        final List<CompiledNode<V>> orderedNodes = new ArrayList<>();
908 1 1. size : removed call to org/egothor/stemmer/FrequencyTrie::assignNodeIds → KILLED
        assignNodeIds(this.root, nodeIds, orderedNodes);
909 1 1. size : replaced int return with 0 for org/egothor/stemmer/FrequencyTrie::size → KILLED
        return orderedNodes.size();
910
    }
911
912
    /**
913
     * Assigns deterministic identifiers to all canonical compiled nodes reachable
914
     * from the supplied root.
915
     *
916
     * @param node         current node
917
     * @param nodeIds      assigned node identifiers
918
     * @param orderedNodes ordered nodes in identifier order
919
     */
920
    private static <V> void assignNodeIds(final CompiledNode<V> node, final Map<CompiledNode<V>, Integer> nodeIds,
921
            final List<CompiledNode<V>> orderedNodes) {
922 1 1. assignNodeIds : negated conditional → KILLED
        if (nodeIds.containsKey(node)) {
923
            return;
924
        }
925
926
        final int nodeId = orderedNodes.size();
927
        nodeIds.put(node, nodeId);
928
        orderedNodes.add(node);
929
930
        for (CompiledNode<V> child : node.children()) {
931 1 1. assignNodeIds : removed call to org/egothor/stemmer/FrequencyTrie::assignNodeIds → KILLED
            assignNodeIds(child, nodeIds, orderedNodes);
932
        }
933
    }
934
935
    /**
936
     * Collects the deterministic equality-based value table for serialization.
937
     *
938
     * <p>
939
     * Nodes are visited in canonical node-identifier order and values are visited
940
     * in their existing node-local order. The first occurrence according to
941
     * {@link Object#equals(Object)} and {@link Object#hashCode()} assigns the table
942
     * index.
943
     * </p>
944
     *
945
     * @param orderedNodes   canonical nodes in identifier order
946
     * @param valueIds       destination mapping from values to table indexes
947
     * @param distinctValues destination values in table-index order
948
     * @param <V>            value type
949
     */
950
    private static <V> void collectDistinctValues(final List<CompiledNode<V>> orderedNodes,
951
            final Map<V, Integer> valueIds, final List<V> distinctValues) {
952
        for (CompiledNode<V> node : orderedNodes) {
953
            for (V value : node.orderedValues()) {
954 1 1. collectDistinctValues : negated conditional → KILLED
                if (!valueIds.containsKey(value)) {
955
                    final int valueId = distinctValues.size();
956
                    valueIds.put(value, valueId);
957
                    distinctValues.add(value);
958
                }
959
            }
960
        }
961
    }
962
963
    /**
964
     * Writes every distinct value exactly once in table-index order.
965
     *
966
     * @param dataOutput     output stream
967
     * @param valueCodec     codec responsible for value encoding
968
     * @param distinctValues distinct values in deterministic table order
969
     * @param <V>            value type
970
     * @throws IOException if writing the table fails
971
     */
972
    private static <V> void writeValueTable(final DataOutputStream dataOutput, final ValueStreamCodec<V> valueCodec,
973
            final List<V> distinctValues) throws IOException {
974 1 1. writeValueTable : removed call to java/io/DataOutputStream::writeInt → KILLED
        dataOutput.writeInt(distinctValues.size());
975
        for (V value : distinctValues) {
976 1 1. writeValueTable : removed call to org/egothor/stemmer/FrequencyTrie$ValueStreamCodec::write → KILLED
            valueCodec.write(dataOutput, value);
977
        }
978
    }
979
980
    /**
981
     * Writes one compiled node using stream-local value-table indexes.
982
     *
983
     * @param dataOutput output
984
     * @param node       node to write
985
     * @param nodeId     canonical identifier of {@code node}
986
     * @param nodeIds    node identifiers
987
     * @param valueIds   value-table indexes
988
     * @param <V>        value type
989
     * @throws IOException if writing fails
990
     */
991
    private static <V> void writeNode(final DataOutputStream dataOutput, final CompiledNode<V> node, final int nodeId,
992
            final Map<CompiledNode<V>, Integer> nodeIds, final Map<V, Integer> valueIds) throws IOException {
993 1 1. writeNode : removed call to java/io/DataOutputStream::writeBoolean → KILLED
        dataOutput.writeBoolean(node.acceptsRemainingInput());
994 1 1. writeNode : removed call to java/io/DataOutputStream::writeInt → KILLED
        dataOutput.writeInt(node.edgeLabels().length);
995 2 1. writeNode : changed conditional boundary → KILLED
2. writeNode : negated conditional → KILLED
        for (int index = 0; index < node.edgeLabels().length; index++) {
996 1 1. writeNode : removed call to java/io/DataOutputStream::writeChar → KILLED
            dataOutput.writeChar(node.edgeLabels()[index]);
997
            final Integer childNodeId = nodeIds.get(node.children()[index]);
998 1 1. writeNode : negated conditional → KILLED
            if (childNodeId == null) {
999
                throw new IOException("Missing child node identifier during serialization.");
1000
            }
1001 1 1. writeNode : removed call to java/io/DataOutputStream::writeInt → KILLED
            dataOutput.writeInt(childNodeId);
1002
        }
1003
1004 1 1. writeNode : removed call to java/io/DataOutputStream::writeInt → KILLED
        dataOutput.writeInt(node.orderedValues().length);
1005 2 1. writeNode : changed conditional boundary → KILLED
2. writeNode : negated conditional → KILLED
        for (int index = 0; index < node.orderedValues().length; index++) {
1006
            final V value = node.orderedValues()[index];
1007
            final Integer valueId = valueIds.get(value);
1008 1 1. writeNode : negated conditional → KILLED
            if (valueId == null) {
1009 1 1. writeNode : negated conditional → NO_COVERAGE
                final String valueContext = value == null ? "null"
1010
                        : value.getClass().getName() + '[' + value + ']';
1011
                throw new IOException("Missing value table index at canonical node " + nodeId + ", local value "
1012
                        + index + ": " + valueContext);
1013
            }
1014 1 1. writeNode : removed call to java/io/DataOutputStream::writeInt → KILLED
            dataOutput.writeInt(valueId);
1015 1 1. writeNode : removed call to java/io/DataOutputStream::writeInt → KILLED
            dataOutput.writeInt(node.orderedCounts()[index]);
1016
        }
1017
    }
1018
1019
    private static MessageDigest newSha256Digest() {
1020
        try {
1021 1 1. newSha256Digest : replaced return value with null for org/egothor/stemmer/FrequencyTrie::newSha256Digest → KILLED
            return MessageDigest.getInstance("SHA-256");
1022
        } catch (NoSuchAlgorithmException exception) {
1023
            throw new IllegalStateException("SHA-256 digest is not available.", exception);
1024
        }
1025
    }
1026
1027
    private static <V> void updateNodeFingerprint(final MessageDigest messageDigest, final CompiledNode<V> node,
1028
            final Map<CompiledNode<V>, Integer> nodeIds) {
1029
        final char[] edgeLabels = node.edgeLabels();
1030
        final CompiledNode<V>[] children = node.children();
1031
        final V[] values = node.orderedValues();
1032
        final int[] counts = node.orderedCounts();
1033
1034 2 1. updateNodeFingerprint : negated conditional → SURVIVED
2. updateNodeFingerprint : removed call to org/egothor/stemmer/FrequencyTrie::updateInt → SURVIVED
        updateInt(messageDigest, node.acceptsRemainingInput() ? 1 : 0);
1035 1 1. updateNodeFingerprint : removed call to org/egothor/stemmer/FrequencyTrie::updateInt → SURVIVED
        updateInt(messageDigest, edgeLabels.length);
1036
        for (char edgeLabel : edgeLabels) {
1037 1 1. updateNodeFingerprint : removed call to org/egothor/stemmer/FrequencyTrie::updateInt → SURVIVED
            updateInt(messageDigest, edgeLabel);
1038
        }
1039
        for (CompiledNode<V> child : children) {
1040
            final Integer childNodeId = nodeIds.get(child);
1041 1 1. updateNodeFingerprint : negated conditional → KILLED
            if (childNodeId == null) {
1042
                throw new IllegalStateException("Missing child node identifier during trie fingerprinting.");
1043
            }
1044 1 1. updateNodeFingerprint : removed call to org/egothor/stemmer/FrequencyTrie::updateInt → SURVIVED
            updateInt(messageDigest, childNodeId);
1045
        }
1046
1047 1 1. updateNodeFingerprint : removed call to org/egothor/stemmer/FrequencyTrie::updateInt → SURVIVED
        updateInt(messageDigest, values.length);
1048
        for (V value : values) {
1049 1 1. updateNodeFingerprint : removed call to org/egothor/stemmer/FrequencyTrie::updateUtf8 → SURVIVED
            updateUtf8(messageDigest, String.valueOf(value));
1050
        }
1051
        for (int count : counts) {
1052 1 1. updateNodeFingerprint : removed call to org/egothor/stemmer/FrequencyTrie::updateInt → KILLED
            updateInt(messageDigest, count);
1053
        }
1054
    }
1055
1056
    private static void updateUtf8(final MessageDigest messageDigest, final String value) {
1057
        final byte[] encoded = value.getBytes(StandardCharsets.UTF_8);
1058 1 1. updateUtf8 : removed call to org/egothor/stemmer/FrequencyTrie::updateInt → SURVIVED
        updateInt(messageDigest, encoded.length);
1059 1 1. updateUtf8 : removed call to java/security/MessageDigest::update → SURVIVED
        messageDigest.update(encoded);
1060
    }
1061
1062
    private static void updateInt(final MessageDigest messageDigest, final int value) {
1063 2 1. updateInt : removed call to java/security/MessageDigest::update → SURVIVED
2. updateInt : Replaced Unsigned Shift Right with Shift Left → SURVIVED
        messageDigest.update((byte) (value >>> 24));
1064 2 1. updateInt : removed call to java/security/MessageDigest::update → SURVIVED
2. updateInt : Replaced Unsigned Shift Right with Shift Left → SURVIVED
        messageDigest.update((byte) (value >>> 16));
1065 2 1. updateInt : removed call to java/security/MessageDigest::update → SURVIVED
2. updateInt : Replaced Unsigned Shift Right with Shift Left → SURVIVED
        messageDigest.update((byte) (value >>> 8));
1066 1 1. updateInt : removed call to java/security/MessageDigest::update → KILLED
        messageDigest.update((byte) value);
1067
    }
1068
1069
    private static String toLowerHex(final byte[] digest) {
1070 1 1. toLowerHex : Replaced integer multiplication with division → SURVIVED
        final StringBuilder builder = new StringBuilder(digest.length * 2);
1071
        for (byte item : digest) {
1072 3 1. toLowerHex : Replaced Unsigned Shift Right with Shift Left → KILLED
2. toLowerHex : Replaced bitwise AND with OR → KILLED
3. toLowerHex : Replaced bitwise AND with OR → KILLED
            builder.append(Character.forDigit((item >>> 4) & 0x0F, 16)).append(Character.forDigit(item & 0x0F, 16));
1073
        }
1074 1 1. toLowerHex : replaced return value with "" for org/egothor/stemmer/FrequencyTrie::toLowerHex → KILLED
        return builder.toString();
1075
    }
1076
1077
    /**
1078
     * Internal helper that materializes serialized trie data.
1079
     *
1080
     * <p>
1081
     * Moving reader complexity into this helper keeps the public-facing class from
1082
     * accumulating excessive class-level cyclomatic complexity while preserving the
1083
     * same binary compatibility contract.
1084
     * </p>
1085
     */
1086
    private static final class CompiledTrieReader {
1087
1088
        private static <V> FrequencyTrie<V> read(final InputStream inputStream, final IntFunction<V[]> arrayFactory,
1089
                final MetadataValueStreamReader<V> valueReader, final int maxExpandedIndex) throws IOException {
1090
            Objects.requireNonNull(inputStream, "inputStream");
1091
            Objects.requireNonNull(arrayFactory, "arrayFactory");
1092
            Objects.requireNonNull(valueReader, "valueReader");
1093 2 1. read : changed conditional boundary → KILLED
2. read : negated conditional → KILLED
            if (maxExpandedIndex < -1) {
1094
                throw new IllegalArgumentException("maxExpandedIndex must be >= -1.");
1095
            }
1096
1097
            final DataInputStream dataInput = wrapInputStream(inputStream);
1098
            final int magic = dataInput.readInt();
1099 1 1. read : negated conditional → KILLED
            if (magic != STREAM_MAGIC) {
1100
                throw new IOException("Unsupported trie stream header: " + Integer.toHexString(magic));
1101
            }
1102
1103
            final int version = dataInput.readInt();
1104 4 1. read : negated conditional → KILLED
2. read : changed conditional boundary → KILLED
3. read : changed conditional boundary → KILLED
4. read : negated conditional → KILLED
            if (version < MIN_STREAM_VERSION || version > STREAM_VERSION) {
1105
                throw new IOException("Unsupported trie stream version: " + version);
1106
            }
1107
1108
            final int nodeCount = dataInput.readInt();
1109 2 1. read : changed conditional boundary → SURVIVED
2. read : negated conditional → KILLED
            if (nodeCount < 0) {
1110
                throw new IOException("Negative node count: " + nodeCount);
1111
            }
1112
1113
            final int rootNodeId = dataInput.readInt();
1114 4 1. read : changed conditional boundary → KILLED
2. read : changed conditional boundary → KILLED
3. read : negated conditional → KILLED
4. read : negated conditional → KILLED
            if (rootNodeId < 0 || rootNodeId >= nodeCount) {
1115
                throw new IOException("Invalid root node id: " + rootNodeId);
1116
            }
1117
1118
            final TrieMetadata sourceMetadata = readMetadata(dataInput, version);
1119 2 1. read : negated conditional → KILLED
2. read : changed conditional boundary → KILLED
            final V[] valueTable = version >= VALUE_TABLE_VERSION
1120
                    ? readValueTable(dataInput, arrayFactory, valueReader, sourceMetadata)
1121
                    : null;
1122 2 1. read : negated conditional → KILLED
2. read : changed conditional boundary → KILLED
            final int effectiveMaxExpandedIndex = maxExpandedIndex >= 0 ? maxExpandedIndex : DEFAULT_MAX_EXPANDED_INDEX;
1123
            final CompiledNode<V>[] nodes = readNodes(dataInput, arrayFactory, valueReader, sourceMetadata, valueTable,
1124
                    nodeCount, effectiveMaxExpandedIndex, version);
1125
            final CompiledNode<V> rootNode = nodes[rootNodeId];
1126
1127
            if (LOGGER.isLoggable(Level.FINE)) {
1128
                LOGGER.log(Level.FINE, "Read compiled trie with {0} canonical nodes.", nodeCount);
1129
            }
1130
1131 1 1. read : replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::read → KILLED
            return new FrequencyTrie<>(arrayFactory, rootNode, sourceMetadata);
1132
        }
1133
1134
        /**
1135
         * Reads the temporary stream-local value table.
1136
         *
1137
         * <p>
1138
         * Each serialized value is decoded exactly once. The returned array is used
1139
         * only while materializing node value arrays and is not retained by the
1140
         * resulting trie.
1141
         * </p>
1142
         *
1143
         * @param dataInput    input stream
1144
         * @param arrayFactory typed-array factory
1145
         * @param valueReader  metadata-aware value reader
1146
         * @param metadata     parsed trie metadata
1147
         * @param <V>          value type
1148
         * @return decoded values in table-index order
1149
         * @throws IOException if the count is negative or value decoding fails
1150
         */
1151
        private static <V> V[] readValueTable(final DataInputStream dataInput, final IntFunction<V[]> arrayFactory,
1152
                final MetadataValueStreamReader<V> valueReader, final TrieMetadata metadata) throws IOException {
1153
            final int distinctValueCount = dataInput.readInt();
1154 2 1. readValueTable : changed conditional boundary → SURVIVED
2. readValueTable : negated conditional → KILLED
            if (distinctValueCount < 0) {
1155
                throw new IOException("Negative distinct value count: " + distinctValueCount);
1156
            }
1157
1158
            final V[] valueTable = arrayFactory.apply(distinctValueCount);
1159 2 1. readValueTable : negated conditional → KILLED
2. readValueTable : changed conditional boundary → KILLED
            for (int valueIndex = 0; valueIndex < distinctValueCount; valueIndex++) {
1160
                valueTable[valueIndex] = valueReader.read(dataInput, metadata);
1161
            }
1162 1 1. readValueTable : replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readValueTable → KILLED
            return valueTable;
1163
        }
1164
1165
        private static DataInputStream wrapInputStream(final InputStream inputStream) {
1166 2 1. wrapInputStream : negated conditional → KILLED
2. wrapInputStream : replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::wrapInputStream → KILLED
            return inputStream instanceof DataInputStream ? (DataInputStream) inputStream
1167
                    : new DataInputStream(inputStream);
1168
        }
1169
1170
        private static TrieMetadata readMetadata(final DataInputStream dataInput, final int version)
1171
                throws IOException {
1172 2 1. readMetadata : negated conditional → KILLED
2. readMetadata : changed conditional boundary → KILLED
            if (version >= TEXT_METADATA_VERSION) {
1173 1 1. readMetadata : replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readMetadata → KILLED
                return readTextMetadata(dataInput, version);
1174
            }
1175
1176
            final WordTraversalDirection traversalDirection = readTraversalDirection(dataInput, version);
1177 2 1. readMetadata : negated conditional → KILLED
2. readMetadata : changed conditional boundary → KILLED
            if (version < REDUCTION_VERSION) {
1178 1 1. readMetadata : replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readMetadata → KILLED
                return TrieMetadata.legacy(version, traversalDirection);
1179
            }
1180
1181
            final ReductionSettings reductionSettings = readReductionSettings(dataInput);
1182
            final DiacriticProcessingMode diacriticProcessingMode = readEnumByOrdinal(dataInput,
1183
                    DiacriticProcessingMode.values(), "diacritic processing mode");
1184 2 1. readMetadata : negated conditional → KILLED
2. readMetadata : changed conditional boundary → KILLED
            final CaseProcessingMode caseProcessingMode = version >= CASE_VERSION ? readCaseProcessingMode(dataInput)
1185
                    : CaseProcessingMode.LOWERCASE_WITH_LOCALE_ROOT;
1186 1 1. readMetadata : replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readMetadata → KILLED
            return new TrieMetadata(version, traversalDirection, reductionSettings, diacriticProcessingMode,
1187
                    caseProcessingMode);
1188
        }
1189
1190
        private static TrieMetadata readTextMetadata(final DataInputStream dataInput, final int version)
1191
                throws IOException {
1192
            try {
1193 1 1. readTextMetadata : replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readTextMetadata → KILLED
                return TrieMetadata.fromTextBlock(version, dataInput.readUTF());
1194
            } catch (IllegalArgumentException exception) {
1195
                throw new IOException("Invalid metadata block.", exception);
1196
            }
1197
        }
1198
1199
        private static WordTraversalDirection readTraversalDirection(final DataInputStream dataInput, final int version)
1200
                throws IOException {
1201 2 1. readTraversalDirection : negated conditional → KILLED
2. readTraversalDirection : changed conditional boundary → KILLED
            if (version < TRAVERSAL_VERSION) {
1202 1 1. readTraversalDirection : replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readTraversalDirection → KILLED
                return WordTraversalDirection.BACKWARD;
1203
            }
1204 1 1. readTraversalDirection : replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readTraversalDirection → KILLED
            return readEnumByOrdinal(dataInput, WordTraversalDirection.values(), "traversal direction");
1205
        }
1206
1207
        private static ReductionSettings readReductionSettings(final DataInputStream dataInput) throws IOException {
1208
            final ReductionMode reductionMode = readEnumByOrdinal(dataInput, ReductionMode.values(), "reduction mode");
1209
            final int dominantWinnerMinPercent = dataInput.readInt();
1210
            final int dominantWinnerOverSecondRatio = dataInput.readInt(); // NOPMD
1211 1 1. readReductionSettings : replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readReductionSettings → KILLED
            return new ReductionSettings(reductionMode, dominantWinnerMinPercent, dominantWinnerOverSecondRatio);
1212
        }
1213
1214
        private static CaseProcessingMode readCaseProcessingMode(final DataInputStream dataInput) throws IOException {
1215 1 1. readCaseProcessingMode : replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readCaseProcessingMode → KILLED
            return readEnumByOrdinal(dataInput, CaseProcessingMode.values(), "case processing mode");
1216
        }
1217
1218
        private static <E extends Enum<E>> E readEnumByOrdinal(final DataInputStream dataInput, final E[] values,
1219
                final String name) throws IOException {
1220
            final int ordinal = dataInput.readInt();
1221 4 1. readEnumByOrdinal : changed conditional boundary → SURVIVED
2. readEnumByOrdinal : negated conditional → KILLED
3. readEnumByOrdinal : changed conditional boundary → KILLED
4. readEnumByOrdinal : negated conditional → KILLED
            if (ordinal < 0 || ordinal >= values.length) {
1222
                throw new IOException("Invalid " + name + " ordinal: " + ordinal);
1223
            }
1224 1 1. readEnumByOrdinal : replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readEnumByOrdinal → KILLED
            return values[ordinal];
1225
        }
1226
1227
        private static <V> CompiledNode<V>[] readNodes(final DataInputStream dataInput,
1228
                final IntFunction<V[]> arrayFactory, final MetadataValueStreamReader<V> valueReader,
1229
                final TrieMetadata metadata, final V[] valueTable, final int nodeCount, final int maxExpandedIndex,
1230
                final int version) throws IOException {
1231
            final char[][] edgeLabelsByNode = new char[nodeCount][];
1232
            final int[][] childNodeIdsByNode = new int[nodeCount][];
1233
            @SuppressWarnings("unchecked")
1234
            final V[][] orderedValuesByNode = (V[][]) new Object[nodeCount][];
1235
            final int[][] orderedCountsByNode = new int[nodeCount][];
1236
            final boolean[] acceptsRemainingInputByNode = new boolean[nodeCount];
1237
1238 2 1. readNodes : changed conditional boundary → KILLED
2. readNodes : negated conditional → KILLED
            for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) {
1239 2 1. readNodes : negated conditional → KILLED
2. readNodes : changed conditional boundary → KILLED
                if (version >= ACCEPTING_NODE_VERSION) {
1240
                    acceptsRemainingInputByNode[nodeIndex] = dataInput.readBoolean();
1241
                }
1242
1243
                final int edgeCount = dataInput.readInt();
1244 2 1. readNodes : negated conditional → KILLED
2. readNodes : changed conditional boundary → KILLED
                if (edgeCount < 0) {
1245
                    throw new IOException("Negative edge count at node " + nodeIndex + ": " + edgeCount);
1246
                }
1247
1248
                edgeLabelsByNode[nodeIndex] = new char[edgeCount];
1249
                childNodeIdsByNode[nodeIndex] = new int[edgeCount];
1250
1251 2 1. readNodes : negated conditional → KILLED
2. readNodes : changed conditional boundary → KILLED
                for (int edgeIndex = 0; edgeIndex < edgeCount; edgeIndex++) {
1252
                    edgeLabelsByNode[nodeIndex][edgeIndex] = dataInput.readChar();
1253
                    childNodeIdsByNode[nodeIndex][edgeIndex] = dataInput.readInt();
1254
                }
1255
1256 1 1. readNodes : removed call to org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::validateSerializedEdges → KILLED
                validateSerializedEdges(nodeIndex, edgeLabelsByNode[nodeIndex]);
1257
1258
                final int valueCount = dataInput.readInt();
1259 2 1. readNodes : changed conditional boundary → KILLED
2. readNodes : negated conditional → KILLED
                if (valueCount < 0) {
1260
                    throw new IOException("Negative value count at node " + nodeIndex + ": " + valueCount);
1261
                }
1262 2 1. readNodes : negated conditional → KILLED
2. readNodes : negated conditional → KILLED
                if (acceptsRemainingInputByNode[nodeIndex] && edgeCount != 0) {
1263
                    throw new IOException("Accepting node " + nodeIndex + " cannot have child edges.");
1264
                }
1265 2 1. readNodes : negated conditional → KILLED
2. readNodes : negated conditional → KILLED
                if (acceptsRemainingInputByNode[nodeIndex] && valueCount == 0) {
1266
                    throw new IOException("Accepting node " + nodeIndex + " must store at least one value.");
1267
                }
1268
1269
                orderedValuesByNode[nodeIndex] = arrayFactory.apply(valueCount);
1270
                orderedCountsByNode[nodeIndex] = new int[valueCount];
1271
1272 2 1. readNodes : changed conditional boundary → KILLED
2. readNodes : negated conditional → KILLED
                for (int valueIndex = 0; valueIndex < valueCount; valueIndex++) {
1273 2 1. readNodes : negated conditional → KILLED
2. readNodes : changed conditional boundary → KILLED
                    if (version >= VALUE_TABLE_VERSION) {
1274
                        final int valueTableIndex = dataInput.readInt();
1275 4 1. readNodes : changed conditional boundary → KILLED
2. readNodes : changed conditional boundary → KILLED
3. readNodes : negated conditional → KILLED
4. readNodes : negated conditional → KILLED
                        if (valueTableIndex < 0 || valueTableIndex >= valueTable.length) {
1276
                            throw new IOException("Invalid value table index at node " + nodeIndex + ", local value "
1277
                                    + valueIndex + ": " + valueTableIndex + "; table size is " + valueTable.length
1278
                                    + '.');
1279
                        }
1280
                        orderedValuesByNode[nodeIndex][valueIndex] = valueTable[valueTableIndex];
1281
                    } else {
1282
                        orderedValuesByNode[nodeIndex][valueIndex] = valueReader.read(dataInput, metadata);
1283
                    }
1284
                    orderedCountsByNode[nodeIndex][valueIndex] = dataInput.readInt();
1285 2 1. readNodes : negated conditional → KILLED
2. readNodes : changed conditional boundary → KILLED
                    if (orderedCountsByNode[nodeIndex][valueIndex] <= 0) {
1286
                        throw new IOException("Non-positive stored count at node " + nodeIndex + ", value index "
1287
                                + valueIndex + ": " + orderedCountsByNode[nodeIndex][valueIndex]);
1288
                    }
1289
                }
1290
            }
1291
1292
            @SuppressWarnings("unchecked")
1293
            final CompiledNode<V>[] nodes = new CompiledNode[nodeCount];
1294
            final boolean[] inProgress = new boolean[nodeCount];
1295
1296 2 1. readNodes : changed conditional boundary → KILLED
2. readNodes : negated conditional → KILLED
            for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) {
1297
                nodes[nodeIndex] = resolveNode(nodeIndex, edgeLabelsByNode, childNodeIdsByNode, orderedValuesByNode,
1298
                        orderedCountsByNode, acceptsRemainingInputByNode, nodes, inProgress, maxExpandedIndex);
1299
            }
1300
1301 1 1. readNodes : replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readNodes → KILLED
            return nodes;
1302
        }
1303
1304
        private static <V> CompiledNode<V> resolveNode(final int nodeIndex, final char[][] edgeLabelsByNode,
1305
                final int[][] childNodeIdsByNode, final V[][] orderedValuesByNode, final int[][] orderedCountsByNode,
1306
                final boolean[] acceptsRemainingInputByNode, final CompiledNode<V>[] nodes,
1307
                final boolean[] inProgress, final int maxExpandedIndex) throws IOException {
1308
            final CompiledNode<V> cachedNode = nodes[nodeIndex];
1309 1 1. resolveNode : negated conditional → KILLED
            if (cachedNode != null) {
1310 1 1. resolveNode : replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::resolveNode → KILLED
                return cachedNode;
1311
            }
1312
1313 1 1. resolveNode : negated conditional → KILLED
            if (inProgress[nodeIndex]) {
1314
                throw new IOException(
1315
                        "Invalid serialized node graph: cyclic reference detected at node " + nodeIndex + '.');
1316
            }
1317
            inProgress[nodeIndex] = true;
1318
            try {
1319
                final char[] edgeLabels = edgeLabelsByNode[nodeIndex];
1320
                final int[] childNodeIds = childNodeIdsByNode[nodeIndex];
1321
                final int edgeCount = childNodeIds.length;
1322
                @SuppressWarnings("unchecked")
1323
                final CompiledNode<V>[] children = new CompiledNode[edgeCount];
1324
1325 2 1. resolveNode : negated conditional → KILLED
2. resolveNode : changed conditional boundary → KILLED
                for (int edgeIndex = 0; edgeIndex < edgeCount; edgeIndex++) {
1326
                    final int childNodeId = childNodeIds[edgeIndex];
1327 4 1. resolveNode : changed conditional boundary → SURVIVED
2. resolveNode : negated conditional → KILLED
3. resolveNode : changed conditional boundary → KILLED
4. resolveNode : negated conditional → KILLED
                    if (childNodeId < 0 || childNodeId >= edgeLabelsByNode.length) {
1328
                        throw new IOException("Invalid child node id at node " + nodeIndex + ", edge index " + edgeIndex
1329
                                + ": " + childNodeId);
1330
                    }
1331
                    children[edgeIndex] = resolveNode(childNodeId, edgeLabelsByNode, childNodeIdsByNode,
1332
                            orderedValuesByNode, orderedCountsByNode, acceptsRemainingInputByNode, nodes, inProgress,
1333
                            maxExpandedIndex);
1334
                }
1335
1336
                final CompiledNode<V> node = new CompiledNode<>(edgeLabels, children, orderedValuesByNode[nodeIndex],
1337
                        acceptsRemainingInputByNode[nodeIndex], maxExpandedIndex, orderedCountsByNode[nodeIndex]);
1338
                nodes[nodeIndex] = node;
1339 1 1. resolveNode : replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::resolveNode → KILLED
                return node;
1340
            } finally {
1341
                inProgress[nodeIndex] = false;
1342
            }
1343
        }
1344
1345
        private static void validateSerializedEdges(final int nodeIndex, final char... edgeLabels) throws IOException {
1346 2 1. validateSerializedEdges : changed conditional boundary → KILLED
2. validateSerializedEdges : negated conditional → KILLED
            for (int edgeIndex = 1; edgeIndex < edgeLabels.length; edgeIndex++) {
1347 3 1. validateSerializedEdges : changed conditional boundary → SURVIVED
2. validateSerializedEdges : negated conditional → KILLED
3. validateSerializedEdges : Replaced integer subtraction with addition → KILLED
                if (edgeLabels[edgeIndex - 1] >= edgeLabels[edgeIndex]) {
1348 1 1. validateSerializedEdges : Replaced integer subtraction with addition → KILLED
                    throw new IOException(
1349
                            "Edge labels must be strictly ascending at node " + nodeIndex + ", edge index " + edgeIndex
1350
                                    + ": '" + edgeLabels[edgeIndex - 1] + "' then '" + edgeLabels[edgeIndex] + "'.");
1351
                }
1352
            }
1353
        }
1354
    }
1355
1356
    /**
1357
     * Locates the compiled node for the supplied key.
1358
     *
1359
     * @param key already-normalized key to resolve
1360
     * @return compiled node, or {@code null} if the path does not exist
1361
     */
1362
    private CompiledNode<V> findNode(final String key) {
1363
        CompiledNode<V> current = this.root;
1364 1 1. findNode : negated conditional → KILLED
        if (this.lookupTraversalDirection == WordTraversalDirection.BACKWARD) {
1365 3 1. findNode : changed conditional boundary → KILLED
2. findNode : Replaced integer subtraction with addition → KILLED
3. findNode : negated conditional → KILLED
            for (int traversalOffset = key.length() - 1; traversalOffset >= 0; traversalOffset--) {
1366 1 1. findNode : negated conditional → KILLED
                if (current.acceptsRemainingInput()) {
1367 1 1. findNode : replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → KILLED
                    return current;
1368
                }
1369
                current = current.findChild(key.charAt(traversalOffset));
1370 1 1. findNode : negated conditional → KILLED
                if (current == null) {
1371
                    return null;
1372
                }
1373
            }
1374 1 1. findNode : replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → KILLED
            return current;
1375
        }
1376
1377 2 1. findNode : negated conditional → KILLED
2. findNode : changed conditional boundary → KILLED
        for (int traversalOffset = 0; traversalOffset < key.length(); traversalOffset++) {
1378 1 1. findNode : negated conditional → KILLED
            if (current.acceptsRemainingInput()) {
1379 1 1. findNode : replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → KILLED
                return current;
1380
            }
1381
            current = current.findChild(key.charAt(traversalOffset));
1382 1 1. findNode : negated conditional → KILLED
            if (current == null) {
1383
                return null;
1384
            }
1385
        }
1386 1 1. findNode : replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → KILLED
        return current;
1387
    }
1388
1389
    /**
1390
     * Locates the compiled node for the supplied key.
1391
     *
1392
     * @param key already-normalized key to resolve
1393
     * @return compiled node, or {@code null} if the path does not exist
1394
     */
1395
    private CompiledNode<V> findNode(final CharSequence key) {
1396
        CompiledNode<V> current = this.root;
1397 1 1. findNode : negated conditional → KILLED
        if (this.lookupTraversalDirection == WordTraversalDirection.BACKWARD) {
1398 3 1. findNode : changed conditional boundary → KILLED
2. findNode : Replaced integer subtraction with addition → KILLED
3. findNode : negated conditional → KILLED
            for (int traversalOffset = key.length() - 1; traversalOffset >= 0; traversalOffset--) {
1399 1 1. findNode : negated conditional → KILLED
                if (current.acceptsRemainingInput()) {
1400 1 1. findNode : replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → NO_COVERAGE
                    return current;
1401
                }
1402
                current = current.findChild(key.charAt(traversalOffset));
1403 1 1. findNode : negated conditional → KILLED
                if (current == null) {
1404
                    return null;
1405
                }
1406
            }
1407 1 1. findNode : replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → KILLED
            return current;
1408
        }
1409
1410 2 1. findNode : negated conditional → NO_COVERAGE
2. findNode : changed conditional boundary → NO_COVERAGE
        for (int traversalOffset = 0; traversalOffset < key.length(); traversalOffset++) {
1411 1 1. findNode : negated conditional → NO_COVERAGE
            if (current.acceptsRemainingInput()) {
1412 1 1. findNode : replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → NO_COVERAGE
                return current;
1413
            }
1414
            current = current.findChild(key.charAt(traversalOffset));
1415 1 1. findNode : negated conditional → NO_COVERAGE
            if (current == null) {
1416
                return null;
1417
            }
1418
        }
1419 1 1. findNode : replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → NO_COVERAGE
        return current;
1420
    }
1421
1422
    /**
1423
     * Locates the compiled node for the supplied key slice.
1424
     *
1425
     * @param key    already-normalized key storage
1426
     * @param offset first character offset
1427
     * @param length number of characters to read
1428
     * @return compiled node, or {@code null} if the path does not exist
1429
     */
1430
    private CompiledNode<V> findNode(final char[] key, final int offset, final int length) {
1431
        CompiledNode<V> current = this.root;
1432 1 1. findNode : negated conditional → KILLED
        if (this.lookupTraversalDirection == WordTraversalDirection.BACKWARD) {
1433 4 1. findNode : Replaced integer subtraction with addition → KILLED
2. findNode : Replaced integer addition with subtraction → KILLED
3. findNode : negated conditional → KILLED
4. findNode : changed conditional boundary → KILLED
            for (int traversalOffset = offset + length - 1; traversalOffset >= offset; traversalOffset--) {
1434 1 1. findNode : negated conditional → KILLED
                if (current.acceptsRemainingInput()) {
1435 1 1. findNode : replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → NO_COVERAGE
                    return current;
1436
                }
1437
                current = current.findChild(key[traversalOffset]);
1438 1 1. findNode : negated conditional → KILLED
                if (current == null) {
1439
                    return null;
1440
                }
1441
            }
1442 1 1. findNode : replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → KILLED
            return current;
1443
        }
1444
1445 1 1. findNode : Replaced integer addition with subtraction → NO_COVERAGE
        final int endExclusive = offset + length;
1446 2 1. findNode : negated conditional → NO_COVERAGE
2. findNode : changed conditional boundary → NO_COVERAGE
        for (int traversalOffset = offset; traversalOffset < endExclusive; traversalOffset++) {
1447 1 1. findNode : negated conditional → NO_COVERAGE
            if (current.acceptsRemainingInput()) {
1448 1 1. findNode : replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → NO_COVERAGE
                return current;
1449
            }
1450
            current = current.findChild(key[traversalOffset]);
1451 1 1. findNode : negated conditional → NO_COVERAGE
            if (current == null) {
1452
                return null;
1453
            }
1454
        }
1455 1 1. findNode : replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → NO_COVERAGE
        return current;
1456
    }
1457
1458
    /**
1459
     * Visits node-local values without allocating result containers.
1460
     *
1461
     * @param node       resolved node, or {@code null}
1462
     * @param sink       value sink
1463
     * @param maxResults maximum values to visit
1464
     * @return number of visited values
1465
     */
1466
    private int visitNode(final CompiledNode<V> node, final EntrySink<? super V> sink, final int maxResults) {
1467 1 1. visitNode : negated conditional → KILLED
        if (node == null) {
1468
            return 0;
1469
        }
1470
1471
        final V[] orderedValues = node.orderedValues();
1472
        final int valueCount = Math.min(orderedValues.length, maxResults);
1473 1 1. visitNode : negated conditional → KILLED
        if (valueCount == 0) {
1474
            return 0;
1475
        }
1476
1477
        final int[] orderedCounts = node.orderedCounts();
1478
        int visited = 0;
1479 2 1. visitNode : changed conditional boundary → KILLED
2. visitNode : negated conditional → KILLED
        for (int rank = 0; rank < valueCount; rank++) {
1480 1 1. visitNode : Changed increment from 1 to -1 → KILLED
            visited++;
1481 1 1. visitNode : negated conditional → KILLED
            if (!sink.accept(orderedValues[rank], orderedCounts[rank], rank)) {
1482
                break;
1483
            }
1484
        }
1485 1 1. visitNode : replaced int return with 0 for org/egothor/stemmer/FrequencyTrie::visitNode → KILLED
        return visited;
1486
    }
1487
1488
    /**
1489
     * Validates visitor maximum result count.
1490
     *
1491
     * @param maxResults maximum result count
1492
     */
1493
    private static void validateMaxResults(final int maxResults) {
1494 2 1. validateMaxResults : negated conditional → KILLED
2. validateMaxResults : changed conditional boundary → KILLED
        if (maxResults < 0) {
1495
            throw new IllegalArgumentException("maxResults must be non-negative.");
1496
        }
1497
    }
1498
1499
    /**
1500
     * Applies lookup-time case normalization according to persisted metadata.
1501
     *
1502
     * @param key lookup key
1503
     * @return normalized key for trie traversal
1504
     */
1505
    private String normalizeLookupKey(final String key) {
1506 1 1. normalizeLookupKey : replaced return value with "" for org/egothor/stemmer/FrequencyTrie::normalizeLookupKey → KILLED
        return normalizeLookupKey((CharSequence) key).toString();
1507
    }
1508
1509
    /**
1510
     * Applies lookup-time normalization according to persisted metadata.
1511
     *
1512
     * @param key lookup key
1513
     * @return normalized key for trie traversal
1514
     */
1515
    private CharSequence normalizeLookupKey(final CharSequence key) {
1516 2 1. normalizeLookupKey : negated conditional → SURVIVED
2. normalizeLookupKey : negated conditional → KILLED
        if (!this.lowercasesLookupKeys && !this.removeDiacritics) {
1517 1 1. normalizeLookupKey : replaced return value with null for org/egothor/stemmer/FrequencyTrie::normalizeLookupKey → KILLED
            return key;
1518
        }
1519
1520
        String normalized = key.toString();
1521 1 1. normalizeLookupKey : negated conditional → KILLED
        if (this.lowercasesLookupKeys) {
1522
            normalized = normalized.toLowerCase(Locale.ROOT);
1523
        }
1524 1 1. normalizeLookupKey : negated conditional → KILLED
        if (this.removeDiacritics) {
1525
            normalized = DiacriticStripper.strip(normalized);
1526 1 1. normalizeLookupKey : negated conditional → KILLED
        } else if (this.metadata.diacriticProcessingMode() == DiacriticProcessingMode.AS_IS_AND_STRIPPED_FALLBACK) {
1527
            throw new UnsupportedOperationException(
1528
                    "Diacritic processing mode AS_IS_AND_STRIPPED_FALLBACK is not supported yet.");
1529
        }
1530
1531 1 1. normalizeLookupKey : replaced return value with null for org/egothor/stemmer/FrequencyTrie::normalizeLookupKey → KILLED
        return normalized;
1532
    }
1533
1534
    /**
1535
     * Builder of {@link FrequencyTrie}.
1536
     *
1537
     * <p>
1538
     * The builder is intentionally mutable and optimized for repeated
1539
     * {@link #put(String, Object)} calls. The final trie is created by
1540
     * {@link #build()}, which performs bottom-up subtree reduction and converts the
1541
     * structure to a compact immutable representation optimized for read
1542
     * operations.
1543
     *
1544
     * @param <V> value type
1545
     */
1546
    public static final class Builder<V> {
1547
1548
        /**
1549
         * Logger of this class.
1550
         */
1551
        private static final Logger LOGGER = Logger.getLogger(Builder.class.getName());
1552
1553
        /**
1554
         * Factory used to create typed arrays.
1555
         */
1556
        private final IntFunction<V[]> arrayFactory;
1557
1558
        /**
1559
         * Reduction configuration.
1560
         */
1561
        private final ReductionSettings reductionSettings;
1562
1563
        /**
1564
         * Logical key traversal direction used by this builder.
1565
         */
1566
        private final WordTraversalDirection traversalDirection;
1567
1568
        /**
1569
         * Dictionary case processing mode associated with this builder.
1570
         */
1571
        private final CaseProcessingMode caseProcessingMode;
1572
1573
        /**
1574
         * Dictionary diacritic processing mode associated with this builder.
1575
         */
1576
        private final DiacriticProcessingMode diacriticProcessingMode;
1577
1578
        /**
1579
         * Dense edge lookup span threshold.
1580
         * <p>
1581
         * This value controls a speed/memory trade-off during freezing: dense child
1582
         * lookup tables are allocated only for nodes whose child labels fit in this
1583
         * span.
1584
         * </p>
1585
         */
1586
        private final int maxExpandedIndex;
1587
1588
        /**
1589
         * Mutable root node.
1590
         */
1591
        private final MutableNode<V> root;
1592
1593
        /**
1594
         * Creates a new builder with the provided settings.
1595
         *
1596
         * <p>
1597
         * This constructor preserves the historical Egothor behavior and therefore
1598
         * traverses logical keys from their end toward their beginning.
1599
         * </p>
1600
         *
1601
         * @param arrayFactory      array factory
1602
         * @param reductionSettings reduction configuration
1603
         * @throws NullPointerException if any argument is {@code null}
1604
         */
1605
        public Builder(final IntFunction<V[]> arrayFactory, final ReductionSettings reductionSettings) {
1606
            this(arrayFactory, reductionSettings, WordTraversalDirection.BACKWARD);
1607
        }
1608
1609
        /**
1610
         * Creates a new builder with the provided settings and explicit traversal
1611
         * direction.
1612
         *
1613
         * @param arrayFactory       array factory
1614
         * @param reductionSettings  reduction configuration
1615
         * @param traversalDirection logical key traversal direction
1616
         * @throws NullPointerException if any argument is {@code null}
1617
         */
1618
        public Builder(final IntFunction<V[]> arrayFactory, final ReductionSettings reductionSettings,
1619
                final WordTraversalDirection traversalDirection) {
1620
            this(arrayFactory, reductionSettings, traversalDirection, CaseProcessingMode.LOWERCASE_WITH_LOCALE_ROOT);
1621
        }
1622
1623
        /**
1624
         * Creates a new builder with the provided settings, explicit traversal
1625
         * direction, and explicit case processing mode.
1626
         *
1627
         * @param arrayFactory       array factory
1628
         * @param reductionSettings  reduction configuration
1629
         * @param traversalDirection logical key traversal direction
1630
         * @param caseProcessingMode dictionary case processing mode
1631
         * @throws NullPointerException if any argument is {@code null}
1632
         */
1633
        public Builder(final IntFunction<V[]> arrayFactory, final ReductionSettings reductionSettings,
1634
                final WordTraversalDirection traversalDirection, final CaseProcessingMode caseProcessingMode) {
1635
            this(arrayFactory, reductionSettings, traversalDirection, caseProcessingMode,
1636
                    DiacriticProcessingMode.AS_IS);
1637
        }
1638
1639
        /**
1640
         * Creates a new builder with the provided settings, explicit traversal
1641
         * direction, explicit case processing mode, and explicit diacritic processing
1642
         * mode.
1643
         *
1644
         * @param arrayFactory            array factory
1645
         * @param reductionSettings       reduction configuration
1646
         * @param traversalDirection      logical key traversal direction
1647
         * @param caseProcessingMode      dictionary case processing mode
1648
         * @param diacriticProcessingMode dictionary diacritic processing mode
1649
         * @throws NullPointerException if any argument is {@code null}
1650
         */
1651
        public Builder(final IntFunction<V[]> arrayFactory, final ReductionSettings reductionSettings,
1652
                final WordTraversalDirection traversalDirection, final CaseProcessingMode caseProcessingMode,
1653
                final DiacriticProcessingMode diacriticProcessingMode) {
1654
            this(arrayFactory, reductionSettings, traversalDirection, caseProcessingMode, diacriticProcessingMode,
1655
                    CompiledNode.DEFAULT_MAX_EXPANDED_INDEX);
1656
        }
1657
1658
        /**
1659
         * Creates a new builder with the provided settings, explicit traversal
1660
         * direction, explicit case processing mode, explicit diacritic processing mode,
1661
         * and an explicit dense child lookup threshold.
1662
         *
1663
         * @param arrayFactory            array factory
1664
         * @param reductionSettings       reduction configuration
1665
         * @param traversalDirection      logical key traversal direction
1666
         * @param caseProcessingMode      dictionary case processing mode
1667
         * @param diacriticProcessingMode dictionary diacritic processing mode
1668
         * @param maxExpandedIndex        dense lookup span override; zero disables
1669
         *                                dense lookup. Larger values increase direct
1670
         *                                indexing opportunities while potentially
1671
         *                                increasing materialization memory in nodes
1672
         *                                whose edge label span is within the limit.
1673
         * @throws NullPointerException if any argument is {@code null}
1674
         */
1675
        public Builder(final IntFunction<V[]> arrayFactory, final ReductionSettings reductionSettings,
1676
                final WordTraversalDirection traversalDirection, final CaseProcessingMode caseProcessingMode,
1677
                final DiacriticProcessingMode diacriticProcessingMode, final int maxExpandedIndex) {
1678
            this.arrayFactory = Objects.requireNonNull(arrayFactory, "arrayFactory");
1679
            this.reductionSettings = Objects.requireNonNull(reductionSettings, "reductionSettings");
1680
            this.traversalDirection = Objects.requireNonNull(traversalDirection, "traversalDirection");
1681
            this.caseProcessingMode = Objects.requireNonNull(caseProcessingMode, "caseProcessingMode");
1682
            this.diacriticProcessingMode = Objects.requireNonNull(diacriticProcessingMode, "diacriticProcessingMode");
1683 2 1. <init> : changed conditional boundary → SURVIVED
2. <init> : negated conditional → KILLED
            if (maxExpandedIndex < 0) {
1684
                throw new IllegalArgumentException("maxExpandedIndex must be non-negative.");
1685
            }
1686
            this.maxExpandedIndex = maxExpandedIndex;
1687
            this.root = new MutableNode<>();
1688
        }
1689
1690
        /**
1691
         * Creates a new builder using default thresholds for the supplied reduction
1692
         * mode.
1693
         *
1694
         * <p>
1695
         * This constructor preserves the historical Egothor behavior and therefore
1696
         * traverses logical keys from their end toward their beginning.
1697
         * </p>
1698
         *
1699
         * @param arrayFactory  array factory
1700
         * @param reductionMode reduction mode
1701
         * @throws NullPointerException if any argument is {@code null}
1702
         */
1703
        public Builder(final IntFunction<V[]> arrayFactory, final ReductionMode reductionMode) {
1704
            this(arrayFactory, ReductionSettings.withDefaults(reductionMode), WordTraversalDirection.BACKWARD);
1705
        }
1706
1707
        /**
1708
         * Creates a new builder using default thresholds for the supplied reduction
1709
         * mode and explicit traversal direction.
1710
         *
1711
         * @param arrayFactory       array factory
1712
         * @param reductionMode      reduction mode
1713
         * @param traversalDirection logical key traversal direction
1714
         * @throws NullPointerException if any argument is {@code null}
1715
         */
1716
        public Builder(final IntFunction<V[]> arrayFactory, final ReductionMode reductionMode,
1717
                final WordTraversalDirection traversalDirection) {
1718
            this(arrayFactory, ReductionSettings.withDefaults(reductionMode), traversalDirection);
1719
        }
1720
1721
        /**
1722
         * Stores a value for the supplied key and increments its local frequency.
1723
         *
1724
         * <p>
1725
         * Values are stored at the node addressed by the full key. Since trie values
1726
         * may also appear on internal nodes, an empty key is valid and stores a value
1727
         * directly at the root.
1728
         *
1729
         * @param key   key
1730
         * @param value value
1731
         * @return this builder
1732
         * @throws NullPointerException if {@code key} or {@code value} is {@code null}
1733
         */
1734
        public Builder<V> put(final String key, final V value) {
1735 1 1. put : replaced return value with null for org/egothor/stemmer/FrequencyTrie$Builder::put → SURVIVED
            return put(key, value, 1);
1736
        }
1737
1738
        /**
1739
         * Builds a compiled read-only trie.
1740
         *
1741
         * @return compiled trie
1742
         */
1743
        public FrequencyTrie<V> build() {
1744
            if (LOGGER.isLoggable(Level.FINE)) {
1745
                LOGGER.log(Level.FINE, "Starting trie compilation with reduction mode {0}.",
1746
                        this.reductionSettings.reductionMode());
1747
            }
1748
1749
            final ReductionContext<V> reductionContext = new ReductionContext<>(this.reductionSettings);
1750
            final ReducedNode<V> reducedRoot = reduce(this.root, reductionContext);
1751
            final CompiledNode<V> compiledRoot = freeze(reducedRoot, new IdentityHashMap<>());
1752
1753
            if (LOGGER.isLoggable(Level.FINE)) {
1754
                LOGGER.log(Level.FINE, "Trie compilation finished. Canonical node count: {0}.",
1755
                        reductionContext.canonicalNodeCount());
1756
            }
1757
1758
            final TrieMetadata metadata = TrieMetadata.forCompilation(this.traversalDirection, this.reductionSettings,
1759
                    this.diacriticProcessingMode, this.caseProcessingMode);
1760 1 1. build : replaced return value with null for org/egothor/stemmer/FrequencyTrie$Builder::build → KILLED
            return new FrequencyTrie<>(this.arrayFactory, compiledRoot, metadata);
1761
        }
1762
1763
        /**
1764
         * Stores a value for the supplied key and increments its local frequency by the
1765
         * specified positive count.
1766
         *
1767
         * <p>
1768
         * Values are stored at the node addressed by the full key. Since trie values
1769
         * may also appear on internal nodes, an empty key is valid and stores a value
1770
         * directly at the root.
1771
         *
1772
         * <p>
1773
         * This method is functionally equivalent to calling
1774
         * {@link #put(String, Object)} repeatedly {@code count} times, but it avoids
1775
         * unnecessary repeated map updates and is therefore preferable for bulk
1776
         * reconstruction from compiled tries or other aggregated sources.
1777
         *
1778
         * @param key   key
1779
         * @param value value
1780
         * @param count positive frequency increment
1781
         * @return this builder
1782
         * @throws NullPointerException     if {@code key} or {@code value} is
1783
         *                                  {@code null}
1784
         * @throws IllegalArgumentException if {@code count} is less than {@code 1}
1785
         */
1786
        public Builder<V> put(final String key, final V value, final int count) {
1787
            Objects.requireNonNull(key, ARG_KEY);
1788
            Objects.requireNonNull(value, "value");
1789
1790 2 1. put : changed conditional boundary → KILLED
2. put : negated conditional → KILLED
            if (count < 1) { // NOPMD
1791
                throw new IllegalArgumentException("count must be at least 1.");
1792
            }
1793
1794
            final String normalizedKey = normalizeDictionaryKey(key);
1795
1796
            MutableNode<V> current = this.root;
1797 2 1. put : changed conditional boundary → KILLED
2. put : negated conditional → KILLED
            for (int traversalOffset = 0; traversalOffset < normalizedKey.length(); traversalOffset++) {
1798
                final Character edge = normalizedKey
1799
                        .charAt(this.traversalDirection.logicalIndex(normalizedKey.length(), traversalOffset));
1800
                MutableNode<V> child = current.children().get(edge);
1801 1 1. put : negated conditional → KILLED
                if (child == null) {
1802
                    child = new MutableNode<>(); // NOPMD
1803
                    current.children().put(edge, child);
1804
                }
1805
                current = child;
1806
            }
1807
1808
            final Integer previous = current.valueCounts().get(value);
1809 1 1. put : negated conditional → KILLED
            if (previous == null) {
1810
                current.valueCounts().put(value, count);
1811
            } else {
1812 1 1. put : Replaced integer addition with subtraction → KILLED
                current.valueCounts().put(value, previous + count);
1813
            }
1814 1 1. put : replaced return value with null for org/egothor/stemmer/FrequencyTrie$Builder::put → SURVIVED
            return this;
1815
        }
1816
1817
        /**
1818
         * Applies build-time dictionary-key normalization according to the builder
1819
         * configuration.
1820
         *
1821
         * @param key dictionary key
1822
         * @return normalized key for trie insertion
1823
         */
1824
        private String normalizeDictionaryKey(final String key) {
1825
            String normalized = key;
1826
1827 1 1. normalizeDictionaryKey : negated conditional → KILLED
            if (this.caseProcessingMode == CaseProcessingMode.LOWERCASE_WITH_LOCALE_ROOT) {
1828
                normalized = normalized.toLowerCase(Locale.ROOT);
1829
            }
1830
1831 1 1. normalizeDictionaryKey : negated conditional → KILLED
            if (this.diacriticProcessingMode == DiacriticProcessingMode.REMOVE) {
1832
                normalized = DiacriticStripper.strip(normalized);
1833 1 1. normalizeDictionaryKey : negated conditional → KILLED
            } else if (this.diacriticProcessingMode == DiacriticProcessingMode.AS_IS_AND_STRIPPED_FALLBACK) {
1834
                throw new UnsupportedOperationException(
1835
                        "Diacritic processing mode AS_IS_AND_STRIPPED_FALLBACK is not supported yet.");
1836
            }
1837
1838 1 1. normalizeDictionaryKey : replaced return value with "" for org/egothor/stemmer/FrequencyTrie$Builder::normalizeDictionaryKey → KILLED
            return normalized;
1839
        }
1840
1841
        /**
1842
         * Returns the number of mutable build-time nodes currently reachable from the
1843
         * builder root.
1844
         *
1845
         * <p>
1846
         * This metric is intended mainly for diagnostics and tests that compare the
1847
         * unreduced build-time structure with the final reduced compiled trie.
1848
         *
1849
         * @return number of mutable build-time nodes
1850
         */
1851
        /* default */ int buildTimeSize() {
1852 1 1. buildTimeSize : replaced int return with 0 for org/egothor/stemmer/FrequencyTrie$Builder::buildTimeSize → KILLED
            return countMutableNodes(this.root);
1853
        }
1854
1855
        /**
1856
         * Returns the logical key traversal direction used by this builder.
1857
         *
1858
         * @return logical key traversal direction
1859
         */
1860
        /* default */ WordTraversalDirection traversalDirection() {
1861 1 1. traversalDirection : replaced return value with null for org/egothor/stemmer/FrequencyTrie$Builder::traversalDirection → NO_COVERAGE
            return this.traversalDirection;
1862
        }
1863
1864
        /**
1865
         * Counts mutable nodes recursively.
1866
         *
1867
         * @param node current node
1868
         * @return reachable mutable node count
1869
         */
1870
        private int countMutableNodes(final MutableNode<V> node) {
1871
            int count = 1;
1872
            for (MutableNode<V> child : node.children().values()) {
1873 1 1. countMutableNodes : Replaced integer addition with subtraction → KILLED
                count += countMutableNodes(child);
1874
            }
1875 1 1. countMutableNodes : replaced int return with 0 for org/egothor/stemmer/FrequencyTrie$Builder::countMutableNodes → KILLED
            return count;
1876
        }
1877
1878
        /**
1879
         * Reduces a mutable node to a canonical reduced node.
1880
         *
1881
         * @param source  source mutable node
1882
         * @param context reduction context
1883
         * @return canonical reduced node
1884
         */
1885
        private ReducedNode<V> reduce(final MutableNode<V> source, final ReductionContext<V> context) {
1886
            Map<Character, ReducedNode<V>> reducedChildren = new LinkedHashMap<>();
1887
1888
            for (Map.Entry<Character, MutableNode<V>> childEntry : source.children().entrySet()) {
1889
                final ReducedNode<V> reducedChild = reduce(childEntry.getValue(), context);
1890
                reducedChildren.put(childEntry.getKey(), reducedChild);
1891
            }
1892
1893
            Map<V, Integer> localCounts = copyCounts(source.valueCounts());
1894
            boolean acceptsRemainingInput = false;
1895 1 1. reduce : negated conditional → KILLED
            if (context.settings().contractUniformSubtrees()) {
1896
                final Map<V, Integer> contractedCounts = contractUniformSubtree(localCounts, reducedChildren);
1897 1 1. reduce : negated conditional → KILLED
                if (!contractedCounts.isEmpty()) {
1898
                    localCounts = contractedCounts;
1899
                    reducedChildren = Collections.emptyMap();
1900
                    acceptsRemainingInput = true;
1901
                }
1902
            }
1903
1904
            final LocalValueSummary<V> localSummary = LocalValueSummary.of(localCounts, this.arrayFactory);
1905
            final ReductionSignature<V> signature = ReductionSignature.create(localSummary, reducedChildren,
1906
                    context.settings(), acceptsRemainingInput);
1907
1908
            ReducedNode<V> canonical = context.lookup(signature);
1909 1 1. reduce : negated conditional → KILLED
            if (canonical == null) {
1910
                canonical = new ReducedNode<>(signature, localCounts, reducedChildren, acceptsRemainingInput);
1911 1 1. reduce : removed call to org/egothor/stemmer/trie/ReductionContext::register → KILLED
                context.register(signature, canonical);
1912 1 1. reduce : replaced return value with null for org/egothor/stemmer/FrequencyTrie$Builder::reduce → KILLED
                return canonical;
1913
            }
1914
1915 1 1. reduce : removed call to org/egothor/stemmer/trie/ReducedNode::mergeLocalCounts → KILLED
            canonical.mergeLocalCounts(localCounts);
1916 1 1. reduce : removed call to org/egothor/stemmer/trie/ReducedNode::mergeChildren → SURVIVED
            canonical.mergeChildren(reducedChildren);
1917
1918 1 1. reduce : replaced return value with null for org/egothor/stemmer/FrequencyTrie$Builder::reduce → KILLED
            return canonical;
1919
        }
1920
1921
        /**
1922
         * Returns aggregated local counts when the supplied internal subtree contains
1923
         * one uniform value, otherwise {@code null}.
1924
         *
1925
         * @param localCounts     local counts at the current node
1926
         * @param reducedChildren already reduced children
1927
         * @return single-value aggregate for a uniform non-leaf subtree, otherwise an
1928
         *         empty map
1929
         */
1930
        private Map<V, Integer> contractUniformSubtree(final Map<V, Integer> localCounts,
1931
                final Map<Character, ReducedNode<V>> reducedChildren) {
1932 1 1. contractUniformSubtree : negated conditional → KILLED
            if (reducedChildren.isEmpty()) {
1933
                return Collections.emptyMap();
1934
            }
1935
1936
            V uniformValue = null;
1937
            boolean valueSeen = false;
1938
1939 1 1. contractUniformSubtree : negated conditional → KILLED
            if (!localCounts.isEmpty()) {
1940 1 1. contractUniformSubtree : negated conditional → SURVIVED
                if (localCounts.size() != SINGLE_VALUE_COUNT) {
1941
                    return Collections.emptyMap();
1942
                }
1943
                final Map.Entry<V, Integer> localEntry = localCounts.entrySet().iterator().next();
1944
                uniformValue = localEntry.getKey();
1945
                valueSeen = true;
1946
            }
1947
1948
            for (ReducedNode<V> child : reducedChildren.values()) {
1949 1 1. contractUniformSubtree : negated conditional → KILLED
                if (!isSingleValueLeaf(child)) {
1950
                    return Collections.emptyMap();
1951
                }
1952
                final Map.Entry<V, Integer> childEntry = child.localCounts().entrySet().iterator().next();
1953 2 1. contractUniformSubtree : negated conditional → KILLED
2. contractUniformSubtree : negated conditional → KILLED
                if (valueSeen && !Objects.equals(uniformValue, childEntry.getKey())) {
1954
                    return Collections.emptyMap();
1955
                }
1956
                uniformValue = childEntry.getKey();
1957
                valueSeen = true;
1958
            }
1959
1960 1 1. contractUniformSubtree : negated conditional → KILLED
            if (!valueSeen) {
1961
                return Collections.emptyMap();
1962
            }
1963
1964
            final Map<V, Integer> contractedCounts = new LinkedHashMap<>(SINGLE_VALUE_COUNT);
1965
            contractedCounts.put(uniformValue, SINGLE_VALUE_COUNT);
1966 1 1. contractUniformSubtree : replaced return value with Collections.emptyMap for org/egothor/stemmer/FrequencyTrie$Builder::contractUniformSubtree → KILLED
            return contractedCounts;
1967
        }
1968
1969
        /**
1970
         * Returns whether the reduced node is a leaf with exactly one stored value.
1971
         *
1972
         * @param node node to inspect
1973
         * @return {@code true} when the node can participate in uniform contraction
1974
         */
1975
        private boolean isSingleValueLeaf(final ReducedNode<V> node) {
1976 3 1. isSingleValueLeaf : negated conditional → KILLED
2. isSingleValueLeaf : replaced boolean return with true for org/egothor/stemmer/FrequencyTrie$Builder::isSingleValueLeaf → KILLED
3. isSingleValueLeaf : negated conditional → KILLED
            return node.children().isEmpty() && node.localCounts().size() == SINGLE_VALUE_COUNT;
1977
        }
1978
1979
        /**
1980
         * Freezes a reduced node into an immutable compiled node.
1981
         *
1982
         * @param reducedNode reduced node
1983
         * @param cache       already frozen nodes
1984
         * @return immutable compiled node
1985
         */
1986
        private CompiledNode<V> freeze(final ReducedNode<V> reducedNode,
1987
                final Map<ReducedNode<V>, CompiledNode<V>> cache) {
1988
            final CompiledNode<V> existing = cache.get(reducedNode);
1989 1 1. freeze : negated conditional → KILLED
            if (existing != null) {
1990 1 1. freeze : replaced return value with null for org/egothor/stemmer/FrequencyTrie$Builder::freeze → KILLED
                return existing;
1991
            }
1992
1993
            final LocalValueSummary<V> localSummary = LocalValueSummary.of(reducedNode.localCounts(),
1994
                    this.arrayFactory);
1995
1996
            final List<Map.Entry<Character, ReducedNode<V>>> childEntries = new ArrayList<>(
1997
                    reducedNode.children().entrySet());
1998 1 1. freeze : removed call to java/util/List::sort → KILLED
            childEntries.sort(Map.Entry.comparingByKey());
1999
2000
            final char[] edges = new char[childEntries.size()];
2001
            @SuppressWarnings("unchecked")
2002
            final CompiledNode<V>[] childNodes = new CompiledNode[childEntries.size()];
2003
2004 2 1. freeze : changed conditional boundary → KILLED
2. freeze : negated conditional → KILLED
            for (int index = 0; index < childEntries.size(); index++) {
2005
                final Map.Entry<Character, ReducedNode<V>> entry = childEntries.get(index);
2006
                edges[index] = entry.getKey();
2007
                childNodes[index] = freeze(entry.getValue(), cache);
2008
            }
2009
2010
            final CompiledNode<V> frozen = new CompiledNode<>(edges, childNodes, localSummary.orderedValues(),
2011
                    reducedNode.acceptsRemainingInput(), this.maxExpandedIndex, localSummary.orderedCounts());
2012
            cache.put(reducedNode, frozen);
2013 1 1. freeze : replaced return value with null for org/egothor/stemmer/FrequencyTrie$Builder::freeze → KILLED
            return frozen;
2014
        }
2015
2016
        /**
2017
         * Creates a shallow frequency copy preserving deterministic insertion order of
2018
         * first occurrence.
2019
         *
2020
         * @param source source counts
2021
         * @return copied counts
2022
         */
2023
        private Map<V, Integer> copyCounts(final Map<V, Integer> source) {
2024 1 1. copyCounts : replaced return value with Collections.emptyMap for org/egothor/stemmer/FrequencyTrie$Builder::copyCounts → KILLED
            return new LinkedHashMap<>(source);
2025
        }
2026
    }
2027
2028
    /**
2029
     * Reads one final trie value using metadata parsed from the same binary stream.
2030
     *
2031
     * <p>
2032
     * Implementations are invoked only during deserialization and are not retained
2033
     * by the resulting trie. Returned values are stored directly in final compiled
2034
     * node arrays.
2035
     * </p>
2036
     *
2037
     * @param <V> final value type
2038
     */
2039
    /* default */
2040
    @FunctionalInterface
2041
    interface MetadataValueStreamReader<V> {
2042
2043
        /**
2044
         * Reads and materializes one final value.
2045
         *
2046
         * @param dataInput source data input
2047
         * @param metadata  already parsed trie metadata
2048
         * @return final value to store directly in compiled nodes
2049
         * @throws IOException if reading or materialization fails
2050
         */
2051
        V read(DataInputStream dataInput, TrieMetadata metadata) throws IOException;
2052
    }
2053
2054
    /**
2055
     * Codec used to persist values stored in the trie.
2056
     *
2057
     * @param <V> value type
2058
     */
2059
    public interface ValueStreamCodec<V> {
2060
2061
        /**
2062
         * Writes one value to the supplied data output.
2063
         *
2064
         * @param dataOutput target data output
2065
         * @param value      value to write
2066
         * @throws IOException if writing fails
2067
         */
2068
        void write(DataOutputStream dataOutput, V value) throws IOException;
2069
2070
        /**
2071
         * Reads one value from the supplied data input.
2072
         *
2073
         * @param dataInput source data input
2074
         * @return read value
2075
         * @throws IOException if reading fails
2076
         */
2077
        V read(DataInputStream dataInput) throws IOException;
2078
    }
2079
2080
}

Mutations

242

1.1
Location : currentFormatVersion
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:currentCompiledTrieFormatVersionIsSeven()]
replaced int return with 0 for org/egothor/stemmer/FrequencyTrie::currentFormatVersion → KILLED

254

1.1
Location : usesValueTableFormat
Killed by : none
changed conditional boundary → SURVIVED
Covering tests

2.2
Location : usesValueTableFormat
Killed by : org.egothor.stemmer.StemmerPatchTrieBinaryIOTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.StemmerPatchTrieBinaryIOTest]/[nested-class:ReadTests]/[method:shouldCompileRepeatedVersionSixInlineCommandsOnce()]
negated conditional → KILLED

3.3
Location : usesValueTableFormat
Killed by : org.egothor.stemmer.StemmerPatchTrieBinaryIOTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.StemmerPatchTrieBinaryIOTest]/[nested-class:ReadTests]/[method:shouldCompileRepeatedVersionSixInlineCommandsOnce()]
replaced boolean return with true for org/egothor/stemmer/FrequencyTrie::usesValueTableFormat → KILLED

294

1.1
Location : <init>
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:lookupKeepsCaseSensitiveBehaviorWhenMetadataIsAsIs()]
negated conditional → KILLED

295

1.1
Location : <init>
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:diacriticRemoveModeStripsDictionaryAndLookupKeys()]
negated conditional → KILLED

311

1.1
Location : fromCompiled
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldPreserveUniformSubtreeContractionWhenMappingValues()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::fromCompiled → KILLED

336

1.1
Location : get
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyTrieReturnsNullEmptyArrayAndEmptyEntries()]
negated conditional → KILLED

340

1.1
Location : get
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyKeyStoresValuesAtRootNode()]
negated conditional → KILLED

343

1.1
Location : get
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyKeyStoresValuesAtRootNode()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::get → KILLED

365

1.1
Location : getNormalized
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupSupportsCharSlicesAndMetadataAwareKeys()]
negated conditional → KILLED

369

1.1
Location : getNormalized
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupSupportsCharSlicesAndMetadataAwareKeys()]
negated conditional → KILLED

372

1.1
Location : getNormalized
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupSupportsCharSlicesAndMetadataAwareKeys()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::getNormalized → KILLED

393

1.1
Location : getNormalizedString
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupSupportsCharSlicesAndMetadataAwareKeys()]
negated conditional → KILLED

397

1.1
Location : getNormalizedString
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupSupportsCharSlicesAndMetadataAwareKeys()]
negated conditional → KILLED

400

1.1
Location : getNormalizedString
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupSupportsCharSlicesAndMetadataAwareKeys()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::getNormalizedString → KILLED

430

1.1
Location : getAll
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyTrieReturnsNullEmptyArrayAndEmptyEntries()]
negated conditional → KILLED

431

1.1
Location : getAll
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyTrieReturnsNullEmptyArrayAndEmptyEntries()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::getAll → KILLED

434

1.1
Location : getAll
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyKeyStoresValuesAtRootNode()]
negated conditional → KILLED

435

1.1
Location : getAll
Killed by : none
replaced return value with null for org/egothor/stemmer/FrequencyTrie::getAll → SURVIVED
Covering tests

437

1.1
Location : getAll
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyKeyStoresValuesAtRootNode()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::getAll → KILLED

465

1.1
Location : getEntries
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyTrieReturnsNullEmptyArrayAndEmptyEntries()]
negated conditional → KILLED

471

1.1
Location : getEntries
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyKeyStoresValuesAtRootNode()]
negated conditional → KILLED

475

1.1
Location : getEntries
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyKeyStoresValuesAtRootNode()]
negated conditional → KILLED

476

1.1
Location : getEntries
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:getEntriesReturnsSingleItemListForSingleStoredValue()]
replaced return value with Collections.emptyList for org/egothor/stemmer/FrequencyTrie::getEntries → KILLED

481

1.1
Location : getEntries
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyKeyStoresValuesAtRootNode()]
changed conditional boundary → KILLED

2.2
Location : getEntries
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyKeyStoresValuesAtRootNode()]
negated conditional → KILLED

484

1.1
Location : getEntries
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyKeyStoresValuesAtRootNode()]
replaced return value with Collections.emptyList for org/egothor/stemmer/FrequencyTrie::getEntries → KILLED

515

1.1
Location : getAllNormalized
Killed by : none
removed call to org/egothor/stemmer/FrequencyTrie::validateMaxResults → SURVIVED
Covering tests

516

1.1
Location : getAllNormalized
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupSupportsCharSlicesAndMetadataAwareKeys()]
negated conditional → KILLED

519

1.1
Location : getAllNormalized
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupSupportsCharSlicesAndMetadataAwareKeys()]
replaced int return with 0 for org/egothor/stemmer/FrequencyTrie::getAllNormalized → KILLED

538

1.1
Location : getAllNormalized
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupHandlesBoundaryCases()]
removed call to org/egothor/stemmer/FrequencyTrie::validateMaxResults → KILLED

539

1.1
Location : getAllNormalized
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupMatchesGetAllOrderAndGetEntriesCounts()]
negated conditional → KILLED

542

1.1
Location : getAllNormalized
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupMatchesGetAllOrderAndGetEntriesCounts()]
replaced int return with 0 for org/egothor/stemmer/FrequencyTrie::getAllNormalized → KILLED

558

1.1
Location : getFirstNormalized
Killed by : none
replaced boolean return with true for org/egothor/stemmer/FrequencyTrie::getFirstNormalized → NO_COVERAGE

2.2
Location : getFirstNormalized
Killed by : none
negated conditional → NO_COVERAGE

571

1.1
Location : getFirstNormalized
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupHandlesBoundaryCases()]
negated conditional → KILLED

2.2
Location : getFirstNormalized
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupHandlesBoundaryCases()]
replaced boolean return with true for org/egothor/stemmer/FrequencyTrie::getFirstNormalized → KILLED

592

1.1
Location : getAll
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupRejectsNullAndInvalidRangeArguments()]
removed call to org/egothor/stemmer/FrequencyTrie::validateMaxResults → KILLED

593

1.1
Location : getAll
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupSupportsCharSlicesAndMetadataAwareKeys()]
negated conditional → KILLED

597

1.1
Location : getAll
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupSupportsCharSlicesAndMetadataAwareKeys()]
replaced int return with 0 for org/egothor/stemmer/FrequencyTrie::getAll → KILLED

610

1.1
Location : getFirst
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupSupportsCharSlicesAndMetadataAwareKeys()]
negated conditional → KILLED

2.2
Location : getFirst
Killed by : none
replaced boolean return with true for org/egothor/stemmer/FrequencyTrie::getFirst → SURVIVED
Covering tests

624

1.1
Location : traversalDirection
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:ordinaryOperationsDoNotCalculateFingerprint()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::traversalDirection → KILLED

633

1.1
Location : metadata
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromSupportsLegacyVersionTwoMetadata()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::metadata → KILLED

660

1.1
Location : getFingerprint
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:firstGetFingerprintCalculatesAndCachesFingerprint()]
replaced return value with "" for org/egothor/stemmer/FrequencyTrie::getFingerprint → KILLED

680

1.1
Location : copyFingerprintBytes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:firstGetFingerprintCalculatesAndCachesFingerprint()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::copyFingerprintBytes → KILLED

697

1.1
Location : fingerprintBytes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:firstGetFingerprintCalculatesAndCachesFingerprint()]
removed call to java/util/concurrent/locks/ReentrantLock::lock → KILLED

700

1.1
Location : fingerprintBytes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:firstGetFingerprintCalculatesAndCachesFingerprint()]
negated conditional → KILLED

704

1.1
Location : fingerprintBytes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:firstGetFingerprintCalculatesAndCachesFingerprint()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::fingerprintBytes → KILLED

706

1.1
Location : fingerprintBytes
Killed by : none
removed call to java/util/concurrent/locks/ReentrantLock::unlock → TIMED_OUT

712

1.1
Location : computeFingerprintBytes
Killed by : none
removed call to org/egothor/stemmer/FrequencyTrie::updateUtf8 → SURVIVED
Covering tests

713

1.1
Location : computeFingerprintBytes
Killed by : none
removed call to org/egothor/stemmer/FrequencyTrie::updateInt → SURVIVED
Covering tests

714

1.1
Location : computeFingerprintBytes
Killed by : none
removed call to org/egothor/stemmer/FrequencyTrie::updateUtf8 → SURVIVED
Covering tests

718

1.1
Location : computeFingerprintBytes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:firstGetFingerprintCalculatesAndCachesFingerprint()]
removed call to org/egothor/stemmer/FrequencyTrie::assignNodeIds → KILLED

720

1.1
Location : computeFingerprintBytes
Killed by : none
removed call to org/egothor/stemmer/FrequencyTrie::updateInt → SURVIVED
Covering tests

721

1.1
Location : computeFingerprintBytes
Killed by : none
removed call to org/egothor/stemmer/FrequencyTrie::updateInt → SURVIVED
Covering tests

723

1.1
Location : computeFingerprintBytes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:firstGetFingerprintCalculatesAndCachesFingerprint()]
removed call to org/egothor/stemmer/FrequencyTrie::updateNodeFingerprint → KILLED

725

1.1
Location : computeFingerprintBytes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:firstGetFingerprintCalculatesAndCachesFingerprint()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::computeFingerprintBytes → KILLED

734

1.1
Location : root
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldKeepExactLookupWhenUniformSubtreeContractionIsDisabled()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::root → KILLED

759

1.1
Location : writeTo
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:writeToAndReadFromRejectNullArguments()]
negated conditional → KILLED

767

1.1
Location : writeTo
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:writeToAndReadFromRejectNullArguments()]
removed call to org/egothor/stemmer/FrequencyTrie::assignNodeIds → KILLED

770

1.1
Location : writeTo
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:versionSevenWriterEncodesEachEqualityDistinctValueOnce()]
removed call to org/egothor/stemmer/FrequencyTrie::collectDistinctValues → KILLED

776

1.1
Location : writeTo
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:versionSevenStreamWritesHeaderMetadataAndValueTableInOrder()]
removed call to java/io/DataOutputStream::writeInt → KILLED

777

1.1
Location : writeTo
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:versionSevenStreamWritesHeaderMetadataAndValueTableInOrder()]
removed call to java/io/DataOutputStream::writeInt → KILLED

778

1.1
Location : writeTo
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:versionSevenStreamWritesHeaderMetadataAndValueTableInOrder()]
removed call to java/io/DataOutputStream::writeInt → KILLED

779

1.1
Location : writeTo
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:versionSevenStreamWritesHeaderMetadataAndValueTableInOrder()]
removed call to java/io/DataOutputStream::writeInt → KILLED

780

1.1
Location : writeTo
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:versionSevenStreamWritesHeaderMetadataAndValueTableInOrder()]
removed call to org/egothor/stemmer/FrequencyTrie::writeMetadata → KILLED

781

1.1
Location : writeTo
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:versionSevenWriterEncodesEachEqualityDistinctValueOnce()]
removed call to org/egothor/stemmer/FrequencyTrie::writeValueTable → KILLED

783

1.1
Location : writeTo
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:metadataAwareVersionSevenReaderMaterializesSharedFinalValues()]
negated conditional → KILLED

2.2
Location : writeTo
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:writeToAndReadFromRejectNullArguments()]
changed conditional boundary → KILLED

784

1.1
Location : writeTo
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:metadataAwareVersionSevenReaderMaterializesSharedFinalValues()]
removed call to org/egothor/stemmer/FrequencyTrie::writeNode → KILLED

787

1.1
Location : writeTo
Killed by : none
removed call to java/io/DataOutputStream::flush → SURVIVED
Covering tests

807

1.1
Location : readFrom
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromSupportsLegacyVersionTwoMetadata()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::readFrom → KILLED

833

1.1
Location : readFrom
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromSupportsLegacyVersionTwoMetadata()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::readFrom → KILLED

834

1.1
Location : lambda$readFrom$0
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromSupportsInlineValuesInStreamVersionsFiveAndSix()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::lambda$readFrom$0 → KILLED

862

1.1
Location : readFromWithMetadata
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromSupportsLegacyVersionTwoMetadata()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::readFromWithMetadata → KILLED

874

1.1
Location : writeMetadata
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:versionSevenStreamWritesHeaderMetadataAndValueTableInOrder()]
removed call to java/io/DataOutputStream::writeUTF → KILLED

891

1.1
Location : metadataForCurrentStream
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:writeToAndReadFromRejectNullArguments()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::metadataForCurrentStream → KILLED

908

1.1
Location : size
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:ordinaryOperationsDoNotCalculateFingerprint()]
removed call to org/egothor/stemmer/FrequencyTrie::assignNodeIds → KILLED

909

1.1
Location : size
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:ordinaryOperationsDoNotCalculateFingerprint()]
replaced int return with 0 for org/egothor/stemmer/FrequencyTrie::size → KILLED

922

1.1
Location : assignNodeIds
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:writeToAndReadFromRejectNullArguments()]
negated conditional → KILLED

931

1.1
Location : assignNodeIds
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:versionSevenWriterEncodesEachEqualityDistinctValueOnce()]
removed call to org/egothor/stemmer/FrequencyTrie::assignNodeIds → KILLED

954

1.1
Location : collectDistinctValues
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:versionSevenWriterEncodesEachEqualityDistinctValueOnce()]
negated conditional → KILLED

974

1.1
Location : writeValueTable
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:versionSevenStreamWritesHeaderMetadataAndValueTableInOrder()]
removed call to java/io/DataOutputStream::writeInt → KILLED

976

1.1
Location : writeValueTable
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:versionSevenWriterEncodesEachEqualityDistinctValueOnce()]
removed call to org/egothor/stemmer/FrequencyTrie$ValueStreamCodec::write → KILLED

993

1.1
Location : writeNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:metadataAwareVersionSevenReaderMaterializesSharedFinalValues()]
removed call to java/io/DataOutputStream::writeBoolean → KILLED

994

1.1
Location : writeNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:metadataAwareVersionSevenReaderMaterializesSharedFinalValues()]
removed call to java/io/DataOutputStream::writeInt → KILLED

995

1.1
Location : writeNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:writeToAndReadFromRejectNullArguments()]
changed conditional boundary → KILLED

2.2
Location : writeNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:writeToAndReadFromRejectNullArguments()]
negated conditional → KILLED

996

1.1
Location : writeNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:metadataAwareVersionSevenReaderMaterializesSharedFinalValues()]
removed call to java/io/DataOutputStream::writeChar → KILLED

998

1.1
Location : writeNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:versionSevenWriterEncodesEachEqualityDistinctValueOnce()]
negated conditional → KILLED

1001

1.1
Location : writeNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:metadataAwareVersionSevenReaderMaterializesSharedFinalValues()]
removed call to java/io/DataOutputStream::writeInt → KILLED

1004

1.1
Location : writeNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:metadataAwareVersionSevenReaderMaterializesSharedFinalValues()]
removed call to java/io/DataOutputStream::writeInt → KILLED

1005

1.1
Location : writeNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:writeToAndReadFromRejectNullArguments()]
changed conditional boundary → KILLED

2.2
Location : writeNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:writeToAndReadFromRejectNullArguments()]
negated conditional → KILLED

1008

1.1
Location : writeNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:versionSevenWriterEncodesEachEqualityDistinctValueOnce()]
negated conditional → KILLED

1009

1.1
Location : writeNode
Killed by : none
negated conditional → NO_COVERAGE

1014

1.1
Location : writeNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:metadataAwareVersionSevenReaderMaterializesSharedFinalValues()]
removed call to java/io/DataOutputStream::writeInt → KILLED

1015

1.1
Location : writeNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:metadataAwareVersionSevenReaderMaterializesSharedFinalValues()]
removed call to java/io/DataOutputStream::writeInt → KILLED

1021

1.1
Location : newSha256Digest
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:firstGetFingerprintCalculatesAndCachesFingerprint()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::newSha256Digest → KILLED

1034

1.1
Location : updateNodeFingerprint
Killed by : none
negated conditional → SURVIVED
Covering tests

2.2
Location : updateNodeFingerprint
Killed by : none
removed call to org/egothor/stemmer/FrequencyTrie::updateInt → SURVIVED Covering tests

1035

1.1
Location : updateNodeFingerprint
Killed by : none
removed call to org/egothor/stemmer/FrequencyTrie::updateInt → SURVIVED
Covering tests

1037

1.1
Location : updateNodeFingerprint
Killed by : none
removed call to org/egothor/stemmer/FrequencyTrie::updateInt → SURVIVED
Covering tests

1041

1.1
Location : updateNodeFingerprint
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:firstGetFingerprintCalculatesAndCachesFingerprint()]
negated conditional → KILLED

1044

1.1
Location : updateNodeFingerprint
Killed by : none
removed call to org/egothor/stemmer/FrequencyTrie::updateInt → SURVIVED
Covering tests

1047

1.1
Location : updateNodeFingerprint
Killed by : none
removed call to org/egothor/stemmer/FrequencyTrie::updateInt → SURVIVED
Covering tests

1049

1.1
Location : updateNodeFingerprint
Killed by : none
removed call to org/egothor/stemmer/FrequencyTrie::updateUtf8 → SURVIVED
Covering tests

1052

1.1
Location : updateNodeFingerprint
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:fingerprintReflectsMetadataAndCompiledTrieContent()]
removed call to org/egothor/stemmer/FrequencyTrie::updateInt → KILLED

1058

1.1
Location : updateUtf8
Killed by : none
removed call to org/egothor/stemmer/FrequencyTrie::updateInt → SURVIVED
Covering tests

1059

1.1
Location : updateUtf8
Killed by : none
removed call to java/security/MessageDigest::update → SURVIVED
Covering tests

1063

1.1
Location : updateInt
Killed by : none
removed call to java/security/MessageDigest::update → SURVIVED
Covering tests

2.2
Location : updateInt
Killed by : none
Replaced Unsigned Shift Right with Shift Left → SURVIVED Covering tests

1064

1.1
Location : updateInt
Killed by : none
removed call to java/security/MessageDigest::update → SURVIVED
Covering tests

2.2
Location : updateInt
Killed by : none
Replaced Unsigned Shift Right with Shift Left → SURVIVED Covering tests

1065

1.1
Location : updateInt
Killed by : none
removed call to java/security/MessageDigest::update → SURVIVED
Covering tests

2.2
Location : updateInt
Killed by : none
Replaced Unsigned Shift Right with Shift Left → SURVIVED Covering tests

1066

1.1
Location : updateInt
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:fingerprintReflectsMetadataAndCompiledTrieContent()]
removed call to java/security/MessageDigest::update → KILLED

1070

1.1
Location : toLowerHex
Killed by : none
Replaced integer multiplication with division → SURVIVED
Covering tests

1072

1.1
Location : toLowerHex
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:firstGetFingerprintCalculatesAndCachesFingerprint()]
Replaced Unsigned Shift Right with Shift Left → KILLED

2.2
Location : toLowerHex
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:firstGetFingerprintCalculatesAndCachesFingerprint()]
Replaced bitwise AND with OR → KILLED

3.3
Location : toLowerHex
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:firstGetFingerprintCalculatesAndCachesFingerprint()]
Replaced bitwise AND with OR → KILLED

1074

1.1
Location : toLowerHex
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:firstGetFingerprintCalculatesAndCachesFingerprint()]
replaced return value with "" for org/egothor/stemmer/FrequencyTrie::toLowerHex → KILLED

1093

1.1
Location : read
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsInvalidRootNodeIdentifier()]
changed conditional boundary → KILLED

2.2
Location : read
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsInvalidRootNodeIdentifier()]
negated conditional → KILLED

1099

1.1
Location : read
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsInvalidRootNodeIdentifier()]
negated conditional → KILLED

1104

1.1
Location : read
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsInvalidRootNodeIdentifier()]
negated conditional → KILLED

2.2
Location : read
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsInvalidTextualMetadataBlock()]
changed conditional boundary → KILLED

3.3
Location : read
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsInvalidRootNodeIdentifier()]
changed conditional boundary → KILLED

4.4
Location : read
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsInvalidRootNodeIdentifier()]
negated conditional → KILLED

1109

1.1
Location : read
Killed by : none
changed conditional boundary → SURVIVED
Covering tests

2.2
Location : read
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsInvalidRootNodeIdentifier()]
negated conditional → KILLED

1114

1.1
Location : read
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsInvalidTextualMetadataBlock()]
changed conditional boundary → KILLED

2.2
Location : read
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsInvalidRootNodeIdentifier()]
changed conditional boundary → KILLED

3.3
Location : read
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsInvalidRootNodeIdentifier()]
negated conditional → KILLED

4.4
Location : read
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsInvalidTextualMetadataBlock()]
negated conditional → KILLED

1119

1.1
Location : read
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
negated conditional → KILLED

2.2
Location : read
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:versionSevenReaderRejectsNegativeValueTableSize()]
changed conditional boundary → KILLED

1122

1.1
Location : read
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromSupportsLegacyVersionTwoMetadata()]
negated conditional → KILLED

2.2
Location : read
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRespectsDenseLookupMaxExpandedIndexOverride()]
changed conditional boundary → KILLED

1131

1.1
Location : read
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromSupportsLegacyVersionTwoMetadata()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::read → KILLED

1154

1.1
Location : readValueTable
Killed by : none
changed conditional boundary → SURVIVED
Covering tests

2.2
Location : readValueTable
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:versionSevenReaderRejectsNegativeValueTableSize()]
negated conditional → KILLED

1159

1.1
Location : readValueTable
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:versionSevenReaderRejectsValueTableIndexGreaterThanSize()]
negated conditional → KILLED

2.2
Location : readValueTable
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:versionSevenReaderRejectsValueTableIndexGreaterThanSize()]
changed conditional boundary → KILLED

1162

1.1
Location : readValueTable
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:versionSevenReaderRejectsValueTableIndexGreaterThanSize()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readValueTable → KILLED

1166

1.1
Location : wrapInputStream
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsInvalidRootNodeIdentifier()]
negated conditional → KILLED

2.2
Location : wrapInputStream
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsInvalidRootNodeIdentifier()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::wrapInputStream → KILLED

1172

1.1
Location : readMetadata
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsInvalidTextualMetadataBlock()]
negated conditional → KILLED

2.2
Location : readMetadata
Killed by : org.egothor.stemmer.CompiledTrieArtifactRegressionTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.CompiledTrieArtifactRegressionTest]/[test-template:shouldLoadGoldenArtifactsDirectlyAsCompiledCommands(org.egothor.stemmer.CompiledTrieArtifactRegressionTest$ArtifactCase)]/[test-template-invocation:#3]
changed conditional boundary → KILLED

1173

1.1
Location : readMetadata
Killed by : org.egothor.stemmer.CompiledTrieArtifactRegressionTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.CompiledTrieArtifactRegressionTest]/[test-template:shouldLoadGoldenArtifactsDirectlyAsCompiledCommands(org.egothor.stemmer.CompiledTrieArtifactRegressionTest$ArtifactCase)]/[test-template-invocation:#3]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readMetadata → KILLED

1177

1.1
Location : readMetadata
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsNonPositiveStoredCounts()]
negated conditional → KILLED

2.2
Location : readMetadata
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromParsesVersionThreeMetadata()]
changed conditional boundary → KILLED

1178

1.1
Location : readMetadata
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromSupportsLegacyVersionTwoMetadata()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readMetadata → KILLED

1184

1.1
Location : readMetadata
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromParsesVersionThreeMetadata()]
negated conditional → KILLED

2.2
Location : readMetadata
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromParsesVersionFourCaseMetadata()]
changed conditional boundary → KILLED

1186

1.1
Location : readMetadata
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromParsesVersionThreeMetadata()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readMetadata → KILLED

1193

1.1
Location : readTextMetadata
Killed by : org.egothor.stemmer.CompiledTrieArtifactRegressionTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.CompiledTrieArtifactRegressionTest]/[test-template:shouldLoadGoldenArtifactsDirectlyAsCompiledCommands(org.egothor.stemmer.CompiledTrieArtifactRegressionTest$ArtifactCase)]/[test-template-invocation:#3]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readTextMetadata → KILLED

1201

1.1
Location : readTraversalDirection
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsInvalidLegacyMetadataOrdinal()]
negated conditional → KILLED

2.2
Location : readTraversalDirection
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsInvalidLegacyMetadataOrdinal()]
changed conditional boundary → KILLED

1202

1.1
Location : readTraversalDirection
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsNonPositiveStoredCounts()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readTraversalDirection → KILLED

1204

1.1
Location : readTraversalDirection
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromSupportsLegacyVersionTwoMetadata()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readTraversalDirection → KILLED

1211

1.1
Location : readReductionSettings
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromParsesVersionThreeMetadata()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readReductionSettings → KILLED

1215

1.1
Location : readCaseProcessingMode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromParsesVersionFourCaseMetadata()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readCaseProcessingMode → KILLED

1221

1.1
Location : readEnumByOrdinal
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromSupportsLegacyVersionTwoMetadata()]
negated conditional → KILLED

2.2
Location : readEnumByOrdinal
Killed by : none
changed conditional boundary → SURVIVED
Covering tests

3.3
Location : readEnumByOrdinal
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromSupportsLegacyVersionTwoMetadata()]
changed conditional boundary → KILLED

4.4
Location : readEnumByOrdinal
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsInvalidLegacyMetadataOrdinal()]
negated conditional → KILLED

1224

1.1
Location : readEnumByOrdinal
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromSupportsLegacyVersionTwoMetadata()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readEnumByOrdinal → KILLED

1238

1.1
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
changed conditional boundary → KILLED

2.2
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
negated conditional → KILLED

1239

1.1
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
negated conditional → KILLED

2.2
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromSupportsInlineValuesInStreamVersionsFiveAndSix()]
changed conditional boundary → KILLED

1244

1.1
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
negated conditional → KILLED

2.2
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsNonPositiveStoredCounts()]
changed conditional boundary → KILLED

1251

1.1
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
negated conditional → KILLED

2.2
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
changed conditional boundary → KILLED

1256

1.1
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsNonAscendingSerializedEdgeLabels()]
removed call to org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::validateSerializedEdges → KILLED

1259

1.1
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
changed conditional boundary → KILLED

2.2
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
negated conditional → KILLED

1262

1.1
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
negated conditional → KILLED

2.2
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldPreserveUniformSubtreeContractionAcrossBinaryRoundTrip()]
negated conditional → KILLED

1265

1.1
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldPreserveUniformSubtreeContractionAcrossBinaryRoundTrip()]
negated conditional → KILLED

2.2
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
negated conditional → KILLED

1272

1.1
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
changed conditional boundary → KILLED

2.2
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
negated conditional → KILLED

1273

1.1
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsNonPositiveStoredCounts()]
negated conditional → KILLED

2.2
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:versionSevenReaderRejectsValueTableIndexGreaterThanSize()]
changed conditional boundary → KILLED

1275

1.1
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:versionSevenReaderRejectsValueTableIndexEqualToSize()]
changed conditional boundary → KILLED

2.2
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:versionSevenReaderRejectsTruncatedOccurrenceCount()]
changed conditional boundary → KILLED

3.3
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:versionSevenReaderRejectsValueTableIndexGreaterThanSize()]
negated conditional → KILLED

4.4
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:versionSevenReaderRejectsTruncatedOccurrenceCount()]
negated conditional → KILLED

1285

1.1
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsNonPositiveStoredCounts()]
negated conditional → KILLED

2.2
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsNonPositiveStoredCounts()]
changed conditional boundary → KILLED

1296

1.1
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromSupportsLegacyVersionTwoMetadata()]
changed conditional boundary → KILLED

2.2
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
negated conditional → KILLED

1301

1.1
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromSupportsLegacyVersionTwoMetadata()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readNodes → KILLED

1309

1.1
Location : resolveNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
negated conditional → KILLED

1310

1.1
Location : resolveNode
Killed by : org.egothor.stemmer.CompiledTrieArtifactRegressionTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.CompiledTrieArtifactRegressionTest]/[test-template:shouldLoadGoldenArtifactsDirectlyAsCompiledCommands(org.egothor.stemmer.CompiledTrieArtifactRegressionTest$ArtifactCase)]/[test-template-invocation:#3]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::resolveNode → KILLED

1313

1.1
Location : resolveNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromSupportsLegacyVersionTwoMetadata()]
negated conditional → KILLED

1325

1.1
Location : resolveNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
negated conditional → KILLED

2.2
Location : resolveNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromSupportsLegacyVersionTwoMetadata()]
changed conditional boundary → KILLED

1327

1.1
Location : resolveNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
negated conditional → KILLED

2.2
Location : resolveNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
changed conditional boundary → KILLED

3.3
Location : resolveNode
Killed by : none
changed conditional boundary → SURVIVED
Covering tests

4.4
Location : resolveNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
negated conditional → KILLED

1339

1.1
Location : resolveNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromSupportsLegacyVersionTwoMetadata()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::resolveNode → KILLED

1346

1.1
Location : validateSerializedEdges
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
changed conditional boundary → KILLED

2.2
Location : validateSerializedEdges
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
negated conditional → KILLED

1347

1.1
Location : validateSerializedEdges
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsNonAscendingSerializedEdgeLabels()]
negated conditional → KILLED

2.2
Location : validateSerializedEdges
Killed by : none
changed conditional boundary → SURVIVED
Covering tests

3.3
Location : validateSerializedEdges
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsNonAscendingSerializedEdgeLabels()]
Replaced integer subtraction with addition → KILLED

1348

1.1
Location : validateSerializedEdges
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsNonAscendingSerializedEdgeLabels()]
Replaced integer subtraction with addition → KILLED

1364

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:lookupKeepsCaseSensitiveBehaviorWhenMetadataIsAsIs()]
negated conditional → KILLED

1365

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:lookupKeepsCaseSensitiveBehaviorWhenMetadataIsAsIs()]
changed conditional boundary → KILLED

2.2
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyTrieReturnsNullEmptyArrayAndEmptyEntries()]
Replaced integer subtraction with addition → KILLED

3.3
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyKeyStoresValuesAtRootNode()]
negated conditional → KILLED

1366

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:lookupKeepsCaseSensitiveBehaviorWhenMetadataIsAsIs()]
negated conditional → KILLED

1367

1.1
Location : findNode
Killed by : org.egothor.stemmer.CompiledTrieArtifactRegressionTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.CompiledTrieArtifactRegressionTest]/[test-template:shouldPreserveRepresentativeSemanticProbes(org.egothor.stemmer.CompiledTrieArtifactRegressionTest$ArtifactCase)]/[test-template-invocation:#2]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → KILLED

1370

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyTrieReturnsNullEmptyArrayAndEmptyEntries()]
negated conditional → KILLED

1374

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyKeyStoresValuesAtRootNode()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → KILLED

1377

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldKeepExactLookupWhenUniformSubtreeContractionIsDisabled()]
negated conditional → KILLED

2.2
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldKeepExactLookupWhenUniformSubtreeContractionIsDisabled()]
changed conditional boundary → KILLED

1378

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldKeepExactLookupWhenUniformSubtreeContractionIsDisabled()]
negated conditional → KILLED

1379

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldContractUniformInternalSubtreeIntoAcceptingLeaf()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → KILLED

1382

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldKeepExactLookupWhenUniformSubtreeContractionIsDisabled()]
negated conditional → KILLED

1386

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldKeepExactLookupWhenUniformSubtreeContractionIsDisabled()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → KILLED

1397

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupMatchesGetAllOrderAndGetEntriesCounts()]
negated conditional → KILLED

1398

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupMatchesGetAllOrderAndGetEntriesCounts()]
changed conditional boundary → KILLED

2.2
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupMatchesGetAllOrderAndGetEntriesCounts()]
Replaced integer subtraction with addition → KILLED

3.3
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupMatchesGetAllOrderAndGetEntriesCounts()]
negated conditional → KILLED

1399

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupMatchesGetAllOrderAndGetEntriesCounts()]
negated conditional → KILLED

1400

1.1
Location : findNode
Killed by : none
replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → NO_COVERAGE

1403

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupMatchesGetAllOrderAndGetEntriesCounts()]
negated conditional → KILLED

1407

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupMatchesGetAllOrderAndGetEntriesCounts()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → KILLED

1410

1.1
Location : findNode
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : findNode
Killed by : none
changed conditional boundary → NO_COVERAGE

1411

1.1
Location : findNode
Killed by : none
negated conditional → NO_COVERAGE

1412

1.1
Location : findNode
Killed by : none
replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → NO_COVERAGE

1415

1.1
Location : findNode
Killed by : none
negated conditional → NO_COVERAGE

1419

1.1
Location : findNode
Killed by : none
replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → NO_COVERAGE

1432

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupSupportsCharSlicesAndMetadataAwareKeys()]
negated conditional → KILLED

1433

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupSupportsCharSlicesAndMetadataAwareKeys()]
Replaced integer subtraction with addition → KILLED

2.2
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupSupportsCharSlicesAndMetadataAwareKeys()]
Replaced integer addition with subtraction → KILLED

3.3
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupSupportsCharSlicesAndMetadataAwareKeys()]
negated conditional → KILLED

4.4
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupSupportsCharSlicesAndMetadataAwareKeys()]
changed conditional boundary → KILLED

1434

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupSupportsCharSlicesAndMetadataAwareKeys()]
negated conditional → KILLED

1435

1.1
Location : findNode
Killed by : none
replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → NO_COVERAGE

1438

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupSupportsCharSlicesAndMetadataAwareKeys()]
negated conditional → KILLED

1442

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupSupportsCharSlicesAndMetadataAwareKeys()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → KILLED

1445

1.1
Location : findNode
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

1446

1.1
Location : findNode
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : findNode
Killed by : none
changed conditional boundary → NO_COVERAGE

1447

1.1
Location : findNode
Killed by : none
negated conditional → NO_COVERAGE

1448

1.1
Location : findNode
Killed by : none
replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → NO_COVERAGE

1451

1.1
Location : findNode
Killed by : none
negated conditional → NO_COVERAGE

1455

1.1
Location : findNode
Killed by : none
replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → NO_COVERAGE

1467

1.1
Location : visitNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupMatchesGetAllOrderAndGetEntriesCounts()]
negated conditional → KILLED

1473

1.1
Location : visitNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupMatchesGetAllOrderAndGetEntriesCounts()]
negated conditional → KILLED

1479

1.1
Location : visitNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupMatchesGetAllOrderAndGetEntriesCounts()]
changed conditional boundary → KILLED

2.2
Location : visitNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupMatchesGetAllOrderAndGetEntriesCounts()]
negated conditional → KILLED

1480

1.1
Location : visitNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupMatchesGetAllOrderAndGetEntriesCounts()]
Changed increment from 1 to -1 → KILLED

1481

1.1
Location : visitNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupMatchesGetAllOrderAndGetEntriesCounts()]
negated conditional → KILLED

1485

1.1
Location : visitNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupMatchesGetAllOrderAndGetEntriesCounts()]
replaced int return with 0 for org/egothor/stemmer/FrequencyTrie::visitNode → KILLED

1494

1.1
Location : validateMaxResults
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupRejectsNullAndInvalidRangeArguments()]
negated conditional → KILLED

2.2
Location : validateMaxResults
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupHandlesBoundaryCases()]
changed conditional boundary → KILLED

1506

1.1
Location : normalizeLookupKey
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:lookupKeepsCaseSensitiveBehaviorWhenMetadataIsAsIs()]
replaced return value with "" for org/egothor/stemmer/FrequencyTrie::normalizeLookupKey → KILLED

1516

1.1
Location : normalizeLookupKey
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:lookupAppliesLowercaseNormalizationWhenMetadataRequiresIt()]
negated conditional → KILLED

2.2
Location : normalizeLookupKey
Killed by : none
negated conditional → SURVIVED
Covering tests

1517

1.1
Location : normalizeLookupKey
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:lookupKeepsCaseSensitiveBehaviorWhenMetadataIsAsIs()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::normalizeLookupKey → KILLED

1521

1.1
Location : normalizeLookupKey
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:lookupAppliesLowercaseNormalizationWhenMetadataRequiresIt()]
negated conditional → KILLED

1524

1.1
Location : normalizeLookupKey
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:diacriticRemoveModeStripsDictionaryAndLookupKeys()]
negated conditional → KILLED

1526

1.1
Location : normalizeLookupKey
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyTrieReturnsNullEmptyArrayAndEmptyEntries()]
negated conditional → KILLED

1531

1.1
Location : normalizeLookupKey
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyTrieReturnsNullEmptyArrayAndEmptyEntries()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::normalizeLookupKey → KILLED

1683

1.1
Location : <init>
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:fallbackDiacriticModeIsNotSupportedYet()]
negated conditional → KILLED

2.2
Location : <init>
Killed by : none
changed conditional boundary → SURVIVED
Covering tests

1735

1.1
Location : put
Killed by : none
replaced return value with null for org/egothor/stemmer/FrequencyTrie$Builder::put → SURVIVED
Covering tests

1760

1.1
Location : build
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupRejectsNullAndInvalidRangeArguments()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$Builder::build → KILLED

1790

1.1
Location : put
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:fallbackDiacriticModeIsNotSupportedYet()]
changed conditional boundary → KILLED

2.2
Location : put
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:fallbackDiacriticModeIsNotSupportedYet()]
negated conditional → KILLED

1797

1.1
Location : put
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyKeyStoresValuesAtRootNode()]
changed conditional boundary → KILLED

2.2
Location : put
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyKeyStoresValuesAtRootNode()]
negated conditional → KILLED

1801

1.1
Location : put
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:missingPathBelowExistingPrefixReturnsEmptyResults()]
negated conditional → KILLED

1809

1.1
Location : put
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyKeyStoresValuesAtRootNode()]
negated conditional → KILLED

1812

1.1
Location : put
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyKeyStoresValuesAtRootNode()]
Replaced integer addition with subtraction → KILLED

1814

1.1
Location : put
Killed by : none
replaced return value with null for org/egothor/stemmer/FrequencyTrie$Builder::put → SURVIVED
Covering tests

1827

1.1
Location : normalizeDictionaryKey
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:lookupKeepsCaseSensitiveBehaviorWhenMetadataIsAsIs()]
negated conditional → KILLED

1831

1.1
Location : normalizeDictionaryKey
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:fallbackDiacriticModeIsNotSupportedYet()]
negated conditional → KILLED

1833

1.1
Location : normalizeDictionaryKey
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:fallbackDiacriticModeIsNotSupportedYet()]
negated conditional → KILLED

1838

1.1
Location : normalizeDictionaryKey
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:lookupKeepsCaseSensitiveBehaviorWhenMetadataIsAsIs()]
replaced return value with "" for org/egothor/stemmer/FrequencyTrie$Builder::normalizeDictionaryKey → KILLED

1852

1.1
Location : buildTimeSize
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:reductionMateriallyDecreasesCompiledTrieSizeForRepeatedEquivalentSuffixes()]
replaced int return with 0 for org/egothor/stemmer/FrequencyTrie$Builder::buildTimeSize → KILLED

1861

1.1
Location : traversalDirection
Killed by : none
replaced return value with null for org/egothor/stemmer/FrequencyTrie$Builder::traversalDirection → NO_COVERAGE

1873

1.1
Location : countMutableNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:reductionMateriallyDecreasesCompiledTrieSizeForRepeatedEquivalentSuffixes()]
Replaced integer addition with subtraction → KILLED

1875

1.1
Location : countMutableNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:reductionMateriallyDecreasesCompiledTrieSizeForRepeatedEquivalentSuffixes()]
replaced int return with 0 for org/egothor/stemmer/FrequencyTrie$Builder::countMutableNodes → KILLED

1895

1.1
Location : reduce
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:lookupKeepsCaseSensitiveBehaviorWhenMetadataIsAsIs()]
negated conditional → KILLED

1897

1.1
Location : reduce
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldContractUniformInternalSubtreeIntoAcceptingLeaf()]
negated conditional → KILLED

1909

1.1
Location : reduce
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:trieRejectsNullLookupKeys()]
negated conditional → KILLED

1911

1.1
Location : reduce
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:unorderedReductionMergesNodesWithSameGetAllValueSet()]
removed call to org/egothor/stemmer/trie/ReductionContext::register → KILLED

1912

1.1
Location : reduce
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:trieRejectsNullLookupKeys()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$Builder::reduce → KILLED

1915

1.1
Location : reduce
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:dominantReductionMergesQualifiedDominantWinnerNodes()]
removed call to org/egothor/stemmer/trie/ReducedNode::mergeLocalCounts → KILLED

1916

1.1
Location : reduce
Killed by : none
removed call to org/egothor/stemmer/trie/ReducedNode::mergeChildren → SURVIVED
Covering tests

1918

1.1
Location : reduce
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:reductionTakesInternalNodeLocalValuesIntoAccount()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$Builder::reduce → KILLED

1932

1.1
Location : contractUniformSubtree
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldContractUniformInternalSubtreeIntoAcceptingLeaf()]
negated conditional → KILLED

1939

1.1
Location : contractUniformSubtree
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldContractUniformInternalSubtreeIntoAcceptingLeaf()]
negated conditional → KILLED

1940

1.1
Location : contractUniformSubtree
Killed by : none
negated conditional → SURVIVED
Covering tests

1949

1.1
Location : contractUniformSubtree
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldContractUniformInternalSubtreeIntoAcceptingLeaf()]
negated conditional → KILLED

1953

1.1
Location : contractUniformSubtree
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldContractUniformInternalSubtreeIntoAcceptingLeaf()]
negated conditional → KILLED

2.2
Location : contractUniformSubtree
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldContractUniformInternalSubtreeIntoAcceptingLeaf()]
negated conditional → KILLED

1960

1.1
Location : contractUniformSubtree
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldContractUniformInternalSubtreeIntoAcceptingLeaf()]
negated conditional → KILLED

1966

1.1
Location : contractUniformSubtree
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldContractUniformInternalSubtreeIntoAcceptingLeaf()]
replaced return value with Collections.emptyMap for org/egothor/stemmer/FrequencyTrie$Builder::contractUniformSubtree → KILLED

1976

1.1
Location : isSingleValueLeaf
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldContractUniformInternalSubtreeIntoAcceptingLeaf()]
negated conditional → KILLED

2.2
Location : isSingleValueLeaf
Killed by : org.egothor.stemmer.CompileTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.CompileTest]/[method:shouldFailWithProcessingErrorWhenOutputExistsAndOverwriteIsNotEnabled()]
replaced boolean return with true for org/egothor/stemmer/FrequencyTrie$Builder::isSingleValueLeaf → KILLED

3.3
Location : isSingleValueLeaf
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldContractUniformInternalSubtreeIntoAcceptingLeaf()]
negated conditional → KILLED

1989

1.1
Location : freeze
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:trieRejectsNullLookupKeys()]
negated conditional → KILLED

1990

1.1
Location : freeze
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:reductionTakesInternalNodeLocalValuesIntoAccount()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$Builder::freeze → KILLED

1998

1.1
Location : freeze
Killed by : org.egothor.stemmer.FrequencyTrieBuildersTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieBuildersTest]/[method:shouldAllowFurtherModificationsWithoutAffectingSourceTrie()]
removed call to java/util/List::sort → KILLED

2004

1.1
Location : freeze
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:trieRejectsNullLookupKeys()]
changed conditional boundary → KILLED

2.2
Location : freeze
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:trieRejectsNullLookupKeys()]
negated conditional → KILLED

2013

1.1
Location : freeze
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:trieRejectsNullLookupKeys()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$Builder::freeze → KILLED

2024

1.1
Location : copyCounts
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyKeyStoresValuesAtRootNode()]
replaced return value with Collections.emptyMap for org/egothor/stemmer/FrequencyTrie$Builder::copyCounts → KILLED

Active mutators

Tests examined


Report generated by PIT 1.22.1