Better quote handling, parsing state refactor

Should be easier to test in the future
Still needs some work on spacing
This commit is contained in:
Bradlee Speice 2015-04-16 00:37:11 -04:00
parent aec86f9898
commit 3a0a5baa1c
8 changed files with 72 additions and 49 deletions

View File

@ -24,7 +24,7 @@ public class MinimalBible extends Application implements Injector {
}
public static Context getAppContext() {
Logger.w("Statically accessing context, please refactor that.");
Logger.v("Statically accessing context, please refactor that.");
return mContext;
}

View File

@ -3,7 +3,6 @@ package org.bspeice.minimalbible.activity.viewer
import android.support.v7.widget.RecyclerView
import android.text.SpannableStringBuilder
import android.widget.TextView
import com.orhanobut.logger.Logger
import org.bspeice.minimalbible.service.format.osisparser.OsisParser
import org.crosswire.jsword.book.Book
import org.crosswire.jsword.book.getVersification
@ -11,18 +10,18 @@ import org.crosswire.jsword.book.getVersification
class PassageView(val v: TextView, val b: Book)
: RecyclerView.ViewHolder(v) {
val parser = OsisParser()
fun buildOrdinal(verse: Int, info: BookAdapter.ChapterInfo) =
b.getVersification().decodeOrdinal(verse + info.vOffset)
fun getAllVerses(verses: Progression<Int>, info: BookAdapter.ChapterInfo): SpannableStringBuilder {
val builder = SpannableStringBuilder()
val parser = OsisParser()
verses.forEach { parser.appendVerse(b, buildOrdinal(it, info), builder) }
return builder
}
fun bind(info: BookAdapter.ChapterInfo) {
Logger.d("PassageView", "Binding chapter ${info.chapter}")
v setText getAllVerses(info.vStart..info.vEnd, info)
}
}

View File

@ -25,8 +25,11 @@ class OsisParser() : DefaultHandler() {
// Don't pass a verse as part of the constructor, but still guarantee
// that it will exist
var verseContent: VerseContent by Delegates.notNull()
var builder: SpannableStringBuilder by Delegates.notNull()
var state: ParseState = ParseState(listOf())
// TODO: Implement a stack to keep min API 8
val handlerStack = ArrayDeque<TagHandler>()
@ -52,23 +55,25 @@ class OsisParser() : DefaultHandler() {
override fun startElement(uri: String, localName: String,
qName: String, attributes: Attributes) {
when (localName) {
OSISUtil.OSIS_ELEMENT_VERSE -> handlerStack push VerseHandler()
"divineName" -> handlerStack push DivineHandler()
"q" -> handlerStack push QHandler(MinimalBible.getAppContext()
val tag = when (localName) {
OSISUtil.OSIS_ELEMENT_VERSE -> VerseHandler()
"divineName" -> DivineHandler()
"q" -> QHandler(MinimalBible.getAppContext()
.getResources().getColor(R.color.divineSpeech))
else -> handlerStack push UnknownHandler(localName)
else -> UnknownHandler(localName)
}
handlerStack.peek().start(attributes, verseContent, builder)
state = tag.start(attributes, verseContent, builder, state)
handlerStack push tag
}
override fun endElement(uri: String, localName: String, qName: String) {
val tagHandler = handlerStack.pop()
tagHandler.end(verseContent, builder)
state = tagHandler.end(verseContent, builder, state) build builder
}
override fun characters(ch: CharArray, start: Int, length: Int) {
handlerStack.peek().render(builder, verseContent, String(ch))
val tag = handlerStack.peek()
state = tag.render(builder, verseContent, String(ch), state)
}
}

View File

@ -6,19 +6,18 @@ import org.bspeice.minimalbible.service.format.osisparser.VerseContent
import org.xml.sax.Attributes
class DivineHandler() : TagHandler {
override fun end(info: VerseContent, builder: SpannableStringBuilder) {
}
override fun end(info: VerseContent, builder: SpannableStringBuilder,
state: ParseState) = state
override fun start(attrs: Attributes, info: VerseContent,
builder: SpannableStringBuilder) {
}
override fun start(attrs: Attributes, info: VerseContent, builder: SpannableStringBuilder,
state: ParseState) = state
override fun render(builder: SpannableStringBuilder, info: VerseContent, chars: String) {
this buildDivineName chars forEach { it apply builder }
}
override fun render(builder: SpannableStringBuilder, info: VerseContent, chars: String,
state: ParseState) =
state append(buildDivineName(chars))
fun buildDivineName(chars: String) =
listOf(AppendArgs(chars take 1, null),
listOf(AppendArgs(chars take 1),
AppendArgs((chars drop 1).toUpperCase(), RelativeSizeSpan(.8f))
)
}

View File

@ -7,14 +7,16 @@ import org.xml.sax.Attributes
class QHandler(val color: Int) : TagHandler {
override fun start(attrs: Attributes, info: VerseContent, builder: SpannableStringBuilder) {
}
fun retrieveMarker(attrs: Attributes) =
AppendArgs(attrs getValue "marker" ?: "")
override fun render(builder: SpannableStringBuilder, info: VerseContent, chars: String) {
AppendArgs(chars, ForegroundColorSpan(color)) apply builder
}
override fun start(attrs: Attributes, info: VerseContent, builder: SpannableStringBuilder,
state: ParseState) = state append retrieveMarker(attrs)
override fun end(info: VerseContent, builder: SpannableStringBuilder) {
AppendArgs(" ", null) apply builder
}
override fun render(builder: SpannableStringBuilder, info: VerseContent, chars: String,
state: ParseState) =
state append AppendArgs(chars.trim() + " ", ForegroundColorSpan(color))
override fun end(info: VerseContent, builder: SpannableStringBuilder,
state: ParseState) = state
}

View File

@ -6,12 +6,29 @@ import org.bspeice.minimalbible.service.format.osisparser.VerseContent
import org.xml.sax.Attributes
trait TagHandler {
fun start(attrs: Attributes, info: VerseContent, builder: SpannableStringBuilder)
fun render(builder: SpannableStringBuilder, info: VerseContent, chars: String)
fun end(info: VerseContent, builder: SpannableStringBuilder)
fun start(attrs: Attributes, info: VerseContent, builder: SpannableStringBuilder,
state: ParseState): ParseState
fun render(builder: SpannableStringBuilder, info: VerseContent, chars: String,
state: ParseState): ParseState
fun end(info: VerseContent, builder: SpannableStringBuilder,
state: ParseState): ParseState
}
data class AppendArgs(val text: String, val span: Any?) {
class ParseState(val spans: List<AppendArgs>) {
fun build(builder: SpannableStringBuilder): ParseState {
spans.forEach { it apply builder }
return ParseState(listOf())
}
fun append(arg: AppendArgs) = ParseState(spans + arg)
fun append(args: List<AppendArgs>) = ParseState(spans + args)
}
data class AppendArgs(val text: String, val span: Any? = null) {
fun apply(builder: SpannableStringBuilder) {
val offset = builder.length()
builder.append(text)

View File

@ -6,14 +6,15 @@ import org.bspeice.minimalbible.service.format.osisparser.VerseContent
import org.xml.sax.Attributes
class UnknownHandler(val tagName: String) : TagHandler {
override fun end(info: VerseContent, builder: SpannableStringBuilder) {
}
override fun end(info: VerseContent, builder: SpannableStringBuilder,
state: ParseState): ParseState = state
override fun start(attrs: Attributes, info: VerseContent,
builder: SpannableStringBuilder) {
}
override fun start(attrs: Attributes, info: VerseContent, builder: SpannableStringBuilder,
state: ParseState) = state
override fun render(builder: SpannableStringBuilder, info: VerseContent, chars: String) {
Logger.w("Unknown tag '$tagName' received text: '$chars'")
override fun render(builder: SpannableStringBuilder, info: VerseContent, chars: String,
state: ParseState): ParseState {
Logger.v("Unknown tag '$tagName' received text: '$chars'")
return state
}
}

View File

@ -10,19 +10,19 @@ import org.xml.sax.Attributes
class VerseHandler() : TagHandler {
override fun end(info: VerseContent, builder: SpannableStringBuilder) {
}
override fun end(info: VerseContent, builder: SpannableStringBuilder,
state: ParseState) =
state append AppendArgs(" ")
override fun start(attrs: Attributes, info: VerseContent,
builder: SpannableStringBuilder) {
when {
builder: SpannableStringBuilder, state: ParseState) =
state append when {
info.verseNum == 1 -> AppendArgs("${info.chapter} ", StyleSpan(Typeface.BOLD))
else -> AppendArgs("${info.verseNum}",
listOf(SuperscriptSpan(), RelativeSizeSpan(.75f)))
} apply builder
}
}
override fun render(builder: SpannableStringBuilder, info: VerseContent, chars: String) {
builder append chars
}
override fun render(builder: SpannableStringBuilder, info: VerseContent, chars: String,
state: ParseState) =
state append AppendArgs(chars)
}