Skip to content

Commit 3f88468

Browse files
author
Vasyl Khrystiuk
committed
fixed bug and adding more readme
1 parent d67c1d0 commit 3f88468

File tree

6 files changed

+169
-25
lines changed

6 files changed

+169
-25
lines changed

README.md

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,98 @@ Draft for creating classical property file: https://gist.github.com/msangel/1167
88
Follow instructions here: https://jitpack.io/#msangel/Yaml2DotNotation
99

1010
## Usage
11-
TBD
11+
The library can work with both POJOs and primitives.
12+
This is sample usages from tests:
13+
```java
14+
public class DottedPropertiesInjectorTest {
15+
public static class InnerObject {
16+
@JsonProperty("innerField")
17+
public String a;
18+
}
19+
20+
public static class TestObjectFine {
21+
@Value("a")
22+
public String as;
23+
24+
@Value("b")
25+
private Integer bas;
26+
27+
@Value("c")
28+
private Boolean das;
29+
30+
@Value("d")
31+
private InnerObject inner;
32+
33+
public void setBas(Integer bas) {
34+
this.bas = bas;
35+
}
36+
37+
public Integer getBas() {
38+
return bas;
39+
}
40+
41+
public Boolean isDas() {
42+
return das;
43+
}
44+
45+
public void setDas(Boolean das) {
46+
this.das = das;
47+
}
48+
49+
public InnerObject getInner() {
50+
return inner;
51+
}
52+
53+
public void setInner(InnerObject inner) {
54+
this.inner = inner;
55+
}
56+
}
57+
58+
@Test
59+
public void testInjectFine() {
60+
// yaml is superset of json, so we can use either of them
61+
DottedProperties properties = Yaml2Props.create("{ a: 1, b: 3, c: true, d: { innerField : 'inner object'}}");
62+
TestObjectFine to = new TestObjectFine();
63+
64+
// this method expect existed object, the marked for setting fields must be accessible for that(not final and public/have setter )
65+
DottedPropertiesInjector.injectAnnotatedFields(to, properties);
66+
assertEquals("1", to.as);
67+
assertEquals(3, (int)to.bas);
68+
assertTrue(to.isDas());
69+
70+
// none that top-level properties use @Value annotation as this object is utilazed by our library
71+
// but for nested we have to use JsonProperty as problems of writing proper type for value is Jackson responsibility
72+
assertEquals("inner object", to.inner.a);
73+
}
74+
75+
@Test
76+
public void testGettingFine() {
77+
78+
// yaml is superset of json, so we can use either of them
79+
DottedProperties properties = Yaml2Props.create("{ a: 1, b: 3, c: true, d: { innerField : 'inner object'}}");
80+
String a = properties.getProperty("a").asString();
81+
assertEquals("1", a);
82+
83+
Integer b = properties.getProperty("b").asInteger();
84+
assertEquals(3L, b.longValue());
85+
86+
InnerObject inner = properties.getProperty("d", new TypeReference<InnerObject>() {}); // can be generics
87+
InnerObject expectd = new InnerObject();
88+
expectd.a = "inner object";
89+
assertEquals(expectd, inner);
90+
91+
// all of them are valid and equal selectors:
92+
// d.innerField
93+
// d['innerField']
94+
// ['d'].innerField
95+
// ['d']['innerField']
96+
String nestedValue = properties.getProperty("d['innerField']", String.class); // value will be converted to needed type, if conversion is possible
97+
98+
assertEquals("inner object", nestedValue);
99+
100+
}
101+
}
102+
```
12103

13104
## Alternatives
14105
Here are two similar projects with answers about why they did not fit my needs:

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ apply plugin: "maven-publish"
88
apply plugin: "jacoco"
99

1010
group 'io.github.msangel'
11-
version '1.0.0-SNAPSHOT'
11+
version '1.0.3-SNAPSHOT'
1212

1313
sourceCompatibility = 1.8
1414
targetCompatibility = 1.8

src/main/java/ua/co/k/yaml2dotnotation/Base.java

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package ua.co.k.yaml2dotnotation;
22

33
import com.fasterxml.jackson.core.JsonParser;
4+
import com.fasterxml.jackson.core.JsonPointer;
45
import com.fasterxml.jackson.core.TreeNode;
56
import com.fasterxml.jackson.core.type.TypeReference;
67
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -25,8 +26,8 @@ public boolean hasProperty(String path) {
2526

2627
@Override
2728
public <T> T getProperty(String path, TypeReference<T> ref) {
28-
path = dotted2pointer(path);
29-
TreeNode node = this.treeNode.at(path);
29+
JsonPointer jsonPointer = new DottedPathLexer(path).convert();
30+
TreeNode node = this.treeNode.at(jsonPointer);
3031
if (node.isMissingNode()) {
3132
return null;
3233
}
@@ -38,9 +39,4 @@ public <T> T getProperty(String path, TypeReference<T> ref) {
3839
throw new RuntimeException("problem getting property", e);
3940
}
4041
}
41-
42-
// todo: https://tools.ietf.org/html/rfc6901
43-
private static String dotted2pointer(String in) {
44-
return "/"+String.join("/", in.split("\\."));
45-
}
4642
}

src/main/java/ua/co/k/yaml2dotnotation/DottedPropertiesInjector.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package ua.co.k.yaml2dotnotation;
22

33
import com.fasterxml.jackson.core.type.TypeReference;
4-
import ua.co.k.yaml2dotnotation.annot.Prop;
4+
import ua.co.k.yaml2dotnotation.annot.Value;
55

66
import java.beans.IntrospectionException;
77
import java.beans.PropertyDescriptor;
@@ -34,7 +34,7 @@ public static abstract class FieldInformation implements Consumer<DottedProperti
3434
final String path;
3535
final TypeReference<?> valueTypeRef;
3636

37-
public FieldInformation(String path, TypeReference<?> valueTypeRef){
37+
FieldInformation(String path, TypeReference<?> valueTypeRef){
3838
this.path = path;
3939
this.valueTypeRef = valueTypeRef;
4040
}
@@ -57,7 +57,7 @@ public static void injectAnnotatedFields(Object target, DottedProperties props)
5757
fieldsToInject.forEach(el -> el.accept(props));
5858
}
5959

60-
static Function<List<Field>, List<FieldInformation>> getCandidateFieldMapper(Object target) {
60+
private static Function<List<Field>, List<FieldInformation>> getCandidateFieldMapper(Object target) {
6161
return new Function<List<Field>, List<FieldInformation>>() {
6262
@Override
6363
public List<FieldInformation> apply(List<Field> fields) {
@@ -73,7 +73,7 @@ public List<FieldInformation> apply(List<Field> fields) {
7373

7474
private FieldInformation getFieldInformation(Field field) {
7575

76-
Prop annotation = field.getAnnotation(Prop.class);
76+
Value annotation = field.getAnnotation(Value.class);
7777
if (annotation == null) {
7878
return null;
7979
}
@@ -126,7 +126,7 @@ void acceptThrows(DottedProperties elem) throws Exception {
126126
};
127127
}
128128

129-
public static List<FieldInformation> getFields(Class<?> startClass, Function<List<Field>, List<FieldInformation>> mapperToSetters) {
129+
private static List<FieldInformation> getFields(Class<?> startClass, Function<List<Field>, List<FieldInformation>> mapperToSetters) {
130130

131131
List<FieldInformation> currentClassFields = mapperToSetters.apply(Arrays.asList(startClass.getDeclaredFields()));
132132

src/main/java/ua/co/k/yaml2dotnotation/annot/Prop.java renamed to src/main/java/ua/co/k/yaml2dotnotation/annot/Value.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@
1010
*/
1111
@Retention(RetentionPolicy.RUNTIME)
1212
@Target(ElementType.FIELD)
13-
public @interface Prop {
13+
public @interface Value {
1414
String value();
1515
}

src/test/java/ua/co/k/yaml2dotnotation/DottedPropertiesInjectorTest.java

Lines changed: 67 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
package ua.co.k.yaml2dotnotation;
22

3+
import com.fasterxml.jackson.annotation.JsonProperty;
4+
import com.fasterxml.jackson.core.type.TypeReference;
35
import org.junit.Test;
4-
import ua.co.k.yaml2dotnotation.annot.Prop;
6+
import ua.co.k.yaml2dotnotation.annot.Value;
7+
8+
import java.util.Objects;
59

610
import static org.junit.Assert.*;
711

@@ -10,16 +14,32 @@
1014
*/
1115
public class DottedPropertiesInjectorTest {
1216

17+
public static class InnerObject {
18+
@JsonProperty("innerField")
19+
public String a;
20+
21+
@Override
22+
public boolean equals(Object obj) {
23+
if (obj instanceof InnerObject) {
24+
return Objects.equals(this.a, ((InnerObject) obj).a);
25+
}
26+
return false;
27+
}
28+
}
29+
1330
public static class TestObjectFine {
14-
@Prop("a")
31+
@Value("a")
1532
public String as;
1633

17-
@Prop("b")
34+
@Value("b")
1835
private Integer bas;
1936

20-
@Prop("c")
37+
@Value("c")
2138
private Boolean das;
2239

40+
@Value("d")
41+
private InnerObject inner;
42+
2343
public void setBas(Integer bas) {
2444
this.bas = bas;
2545
}
@@ -35,23 +55,34 @@ public Boolean isDas() {
3555
public void setDas(Boolean das) {
3656
this.das = das;
3757
}
58+
59+
public InnerObject getInner() {
60+
return inner;
61+
}
62+
63+
public void setInner(InnerObject inner) {
64+
this.inner = inner;
65+
}
3866
}
3967

4068
@Test
4169
public void testInjectFine() {
42-
DottedProperties properties = Yaml2Props.create("{ a: 1, b: 3, c: true}");
70+
DottedProperties properties = Yaml2Props.create("{ a: 1, b: 3, c: true, d: { innerField : 'inner object'}}");
4371
TestObjectFine to = new TestObjectFine();
4472
DottedPropertiesInjector.injectAnnotatedFields(to, properties);
4573
assertEquals("1", to.as);
4674
assertEquals(3, (int)to.bas);
4775
assertTrue(to.isDas());
76+
// none that top-level properties use @Value annotation as this object is utilazed by our library
77+
// but for nested we have to use JsonProperty as problems of writing proper type for value is Jackson responsibility
78+
assertEquals("inner object", to.inner.a);
4879
}
4980

5081
public static class TestObjectInvalidPrivatFieldUsed {
51-
@Prop("a")
82+
@Value("a")
5283
public String as;
5384

54-
@Prop("b")
85+
@Value("b")
5586
private Integer bas;
5687
}
5788

@@ -64,10 +95,10 @@ public void testInjectPrivateError() {
6495
}
6596

6697
public static class TestObjectInvalidFinalFielsUsed {
67-
@Prop("a")
98+
@Value("a")
6899
public String as;
69100

70-
@Prop("b")
101+
@Value("b")
71102
private final Integer bas;
72103

73104
public TestObjectInvalidFinalFielsUsed() {
@@ -89,7 +120,7 @@ public void testInjectFinalError() {
89120

90121

91122
public static class MoreLevels extends TestObjectFine {
92-
@Prop("d")
123+
@Value("d")
93124
public String cas;
94125
}
95126

@@ -103,4 +134,30 @@ public void testInjectFineWithInheritance() {
103134
assertTrue(to.isDas());
104135
assertEquals("42", to.cas);
105136
}
137+
138+
@Test
139+
public void testGettingFine() {
140+
// yaml is superset of json, so we can use either of them
141+
DottedProperties properties = Yaml2Props.create("{ a: 1, b: 3, c: true, d: { innerField : 'inner object'}}");
142+
String a = properties.getProperty("a").asString();
143+
assertEquals("1", a);
144+
145+
Integer b = properties.getProperty("b").asInteger();
146+
assertEquals(3L, b.longValue());
147+
148+
InnerObject inner = properties.getProperty("d", new TypeReference<InnerObject>() {}); // can be generics
149+
InnerObject expectd = new InnerObject();
150+
expectd.a = "inner object";
151+
assertEquals(expectd, inner);
152+
153+
// all of them are valid and equal selectors:
154+
// d.innerField
155+
// d['innerField']
156+
// ['d'].innerField
157+
// ['d']['innerField']
158+
String nestedValue = properties.getProperty("d['innerField']", String.class); // value will be converted to needed type, if conversion is possible
159+
160+
assertEquals("inner object", nestedValue);
161+
162+
}
106163
}

0 commit comments

Comments
 (0)