CHANGES v1.9 ============ * Made statement an optional block element, a-la JSTL. - Assign blocks are dynamically scoped, ie. wrapped in a RootModelWrapper object. - RootModelWrapper is now a part of the core package, rather than an extension. - Empty assign and block assign are separate instruction classes. - Some minor changes to StandardTemplateParser, findTagEnd() method is refactored, as is parseAssign(). - Added test cases for this behaviour. - Need to update the manual to reflect this behaviour. * Function variables can be either globally or dynamically scoped. Added an extra two keywords to function declarations. Default is still global scope, although we don't want to encourage side-effects, but realise they are sometimes useful. - Added test cases for this behaviour. - Need to update the manual to reflect this behaviour. * Similarly, functions take on Awk behaviour regarding local variables: any declared variable without a matching parameter in the instruction becomes an empty local variable. - Need to update the manual to reflect this behaviour. * Added an #empty special identifier, which returns a null model. - Take special note of the behaviour of the Plus operator when it interacts with null models. Always returns a Scalar model. - Regularised the parser so that #true, #false, and #empty can be on the left hand size of a binary expression - Need to update the manual to reflect this behaviour. * Added a Pipeline method model, which takes a parameter list of Transform or Transform2 objects and returns a wrapping Transform2 object that calls each one in turn. - Documented which order the transformations occur, and whether this is equivalent to nesting instructions. * Added a Join method model, which is the complement of the Split model. The Split model itself has had a minor rework. * Added the Transliterate library as methods and transforms, similar to the Substitute models. - Added test cases for this model. * Added the new models to the Methods and Transforms classes. * Improved the way the reflection library deals with numbers and number conversions from the internal template models. - Add more test cases for this model. * Abstracted FunctionModel into a TemplateFunctionModel interface with appropriate warnings and hazard lights. This allows expert users most of the power of an empty instruction without having to extend the parser. - Refactored Template and FunctionTemplateProcessor to deal with TemplateFunctionModel. This gives some added flexibility as to when and how such models can be stored and retrieved. - Changed the serialized form of Template as a result, since the internal data model has changed. A new serialization UID has been generated. - Added a simple model to the test cases and exercise it. * Added a getAsStringOrEmpty() method to TemplateUtils class, and use it in several places instead of the getAsString() method. Makes the class more user friendly, especially for TemplateMethodModel2 handling. * Created TemplateWriteableIndexedModel and TemplateWriteableHashModel interfaces, primarily used with the beans2 package. Reworked a lot of related expression code so that any variable model can potentially be the left-hand-side of an assignment. Consequential changes to AssignInstruction and StandardTemplateParser made. * Use an InputSource interface and concrete classes, similar to the SAX 2 library, to pass input streams into the Template constructor. Simplifies a lot of related constructors. Also allows us to pass in the name of the template (as per the template cache) without compromising the immutability of the template. See also Source in the TRaX library. * Also created FileInputSource and StringInputSource sublasses of InputSource. * Pushed up the concept of InputSource into the StandardTemplateParser, so that the parser isn't completely tied to reading its input from a String source. * FastList now implements TemplateWriteableIndexedModel. * Created a rewrite of the freemarker.ext.beans classes (beans2). The old package is becoming difficult to maintain, and the current license is a problem. - Need to extensively document the behaviour of the new package. * Created a separate formatters package, with classes for MessageFormat, DateFormat, and NumberFormat. * Created wrapper TemplateWriteableHashModel classes for calling globally-scoped functions and list iterations. Made list items "live" (long "i") by extending TemplateIteratorModel to add a "set(TemplateModel m)" method. A lot of intelligence ends up in the wrapping list iteration model. The "remove(String key)" method from the TemplateModelRoot interface becomes redundant as a result. * Writeable models always extend the read-only models. This eliminates the need for TemplateModelRoot altogether, which becomes a marker interface only. Retrofitted all existing uses of TemplateModelRoot back to TemplateWriteableHashModel. * Deleted deprecated classes from the freemarker.ext.misc package.