/*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.neederneedable;
import com.github.xbn.lang.CrashIfObject;
import com.github.xbn.testdev.CompositionConstructor;
import com.github.xbn.testdev.CompositionFunction;
/**
<p>For classes that need to implement {@code Needable}, that cannot extend {@code AbstractNeedable}.</p>
* @see Needable
* @see AbstractNeedable
* @since 0.1.0
* @author Copyright (C) 2014, Jeff Epstein ({@code aliteralmind __DASH__ github __AT__ yahoo __DOT__ com}), dual-licensed under the LGPL (version 3.0 or later) or the ASL (version 2.0). See source code for details. <a href="http://xbnjava.aliteralmind.com">{@code http://xbnjava.aliteralmind.com}</a>, <a href="https://github.com/aliteralmind/xbnjava">{@code https://github.com/aliteralmind/xbnjava}</a>
**/
public class NeedableComposer<O,R extends Needer> extends ChainableComposer {// implements Needable<O,R> {
//state
private boolean bNdUsbl = false;
private boolean bNdUsblAtStrt = false;
private boolean bAv2Ndr = false;
private R cndr = null;
//internal: For error messages
//constructors...START
/**
<p>Create a new instance and potentially start configuration--this must be implemented as {@code protected}.</p>
<p>This calls<ol>
<li>{@link com.github.xbn.neederneedable.ChainableComposer#ChainableComposer() super}{@code ()}</li>
<li>{@link #declareNeededReset_4prot() declareNeededReset_4prot}{@code ()}</li>
</ol></p>
* @param is_avaliableToNeeders Get with {@link #isAvailableToNeeder() isAvailableToNeeder}{@code ()}.
* @param is_neededUseableAtInit If {@code true}, the needed object is useable immediately after a configuration is started. Get with {@link #isNeededUseableAtStart() isNeededUseableAtStart}{@code ()}.
*/
@CompositionConstructor
public NeedableComposer(boolean is_avaliableToNeeders, boolean is_neededUseableAtInit) {
super();
bAv2Ndr = is_avaliableToNeeders;
bNdUsblAtStrt = is_neededUseableAtInit;
declareNeededReset_4prot();
}
//constructors...END
//main...START
/**
<p>Immediately reverts to as if a configuration was never started. Under most circumstances, this is called by <code><!-- GENERIC PARAMETERS FAIL IN @link --><a href="#endCfgWithNeededReturnNeeder_4prot(O)">endCfgWithNeededReturnNeeder_4prot</a>(O)</code>. <i>If called manually, the {@link #getActiveNeeder() active needer} will be left in an unstable state.</i></p>
<p>This<ol>
<li>Sets {@code getActiveNeeder()} to {@code null}</li>
<li>Sets {@link #isNeededUsable() isNeededUsable}{@code ()} to {@code false}</li>
<li>Calls <code><i>[{@link com.github.xbn.neederneedable.SimpleChainable super}]</i>.{@link com.github.xbn.neederneedable.SimpleChainable#unsetChainID(boolean) unsetChainID}(false)</code></li>
</ol></p>
<h3><i>Does this interact acceptably with directly-used {@code Needables}?</i></h3>
*/
@CompositionFunction
public void declareNeededReset_4prot() {
cndr = null;
bNdUsbl = isNeededUseableAtStart();
unsetChainID(false);
}
/**
<p>Start configuration with a default object--this must be implemented as {@code protected} with the name "{@code startConfig}".</p>
<p>This<ol>
<li>Calls <code>{@link #ciActive_4prot() ciActive_4prot}()</code></li>
<li>Calls <code>needer.{@link com.github.xbn.neederneedable.Needer#startConfig(Class) startConfig}(expected_type)</code></li>
<li>Sets {@link #getActiveNeeder() getActiveNeeder}{@code ()} to {@code needer}</li>
</ol></p>
* @param needer May not be equal to <i>{@code this}</i> (for situations where classes implement both {@code Needable} and {@code Needer}. See {@link com.github.xbn.neederneedable.NeedableWithSubsComposer NeedableWithSubsComposer}).
* @see <code><!-- GENERIC PARAMETERS FAIL IN @link --><a href="#endCfgWithNeededReturnNeeder_4prot(O)">endCfgWithNeededReturnNeeder_4prot</a>(O)</code>
* @see #declareNeededUseable_4prot(boolean) declareNeededUseable_4prot(b)
*/
@CompositionFunction
public void startConfig_4prot(R needer, Class<O> expected_type) {
if(needer == this) {
throw new IllegalArgumentException("needer is the SAME OBJECT as this Needable.");
}
ciActive_4prot();
try {
needer.startConfig(expected_type);
} catch(RuntimeException rx) {
throw CrashIfObject.nullOrReturnCause(needer, "needer", null, rx);
}
cndr = needer;
}
/**
<p>Sets the fully configured object into the {@code Needer} and then ends configuration--this must be implemented as {@code protected} with the name "{@code endCfgWithNeededReturnNeeder}".</p>
<p>This<ol>
<li>Calls
<br/> {@link #getActiveNeeder() getActiveNeeder}{@code ().}{@link com.github.xbn.neederneedable.Needer#neeadableSetsNeeded(Object) neeadableSetsNeeded}{@code ()}</li>
<li>Calls {@link #declareNeededReset_4prot() declareNeededReset_4prot}{@code ()} (which sets {@code getActiveNeeder()} to {@code null}).</li>
<li>Returns the (now inactive) {@code Needer}.</li>
</ol></p>
* @see <code><!-- GENERIC PARAMETERS FAIL IN @link --><a href="NeedableComposer.html#startConfig_4prot(R, java.lang.Class)">startConfig_4prot</a>(R,cls)</code>
*/
@CompositionFunction
public R endCfgWithNeededReturnNeeder_4prot(O fully_configured) {
ciInactive_4prot();
if(!isNeededUsable()) {
throw new IllegalStateException("isNeededUsable() is false.");
}
getActiveNeeder().neeadableSetsNeeded(fully_configured);
R cndr = getActiveNeeder();
declareNeededReset_4prot(); //Sets getActiveNeeder() to null.
return cndr;
}
//main...END
//setters...START
/**
<p>Declare that {@code endCfg()} may be safely called.--this must be implemented as {@code protected} with the name "{@code declareNeededUseable}".</p>
* @param is_usable If {@code null}, the needed object is ready for use. It may be configured further, or may be retrieved immediately (by first ending the configuration).
* @exception IllegalStateException If {@link #getActiveNeeder() getActiveNeeder}{@code ()} is {@code null}.
* @see <code><!-- GENERIC PARAMETERS FAIL IN @link --><a href="NeedableComposer.html#startConfig_4prot(R, java.lang.Class)">startConfig_4prot</a>(R,cls)</code>
*/
@CompositionFunction
public void declareNeededUseable_4prot(boolean is_usable) {
ciInactive_4prot();
bNdUsbl = is_usable;
}
//setters...END
//getters...START
/**
* @see #declareNeededUseable_4prot(boolean)
*/
@CompositionFunction
public boolean isNeededUsable() {
ciInactive_4prot();
return bNdUsbl;
}
/**
* @see #NeedableComposer(boolean, boolean)
*/
@CompositionFunction
public boolean isNeededUseableAtStart() {
return bNdUsblAtStrt;
}
@CompositionFunction
public R getActiveNeeder() {
return cndr;
}
/**
* @see #NeedableComposer(boolean, boolean)
*/
@CompositionFunction
public boolean isAvailableToNeeder() {
return bAv2Ndr;
}
//getters...END
//other...START
//Not a composition-function, because super.toString() already is
public String toString() {
return super.toString() +
((getActiveNeeder() != null) ? ", isNeededUsable()=" + isNeededUsable() : "") +
", isNeededUseableAtStart()=" + isNeededUseableAtStart() + ", isAvailableToNeeder()=" + isAvailableToNeeder() + ", getActiveNeeder()=[" + getActiveNeeder() + "]";
}
/**
<p>If a configuration is active, crash.</p>
* @exception IllegalStateException If {@link #getActiveNeeder() getActiveNeeder}{@code ()} is non-{@code null}.
* @see #ciInactive_4prot()
*/
@CompositionFunction
public void ciActive_4prot() {
if(getActiveNeeder() != null) {
throw new IllegalStateException("Must endCfg(). getActiveNeeder()=[" + getActiveNeeder() + "]");
}
}
/**
<p>If no configuration is active, crash.</p>
* @exception IllegalStateException If {@link #getActiveNeeder() getActiveNeeder}{@code ()} is {@code null}.
* @see #ciActive_4prot() ciActive_4prot(s)
*/
@CompositionFunction
public void ciInactive_4prot() {
if(getActiveNeeder() == null) {
throw new IllegalStateException("Must startConfigReturnNeedable(cndr). getActiveNeeder()=null");
}
}
//other...END
}