Subversion Repositories bacoAlunos

Rev

Rev 1969 | Blame | Compare with Previous | Last modification | View Log | RSS feed

package com.owlike.genson.convert;

import java.lang.reflect.Type;

import com.owlike.genson.Context;
import com.owlike.genson.Converter;
import com.owlike.genson.Genson;
import com.owlike.genson.JsonBindingException;
import com.owlike.genson.Serializer;
import com.owlike.genson.Wrapper;
import com.owlike.genson.annotation.HandleNull;
import com.owlike.genson.reflect.TypeUtil;
import com.owlike.genson.stream.ObjectReader;
import com.owlike.genson.stream.ObjectWriter;
import com.owlike.genson.stream.ValueType;

/**
 * The default implementation handles null values by returning the predefined default value if any or null during
 * deserialization and by calling writer.writeNull() during serialization.
 * <p/>
 *
 * @author eugen
 */

public class NullConverterFactory extends ChainedFactory {
  private final boolean failOnNullPrimitive;

  public NullConverterFactory(boolean failOnNullPrimitive) {
    this.failOnNullPrimitive = failOnNullPrimitive;
  }

  private class FailIfNullConverter<T> extends Wrapper<Converter<T>> implements Converter<T> {
    public FailIfNullConverter(Converter<T> delegate) {
      super(delegate);
    }

    @1.5.0/docs/api/java/lang/Override.html">Override
    public void serialize(T object, ObjectWriter writer, 5+0%2Fdocs%2Fapi+Context">Context ctx) throws 1.5.0/docs/api/java/lang/Exception.html">Exception {
      if (object == null) {
        throw new JsonBindingException("Serialization of null primitives is forbidden");
      } else {
        wrapped.serialize(object, writer, ctx);
      }
    }

    @1.5.0/docs/api/java/lang/Override.html">Override
    public T deserialize(ObjectReader reader, 5+0%2Fdocs%2Fapi+Context">Context ctx) throws 1.5.0/docs/api/java/lang/Exception.html">Exception {
      if (ValueType.NULL == reader.getValueType()) {
        throw new JsonBindingException("Can not deserialize null to a primitive type");
      } else {
        return wrapped.deserialize(reader, ctx);
      }
    }
  }

  // TODO check if making the delegate instance final would improve perfs
  private class NullConverterWrapper<T> extends Wrapper<Converter<T>> implements
    Converter<T> {
    private final T defaultValue;

    public NullConverterWrapper(T defaultValue, Converter<T> converter) {
      super(converter);
      this.defaultValue = defaultValue;
    }

    public void serialize(T obj, ObjectWriter writer, 5+0%2Fdocs%2Fapi+Context">Context ctx) throws 1.5.0/docs/api/java/lang/Exception.html">Exception {
      if (obj == null) {
        writer.writeNull();
      } else {
        wrapped.serialize(obj, writer, ctx);
      }
    }

    public T deserialize(ObjectReader reader, 5+0%2Fdocs%2Fapi+Context">Context ctx) throws 1.5.0/docs/api/java/lang/Exception.html">Exception {
      if (ValueType.NULL == reader.getValueType()) {
        return defaultValue;
      } else {
        return wrapped.deserialize(reader, ctx);
      }
    }
  }

  @1.5.0/docs/api/java/lang/SuppressWarnings.html">SuppressWarnings({"unchecked", "rawtypes"})
  @1.5.0/docs/api/java/lang/Override.html">Override
  protected Converter<?> create(1.5.0/docs/api/java/lang/reflect/Type.html">Type type, Genson genson, Converter<?> nextConverter) {
    if (Wrapper.toAnnotatedElement(nextConverter).isAnnotationPresent(HandleNull.class)) {
      return nextConverter;
    } else {
      Class<?> rawClass = TypeUtil.getRawClass(type);
      if (failOnNullPrimitive && rawClass.isPrimitive()) {
        return new FailIfNullConverter(nextConverter);
      } else {
        return new NullConverterWrapper(genson.defaultValue(rawClass), nextConverter);
      }
    }
  }
}