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

leeonky / test-charm-java / 390

18 Oct 2025 04:40PM UTC coverage: 75.298% (+0.01%) from 75.288%
390

push

circleci

leeonky
refactor

8 of 8 new or added lines in 5 files covered. (100.0%)

19 existing lines in 8 files now uncovered.

8895 of 11813 relevant lines covered (75.3%)

0.75 hits per line

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

89.04
/jfactory/src/main/java/com/github/leeonky/jfactory/KeyValue.java
1
package com.github.leeonky.jfactory;
2

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

6
import java.util.List;
7
import java.util.Map;
8
import java.util.Objects;
9
import java.util.regex.Matcher;
10
import java.util.regex.Pattern;
11

12
import static com.github.leeonky.util.CollectionHelper.reify;
13
import static com.github.leeonky.util.Sneaky.cast;
14
import static java.lang.Integer.parseInt;
15
import static java.util.Optional.ofNullable;
16

17
//TODO use a parser to parse this
18
class KeyValue {
19
    private static final String PATTERN_PROPERTY = "([^.(!\\[]+)";
20
    private static final String PATTERN_COLLECTION_INDEX = "(\\[(-?\\d+)])?";
21
    private static final String PATTERN_SPEC_TRAIT_WORD = "[^, )]";
22
    private static final String PATTERN_TRAIT = "((" + PATTERN_SPEC_TRAIT_WORD + "+[, ])(" + PATTERN_SPEC_TRAIT_WORD + "+[, ])*)?";
23
    private static final String PATTERN_SPEC = "(" + PATTERN_SPEC_TRAIT_WORD + "+)";
24
    private static final String PATTERN_TRAIT_SPEC = "(\\(" + PATTERN_TRAIT + PATTERN_SPEC + "\\))?";
25
    private static final String PATTERN_CLAUSE = "(\\." + "(.+)" + ")?";
26
    private static final String PATTERN_INTENTLY = "(!)?";
27
    private static final int GROUP_PROPERTY = 1;
28

29
    private static final int GROUP_TRAIT = 3;
30
    private static final int GROUP_SPEC = 6;
31

32
    private static final int GROUP_COLLECTION_INDEX = 3 + 5;
33
    private static final int GROUP_ELEMENT_TRAIT = 5 + 5;
34
    private static final int GROUP_ELEMENT_SPEC = 8 + 5;
35
    private static final int GROUP_INTENTLY = 9 + 5;
36
    private static final int GROUP_CLAUSE = 11 + 5;
37

38
    private final String key;
39
    private final Object value;
40
    private final String propertyName;
41
    private final String clause;
42
    private final TraitsSpec traitsSpec;
43
    private final TraitsSpec elementTraitSpec;
44
    private final boolean intently;
45
    private final String index;
46

47
    public KeyValue(String key, Object value) {
1✔
48
        this.key = key;
1✔
49
        this.value = value;
1✔
50
        if (key != null) {
1✔
51
            Matcher matcher = Pattern.compile(PATTERN_PROPERTY + PATTERN_TRAIT_SPEC + PATTERN_COLLECTION_INDEX +
1✔
52
                    PATTERN_TRAIT_SPEC + PATTERN_INTENTLY + PATTERN_CLAUSE).matcher(key);
1✔
53
            if (!matcher.matches())
1✔
54
                throw new IllegalArgumentException(String.format("The format of property `%s` is invalid.", key));
1✔
55
            propertyName = matcher.group(GROUP_PROPERTY);
1✔
56
            clause = matcher.group(GROUP_CLAUSE);
1✔
57
            traitsSpec = new TraitsSpec(matcher.group(GROUP_TRAIT) != null ?
1✔
58
                    matcher.group(GROUP_TRAIT).split(", |,| ") : new String[0], matcher.group(GROUP_SPEC));
1✔
59
            elementTraitSpec = new TraitsSpec(matcher.group(GROUP_ELEMENT_TRAIT) != null ?
1✔
60
                    matcher.group(GROUP_ELEMENT_TRAIT).split(", |,| ") : new String[0], matcher.group(GROUP_ELEMENT_SPEC));
1✔
61
            intently = matcher.group(GROUP_INTENTLY) != null;
1✔
62
            index = matcher.group(GROUP_COLLECTION_INDEX);
1✔
63
        } else {
1✔
UNCOV
64
            propertyName = null;
×
UNCOV
65
            clause = null;
×
UNCOV
66
            traitsSpec = null;
×
UNCOV
67
            elementTraitSpec = null;
×
UNCOV
68
            intently = false;
×
UNCOV
69
            index = null;
×
70
        }
71
    }
1✔
72

73
    public <T> Expression<T> createExpression(BeanClass<T> beanClass, ObjectFactory<T> objectFactory, Producer<T> producer, boolean forQuery) {
74
        Property<T> property = beanClass.getProperty(propertyName);
1✔
75
        Producer<?> subProducer;
76

77
        if (traitsSpec.isCollectionSpec()
1✔
78
//        TODO raise error when spec and property type conflicted
79
//                && producer instanceof ObjectProducer
80
//                && (property.getWriterType().is(Object.class) || property.getWriterType().isCollection())
81
        ) {
82
            SpecClassFactory<T> specFactory = objectFactory.getFactorySet().querySpecClassFactory(traitsSpec.spec());
1✔
83
            property = property.decorateType(reify(
1✔
84
                    property.getWriterType().isCollection() ? property.getWriterType().getType() :
1✔
85
                            List.class, specFactory.getType().getGenericType()));
1✔
86
            subProducer = ((ObjectProducer) producer).forceChildOrDefaultCollection(property.getWriter());
1✔
87
            if (subProducer instanceof CollectionProducer)
1✔
88
                ((CollectionProducer<?, ?>) subProducer).changeElementPopulationFactory(i ->
1✔
89
                                new BuilderValueProducer<>(
1✔
90
                                        traitsSpec.toBuilder(((ObjectProducer) producer).jFactory(), specFactory.getType()), true)
1✔
91
//                                .createProducer()
92
                );
93
            if (subProducer == null)
1✔
UNCOV
94
                subProducer = PlaceHolderProducer.PLACE_HOLDER;
×
95
        } else {
1✔
96
            subProducer = producer.getChild(propertyName).orElse(PlaceHolderProducer.PLACE_HOLDER);
1✔
97
            if (subProducer instanceof ObjectProducer
1✔
98
                    || subProducer instanceof CollectionProducer
99
                    || subProducer instanceof BuilderValueProducer
100
            )
101
                property = property.decorateType(subProducer.getType());
1✔
102
        }
103
        Property<T> finalSubProperty = property;
1✔
104
        Producer<T> finalSubProducer = (Producer<T>) subProducer;
1✔
105
        return ofNullable(index).map(index -> createCollectionExpression(finalSubProperty, index, objectFactory, finalSubProducer, forQuery))
1✔
106
                .orElseGet(() -> createSubExpression(finalSubProperty, null, objectFactory, finalSubProducer, forQuery, traitsSpec));
1✔
107
    }
108

109
    //    TODO refactor
110
    private <T> Expression<T> createCollectionExpression(Property<T> property, String index,
111
                                                         ObjectFactory<T> objectFactory, Producer<?> collectionProducer, boolean forQuery) {
112
        Property<?> propertySub = property.getWriter().getType().getProperty(index);
1✔
113
        int intIndex = parseInt(index);
1✔
114
        Producer<?> subProducer;
115
        if (collectionProducer instanceof CollectionProducer) {
1✔
116
            subProducer = ((CollectionProducer<?, ?>) collectionProducer).newElementPopulationProducer(cast(collectionProducer.getType().getPropertyWriter(index)));
1✔
117
            if (subProducer instanceof ObjectProducer || subProducer instanceof BuilderValueProducer) {
1✔
118
                propertySub = propertySub.decorateType(subProducer.getType());
1✔
119
            }
120
        } else
121
            subProducer = collectionProducer.getChild(index).orElse(PlaceHolderProducer.PLACE_HOLDER);
1✔
122
        if (collectionProducer instanceof BuilderValueProducer) {
1✔
123
            return new SubObjectExpression<>(new KeyValueCollection().append(index + "." + clause, value), elementTraitSpec, property, objectFactory, subProducer, forQuery);
1✔
124
        }
125
        return new CollectionExpression<>(property, intIndex,
1✔
126
                createSubExpression(propertySub, property, objectFactory, subProducer, forQuery, elementTraitSpec));
1✔
127
    }
128

129

130
    private boolean isEmptyMap(Object value) {
131
        return value instanceof Map && ((Map<?, ?>) value).isEmpty();
1✔
132
    }
133

134
    private <T> Expression<T> createSubExpression(Property<T> property, Property<?> parentProperty,
135
                                                  ObjectFactory<?> objectFactory, Producer<?> subProducer, boolean forQuery, TraitsSpec traitsSpec) {
136
        Expression<T> result;
137
        Property<T> decoratedProperty = traitsSpec.guessPropertyType(objectFactory).map(property::decorateType).orElse(property);
1✔
138
        if (clause == null) {
1✔
139
            String transformerName = parentProperty != null && decoratedProperty.getBeanType().isCollection()
1✔
140
                    ? propertyName + "[]" : propertyName;
141
            Object value = objectFactory.transform(transformerName, this.value);
1✔
142
            if (isEmptyMap(value))
1✔
143
                result = new SubObjectExpression<>(new KeyValueCollection(), traitsSpec, decoratedProperty, objectFactory, subProducer, forQuery);
1✔
144
            else
145
                result = new SingleValueExpression<>(value, traitsSpec, decoratedProperty, forQuery);
1✔
146
        } else
1✔
147
            result = new SubObjectExpression<>(new KeyValueCollection().append(clause, value), traitsSpec, decoratedProperty, objectFactory, subProducer, forQuery);
1✔
148
        return result.setIntently(intently);
1✔
149
    }
150

151
    public <T> Builder<T> apply(Builder<T> builder) {
152
        return builder.property(key, value);
1✔
153
    }
154

155
    @Override
156
    public int hashCode() {
157
        return Objects.hash(KeyValue.class, key, value);
1✔
158
    }
159

160
    @Override
161
    public boolean equals(Object another) {
162
        return BeanClass.cast(another, KeyValue.class)
1✔
163
                .map(keyValue -> Objects.equals(key, keyValue.key) && Objects.equals(value, keyValue.value))
1✔
164
                .orElseGet(() -> super.equals(another));
1✔
165
    }
166

167
    public Object getValue() {
UNCOV
168
        return value;
×
169
    }
170
}
171

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