/* XBN Java: Generically useful, non-GUI Java code. http://sourceforge.net/projects/xbnjava Copyright (C) 1997-2003, Jeff Epstein All rights reserved. Modifications: No Redistribution in binary form, with or without modifications, are permitted provided that the following conditions are met: * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * If modifications are made to source code then this license should indicate that fact in the "Modifications" section above. * Neither the author, nor the contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. [NOTE: This license contains NO advertising clause.] */ package xbn.template; import xbn.XBNObject; import xbn.AssertException; import xbn.array.primitive.ListPA; import xbn.output.Outputter; import xbn.output.OWriter; import xbn.output.OWIntoSB; import xbn.string.UtilString; import xbn.string.padchop.PadChopString; import xbn.string.padchop.ConfigChop; /**
Take a Template, fill each gap with something, and output the resulting text.
Source code: TemplateFiller.java. Example code XmplTemplateFiller.java
Examples: One, two and demonstration of how output is built on the fly.
Take this text...
Hello there, \~G\~name\~EG\~. Through significant research, \~G\~name\~EG\~, it has been discovered that you are exactly \~G\~age\~EG\~ years old.
...and this code...
Template t = new Template(FLRFile("[...file path to text file...]"));
TemplateFiller tf = new TemplateFiller();
tf.setTemplate(t);
tf.fill("name", "Jeffy");
tf.fill("age", 30);
sopl(tf.getResult());
...and here's the output:
Hello there, Jeffy. Through significant research, Jeffy, it has been discovered that you are exactly 30 years old.
Take this text...
\~G\~name\~EG\~\~G\~name\~EG\~
There's an example of a gap at the very beginning of the file, and of two gaps directly next to each other.
Following is an example of the same, but at the <I>end</I> of the file.
\~G\~age\~EG\~\~G\~age\~EG\~
...and the same code as in example one, and here's the output:
JeffyJeffy
There's an example of a gap at the very beginning of the file, and of two gaps directly next to each other.
Following is an example of the same, but at the <I>end</I> of the file.
3030
Given the template in example one...
Hello there, \~G\~name\~EG\~. Through significant research, \~G\~name\~EG\~, it has been discovered that you are exactly \~G\~age\~EG\~ years old.
getString |
getUnqArrIdx |
getInstanceCount |
name | 0 | 2 |
age | 1 | 1 |
getString |
getUnqArrIdx |
getInstanceCount |
name | 0 | 2 |
name | 0 | 2 |
age | 1 | 1 |
Key (unique string) | Value (UniqueString) |
name | [name, 0, 2] |
age | [age, 1, 1] |
["Hello there, ", ". Through significant research, ", ", it has been discovered that you are exactly ", "years old."]
The output is built on the fly. Before any gaps are even filled, we already know how the result will start...with the first element of surrounding text:
Hello there, |
We've reached the first gap. The first absolute gap. Array index zero. What is the name of this gap? We need the unique name of this gap, knowing that the absolute array index is zero...
String sGapName = getAOSLookup().getUSAPAbsolute().getUniqueString(i).getString();
The first absolute gap name is "name". Until it is filled, the result text will remain in this state. If the "age" gap is filled before the "name" gap is filled, this resulting output text remains unchanged.
Now, say the "name" gap was filled (with the value "Jeffy"). The resulting output can be further constructed. First, append the fill text for it:
Hello there, Jeffy |
Now get element two (array index zero) of the surrounding text, and add it:
Hello there, Jeffy. Through significant research, |
Now we've reached the second absolute gap (array index one). What is the name of this gap, knowing that the absolute array index? By calling the same code as above (with "1" instead of "0"), we find that the second absolute gap is a duplicate of the first: "name". We know that this gap has already been filled, so we can proceed. Take the same fill text and append it to the output:
Hello there, Jeffy. Through significant research, Jeffy |
Add the next item of the surrounding text (the third element, array index two):
Hello there, Jeffy. Through significant research, Jeffy, it has been discovered that you are exactly |
Now we've reached the third absolute gap (array index two). What is the name of this gap, knowing the absolute array index? The gap name is "age".
Gap "age" has not been filled yet, so the output remains as it is.
...Gap "age" has still not been filled...
...Okay, there we are. Gap "age" has been filled. Get the fill text for it, and append it onto the resulting output:
Hello there, Jeffy. Through significant research, Jeffy, it has been discovered that you are exactly 30 |
Add the next surrounding text to the output:
Hello there, Jeffy. Through significant research, Jeffy, it has been discovered that you are exactly 30 years old. |
We've reached the end of the surrounding text array. By definition, there is exactly one more surrounding text element than there are absolute gaps. Therefore, outputting the last element of surrounding text is a way of detecting that the result output has been completely constructed.
Ta-da.
@version 0.9b @author Jeff Epstein, http://sourceforge.net/projects/xbnjava. **/ public class TemplateFiller extends XBNObject { private PadChopString pcs = null; private UtilString uString = null; //The currently set template. private Template template = null; //The debugging Outputter. private Outputter optrDbg = new Outputter(); //The OWriter that actually outputs the Template's //resulting text. private OWriter owrtr = null; //Is the OWriter an OWIntoSB? Totally internal. private boolean bOWIsOWIntoSB = false; //See doAllowOWSetInMidFill. private boolean bAllowSetOWInMidFill = false; //Internal variable that keeps track of what //unique gaps have so far been output. private int i_outputArrIdx = 0; private String sExtFillGapName = null; //Sub-objects...START //For fill(...TemplateOrderedGaps...) //and getAllFilledWith() private TemplateFiller tfSub = null; private String[] asFT_TOG1 = null; private String[] asFT_TOG2 = null; private String[] asFT_TOG3 = null; //Sub-objects...END /** An *empty* String array that will temporarily hold the fill text. This maps one-to-one to template.asUniqueGapNames. That is, asFillText[i] is the fill text for asUniqueGapNames[i]. After each getResult, each element is reset to null. Discuss changing of sizes, and why it exists in this class... **/ private String asFillText[] = null; /**Create a TemplateFiller.
Equal to TemplateFiller(false)
Create a TemplateFiller.
Note that setOWIntoSB is called by this constructor.
@param b_allowSetOWInMidFill If true, then you may repeatedly set different OWriters into this TemplateFiller, even if you're currently in the middle of filling a Template's gaps (this might be useful for testing and verification purposes. Not sure how it would be useful for real...). If false, then attempting to set a new OWriter while in mid-fill will cause an AssertException to be thrown. **/ public TemplateFiller(boolean b_allowSetOWInMidFill) { setOWIntoSB(); bAllowSetOWInMidFill = b_allowSetOWInMidFill; } /**Create a TemplateFiller.
@param o_writer The OWriter that will be used to write output in this TemplateFiller. See setOWriter and getOWriter @param b_allowSetOWInMidFill If true, then you may repeatedly set different OWriters into this TemplateFiller, even if you're currently in the middle of filling a Template's gaps (this might be useful for testing and verification purposes. Not sure how it would be useful for real...). If false, then attempting to set a new OWriter while in mid-fill will cause an AssertException to be thrown. **/ public TemplateFiller(OWriter o_writer, boolean b_allowSetOWInMidFill) { setOWriter(o_writer); setAllowOWSetInMidFill(b_allowSetOWInMidFill); } /**Create a TemplateFiller.
Equal to TemplateFiller(o_writer, false)
Is it legal to fill a gap?
@return true If isTemplateSet is true, and areAllGapsFilled is false.Have all the currently-set Template's gaps been filled?
@return(([THE NUMBER OF GAPS FILLED SO FAR] - 1) >= getTemplate().getUSAPAbsolute().getLength())
@exception AssertException If isTemplateSet is false.
**/
public boolean areAllGapsFilled() {
if(!isTemplateSet()) {
throwAX("areAllGapsFilled", "This function may not be called when isTemplateSet() is false.");
}
//The template is set.
return (i_outputArrIdx >= getTemplate().getUSAPAbsolute().getLength());
}
/**
Which Template do you want to fill?
Get with getTemplate
. Analyze with isTemplateSet
.
Get the Template for direct manipulation.
Set with setTemplate
. Analyze with isTemplateSet
.
Is a template currently set into this TemplateFiller?
Set with setTemplate
. Get with getTemplate
.
Get the array index of the next absolute gap not yet filled. See getNextAbsGapNameNYF
This is important when doing external fills.
**/ public final int getNextAbsGapArrIdxNYF() { return i_outputArrIdx; } /**Get the name of the next absolute gap not yet filled. See getNextAbsGapArrIdxNYF.
This is important when doing external fills.
@returngetTemplate().getUSAPAbsolute().getUniqueString(getNextAbsGapArrIdxNYF())
@exception AssertException if isTemplateSet equals false.
**/
public final String getNextAbsGapNameNYF() {
if(!isTemplateSet()) {
throwAX("getNextAbsGapNameNYF: isTemplateSet() equals false.");
}
return getTemplate().getUSAPAbsolute().getUniqueString(getNextAbsGapArrIdxNYF()).getString();
}
/**
Has the gap with the provided name been filled?
@param s_gapName The name of the gap. @return true If this gap has been filled.Get the OWriter for an external fill. After you have completed filling this gap, you must declare this with declareExtFillComplete.
See getMidExtFillGapName, declareExtFillComplete and isMidExtFill.
An external fill is best for large, process intensive gaps. If you compile the text of this gap, and then--only after you have it all--fill the gap with it, then there will be a long pause while the gap text is being retrieved. Then, all of the sudden, all that text will just "snap" to the screen, as soon as the fill is executed. An external fill allows your text to be "streamed" to the user, on the fly.
The following conditions must be met before an external fill is legal:
hasGapBeenFilled(s_gapName)
must equal false. You can't fill the same gap twice.getTemplate().getTemplateData().getAOSLookup().getAOSLHashtable().getUniqueString(s_gapName).isSingular()
must be true. If there are more than one instance of this unique gap in the source text, an external fill won't work. See declareExtFillComplete.getNextAbsGapNameNYF().equals(s_gapName)
must be true. If this condition is not met, you'll get a list of all the absolute gaps preceding this one, in the error message.Since there are so many requirements for an external fill, it is safest to postpone all external fills until all other gaps have been filled. It is also recommended that you check all Templates at the start of your program, to ensure that the to-be-externally-filled gaps are found where you expect.
@param s_gapName The name of the gap to fill externally. **/ public final OWriter getOWForExtFill(String s_gapName) { final String sGOWFXF = "getOWForExtFill"; if(!isTemplateSet()) { throwAX(sGOWFXF, "isTemplateSet() is false."); } if(isMidExtFill()) { throwAX(sGOWFXF, "isMidExtFill() is true. You must declareExtFillComplete() before doing another external fill."); } if(!getTemplate().getAOSLHashtable().containsKey(s_gapName)) { throwAX(sGOWFXF, "getTemplate().getAOSLHashtable().containsKey('" + s_gapName + "') equals false."); } if(hasGapBeenFilled(s_gapName)) { throwAX(sGOWFXF, "hasGapBeenFilled('" + s_gapName + "') is true. You've already filled this gap in *this* TemplateFiller."); } if(!getTemplate().getTemplateData().getAOSLookup().getAOSLHashtable().getUniqueString(s_gapName).isSingular()) { throwAX(sGOWFXF, "getTemplate().getTemplateData().getAOSLookup().getAOSLHashtable().getUniqueString(s_gapName).isMultiple() equals true (" + getTemplate().getTemplateData().getAOSLookup().getAOSLHashtable().getUniqueString(s_gapName).getInstanceCount() + " instances). Although s_gapName ('" + s_gapName + "') has not yet been filled, an external fill many only occur against singular gaps."); } if(!getNextAbsGapNameNYF().equals(s_gapName)) { int i = getNextAbsGapArrIdxNYF(); int[] ai = new int[] {getTemplate().getUnqArrIdxFromAbs(i)}; if(i > 0) { int[] aiOneMore = new int[ai.length + 1]; for(int j = 0; j < ai.length; j++) { aiOneMore[j] = ai[j]; } aiOneMore[ai.length] = getTemplate().getUnqArrIdxFromAbs(--i); ai = aiOneMore; aiOneMore = null; } StringBuffer sb = new StringBuffer("getNextAbsGapNameNYF().equals('" + s_gapName + "') is false. Although s_gapName has not yet been filled, there are other gaps that exist (absolutely) before it, that need to be filled first: "); for(i = 0; i < ai.length; i++) { sb.append("'" + getTemplate().getUSAPUnique().getUniqueString(ai[i]).getString() + "'"); if(i < ai.length) { sb.append(", "); } } throwAX(sGOWFXF, sb.toString()); } //Everything looks good and ready for this external fill. sExtFillGapName = s_gapName; dbg("tf.getOWForExtFill('" + sExtFillGapName + "')"); return getOWriter(); } /**Is this TemplateFiller currently in the middle of an external fill?
See getMidExtFillGapName, declareExtFillComplete and getOWForExtFill.
@return true If getOWForExtFill has most recently been called, after declareExtFillComplete.If we're currently in the middle of an external fill, what is the gap name that is being filled?
See isMidExtFill, declareExtFillComplete and getOWForExtFill.
@return s_gapName exactly as passed into getOWForExtFill.Declare that the external fill has been completed.
See isMidExtFill, getMidExtFillGapName and getOWForExtFill.
This does exactly one thing...
fill(getMidExtFillGapName(), sES)
...which is why an external gap must be singular. If there are more than one instance of this gap in the source text, then an extenal fill could only populate one of those instances. The rest of the instances could only be populated by (in this case) empty string.
If you truly wanted to populate all instances with the same text, then you'd have to hold the result in memory, and output it in all the instances' locations. Since an external fill is generally for larger and more process intensive gaps, this is not a good idea.
@return s_gapName exactly as passed into getOWForExtFill. @exception AssertException if isMidExtFill equals false. **/ public final void declareExtFillComplete() { if(!isMidExtFill()) { throwAX("declareExtFillComplete: isMidExtFill() is false. Not currently in the middle of a external fill."); } String sXFGN = sExtFillGapName; sExtFillGapName = null; fill(sXFGN, sES); dbg("tf.declareExtFillComplete(): '" + sXFGN + "'"); } /**Fill in a single gap in the currently-set Template with the resulting text from a TOGOne.
@param s_gapName The name of the gap to fill in the currently-set Template. Passed directly to fill. @param tog_1 The TemplateOrderedGaps object, whose resulting text should fill in the gap name s_gapName, as existing in the currently-set Template. May not be null. @param s_fillText1 The fill text for the only unique gap existing in tog_1. May not be null. **/ public final void fill(String s_gapName, TOGOne tog_1, String s_fillText) { if(tfSub == null) { tfSub = new TemplateFiller(); } if(asFT_TOG1 == null) { asFT_TOG1 = new String[] {null}; } asFT_TOG1[0] = s_fillText; fill(s_gapName, tog_1, asFT_TOG1); asFT_TOG1[0] = null; } /**Fill in a single gap in the currently-set Template with the resulting text from a TOGTwo.
@param s_gapName The name of the gap to fill in the currently-set Template. Passed directly to fill. @param tog_2 The TemplateOrderedGaps object, whose resulting text should fill in the gap name s_gapName, as existing in the currently-set Template. May not be null. @param s_fillText1 The fill text for the first of two unique gaps existing in tog_2. May not be null. @param s_fillText2 The fill text for the second of two unique gaps existing in tog_2. May not be null. **/ public final void fill(String s_gapName, TOGTwo tog_2, String s_fillText1, String s_fillText2) { if(tfSub == null) { tfSub = new TemplateFiller(); } if(asFT_TOG2 == null) { asFT_TOG2 = new String[] {null, null}; } asFT_TOG2[0] = s_fillText1; asFT_TOG2[1] = s_fillText2; fill(s_gapName, tog_2, asFT_TOG2); asFT_TOG2[0] = null; asFT_TOG2[1] = null; } /**Fill in a single gap in the currently-set Template with the resulting text from a TOGThree.
@param s_gapName The name of the gap to fill in the currently-set Template. Passed directly to fill. @param tog_3 The TemplateOrderedGaps object, whose resulting text should fill in the gap name s_gapName, as existing in the currently-set Template. May not be null. @param s_fillText1 The fill text for the first of three unique gaps existing in tog_3. May not be null. @param s_fillText2 The fill text for the second of three unique gaps existing in tog_3. May not be null. @param s_fillText3 The fill text for the third of three unique gaps existing in tog_3. May not be null. **/ public final void fill(String s_gapName, TOGThree tog_3, String s_fillText1, String s_fillText2, String s_fillText3) { if(tfSub == null) { tfSub = new TemplateFiller(); } if(asFT_TOG3 == null) { asFT_TOG3 = new String[] {null, null, null}; } asFT_TOG3[0] = s_fillText1; asFT_TOG3[1] = s_fillText2; asFT_TOG3[2] = s_fillText3; fill(s_gapName, tog_3, asFT_TOG3); asFT_TOG3[0] = null; asFT_TOG3[1] = null; asFT_TOG3[2] = null; } /**Refill the gap with the gap itself.
Equal to reGap(s_gapName, getTemplate().getTagStart(), getTemplate().getTagEnd())
Note, if isTemplateSet equals false, an AssertException is thrown, not a NullPointerException.
**/ public final void reGap(String s_gapName) { String sTagStart = null; String sTagEnd = null; if(isTemplateSet()) { sTagStart = getTemplate().getTemplateData().getTagStart(); sTagEnd = getTemplate().getTemplateData().getTagEnd(); } reGap(s_gapName, sTagStart, sTagEnd); } /**Refill the gap with the gap itself.
This will make the gap appear as it originally existed in the template source text. Note that the gap is considered filled.
Equal to fill(s_gapName, s_gapStart + s_gapName + s_gapStart)
Fill in a single gap in the currently-set Template with the resulting text from a TemplateOrderedGaps.
@param s_gapName The name of the gap to fill in the currently-set Template. Passed directly to fill. @param t_rdrdGaps The TemplateOrderedGaps object, whose resulting text should fill in the gap name s_gapName, as existing in the currently-set Template. May not be null. @param as_fillText The array of fill text to be applied to t_rdrdGaps. Must not be null, and must have the same length ast_rdrdGaps.getUSAPUnique().getLength()
.
**/
public final void fill(String s_gapName, TemplateOrderedGaps t_rdrdGaps, String[] as_fillText) {
if(tfSub == null) {
//This is the first call to a function that uses tfSub. Create it.
tfSub = new TemplateFiller();
}
if(t_rdrdGaps == null) {
throwAX("fill", "t_rdrdGaps is null.");
}
if(as_fillText == null || as_fillText.length != t_rdrdGaps.getUSAPUnique().getLength()) {
throwAX("fill", "as_fillText must be non-null, and its length must be exactly t_rdrdGaps.getUSAPUnique().getLength().");
}
//Set t_rdrdGaps into the sub-tf.
tfSub.setTemplate(t_rdrdGaps);
//For every unique gap that exists in the TOG, in order, fill
//it with the corresponding string element from as_fillText.
for(int i = 0; i < t_rdrdGaps.getUSAPUnique().getLength(); i++) {
tfSub.fill(t_rdrdGaps.getOGConfig().getString(i), as_fillText[i]);
}
//Get the resulting text, and fill it into the currently-set
//in *this* TemplateFiller.
fill(s_gapName, tfSub.getResult());
}
/**
Fill in the requested gap with a string value.
@param s_gapName The name of the gap to be fill. Must exist according togetTemplate().getAOSLHashtable().containsKey(s_gapName)
.
@param s_fillText The text to fill the gap with. May not be null. This may be (or contain) another gap. For example:
"This is the text that \~G\~name\~EG\~ wants to fill this gap with."
Fill in the requested gap with an int value.
Equal to fill(s_gapName, (new Integer(i_fillValue)).toString())
Fill in the requested gap with a boolean value.
Equal to fill(s_gapName, (new Boolean(b_fillValue)).toString())
Has the requested gap been filled?
@param s_gapName The requested gap. Must equal the name of an existing gap. @return Has the gap at array indexgetTemplate().getAOSLHashtable().getUniqueString(s_gapName).getUnqArrIdx()
Get the resulting text from the Template, and all its filled gaps. The template is unset by this function.
NOTE: This function may only be used when getOWriter is of type xbn.output.OWIntoSB
For specifics on how the output (as returned by this function) is built, see the example in the documentation overview. The resulting output is built on the fly, as the gaps are filled, and not by this function. Before getOWForExtFill existed, this function did build this output. External fills are one of the more powerful recent additions to this class.
@return The entire template with all gaps replaced with text, and filled by this TemplateFiller. @exception AssertExceptionProvide a template and fill all of it's gaps with the same fill text. This function will work even if you're currently in the middle of filling another Template's gaps.
Why use this function at all? One realistic usage is for database SQL that will be used in a PreparedStatement. See DBCSPrepared for information.
**/ public final String getAllFilledWith(Template t_emplate, String s_fillText) { dbg("Filling all gaps with '" + s_fillText + "'"); if(tfSub == null) { tfSub = new TemplateFiller(); } tfSub.setTemplate(t_emplate); for(int i = 0; i < t_emplate.getUSAPUnique().getLength(); i++) { tfSub.fill(t_emplate.getUSAPUnique().getUniqueString(i).getString(), s_fillText); } return tfSub.getResult(); } /**Reset this TemplateFiller to its original state...as if you never set a Template or filled any gaps within it.
This should really really really not ever be used, except perhaps during debugging and development phases.
Note that this function leaves the curent OWriter alone. The only exception to this rule is if isOWriterOWIntoSB is true. In that case getOWIntoSB().reset() is called, to eliminate any current output.
**/ public final void forceReset() { if(asFillText != null) { if(template != null) { resetFillText(template.getUSAPUnique().getLength()); } else { resetFillText(); } } i_outputArrIdx = 0; template = null; sExtFillGapName = null; if(isOWriterOWIntoSB()) { getOWIntoSB().reset(); } } /**How many gaps have been filled so far?
@exception AssertException If isTemplateSet equals false. **/ public final int getGapsFilledCount() { if(!isTemplateSet()) { throwAX("getGapsFilledCount", "Must setTemplate before calling this function."); } int iGapsFilled = 0; for(int i = 0; i < getTemplate().getUSAPUnique().getLength(); i++) { if(asFillText[i] != null) { iGapsFilled++; } } return iGapsFilled; } /**How many gaps have not yet been filled?
@return(getTemplate().getUSAPUnique().getLength() - getGapsFilledCount())
@exception AssertException If isTemplateSet equals false.
**/
public final int getGapsNotYetFilledCount() {
if(!isTemplateSet()) {
throwAX("getGapsNotYetFilledCount", "Must setTemplate before calling this function.");
}
return (getTemplate().getUSAPUnique().getLength() - getGapsFilledCount());
}
/**
Get a String array containing all unique gap names that have yet to be filled.
Do not call this repeatedly, as it manually creates an array each time. Calling this two times in a row doesn't work?
@return A string array containing all unique gap names that have not yet been filled. If all gaps have been filled, return null. @exception AssertException If isTemplateSet equals false. **/ public final String[] getGapsNotYetFilled() { String[] asGapsNotYetFilled = null; try { int iGapsNotYetFilled = getGapsNotYetFilledCount(); if(iGapsNotYetFilled == 0) { return null; } asGapsNotYetFilled = new String[iGapsNotYetFilled]; } catch(AssertException ax) { throwAX("getGapsNotYetFilled", "Must setTemplate before calling this function."); } int iGNYF_arrayIndex = 0; for(int i = 0; i < getTemplate().getUSAPUnique().getLength(); i++) { if(asFillText[i] == null) { asGapsNotYetFilled[iGNYF_arrayIndex++] = getTemplate().getUSAPUnique().getUniqueString(i).getString(); } } return asGapsNotYetFilled; } /**Declare if it legal to call setOWriter/setOWIntoSB in mid-fill.
Get with doAllowOWSetInMidFill
Is it legal to call setOWriter/setOWIntoSB in mid-fill?
Set with setAllowOWSetInMidFill
Is the OWriter an OWIntoSB?
@return true Only if you used setOWIntoSB to set the OWriter, or used the non-OWriter constructors of This class.Get the OWriter for direct manipulation.
Set with setOWIntoSB or setOWriter
@return The OWriter as provided to setOWriter or setOWIntoSB. **/ public final OWriter getOWriter() { return owrtr; } /**Get the OWIntoSB for direct manipulation.
Set with setOWIntoSB or setOWriter
@exception AssertException If getOWriter is of any type except OWIntoSB. **/ public final OWIntoSB getOWIntoSB() { try { return (OWIntoSB)getOWriter(); } catch(ClassCastException ccx) { throwAX("getOWIntoSB", "May only be used when getOWriter() is of type xbn.output.OWIntoSB. Currently " + getOWriter().getClass().getName() + "."); } //Never reached. Required for compile. return null; } /**Set an OWriter into this TemplateFiller.
Get with getOWriter.
This Eliminate the current OWriter, and replaces it with parameter.
Note that calling setOWriter(new OWIntoSB()) is not the same as calling setOWIntoSB. If you do call this function with an OWIntoSB (or any other type), isOWriterOWIntoSB will always return false.
@param o_writer The OWriter that will do the outputting of the filled Template text. May not be null. @exception AssertException If doAllowOWSetInMidFill is false, and you are currently in the middle of filling a Template. **/ public final void setOWriter(OWriter o_writer) { if(o_writer == null) { throwAX("setOWriter", "o_writer is null."); } if(!doAllowOWSetInMidFill() && isTemplateSet() && !areAllGapsFilled()) { throwAX("setOWriter", "doAllowOWSetInMidFill() is false, isTemplateSet() is true and areAllGapsFilled() is false. You may not set a new OWriter into this class unless (1) no template is currently set or (2) a template is set, but the output has completed. In other words, if you want to setOWriter(), you must do so before calling setTemplate()."); } owrtr = o_writer; //If this is an OWIntoSB, then set this directly to false after //setting this function. bOWIsOWIntoSB = false; } /**Eliminate the current OWriter, and replaces it with a new OWIntoSB object.
Get with getOWriter.
OWIntoSB is a special OWriter that stores the resulting output into an internal StringBuffer. This holds the result internally until the getResult function is called.
Note that calling setOWriter(new OWIntoSB()) is not the same as calling this function. If you do call setOWriter with an OWIntoSB (or any other type), isOWriterOWIntoSB will always return false. The only thing that will make it return true is to call this function.
@exception AssertException If doAllowOWSetInMidFill is false, and you are currently in the middle of filling a Template. **/ public final void setOWIntoSB() { setOWriter(new OWIntoSB()); bOWIsOWIntoSB = true; } //Debugging output...START public final Outputter getOptrDbg() { return optrDbg; } public final void setOptrDbg(Outputter optr_dbg) { if(optr_dbg == null) { throwAX("setOutputter", "optr_dbg is null."); } optrDbg = optr_dbg; if(pcs == null && optrDbg.isOn()) { pcs = new PadChopString(new ConfigChop(35, "...", 3)); uString = new UtilString(); } } public final void dbg(String s) { getOptrDbg().write(s); } public final void dbgnl(String s) { getOptrDbg().writeNoln(s); } //Debugging output...END /** The number of unique gaps in the currently set template is always equal to or less than asFillText.length. asFillText expands to accomodate every template set into this TemplateFiller, but never shrinks. So we might have previously set a Template with a hundred gaps, the current Template might only have three. Even though asFillText has a hundred elements, there's no need to clear out all hundred. Only the first three are populated. **/ private void resetFillText(int i_uniqueGaps) { for(int i = 0; i < i_uniqueGaps; i++) { if(asFillText[i] != null) { asFillText[i] = null; } } i_uniqueGaps = 0; } private void resetFillText() { //We don't know or care how many unique gaps the //currently-set template has. Clear out all elements. resetFillText(asFillText.length); } private void throwAX(String s_function, String s_error) { String sTemplateName = null; if(getTemplate() != null && getTemplate().getName() != null) { sTemplateName = " [getTemplate().getName()='" + getTemplate().getName() + "']"; } else { sTemplateName = sES; } forceReset(); throwAX(s_function + sTemplateName + ": " + s_error); } }