Added splitIntoPartsAndUnmaskCharByChar(). It's uglier but more efficient on strings with many separators

This commit is contained in:
dankito 2020-05-19 14:22:07 +02:00
parent fd1343d8b9
commit 3d73289649
2 changed files with 56 additions and 7 deletions

View File

@ -4,16 +4,20 @@ package net.dankito.banking.fints.messages
class Separators { class Separators {
companion object { companion object {
const val SegmentSeparator = "'" const val SegmentSeparatorChar = '\''
const val SegmentSeparator = SegmentSeparatorChar.toString()
const val DataElementGroupsSeparator = "+" const val DataElementGroupsSeparatorChar = '+'
const val DataElementGroupsSeparator = DataElementGroupsSeparatorChar.toString()
const val DataElementsSeparator = ":" const val DataElementsSeparatorChar = ':'
const val DataElementsSeparator = DataElementsSeparatorChar.toString()
const val BinaryDataSeparatorChar = '@' const val BinaryDataSeparatorChar = '@'
const val BinaryDataSeparator = BinaryDataSeparatorChar.toString() const val BinaryDataSeparator = BinaryDataSeparatorChar.toString()
const val MaskingCharacter = "?" const val MaskingCharacterChar = '?'
const val MaskingCharacter = MaskingCharacterChar.toString()
val AllSeparators = listOf(DataElementsSeparator, DataElementGroupsSeparator, SegmentSeparator) val AllSeparators = listOf(DataElementsSeparator, DataElementGroupsSeparator, SegmentSeparator)

View File

@ -76,7 +76,7 @@ open class ResponseParser @JvmOverloads constructor(
protected open fun parseSegment(segment: String): ReceivedSegment? { protected open fun parseSegment(segment: String): ReceivedSegment? {
try { try {
if (segment.isNotEmpty()) { // filter out empty lines if (segment.isNotEmpty()) { // filter out empty lines
val dataElementGroups = splitIntoPartsAndUnmask(segment, Separators.DataElementGroupsSeparator) val dataElementGroups = splitIntoPartsAndUnmaskCharByChar(segment, Separators.DataElementGroupsSeparatorChar)
val segmentId = segment.substring(0, segment.indexOf(Separators.DataElementsSeparator)) val segmentId = segment.substring(0, segment.indexOf(Separators.DataElementsSeparator))
@ -715,7 +715,7 @@ open class ResponseParser @JvmOverloads constructor(
} }
protected open fun getDataElements(dataElementGroup: String): List<String> { protected open fun getDataElements(dataElementGroup: String): List<String> {
return splitIntoPartsAndUnmask(dataElementGroup, Separators.DataElementsSeparator) return splitIntoPartsAndUnmaskCharByChar(dataElementGroup, Separators.DataElementsSeparatorChar)
} }
/** /**
@ -742,12 +742,57 @@ open class ResponseParser @JvmOverloads constructor(
elements.add(dataString.substring(startIndex)) elements.add(dataString.substring(startIndex))
} }
val maskedSeparator = Separators.MaskingCharacter + separator
return elements.map { return elements.map {
if (it.contains(Separators.MaskingCharacter + separator)) it.replace(Separators.MaskingCharacter + separator, separator.toString()) if (it.contains(maskedSeparator)) it.replace(maskedSeparator, separator)
else it else it
} }
} }
protected open fun splitIntoPartsAndUnmaskCharByChar(dataString: String, separator: Char): List<String> {
val binaryRanges = messageUtils.findBinaryDataRanges(dataString)
var lastEndIndex = 0
var partContainsMaskedSeparators = false
val parts = mutableListOf<String>()
for (i in dataString.indices) {
val char = dataString[i]
if (char == separator && messageUtils.isInRange(i, binaryRanges) == false) {
if (dataString[i - 1] != Separators.MaskingCharacterChar) {
parts.add(extractPart(dataString, lastEndIndex, i, separator, partContainsMaskedSeparators))
lastEndIndex = i + 1
partContainsMaskedSeparators = false
}
}
else if (char == Separators.MaskingCharacterChar && messageUtils.isInRange(i, binaryRanges) == false && i + 1 < dataString.length && dataString[i + 1] == separator) {
partContainsMaskedSeparators = true
}
}
if (lastEndIndex != dataString.length) {
parts.add(extractPart(dataString, lastEndIndex, dataString.length, separator, partContainsMaskedSeparators))
}
return parts
}
protected open fun extractPart(dataString: String, startIndex: Int, lastEndIndex: Int, separator: Char,
partContainsMaskedSeparators: Boolean): String {
val part = dataString.substring(startIndex, lastEndIndex)
if (partContainsMaskedSeparators) {
return part.replace(Separators.MaskingCharacter + separator, separator.toString())
}
else {
return part
}
}
protected open fun parseStringToNullIfEmpty(string: String): String? { protected open fun parseStringToNullIfEmpty(string: String): String? {
val parsedString = parseString(string) val parsedString = parseString(string)