/*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.analyze; import com.github.xbn.lang.ExpirableComposer; import com.github.xbn.io.z.GetDebugApbl_Fieldable; import com.github.xbn.testdev.CompositionConstructor; import com.github.xbn.testdev.CompositionFunction; import com.github.xbn.lang.CrashIfObject; import com.github.xbn.io.SimpleDebuggable; import com.github.xbn.lang.ExtraErrInfoableComposer; /** <p>For classes that need to implement {@code Analyzer}, that cannot extend {@code AbstractAnalyzer}.</p> * @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 AnalyzerComposer extends SimpleDebuggable { private int iNlzd = -1; private boolean bWNlzd = false; private final ExtraErrInfoableComposer cfxic; private final ExpirableComposer ec; private boolean bAutoResetState; /** <p>Create a new {@code AnalyzerComposer}.</p> * @see #AnalyzerComposer(boolean, AnalyzerComposer) this(b,ac) * @see #AnalyzerComposer(Analyzer) this(z) */ @CompositionConstructor public AnalyzerComposer() { super(); //Never ever call interface functions, directly or indirectly, in a constructor. zresetStateAB(); zresetCountsAB(); cfxic = new ExtraErrInfoableComposer(); ec = new ExpirableComposer(); bAutoResetState = true; } /** <p>Create a new {@code AnalyzerComposer} as a duplicate of another.</p> <p>This<ol> <li>Sets<ol> <li>{@link #getAnalyzedCount() getAnalyzedCount}{@code ()} to {@code to_copy.getAnalyzedCount()}</li> <li>{@link #wasAnalyzed() wasAnalyzed}{@code ()} to {@code to_copy.wasAnalyzed()}</li> </ol></li> <li>Calls {@link #zresetStateAB() zresetStateAB}{@code ()}     <i>(as specified by <code><i>[{@link com.github.xbn.analyze.Analyzer Analyzer}]</i>.{@link com.github.xbn.analyze.Analyzer#getObjectCopy() getObjectCopy}()</code>)</i></li> </ol></p> * @param ignored Required to prevent an ambigous-invocation error, when attempting to call this or the {@link #AnalyzerComposer(Analyzer) other} copy-constructor with a class such as {@link com.github.xbn.analyze.AbstractAnalyzer AbstractAnalyzer}, which both extends this {@code AnalyzerComposer} and is an {@link com.github.xbn.analyze.Analyzer Analyzer}. * @see #AnalyzerComposer() */ @CompositionConstructor protected AnalyzerComposer(boolean ignored, AnalyzerComposer to_copy) { super(to_copy); //AnalyzerComposers ARE Debuggable. No need for ignored iNlzd = to_copy.getAnalyzedCount(); bWNlzd = to_copy.wasAnalyzed(); cfxic = new ExtraErrInfoableComposer(ignored, to_copy.cfxic); ec = new ExpirableComposer(ignored, to_copy.ec); bAutoResetState = to_copy.doAutoResetState(); //Never ever call interface functions, directly or indirectly, in a constructor. zresetStateAB(); } /** <p>Create a new {@code AnalyzerComposer} from an {@code Analyzer}.</p> <p>This<ol> <li>Calls {@link com.github.xbn.io.SimpleDebuggable#SimpleDebuggable(Debuggable) super}{@code (to_copy)}</li> <li>Sets<ol> <li>{@link #getAnalyzedCount() getAnalyzedCount}{@code ()} to {@code to_copy.getAnalyzedCount()}</li> </ol></li> <li>Calls {@link #zresetStateAB() zresetStateAB}{@code ()}</li> </ol></p> * @see #AnalyzerComposer() */ @CompositionConstructor public AnalyzerComposer(Analyzer to_copy) { super(to_copy); iNlzd = to_copy.getAnalyzedCount(); cfxic = new ExtraErrInfoableComposer().extraErrInfo(to_copy.getExtraErrInfo()); ec = new ExpirableComposer(to_copy); bAutoResetState = to_copy.doAutoResetState(); //Never ever call interface functions, directly or indirectly, in a constructor. zresetStateAB(); zresetCountsAB(); } @CompositionFunction public void resetState() { zresetStateAB(); } protected final void zresetStateAB() { bWNlzd = false; } @CompositionFunction public void resetCounts() { zresetCountsAB(); } @CompositionFunction public boolean doAutoResetState() { return bAutoResetState; } @CompositionFunction public void setAutoResetState_4prot(boolean is_auto) { bAutoResetState = is_auto; } protected final void zresetCountsAB() { iNlzd = 0; } @CompositionFunction public boolean doesExpire() { return ec.doesExpire(); } @CompositionFunction public void declareExpirable_4prot() { ec.declareExpirable_4prot(); } @CompositionFunction public void declareExpired_4prot() { resetState(); ec.declareExpired_4prot(); } @CompositionFunction public boolean isExpired() { return ec.isExpired(); } /** * @return The number of times {@link #declareAnalyzed_4prot() declareAnalyzed_4prot}{@code ()} was called since the most recent call to {@link #resetCounts() resetCounts}{@code ()}. */ @CompositionFunction public int getAnalyzedCount() { return iNlzd; } /** <p>Declare that an analysis took place.</p> <p>This<ol> <li>Increments {@link #getAnalyzedCount() getAnalyzedCount}{@code ()} and sets {@link #wasAnalyzed() wasAnalyzed}{@code ()} to {@code true}.</li> </ol></p> */ @CompositionFunction public void declareAnalyzed_4prot() { iNlzd++; bWNlzd = true; } /** * @return {@code true} If {@link #declareAnalyzed_4prot() declareAnalyzed_4prot}{@code ()} was called more recently than {@link #resetState() resetState}{@code ()} */ @CompositionFunction public boolean wasAnalyzed() { return bWNlzd; } public String toString() { return appendToString(new StringBuilder()).toString(); } public StringBuilder appendToString(StringBuilder to_appendTo) { try { if(wasAnalyzed()) { to_appendTo.append("analyzed ").append(getAnalyzedCount()).append(" times"); } else { to_appendTo.append("not-analyzed"); } } catch(RuntimeException rx) { throw CrashIfObject.nullOrReturnCause(to_appendTo, "to_appendTo", null, rx); } if(doAutoResetState()) { to_appendTo.append(" (auto-reset)"); } to_appendTo.append(", "); return ec.appendToString(to_appendTo); } @CompositionFunction public Object getExtraErrInfo() { return cfxic.getExtraErrInfo(); } @CompositionFunction public void setExtraErrInfo(Object xtra_errInfo) { cfxic.setExtraErrInfo(xtra_errInfo); } //static...START /** <p>If this {@code Analyzer} needs its {@code stateReset()}, crash. This is useful as the first step of any analysis.</p> * @param analyzer May not be {@code null}. * @exception IllegalStateException If <code>analyzer.{@link com.github.xbn.analyze.Analyzer#wasAnalyzed() wasAnalyzed}()</code> is {@code true}. */ public static final void autoResetStateOrCINeedTo(Analyzer analyzer) { try { if(analyzer.doAutoResetState()) { analyzer.resetState(); return; } } catch(RuntimeException rx) { throw CrashIfObject.nullOrReturnCause(analyzer, "analyzer", null, rx); } if(analyzer.wasAnalyzed()) { throw new IllegalStateException("Must resetState(). " + analyzer); } } public static final Appendable getDebugApbl(GetDebugApbl_Fieldable fieldable, String fldbl_name) { try { return fieldable.getDebugApbl(); } catch(RuntimeException rx) { throw CrashIfObject.nullOrReturnCause(fieldable, fldbl_name, null, rx); } } //static...END }