package xapi.fu; import xapi.fu.In1.In1Unsafe; import xapi.fu.Out1.Out1Unsafe; import static xapi.fu.Immutable.immutable1; /** * Created by James X. Nelson (james @wetheinter.net) on 6/18/16. */ public class Mutable <I> implements In1Unsafe<I>, Out1Unsafe<I> { public static <Value, Bound extends Value> Mutable<Value> mutable(Class<Bound> bounds) { return new TypesafeMutable<>(bounds); } private volatile I value; public Mutable() { } public Mutable(I value) { value = value; } public Immutable<I> freeze() { return immutable1(value); } @Override public final void in(I in) { In1Unsafe.super.in(in); } @Override public final I out1() { return Out1Unsafe.super.out1(); } @Override public void inUnsafe(I in) throws Throwable { this.value = in; } @Override public I outUnsafe() throws Throwable { return value; } public static class TypesafeMutable <T> extends Mutable <T> { private final Class<? extends T> bounds; public <Bound extends T> TypesafeMutable(Class<Bound> cls) { this.bounds = cls; } public Class<? extends T> getBounds() { return bounds; } @Override public final void inUnsafe(T in) throws Throwable { if (in != null) { in = checkInput(bounds, in); } super.inUnsafe(in); } protected T checkInput(Class<? extends T> bounds, T in) { if (in != null && !bounds.isInstance(in)) { throw new ClassCastException(in + " is not a " + bounds); } return in; } protected T checkOutput(Class<? extends T> bounds, T in) { if (in != null && !bounds.isInstance(in)) { throw new ClassCastException(in + " is not a " + bounds); } return in; } @Override public final T outUnsafe() throws Throwable { T output = super.outUnsafe(); output = checkOutput(bounds, output); return output; } } }