|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | |||||||||
java.lang.Objectcom.ccg.macros.AtMacros
public class AtMacros
Implementation of a "@macro" Interpreter.
This class provides all of the building blocks for a full macro
interpreter. It has all of the tools necessary
to scan ASCII text files looking for "@macros" which it will
then attempt to process.
A "@macro" entered in the following form will always be recognized:
@NAME(["ARG0"][,"ARG1"][,"ARG2"]...)
By default, the NAME of the macro must contain only lower case characters ('a'-'z'), upper case characters ('A'-'Z'), digits ('0'-'9') and the underscore character ('_').
For example:
@define("pkb","Paul Blankenbaker")
The following alternative forms can be used as well:
Your best bet is to use the full form (include the parenthesis and argument quoting) as that form will always be processed as you expect.
At times, you may find that you need to escape characters in the arguments you pass to the macros (in particular the double quote character). The standard Java escape characters can be used in a quoted argument. For example, to pass the argument A "very" wet day! as a argument, one would construct the macro in the following form:
@define("dayType","A \"very\" wet day!")
NOTE:The escape characters are only recognized within
quoted parameters. The following escape sequences are supported:
| Escape Seq | Unicode Value | Description |
|---|---|---|
| \b | \u0008 | Backspace |
| \f | \u000c | Form feed |
| \n | \u000a | Line feed (new line) |
| \r | \u000d | Carriage return |
| \t | \u0009 | Tab |
| \' | \u0027 | Single Quote |
| \" | \u0022 | Double Quote |
| \\ | \u005c | Backslash |
| \( | \u0040 | Begin Parenthesis |
| \) | \u0041 | End Parenthesis |
| \uXXXX | \uXXXX | Any unicode character - must use 4 hex digits |
Using an unrecognized escape sequence in a string will have unpredictable results. Most likely, the escape character will simply be ignored (and not appear in the output). You may find yourself hit with this when quoting DOS style file names. For example, "c:\t.txt" should be written as "c:\\t.txt" to prevent the "\t" from coming out as a tab character.
Also, the escaping of a double quote is only required (it never hurts to do it), if:
For example, the following parameters are equal "Hello \"Paul\"." and "Hello "Paul".", however the first form is preferred (support of the latter form was added later as it seemed reasonable). However, "\"Paul\", B." works where as ""Paul", B." does not (due to the comma following the double quote).
There is one issue in regards to including paranthesis in quoted strings. For example, consider the following:
@define("FullName","@param(0) @param(1)")
@define("PlusPhone","@FullName("@param(0)","@param(1)") (@param(2))")
@define("UnmatchedParen","((--->")
The definition of "PlusPhone" above wants to pass two parameters to the "@define" macro. The first parameter is not a problem, but the second parameter contains nested quoted arguments. The interpreter is "smart" in that it detects the parenthesis following "@FullName" and ignores all quotes until the last parenthesis is found. This allows the interpreter to correctly extract the two arguments in the complex example. However, because of this rule, the "UnmatchedParen" will not be interpretted properly. When the two mismatched parathesis in "((--->" string are encountered the interpreter will ignore the ending quote until it finds two matching ending parenthesis. If you find yourself in this situation, you will need to "escape" your parenthesis and write your macro as follows:
@define("FullName","@param(0) @param(1)")
@define("PlusPhone","@FullName("@param(0)","@param(1)") (@param(2))")
@define("UnmatchedParen","\(\(--->")
@define(pkb,"@PlusPhone(Paul,"Blankenbaker","555-7676")")
@UnmatchedParen() @pkb
It should be noted, that this class doesn't actually provide any
built in macros itself. This class just provides the parsing
building blocks and methods to make the construction of custom
macro sets possible. Typically other classes make use of the addMacro(String,String) method to define simple text replacement,
the addMacro(String,MacroHandler) method to install more
sophisticated macro handlers, and the addMacros(Object) to
automatically add methods with a certain signature to the set of
recognized macro handlers.
The At class is a full implementation of an
interpreter which defines several built in macros and provides a
means for additional macros to be defined based on the contents of
the processed file.
At| Constructor Summary | |
|---|---|
AtMacros()
Initializes object to the default parsing rules. |
|
AtMacros(AtMacros from)
A copy constructor of another AtMacros object. |
|
| Method Summary | |
|---|---|
void |
addMacro(String name,
MacroHandler mh)
Associate a MacroHandler with a macro name. |
void |
addMacro(String name,
String val)
Add a simple string subsitution macro. |
void |
addMacros(Object macroHandler)
Add all "macro handling methods" from a class to our defined set. |
int |
getDepth()
Get the current depth of the recursion as we are processing |
char |
getEndParamChar()
Get the symbol which indicates the end of the parameter list |
char |
getEndQuoteChar()
Get the symbol which ends a "quoted" string |
char |
getEscapeChar()
Get the "escape" character which can appear in quoted strings |
Object |
getMacro(String name)
Fetch the object definition for a particular macro. |
Enumeration |
getMacroNames()
Fetch the list of all macro names which are currently defined. |
String |
getParameter(int i)
Fetch one of the parameters (arguments) passed to a macro. |
String |
getParameter(int i,
boolean eval)
Fetch one of the parameters (arguments) passed to a macro. |
int |
getRecursionDepth()
Get the number of recursive calls allowed while evalutating |
char |
getSepParamChar()
Get the character used to separate parameters in a parameter list |
char |
getStartMacroChar()
Get the symbol which indicates the start of a macro |
char |
getStartParamChar()
Get the symbol which indicates the start of the parameter list |
char |
getStartQuoteChar()
Get the symbol which starts a "quoted" string |
void |
interpret(Input in,
Output out)
Process a input source and write the results to a output destination. |
String |
interpret(String in)
Process a source string and return the resulting string. |
void |
interpretCheck(Input in,
Output out)
Process a input source and write the results to a output destination. |
String |
interpretCheck(String in)
Process a source string and return the resulting string. |
protected Vector |
parseParams(Input in)
|
void |
setDepth(int val)
Set the current depth of the recursion as we are processing |
boolean |
setEndMacroChar(char match,
boolean indicates_end)
Set/clear individual character which indicates end of macro name. |
boolean |
setEndMacroChars(String val)
Set the symbol(s) which indicate the end of a macro name |
void |
setEndParamChar(char val)
Set the symbol which indicates the end of the parameter list |
void |
setEndQuoteChar(char val)
Set the symbol which ends a "quoted" string |
void |
setEscapeChar(char val)
Set the "escape" character which can appear in quoted strings |
void |
setRecursionDepth(int val)
Set the number of recursive calls allowed while evalutating Typically one doesn't need to worry about setting a recursion depth limit (the default value should be sufficient in most cases). |
void |
setSepParamChar(char val)
Set the character used to separate parameters in a parameter list |
void |
setStartMacroChar(char val)
Set the symbol which indicates the start of a macro |
void |
setStartParamChar(char val)
Set the symbol which indicates the start of the parameter list |
void |
setStartQuoteChar(char val)
Set the symbol which starts a "quoted" string |
| Methods inherited from class java.lang.Object |
|---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
| Constructor Detail |
|---|
public AtMacros()
This constructor prepares the macro interpreter with the default parsing rules, but without any definitions.
After construction, one will typically use the the "add macro"
methods to define macros (see addMacro(String,String),
addMacro(String,MacroHandler), and addMacros(Object)).
Typically one will probably not want to change the parsing
characters, HOWEVER you can with methods like setStartMacroChar(char), setEndMacroChars(String),
etc.
public AtMacros(AtMacros from)
AtMacros object.
This constructor makes a duplicate of another AtMacros object. Initially after construction, both objects will
have the same set of definitions - however any new definitions
added to either the new copy or the original will only affect the
object they are added to (each object will have its own
definition rules after the intial construction).
from - The AtMacrosAtMacros()| Method Detail |
|---|
public String getParameter(int i,
boolean eval)
throws InterpretException,
IOException
This method is used by macro handlers to retrieve arguments
which are passed to the macro. For example, if one were to write
a macro handler for the "@define(NAME,TEXT)" macro, the
handler would use this method to retrieve the information (see
At.define(com.ccg.macros.Output, java.util.Vector) for the definition of this handler).
For example, if the following text were being processed by the "define" macro handler:
@define("pkb","Paul Blankenbaker")
The "define" macro handler would get the value pkb if
it invoked getParameter(0), and the value
Paul Blankenbaker if it invoked getParameter(1).
Requesting a parameter that was not passed returns a zero length string (not null).
It should be noted that each parameter returned is also run through the interpreter if you set the second parameter to true. This means that if one of the arguments contains macros itself, they will be expanded in the returned result. Pass false as the second parameter to get the "raw" string value of the original parameter.
index - The index of the argument you want to request (0 correpsonds
to the first argument, 1 to the second, and so on).eval - Whether the raw value of the parameter should be evaluated or
not.
IOException - If a I/O error is encountered when reading from a input
source, or writing to a output destination.
InterpretException - If the contents of the source being interpretted violates the
rules of the interpreter. Note, each interpretter is able to
define its own set of rules as to what is allowed or not.
public String getParameter(int i)
throws InterpretException,
IOException
This method is used by macro handlers to retrieve arguments
which are passed to the macro. For example, if one were to write
a macro handler for the "@define(NAME,TEXT)" macro, the
handler would use this method to retrieve the information (see
At.define(com.ccg.macros.Output, java.util.Vector) for the definition of this handler).
For example, if the following text were being processed by the "define" macro handler:
@define("pkb","Paul Blankenbaker")
The "define" macro handler would get the value pkb if
it invoked getParameter(0), and the value
Paul Blankenbaker if it invoked getParameter(1).
Requesting a parameter that was not passed returns a zero length string (not null).
It should be noted that each parameter returned is also run through the interpreter. This means that if one of the arguments contains macros itself, they will be expanded in the returned result.
index - The index of the argument you want to request (0 correpsonds
to the first argument, 1 to the second, and so on).
IOException - If a I/O error is encountered when reading from a input
source, or writing to a output destination.
InterpretException - If the contents of the source being interpretted violates the
rules of the interpreter. Note, each interpretter is able to
define its own set of rules as to what is allowed or not.
public void addMacro(String name,
String val)
This command defines (or replaces an existing definition) a
macro which evaluates to a simple text replacement. Hence, when
the macro is encountered during processing it will be replaced
with the interpretted value assigned. For example:
public static void foo(AtMacros am) {
am.addMacro("first","Paul");
am.addMacro("last","Blankenbaker");
am.addMacro("name","@first() @last()");
}
After the following is run, when the macro "@first" is encountered in the text being processed, it will be replaced with "Paul". The key thing to notice here is that the replaced text is also interpretted. This means that when the "@name" macro is encountered in the text being processed, its contained text will be interpretted as well. This would result in "Paul Blankenbaker" appearing in the output in this example.
mname - The name of the macro to define (if you pass null or a zero
length string we ignore your request).val - The value to associate with the macro (null is treated like "")addMacros(java.lang.Object)public Object getMacro(String name)
mname - The name of the macro you want to lookup the associated value
for. You can pass null - and get null back.
object associated with the macro
name, or null if there isn't one associated.public Enumeration getMacroNames()
list of all macro names which are
currently defined.
public void addMacro(String name,
MacroHandler mh)
MacroHandler with a macro name.
This installs any object which implements the MacroHandler interface into the defined set of
macros.
mname - The name of the macro to define (this must NOT be null!).val - The value to associate with the macro (null is treated like "")public void addMacros(Object macroHandler)
This method can be used to install a LOT of macro handlers based upon the method signatures within the object passed. It uses Java's reflection mechanisms to inspect the methods in the object passed. For every method which matches the following signature:
public void mName(Outputout,Vectorargs) throwsIOException,InterpretException
A new macro is added such that if the method name in its macro form ("@mName") is encountered, the associated method in the object passed will be invoked to carry out the processing.
This is the easy way to add your own specialized macro
handlers, and what the At utility relies upon to add all
of its "built-in" functions (like: "@define",
"@include", "@param", etc).
o - The object to inspect and look for methods matching the rules
specified above (must not be null).At
public void interpret(Input in,
Output out)
throws IOException,
InterpretException
input source and write the results to a output destination.
This is one of the methods used to actually do the processing of data. It reads information from the input, processes any contained macros and writes the results to the output.
This is how one typically starts to process macros. This
method simply resets our current recursion depth and then invokes
the recursion safe
implementation to do the actual processing.
interpret in interface Interpreterin - A input source to read and interpretout - A output destination to write the results of
the interpretation.
InterpretException - If a internal (or macro error) is encountered while processing.
IOException - If a problem reading input or writing output is encountered.interpret(String),
interpretCheck(Input,Output)
public String interpret(String in)
throws IOException,
InterpretException
This method evaluates a simple string for any contained macros. Any contained macros are expanded and the resulting string is returned.
in - A string to interpret - if you pass null you get null back.
InterpretException - If a internal (or macro error) is encountered while processing.
IOException - If a problem reading input or writing output is encountered.interpret(Input,Output)
public String interpretCheck(String in)
throws IOException,
InterpretException
This method evaluates a simple string for any contained macros. Any contained macros are expanded and the resulting string is returned.
Since macros often require recursive evaulation, this method
makes sure that the recursion depth is not
exceeded. If the recursion depth is exceeded, a Interpret exception is thrown indicating as
much.
in - A string to interpret - if you pass null you get null back.
InterpretException - If a internal (or macro error) is encountered while processing.
IOException - If a problem reading input or writing output is encountered.interpretCheck(Input,Output)
public void interpretCheck(Input in,
Output out)
throws IOException,
InterpretException
input source and write the results to a output destination.
This is one of the methods used to actually do the processing of data. It reads information from the input, processes any contained macros and writes the results to the output.
Since macros often require recursive evaulation, this method
makes sure that the recursion depth is not
exceeded. If the recursion depth is exceeded, a Interpret exception is thrown indicating as
much.
in - A input source to read and interpretout - A output destination to write the results of
the interpretation.
InterpretException - If a internal (or macro error) is encountered while processing.
IOException - If a problem reading input or writing output is encountered.interpret(String),
interpret(Input,Output)public void setDepth(int val)
val - New int value to assign.getDepth()public int getDepth()
setDepth(int)public void setRecursionDepth(int val)
This value sets the maximum recursive call limit. If the interpretation of the source input requires a recursion level greater than this value, the interpreter will give up and throw an exception. This provides a "safety" from entering a infinite recursion loop that doesn't terminate until memory is exhausted.
val - New int value to assign.getRecursionDepth()public int getRecursionDepth()
setRecursionDepth(int)public void setStartMacroChar(char val)
val - New char value to assign.getStartMacroChar()public char getStartMacroChar()
setStartMacroChar(char)public boolean setEndMacroChars(String val)
val - String containing characters which mark the end of a token.
public boolean setEndMacroChar(char match,
boolean indicates_end)
This method can be used to individually add/remove characters which indicate the end of a macro name.
c - The character which we are trying to match againstindicates_end - Set to true if you want the character to indicate the end of a
macro, or false if you don't want it to indicate the end.
setEndMacroChars(java.lang.String)public void setStartQuoteChar(char val)
val - New char value to assign.getStartQuoteChar()public char getStartQuoteChar()
setStartQuoteChar(char)public void setEndQuoteChar(char val)
val - New char value to assign.getEndQuoteChar()public char getEndQuoteChar()
setEndQuoteChar(char)public void setEscapeChar(char val)
val - New char value to assign.getEscapeChar()public char getEscapeChar()
setEscapeChar(char)public void setStartParamChar(char val)
val - New char value to assign.getStartParamChar()public char getStartParamChar()
setStartParamChar(char)public void setEndParamChar(char val)
val - New char value to assign.getEndParamChar()public char getEndParamChar()
setEndParamChar(char)public void setSepParamChar(char val)
val - New char value to assign.getSepParamChar()public char getSepParamChar()
setSepParamChar(char)
protected Vector parseParams(Input in)
throws IOException,
InterpretException
IOException
InterpretException
|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | |||||||||