AuditChange.java

1
package com.rbctcsworld.ecommerce.audit;
2
3
import java.math.BigDecimal;
4
import java.util.ArrayList;
5
import java.util.LinkedHashMap;
6
import java.util.List;
7
import java.util.Map;
8
import java.util.Objects;
9
10
/** One changed field of one record: what the audit trail stores per row. */
11
public record AuditChange(String entityType, long entityId, String action, String field, String oldValue,
12
                          String newValue) {
13
14
    public static final String PRODUCT = "PRODUCT";
15
    public static final String ORDER = "ORDER";
16
    public static final String CUSTOMER = "CUSTOMER";
17
    public static final String COUPON = "COUPON";
18
    public static final String WAREHOUSE = "WAREHOUSE";
19
    public static final int MAX_VALUE = 500;
20
21
    /**
22
     * The fields whose value differs between before and after, in the order of {@code after}.
23
     * {@code before} = null means the record was created (every field with a value is listed).
24
     * Numbers are compared by value: 12.5 and 12.50 are the same price.
25
     */
26
    public static List<AuditChange> diff(String entityType, long entityId, String action,
27
                                         Map<String, Object> before, Map<String, Object> after) {
28
        List<AuditChange> changes = new ArrayList<>();
29
        for (Map.Entry<String, Object> e : after.entrySet()) {
30 1 1. diff : removed conditional - replaced equality check with false → KILLED
            Object old = before == null ? null : before.get(e.getKey());
31 1 1. diff : removed conditional - replaced equality check with false → KILLED
            if (!same(old, e.getValue())) {
32
                changes.add(new AuditChange(entityType, entityId, action, e.getKey(), text(old), text(e.getValue())));
33
            }
34
        }
35 1 1. diff : replaced return value with Collections.emptyList for com/rbctcsworld/ecommerce/audit/AuditChange::diff → KILLED
        return changes;
36
    }
37
38
    /** Convenience for building the before/after maps in field order. */
39
    public static Map<String, Object> fields(Object... namesAndValues) {
40
        Map<String, Object> m = new LinkedHashMap<>();
41 2 1. fields : removed conditional - replaced comparison check with false → KILLED
2. fields : changed conditional boundary → KILLED
        for (int i = 0; i < namesAndValues.length; i += 2) {
42 1 1. fields : Replaced integer addition with subtraction → KILLED
            m.put((String) namesAndValues[i], namesAndValues[i + 1]);
43
        }
44 1 1. fields : replaced return value with Collections.emptyMap for com/rbctcsworld/ecommerce/audit/AuditChange::fields → KILLED
        return m;
45
    }
46
47
    static boolean same(Object a, Object b) {
48 2 1. same : removed conditional - replaced equality check with false → KILLED
2. same : removed conditional - replaced equality check with false → KILLED
        if (a instanceof BigDecimal x && b instanceof BigDecimal y) {
49 2 1. same : replaced boolean return with true for com/rbctcsworld/ecommerce/audit/AuditChange::same → KILLED
2. same : removed conditional - replaced equality check with false → KILLED
            return x.compareTo(y) == 0;
50
        }
51 2 1. same : replaced boolean return with true for com/rbctcsworld/ecommerce/audit/AuditChange::same → KILLED
2. same : replaced boolean return with false for com/rbctcsworld/ecommerce/audit/AuditChange::same → KILLED
        return Objects.equals(a, b);
52
    }
53
54
    /** As stored: plain text, BigDecimal without exponent, at most MAX_VALUE characters, null stays null. */
55
    static String text(Object value) {
56 2 1. text : replaced return value with "" for com/rbctcsworld/ecommerce/audit/AuditChange::text → KILLED
2. text : removed conditional - replaced equality check with false → KILLED
        if (value == null) return null;
57 1 1. text : removed conditional - replaced equality check with false → KILLED
        String s = value instanceof BigDecimal d ? d.toPlainString() : String.valueOf(value);
58 3 1. text : changed conditional boundary → SURVIVED
2. text : replaced return value with "" for com/rbctcsworld/ecommerce/audit/AuditChange::text → KILLED
3. text : removed conditional - replaced comparison check with false → KILLED
        return s.length() > MAX_VALUE ? s.substring(0, MAX_VALUE) : s;
59
    }
60
}

Mutations

30

1.1
Location : diff
Killed by : com.rbctcsworld.ecommerce.audit.AuditChangeTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.audit.AuditChangeTest]/[method:aCreatedRecordListsEveryFieldThatHasAValue()]
removed conditional - replaced equality check with false → KILLED

31

1.1
Location : diff
Killed by : com.rbctcsworld.ecommerce.audit.AuditChangeTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.audit.AuditChangeTest]/[method:aCreatedRecordListsEveryFieldThatHasAValue()]
removed conditional - replaced equality check with false → KILLED

35

1.1
Location : diff
Killed by : com.rbctcsworld.ecommerce.audit.AuditChangeTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.audit.AuditChangeTest]/[method:aCreatedRecordListsEveryFieldThatHasAValue()]
replaced return value with Collections.emptyList for com/rbctcsworld/ecommerce/audit/AuditChange::diff → KILLED

41

1.1
Location : fields
Killed by : com.rbctcsworld.ecommerce.audit.AuditChangeTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.audit.AuditChangeTest]/[method:fieldsKeepsTheGivenOrder()]
removed conditional - replaced comparison check with false → KILLED

2.2
Location : fields
Killed by : com.rbctcsworld.ecommerce.audit.AuditChangeTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.audit.AuditChangeTest]/[method:fieldsKeepsTheGivenOrder()]
changed conditional boundary → KILLED

42

1.1
Location : fields
Killed by : com.rbctcsworld.ecommerce.audit.AuditChangeTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.audit.AuditChangeTest]/[method:fieldsKeepsTheGivenOrder()]
Replaced integer addition with subtraction → KILLED

44

1.1
Location : fields
Killed by : com.rbctcsworld.ecommerce.audit.AuditChangeTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.audit.AuditChangeTest]/[method:fieldsKeepsTheGivenOrder()]
replaced return value with Collections.emptyMap for com/rbctcsworld/ecommerce/audit/AuditChange::fields → KILLED

48

1.1
Location : same
Killed by : com.rbctcsworld.ecommerce.audit.AuditChangeTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.audit.AuditChangeTest]/[method:theSamePriceWrittenDifferentlyIsNoChange()]
removed conditional - replaced equality check with false → KILLED

2.2
Location : same
Killed by : com.rbctcsworld.ecommerce.audit.AuditChangeTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.audit.AuditChangeTest]/[method:theSamePriceWrittenDifferentlyIsNoChange()]
removed conditional - replaced equality check with false → KILLED

49

1.1
Location : same
Killed by : com.rbctcsworld.ecommerce.audit.AuditChangeTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.audit.AuditChangeTest]/[method:theSamePriceWrittenDifferentlyIsNoChange()]
replaced boolean return with true for com/rbctcsworld/ecommerce/audit/AuditChange::same → KILLED

2.2
Location : same
Killed by : com.rbctcsworld.ecommerce.audit.AuditChangeTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.audit.AuditChangeTest]/[method:theSamePriceWrittenDifferentlyIsNoChange()]
removed conditional - replaced equality check with false → KILLED

51

1.1
Location : same
Killed by : com.rbctcsworld.ecommerce.audit.AuditChangeTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.audit.AuditChangeTest]/[method:theSamePriceWrittenDifferentlyIsNoChange()]
replaced boolean return with true for com/rbctcsworld/ecommerce/audit/AuditChange::same → KILLED

2.2
Location : same
Killed by : com.rbctcsworld.ecommerce.audit.AuditChangeTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.audit.AuditChangeTest]/[method:theSamePriceWrittenDifferentlyIsNoChange()]
replaced boolean return with false for com/rbctcsworld/ecommerce/audit/AuditChange::same → KILLED

56

1.1
Location : text
Killed by : com.rbctcsworld.ecommerce.audit.AuditChangeTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.audit.AuditChangeTest]/[method:valuesAreStoredAsPlainTextOfAtMostFiveHundredCharacters()]
replaced return value with "" for com/rbctcsworld/ecommerce/audit/AuditChange::text → KILLED

2.2
Location : text
Killed by : com.rbctcsworld.ecommerce.audit.AuditChangeTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.audit.AuditChangeTest]/[method:valuesAreStoredAsPlainTextOfAtMostFiveHundredCharacters()]
removed conditional - replaced equality check with false → KILLED

57

1.1
Location : text
Killed by : com.rbctcsworld.ecommerce.audit.AuditChangeTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.audit.AuditChangeTest]/[method:valuesAreStoredAsPlainTextOfAtMostFiveHundredCharacters()]
removed conditional - replaced equality check with false → KILLED

58

1.1
Location : text
Killed by : com.rbctcsworld.ecommerce.audit.AuditChangeTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.audit.AuditChangeTest]/[method:valuesAreStoredAsPlainTextOfAtMostFiveHundredCharacters()]
replaced return value with "" for com/rbctcsworld/ecommerce/audit/AuditChange::text → KILLED

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

3.3
Location : text
Killed by : com.rbctcsworld.ecommerce.audit.AuditChangeTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.audit.AuditChangeTest]/[method:valuesAreStoredAsPlainTextOfAtMostFiveHundredCharacters()]
removed conditional - replaced comparison check with false → KILLED

Active mutators

Tests examined


Report generated by PIT 1.30.0 support