minor refactor to tidy up the API

This commit is contained in:
James Strachan
2012-03-14 20:16:34 +00:00
parent 245a4f079c
commit 4352ed38e5
2 changed files with 154 additions and 28 deletions
+111 -28
View File
@@ -1,14 +1,21 @@
package kotlin.template
import kotlin.dom.*
import kotlin.dom. *
import org.w3c.dom.Node
import com.sun.org.apache.xalan.internal.xsltc.dom.UnionIterator
import java.util.Locale
import java.text.NumberFormat
import java.text.DateFormat
import java.util.Date
// TODO this class should move into the runtime
// in jet.StringTemplate
class StringTemplate(val values: Array<Any?>) {
class StringTemplate(val values : Array<Any?>) {
fun toString(): String {
/**
* Converts the template into a String
*/
fun toString() : String {
val out = StringBuilder()
forEach{ out.append(it) }
return out.toString() ?: ""
@@ -17,20 +24,31 @@ class StringTemplate(val values: Array<Any?>) {
/**
* Performs the given function on each value in the collection
*/
fun forEach(fn: (Any?) -> Unit): Unit {
fun forEach(fn : (Any?) -> Unit) : Unit {
for (v in values) {
fn(v)
}
}
}
fun StringTemplate.toString(formatter : ValueFormatter): String {
/**
* Converts the string template into a string using the given formatter
* to encode values as Strings performing any special encoding (such as for HTML)
* or internationalisation.
*
* See [[HtmlFormatter] and [[LocaleFormatter] respectively.
*/
fun StringTemplate.toString(formatter : Formatter) : String {
val buffer = StringBuilder()
append(buffer, formatter)
return buffer.toString() ?: ""
}
fun StringTemplate.append(out: Appendable, formatter: ValueFormatter): Unit {
/**
* Appends the text representation of this string template to the given output
* using the supplied formatter
*/
fun StringTemplate.append(out : Appendable, formatter : Formatter) : Unit {
var constantText = true
this.forEach {
if (constantText) {
@@ -49,43 +67,106 @@ fun StringTemplate.append(out: Appendable, formatter: ValueFormatter): Unit {
}
}
fun StringTemplate.toHtml(formatter : HtmlFormatter = HtmlFormatter()): String = toString(formatter)
/**
* Converts this string template to internationalised text using the supplied
* [[LocaleFormatter]]
*/
fun StringTemplate.toLocale(formatter : LocaleFormatter = LocaleFormatter()) : String = toString(formatter)
/**
* Represents a formatter of values in a [[StringTemplate]] which understands how to escape
* different types for different kinds of language
* Converts this string template to HTML text
*/
trait ValueFormatter {
fun StringTemplate.toHtml(formatter : HtmlFormatter = HtmlFormatter()) : String = toString(formatter)
/**
* Represents a formatter and encoder of values in a [[StringTemplate]] which understands
* how to format values for a particular [[Locale]] such as with the [[LocaleFormatter]] or
* to escape particular characters in different output formats such as [[HtmlFormatter]
*/
trait Formatter {
fun format(buffer : Appendable, val value : Any?) : Unit
}
object ToStringFormatter : ValueFormatter {
/**
* Formats strings with no special encoding other than allowing the null text to be
* configured
*/
open class ToStringFormatter : Formatter {
fun toString() = "ToStringFormatter"
var nullString : String = "null"
override fun format(buffer : Appendable, value : Any?) {
val text = if (value == null) "null" else value.toString()
buffer.append(text)
}
}
open fun toString() = "ToStringFormatter"
class HtmlFormatter : ValueFormatter {
var nullText : String = ""
override fun format(buffer : Appendable, value : Any?) {
override fun format(out : Appendable, value : Any?) {
if (value == null) {
buffer.append(nullText)
format(out, nullString)
} else if (value is StringTemplate) {
value.append(buffer, this)
} else if (value is Node) {
buffer.append(value.toXmlString())
value.append(out, this)
} else {
escape(buffer, value.toString() ?: "")
format(out, value.toString())
}
}
fun escape(buffer : Appendable, text : String) : Unit {
/**
* Formats the given string allowing derived classes to override this method
* to escape strings with special characters such as for HTML
*/
open fun format(out : Appendable, text : String) : Unit {
out.append(text)
}
}
protected val defaultLocale : Locale = Locale.getDefault().sure()
/**
* Formats values using a given [[Locale]] for internationalisation
*/
open class LocaleFormatter(val locale : Locale = defaultLocale) : ToStringFormatter() {
override fun toString() = "LocaleFormatter{$locale}"
public var numberFormat : NumberFormat = NumberFormat.getInstance(locale).sure()
public var dateFormat : DateFormat = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, locale).sure()
override fun format(out : Appendable, value : Any?) {
/* TODO KT-1583 - uncomment when its fixed
if (value is Number) {
format(out, format(value))
} else
*/
if (value is Date) {
format(out, format(value))
} else {
super.format(out, value)
}
}
fun format(number : Number) : String {
return numberFormat.format(number) ?: ""
}
fun format(date : Date) : String {
return dateFormat.format(date) ?: ""
}
}
/**
* Formats values for HTML encoding, escaping special characters in HTML.
*/
class HtmlFormatter(locale : Locale = defaultLocale) : LocaleFormatter(locale) {
override fun toString() = "HtmlFormatter{$locale}"
override fun format(out : Appendable, value : Any?) {
if (value is Node) {
out.append(value.toXmlString())
} else {
super.format(out, value)
}
}
override fun format(buffer : Appendable, text : String) : Unit {
for (c in text) {
if (c == '<') buffer.append("&lt;")
else if (c == '>') buffer.append("&gt;")
@@ -95,3 +176,5 @@ class HtmlFormatter : ValueFormatter {
}
}
}