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

leeonky / test-charm-java / 323

30 Sep 2025 05:15PM UTC coverage: 74.637% (+0.1%) from 74.512%
323

push

circleci

leeonky
Use descendantForRead in consistent provider

16 of 17 new or added lines in 4 files covered. (94.12%)

29 existing lines in 7 files now uncovered.

8531 of 11430 relevant lines covered (74.64%)

0.75 hits per line

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

87.69
/jfactory/src/main/java/com/github/leeonky/jfactory/ConsistencyItem.java
1
package com.github.leeonky.jfactory;
2

3
import java.util.*;
4

5
import static java.util.stream.Collectors.joining;
6
import static java.util.stream.Collectors.toList;
7

8
class ConsistencyItem<T> {
9
    private final Set<PropertyChain> properties;
10
    private final Consistency<T> consistency;
11
    private final StackTraceElement location;
12
    private StackTraceElement composerLocation;
13
    private StackTraceElement decomposerLocation;
14
    private DefaultConsistency.Composer<T> composer;
15
    private DefaultConsistency.Decomposer<T> decomposer;
16

17
    ConsistencyItem(Collection<PropertyChain> properties, Consistency<T> consistency) {
18
        this(properties, consistency, guessCustomerPositionStackTrace());
1✔
19
    }
1✔
20

21
    ConsistencyItem(Collection<PropertyChain> properties, Consistency<T> consistency, StackTraceElement location) {
1✔
22
        this.properties = new LinkedHashSet<>(properties);
1✔
23
        this.consistency = consistency;
1✔
24
        this.location = location;
1✔
25
    }
1✔
26

27
    static StackTraceElement guessCustomerPositionStackTrace() {
28
        StackTraceElement[] stackTrace = new Throwable().getStackTrace();
1✔
29
        return Arrays.stream(stackTrace).filter(s -> !s.getClassName().startsWith("com.github.leeonky.jfactory"))
1✔
30
                .findFirst().orElse(stackTrace[0]);
1✔
31
    }
32

33
    private static boolean isSame(DefaultConsistency.Identity identity1, DefaultConsistency.Identity identity2) {
34
        return identity1 != null && identity2 != null && identity1.same(identity2);
1✔
35
    }
36

37
    private static boolean isBothNull(DefaultConsistency.Identity identity1, DefaultConsistency.Identity identity2) {
38
        return identity1 == null && identity2 == null;
1✔
39
    }
40

41
    void setComposer(DefaultConsistency.Composer<T> composer) {
42
        this.composer = composer;
1✔
43
        composerLocation = composer.getLocation();
1✔
44
    }
1✔
45

46
    void setDecomposer(DefaultConsistency.Decomposer<T> decomposer) {
47
        this.decomposer = decomposer;
1✔
48
        decomposerLocation = decomposer.getLocation();
1✔
49
    }
1✔
50

51
    boolean same(ConsistencyItem<?> another) {
52
        return properties.equals(another.properties) &&
1✔
53
                (isSame(composer, another.composer) && isSame(decomposer, another.decomposer)
1✔
54
                        || isBothNull(composer, another.composer) && isSame(decomposer, another.decomposer)
1✔
55
                        || isSame(composer, another.composer) && isBothNull(decomposer, another.decomposer));
1✔
56
    }
57

58
    private String getPosition() {
59
        return location.getClassName() + "." + location.getMethodName() +
×
UNCOV
60
                "(" + location.getFileName() + ":" + location.getLineNumber() + ")";
×
61
    }
62

63
    private String composerLocation() {
64
        return composerLocation == null ? "null" :
×
UNCOV
65
                "(" + composerLocation.getFileName() + ":" + composerLocation.getLineNumber() + ")";
×
66
    }
67

68
    private String decomposerLocation() {
UNCOV
69
        return decomposerLocation == null ? "null" :
×
UNCOV
70
                "(" + decomposerLocation.getFileName() + ":" + decomposerLocation.getLineNumber() + ")";
×
71
    }
72

73
    public ConsistencyItem<T> absoluteProperty(PropertyChain base) {
74
        ConsistencyItem<T> absolute = new ConsistencyItem<>(properties.stream().map(base::concat).collect(toList()), consistency, location);
1✔
75
        absolute.decomposer = decomposer;
1✔
76
        absolute.composer = composer;
1✔
77
        absolute.decomposerLocation = decomposerLocation;
1✔
78
        absolute.composerLocation = composerLocation;
1✔
79
        return absolute;
1✔
80
    }
81

82
    @Override
83
    public String toString() {
UNCOV
84
        return properties.stream().map(Objects::toString).collect(joining(", ")) +
×
UNCOV
85
                " => " + consistency.type().getName() +
×
86
                (composer != null ? " with composer" : "") +
87
                (decomposer != null ? " with decomposer" : "");
88
    }
89

90
    Resolver resolver(ObjectProducer<?> root, DefaultConsistency<T>.Resolver consistency) {
91
        return new Resolver(root, consistency);
1✔
92
    }
93

94
    class Resolver {
95
        private final ObjectProducer<?> root;
96
        private final DefaultConsistency<T>.Resolver consistency;
97
        private Object[] cached;
98

99
        Resolver(ObjectProducer<?> root, DefaultConsistency<T>.Resolver consistency) {
1✔
100
            this.root = root;
1✔
101
            this.consistency = consistency;
1✔
102
        }
1✔
103

104
        boolean hasTypeOf(Class<?> type) {
105
            return properties.stream().map(root::descendantForRead).anyMatch(type::isInstance);
1✔
106
        }
107

108
        Set<PropertyChain> resolveAsProvider() {
109
            if (hasTypeOf(PlaceHolderProducer.class))
1✔
110
                return Collections.emptySet();
1✔
111
            return consistency.resolve(this);
1✔
112
        }
113

114
        private T compose() {
115
            return composer.apply(properties.stream().map(root::descendantForRead).map(Producer::getValue).toArray());
1✔
116
        }
117

118
        Object[] decompose(Resolver provider) {
119
            if (cached == null)
1✔
120
                cached = decomposer.apply(provider.compose());
1✔
121
            return cached;
1✔
122
        }
123

124
        boolean hasComposer() {
125
            return composer != null;
1✔
126
        }
127

128
        boolean hasDecomposer() {
129
            return decomposer != null;
1✔
130
        }
131

132
        Set<PropertyChain> resolve(Resolver provider) {
133
            int i = 0;
1✔
134
            for (PropertyChain property : properties) {
1✔
135
                int index = i++;
1✔
136
                root.changeDescendant(property, (producer, s) ->
1✔
137
                        new ConsistencyProducer<>(root.descendantForUpdate(property), provider, this, index));
1✔
138
            }
1✔
139
            return properties;
1✔
140
        }
141

142
        @Override
143
        public int hashCode() {
144
            return Objects.hash(properties, composer == null ? null : composer.identity(),
1✔
145
                    decomposer == null ? null : decomposer.identity());
1✔
146
        }
147

148
        private ConsistencyItem<T> outer() {
149
            return ConsistencyItem.this;
1✔
150
        }
151

152
        @Override
153
        @SuppressWarnings("unchecked")
154
        public boolean equals(Object o) {
155
            return o instanceof ConsistencyItem.Resolver && same(((Resolver) o).outer());
1✔
156
        }
157

158
        boolean hasFixed() {
159
            return properties.stream().map(root::descendantForRead).anyMatch(Producer::isFixed);
1✔
160
        }
161

162
        boolean containsProperty(PropertyChain property) {
163
            return properties.contains(property);
1✔
164
        }
165

166
        DefaultConsistency<T>.Resolver consistencyResolver() {
167
            return consistency;
1✔
168
        }
169
    }
170
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc