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

leeonky / test-charm-java / 293

12 Sep 2025 04:43PM UTC coverage: 74.22% (-0.09%) from 74.312%
293

push

circleci

leeonky
create sub list from spec list in spec

33 of 42 new or added lines in 8 files covered. (78.57%)

32 existing lines in 11 files now uncovered.

8234 of 11094 relevant lines covered (74.22%)

0.74 hits per line

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

96.0
/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.Objects;
7
import java.util.Optional;
8
import java.util.regex.Matcher;
9
import java.util.regex.Pattern;
10

11
import static java.lang.Integer.parseInt;
12

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

25
    private static final int GROUP_TRAIT = 3;
26
    private static final int GROUP_SPEC = 6;
27

28
    private static final int GROUP_COLLECTION_INDEX = 3 + 5;
29
    private static final int GROUP_ELEMENT_TRAIT = 5 + 5;
30
    private static final int GROUP_ELEMENT_SPEC = 8 + 5;
31
    private static final int GROUP_INTENTLY = 9 + 5;
32
    private static final int GROUP_CLAUSE = 11 + 5;
33
    private final String key;
34
    private final Object value;
35
    private final FactorySet factorySet;
36

37
    public KeyValue(String key, Object value, FactorySet factorySet) {
1✔
38
        this.key = key;
1✔
39
        this.value = value;
1✔
40
        this.factorySet = factorySet;
1✔
41
    }
1✔
42

43
    public <T> Expression<T> createExpression(BeanClass<T> beanClass, ObjectFactory<T> objectFactory, Producer<T> producer, boolean forQuery) {
44
        Matcher matcher = parse(beanClass);
1✔
45
        String propertyName = matcher.group(GROUP_PROPERTY);
1✔
46
        Property<T> property = beanClass.getProperty(propertyName);
1✔
47
        Producer<?> subProducer = producer.child(propertyName).orElse(Producer.PLACE_HOLDER);
1✔
48
        if (subProducer instanceof ObjectProducer ||
1✔
49
                subProducer instanceof CollectionProducer && property.getWriterType().is(Object.class)) {
1✔
50
            BeanClass<? extends T> type = (BeanClass<? extends T>) subProducer.getType();
1✔
51
            property = property.decorateNarrowWriterType(type).decorateNarrowReaderType(type);
1✔
52
        }
53
        Property<T> finalSubProducer = property;
1✔
54
        return hasIndex(matcher).map(index -> createCollectionExpression(matcher, finalSubProducer, index, objectFactory, subProducer, forQuery))
1✔
55
                .orElseGet(() -> {
1✔
56
                    TraitsSpec traitsSpec = new TraitsSpec(matcher.group(GROUP_TRAIT) != null ?
1✔
57
                            matcher.group(GROUP_TRAIT).split(", |,| ") : new String[0], matcher.group(GROUP_SPEC));
1✔
58
                    return createSubExpression(matcher, finalSubProducer, null, objectFactory, subProducer, forQuery, traitsSpec);
1✔
59
                });
60
    }
61

62
    private <T> Expression<T> createCollectionExpression(Matcher matcher, Property<T> property, String index,
63
                                                         ObjectFactory<T> objectFactory, Producer<?> collectionProducer, boolean forQuery) {
64
        Property<?> propertySub = property.getWriter().getType().getProperty(index);
1✔
65
        int intIndex = parseInt(index);
1✔
66
        Producer<?> subProducer;
67
        if (collectionProducer instanceof CollectionProducer) {
1✔
68
            subProducer = ((CollectionProducer<?, ?>) collectionProducer).defaultElementProducer(intIndex);
1✔
69
            if (subProducer instanceof ObjectProducer) {
1✔
70
                BeanClass type = subProducer.getType();
1✔
71
                propertySub = propertySub.decorateNarrowWriterType(type).decorateNarrowReaderType(type);
1✔
72
            }
1✔
73
        } else
74
            subProducer = collectionProducer.child(index).orElse(Producer.PLACE_HOLDER);
1✔
75
        TraitsSpec traitsSpec = new TraitsSpec(matcher.group(GROUP_ELEMENT_TRAIT) != null ?
1✔
76
                matcher.group(GROUP_ELEMENT_TRAIT).split(", |,| ") : new String[0], matcher.group(GROUP_ELEMENT_SPEC));
1✔
77
        return new CollectionExpression<>(property, intIndex,
1✔
78
                createSubExpression(matcher, propertySub, property, objectFactory, subProducer, forQuery, traitsSpec), forQuery);
1✔
79
    }
80

81
    private Optional<String> hasIndex(Matcher matcher) {
82
        return Optional.ofNullable(matcher.group(GROUP_COLLECTION_INDEX));
1✔
83
    }
84

85
    private <T> Expression<T> createSubExpression(Matcher matcher, Property<T> property, Property<?> parentProperty,
86
                                                  ObjectFactory<?> objectFactory, Producer<?> subProducer, boolean forQuery, TraitsSpec traitsSpec) {
87
        KeyValueCollection properties = new KeyValueCollection(factorySet).append(matcher.group(GROUP_CLAUSE), value);
1✔
88
        return properties.createExpression(traitsSpec.guessPropertyType(objectFactory)
1✔
89
                        .map(type -> property.decorateNarrowWriterType(type).decorateNarrowReaderType(type)).orElse(property),
1✔
90
                traitsSpec, parentProperty, objectFactory, subProducer, forQuery).setIntently(matcher.group(GROUP_INTENTLY) != null);
1✔
91
    }
92

93
    private <T> Matcher parse(BeanClass<T> beanClass) {
94
        Matcher matcher = Pattern.compile(PATTERN_PROPERTY + PATTERN_TRAIT_SPEC + PATTERN_COLLECTION_INDEX +
1✔
95
                PATTERN_TRAIT_SPEC + PATTERN_INTENTLY + PATTERN_CLAUSE).matcher(key);
1✔
96
        if (!matcher.matches())
1✔
UNCOV
97
            throw new IllegalArgumentException(String.format("Invalid property `%s` for %s creation.",
×
UNCOV
98
                    key, beanClass.getName()));
×
99
        return matcher;
1✔
100
    }
101

102
    public <T> Builder<T> apply(Builder<T> builder) {
103
        return builder.property(key, value);
1✔
104
    }
105

106
    public boolean nullKey() {
107
        return key == null;
1✔
108
    }
109

110
    @Override
111
    public int hashCode() {
112
        return Objects.hash(KeyValue.class, key, value);
1✔
113
    }
114

115
    @Override
116
    public boolean equals(Object another) {
117
        return BeanClass.cast(another, KeyValue.class)
1✔
118
                .map(keyValue -> Objects.equals(key, keyValue.key) && Objects.equals(value, keyValue.value))
1✔
119
                .orElseGet(() -> super.equals(another));
1✔
120
    }
121

122
    public Object getValue() {
123
        return value;
1✔
124
    }
125
}
126

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