/*license*\ XBN-Java: Copyright (C) 2014, Jeff Epstein (aliteralmind __DASH__ github __AT__ yahoo __DOT__ com) This software is dual-licensed under the: - Lesser General Public License (LGPL) version 3.0 or, at your option, any later version; - Apache Software License (ASL) version 2.0. Either license may be applied at your discretion. More information may be found at - http://en.wikipedia.org/wiki/Multi-licensing. The text of both licenses is available in the root directory of this project, under the names "LICENSE_lgpl-3.0.txt" and "LICENSE_asl-2.0.txt". The latest copies may be downloaded at: - LGPL 3.0: https://www.gnu.org/licenses/lgpl-3.0.txt - ASL 2.0: http://www.apache.org/licenses/LICENSE-2.0.txt \*license*/ package com.github.xbn.util.lock; import com.github.xbn.lang.CrashIfObject; /** <p>For classes needing to implement {@code Lockable}, that cannot extend {@code AbstractLockable}.</p> <h3>Implementation template (view source)</h3> **/ public class LockableComposer { //state private boolean bLkd = false; private boolean bUnlkbl = false; /** <p>Create a new {@code LockableComposer}.</p> <p>This<ol> <li>Sets {@link #isUnlockable() isUnlockable}{@code ()} to {@code is_unlockable}.</li> <li>Sets {@link #isLocked() isLocked}{@code ()} to {@code false}.</li> </ol></p> * @see #LockableComposer(boolean, LockableComposer) this(b,lc) * @see #LockableComposer(Lockable) LockableComposer(lkbl) */ public LockableComposer(boolean is_unlockable) { bUnlkbl = is_unlockable; bLkd = false; } /** <p>Create a new {@code LockableComposer} from a {@code Lockable} object.</p> <p>This<ol> <li>Sets {@link #isUnlockable() isUnlockable}{@code ()} to {@code to_copy.isUnlockable()}</li> <li>Sets {@link #isLocked() isLocked}{@code ()} to {@code false}.</li> </ol></p> * @see #LockableComposer(boolean) this(b) */ public LockableComposer(boolean ignored, LockableComposer to_copy) { try { bUnlkbl = to_copy.isUnlockable(); } catch(RuntimeException rx) { throw CrashIfObject.nullOrReturnCause(to_copy, "to_copy", null, rx); } //Never ever call interface functions, directly or indirectly, in a constructor. zlockLB(false); } /** <p>Create a new {@code LockableComposer} from a {@code Lockable} object.</p> <p>This<ol> <li>Sets {@link #isUnlockable() isUnlockable}{@code ()} to {@code to_copy.isUnlockable()}</li> <li>Sets {@link #isLocked() isLocked}{@code ()} to {@code false}.</li> </ol></p> * @see #LockableComposer(boolean) this(b) */ public LockableComposer(Lockable to_copy) { try { bUnlkbl = to_copy.isUnlockable(); } catch(RuntimeException rx) { throw CrashIfObject.nullOrReturnCause(to_copy, "to_copy", null, rx); } //Never ever call interface functions, directly or indirectly, in a constructor. zlockLB(false); } /** <p>Can it be unlocked?.</p> * @return {@code true} If it is safe to call {@link #unlock() unlock}{@code ()} * @see #LockableComposer(boolean) this(b) * @see #forceUnlock_4prot() */ public boolean isUnlockable() { return bUnlkbl; } /** <p>Is it locked?.</p> * @return <ul> <li><b>{@code true}</b> If {@link #lock(boolean) lock}{@code (b)} was called (more recently than {@link #forceUnlock_4prot() forceUnlock_4prot}{@code ()}).</li> <li><b>{@code false}</b> If otherwise.</li> </ul> */ public boolean isLocked() { return bLkd; } public void lock() { lock(true); } public void lock(boolean do_lock) { zlockLB(do_lock); } protected final void zlockLB(boolean do_lock) { if(isLocked() && !isUnlockable() && !do_lock) { throw new IllegalStateException("Cannot unlock. isLocked()=" + isLocked() + ", isUnlockable()=" + isUnlockable() + ", do_lock=" + do_lock); } bLkd = do_lock; } /** <p>Crash if this {@code LockableComposer} is locked.</p> * @exception LockException If {@link #isLocked() isLocked}{@code ()} is {@code true}. * @see <li>{@link #ciNotLocked() ciNotLocked}{@code ()}</li> </ul> */ public void ciLocked_4prot() { if(isLocked()) { throw new LockException("isLocked() is true"); } } /** <p>Crash if this {@code LockableComposer} is unlocked.</p> * @exception LockException If {@link #isLocked() isLocked}{@code ()} is {@code false}. * @see #ciLocked(String) ciLocked(s) */ public void ciNotLocked_4prot() { if(!isLocked()) { throw new LockException("isLocked() is false"); } } /** <p>Forces {@code isLocked()} to be {@code false}, regardless the value of {@code isUnlockable()}.</p> <p>Sets {@link #isLocked() isLocked}{@code ()} to {@code false}.</p> */ public void forceUnlock_4prot() { bLkd = false; } public String toString() { return appendToString(new StringBuilder()).toString(); } public StringBuilder appendToString(StringBuilder to_appendTo) { return to_appendTo.append("isLocked()=").append(isLocked()).append(", isUnlockable()=").append(isUnlockable()); } //static...START public static final void lockIfNNull(Lockable lk_bl, boolean do_lock) { if(lk_bl != null) { lk_bl.lock(do_lock); } } //static...END }