1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
package design.persistence;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.util.DefaultIndenter;
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
import design.model.Club;
import design.model.Course;
import design.model.Golfer;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
public class JSONPersonalDatabase implements PersonalDatabase {
private static JSONPersonalDatabase INSTANCE;
public static JSONPersonalDatabase instance() {
if (INSTANCE == null) {
INSTANCE = new JSONPersonalDatabase("data/personaldb.json");
}
return INSTANCE;
}
private final Map<String, Golfer> cache;
private final ObjectMapper mapper;
private final File file;
private JSONPersonalDatabase(String filename) {
this.file = new File(filename);
this.cache = new HashMap<>();
this.mapper = new ObjectMapper();
// TODO: Once the saved JSON matches the model, consider removing.
// TEMP: tolerate unknown props while the model stabilizes
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
SimpleModule module = new SimpleModule();
module.addDeserializer(Course.class, new CourseIdDeserializer());
module.addSerializer(Course.class, new CourseIdSerializer());
mapper.registerModule(module);
mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
mapper.registerModule(new ParameterNamesModule(JsonCreator.Mode.PROPERTIES));
mapper.registerModule(new JavaTimeModule());
try {
load();
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
private void load() throws IOException {
Golfer[] data = mapper.readValue(file, Golfer[].class);
cache.clear();
for (Golfer i : data) {
cache.put(i.getUsername(), i);
}
}
private void save() throws IOException {
Golfer[] data = cache.values().toArray(Golfer[]::new);
mapper.writer(new CustomPrettyPrinter()).writeValue(file, data);
}
// turns that collection into a real array of golfers
@Override
public Golfer[] getGolfers() {
return cache.values().toArray(Golfer[]::new);
}
@Override
public Golfer getGolfer(String username) {
return cache.get(username);
}
@Override
public void addGolfer(Golfer golfer) throws IOException {
cache.putIfAbsent(golfer.getUsername(), golfer);
save();
}
@Override
public void removeGolfer(Golfer golfer) throws IOException {
cache.remove(golfer.getUsername());
save();
}
@Override
public void updateGolfer(Golfer golfer) throws IOException {
cache.put(golfer.getUsername(), golfer);
save();
}
private static class CourseIdSerializer extends JsonSerializer<Course> {
@Override
public void serialize(Course course, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeNumber(course.getId());
}
}
private static class CourseIdDeserializer extends JsonDeserializer<Course> {
MasterDatabase masterDB = MasterDatabase.instance();
@Override
public Course deserialize(JsonParser p, DeserializationContext context) throws IOException {
int id = p.getValueAsInt();
return masterDB.getCourse(id);
}
}
private static class CustomPrettyPrinter extends DefaultPrettyPrinter {
public CustomPrettyPrinter() {
super._arrayIndenter = new DefaultIndenter();
super._objectFieldValueSeparatorWithSpaces = _separators.getObjectFieldValueSeparator() + " ";
super._arrayEmptySeparator = "";
}
@Override
public CustomPrettyPrinter createInstance() {
return new CustomPrettyPrinter();
}
}
}
|