/*
XBN-Java Library
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
*/
package com.github.xbn.analyze.validate;
import com.github.xbn.lang.IllegalArgumentStateException;
import com.github.xbn.lang.ExpirableComposer;
import com.github.xbn.io.SimpleDebuggable;
import com.github.xbn.lang.CrashIfObject;
import com.github.xbn.number.LengthInRange;
import com.github.xbn.analyze.validate.z.FilterValidCounts_Fieldable;
/**
<p>A valid-result filter that changes the result based on the number of valid, invalid, or total analysis counts.</p>
<A NAME="cfg"></a><h3>Builder Configuration: {@link com.github.xbn.analyze.validate.z.FilterValidCounts_Cfg FilterValidCounts_Cfg}</h3>
<p><ul>
<li><b>Convenience builders:</b> {@link com.github.xbn.analyze.validate.NewValidResultFilterFor NewValidResultFilterFor}</li>
<li><b>Count what?</b> <code>{@link com.github.xbn.analyze.validate.z.FilterValidCounts_Cfg#countAll() countAll}()</code>, <code>{@link com.github.xbn.analyze.validate.z.FilterValidCounts_Cfg#countInvalid() countInvalid}()</code>, <code>{@link com.github.xbn.analyze.validate.z.FilterValidCounts_Cfg#countValid() countValid}()</code>
</li>
<li><b>Pre:</b> <code>{@link com.github.xbn.analyze.validate.z.FilterValidCounts_Cfg#preActionBelowInAfter(FilterPreAction, FilterPreAction, FilterPreAction) preActionBelowInAfter}(fpa,fpa,fpa)</code>, <code>{@link com.github.xbn.analyze.validate.z.FilterValidCounts_Cfg#preActionProceed_afterFalse() preActionProceed_afterFalse}()</code></li>
<li><b>Post:</b> <code>{@link com.github.xbn.analyze.validate.z.FilterValidCounts_Cfg#postValueBelowInAfter(FilterAfterValue, FilterAfterValue, FilterAfterValue) postValueBelowInAfter}(fpv,fpv,fpv)</code>, <code>{@link com.github.xbn.analyze.validate.z.FilterValidCounts_Cfg#inUnchangedOutFalse() inUnchangedOutFalse}()</code>, <code>{@link com.github.xbn.analyze.validate.z.FilterValidCounts_Cfg#unfiltered() unfiltered}()</code></li>
<li><b>Pre and post:</b> <code>{@link com.github.xbn.analyze.validate.z.FilterValidCounts_Cfg#postValueAlwaysUnchanged() postValueAlwaysUnchanged}()</code>, <code>{@link com.github.xbn.analyze.validate.z.FilterValidCounts_Cfg#postValue_inUnchanged_outFalse() postValue_inUnchanged_outFalse}()</code></li>
<li><b>Other:</b> <code>{@link com.github.xbn.analyze.validate.z.FilterValidCounts_Cfg#range(LengthInRange) range}(lir)</code>, <code>{@link com.github.xbn.analyze.validate.z.FilterValidCounts_Cfg#chainID(boolean, Object) chainID}(b,o)</code>, <code>{@link com.github.xbn.analyze.validate.z.FilterValidCounts_Cfg#debugTo(Appendable) debugTo}(apbl)</code>, <code>{@link com.github.xbn.analyze.validate.z.FilterValidCounts_Cfg#reset() reset}()</code></li>
</ul></p>
<p>{@code java com.github.xbn.examples.analyze.validate.ValidResultFilterXmpl}</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 FilterValidCounts extends SimpleDebuggable implements ValidResultFilter, FilterValidCounts_Fieldable {
//configuration
private final LengthInRange lir;
private final FilterCountType vfc;
private final FilterAfterValue fPostBlw;
private final FilterAfterValue fPostIn;
private final FilterPreAction fPreIn;
private final FilterAfterValue fPostAftr;
private final FilterPreAction fPreAftr;
private final FilterPreAction fPreBlw;
private final ExpirableComposer ec;
//counts
private final ValidCounter validCounts;
private final CountGetter countGtr;
/**
<p>Create a new instance.</p>
<p>This<ol>
<li>Calls {@link com.github.xbn.io.SimpleDebuggable#SimpleDebuggable(GetDebugApbl_Fieldable) super}(fieldable)</li>
<li>Sets <i>and validates</i> all fields from {@code fieldable}</li>
<li>Sets {@link #doesExpire() doesExpire}{@code ()} to
<br/> <code>(fieldable.{@link com.github.xbn.analyze.validate.z.FilterValidCounts_Fieldable#getAfterPreAction() getAfterPreAction}().{@link FilterPreAction#isReturn() isReturn}() || !fieldable.{@link com.github.xbn.analyze.validate.z.FilterValidCounts_Fieldable#getAfterAfterValue() getAfterAfterValue}().{@link FilterAfterValue#isUnchanged() isUnchanged}())</code></li>
</ol></p>
* @see #FilterValidCounts(FilterValidCounts) this(fvc)
*/
public FilterValidCounts(FilterValidCounts_Fieldable fieldable) {
super(fieldable);
crashIfBadFieldsFVC(fieldable);
vfc = fieldable.getFilterCountType();
lir = fieldable.getRange();
fPostAftr = fieldable.getAfterAfterValue();
fPostBlw = fieldable.getBelowAfterValue();
fPostIn = fieldable.getInAfterValue();
fPreAftr = fieldable.getAfterPreAction();
fPreBlw = fieldable.getBelowPreAction();
fPreIn = fieldable.getInPreAction();
if(lir.getMin() == 0) {
throw new IllegalArgumentException("fieldable.getRange().getMin() is zero: " + lir.getMinBound());
}
validCounts = new ValidCounter();
countGtr = getCountGetter(vfc, validCounts);
ec = new ExpirableComposer(fPreAftr.isReturn() || !fPostAftr.isUnchanged());
}
/**
<p>Crash if any fields are invalid, as specified throughout the setter functions in the builder: {@link com.github.xbn.analyze.validate.z.FilterValidCounts_CfgForNeeder z.FilterValidCounts_CfgForNeeder}</p>
*/
public static final void crashIfBadFieldsFVC(FilterValidCounts_Fieldable fieldable) {
if(fieldable.getRange() == null) {
throw new NullPointerException("fieldable.getRange() (set range(lir))");
}
if(fieldable.getBelowAfterValue() == null) {
throw new NullPointerException("fieldable.getBelowAfterValue() (set with postValueBelowInAfter(fpv,fpv,fpv)");
}
if(fieldable.getInAfterValue() == null) {
throw new NullPointerException("fieldable.getInAfterValue() (set with postValueBelowInAfter(fpv,fpv,fpv)");
}
if(fieldable.getAfterAfterValue() == null) {
throw new NullPointerException("fieldable.getAfterAfterValue() (set with postValueBelowInAfter(fpv,fpv,fpv)");
}
if(fieldable.getBelowPreAction() == null) {
throw new NullPointerException("fieldable.getBelowPreAction() (set with preActionBelowInAfter(fpa,fpa,fpa)");
}
if(fieldable.getInPreAction() == null) {
throw new NullPointerException("fieldable.getInPreAction() (set with preActionBelowInAfter(fpa,fpa,fpa)");
}
if(fieldable.getAfterPreAction() == null) {
throw new NullPointerException("fieldable.getAfterPreAction() (set with preActionBelowInAfter(fpa,fpa,fpa)");
}
try {
if(!fieldable.getFilterCountType().isAll() &&
(!fieldable.getBelowPreAction().isProceed() || !fieldable.getInPreAction().isProceed())) {
throw new IllegalArgumentStateException("fieldable.getFilterCountType() is FilterCountType." + fieldable.getFilterCountType() + ". fieldable.getBelowPreAction() (" + fieldable.getBelowPreAction() + ") and fieldable.getInPreAction() (" + fieldable.getInPreAction() + ") must both be PROCEED. (Otherwise the follows-rules-inverted valid/invalid-count will never increase.)");
}
} catch(RuntimeException rx) {
throw CrashIfObject.nullOrReturnCause(fieldable.getFilterCountType(), "fieldable.getFilterCountType()", "set with count*().", rx);
}
}
/**
<p>Create a new instance as a duplicate of another.</p>
<p>This<ol>
<li>Calls {@link com.github.xbn.io.SimpleDebuggable#SimpleDebuggable(Debuggable) super}(to_copy)</li>
<li>Sets all fields from {@code to_copy}</li>
</ol></p>
* @see #FilterValidCounts(FilterValidCounts_Fieldable) this(fvc_f)
*/
public FilterValidCounts(FilterValidCounts to_copy) {
super(to_copy);
vfc = to_copy.getFilterCountType();
lir = to_copy.getRange();
fPostAftr = to_copy.getAfterAfterValue();
fPostBlw = to_copy.getBelowAfterValue();
fPostIn = to_copy.getInAfterValue();
fPreAftr = to_copy.getAfterPreAction();
fPreBlw = to_copy.getBelowPreAction();
fPreIn = to_copy.getInPreAction();
validCounts = new ValidCounter(to_copy.validCounts);
countGtr = getCountGetter(vfc, validCounts);
ec = new ExpirableComposer(to_copy);
}
private static final CountGetter getCountGetter(FilterCountType fc_t, ValidCounter counter) {
//Delta, so vf_c doesn't need to be checked each time.
return (fc_t.isAll()
? new CGAll(counter, fc_t)
: (fc_t.isValid()
? new CGValid(counter, fc_t)
: new CGInvalid(counter, fc_t)));
}
/**
<p>The min-max range the count must conform to.</p>
* @return A non-{@code null} {@code LengthInRange}.
* @see com.github.xbn.analyze.validate.z.FilterValidCounts_Cfg#range(LengthInRange range) range(lir)
*/
public LengthInRange getRange() {
return lir;
}
/**
<p>What is counted?.</p>
* @see com.github.xbn.analyze.validate.z.FilterValidCounts_Cfg#countAll() FilterValidCounts_Cfg#countAll()
* @see com.github.xbn.analyze.validate.z.FilterValidCounts_Cfg#countInvalid() FilterValidCounts_Cfg#countInvalid()
* @see com.github.xbn.analyze.validate.z.FilterValidCounts_Cfg#countValid() FilterValidCounts_Cfg#countValid()
*/
public FilterCountType getFilterCountType() {
return vfc;
}
/**
<p>What does the pre-filter do when the count is below the range?.</p>
<p><i>See:</i><ul>
<li><b>Pre:</b> {@code getBelowPreAction()}, {@link #getInPreAction() getInPreAction}{@code ()}, {@link #getAfterPreAction() getAfterPreAction}{@code ()}</li>
<li><b>Post:</b> {@link #getBelowAfterValue() getBelowAfterValue}{@code ()}, {@link #getInAfterValue() getInAfterValue}{@code ()}, {@link #getAfterAfterValue() getAfterAfterValue}{@code ()}</li>
</ul></p>
* @see #getRange()
* @see com.github.xbn.analyze.validate.z.FilterValidCounts_Cfg#preActionBelowInAfter(FilterPreAction, FilterPreAction, FilterPreAction) FilterValidCounts_Cfg#preActionBelowInAfter(fpa,fpa,fpa)
*/
public FilterPreAction getBelowPreAction() {
return fPreBlw;
}
/**
<p>What does the post-filter return when the count is below the range?.</p>
* @see #getBelowPreAction()
* @see #getInAfterValue()
* @see #getAfterAfterValue()
* @see com.github.xbn.analyze.validate.z.FilterValidCounts_Cfg#postValueBelowInAfter(FilterAfterValue, FilterAfterValue, FilterAfterValue) postValueBelowInAfter(fpv,fpv,fpv)
*/
public FilterAfterValue getBelowAfterValue() {
return fPostBlw;
}
/**
<p>What does the pre-filter do when the count is in the range?.</p>
* @see #getBelowPreAction()
* @see com.github.xbn.analyze.validate.z.FilterValidCounts_Cfg#preActionBelowInAfter(FilterPreAction, FilterPreAction, FilterPreAction) FilterValidCounts_Cfg#preActionBelowInAfter(fpa,fpa,fpa)
*/
public FilterPreAction getInPreAction() {
return fPreIn;
}
/**
<p>What does the post-filter return when the count is in the range?.</p>
* @see #getBelowAfterValue()
* @see com.github.xbn.analyze.validate.z.FilterValidCounts_Cfg#postValueBelowInAfter(FilterAfterValue, FilterAfterValue, FilterAfterValue) postValueBelowInAfter(fpv,fpv,fpv)
*/
public FilterAfterValue getInAfterValue() {
return fPostIn;
}
/**
<p>What does the pre-filter do on the iteration <i>after</i> the count has reached the range-maximum?.</p>
* @see #getBelowPreAction()
* @see com.github.xbn.analyze.validate.z.FilterValidCounts_Cfg#preActionBelowInAfter(FilterPreAction, FilterPreAction, FilterPreAction) FilterValidCounts_Cfg#preActionBelowInAfter(fpa,fpa,fpa)
*/
public FilterPreAction getAfterPreAction() {
return fPreAftr;
}
/**
<p>What does the post-filter return on the iteration <i>after</i> the count has reached the range-maximum?.</p>
* @see #getBelowAfterValue()
* @see com.github.xbn.analyze.validate.z.FilterValidCounts_Cfg#postValueBelowInAfter(FilterAfterValue, FilterAfterValue, FilterAfterValue) postValueBelowInAfter(fpv,fpv,fpv)
*/
public FilterAfterValue getAfterAfterValue() {
return fPostAftr;
}
/**
<p>Get the pre-filter action, given the current count and expiration.</p>
* @return If {@link #isExpired() isExpired}{@code ()} is<ul>
<li>{@code true}: {@link #getAfterPreAction() getAfterPreAction}{@code ()}</li>
<li>Greater than the {@link #getRange() range} maxumum: {@link #getBelowPreAction() getBelowPreAction}{@code ()}</li>
<li>Between the range minimum and maximum (inclusive): {@link #getInPreAction() getInPreAction}{@code ()} (If <b>equal</b> to the maximum and
<br/>
<code>getBelowPreAction().{@link FilterPreAction#isReturn() isReturn}()</code>
<br/>is {@code true}, then {@link #isExpired() isExpired}{@code ()} is set to {@code true})</li>
</ul><b>Note:</b> No counts are incremented by this function. {@link FilterValidCounts} only count the number of times the <i>something</i> is validated against the <i><b>rules</b></i>, and it [post {@link com.github.xbn.analyze.validate.Validator#doInvertRules() inversion}] is determined to be valid.)
* @see #getAfterValueFromInvertedRules(boolean) getAfterValueFromInvertedRules(b)
*/
public FilterPreAction getPreAction() {
if(isDebugOn()) { getDebugAptr().appentln("<FVC> getPreAction(): " + toString()); }
if(isExpired()) {
FilterPreAction fpa = getAfterPreAction();
if(isDebugOn()) { getDebugAptr().appentln("<FVC> isExpired()=true. returning FilterPreAction." + getAfterPreAction() + ", " + countGtr); }
return fpa;
}
int iCount = countGtr.getCount();
int iMinCmprdToCount = getRange().getInclMinComparedToOrIfNoMin(iCount, 0);
int iMaxCmprdToCount = getRange().getInclMaxComparedToOrIfNoMax(iCount, 0);
FilterPreAction fpa = null;
if(iMinCmprdToCount > 0) { //(count < min)
fpa = getBelowPreAction();
//ELSE: count is greater-than-or-equal-to min
} else {
if(iMaxCmprdToCount > 0) { //(count < max)
//In bounds
fpa = getInPreAction();
} else if(iMaxCmprdToCount == 0) { //(count == max)
fpa = getInPreAction();
if(fpa.isReturn()) {
if(isDebugOn()) { getDebugAptr().appentln("<FVC> Max bound reached and getAfterPreAction().isReturn() is true. Expiring"); }
ec.declareExpired_4prot();
}
}
}
if(isDebugOn()) {
getDebugAptr().appentln("<FVC> Returning FilterPreAction." + fpa + ". FilterCountType." + countGtr.fct + "=" + iCount + ", " + countGtr);
}
return fpa;
}
/**
<p>Get the post-filter action, given the current count, expiration, and if the (post-inverted) rules are followed. This increases {@link #getAnalyzedCount() getAnalyzedCount}{@code ()} by one.</p>
* @param are_postInvertRulesFollowed Does the <i>something</i> follow the rules? If {@code true}, the rules are followed (or it doesn't, but the rules are {@link com.github.xbn.analyze.validate.Validator#doInvertRules() inverted}). When {@code true}, {@link #getValidCount() getValidCount}{@code ()} are increased by one. When {@code false}, {@link #getInvalidCount() getInvalidCount}{@code ()} is increased. <b>Note:</b> {@link FilterValidCounts} only count the number of times the <i>something</i> is validated against the <i><b>rules</b></i>, and it [post inversion] is determined to be valid. Regardless the {@code FilterAfterValue} returned by this function, the counts are only affected by the value of this parameter.)
* @return If {@link #isExpired() isExpired}{@code ()} is<ul>
<li>{@code true}: {@link #getAfterAfterValue() getAfterAfterValue}{@code ()}</li>
<li>{@code false}: If the {@link #getFilterCountType() count} is<ul>
<li>Greater than the {@link #getRange() range} maxumum: {@link #getBelowAfterValue() getBelowAfterValue}{@code ()}</li>
<li>Between the range minimum and maximum (inclusive): {@link #getInAfterValue() getInAfterValue}{@code ()} <i>(If <b>equal</b> to the maximum, then {@link #isExpired() isExpired}{@code ()} is set to {@code true})</i></li>
</ul></li>
</ul>
* @see #getPreAction()
* @see com.github.xbn.analyze.validate.Validator#doInvertRules()
*/
public FilterAfterValue getAfterValueFromInvertedRules(boolean are_postInvertRulesFollowed) {
getDebugAptr().appentln("<FVC> getAfterValueFromInvertedRules(" + are_postInvertRulesFollowed + ")");
validCounts.declareValid(are_postInvertRulesFollowed);
if(isExpired()) {
FilterAfterValue fpv = getAfterAfterValue();
// boolean bValid = ValidResultFilterUtil.getPostReturnValueFromInvertedRules(fpv, are_postInvertRulesFollowed);
if(isDebugOn()) { getDebugAptr().appentln("<FVC> isExpired()=true. returning FilterAfterValue." + getAfterAfterValue() + ", " + countGtr); }
return fpv;
}
int iCount = countGtr.getCount();
int iMinCmprdToCount = getRange().getInclMinComparedToOrIfNoMin(iCount, 0);
int iMaxCmprdToCount = getRange().getInclMaxComparedToOrIfNoMax(iCount, 0);
FilterAfterValue fpv = null;
if(iMinCmprdToCount > 0) { //(count < min)
fpv = getBelowAfterValue();
//ELSE: count is greater-than-or-equal-to min
} else {
if(iMaxCmprdToCount > 0) { //(count < max)
//In bounds
fpv = getInAfterValue();
} else if(iMaxCmprdToCount == 0) { //(count == max)
fpv = getInAfterValue();
if(isDebugOn()) { getDebugAptr().appentln("<FVC> Max bound reached. Expiring"); }
ec.declareExpired_4prot();
}
}
if(isDebugOn()) {
getDebugAptr().appentln("<FVC> getAfterValueFromInvertedRules(" + are_postInvertRulesFollowed + ")=" + fpv + ". " + countGtr.fct + "=" + countGtr.getCount() + ", range=<" + getRange().getRules() + ">], " + countGtr);
}
return fpv;
}
/**
* @see #FilterValidCounts(FilterValidCounts_Fieldable) this(fvc_f)
*/
public boolean doesExpire() {
return ec.doesExpire();
}
/**
* @see #getPreAction()
* @see #getAfterValueFromInvertedRules(boolean) getAfterValueFromInvertedRules(b)
*/
public boolean isExpired() {
return ec.isExpired();
}
/**
<p>How many times has the <i>something</i> been analyzed against the rules?.</p>
* @see #getValidCount()
* @see #getInvalidCount()
* @see #getAfterValueFromInvertedRules(boolean) getAfterValueFromInvertedRules(b)
*/
public int getAnalyzedCount() {
return validCounts.getAnalyzedCount();
}
/**
<p>How many times has the <i>something</i> been analyzed against the rules, and (post-inversion) deemed valid?.</p>
@see #getAnalyzedCount()
* @see com.github.xbn.analyze.validate.Validator#doInvertRules()
*/
public int getValidCount() {
return validCounts.getValidCount();
}
/**
<p>How many times has the <i>something</i> been analyzed against the rules, and (post-inversion) deemed invalid?.</p>
@see #getAnalyzedCount()
* @see com.github.xbn.analyze.validate.Validator#doInvertRules()
*/
public int getInvalidCount() {
return validCounts.getInvalidCount();
}
public String toString() {
return appendToString(new StringBuilder()).toString();
}
public boolean doesNothing() {
return (getBelowPreAction().isProceed() &&
getBelowAfterValue().isUnchanged() &&
getInPreAction().isProceed() &&
getInAfterValue().isUnchanged() &&
getAfterPreAction().isProceed() &&
getAfterAfterValue().isUnchanged());
}
public StringBuilder appendToString(StringBuilder to_appendTo) {
try {
if(doesNothing()) {
return to_appendTo.append("unfiltered");
}
} catch(RuntimeException rx) {
throw CrashIfObject.nullOrReturnCause(to_appendTo, "to_appendTo", null, rx);
}
to_appendTo.append("range=").append(getRange()).append(", ");
to_appendTo.append(countGtr.toString()).
append(", FilterCountType.").append(countGtr.fct).append(", below=[pre=").
append(getBelowPreAction()).append(",post=").
append(getBelowAfterValue()).append("]").append(", in=[").
append(getInPreAction()).append(",").append(getInAfterValue()).append("], after=[").
append(getAfterPreAction()).append(",").
append(getAfterAfterValue()).append("], ");
return ec.appendToString(to_appendTo);
}
/**
<p>Duplicate this <code>FilterValidCounts</code>.</p>
* @return <code>(new <a href="#FilterValidCounts(FilterValidCounts)">FilterValidCounts</a>(this))</code>
*/
public FilterValidCounts getObjectCopy() {
return (new FilterValidCounts(this));
}
/**
@return <code>true</code> If {@code to_compareTo} is non-{@code null}, a {@code FilterValidCounts}, and all relevant fields {@linkplain #areFieldsEqual(FilterValidCounts) are equal}. This is implemented as suggested by Joshua Bloch in "Effective Java" (2nd ed, item 8, page 46).
*/
@Override
public boolean equals(Object to_compareTo) {
//Check for object equality first, since it's faster than instanceof.
if(this == to_compareTo) {
return true;
}
if(!(to_compareTo instanceof FilterValidCounts)) {
//to_compareTo is either null or not an FilterValidCounts.
//java.lang.Object.object(o):
// "For any non-null reference value x, x.equals(null) should return false."
//See the bottom of this class for a counter-argument (which I'm not going with).
return false;
}
//Safe to cast
FilterValidCounts o = (FilterValidCounts)to_compareTo;
//Finish with field-by-field comparison.
return areFieldsEqual(o);
}
/**
<p>Are all relevant fields equal?.</p>
* @param to_compareTo May not be {@code null}.
*/
public boolean areFieldsEqual(FilterValidCounts to_compareTo) {
try {
return (getRange().equals(to_compareTo.getRange()) &&
getFilterCountType() == to_compareTo.getFilterCountType() &&
getBelowAfterValue() == to_compareTo.getBelowAfterValue() &&
getInAfterValue() == to_compareTo.getInAfterValue() &&
getInPreAction() == to_compareTo.getInPreAction() &&
getAfterAfterValue() == to_compareTo.getAfterAfterValue() &&
getAfterPreAction() == to_compareTo.getAfterPreAction() &&
doesExpire() == to_compareTo.doesExpire() &&
isExpired() == to_compareTo.isExpired());
} catch(RuntimeException rx) {
throw CrashIfObject.nullOrReturnCause(to_compareTo, "to_compareTo", null, rx);
}
}
public int hashCode() {
return 27 * getRange().hashCode() +
getFilterCountType().ordinal() +
getBelowAfterValue().ordinal() +
getInAfterValue().ordinal() +
getInPreAction().ordinal() +
getAfterAfterValue().ordinal() +
getAfterPreAction().ordinal() +
(doesExpire() ? 1 : 0) +
(isExpired() ? 1 : 0);
}
}
abstract class CountGetter {
protected final ValidCounter validCounts;
public final FilterCountType fct;
public CountGetter(ValidCounter counter, FilterCountType fc_t) {
validCounts = counter;
fct = fc_t;
}
public abstract int getCount();
public String toString() {
return "follows-rules-inverted:" + validCounts.toString();
}
}
class CGAll extends CountGetter {
public CGAll(ValidCounter counter, FilterCountType fc_t) {
super(counter, fc_t);
}
public int getCount() {
return validCounts.getAnalyzedCount();
}
}
class CGValid extends CountGetter {
public CGValid(ValidCounter counter, FilterCountType fc_t) {
super(counter, fc_t);
}
public int getCount() {
return validCounts.getValidCount();
}
}
class CGInvalid extends CountGetter {
public CGInvalid(ValidCounter counter, FilterCountType fc_t) {
super(counter, fc_t);
}
public int getCount() {
return validCounts.getAnalyzedCount() - validCounts.getValidCount();
}
}
class ValidCounter {
private int iVld ;
private int iInvld;
public ValidCounter() {
resetVC();
}
public ValidCounter(ValidCounter to_copy) {
iVld = to_copy.getValidCount();
iInvld = to_copy.getInvalidCount();
}
public void reset() {
resetVC();
}
protected final void resetVC() {
iVld = 0;
iInvld = 0;
}
public void declareValid(boolean is_valid) {
if(is_valid) {
iVld++;
} else {
iInvld++;
}
}
public int getAnalyzedCount() {
return (getValidCount() + getInvalidCount());
}
public int getValidCount() {
return iVld;
}
public int getInvalidCount() {
return iInvld;
}
public String toString() {
return "analyzed/valid/invalid=[" + getAnalyzedCount() + "," + getValidCount() + "," + getInvalidCount() + "]";
}
}