cox.jmatt.java.MathTools
Class Question

java.lang.Object
  extended by cox.jmatt.java.MathTools.Question
All Implemented Interfaces:
MTestElement

public class Question
extends java.lang.Object
implements MTestElement

This is MathTools' basic unit of data storage and presentation. A Question consists of three basic parts: the ID, the Problem part and the Answer part. Since MathTools is designed to simplify creation and formatting of tests and worksheets this class also defines multiple formatting methods and plenty of formatting data, both global and local.

Concerning content, every individual Question component can be individually set or cleared. There are multiple methods for doing this along with a very broad setData() method to set up to everything at once. What's more, many methods that would ordinarily return void instead return a self-reference to allow for method chaining.

Templates

Question's unquestioned power-method is fillTemplate(). This method provides a very simple templating engine. It accepts a String template and a String array of replacement data. The replacement tokens are numbered and the token number equals the index of the array element that will replace it.

When called, fillTemplate() replaces the numbered elements in the template String with the appropriate element in the replacement array. The replacement tokens are of the form '<N>' where N is a number. This method is useful in and of itself but it also forms the basis for the other MathTools formatting methods. Other MathTools classes define a specific set of replacement tokens and accept a template String as an argument for maximum flexibility and simplicity.

The MathTestFormatter class provides a much more powerful templating engine, raising the Question (pun intended) 'Why here, too?' The answer is in intents. MathTestFormatter is test-centric in its design. It is not concerned with exactly how a fraction or radical should be formatted, merely with where they should go on the test. The fillTemplate() method here is concerned less with the overall test and most with the formatting of the individual element the Question represents.

Validating Strings

Another method (static, with an instance shadow) used ubiquitously throughout MathTools is the validString() method. This method accepts a String argument and returns true if the String sent in is non-null and has a trimmed length greater than zero.

Formatting and The Clicker

Each Question instance maintains four separate internal formats: ID, entire Question, Problem-only and Answer-only. Each of these formats is individually settable but the Question class itself maintains (static) default formats for each of these. For maximum ease of use simply set whatever default(s) are appropriate and only set what needs changing.

The Answer Token

The Answer Token is a part of the class that isn't really presentation nor is it data. Its original intent was as a simple String that could be used to split() the result of a formatting method's output. The default value is '@@' and it should not be changed without a valid reason. As with other data the Answer Token has a settable default value along with instance setter methods.

The Clicker

The Clicker is a number that can be accessed when formatting a Question's ID. Conceptually it represents a cheap plastic (or expensive metal) counter: a small box with one or more buttons and three or more digit-wheels. When a button is pressed the corresponding digit-wheel increments by one. When one of the wheels passes '9' it resets to '0' and automatically increments the next-higher wheel.

The Clicker, then, provides an internal 'clicky-counter' for the Question class. Although it defines both static and instance methods to set and increment, The Clicker itself is a static value. Its companion method numberToLetter() converts a numeric value, presumably The Clicker, to a one- or more letter combination.

ID Formatting

Manually setting a Question's ID to a valid String sets that String as the ID. Period. That can be bothersome, though, when assigning large numbers of relatively similar IDs. For this reason Question maintains a (static) default ID format. This format has access to The Clicker as a number, as lower-case letters or as UPPERCASE letters. The format is static but each instance's ID can be set using it. This is done automatically when a new Question is created but it can be forced by setting the (instance!) ID to null. This replaces the instance ID with the result of formatting the default ID (format) with The Clicker. Afterwards a quick call to click() increments The Clicker.

Version Codes

This class provides a way to generate version codes automatically. The formatVCode() methods provide formatting tokens based on the current time (full version!) and the Clicker. A formatting template with settable default determines the result of these methods.

Besides simple version codes this method can also be used for timestamps. It provides both the date and time formatted per the DateFormat constants SHORT, MEDIUM, LONG and FULL.

Built-In Formats

Concerning formatting questions, Question provides four pre-built format templates. Each of these is a static String constant that starts with 'FORMAT_'. Debug format is for dumping the internal data and shouldn't really be used for production. XML format is used by the toXML() method. The Properties and Velocity formats result in a java.util.Properties-type two-line result. The Velocity format uses underscores instead of dots to allow for easier use with the Apache Velocity templating engine.


Field Summary
static java.lang.String DEFAULT_ANSWER_FORMAT
          Default format template for the Answer part only: '<0>_Ans = <2>'.
static java.lang.String DEFAULT_ANSWER_TOKEN
          This is the default Answer Token: '@@'.
static java.lang.String DEFAULT_ID_FORMAT
          The default format used to generate ID Strings: 'Question_<0>.'
static java.lang.String DEFAULT_PROBLEM_FORMAT
          Default format template for the Problem only: '<0>_Prob = <1>'.
static java.lang.String DEFAULT_QUESTION_FORMAT
          Default format for the entire Question: '<0> <3> <1> <3> <2>'.
static java.lang.String DEFAULT_VCODE
          Version code default: <3><6><9><28>.
static java.lang.String FORMAT_DEBUG
          Debugging format, not for production use!
static java.lang.String FORMAT_PROPERTIES
          Simple Properties-style format.
static java.lang.String FORMAT_VELOCITY
          Apache Velocity-style format String.
static java.lang.String FORMAT_XML
          Format String for internal MathTools XML.
 
Constructor Summary
Question()
          Build a blank Question.
Question(Question pQues)
          Copy constructor.
Question(java.lang.String pProb, java.lang.String pAns)
          Create a Question with Problem and Answer specified.
Question(java.lang.String pID, java.lang.String pProb, java.lang.String pAns)
          Build a Question with ID, Problem and Answer specified.
 
Method Summary
 Question click()
          Shadow method for incrementClicker().
 Question copyOf()
          Create a copy of this Question.
static Question createQuestion()
          Static factory method to create a blank Question.
static Question createQuestion(java.lang.String... pData)
          Factory method to set up to all internal data.
 java.lang.String fill_Template(java.lang.String pTemplate, java.lang.Number[] pNData, boolean pForceInt)
          Instance version of fillTemplate(), Number version.
 java.lang.String fill_Template(java.lang.String pTemplate, java.lang.String[] pData)
          Instance version of fillTemplate() with a slightly changed name.
static java.lang.String fillTemplate(java.lang.String pTemplate, java.lang.Number[] pNData, boolean pForceInt)
          This is fillTemplate() designed around an array of Number instead of String.
static java.lang.String fillTemplate(java.lang.String pTemplate, java.lang.String[] pData)
          This is Question's power method.
 java.lang.String format()
          Format this Question per its internal format.
 java.lang.String format(java.lang.String pTemplate)
          Format this Question per the supplied template String.
 java.lang.String formatAnswer()
          Format per the internal Answer format.
 java.lang.String formatNewVCode()
          Instance shadow.
 java.lang.String formatNewVCode(java.lang.String pFormat)
          Instance shadow.
 java.lang.String formatProblem()
          Format per the internal Problem format.
static java.lang.String formatVCode()
          Format a VCode per the currently-set default.
static java.lang.String formatVCode(java.lang.String pFormat)
          Format a version code per the supplied template.
 java.lang.String getAnswer()
          Fetch the current value of the Answer.
 java.lang.String getAnswerToken()
          Fetch the current Answer Token.
 java.lang.String getID()
          Retrieve the currently-set ID.
 java.lang.String getProblem()
          Fetch the current value of the Problem.
static void incrementClicker()
          Increment the clicker by 1.
 boolean isValidString(java.lang.String pStr)
          This is the instance version of validString().
 Question newQuestion()
          Shadow method for createQuestion().
 Question newQuestion(java.lang.String... pData)
          Instance shadow for the full createQuestion() method.
static java.lang.String numberToLetter(long pNum)
          Convert a number to an uppercase letter.
 Question parse_Question(java.lang.String pData)
          Instance shadow for the single-String parse method.
 Question parse_Question(java.lang.String pData, java.lang.String pSplitter)
          Instance shadow for parseQuestion(String, String).
static Question parseQuestion(java.lang.String pData)
          Convenience method for parseQuestion(String, null).
static Question parseQuestion(java.lang.String pData, java.lang.String pSplitter)
          Generate a Question by breaking a string on a specified splitting sequence.
 java.lang.String re_quote(java.lang.String pCooked)
          Instance shadow.
 Question requote()
          This method requote()'s the (presumably-escaped) ID, Problem and Answer.
static java.lang.String requote(java.lang.String pCooked)
          This method undoes unquote().
 Question setAnswer(java.lang.String pAns)
          Set the Answer part of this Question.
 Question setAnswerToken(java.lang.String pToken)
          Set the Answer Token for this Question.
static void setClicker(int pNewVal)
          Set a new value for the clicker.
 Question setData(java.lang.String... pData)
          Set up to ALL aspects of this Question in one fell swoop.
static void setDefaultEscapeXML(boolean pYesNo)
          Set the default value for XML-escaping Problem and Answer content.
static void setDefaultFormat(java.lang.String... pFormats)
          Set a new default format for all subsequent instances.
 Question setEscapeXML(boolean pYesNo)
          Set the 'escape XML' state for this instance and return a self-reference.
 Question setFormat(java.lang.String... pFormats)
          Set the internal formats used to format the individual components.
 Question setID(java.lang.String pNewID)
          Set the ID for this Question.
static void setIDFormat(java.lang.String pFormat)
          This method sets the default format used to generate Question IDs.
 Question setNewClicker(int pNewVal)
          Instance version of setClicker().
 Question setNewDefaultEscapeXML(boolean pYesNo)
          Shadow method to set default XML escape.
 Question setNewDefaultFormat(java.lang.String... pFormats)
          Shadow method to set default format.
 void setNewVCFormat(java.lang.String pFormat)
          Instance shadow.
 Question setProblem(java.lang.String pProb)
          Set the Problem part of this Question.
static void setVCFormat(java.lang.String pFormat)
          Set the default version code format.
 java.lang.String toString()
          Return a simple constructor-like representation of this Question.
 java.lang.String toXML()
          Return a simple XML representation of this Question.
 java.lang.String un_quote(java.lang.String pRaw)
          Instance method.
 Question unqoute()
          This method unquote()'s the ID, Problem and Answer.
static java.lang.String unquote(java.lang.String pRaw)
          This method replaces newlines, tabs, returns and quotes.
static boolean validString(java.lang.String pStr)
          Check to see if a string is null or of zero length AFTER its trim() function is applied: whitespace characters are considered length zero!
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

DEFAULT_ANSWER_TOKEN

public static final java.lang.String DEFAULT_ANSWER_TOKEN
This is the default Answer Token: '@@'.

See Also:
Constant Field Values

DEFAULT_ID_FORMAT

public static final java.lang.String DEFAULT_ID_FORMAT
The default format used to generate ID Strings: 'Question_<0>.'

See Also:
Constant Field Values

DEFAULT_QUESTION_FORMAT

public static final java.lang.String DEFAULT_QUESTION_FORMAT
Default format for the entire Question: '<0> <3> <1> <3> <2>'.

See Also:
Constant Field Values

DEFAULT_PROBLEM_FORMAT

public static final java.lang.String DEFAULT_PROBLEM_FORMAT
Default format template for the Problem only: '<0>_Prob = <1>'.

See Also:
Constant Field Values

DEFAULT_ANSWER_FORMAT

public static final java.lang.String DEFAULT_ANSWER_FORMAT
Default format template for the Answer part only: '<0>_Ans = <2>'.

See Also:
Constant Field Values

FORMAT_XML

public static final java.lang.String FORMAT_XML
Format String for internal MathTools XML.

See Also:
Constant Field Values

FORMAT_PROPERTIES

public static final java.lang.String FORMAT_PROPERTIES
Simple Properties-style format.

See Also:
Constant Field Values

FORMAT_VELOCITY

public static final java.lang.String FORMAT_VELOCITY
Apache Velocity-style format String.

See Also:
Constant Field Values

FORMAT_DEBUG

public static final java.lang.String FORMAT_DEBUG
Debugging format, not for production use!

See Also:
Constant Field Values

DEFAULT_VCODE

public static final java.lang.String DEFAULT_VCODE
Version code default: <3><6><9><28>.

See Also:
Constant Field Values
Constructor Detail

Question

public Question()
Build a blank Question.


Question

public Question(java.lang.String pProb,
                java.lang.String pAns)
Create a Question with Problem and Answer specified.


Question

public Question(java.lang.String pID,
                java.lang.String pProb,
                java.lang.String pAns)
Build a Question with ID, Problem and Answer specified.


Question

public Question(Question pQues)
Copy constructor. If pQues is null an empty Question is returned. NO FORMATTING INFORMATION IS COPIED!! Only data.

Method Detail

createQuestion

public static Question createQuestion()
Static factory method to create a blank Question.


newQuestion

public Question newQuestion()
Shadow method for createQuestion().


createQuestion

public static Question createQuestion(java.lang.String... pData)
Factory method to set up to all internal data. Parameters are per setData().


newQuestion

public Question newQuestion(java.lang.String... pData)
Instance shadow for the full createQuestion() method.


parseQuestion

public static Question parseQuestion(java.lang.String pData,
                                     java.lang.String pSplitter)

Generate a Question by breaking a string on a specified splitting sequence. If the resulting array has two or three elements they are formed into a new Question (ID + Problem + Answer or Problem + Answer). If pData is null or blank or the split array is not two or three elements a blank Question is returned. If pSplitter is null or blank the default Answer Token ('@@') is used.

This method is provided to allow Questions to be stored compactly as single Strings. Of course scripts can also build the requisite String manually and parse it into a Question when needed. Judicious use of the unquote() and quote() methods can tidy things up as needed.

Parameters:
pData - A String containing two or three Question components.
pSplitter - The String on which pData is to be split.

parse_Question

public Question parse_Question(java.lang.String pData,
                               java.lang.String pSplitter)
Instance shadow for parseQuestion(String, String).


parseQuestion

public static Question parseQuestion(java.lang.String pData)
Convenience method for parseQuestion(String, null).


parse_Question

public Question parse_Question(java.lang.String pData)
Instance shadow for the single-String parse method.


validString

public static boolean validString(java.lang.String pStr)
Check to see if a string is null or of zero length AFTER its trim() function is applied: whitespace characters are considered length zero!

Parameters:
pStr - The String to check.
Returns:
false if the String is null or of zero length, true otherwise.

isValidString

public boolean isValidString(java.lang.String pStr)
This is the instance version of validString(). The name is slightly altered.


unquote

public static java.lang.String unquote(java.lang.String pRaw)
This method replaces newlines, tabs, returns and quotes. The replacement tokens are longer than one character but can be read as to what they are. The intent with this method is to allow a String containing potentially irritating formatting characters to be expressed as a single unbroken line. Because of the inherent instability in trying to out-think the number of backslashes required the replacement tokens are mangled versions of the spelling of what they replace. If this method behaves irrationally the replacement token characters should be checked. To view these tokens unquote() a String with the formatting characters and print it from a script.

Parameters:
pRaw - The String containing embedded tabs, newlines etc.
Returns:
The same String but with escapes replacing the embedded characters.

un_quote

public java.lang.String un_quote(java.lang.String pRaw)
Instance method.


requote

public static java.lang.String requote(java.lang.String pCooked)
This method undoes unquote(). It restores the original characters into the supplied String.

Parameters:
pCooked - A String containing converted (escaped) control characters.
Returns:
The original String with the raw control characters restored.

re_quote

public java.lang.String re_quote(java.lang.String pCooked)
Instance shadow.


fillTemplate

public static java.lang.String fillTemplate(java.lang.String pTemplate,
                                            java.lang.String[] pData)

This is Question's power method. It provides a very basic templating engine. The template itself is a string containing tokens of the form '<X>' or '<KX>' where X is a number. Each numbered token is replaced with the corresponding element from the String[] array supplied to the method. Invalid tokens are ignored as are numbers outside the array supplied. If the template is null or blank it is returned as-is. If the replacement array is null or empty, the template is returned unaltered. The 'K' form of the token is there for Knob identification; either form is equally valid and both may be mixed.

This method does define one special token: '<-1>' is a blanking token; it is replaced with an empty String after all other tokens have been replaced.

Parameters:
pTemplate - A String template containing one or more replacement tokens as defined above.
pData - A String array containing replacement data for the tokens in the template.
Returns:
A fresh String with all tokens replaced.

fill_Template

public java.lang.String fill_Template(java.lang.String pTemplate,
                                      java.lang.String[] pData)
Instance version of fillTemplate() with a slightly changed name.


fillTemplate

public static java.lang.String fillTemplate(java.lang.String pTemplate,
                                            java.lang.Number[] pNData,
                                            boolean pForceInt)
This is fillTemplate() designed around an array of Number instead of String. The pForceInt flag can be set to 'true' to format the Numbers as integer type (long, specifically), but should only be used when the Numbers are integer type.

Parameters:
pTemplate - A String template containing replacement tokens.
pNData - A Number array with replacement values.
pForceInt - Set 'true' to force an integer value.
Returns:
A fresh String with all the numeric tokens replaced.

fill_Template

public java.lang.String fill_Template(java.lang.String pTemplate,
                                      java.lang.Number[] pNData,
                                      boolean pForceInt)
Instance version of fillTemplate(), Number version.


setDefaultFormat

public static void setDefaultFormat(java.lang.String... pFormats)
Set a new default format for all subsequent instances. If a format is null or blank DEFAULT_QUESTION_FORMAT is used. Replacement tokens are per the format(String) method. Up to three defaults can be specified; use is per setFormat(String...).

Parameters:
pFormats - The new default format templates. If null this method returns silently.

setNewDefaultFormat

public Question setNewDefaultFormat(java.lang.String... pFormats)
Shadow method to set default format. Returns a self-reference.


setDefaultEscapeXML

public static void setDefaultEscapeXML(boolean pYesNo)
Set the default value for XML-escaping Problem and Answer content. Unless this is handled explicitly it should always be 'true.'


setNewDefaultEscapeXML

public Question setNewDefaultEscapeXML(boolean pYesNo)
Shadow method to set default XML escape.


incrementClicker

public static void incrementClicker()
Increment the clicker by 1.


click

public Question click()
Shadow method for incrementClicker(). Returns a self-reference to allow method chaining.


setClicker

public static void setClicker(int pNewVal)
Set a new value for the clicker. If less than zero it becomes zero.

Parameters:
pNewVal - The new clicker value.

setNewClicker

public Question setNewClicker(int pNewVal)
Instance version of setClicker(). Returns a self-reference to allow chaining.


numberToLetter

public static java.lang.String numberToLetter(long pNum)
Convert a number to an uppercase letter. Does not include 'I' or 'O' since this is primarily to represent question numbers as letters. If the number is too great for a single letter the sequence grows to two letters: 'AA,' 'AB,' 'AC' etc.

Parameters:
pNum - The number to express as a letter.

setVCFormat

public static void setVCFormat(java.lang.String pFormat)
Set the default version code format. Setting null or blank sets the default.


setNewVCFormat

public void setNewVCFormat(java.lang.String pFormat)
Instance shadow.


formatVCode

public static java.lang.String formatVCode(java.lang.String pFormat)

Format a version code per the supplied template. Most of the replacement tokens are based on a java.util.Calendar created as soon as this method is called. The Calendar is specifically set to lenient mode and where applicable zero-based values (offsets) are used. Each quantity supplied has three tokens: the raw number, the number as UPPER case letters and as lower case.

The formatting tokens are:

RawUCLCDescription
<0><1><2>Current year, 4-digit.
<3><4><5>Current year, 2-digit.
<6><7><8>Current month.
<9><10><11>Current day of month.
<12><13><14>Current hour (0 - 23).
<15><16><17>Current minute.
<18><19><20>Current second.
<21><22><23>Current millisecond.
<24><25><26>The long time in millis.
<27><28><29>Long time in millis modded to a two-letter String.
<30><31><32>Long time in millis modded to a single letter String.
<33><34><35>The Clicker.
DateTimeTimestamp Style
<36><37>DateFormat.SHORT.
<38><39>DateFormat.MEDIUM.
<40><41>DateFormat.LONG.
<42><43>DateFormat.FULL.

If 'pFormat' is null or blank DEFAULT_VCODE is used.


formatNewVCode

public java.lang.String formatNewVCode(java.lang.String pFormat)
Instance shadow.


formatVCode

public static java.lang.String formatVCode()
Format a VCode per the currently-set default.


formatNewVCode

public java.lang.String formatNewVCode()
Instance shadow.


setIDFormat

public static void setIDFormat(java.lang.String pFormat)

This method sets the default format used to generate Question IDs. Null or blank resets it to DEFAULT_ID_FORMAT. There are three replacement tokens available:

This value remains until it is changed.

Parameters:
pFormat - The new ID format String.

setID

public Question setID(java.lang.String pNewID)
Set the ID for this Question. If pNewID is null or blank a default ID is assigned based on the default format and current Clicker. Returns a self-reference to allow method chaining.

Parameters:
pNewID - The new ID to assign.

getID

public java.lang.String getID()
Retrieve the currently-set ID. No formatting takes place here.


setProblem

public Question setProblem(java.lang.String pProb)
Set the Problem part of this Question. If null a blank String is assigned.

Parameters:
pProb - The new value for the Problem.

getProblem

public java.lang.String getProblem()
Fetch the current value of the Problem.


setAnswer

public Question setAnswer(java.lang.String pAns)
Set the Answer part of this Question. If null a blank String is assigned.

Parameters:
pAns - The new value for the Answer.

getAnswer

public java.lang.String getAnswer()
Fetch the current value of the Answer.


setAnswerToken

public Question setAnswerToken(java.lang.String pToken)
Set the Answer Token for this Question. If pToken is null the default Answer Token is used.

Parameters:
pToken - The new value for the Answer Token.

getAnswerToken

public java.lang.String getAnswerToken()
Fetch the current Answer Token.


setData

public Question setData(java.lang.String... pData)

Set up to ALL aspects of this Question in one fell swoop. The number of arguments is valid for up to four elements. These are interpreted as follows:

Any other argument lengths are ignored. A self-reference is returned.

Parameters:
pData - Up to four Strings for each component.

format

public java.lang.String format(java.lang.String pTemplate)

Format this Question per the supplied template String. All data is supplied as fillTemplate()-style replacement tokens. The tokens available are:

This is the base method for all other Question.format() methods so these are the replacement tokens available to them.

Specified by:
format in interface MTestElement
Parameters:
pTemplate - A template String used to format the Question.
Returns:
The freshly-formatted String based on the template sent in and the current data set.

setFormat

public Question setFormat(java.lang.String... pFormats)

Set the internal formats used to format the individual components. One, two or three arguments are valid; the interpretation depends on the number:

Any other number of arguments are ignored. A self-reference is returned.

Parameters:
pFormats - Up to three Strings used for the internal format(s) for this instance.

format

public java.lang.String format()
Format this Question per its internal format.

Specified by:
format in interface MTestElement

formatProblem

public java.lang.String formatProblem()
Format per the internal Problem format.

Specified by:
formatProblem in interface MTestElement

formatAnswer

public java.lang.String formatAnswer()
Format per the internal Answer format.

Specified by:
formatAnswer in interface MTestElement

toString

public java.lang.String toString()
Return a simple constructor-like representation of this Question.

Overrides:
toString in class java.lang.Object

setEscapeXML

public Question setEscapeXML(boolean pYesNo)
Set the 'escape XML' state for this instance and return a self-reference. Unless the content is XML or escaping is handled explicitly this flag should always be 'true.'

Parameters:
pYesNo - true to escape XML content, false to disable.

toXML

public java.lang.String toXML()
Return a simple XML representation of this Question. This particular format is internal to MathTools and not meant to be used outside of it. It consists of a <Question> tag with an 'id=' attribute and two child elements: <Problem> and <Answer>.

Specified by:
toXML in interface MTestElement

copyOf

public Question copyOf()
Create a copy of this Question. Only data is copied; formatting information and the Answer Token are not.

Specified by:
copyOf in interface MTestElement

unqoute

public Question unqoute()
This method unquote()'s the ID, Problem and Answer. This allows multiline content to be represented on a single, compact line. A self-reference is returned.


requote

public Question requote()
This method requote()'s the (presumably-escaped) ID, Problem and Answer. This restores the original formatting.