• 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

95.87
/jfactory/src/main/java/com/github/leeonky/jfactory/ObjectProducer.java
1
package com.github.leeonky.jfactory;
2

3
import com.github.leeonky.util.PropertyWriter;
4

5
import java.util.*;
6
import java.util.function.Function;
7
import java.util.stream.Collectors;
8

9
import static com.github.leeonky.jfactory.PropertyChain.propertyChain;
10
import static com.github.leeonky.util.Sneaky.cast;
11
import static com.github.leeonky.util.function.Extension.getFirstPresent;
12
import static java.util.Optional.empty;
13
import static java.util.Optional.of;
14
import static java.util.stream.IntStream.range;
15

16
class ObjectProducer<T> extends Producer<T> {
17
    private final ObjectFactory<T> factory;
18
    private final JFactory jFactory;
19
    private final DefaultBuilder<T> builder;
20
    private final RootInstance<T> instance;
21
    private final Map<String, Producer<?>> children = new HashMap<>();
1✔
22
    private final Map<PropertyChain, String> reverseAssociations = new LinkedHashMap<>();
1✔
23
    private final ListPersistable cachedChildren = new ListPersistable();
1✔
24
    private final Set<String> ignorePropertiesInSpec = new HashSet<>();
1✔
25
    private Persistable persistable;
26
    private Function<PropertyWriter<?>, Producer<?>> defaultListElementValueProducerFactory;
27
    private final ConsistencySet consistencySet = new ConsistencySet();
1✔
28

29
    public JFactory jFactory() {
30
        return jFactory;
1✔
31
    }
32

33
    public ObjectProducer(JFactory jFactory, ObjectFactory<T> factory, DefaultBuilder<T> builder) {
34
        this(jFactory, factory, builder, false);
1✔
35
    }
1✔
36

37
    public ObjectProducer(JFactory jFactory, ObjectFactory<T> factory, DefaultBuilder<T> builder, boolean forQuery) {
38
        super(factory.getType());
1✔
39
        this.factory = factory;
1✔
40
        this.jFactory = jFactory;
1✔
41
        this.builder = builder;
1✔
42
        instance = factory.createInstance(builder.getArguments());
1✔
43
        persistable = jFactory.getDataRepository();
1✔
44
        defaultListElementValueProducerFactory = propertyWriter -> new DefaultValueFactoryProducer<>(factory.getType(),
1✔
45
                factory.getFactorySet().getDefaultValueFactory(propertyWriter.getType()),
1✔
46
                instance.sub(propertyWriter));
1✔
47
        createDefaultValueProducers();
1✔
48
        builder.collectSpec(this, instance);
1✔
49
        builder.processInputProperty(this, forQuery);
1✔
50
        setupReverseAssociations();
1✔
51
        resolveBuilderProducers();
1✔
52
    }
1✔
53

54
    protected void resolveBuilderProducers() {
55
        List<Map.Entry<String, Producer<?>>> buildValueProducers = children.entrySet().stream()
1✔
56
                .filter(entry -> entry.getValue() instanceof BuilderValueProducer).collect(Collectors.toList());
1✔
57
        buildValueProducers.forEach(e -> setChild(e.getKey(), ((BuilderValueProducer) e.getValue()).getProducer()));
1✔
58
    }
1✔
59

60
    private void createElementDefaultValueProducersWhenBuildListAsRoot() {
61
        try {
62
            children.keySet().stream().map(Integer::valueOf).max(Integer::compareTo).ifPresent(size -> {
1✔
63
                size++;
1✔
64
                instance.setCollectionSize(size);
1✔
65
                range(0, size).mapToObj(String::valueOf)
1✔
66
                        .filter(index -> children.get(index) == null)
1✔
67
                        .map(index -> getType().getPropertyWriter(index))
1✔
68
                        .forEach((PropertyWriter<T> propertyWriter) ->
1✔
69
                                setChild(propertyWriter.getName(), defaultListElementValueProducerFactory.apply(propertyWriter)));
1✔
70
            });
1✔
71
        } catch (Exception ignore) {
1✔
72
        }
1✔
73
    }
1✔
74

75
    private void setupReverseAssociations() {
76
        reverseAssociations.forEach((child, association) ->
1✔
77
                descendantForUpdate(child).setupAssociation(association, instance, cachedChildren));
1✔
78
    }
1✔
79

80
    @Override
81
    protected void setChild(String property, Producer<?> producer) {
82
        children.put(property, producer);
1✔
83
    }
1✔
84

85
    @Override
86
    public Optional<Producer<?>> getChild(String property) {
87
        return Optional.ofNullable(children.get(property));
1✔
88
    }
89

90
    @Override
91
    public Producer<?> childForUpdate(String property) {
92
        PropertyWriter<T> propertyWriter = getType().getPropertyWriter(property);
1✔
93
        return getFirstPresent(() -> getChild(propertyWriter.getName()),
1✔
94
                () -> newDefaultValueProducer(propertyWriter)).orElseGet(() -> {
1✔
95
            if (ignorePropertiesInSpec.contains(propertyWriter.getName()))
1✔
UNCOV
96
                return new ReadOnlyProducer<>(this, propertyWriter.getName());
×
97
            return new DefaultValueProducer<>(propertyWriter.getType(),
1✔
UNCOV
98
                    () -> cast(propertyWriter.getType().createDefault()));
×
99
        });
100
    }
101

102
    @Override
103
    public Producer<?> childForRead(String property) {
104
        PropertyWriter<T> propertyWriter = getType().getPropertyWriter(property);
1✔
105
        return getFirstPresent(() -> getChild(propertyWriter.getName()),
1✔
106
                () -> newDefaultValueProducerForRead(propertyWriter)).orElseGet(() -> {
1✔
107
            if (ignorePropertiesInSpec.contains(propertyWriter.getName()))
1✔
108
                return new ReadOnlyProducer<>(this, propertyWriter.getName());
1✔
109
            return new DefaultValueProducer<>(propertyWriter.getType(),
1✔
NEW
110
                    () -> cast(propertyWriter.getType().createDefault()));
×
111
        });
112
    }
113

114
    public Producer<?> forceChildOrDefaultCollection(PropertyWriter<T> propertyWriter) {
115
        return getChild(propertyWriter.getName()).orElseGet(() -> createCollectionProducer(propertyWriter));
1✔
116
    }
117

118
    @Override
119
    protected T produce() {
120
        return instance.cache(() -> {
1✔
121
            createElementDefaultValueProducersWhenBuildListAsRoot();
1✔
122
            return factory.create(instance);
1✔
123
        }, obj -> {
124
            produceSubs(obj);
1✔
125
            persistable.save(obj);
1✔
126
            cachedChildren.getAll().forEach(persistable::save);
1✔
127
        });
1✔
128
    }
129

130
    private void produceSubs(T obj) {
131
        children.entrySet().stream().filter(this::isDefaultValueProducer).forEach(e -> produceSub(obj, e));
1✔
132
        children.entrySet().stream().filter(e -> !(isDefaultValueProducer(e))).forEach(e -> produceSub(obj, e));
1✔
133
    }
1✔
134

135
    private void produceSub(T obj, Map.Entry<String, Producer<?>> e) {
136
        getType().setPropertyValue(obj, e.getKey(), e.getValue().getValue());
1✔
137
    }
1✔
138

139
    private boolean isDefaultValueProducer(Map.Entry<String, Producer<?>> e) {
140
        return e.getValue() instanceof DefaultValueFactoryProducer;
1✔
141
    }
142

143
    public ObjectProducer<T> processConsistent() {
144
        collectConsistent(this, propertyChain(""));
1✔
145
        consistencySet.resolve(this);
1✔
146
        return this;
1✔
147
    }
148

149
    @Override
150
    protected void collectConsistent(ObjectProducer<?> root, PropertyChain base) {
151
        if (root != this)
1✔
152
            root.consistencySet.addAll(consistencySet.absoluteProperty(base));
1✔
153
        children.forEach((property, producer) -> producer.collectConsistent(root, base.concat(property)));
1✔
154
    }
1✔
155

156
    private void createDefaultValueProducers() {
157
        getType().getPropertyWriters().values().stream().filter(jFactory::shouldCreateDefaultValue)
1✔
158
                .forEach(propertyWriter -> factory.getFactorySet().queryDefaultValueFactory(propertyWriter.getType())
1✔
159
                        .map(builder -> new DefaultValueFactoryProducer<>(getType(), builder, instance.sub(propertyWriter)))
1✔
160
                        .ifPresent(producer -> setChild(propertyWriter.getName(), producer)));
1✔
161
    }
1✔
162

163
    @Override
164
    public Optional<Producer<?>> newDefaultValueProducer(PropertyWriter<?> property) {
165
        if (ignorePropertiesInSpec.contains(property.getName()))
1✔
UNCOV
166
            return empty();
×
167
        if (property.getType().isCollection()) {
1✔
168
            return of(createCollectionProducer(property));
1✔
169
        } else
170
            return factory.getFactorySet().queryDefaultValueFactory(property.getType())
1✔
171
                    .map(builder -> new DefaultValueFactoryProducer<>(getType(), builder, instance.sub(property)));
1✔
172
    }
173

174
    public Optional<Producer<?>> newDefaultValueProducerForRead(PropertyWriter<?> property) {
175
        if (ignorePropertiesInSpec.contains(property.getName()))
1✔
176
            return empty();
1✔
177
        else
178
            return factory.getFactorySet().queryDefaultValueFactory(property.getType())
1✔
179
                    .map(builder -> new DefaultValueFactoryProducer<>(getType(), builder, instance.sub(property)));
1✔
180
    }
181

182
    private Producer<?> createCollectionProducer(PropertyWriter<?> property) {
183
        Producer<?> producer = new CollectionProducer<>(getType(), property.getType(), instance.sub(property),
1✔
184
                factory.getFactorySet());
1✔
185
        setChild(property.getName(), producer);
1✔
186
        return producer;
1✔
187
    }
188

189
    @Override
190
    public Producer<T> changeTo(Producer<T> newProducer) {
191
        return newProducer.changeFrom(this);
1✔
192
    }
193

194
    @Override
195
    protected Producer<T> changeFrom(ObjectProducer<T> origin) {
196
        return origin.builder.marge(builder).createProducer();
1✔
197
    }
198

199
    @Override
200
    @SuppressWarnings("unchecked")
201
    protected Producer<T> changeFrom(OptionalSpecDefaultValueProducer<T> producer) {
202
        if (producer.getTraitsAndSpec() != null)
1✔
203
            return ((DefaultBuilder<T>) jFactory.spec(producer.getTraitsAndSpec())).marge(builder).createProducer();
1✔
UNCOV
204
        return this;
×
205
    }
206

207
    public void appendReverseAssociation(PropertyChain property, String association) {
208
        reverseAssociations.put(property, association);
1✔
209
    }
1✔
210

211
    @Override
212
    protected <R> void setupAssociation(String association, RootInstance<R> instance, ListPersistable cachedChildren) {
213
        setChild(association, new UnFixedValueProducer<>(instance.reference(), instance.spec().getType()));
1✔
214
        persistable = cachedChildren;
1✔
215
    }
1✔
216

217
    public boolean isReverseAssociation(String property) {
218
        return reverseAssociations.containsKey(PropertyChain.propertyChain(property));
1✔
219
    }
220

221
    public void ignoreProperty(String property) {
222
        ignorePropertiesInSpec.add(property);
1✔
223
    }
1✔
224

225
    public void processSpecIgnoreProperties() {
226
        children.entrySet().stream().filter(e -> e.getValue() instanceof DefaultValueProducer
1✔
227
                        && ignorePropertiesInSpec.contains(e.getKey())).map(Map.Entry::getKey).collect(Collectors.toList())
1✔
228
                .forEach(children::remove);
1✔
229
    }
1✔
230

231
    @Override
232
    protected boolean isFixed() {
233
        return children.values().stream().anyMatch(Producer::isFixed);
1✔
234
    }
235

236
    public void changeElementDefaultValueProducerFactory(Function<PropertyWriter<?>, Producer<?>> factory) {
237
        defaultListElementValueProducerFactory = factory;
1✔
238
    }
1✔
239

240
    public void appendLink(DefaultConsistency<?> consistency) {
241
        consistencySet.add(consistency);
1✔
242
    }
1✔
243
}
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