package net.sf.openrocket.util; /** * A utility class helping an object to be made immutable after a certain point of time. * An object should contain an instance of Mutable and an immute() method which calls * {@link #immute()}. Additionally, every method that changes the state of the object * should call {@link #check()} before modification. * <p> * This class also provides a stack trace of the position where the object was made * immutable to help in debugging modifications of immuted objects. * * @author Sampo Niskanen <sampo.niskanen@iki.fi> */ public class Mutable implements Cloneable { private Throwable immuteTrace = null; /** * Mark the object immutable. Once the object has been called the object * cannot be made mutable again. Repeated calls to this method have no effect. */ public void immute() { if (immuteTrace == null) { immuteTrace = new Throwable(); } } /** * Check that the object is still mutable, and throw an exception if it is not. * <p> * The thrown exception will contain a trace of the position where the object was made * immutable to help in debugging. * * @throws IllegalStateException if {@link #immute()} has been called for this object. */ public void check() { if (immuteTrace != null) { throw new IllegalStateException("Object has been made immutable at " + immuteTrace.getMessage(), immuteTrace); } } /** * Check whether this object is still mutable. * * @return whether this object is still mutable. */ public boolean isMutable() { return immuteTrace == null; } /** * Return a new Mutable instance with the same state as the current object. */ @Override public Mutable clone() { try { return (Mutable) super.clone(); } catch (CloneNotSupportedException e) { throw new BugException("CloneNotSupportedException", e); } } }