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

leeonky / test-charm-java / 356

08 Oct 2025 01:39PM UTC coverage: 75.141% (+5.1%) from 70.03%
356

push

circleci

leeonky
Update version

8817 of 11734 relevant lines covered (75.14%)

0.75 hits per line

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

97.71
/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.function.Extension.getFirstPresent;
11
import static java.util.Optional.*;
12
import static java.util.stream.IntStream.range;
13

14
class ObjectProducer<T> extends Producer<T> {
15
    private final ObjectFactory<T> factory;
16
    private final JFactory jFactory;
17
    private final DefaultBuilder<T> builder;
18
    private final RootInstance<T> instance;
19
    private final Map<String, Producer<?>> children = new HashMap<>();
1✔
20
    private final Map<PropertyChain, String> reverseAssociations = new LinkedHashMap<>();
1✔
21
    private final ListPersistable cachedChildren = new ListPersistable();
1✔
22
    private final Set<String> ignorePropertiesInSpec = new HashSet<>();
1✔
23
    private Persistable persistable;
24
    private Function<PropertyWriter<T>, Producer<?>> elementPopulationFactory = any -> null;
1✔
25
    private final ConsistencySet consistencySet = new ConsistencySet();
1✔
26
    private final List<PropertyStructureDependent> propertyStructureDependents = new ArrayList<>();
1✔
27
    private final List<DefaultListStructure<T, ?>> listStructures = new ArrayList<>();
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
        createDefaultValueProducers();
1✔
45
        builder.collectSpec(this, instance);
1✔
46
        builder.processInputProperty(this, forQuery);
1✔
47
        instance.spec.applyPropertyStructureDefinitions(jFactory, this);
1✔
48
        processListStructures();
1✔
49
        setupReverseAssociations();
1✔
50
        resolveBuilderProducers();
1✔
51
    }
1✔
52

53
    private void processListStructures() {
54
        listStructures.forEach(listStructure -> listStructure.process(this, jFactory));
1✔
55
    }
1✔
56

57
    public Producer<?> newElementPopulationProducer(PropertyWriter<T> propertyWriter) {
58
        return getFirstPresent(() -> ofNullable(elementPopulationFactory.apply(propertyWriter)),
1✔
59
                () -> newDefaultValueProducer(propertyWriter))
1✔
60
                .orElseGet(() -> new DefaultTypeValueProducer<>(propertyWriter.getType()));
1✔
61
    }
62

63
    protected void resolveBuilderProducers() {
64
        List<Map.Entry<String, Producer<?>>> buildValueProducers = children.entrySet().stream()
1✔
65
                .filter(entry -> entry.getValue() instanceof BuilderValueProducer).collect(Collectors.toList());
1✔
66
        buildValueProducers.forEach(e -> setChild(e.getKey(), ((BuilderValueProducer) e.getValue()).getProducer()));
1✔
67
    }
1✔
68

69
    private void createElementDefaultValueProducersWhenBuildListAsRoot() {
70
        try {
71
            children.keySet().stream().map(Integer::valueOf).max(Integer::compareTo).ifPresent(size -> {
1✔
72
                size++;
1✔
73
                instance.setCollectionSize(size);
1✔
74
                range(0, size).mapToObj(String::valueOf)
1✔
75
                        .filter(index -> children.get(index) == null)
1✔
76
                        .map(index -> getType().getPropertyWriter(index))
1✔
77
                        .forEach((PropertyWriter<T> propertyWriter) ->
1✔
78
                                setChild(propertyWriter.getName(), newElementPopulationProducer(propertyWriter)));
1✔
79
            });
1✔
80
        } catch (Exception ignore) {
1✔
81
        }
1✔
82
    }
1✔
83

84
    private void setupReverseAssociations() {
85
        reverseAssociations.forEach((child, association) ->
1✔
86
                descendantForUpdate(child).setupAssociation(association, instance, cachedChildren));
1✔
87
    }
1✔
88

89
    @Override
90
    protected void setChild(String property, Producer<?> producer) {
91
        children.put(property, producer);
1✔
92
    }
1✔
93

94
    @Override
95
    public Optional<Producer<?>> getChild(String property) {
96
        return ofNullable(children.get(property));
1✔
97
    }
98

99
    @Override
100
    public Producer<?> childForUpdate(String property) {
101
        PropertyWriter<T> propertyWriter = getType().getPropertyWriter(property);
1✔
102
        return getFirstPresent(() -> getChild(propertyWriter.getName()),
1✔
103
                () -> newDefaultValueProducer(propertyWriter)).orElseGet(() -> {
1✔
104
            if (ignorePropertiesInSpec.contains(propertyWriter.getName()))
1✔
105
                return new ReadOnlyProducer<>(this, propertyWriter.getName());
×
106
            return new DefaultTypeValueProducer<>(propertyWriter.getType());
1✔
107
        });
108
    }
109

110
    @Override
111
    public Producer<?> childForRead(String property) {
112
        PropertyWriter<T> propertyWriter = getType().getPropertyWriter(property);
1✔
113
        return getFirstPresent(() -> getChild(propertyWriter.getName()),
1✔
114
                () -> newDefaultValueProducerForRead(propertyWriter)).orElseGet(() -> {
1✔
115
            if (ignorePropertiesInSpec.contains(propertyWriter.getName()))
1✔
116
                return new ReadOnlyProducer<>(this, propertyWriter.getName());
1✔
117
            return new DefaultTypeValueProducer<>(propertyWriter.getType());
1✔
118
        });
119
    }
120

121
    public Producer<?> forceChildOrDefaultCollection(PropertyWriter<T> propertyWriter) {
122
        return getChild(propertyWriter.getName()).orElseGet(() -> createCollectionProducer(propertyWriter));
1✔
123
    }
124

125
    @Override
126
    protected T produce() {
127
        return instance.cache(() -> {
1✔
128
            createElementDefaultValueProducersWhenBuildListAsRoot();
1✔
129
            return factory.create(instance);
1✔
130
        }, obj -> {
131
            produceSubs(obj);
1✔
132
            persistable.save(obj);
1✔
133
            cachedChildren.getAll().forEach(persistable::save);
1✔
134
        });
1✔
135
    }
136

137
    private void produceSubs(T obj) {
138
        children.entrySet().stream().filter(this::isDefaultValueProducer).forEach(e -> produceSub(obj, e));
1✔
139
        children.entrySet().stream().filter(e -> !(isDefaultValueProducer(e))).forEach(e -> produceSub(obj, e));
1✔
140
    }
1✔
141

142
    private void produceSub(T obj, Map.Entry<String, Producer<?>> e) {
143
        getType().setPropertyValue(obj, e.getKey(), e.getValue().getValue());
1✔
144
    }
1✔
145

146
    private boolean isDefaultValueProducer(Map.Entry<String, Producer<?>> e) {
147
        return e.getValue() instanceof DefaultValueFactoryProducer;
1✔
148
    }
149

150
    public ObjectProducer<T> processConsistent() {
151
        collectConsistent(this, propertyChain(""));
1✔
152
        consistencySet.resolve(this);
1✔
153
        return this;
1✔
154
    }
155

156
    @Override
157
    public void verifyPropertyStructureDependent() {
158
        for (PropertyStructureDependent propertyStructureDependent : propertyStructureDependents)
1✔
159
            propertyStructureDependent.verify(getValue());
1✔
160

161
        children.values().forEach(Producer::verifyPropertyStructureDependent);
1✔
162
    }
1✔
163

164
    @Override
165
    protected void collectConsistent(ObjectProducer<?> root, PropertyChain base) {
166
        if (root != this)
1✔
167
            root.consistencySet.addAll(consistencySet.absoluteProperty(base));
1✔
168
        children.forEach((property, producer) -> producer.collectConsistent(root, base.concat(property)));
1✔
169
    }
1✔
170

171
    private void createDefaultValueProducers() {
172
        getType().getPropertyWriters().values().stream().filter(jFactory::shouldCreateDefaultValue)
1✔
173
                .forEach(propertyWriter -> factory.getFactorySet().newDefaultValueFactoryProducer(propertyWriter, instance)
1✔
174
                        .ifPresent(producer -> setChild(propertyWriter.getName(), producer)));
1✔
175
    }
1✔
176

177
    @Override
178
    public Optional<Producer<?>> newDefaultValueProducer(PropertyWriter<T> property) {
179
        if (ignorePropertiesInSpec.contains(property.getName()))
1✔
180
            return empty();
×
181
        if (property.getType().isCollection()) {
1✔
182
            return of(createCollectionProducer(property));
1✔
183
        } else
184
            return factory.getFactorySet().newDefaultValueFactoryProducer(property, instance);
1✔
185
    }
186

187
    public Optional<Producer<?>> newDefaultValueProducerForRead(PropertyWriter<T> property) {
188
        if (ignorePropertiesInSpec.contains(property.getName()))
1✔
189
            return empty();
1✔
190
        else
191
            return factory.getFactorySet().newDefaultValueFactoryProducer(property, instance);
1✔
192
    }
193

194
    private Producer<?> createCollectionProducer(PropertyWriter<T> property) {
195
        Producer<?> producer = new CollectionProducer<>(getType(), property.getType(), instance.sub(property),
1✔
196
                factory.getFactorySet(), jFactory);
1✔
197
        setChild(property.getName(), producer);
1✔
198
        return producer;
1✔
199
    }
200

201
    @Override
202
    public Producer<T> changeTo(Producer<T> newProducer) {
203
        return newProducer.changeFrom(this);
1✔
204
    }
205

206
    @Override
207
    protected Producer<T> changeFrom(ObjectProducer<T> origin) {
208
        return origin.builder.marge(builder).createProducer();
1✔
209
    }
210

211
    @Override
212
    @SuppressWarnings("unchecked")
213
    protected Producer<T> changeFrom(OptionalSpecDefaultValueProducer<T> producer) {
214
        if (producer.getTraitsAndSpec() != null)
1✔
215
            return ((DefaultBuilder<T>) jFactory.spec(producer.getTraitsAndSpec())).marge(builder).createProducer();
1✔
216
        return this;
×
217
    }
218

219
    public void appendReverseAssociation(PropertyChain property, String association) {
220
        reverseAssociations.put(property, association);
1✔
221
    }
1✔
222

223
    @Override
224
    protected <R> void setupAssociation(String association, RootInstance<R> instance, ListPersistable cachedChildren) {
225
        setChild(association, new UnFixedValueProducer<>(instance.reference(), instance.spec().getType()));
1✔
226
        persistable = cachedChildren;
1✔
227
    }
1✔
228

229
    public boolean isReverseAssociation(String property) {
230
        return reverseAssociations.containsKey(PropertyChain.propertyChain(property));
1✔
231
    }
232

233
    public void ignoreProperty(String property) {
234
        ignorePropertiesInSpec.add(property);
1✔
235
    }
1✔
236

237
    public void processSpecIgnoreProperties() {
238
        children.entrySet().stream().filter(e -> e.getValue() instanceof DefaultValueProducer
1✔
239
                        && ignorePropertiesInSpec.contains(e.getKey())).map(Map.Entry::getKey).collect(Collectors.toList())
1✔
240
                .forEach(children::remove);
1✔
241
    }
1✔
242

243
    @Override
244
    protected boolean isFixed() {
245
        return children.values().stream().anyMatch(Producer::isFixed);
1✔
246
    }
247

248
    public void changeElementPopulationFactory(Function<PropertyWriter<T>, Producer<?>> factory) {
249
        elementPopulationFactory = factory;
1✔
250
    }
1✔
251

252
    public void appendLink(DefaultConsistency<?, ?> consistency) {
253
        consistencySet.add(consistency);
1✔
254
    }
1✔
255

256
    public void lock(PropertyStructureDependent propertyStructureDependent) {
257
        propertyStructureDependents.add(propertyStructureDependent);
1✔
258
    }
1✔
259

260
    public void appendListStructure(DefaultListStructure<T, ?> listStructure) {
261
        listStructures.add(listStructure);
1✔
262
    }
1✔
263
}
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