public abstract class BooleanTinyType {

    public final boolean value;

    /**
     * Wrapping ctor.
     *
     * @param value the native value to be wrapped.
     */
    public BooleanTinyType(boolean value) {
        this.value = value;
    }

    @Override
    public int hashCode() {
        return value ? 1231 : 1237; //as per implementation of Boolean::hashCode(boolean) in jdk8.0.45
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final BooleanTinyType other = (BooleanTinyType) obj;
        return this.value == other.value;
    }

    /**
     * Get a String representation of this TinyType. Please note that this is
     * not meant to be a "stringification" of the boxed value.
     *
     * @return A type-informative, value-informative representation of this
     * TinyType instance.
     */
    @Override
    public String toString() {
        return String.format("%s#%s", this.getClass().getSimpleName(), value);
    }

} public abstract class ByteTinyType {

    public final byte value;

    /**
     * Wrapping ctor.
     *
     * @param value the native value to be wrapped.
     */
    public ByteTinyType(byte value) {
        this.value = value;
    }

    @Override
    public int hashCode() {
        return (int) value; //as per implementation of Byte::hashCode(byte) in jdk8.0.45
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final ByteTinyType other = (ByteTinyType) obj;
        return this.value == other.value;
    }

    /**
     * Get a String representation of this TinyType. Please note that this is
     * not meant to be a "stringification" of the boxed value.
     *
     * @return A type-informative, value-informative representation of this
     * TinyType instance.
     */
    @Override
    public String toString() {
        return String.format("%s#%s", this.getClass().getSimpleName(), value);
    }
} public abstract class IntTinyType {

    public final int value;

    /**
     * Wrapping ctor.
     *
     * @param value the native value to be wrapped.
     */
    public IntTinyType(int value) {
        this.value = value;
    }

    @Override
    public int hashCode() {
        return value;  //as per implementation of Integer::hashCode(int) in jdk8.0.45
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final IntTinyType other = (IntTinyType) obj;
        return this.value == other.value;
    }

    /**
     * Get a String representation of this TinyType. Please note that this is
     * not meant to be a "stringification" of the boxed value.
     *
     * @return A type-informative, value-informative representation of this
     * TinyType instance.
     */
    @Override
    public String toString() {
        return String.format("%s#%s", this.getClass().getSimpleName(), value);
    }

} public abstract class LongTinyType {

    public final long value;

    /**
     * Wrapping ctor.
     *
     * @param value the native value to be wrapped.
     */
    public LongTinyType(long value) {
        this.value = value;
    }

    @Override
    public int hashCode() {
        return (int) (value ^ (value >>> 32)); //as per implementation of Long::hashCode(long) in jdk8.0.45
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final LongTinyType other = (LongTinyType) obj;
        return this.value == other.value;
    }

    /**
     * Get a String representation of this TinyType. Please note that this is
     * not meant to be a "stringification" of the boxed value.
     *
     * @return A type-informative, value-informative representation of this
     * TinyType instance.
     */
    @Override
    public String toString() {
        return String.format("%s#%s", this.getClass().getSimpleName(), value);
    }

} public abstract class ShortTinyType {

    public final short value;

    /**
     * Wrapping ctor.
     *
     * @param value the native value to be wrapped.
     */
    public ShortTinyType(short value) {
        this.value = value;
    }

    @Override
    public int hashCode() {
        return (int) value; //as per implementation of Short::hashCode(short) in jdk8.0.45
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final ShortTinyType other = (ShortTinyType) obj;
        return this.value == other.value;
    }

    /**
     * Get a String representation of this TinyType. Please note that this is
     * not meant to be a "stringification" of the boxed value.
     *
     * @return A type-informative, value-informative representation of this
     * TinyType instance.
     */
    @Override
    public String toString() {
        return String.format("%s#%s", this.getClass().getSimpleName(), value);
    }

} public abstract class StringTinyType {

    public final String value;

    /**
     * Wrapping ctor.
     *
     * @param value the native value to be wrapped.
     * @throws IllegalArgumentException for a null value.
     */
    public StringTinyType(String value) {
        if (value == null) {
            throw new IllegalArgumentException("a StringTinyType cannot have a null value");
        }
        this.value = value;
    }

    @Override
    public int hashCode() {
        return value.hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final StringTinyType other = (StringTinyType) obj;
        return this.value.equals(other.value);
    }

    /**
     * Get a String representation of this TinyType. Please note that this is
     * not meant to be a "stringification" of the boxed value.
     *
     * @return A type-informative, value-informative representation of this
     * TinyType instance.
     */
    @Override
    public String toString() {
        return String.format("%s#%s", this.getClass().getSimpleName(), value);
    }

} public class BooleanTinyTypes implements MetaTinyType<BooleanTinyType> {

    public static boolean includes(Class<?> candidate) {
        if (candidate == null) {
            return false;
        }

        return BooleanTinyType.class.equals(candidate.getSuperclass());
    }

    @Override
    public boolean isMetaOf(Class<?> candidate) {
        if (candidate == null) {
            return false;
        }
        return BooleanTinyType.class.equals(candidate.getSuperclass());
    }

    @Override
    public String stringify(BooleanTinyType value) {
        if (value == null) {
            throw new IllegalArgumentException("value must be not null");
        }
        return Boolean.toString(value.value);
    }

    @Override
    public <U extends BooleanTinyType> U newInstance(Class<U> type, Object value) {
        if (type == null || !includes(type)) {
            throw new IllegalArgumentException(String.format("Not a %s: %s", BooleanTinyType.class.getSimpleName(), type == null ? "null" : type.getCanonicalName()));
        }
        try {
            return type.getConstructor(boolean.class).newInstance(value);
        } catch (IllegalAccessException | InvocationTargetException ex) {
            throw new RuntimeException(ex);
        } catch (InstantiationException | NoSuchMethodException | ClassCastException ex) {
            throw new IllegalArgumentException(ex);
        }
    }

    @Override
    public <U extends BooleanTinyType> U fromString(Class<U> type, String value) {
        if (value == null) {
            throw new IllegalArgumentException("value must be not null");
        }
        return newInstance(type, Boolean.parseBoolean(value));
    }

} public class ByteTinyTypes implements MetaTinyType<ByteTinyType> {

    public static boolean includes(Class<?> candidate) {
        if (candidate == null) {
            return false;
        }
        return ByteTinyType.class.equals(candidate.getSuperclass());
    }

    @Override
    public boolean isMetaOf(Class<?> candidate) {
        if (candidate == null) {
            return false;
        }
        return ByteTinyType.class.equals(candidate.getSuperclass());
    }

    @Override
    public String stringify(ByteTinyType value) {
        if (value == null) {
            throw new IllegalArgumentException("value must be not null");
        }
        return Byte.toString(value.value);
    }

    @Override
    public <U extends ByteTinyType> U newInstance(Class<U> type, Object value) {
        if (type == null || !includes(type)) {
            throw new IllegalArgumentException(String.format("Not a %s: %s", ByteTinyType.class.getSimpleName(), type == null ? "null" : type.getCanonicalName()));
        }
        try {
            return type.getConstructor(byte.class).newInstance(value);
        } catch (IllegalAccessException | InvocationTargetException ex) {
            throw new RuntimeException(ex);
        } catch (InstantiationException | NoSuchMethodException | ClassCastException ex) {
            throw new IllegalArgumentException(ex);
        }
    }

    @Override
    public <U extends ByteTinyType> U fromString(Class<U> type, String value) {
        return newInstance(type, Byte.parseByte(value));
    }

} public class IntTinyTypes implements MetaTinyType<IntTinyType> {

    public static boolean includes(Class<?> candidate) {
        if (candidate == null) {
            return false;
        }
        return IntTinyType.class.equals(candidate.getSuperclass());
    }

    @Override
    public boolean isMetaOf(Class<?> candidate) {
        if (candidate == null) {
            return false;
        }
        return IntTinyType.class.equals(candidate.getSuperclass());
    }

    @Override
    public String stringify(IntTinyType value) {
        if (value == null) {
            throw new IllegalArgumentException("value must be not null");
        }
        return Integer.toString(value.value);
    }

    @Override
    public <U extends IntTinyType> U newInstance(Class<U> type, Object value) {
        if (type == null || !includes(type)) {
            throw new IllegalArgumentException(String.format("Not a %s: %s", IntTinyType.class.getSimpleName(), type == null ? "null" : type.getCanonicalName()));
        }
        try {
            return type.getConstructor(int.class).newInstance(value);
        } catch (IllegalAccessException | InvocationTargetException ex) {
            throw new RuntimeException(ex);
        } catch (InstantiationException | NoSuchMethodException | ClassCastException ex) {
            throw new IllegalArgumentException(ex);
        }
    }

    @Override
    public <U extends IntTinyType> U fromString(Class<U> type, String value) {
        return newInstance(type, Integer.parseInt(value));
    }

} public class LongTinyTypes implements MetaTinyType<LongTinyType> {

    public static boolean includes(Class<?> candidate) {
        if (candidate == null) {
            return false;
        }
        return LongTinyType.class.equals(candidate.getSuperclass());
    }

    @Override
    public boolean isMetaOf(Class<?> candidate) {
        if (candidate == null) {
            return false;
        }
        return LongTinyType.class.equals(candidate.getSuperclass());
    }

    @Override
    public String stringify(LongTinyType value) {
        if (value == null) {
            throw new IllegalArgumentException("value must be not null");
        }
        return Long.toString(value.value);
    }

    @Override
    public <U extends LongTinyType> U newInstance(Class<U> type, Object value) {
        if (type == null || !includes(type)) {
            throw new IllegalArgumentException(String.format("Not a %s: %s", LongTinyType.class.getSimpleName(), type == null ? "null" : type.getCanonicalName()));
        }
        try {
            return type.getConstructor(long.class).newInstance(value);
        } catch (IllegalAccessException | InvocationTargetException ex) {
            throw new RuntimeException(ex);
        } catch (InstantiationException | NoSuchMethodException | ClassCastException ex) {
            throw new IllegalArgumentException(ex);
        }
    }

    @Override
    public <U extends LongTinyType> U fromString(Class<U> type, String value) {
        return newInstance(type, Long.parseLong(value));
    }

} public abstract class MetaTinyTypes {

    public static final MetaTinyType[] metas = new MetaTinyType[]{
        new StringTinyTypes(),
        new BooleanTinyTypes(),
        new ByteTinyTypes(),
        new ShortTinyTypes(),
        new IntTinyTypes(),
        new LongTinyTypes()
    };

    /**
     * Provides a type-specific Meta class for the given TinyType.
     *
     * @param <T> the TinyType class type
     * @param candidate the TinyType class to obtain a Meta for
     * @return a Meta implementation suitable for the candidate
     * @throws IllegalArgumentException for null or a non-TinyType
     */
    public static <T> MetaTinyType<T> metaFor(Class<?> candidate) {
        for (MetaTinyType meta : metas) {
            if (meta.isMetaOf(candidate)) {
                return meta;
            }
        }
        throw new IllegalArgumentException(String.format("not a tinytype: %s", candidate == null ? "null" : candidate.getCanonicalName()));
    }

    /**
     * Checks whether a class is a TinyType. A class is considered a TinyType if
     * is a direct ancestor of a tech.anima.tinytypes.*TinyType, is not abstract
     * and provides a ctor matching super.
     *
     * @param candidate the class to be checked
     * @return true if the candidate is a TinyType, false otherwise.
     */
    public static boolean isTinyType(Class<?> candidate) {
        for (MetaTinyType meta : metas) {
            if (meta.isMetaOf(candidate)) {
                return true;
            }
        }
        return false;
    }

} public class ShortTinyTypes implements MetaTinyType<ShortTinyType> {

    public static boolean includes(Class<?> candidate) {
        if (candidate == null) {
            return false;
        }
        return ShortTinyType.class.equals(candidate.getSuperclass());
    }

    @Override
    public boolean isMetaOf(Class<?> candidate) {
        if (candidate == null) {
            return false;
        }
        return ShortTinyType.class.equals(candidate.getSuperclass());
    }

    @Override
    public String stringify(ShortTinyType value) {
        if (value == null) {
            throw new IllegalArgumentException("value must be not null");
        }
        return Short.toString(value.value);
    }

    @Override
    public <U extends ShortTinyType> U newInstance(Class<U> type, Object value) {
        if (type == null || !includes(type)) {
            throw new IllegalArgumentException(String.format("Not a %s: %s", ShortTinyType.class.getSimpleName(), type == null ? "null" : type.getCanonicalName()));
        }
        try {
            return type.getConstructor(short.class).newInstance((short) value);
        } catch (IllegalAccessException | InvocationTargetException ex) {
            throw new RuntimeException(ex);
        } catch (InstantiationException | NoSuchMethodException | ClassCastException ex) {
            throw new IllegalArgumentException(ex);
        }
    }

    @Override
    public <U extends ShortTinyType> U fromString(Class<U> type, String value) {
        return newInstance(type, Short.parseShort(value));
    }

} public class StringTinyTypes implements MetaTinyType<StringTinyType> {

    public static boolean includes(Class<?> candidate) {
        if (candidate == null) {
            return false;
        }
        return StringTinyType.class.equals(candidate.getSuperclass());
    }

    @Override
    public boolean isMetaOf(Class<?> candidate) {
        if (candidate == null) {
            return false;
        }
        return StringTinyType.class.equals(candidate.getSuperclass());
    }

    @Override
    public String stringify(StringTinyType value) {
        if (value == null) {
            throw new IllegalArgumentException("value must be not null");
        }
        return value.value;
    }

    @Override
    public <U extends StringTinyType> U newInstance(Class<U> type, Object value) {
        if (value == null) {
            throw new IllegalArgumentException("value must be not null");
        }
        if (type == null || !includes(type)) {
            throw new IllegalArgumentException(String.format("Not a %s: %s", StringTinyType.class.getSimpleName(), type == null ? "null" : type.getCanonicalName()));
        }
        try {
            return type.getConstructor(String.class).newInstance(value);
        } catch (IllegalAccessException | InvocationTargetException ex) {
            throw new RuntimeException(ex);
        } catch (InstantiationException | NoSuchMethodException | ClassCastException ex) {
            throw new IllegalArgumentException(ex);
        }
    }

    @Override
    public <U extends StringTinyType> U fromString(Class<U> type, String value) {
        return newInstance(type, value);
    }

}
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.Serializers;
import java.io.IOException;
import tech.anima.tinytypes.BooleanTinyType;
import tech.anima.tinytypes.ByteTinyType;
import tech.anima.tinytypes.IntTinyType;
import tech.anima.tinytypes.LongTinyType;
import tech.anima.tinytypes.ShortTinyType;
import tech.anima.tinytypes.StringTinyType;
import tech.anima.tinytypes.meta.BooleanTinyTypes;
import tech.anima.tinytypes.meta.ByteTinyTypes;
import tech.anima.tinytypes.meta.IntTinyTypes;
import tech.anima.tinytypes.meta.LongTinyTypes;
import tech.anima.tinytypes.meta.MetaTinyTypes;
import tech.anima.tinytypes.meta.ShortTinyTypes;
import tech.anima.tinytypes.meta.StringTinyTypes;
package tech.anima.tinytypes.jackson;


public class TinyTypesSerializers extends Serializers.Base {

    @Override
    public JsonSerializer<?> findSerializer(SerializationConfig config, JavaType type, BeanDescription beanDesc) {
        Class<?> candidateTT = type.getRawClass();
        if (MetaTinyTypes.isTinyType(candidateTT)) {
            return new TinyTypesSerializer(candidateTT);
        }
        return super.findSerializer(config, type, beanDesc);
    }

    public static class TinyTypesSerializer<T> extends JsonSerializer<T> {

        private final Class<T> type;

        public TinyTypesSerializer(Class<T> type) {
            if (type == null || !MetaTinyTypes.isTinyType(type)) {
                throw new IllegalArgumentException(String.format("not a tinytype: %s", type == null ? "null" : type.getCanonicalName()));
            }

            this.type = type;
        }

        @Override
        public void serialize(T value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException {
            if (StringTinyTypes.includes(type)) {
                gen.writeString(((StringTinyType) value).value);
                return;
            }
            if (BooleanTinyTypes.includes(type)) {