package com.codepoetics.octarine.json.serialisation;
import com.codepoetics.octarine.records.Key;
import com.codepoetics.octarine.records.Record;
import com.fasterxml.jackson.core.JsonGenerator;
import org.pcollections.PVector;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Supplier;
public final class RecordSerialiser implements SafeSerialiser<Record> {
public static Builder builder() {
return new Builder();
}
public static final class Builder implements Supplier<RecordSerialiser> {
private final Map<Key<?>, BiConsumer<JsonGenerator, ?>> serialiserMap = new LinkedHashMap<>();
public <V> Builder write(Key<? extends V> key, String fieldName, BiConsumer<JsonGenerator, ? super V> serialiser) {
BiConsumer<JsonGenerator, ? extends V> keyValueWriter = (JsonGenerator generator, V value) -> {
try {
generator.writeFieldName(fieldName);
serialiser.accept(generator, value);
} catch (IOException e) {
throw new SerialisationException(e);
}
};
serialiserMap.put(key, keyValueWriter);
return this;
}
public <V> Builder write(Key<? extends V> key, BiConsumer<JsonGenerator, ? super V> serialiser) {
return write(key, key.name(), serialiser);
}
public <V> Builder write(Key<? extends V> key, Supplier<BiConsumer<JsonGenerator, ? super V>> serialiserSupplier) {
return write(key, serialiserSupplier.get());
}
public <V> Builder write(Key<? extends V> key, String fieldName, Supplier<BiConsumer<JsonGenerator, ? super V>> serialiserSupplier) {
return write(key, fieldName, serialiserSupplier.get());
}
public Builder writeString(Key<String> key) {
return write(key, Serialisers.toString);
}
public Builder writeString(Key<String> key, String fieldName) {
return write(key, fieldName, Serialisers.toString);
}
public <V> Builder writeToString(Key<V> key) {
return writeToString(key, Object::toString);
}
public <V> Builder writeToString(Key<V> key, String fieldName) {
return writeToString(key, fieldName, Object::toString);
}
public <V> Builder writeToString(Key<V> key, Function<V, String> converter) {
return writeToString(key, key.name(), converter);
}
public <V> Builder writeToString(Key<V> key, String fieldName, Function<V, String> converter) {
return write(key, fieldName, (g, v) -> Serialisers.toString.accept(g, converter.apply(v)));
}
public Builder writeInteger(Key<Integer> key) {
return write(key, Serialisers.toInteger);
}
public Builder writeInteger(Key<Integer> key, String fieldName) {
return write(key, fieldName, Serialisers.toInteger);
}
public Builder writeDouble(Key<Double> key) {
return write(key, Serialisers.toDouble);
}
public Builder writeDouble(Key<Double> key, String fieldName) {
return write(key, fieldName, Serialisers.toDouble);
}
public Builder writeLong(Key<Long> key) {
return write(key, Serialisers.toLong);
}
public Builder writeLong(Key<Long> key, String fieldName) {
return write(key, fieldName, Serialisers.toLong);
}
public Builder writeBoolean(Key<Boolean> key) {
return write(key, Serialisers.toBoolean);
}
public Builder writeBoolean(Key<Boolean> key, String fieldName) {
return write(key, fieldName, Serialisers.toBoolean);
}
public <V> Builder writeList(Key<PVector<V>> key, Serialiser<V> itemSerialiser) {
return write(key, ListSerialiser.writingItemsWith(itemSerialiser));
}
public <V> Builder writeList(Key<PVector<V>> key, String fieldName, Serialiser<V> itemSerialiser) {
return write(key, fieldName, ListSerialiser.writingItemsWith(itemSerialiser));
}
public <V> Builder writeMap(Key<Map<String, V>> key, Serialiser<V> valueSerialiser) {
return write(key, MapSerialiser.writingValuesWith(valueSerialiser));
}
public <V> Builder writeMap(Key<Map<String, V>> key, String fieldName, Serialiser<V> valueSerialiser) {
return write(key, fieldName, MapSerialiser.writingValuesWith(valueSerialiser));
}
@Override
public RecordSerialiser get() {
return new RecordSerialiser(serialiserMap);
}
}
private final Map<Key<?>, BiConsumer<JsonGenerator, ?>> serialiserMap;
public RecordSerialiser(Map<Key<?>, BiConsumer<JsonGenerator, ?>> serialiserMap) {
this.serialiserMap = serialiserMap;
}
@Override
public void unsafeAccept(JsonGenerator generator, Record record) throws IOException {
generator.writeStartObject();
serialiserMap.keySet().forEach(k ->
k.get(record).ifPresent(value ->
((BiConsumer<JsonGenerator, Object>) serialiserMap.get(k)).accept(generator, value)
));
generator.writeEndObject();
}
}