All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.bild.codec.PolymorphicCodec Maven / Gradle / Ivy

Go to download

A very fast POJO codec for MongoDB (used in conjunction with the Mongo Java Driver) that handles generic types as well as polymorphic class hierarchies

There is a newer version: 2.8.2
Show newest version
package de.bild.codec;

import org.bson.BsonReader;
import org.bson.BsonReaderMark;
import org.bson.BsonType;
import org.bson.BsonWriter;
import org.bson.codecs.DecoderContext;
import org.bson.codecs.EncoderContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Set;

/**
 * Provides functionality for handling polymorphic structures.
 * decode() as well as encode() have default implementations within this interface.
 * 

* Attention: The name of this interface may be misleading. * Any Codec that might be part of a polymorphic codec structure needs to implement this interface, * as the codec needs to answer certain questions, most obviously {@link #verifyFieldsNotNamedLikeAnyDiscriminatorKey} * A map of {@link PolymorphicCodec} is part of {@link PolymorphicReflectionCodec} which itself does not implement {@link PolymorphicCodec} * * @param the value type */ public interface PolymorphicCodec extends TypeCodec { Logger LOGGER = LoggerFactory.getLogger(PolymorphicCodec.class); /* * When encoding polymorphic types, a discriminator must be written to the database along with the instance. * Instead of restructuring the json within the database, the discriminator key/value will be written at the same * json level as the instance data. Nesting the instance data in a deeper level may complicate things in the database, * especially if you store non-polymorphic entities together with polymorphic entities in one collection and if * you need to set an index at a specific field these entities have in common. * * Hence provide methods for encoding all entity fields as well as one for decoding just the fields. The wrapping * curly brackets will be written along with the discriminator in encode() * */ T decodeFields(BsonReader reader, DecoderContext decoderContext, T instance); void encodeFields(BsonWriter writer, T instance, EncoderContext encoderContext); T newInstance(); @Override default T decode(BsonReader reader, DecoderContext decoderContext) { BsonReaderMark mark = null; /* TODO: need fix for https://jira.mongodb.org/browse/JAVA-2754 to implement backoff strategy. */ // try { // mark = reader.getMark(); T newInstance; if (reader.getCurrentBsonType() == null || reader.getCurrentBsonType() == BsonType.DOCUMENT) { reader.readStartDocument(); newInstance = decodeFields(reader, decoderContext, newInstance()); reader.readEndDocument(); return newInstance; } else { LOGGER.error("Expected to read document but reader is in state {}. Skipping value!", reader.getCurrentBsonType()); reader.skipValue(); return null; } // } catch (Exception e) { // LOGGER.error("Exception while reading pojo from reader. Skipping value.", e); // // /** // * in case the current pojo can be decoded due to errors, the codec will skip the current entity from the reader and returns null. // * The user can then react accordingly. // * TODO: Maybe it can be achieved to throw an unchecked exception with additional information on why the decoding failed. // * TODO: The question is: how would the user handle this exception and proceed with the stream? // */ // // if (mark != null) { // mark.reset(); // reader.skipValue(); // } // } // return null; } @Override default void encode(BsonWriter writer, T value, EncoderContext encoderContext) { if (value == null) { writer.writeNull(); } else { writer.writeStartDocument(); encodeFields(writer, value, encoderContext); writer.writeEndDocument(); } } /** * A check for properties with names equal to any of the identified discriminator keys * * @param discriminatorKeys the identified discriminator keys * throws an {@link IllegalArgumentException} if a name of an internally used property is equal to one of the discriminator keys */ void verifyFieldsNotNamedLikeAnyDiscriminatorKey(Set discriminatorKeys) throws IllegalArgumentException; }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy