package de.anycook.db.drafts.mongo.codecs;
import de.anycook.drafts.IngredientDraft;
import de.anycook.drafts.RecipeDraft;
import de.anycook.drafts.StepDraft;
import de.anycook.recipe.Time;
import org.bson.BsonReader;
import org.bson.BsonType;
import org.bson.BsonWriter;
import org.bson.codecs.Codec;
import org.bson.codecs.DecoderContext;
import org.bson.codecs.EncoderContext;
import org.bson.codecs.configuration.CodecRegistry;
import org.bson.types.ObjectId;
import java.util.ArrayList;
import java.util.List;
public class RecipeDraftCodec implements Codec<RecipeDraft> {
private final Codec<IngredientDraft> ingredientDraftCodec;
private final Codec<StepDraft> stepDraftCodec;
private final Codec<Time> timeCodec;
public RecipeDraftCodec(final CodecRegistry codecRegistry) {
this.ingredientDraftCodec = codecRegistry.get(IngredientDraft.class);
this.stepDraftCodec = codecRegistry.get(StepDraft.class);
this.timeCodec = codecRegistry.get(Time.class);
}
@Override
public RecipeDraft decode(final BsonReader reader, final DecoderContext decoderContext) {
final RecipeDraft draft = new RecipeDraft();
reader.readStartDocument();
while (reader.readBsonType() != BsonType.END_OF_DOCUMENT) {
final String name = reader.readName();
switch (name) {
case "userId":
draft.setUserId(reader.readInt32());
break;
case "_id":
draft.setId(reader.readObjectId().toString());
break;
case "timestamp":
draft.setTimestamp(reader.readInt64());
break;
case "description":
draft.setDescription(reader.readString());
break;
case "image":
draft.setImage(reader.readString());
break;
case "name":
draft.setName(reader.readString());
break;
case "persons":
draft.setPersons(reader.readInt32());
break;
case "category":
draft.setCategory(reader.readString());
break;
case "skill":
draft.setSkill(reader.readInt32());
break;
case "calorie":
draft.setCalorie(reader.readInt32());
break;
case "percentage":
draft.setPercentage(reader.readDouble());
break;
case "time":
final Time time = timeCodec.decode(reader, decoderContext);
draft.setTime(time);
break;
case "ingredients":
final List<IngredientDraft> ingredientDrafts = new ArrayList<>();
reader.readStartArray();
while (reader.readBsonType() != BsonType.END_OF_DOCUMENT) {
ingredientDrafts.add(ingredientDraftCodec.decode(reader, decoderContext));
}
draft.setIngredients(ingredientDrafts);
reader.readEndArray();
break;
case "steps":
final List<StepDraft> stepDrafts = new ArrayList<>();
reader.readStartArray();
while (reader.readBsonType() != BsonType.END_OF_DOCUMENT) {
stepDrafts.add(stepDraftCodec.decode(reader, decoderContext));
}
draft.setSteps(stepDrafts);
reader.readEndArray();
break;
case "tags":
final List<String> tags = new ArrayList<>();
reader.readStartArray();
while (reader.readBsonType() != BsonType.END_OF_DOCUMENT) {
tags.add(reader.readString());
}
draft.setTags(tags);
reader.readEndArray();
break;
default:
throw new RuntimeException(String.format("Unknown key: %s", name));
}
}
reader.readEndDocument();
return draft;
}
@Override
public void encode(final BsonWriter writer, final RecipeDraft value,
final EncoderContext encoderContext) {
writer.writeStartDocument();
writer.writeInt32("userId", value.getUserId());
final String id = value.getId();
if (id != null) {
writer.writeObjectId("_id", new ObjectId(id));
}
final Long timestamp = value.getTimestamp();
if (timestamp != null) {
writer.writeInt64("timestamp", timestamp);
}
final String image = value.getImage();
if (image != null) {
writer.writeString("image", image);
}
final String name = value.getName();
if (name != null) {
writer.writeString("name", name);
}
final String description = value.getDescription();
if (description != null) {
writer.writeString("description", description);
}
final Integer persons = value.getPersons();
if (persons != null) {
writer.writeInt32("persons", persons);
}
final String category = value.getCategory();
if (category != null) {
writer.writeString("category", category);
}
final Integer skill = value.getSkill();
if (skill != null) {
writer.writeInt32("skill", skill);
}
final Integer calorie = value.getCalorie();
if (calorie != null) {
writer.writeInt32("calorie", calorie);
}
final Time time = value.getTime();
if (time != null) {
writer.writeName("time");
encoderContext.encodeWithChildContext(timeCodec, writer, time);
}
final List<IngredientDraft> ingredients = value.getIngredients();
if (ingredients != null) {
writer.writeStartArray("ingredients");
ingredients.forEach(x -> encoderContext.encodeWithChildContext(
ingredientDraftCodec, writer, x));
writer.writeEndArray();
}
final List<StepDraft> steps = value.getSteps();
if (steps != null) {
writer.writeStartArray("steps");
steps.forEach(x -> encoderContext.encodeWithChildContext(stepDraftCodec, writer, x));
writer.writeEndArray();
}
final List<String> tags = value.getTags();
if (tags != null) {
writer.writeStartArray("tags");
value.getTags().forEach(writer::writeString);
writer.writeEndArray();
}
writer.writeEndDocument();
}
@Override
public Class<RecipeDraft> getEncoderClass() {
return RecipeDraft.class;
}
}