/*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.regexutil.z;
import com.github.xbn.number.IntBoundInclusive;
import com.github.xbn.lang.Null;
import com.github.xbn.analyze.validate.ValidResultFilter;
import com.github.xbn.analyze.validate.ValueValidator;
import com.github.xbn.lang.CrashIfObject;
import com.github.xbn.neederneedable.AbstractNeedable;
import com.github.xbn.neederneedable.Needer;
import com.github.xbn.number.LengthInRange;
import com.github.xbn.number.NewLengthInRangeValidatorFor;
import com.github.xbn.number.z.LengthInRangeValidator_Cfg;
import com.github.xbn.regexutil.NewPatternFor;
import com.github.xbn.regexutil.RegexReplacer;
import com.github.xbn.regexutil.ReplacedInEachInput;
import java.util.regex.Pattern;
/**
<p>For <a href="{@docRoot}/com/github/xbn/neederneedable/Needable.html#indirect">indirectly</a> configuring a {@link com.github.xbn.regexutil.RegexReplacer RegexReplacer}.</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 RegexReplacer_CfgForNeeder<P extends RegexReplacer,R extends Needer> extends AbstractNeedable<P,R> implements RegexReplacer_Fieldable {
//config
public Pattern pFindWhat = null ;
public Object oRplcWithDirect = null ;
public Appendable apblDebug = null ;
public ReplacedInEachInput rplcsWhat = null ;
public ValueValidator<Integer> vvMatchNum = null ;
public int iMaxUntilLoops = -1 ;
public boolean doCrashIfMaxUntilExceeded = false;
//constructors...START
/**
<p>Configure a <code>RegexReplacer</code> with defaults.</p>
<p>This calls<ol>
<li><code><!-- GENERIC PARAMETERS FAIL IN @link --><a href="{@docRoot}/com/github/xbn/neederneedable/AbstractNeedable.html#AbstractNeedable(boolean, boolean, R)">super</a>(true, true, needer)</code>{@code (true, true, needer)}</li>
<li>{@link #resetRRCFN() resetRRCFN}{@code ()}</li>
</ol></p>
*/
public RegexReplacer_CfgForNeeder(R needer) {
super(true, true, needer);
resetRRCFN();
}
//constructors...END
/**
<p>Reset configuration with <i>no search terms</i>.</p>
* <p>Equal to
<br/> {@link #resetRRCFN() resetRRCFN}{@code ()}</p>
* @return <i>{@code this}</i>
*/
public RegexReplacer_CfgForNeeder<P,R> reset() {
resetRRCFN();
return this;
}
/**
<p>Reset configuration specific to this {@code RegexReplacer_CfgForNeeder}</p>
<p>This<ol>
<li>Calls<ol>
<li>{@link #direct(Pattern, Object) direct}{@code ((Pattern)null, null)}</li>
<li>{@link #all() all}{@code ()}</li>
</ol></li>
<li>Sets<ol>
<li>{@link com.github.xbn.regexutil.RegexReplacer#getMatchNumValidator() getMatchNumValidator}{@code ()}* to be {@link com.github.xbn.number.NewLengthInRangeValidatorFor#unrestricted(Null, ValidResultFilter, Appendable) unrestricted}</li>
<li>{@link com.github.xbn.regexutil.RegexReplacer#getMaxUntilLoops() getMaxUntilLoops}{@code ()}* to its {@link com.github.xbn.regexutil.RegexReplacer#DEFAULT_MAX_UNTIL_LOOPS default}</li>
<li>{@link com.github.xbn.regexutil.RegexReplacer#doCrashIfMaxUntilExceeded() doCrashIfMaxUntilExceeded}{@code ()}* to {@code true}.</li>
</ol></li>
</ol></p>
* @see #reset()
*/
protected final void resetRRCFN() {
direct((Pattern)null, null);
all();
vvMatchNum = NewLengthInRangeValidatorFor.unrestricted(Null.BAD, null, null);
iMaxUntilLoops = RegexReplacer.DEFAULT_MAX_UNTIL_LOOPS;
doCrashIfMaxUntilExceeded = false;
}
/**
<p>Replace the first match only.</p>
<p>This sets {@link RegexReplacer#getReplacedInEachInput() getReplacedInEachInput}{@code ()}* to <code>{@link com.github.xbn.regexutil.ReplacedInEachInput ReplacedInEachInput}.{@link com.github.xbn.regexutil.ReplacedInEachInput#FIRST FIRST}</code></p>
* @return <i>{@code this}</i>
* @see #all()
*/
public RegexReplacer_CfgForNeeder<P,R> first() {
rplcsWhat = ReplacedInEachInput.FIRST;
return this;
}
/**
<p>Replace the first match only, <i>which must be anchored to the start of the search string</i>.</p>
<p>This sets {@link RegexReplacer#getReplacedInEachInput() getReplacedInEachInput}{@code ()}* to <code>{@link com.github.xbn.regexutil.ReplacedInEachInput ReplacedInEachInput}.{@link com.github.xbn.regexutil.ReplacedInEachInput#LOOKING_AT LOOKING_AT}</code></p>
* @return <i>{@code this}</i>
* @see #all()
*/
public RegexReplacer_CfgForNeeder<P,R> lookingAt() {
rplcsWhat = ReplacedInEachInput.LOOKING_AT;
return this;
}
/**
<p>Only if the <i>entire string</i> matches the regex, replace it. Otherwise, do nothing.</p>
<p>This sets {@link RegexReplacer#getReplacedInEachInput() getReplacedInEachInput}{@code ()}* to <code>{@link com.github.xbn.regexutil.ReplacedInEachInput ReplacedInEachInput}.{@link com.github.xbn.regexutil.ReplacedInEachInput#MATCHES MATCHES}</code></p>
* @return <i>{@code this}</i>
* @see #all()
*/
public RegexReplacer_CfgForNeeder<P,R> matches() {
rplcsWhat = ReplacedInEachInput.MATCHES;
return this;
}
/**
<p>Set debugging.</p>
* @param dest_ifNonNull When non-{@code null}, this is the destination to write debugging output (and debugging is turned {@link com.github.xbn.io.Debuggable#isDebugOn() on}). Get with {@link com.github.xbn.io.Debuggable#getDebugApbl() getDebugApbl}{@code ()}* and {@link com.github.xbn.io.Debuggable#getDebugAptr() getDebugAptr}{@code ()}*.
* @return <i>{@code this}</i>
*/
public RegexReplacer_CfgForNeeder<P,R> debugTo(Appendable dest_ifNonNull) {
apblDebug = dest_ifNonNull;
return this;
}
/**
<p>Replace specific matches only, based on their numeric location in the search-string (such as the second-through-fourth matches only).</p>
<p>This sets {@link RegexReplacer#getReplacedInEachInput() getReplacedInEachInput}{@code ()}* to <code>{@link com.github.xbn.regexutil.ReplacedInEachInput ReplacedInEachInput}.{@link com.github.xbn.regexutil.ReplacedInEachInput#MATCH_NUMBERS MATCH_NUMBERS}</code></p>
* @param match_numValidator May not be <code>null</code>, and
<br/> <code>match_numValidator.{@link com.github.xbn.analyze.validate.ValueValidator#getRuleType() getRuleType}().{@link com.github.xbn.lang.RuleType#isImpossible() isImpossible}()</code>
<br/>must be {@code false}. Get with {@link RegexReplacer#getMatchNumValidator() getMatchNumValidator}{@code ()}
* @return <i>{@code this}</i>
* @see #all()
* @see #matchRange(LengthInRange) matchRange(iir)
* @see #matchRange(int, int) matchRange(i,i)
*/
public RegexReplacer_CfgForNeeder<P,R> matchNumbers(ValueValidator<Integer> match_numValidator) {
vvMatchNum = match_numValidator;
rplcsWhat = ReplacedInEachInput.MATCH_NUMBERS;
return this;
}
/**
<p>Replace only the matches found within a specific numeric range.</p>
* @return <code>{@link #matchNumbers(ValueValidator) matchNumbers}(new {@link com.github.xbn.number.z.LengthInRangeValidator_Cfg#LengthInRangeValidator_Cfg() LengthInRangeValidator_Cfg}().{@link com.github.xbn.number.z.LengthInRangeValidator_CfgForNeeder#range(LengthInRange) range}(range).{@link com.github.xbn.number.z.LengthInRangeValidator_CfgForNeeder#build() build}())</code>
*/
public RegexReplacer_CfgForNeeder<P,R> matchRange(LengthInRange range) {
return matchNumbers(new LengthInRangeValidator_Cfg().range(range).build());
}
/**
<p>Replace only the matches found within a specific numeric range, such as the second-through-fourth.</p>
* @return <code>{@link #matchRange(LengthInRange) matchRange}(new {@link com.github.xbn.number.LengthInRange#LengthInRange(int, String, IntBound) LengthInRange}(min, null, new new com.github.xbn.number.IntBoundInclusive#IntBoundInclusive(Integer, String)(max_inclusive, null)))</code>
*/
public RegexReplacer_CfgForNeeder<P,R> matchRange(int min, int max_inclusive) {
return matchRange(new LengthInRange(min, null, new IntBoundInclusive(max_inclusive, null)));
}
/**
<p>Replace all matches.</p>
<p>This sets {@link RegexReplacer#getReplacedInEachInput() getReplacedInEachInput}{@code ()}* to <code>{@link com.github.xbn.regexutil.ReplacedInEachInput ReplacedInEachInput}.{@link com.github.xbn.regexutil.ReplacedInEachInput#ALL ALL}</code></p>
* @return <i>{@code this}</i>
* @see #first()
* @see #lookingAt()
* @see #matches()
* @see #matchNumbers(ValueValidator) matchNumbers(vv)
* @see #until(int, MaxUntilLoopsExceeded) until(i,muxi)
* @see #replaceWhatNotMatchNums(ReplacedInEachInput) replaceWhatNotMatchNums(rw)
*/
public RegexReplacer_CfgForNeeder<P,R> all() {
rplcsWhat = ReplacedInEachInput.ALL;
return this;
}
/**
<p>Set the replaces-what Enum explicitely, to anything except "match numbers".</p>
* @param rplcs_what May not be {@code null}, and may not equal <code>ReplacedInEachInput.{@link com.github.xbn.regexutil.ReplacedInEachInput#MATCH_NUMBERS MATCH_NUMBERS}</code>. If {@link com.github.xbn.regexutil.ReplacedInEachInput#UNTIL UNTIL}, then this calls {@link #until(int) until}{@code (20)}. Otherwise it sets {@link com.github.xbn.regexutil.RegexReplacer#getReplacedInEachInput() getReplacedInEachInput}{@code ()}* to {@code rplcs_what}.
* @return <i>{@code this}</i>
* @see #all()
*/
public RegexReplacer_CfgForNeeder<P,R> replaceWhatNotMatchNums(ReplacedInEachInput rplcs_what) {
try {
rplcs_what.crashIfForbiddenValue(ReplacedInEachInput.MATCH_NUMBERS, "rplcs_what", null);
} catch(RuntimeException rx) {
throw CrashIfObject.nullOrReturnCause(rplcs_what, "rplcs_what", null, rx);
}
if(rplcs_what == ReplacedInEachInput.UNTIL) {
until(20);
} else {
rplcsWhat = rplcs_what;
}
return this;
}
/**
<p>Replace all matches repeatedly, until no more are found.</p>
<p>This sets {@link RegexReplacer#getReplacedInEachInput() getReplacedInEachInput}{@code ()}* to <code>{@link com.github.xbn.regexutil.ReplacedInEachInput ReplacedInEachInput}.{@link com.github.xbn.regexutil.ReplacedInEachInput#UNTIL UNTIL}</code></p>
* @return <i>{@code this}</i>
* @see #first()
* @see #until(int) until(i)
* @see #until()
*/
public RegexReplacer_CfgForNeeder<P,R> until(int max_loops, MaxUntilLoopsExceeded exceeded_is) {
iMaxUntilLoops = max_loops;
try {
doCrashIfMaxUntilExceeded = exceeded_is.isBad();
} catch(RuntimeException rx) {
throw CrashIfObject.nullOrReturnCause(exceeded_is, "exceeded_is", null, rx);
}
rplcsWhat = ReplacedInEachInput.UNTIL;
return this;
}
/**
<p>Replace all matches repeatedly, until no more are found.</p>
* @return <code>{@link #until(int, MaxUntilLoopsExceeded) until}(max_loops, {@link com.github.xbn.regexutil.z.MaxUntilLoopsExceeded MaxUntilLoopsExceeded}.{@link com.github.xbn.regexutil.z.MaxUntilLoopsExceeded#BAD BAD})</code>
*/
public RegexReplacer_CfgForNeeder<P,R> until(int max_loops) {
return until(max_loops, MaxUntilLoopsExceeded.BAD);
}
/**
<p>Set the find-what search-term for <i>indirect</i> replacements only.</p>
* @return <i>{@code this}</i>
* @see #findWhat(String) findWhat(s)
* @see #findWhatLiteral(String) findWhatLiteral(s)
*/
public RegexReplacer_CfgForNeeder<P,R> findWhat(Pattern pattern_toFind) {
pFindWhat = pattern_toFind;
return this;
}
/**
<p>Set the find-what search-term for <i>indirect</i> replacements only.</p>
* @param findWhat_regex May not be <code>null</code>.
* @return <code>{@link #findWhat(Pattern) pattern}({@link com.github.xbn.regexutil.NewPatternFor NewPatternFor}{@link com.github.xbn.regexutil.NewPatternFor#regex(String, String) regex}(findWhat_regex))</code>
*/
public RegexReplacer_CfgForNeeder<P,R> findWhat(String findWhat_regex) {
return findWhat(NewPatternFor.regex(findWhat_regex, "findWhat_regex"));
}
/**
<p>Set the find-what search-term for <i>indirect</i> replacements only.</p>
* @param findWhat_regex May not be <code>null</code>.
* @return <code>{@link #findWhat(Pattern) pattern}({@link com.github.xbn.regexutil.NewPatternFor NewPatternFor}{@link com.github.xbn.regexutil.NewPatternFor#regex(String, int, String) regex}(findWhat_regex, bit_flags))</code>
*/
public RegexReplacer_CfgForNeeder<P,R> findWhat(String findWhat_regex, int bit_flags) {
return findWhat(NewPatternFor.regex(findWhat_regex, bit_flags, "findWhat_regex"));
}
/**
<p>Set the find-what search-term for <i>indirect</i> replacements only.</p>
* @param findWhat_literal May not be <code>null</code>.
* @return <code>{@link #findWhat(Pattern) pattern}([PRE_LINK-file].{@link NewPatternFor#literal(String) literal}(findWhat_literal))</code>
*/
public RegexReplacer_CfgForNeeder<P,R> findWhatLiteral(String findWhat_literal) {
return findWhat(NewPatternFor.literal(findWhat_literal, "findWhat_literal"));
}
/**
<p>Set the <i>direct</i>-replacement search terms.</p>
*/
public RegexReplacer_CfgForNeeder<P,R> direct(Pattern pattern_toFind, Object direct_rplcWithStr) {
findWhat(pattern_toFind);
return directReplacement(direct_rplcWithStr);
}
/**
<p>Set the direct-replacement search terms.</p>
<p>This calls<ol>
<li>{@link #findWhat(String) findWhat}{@code (findWhat_regex)}</li>
<li>{@link #directReplacement(Object) directReplacement}{@code (direct_rplcWithStr)}</li>
</ol></p>
* @return <i>{@code this}</i>
*/
public RegexReplacer_CfgForNeeder<P,R> direct(String findWhat_regex, Object direct_rplcWithStr) {
findWhat(findWhat_regex);
return directReplacement(direct_rplcWithStr);
}
/**
<p>Set the direct-replacement search terms.</p>
<p>This calls<ol>
<li>{@link #findWhat(String, int) findWhat}{@code (findWhat_regex, bit_flags)}</li>
<li>{@link #directReplacement(Object) directReplacement}{@code (direct_rplcWithStr)}</li>
</ol></p>
* @return <i>{@code this}</i>
*/
public RegexReplacer_CfgForNeeder<P,R> direct(String findWhat_regex, int bit_flags, Object direct_rplcWithStr) {
findWhat(findWhat_regex, bit_flags);
return directReplacement(direct_rplcWithStr);
}
/**
<p>Set the direct-replacement search terms.</p>
<p>This calls<ol>
<li>{@link #findWhatLiteral(String) findWhatLiteral}{@code (findWhat_literal, bit_flags)}</li>
<li>{@link #directReplacement(Object) directReplacement}{@code (direct_rplcWithStr)}</li>
</ol></p>
* @return <i>{@code this}</i>
*/
public RegexReplacer_CfgForNeeder<P,R> directLiteral(String findWhat_literal, Object direct_rplcWithStr) {
findWhatLiteral(findWhat_literal);
return directReplacement(direct_rplcWithStr);
}
/**
<p>Set the direct replace-with string.</p>
* @param direct_rplcWithStr If non-{@code null}, this is a <a href="{@docRoot}/com/github/xbn/regexutil/RegexReplacer.html#direct">direct</a> replacement. If {@code null}, this is an <a href="{@docRoot}/com/github/xbn/regexutil/RegexReplacer.html#indirect">indirect</a> replacement. Get with {@link com.github.xbn.regexutil.RegexReplacer#getDirectReplacement() getDirectReplacement}{@code ()}*.
* @return <i>{@code this}</i>
* @see #direct(Pattern, Object) direct(p,O)
* @see #direct(String, Object) direct(s,O)
* @see #direct(String, int, Object) direct(s,i,O)
* @see #directLiteral(String, Object) directLiteral(s,O)
*/
public RegexReplacer_CfgForNeeder<P,R> directReplacement(Object direct_rplcWithStr) {
oRplcWithDirect = direct_rplcWithStr;
return this;
}
/**
<p>Replace all matches repeatedly, until no more are found.</p>
* @return <code>{@link #until(int) until}(max_loops, {@link com.github.xbn.regexutil.RegexReplacer}.{@link com.github.xbn.regexutil.RegexReplacer#DEFAULT_MAX_UNTIL_LOOPS})</code>
*/
public RegexReplacer_CfgForNeeder<P,R> until() {
return until(RegexReplacer.DEFAULT_MAX_UNTIL_LOOPS);
}
public Appendable getDebugApbl() {
return apblDebug;
}
public Pattern getPattern() {
return pFindWhat;
}
public ReplacedInEachInput getReplacedInEachInput() {
return rplcsWhat;
}
public ValueValidator<Integer> getMatchNumValidator() {
return vvMatchNum;
}
public int getMaxUntilLoops() {
return iMaxUntilLoops;
}
public boolean doCrashIfMaxUntilExceeded() {
return doCrashIfMaxUntilExceeded;
}
public Object getDirectReplacement() {
return oRplcWithDirect;
}
/**
<p>Create a new <code>RegexReplacer</code> as configured, <i>for direct replacements only</i>.</p>
* @return <code>(new {@link com.github.xbn.regexutil.RegexReplacer#RegexReplacer(RegexReplacer_Fieldable) RegexReplacer}(this))</code>
* @exception IllegalArgumentException If {@link #getDirectReplacement() getDirectReplacement}{@code ()} is {@code null}.
* @see <a href="{@docRoot}/com/github/xbn/regexutil/RegexReplacer.html#direct">Definition: direct</a>
*/
public P build() {
if(getDirectReplacement() == null) {
throw new IllegalArgumentException("getDirectReplacement() (build() may only be used for direct replacements)");
}
@SuppressWarnings("unchecked")
P p = (P)(new RegexReplacer(this));
return p;
}
/**
* @return <i>{@code this}</i>
*/
@SuppressWarnings("unchecked") //See LLCfgOverall.startConfigReturnNeedable(R)
public RegexReplacer_CfgForNeeder<P,R> startConfigReturnNeedable(R needer) {
@SuppressWarnings("unchecked")
Class<P> clsp = (Class<P>)((Class)RegexReplacer.class);
startConfig(needer, clsp);
return this;
}
/**
<p>Sets the fully-configured object into the {@code Needer}, and returns control back to the needer-chain.</p>
* @return <code>{@link com.github.xbn.neederneedable.AbstractNeedableWithSubs#endCfgWithNeededReturnNeeder(Object) endCfgWithNeededReturnNeeder}({@link #build() build}())</code>
*/
public R endCfg() {
return endCfgWithNeededReturnNeeder(build());
}
/**
* @return <i>{@code this}</i>
*/
public RegexReplacer_CfgForNeeder<P,R> chainID(boolean do_setStatic, Object id) {
setChainID(do_setStatic, id);
return this;
}
}