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

leeonky / test-charm-java / 335

04 Oct 2025 03:47PM UTC coverage: 74.611% (-0.04%) from 74.653%
335

push

circleci

leeonky
Process list and list consistency

40 of 42 new or added lines in 3 files covered. (95.24%)

29 existing lines in 4 files now uncovered.

8590 of 11513 relevant lines covered (74.61%)

0.75 hits per line

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

88.98
/jfactory/src/main/java/com/github/leeonky/jfactory/DefaultConsistency.java
1
package com.github.leeonky.jfactory;
2

3
import com.github.leeonky.util.BeanClass;
4
import com.github.leeonky.util.Sneaky;
5

6
import java.util.*;
7
import java.util.function.Function;
8
import java.util.function.Predicate;
9

10
import static com.github.leeonky.jfactory.ConsistencyItem.guessCustomerPositionStackTrace;
11
import static com.github.leeonky.jfactory.PropertyChain.propertyChain;
12
import static java.util.Arrays.asList;
13
import static java.util.Collections.singletonList;
14
import static java.util.stream.Collectors.toCollection;
15
import static java.util.stream.Collectors.toList;
16

17
class DefaultConsistency<T> implements Consistency<T> {
18
    final List<ConsistencyItem<T>> items = new ArrayList<>();
1✔
19
    final List<DefaultListConsistency<T>> list = new ArrayList<>();
1✔
20
    private final BeanClass<T> type;
21
    final List<StackTraceElement> locations = new ArrayList<>();
1✔
22

23
    static final Function<Object, Object> LINK_COMPOSER = s -> s;
1✔
24
    static final Function<Object, Object> LINK_DECOMPOSER = s -> s;
1✔
25

26
    DefaultConsistency(Class<T> type) {
27
        this(BeanClass.create(type));
1✔
28
    }
1✔
29

30
    DefaultConsistency(BeanClass<T> type) {
31
        this(type, singletonList(guessCustomerPositionStackTrace()));
1✔
32
    }
1✔
33

34
    DefaultConsistency(BeanClass<T> type, List<StackTraceElement> locations) {
1✔
35
        this.type = type;
1✔
36
        this.locations.addAll(locations);
1✔
37
    }
1✔
38

39
    @Override
40
    public BeanClass<T> type() {
41
        return type;
1✔
42
    }
43

44
    @Override
45
    @SuppressWarnings("unchecked")
46
    public Consistency<T> direct(String property) {
47
        return property(property).read((Function<Object, T>) LINK_COMPOSER).write((Function<T, Object>) LINK_DECOMPOSER);
1✔
48
    }
49

50
    @Override
51
    public <P> C1<T, P> property(String property) {
52
        ConsistencyItem<T> item = new ConsistencyItem<>(singletonList(propertyChain(property)), this);
1✔
53
        items.add(item);
1✔
54
        return new C1<>(this, item);
1✔
55
    }
56

57
    @Override
58
    public <P1, P2> C2<T, P1, P2> properties(String property1, String property2) {
59
        ConsistencyItem<T> item = new ConsistencyItem<>(asList(propertyChain(property1), propertyChain(property2)), this);
1✔
60
        items.add(item);
1✔
61
        return new C2<>(this, item);
1✔
62
    }
63

64
    @Override
65
    public <P1, P2, P3> C3<T, P1, P2, P3> properties(String property1, String property2, String property3) {
66
        ConsistencyItem<T> item = new ConsistencyItem<>(asList(propertyChain(property1), propertyChain(property2), propertyChain(property3)), this);
1✔
67
        items.add(item);
1✔
68
        return new C3<>(this, item);
1✔
69
    }
70

71
    @Override
72
    public CN<T> properties(String... properties) {
73
        ConsistencyItem<T> item = new ConsistencyItem<>(Arrays.stream(properties).map(PropertyChain::propertyChain).collect(toList()), this);
1✔
74
        items.add(item);
1✔
75
        return new CN<>(this, item);
1✔
76
    }
77

78
    boolean merge(DefaultConsistency<?> another) {
79
        if (items.stream().anyMatch(item -> another.items.stream().anyMatch(item::same))) {
1✔
80
            another.items.forEach(item -> items.add(Sneaky.cast(item)));
1✔
81
            return true;
1✔
82
        }
83
        return false;
1✔
84
    }
85

86
    String info() {
87
        StringBuilder builder = new StringBuilder();
×
88
        builder.append("  ").append(type().getName()).append(":");
×
89
        for (StackTraceElement location : locations) {
×
90
            builder.append("\n    ").append(location.getClassName()).append(".").append(location.getMethodName())
×
91
                    .append("(").append(location.getFileName()).append(":").append(location.getLineNumber()).append(")");
×
92
        }
×
93
        return builder.toString();
×
94
    }
95

96
    DefaultConsistency<T> absoluteProperty(PropertyChain base) {
97
        DefaultConsistency<T> absolute = new DefaultConsistency<>(type(), locations);
1✔
98
        items.forEach(item -> absolute.items.add(item.absoluteProperty(base)));
1✔
99
        return absolute;
1✔
100
    }
101

102
    Resolver resolver(ObjectProducer<?> root) {
103
        return new Resolver(root);
1✔
104
    }
105

106
    @Override
107
    public ListConsistencyBuilder<T> list(String property) {
108
        DefaultListConsistency<T> listConsistency = new DefaultListConsistency<>(singletonList(property), this);
1✔
109
        list.add(listConsistency);
1✔
110
        return new ListConsistencyBuilder<>(this, listConsistency);
1✔
111
    }
112

113
    @Override
114
    public ListConsistencyBuilder<T> list(String property1, String property2) {
115
        DefaultListConsistency<T> listConsistency = new DefaultListConsistency<>(asList(property1, property2), this);
1✔
116
        list.add(listConsistency);
1✔
117
        return new ListConsistencyBuilder<>(this, listConsistency);
1✔
118
    }
119

120
    @Deprecated
121
    DefaultConsistency<T> processListConsistency(ObjectProducer<?> producer) {
UNCOV
122
        list.forEach(listConsistency -> listConsistency.populateConsistencies(producer, propertyChain("")));
×
UNCOV
123
        return this;
×
124
    }
125

126

127
    public List<DefaultConsistency<T>> populateListConsistencies(ObjectProducer<?> producer) {
128
        if (list.isEmpty())
1✔
129
            return singletonList(this);
1✔
130
        List<DefaultConsistency<T>> consistencies = new ArrayList<>();
1✔
131
        for (DefaultListConsistency<T> indexSource : list) {
1✔
132
            consistencies.addAll(indexSource.collectCoordinateAndProcess(producer, new ArrayList<>(), 0, propertyChain("")));
1✔
133
        }
1✔
134
        return consistencies;
1✔
135
    }
136

137
    DefaultConsistency<T> populateConsistencyWithList(Coordinate coordinate) {
138
        DefaultConsistency<T> newConsistency = new DefaultConsistency<>(type(), locations);
1✔
139
        for (DefaultListConsistency<T> listConsistency : list) {
1✔
140
            PropertyChain elementProperty = listConsistency.toProperty(coordinate);
1✔
141
            for (ListConsistencyItem<T> item : listConsistency.items) {
1✔
142
                item.populateConsistency(elementProperty, newConsistency);
1✔
143
            }
1✔
144
        }
1✔
145
        for (ConsistencyItem<T> item : items) {
1✔
146
            newConsistency.items.add(item.copy(newConsistency));
1✔
147
        }
1✔
148
        return newConsistency;
1✔
149
    }
150

151
    interface Identity {
152
        default Object identity() {
UNCOV
153
            return this;
×
154
        }
155

156
        default boolean same(Identity another) {
157
            return another != null && identity() == another.identity();
1✔
158
        }
159

160
        StackTraceElement getLocation();
161
    }
162

163
    interface Composer<T> extends Function<Object[], T>, Identity {
164
    }
165

166
    interface Decomposer<T> extends Function<T, Object[]>, Identity {
167
    }
168

169
    class Resolver {
170
        private final Set<ConsistencyItem<T>.Resolver> providers;
171
        private final Set<ConsistencyItem<T>.Resolver> consumers;
172

173
        Resolver(ObjectProducer<?> root) {
1✔
174
            List<ConsistencyItem<T>.Resolver> itemResolvers = items.stream().map(i -> i.resolver(root, this)).collect(toList());
1✔
175
            providers = itemResolvers.stream().filter(ConsistencyItem.Resolver::hasComposer).collect(toCollection(LinkedHashSet::new));
1✔
176
            consumers = itemResolvers.stream().filter(ConsistencyItem.Resolver::hasDecomposer).collect(toCollection(LinkedHashSet::new));
1✔
177
        }
1✔
178

179
        Set<PropertyChain> resolve(ConsistencyItem<T>.Resolver provider) {
180
            Set<PropertyChain> resolved = new HashSet<>();
1✔
181
            for (ConsistencyItem<T>.Resolver consumer : consumers)
1✔
182
                if (consumer != provider)
1✔
183
                    resolved.addAll(consumer.resolve(provider));
1✔
184
            return resolved;
1✔
185
        }
186

187
        Optional<ConsistencyItem<T>.Resolver> searchProvider(Predicate<ConsistencyItem<?>.Resolver> condition) {
188
            return providers.stream().filter(condition).min(this::onlyComposerFirstOrder);
1✔
189
        }
190

191
        ConsistencyItem<T>.Resolver defaultProvider() {
192
            return providers.stream().min(this::onlyComposerFirstOrder).get();
1✔
193
        }
194

195
        private int onlyComposerFirstOrder(ConsistencyItem<T>.Resolver r1, ConsistencyItem<T>.Resolver r2) {
196
            if (!r1.hasDecomposer())
1✔
197
                return -1;
1✔
198
            return !r2.hasDecomposer() ? 1 : 0;
1✔
199
        }
200

201
        Optional<ConsistencyItem<T>.Resolver> propertyRelated(PropertyChain property) {
202
            return providers.stream().filter(p -> p.containsProperty(property)).findFirst();
1✔
203
        }
204
    }
205
}
206

207
class DecorateConsistency<T> implements Consistency<T> {
208
    private final Consistency<T> delegate;
209

210
    DecorateConsistency(Consistency<T> delegate) {
1✔
211
        this.delegate = delegate;
1✔
212
    }
1✔
213

214
    @Override
215
    public BeanClass<T> type() {
UNCOV
216
        return delegate.type();
×
217
    }
218

219
    @Override
220
    public Consistency<T> direct(String property) {
221
        return delegate.direct(property);
1✔
222
    }
223

224
    @Override
225
    public <P> C1<T, P> property(String property) {
226
        return delegate.property(property);
1✔
227
    }
228

229
    @Override
230
    public <P1, P2> C2<T, P1, P2> properties(String property1, String property2) {
231
        return delegate.properties(property1, property2);
1✔
232
    }
233

234
    @Override
235
    public <P1, P2, P3> C3<T, P1, P2, P3> properties(String property1, String property2, String property3) {
236
        return delegate.properties(property1, property2, property3);
1✔
237
    }
238

239
    @Override
240
    public CN<T> properties(String... properties) {
241
        return delegate.properties(properties);
1✔
242
    }
243

244
    @Override
245
    public ListConsistencyBuilder<T> list(String property) {
UNCOV
246
        return delegate.list(property);
×
247
    }
248

249
    @Override
250
    public ListConsistencyBuilder<T> list(String property1, String property2) {
NEW
251
        return delegate.list(property1, property2);
×
252
    }
253
}
254

255
class IdentityAction implements DefaultConsistency.Identity {
256
    protected final Object identity;
257
    private final StackTraceElement location;
258

259
    public IdentityAction(Object identity) {
1✔
260
        this.identity = Objects.requireNonNull(identity);
1✔
261
        location = guessCustomerPositionStackTrace();
1✔
262
    }
1✔
263

264
    @Override
265
    public Object identity() {
266
        return identity;
1✔
267
    }
268

269
    @Override
270
    public StackTraceElement getLocation() {
271
        return location;
1✔
272
    }
273
}
274

275
class ComposerWrapper<T> extends IdentityAction implements DefaultConsistency.Composer<T> {
276
    private final Function<Object[], T> action;
277

278
    ComposerWrapper(Function<Object[], T> action, Object identity) {
279
        super(identity);
1✔
280
        this.action = Objects.requireNonNull(action);
1✔
281
    }
1✔
282

283
    @Override
284
    public T apply(Object[] objects) {
285
        return action.apply(objects);
1✔
286
    }
287
}
288

289
class DecomposerWrapper<T> extends IdentityAction implements DefaultConsistency.Decomposer<T> {
290
    private final Function<T, Object[]> action;
291

292
    DecomposerWrapper(Function<T, Object[]> action, Object identity) {
293
        super(identity);
1✔
294
        this.action = Objects.requireNonNull(action);
1✔
295
    }
1✔
296

297
    @Override
298
    public Object[] apply(T t) {
299
        return action.apply(t);
1✔
300
    }
301
}
302

303
class MultiPropertyConsistency<T, C extends MultiPropertyConsistency<T, C>> extends DecorateConsistency<T> {
304
    final ConsistencyItem<T> lastItem;
305

306
    MultiPropertyConsistency(Consistency<T> origin, ConsistencyItem<T> lastItem) {
307
        super(origin);
1✔
308
        this.lastItem = lastItem;
1✔
309
    }
1✔
310

311
    @SuppressWarnings("unchecked")
312
    public C read(Function<Object[], T> composer) {
313
        lastItem.setComposer(new ComposerWrapper<>(composer, composer));
1✔
314
        return (C) this;
1✔
315
    }
316

317
    @SuppressWarnings("unchecked")
318
    public C write(Function<T, Object[]> decomposer) {
319
        lastItem.setDecomposer(new DecomposerWrapper<>(decomposer, decomposer));
1✔
320
        return (C) this;
1✔
321
    }
322
}
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