Implemented parsing BankParameters

This commit is contained in:
dankl 2019-10-05 22:23:41 +02:00 committed by dankito
parent a3e2b72a09
commit af35f35ba0
6 changed files with 150 additions and 11 deletions

View File

@ -1,16 +1,16 @@
package net.dankito.fints.messages.datenelemente.implementierte
enum class HbciVersion(val versionNumber: Int) {
enum class HbciVersion(val versionNumber: Int, override val code: String) : ICodeEnum {
Hbci_2_0_1(201),
Hbci_2_0_1(201, "201"),
Hbci_2_1_0(210),
Hbci_2_1_0(210, "210"),
Hbci_2_2_0(220),
Hbci_2_2_0(220, "220"),
FinTs_3_0_0(300),
FinTs_3_0_0(300, "300"),
FinTs_4_0_0(400)
FinTs_4_0_0(400, "400")
}

View File

@ -7,8 +7,8 @@ import net.dankito.fints.messages.datenelementgruppen.Datenelementgruppe
open class Kreditinstitutskennung @JvmOverloads constructor(
bankCountryCode: Int,
bankCode: String,
val bankCountryCode: Int,
val bankCode: String,
existenzstatus: Existenzstatus = Existenzstatus.Mandatory
)
: Datenelementgruppe(listOf(

View File

@ -5,6 +5,8 @@ import net.dankito.fints.messages.segmente.id.ISegmentId
enum class InstituteSegmentId(override val id: String) : ISegmentId {
Synchronization("HISYN")
Synchronization("HISYN"),
BankParameters("HIBPA")
}

View File

@ -1,7 +1,12 @@
package net.dankito.fints.response
import net.dankito.fints.messages.Separators
import net.dankito.fints.messages.datenelemente.implementierte.Dialogsprache
import net.dankito.fints.messages.datenelemente.implementierte.HbciVersion
import net.dankito.fints.messages.datenelemente.implementierte.ICodeEnum
import net.dankito.fints.messages.datenelementgruppen.implementierte.Kreditinstitutskennung
import net.dankito.fints.messages.segmente.id.MessageSegmentId
import net.dankito.fints.response.segments.BankParameters
import net.dankito.fints.response.segments.ReceivedMessageHeader
import net.dankito.fints.response.segments.ReceivedSegment
import net.dankito.fints.response.segments.ReceivedSynchronization
@ -54,6 +59,7 @@ open class ResponseParser {
return when (segmentId) {
MessageSegmentId.MessageHeader.id -> parseMessageHeaderSegment(segment, dataElementGroups)
InstituteSegmentId.Synchronization.id -> parseSynchronization(segment, dataElementGroups)
InstituteSegmentId.BankParameters.id -> parseBankParameters(segment, dataElementGroups)
else -> null
}
}
@ -78,4 +84,50 @@ open class ResponseParser {
securityReferenceNumberForSigningKey, securityReferenceNumberForDigitalSignature)
}
protected open fun parseBankParameters(segment: String, dataElementGroups: List<String>): BankParameters {
val bpdVersion = dataElementGroups[1].toInt()
val bankDetails = parseBankDetails(dataElementGroups[2])
val bankName = dataElementGroups[3]
val countMaxJobsPerMessage = dataElementGroups[4].toInt()
val supportedLanguages = parseLanguages(dataElementGroups[5])
val supportedHbciVersions = parseHbciVersions(dataElementGroups[6])
val maxMessageSize = if (dataElementGroups.size > 7) dataElementGroups[7].toInt() else null
val minTimeout = if (dataElementGroups.size > 8) dataElementGroups[8].toInt() else null
val maxTimeout = if (dataElementGroups.size > 9) dataElementGroups[9].toInt() else null
return BankParameters(bpdVersion, bankDetails.bankCountryCode, bankDetails.bankCode, bankName,
countMaxJobsPerMessage, supportedLanguages, supportedHbciVersions, maxMessageSize, minTimeout, maxTimeout, segment)
}
protected open fun parseBankDetails(dataElementsGroup: String): Kreditinstitutskennung {
val detailsStrings = getDataElements(dataElementsGroup)
return Kreditinstitutskennung(detailsStrings[0].toInt(), detailsStrings[1])
}
protected open fun parseLanguages(dataElementsGroup: String): List<Dialogsprache> {
val languageStrings = getDataElements(dataElementsGroup)
return parseFromCode(languageStrings, Dialogsprache.values())
}
protected open fun parseHbciVersions(dataElementsGroup: String): List<HbciVersion> {
val versionStrings = getDataElements(dataElementsGroup)
return parseFromCode(versionStrings, HbciVersion.values())
}
protected open fun <T : ICodeEnum> parseFromCode(codeValues: List<String>, allValues: Array<T>): List<T> {
// mapNotNull: don't crash if new, at time of implementation unknown values get introduced / returned by bank
return codeValues.mapNotNull { code -> allValues.first { it.code == code } }
}
protected open fun getDataElements(dataElementGroup: String): List<String> {
return dataElementGroup.split(Separators.DataElementsSeparator)
}
}

View File

@ -0,0 +1,52 @@
package net.dankito.fints.response.segments
import net.dankito.fints.messages.datenelemente.implementierte.Dialogsprache
import net.dankito.fints.messages.datenelemente.implementierte.HbciVersion
open class BankParameters(
val bpdVersion: Int,
val bankCountryCode: Int,
val bankCode: String,
val bankName: String,
/**
* Maximale Anzahl an Geschäftsvorfallsarten, die pro Nachricht zulässig ist.
* Der Wert 0 gibt an, dass keine Restriktionen bzgl. der Anzahl an Geschäftsvorfallsarten bestehen.
*/
val countMaxJobsPerMessage: Int,
val supportedLanguages: List<Dialogsprache>,
val supportedHbciVersions: List<HbciVersion>,
/**
* Obergrenze in Kilobyte (=1024 Byte) für die Nachrichtengröße. Dies kann kreditinstitutsindividuell
* je nach technischen Restriktionen bzgl. der Verarbeitung umfangreicher Kundennachrichten vorgegeben werden.
*
* Der Wert 0 gibt an, dass keine Restriktionen bzgl. der Nachrichtengröße bestehen.
*
* Eingehende Nachrichten, die dekomprimiert und entschlüsselt diese Grenze überschreiten, können dann
* abgelehnt werden.
*/
val maxMessageSize: Int?,
/**
* Zeitraum, nach dem frühestens eine weitere Life-Indikator-Nachricht gesendet werden darf.
* Die Angabe erfolgt in Sekunden. Liegt keine Begrenzung vor, kann der Wert 0 angegeben werden.
*/
val minTimeout: Int?,
/**
* Zeitraum, nach dem das Kreditinstitut einen Dialog voraussichtlich beenden wird, sofern keine
* weiteren Kundennachrichten gesendet wurden. Die Angabe erfolgt in Sekunden. Liegt keine
* Begrenzung vor, kann der Wert 0 angegeben werden.
*/
val maxTimeout: Int?,
segmentString: String
) : ReceivedSegment(segmentString)

View File

@ -1,10 +1,14 @@
package net.dankito.fints.response
import net.dankito.fints.messages.datenelemente.implementierte.Dialogsprache
import net.dankito.fints.messages.datenelemente.implementierte.HbciVersion
import net.dankito.fints.messages.segmente.id.ISegmentId
import net.dankito.fints.messages.segmente.id.MessageSegmentId
import net.dankito.fints.response.segments.BankParameters
import net.dankito.fints.response.segments.ReceivedMessageHeader
import net.dankito.fints.response.segments.ReceivedSynchronization
import org.assertj.core.api.Assertions.assertThat
import org.junit.Assert
import org.junit.Test
@ -31,6 +35,7 @@ class ResponseParserTest {
assertThat(header.messageNumber).isEqualTo(2)
}
@Test
fun parseSynchronization() {
@ -40,9 +45,37 @@ class ResponseParserTest {
// then
assertSuccessfullyParsedSegment(result, InstituteSegmentId.Synchronization, 173, 4, 6)
val segment = result.receivedSegments.first() as ReceivedSynchronization
result.getFirstSegmentById<ReceivedSynchronization>(InstituteSegmentId.Synchronization)?.let { segment ->
assertThat(segment.customerSystemId).isEqualTo("WL/2/Trhmm0BAAAjIADlyFkXrAQA")
}
?: run { Assert.fail("No segment of type ReceivedSynchronization found in ${result.receivedSegments}") }
}
assertThat(segment.customerSystemId).isEqualTo("WL/2/Trhmm0BAAAjIADlyFkXrAQA")
@Test
fun parseBankParameters() {
// when
val result = underTest.parse("HIBPA:5:3:3+34+280:10070000+Deutsche Bank+0+1+300+0'")
// then
assertSuccessfullyParsedSegment(result, InstituteSegmentId.BankParameters, 5, 3, 3)
result.getFirstSegmentById<BankParameters>(InstituteSegmentId.BankParameters)?.let { segment ->
assertThat(segment.bpdVersion).isEqualTo(34)
assertThat(segment.bankCountryCode).isEqualTo(280)
assertThat(segment.bankCode).isEqualTo("10070000")
assertThat(segment.bankName).isEqualTo("Deutsche Bank")
assertThat(segment.countMaxJobsPerMessage).isEqualTo(0)
assertThat(segment.supportedLanguages).containsExactly(Dialogsprache.German)
assertThat(segment.supportedHbciVersions).containsExactly(HbciVersion.FinTs_3_0_0)
assertThat(segment.maxMessageSize).isEqualTo(0)
assertThat(segment.minTimeout).isNull()
assertThat(segment.maxTimeout).isNull()
}
?: run { Assert.fail("No segment of type BankParameters found in ${result.receivedSegments}") }
}