Class ChainedFactory

  • All Implemented Interfaces:
    Factory<Converter<?>>
    Direct Known Subclasses:
    BeanViewConverter.BeanViewConverterFactory, CircularClassReferenceConverterFactory, ClassMetadataConverter.ClassMetadataConverterFactory, MissingClassConverter.Factory, NullConverterFactory, RuntimeTypeConverter.RuntimeTypeConverterFactory, SerializationSupportConverter.Factory

    public abstract class ChainedFactory
    extends Object
    implements Factory<Converter<?>>
    A chained factory of Converters that gives the ability to implementations to decorate the converter created by the next factory.

    One of Genson big strengths is its extensive use of Decorator and Chain of Responsibility design patterns. Chain of responsibility is applied in chaining Factories that can build Decorated Converters. ChainedFactory is the base class for such factories. But as ChainedFactory next element is an instance of Factory, you are free to apply the chain principle for your custom factories differently if you want.

    The global idea behind this design is to provide great extensibility to the library by allowing to add new functionalities to existing converters in a non intrusive way (extension and source modification). This is achieved by applying the decorator pattern. Here is an example of a decorated converter that adds null handling support.

     public class NullConverter extends Wrapper<Converter<Object>> implements
                    Converter<Object> {
            private final Converter<Object> converter;
    
            public NullConverter(Converter<Object> converter) {
                    super(converter);
                    this.converter = converter;
      }
    
            public void serialize(Object obj, ObjectWriter writer, Context ctx) {
                    if (obj == null)
                            writer.writeNull();
                    else
                            converter.serialize(obj, writer, ctx);
      }
    
            public Object deserialize(ObjectReader reader, Context ctx) {
                    if (TypeValue.NULL == reader.getTypeValue()) {
                            return null;
        } else
                            return converter.deserialize(reader, ctx);
    
      }
     }
    
     // now we need a factory to create the nullconverter for type T and wire it with the existing
     // factories so we can get an instance of the converter for that type.
     public class NullConverterFactory extends ChainedFactory {
            public NullConverterFactory(Factory<Converter<?>> next) {
                    super(next);
      }
    
            public Converter<?> create(Type type, Genson genson, Converter<?> nextConverter) {
                    return new NullConverter(nextConverter);
      }
     }
     

    As you can see it is pretty simple but also powerful. Note that our NullConverter extends Wrapper class. When you encapsulate converters you should extend Wrapper class this way Genson can access the class information of wrapped converters. Imagine for example that you put some annotation on converter A and wrap it in converter B, now if you wrap B in C you wont be able to get class information of A (ex: its annotations). Wrapper class allows to merge class information of current implementation and the wrapped one.

    Author:
    Eugen Cepoi
    See Also:
    NullConverterFactory, BasicConvertersFactory, Wrapper
    • Constructor Detail

      • ChainedFactory

        protected ChainedFactory()
    • Method Detail

      • create

        public Converter<?> create​(Type type,
                                   Genson genson)
        Description copied from interface: Factory
        Implementations of this method must try to create an instance of type T based on the parameter "type". If this factory can not create an object of type T for parameter type then it must return null.
        Specified by:
        create in interface Factory<Converter<?>>
        Parameters:
        type - used to build an instance of T.
        Returns:
        null if it doesn't support this type or an instance of T (or a subclass).
      • create

        protected abstract Converter<?> create​(Type type,
                                               Genson genson,
                                               Converter<?> nextConverter)
        This method will be called by create(Type, Genson) with nextConverter being the converter created for current type by the next factory. This means that ChainedFactory will first create a converter with the next factory and then use it's own create method.
        Parameters:
        type - for which this factory must provide a converter
        genson - instance that you can use when you need a converter for some other type (for example a converter of List<Integer> will need a converter for Integer type).
        nextConverter - created by the next factory, may be null.
        Returns:
        null or a converter for this type
      • withNext

        public final <T extends Factory<? extends Converter<?>>> T withNext​(T next)
        Chains this factory with next and returns next (the tail) so you can do things like chain1.withNext(new chain2).withNext(new chain3); the resulting chain is chain1=>chain2=>chain3. Don't forget to keep a reference to the head (chain1).
        Parameters:
        next - factory
        Returns:
        the next factory passed as argument
      • append

        public final <T extends Factory<? extends Converter<?>>> T append​(T next)
      • next

        public final Factory<? extends Converter<?>> next()
        Returns:
        a reference to the next factory, may be null.