Skip to content

Commit be19a62

Browse files
committed
add ComplexValueConverter
1 parent bca6b48 commit be19a62

File tree

1 file changed

+168
-0
lines changed

1 file changed

+168
-0
lines changed
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
package me.hsgamer.topper.storage.simple.converter;
2+
3+
import org.jetbrains.annotations.NotNull;
4+
import org.jetbrains.annotations.Nullable;
5+
6+
import java.sql.ResultSet;
7+
import java.sql.SQLException;
8+
import java.util.*;
9+
import java.util.function.BiFunction;
10+
import java.util.function.Function;
11+
import java.util.function.Supplier;
12+
import java.util.regex.Pattern;
13+
14+
public class ComplexValueConverter<T> implements ValueConverter<T> {
15+
private final String rawStringSeparator;
16+
private final List<Entry<T>> entries;
17+
private final Supplier<T> constructor;
18+
private final String[] sqlColumns;
19+
private final String[] sqlColumnDefinitions;
20+
21+
private ComplexValueConverter(String rawStringSeparator, List<Entry<T>> entries, Supplier<T> constructor) {
22+
this.rawStringSeparator = rawStringSeparator;
23+
this.entries = Collections.unmodifiableList(entries);
24+
this.constructor = constructor;
25+
26+
List<String> sqlColumns = new ArrayList<>();
27+
List<String> sqlColumnDefinitions = new ArrayList<>();
28+
for (Entry<T> entry : entries) {
29+
String[] columns = entry.converter.getSqlColumns();
30+
String[] columnDefinitions = entry.converter.getSqlColumnDefinitions();
31+
sqlColumns.addAll(Arrays.asList(columns));
32+
sqlColumnDefinitions.addAll(Arrays.asList(columnDefinitions));
33+
}
34+
this.sqlColumns = sqlColumns.toArray(new String[0]);
35+
this.sqlColumnDefinitions = sqlColumnDefinitions.toArray(new String[0]);
36+
}
37+
38+
@Override
39+
public @NotNull String toRawString(@NotNull T value) {
40+
StringJoiner joiner = new StringJoiner(rawStringSeparator);
41+
for (Entry<T> entry : entries) {
42+
String rawString = entry.converter.toRawString(entry.getter.apply(value));
43+
joiner.add(rawString);
44+
}
45+
return joiner.toString();
46+
}
47+
48+
@Override
49+
public @Nullable T fromRawString(@NotNull String value) {
50+
String[] values = value.split(Pattern.quote(rawStringSeparator));
51+
if (values.length != entries.size()) {
52+
return null;
53+
}
54+
T instance = constructor.get();
55+
for (int i = 0; i < values.length; i++) {
56+
Entry<T> entry = entries.get(i);
57+
Object objectValue = entry.converter.fromRawString(values[i]);
58+
if (objectValue == null) {
59+
return null;
60+
}
61+
instance = entry.setter.apply(instance, objectValue);
62+
}
63+
return instance;
64+
}
65+
66+
@Override
67+
public @NotNull Map<String, Object> toObjectMap(@NotNull T value) {
68+
Map<String, Object> map = new LinkedHashMap<>();
69+
for (Entry<T> entry : entries) {
70+
map.putAll(entry.converter.toObjectMap(entry.getter.apply(value)));
71+
}
72+
return map;
73+
}
74+
75+
@Override
76+
public @Nullable T fromObjectMap(@NotNull Map<String, Object> map) {
77+
T instance = constructor.get();
78+
for (Entry<T> entry : entries) {
79+
Object objectValue = entry.converter.fromObjectMap(map);
80+
if (objectValue == null) {
81+
return null;
82+
}
83+
instance = entry.setter.apply(instance, objectValue);
84+
}
85+
return instance;
86+
}
87+
88+
@Override
89+
public String[] getSqlColumns() {
90+
return sqlColumns;
91+
}
92+
93+
@Override
94+
public String[] getSqlColumnDefinitions() {
95+
return sqlColumnDefinitions;
96+
}
97+
98+
@Override
99+
public Object[] toSqlValues(@NotNull T value) {
100+
List<Object> values = new ArrayList<>();
101+
for (Entry<T> entry : entries) {
102+
Object[] objectValues = entry.converter.toSqlValues(entry.getter.apply(value));
103+
values.addAll(Arrays.asList(objectValues));
104+
}
105+
return values.toArray(new Object[0]);
106+
}
107+
108+
@Override
109+
public @Nullable T fromSqlResultSet(@NotNull ResultSet resultSet) throws SQLException {
110+
T instance = constructor.get();
111+
for (Entry<T> entry : entries) {
112+
Object objectValue = entry.converter.fromSqlResultSet(resultSet);
113+
if (objectValue == null) {
114+
return null;
115+
}
116+
instance = entry.setter.apply(instance, objectValue);
117+
}
118+
return instance;
119+
}
120+
121+
private static class Entry<T> {
122+
private final ValueConverter<Object> converter;
123+
private final Function<T, Object> getter;
124+
private final BiFunction<T, Object, T> setter;
125+
126+
private Entry(ValueConverter<Object> converter, Function<T, Object> getter, BiFunction<T, Object, T> setter) {
127+
this.converter = converter;
128+
this.getter = getter;
129+
this.setter = setter;
130+
}
131+
}
132+
133+
public static class Builder<T> {
134+
private final List<Entry<T>> entries = new ArrayList<>();
135+
private String rawStringSeparator = "||";
136+
private Supplier<T> constructor;
137+
138+
public Builder<T> rawStringSeparator(String rawStringSeparator) {
139+
this.rawStringSeparator = rawStringSeparator;
140+
return this;
141+
}
142+
143+
public Builder<T> constructor(Supplier<T> constructor) {
144+
this.constructor = constructor;
145+
return this;
146+
}
147+
148+
@SuppressWarnings("unchecked")
149+
public <V> Builder<T> entry(ValueConverter<T> converter, Function<T, V> getter, BiFunction<T, V, T> setter) {
150+
ValueConverter<Object> objectConverter = (ValueConverter<Object>) converter;
151+
Function<T, Object> objectGetter = (Function<T, Object>) getter;
152+
BiFunction<T, Object, T> objectSetter = (BiFunction<T, Object, T>) setter;
153+
Entry<T> entry = new Entry<>(objectConverter, objectGetter, objectSetter);
154+
entries.add(entry);
155+
return this;
156+
}
157+
158+
public ComplexValueConverter<T> build() {
159+
if (constructor == null) {
160+
throw new IllegalStateException("Constructor is not set");
161+
}
162+
if (entries.isEmpty()) {
163+
throw new IllegalStateException("Entries are empty");
164+
}
165+
return new ComplexValueConverter<>(rawStringSeparator, entries, constructor);
166+
}
167+
}
168+
}

0 commit comments

Comments
 (0)