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

com.owlike.genson.convert.ChainedFactory Maven / Gradle / Ivy

package com.owlike.genson.convert;

import java.lang.reflect.Type;

import com.owlike.genson.Converter;
import com.owlike.genson.Factory;
import com.owlike.genson.Genson;

/**
 * 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 * @see com.owlike.genson.convert.NullConverter NullConverter * @see com.owlike.genson.convert.BasicConvertersFactory BasicConvertersFactory * @see com.owlike.genson.Wrapper Wrapper */ public abstract class ChainedFactory implements Factory> { private Factory> next; protected ChainedFactory() { } protected ChainedFactory(Factory> next) { this.next = next; } public Converter create(Type type, Genson genson) { Converter nextConverter = null; if (next != null) { nextConverter = next.create(type, genson); } Converter converter = create(type, genson, nextConverter); return converter == null ? nextConverter : converter; } /** * This method will be called by {@link #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. * * @param type for which this factory must provide a converter * @param 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). * @param nextConverter created by the next factory, may be null. * @return null or a converter for this type */ protected abstract Converter create(Type type, Genson genson, Converter nextConverter); /** * 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). * * @param next factory * @return the next factory passed as argument */ public final >> T withNext(T next) { if (this.next != null) throw new IllegalStateException("next factory has already been set for " + getClass() + " you can not override it!"); this.next = next; return next; } /** * @return a reference to the next factory, may be null. */ public final Factory> next() { return next; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy