Started ResponseParser
This commit is contained in:
parent
1e7aa6f7b9
commit
7f6752fa6d
|
@ -0,0 +1,10 @@
|
|||
package net.dankito.fints.response
|
||||
|
||||
import net.dankito.fints.messages.segmente.id.ISegmentId
|
||||
|
||||
|
||||
enum class InstituteSegmentId(override val id: String) : ISegmentId {
|
||||
|
||||
Synchronization("HISYN")
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package net.dankito.fints.response
|
||||
|
||||
import net.dankito.fints.messages.segmente.id.ISegmentId
|
||||
import net.dankito.fints.messages.segmente.id.MessageSegmentId
|
||||
import net.dankito.fints.response.segments.ReceivedMessageHeader
|
||||
import net.dankito.fints.response.segments.ReceivedSegment
|
||||
|
||||
|
||||
open class Response(
|
||||
val didReceiveResponse: Boolean,
|
||||
val didResponseContainErrors: Boolean,
|
||||
val receivedResponse: String? = null,
|
||||
val receivedSegments: List<ReceivedSegment> = listOf(),
|
||||
val error: Exception? = null
|
||||
) {
|
||||
|
||||
open val successful: Boolean
|
||||
get() = didReceiveResponse && didResponseContainErrors == false
|
||||
|
||||
|
||||
open val messageHeader: ReceivedMessageHeader?
|
||||
get() = getFirstSegmentById(MessageSegmentId.MessageHeader)
|
||||
|
||||
open fun <T : ReceivedSegment> getFirstSegmentById(id: ISegmentId): T? {
|
||||
return getFirstSegmentById(id.id)
|
||||
}
|
||||
|
||||
open fun <T : ReceivedSegment> getFirstSegmentById(id: String): T? {
|
||||
return receivedSegments.firstOrNull { it.segmentId == id } as T?
|
||||
}
|
||||
|
||||
open fun getSegmentsById(id: ISegmentId): List<ReceivedSegment> {
|
||||
return getSegmentsById(id.id)
|
||||
}
|
||||
|
||||
open fun getSegmentsById(id: String): List<ReceivedSegment> {
|
||||
return receivedSegments.filter { it.segmentId == id }
|
||||
}
|
||||
|
||||
|
||||
override fun toString(): String {
|
||||
return "Successful? $successful"
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
package net.dankito.fints.response
|
||||
|
||||
import net.dankito.fints.messages.Separators
|
||||
import net.dankito.fints.messages.segmente.id.MessageSegmentId
|
||||
import net.dankito.fints.response.segments.ReceivedMessageHeader
|
||||
import net.dankito.fints.response.segments.ReceivedSegment
|
||||
import net.dankito.fints.response.segments.ReceivedSynchronization
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
|
||||
open class ResponseParser {
|
||||
|
||||
companion object {
|
||||
private val log = LoggerFactory.getLogger(ResponseParser::class.java)
|
||||
}
|
||||
|
||||
|
||||
open fun parse(response: String): Response {
|
||||
try {
|
||||
val segments = response.split(Separators.SegmentSeparator)
|
||||
|
||||
val parsedSegments = segments.mapNotNull { parseSegment(it) }
|
||||
|
||||
return Response(true, determineContainsErrors(parsedSegments), response, parsedSegments)
|
||||
} catch (e: Exception) {
|
||||
log.error("Could not parse response '$response'", e)
|
||||
|
||||
return Response(true, true, response, error = e)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected open fun determineContainsErrors(parsedSegments: List<ReceivedSegment>): Boolean {
|
||||
return false // TODO
|
||||
}
|
||||
|
||||
|
||||
protected open fun parseSegment(segment: String): ReceivedSegment? {
|
||||
try {
|
||||
if (segment.isNotEmpty()) { // filter out empty lines
|
||||
val dataElementGroups = segment.split(Separators.DataElementGroupsSeparator)
|
||||
val segmentId = segment.substring(0, segment.indexOf(Separators.DataElementsSeparator))
|
||||
|
||||
return parseSegment(segment, segmentId, dataElementGroups)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
log.error("Could not parse segment '$segment'", e) // TODO: what to do here, how to inform user?
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
protected open fun parseSegment(segment: String, segmentId: String, dataElementGroups: List<String>): ReceivedSegment? {
|
||||
return when (segmentId) {
|
||||
MessageSegmentId.MessageHeader.id -> parseMessageHeaderSegment(segment, dataElementGroups)
|
||||
InstituteSegmentId.Synchronization.id -> parseSynchronization(segment, dataElementGroups)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected open fun parseMessageHeaderSegment(segment: String, dataElementGroups: List<String>): ReceivedMessageHeader {
|
||||
val messageSize = dataElementGroups[1].toInt()
|
||||
val finTsVersion = dataElementGroups[2].toInt()
|
||||
val dialogId = dataElementGroups[3]
|
||||
val messageNumber = dataElementGroups[4].toInt()
|
||||
|
||||
return ReceivedMessageHeader(messageSize, finTsVersion, dialogId, messageNumber, segment)
|
||||
}
|
||||
|
||||
protected open fun parseSynchronization(segment: String, dataElementGroups: List<String>): ReceivedSynchronization {
|
||||
val customerSystemId = dataElementGroups[1]
|
||||
val lastMessageNumber = if (dataElementGroups.size > 2) dataElementGroups[2] else null
|
||||
val securityReferenceNumberForSigningKey = if (dataElementGroups.size > 3) dataElementGroups[3] else null
|
||||
val securityReferenceNumberForDigitalSignature = if (dataElementGroups.size > 4) dataElementGroups[4] else null
|
||||
|
||||
return ReceivedSynchronization(segment, customerSystemId, lastMessageNumber,
|
||||
securityReferenceNumberForSigningKey, securityReferenceNumberForDigitalSignature)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package net.dankito.fints.response.segments
|
||||
|
||||
|
||||
open class ReceivedMessageHeader(
|
||||
val messageSize: Int,
|
||||
val finTsVersion: Int,
|
||||
val dialogId: String,
|
||||
val messageNumber: Int,
|
||||
segmentString: String)
|
||||
|
||||
: ReceivedSegment(segmentString)
|
|
@ -0,0 +1,34 @@
|
|||
package net.dankito.fints.response.segments
|
||||
|
||||
import net.dankito.fints.messages.Separators
|
||||
|
||||
|
||||
open class ReceivedSegment(
|
||||
val segmentId: String,
|
||||
val segmentNumber: Int,
|
||||
val segmentVersion: Int,
|
||||
val referenceSegmentNumber: Int? = null,
|
||||
val segmentString: String
|
||||
) {
|
||||
|
||||
|
||||
/**
|
||||
* Convenience constructor for setting [segmentId], [segmentNumber] and [segmentVersion].
|
||||
*
|
||||
* [segmentHeader] has to have three or four elements like [net.dankito.fints.messages.datenelementgruppen.implementierte.Segmentkopf] has.
|
||||
*/
|
||||
constructor(segmentHeader: List<String>, segmentString: String) :
|
||||
this(segmentHeader[0], segmentHeader[1].toInt(), segmentHeader[2].toInt(),
|
||||
if (segmentHeader.size >= 4) segmentHeader[3].toInt() else null, segmentString)
|
||||
|
||||
constructor(segmentString: String) : this(
|
||||
segmentString.split(Separators.DataElementGroupsSeparator).first().split(Separators.DataElementsSeparator),
|
||||
segmentString
|
||||
)
|
||||
|
||||
|
||||
override fun toString(): String {
|
||||
return segmentId
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package net.dankito.fints.response.segments
|
||||
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.Synchronisierungsmodus
|
||||
|
||||
|
||||
open class ReceivedSynchronization(
|
||||
|
||||
segmentString: String,
|
||||
|
||||
/**
|
||||
* Only set if [Synchronisierungsmodus] was set to [Synchronisierungsmodus.NeueKundensystemIdZurueckmelden]
|
||||
*/
|
||||
val customerSystemId: String? = null,
|
||||
|
||||
/**
|
||||
* Only set if [Synchronisierungsmodus] was set to [Synchronisierungsmodus.LetzteVerarbeiteteNachrichtennummerZurueckmelden]
|
||||
*/
|
||||
val lastMessageNumber: String? = null,
|
||||
|
||||
/**
|
||||
* Only set if [Synchronisierungsmodus] was set to [Synchronisierungsmodus.SignaturIdZurueckmelden]
|
||||
*/
|
||||
val securityReferenceNumberForSigningKey: String? = null,
|
||||
|
||||
/**
|
||||
* Only set if [Synchronisierungsmodus] was set to [Synchronisierungsmodus.SignaturIdZurueckmelden]
|
||||
*/
|
||||
val securityReferenceNumberForDigitalSignature: String? = null
|
||||
|
||||
)
|
||||
: ReceivedSegment(segmentString)
|
|
@ -0,0 +1,64 @@
|
|||
package net.dankito.fints.response
|
||||
|
||||
import net.dankito.fints.messages.segmente.id.ISegmentId
|
||||
import net.dankito.fints.messages.segmente.id.MessageSegmentId
|
||||
import net.dankito.fints.response.segments.ReceivedMessageHeader
|
||||
import net.dankito.fints.response.segments.ReceivedSynchronization
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Test
|
||||
|
||||
|
||||
class ResponseParserTest {
|
||||
|
||||
private val underTest = ResponseParser()
|
||||
|
||||
|
||||
@Test
|
||||
fun parseMessageHeader() {
|
||||
|
||||
// when
|
||||
val result = underTest.parse("HNHBK:1:3+000000000596+300+817407729605=887211382312BLB4=+2+817407729605=887211382312BLB4=:2")
|
||||
|
||||
// then
|
||||
assertSuccessfullyParsedSegment(result, MessageSegmentId.MessageHeader, 1, 3)
|
||||
|
||||
assertThat(result.messageHeader).isNotNull
|
||||
val header = result.receivedSegments.first() as ReceivedMessageHeader
|
||||
|
||||
assertThat(header.messageSize).isEqualTo(596)
|
||||
assertThat(header.finTsVersion).isEqualTo(300)
|
||||
assertThat(header.dialogId).isEqualTo("817407729605=887211382312BLB4=")
|
||||
assertThat(header.messageNumber).isEqualTo(2)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun parseSynchronization() {
|
||||
|
||||
// when
|
||||
val result = underTest.parse("HISYN:173:4:6+WL/2/Trhmm0BAAAjIADlyFkXrAQA")
|
||||
|
||||
// then
|
||||
assertSuccessfullyParsedSegment(result, InstituteSegmentId.Synchronization, 173, 4, 6)
|
||||
|
||||
val segment = result.receivedSegments.first() as ReceivedSynchronization
|
||||
|
||||
assertThat(segment.customerSystemId).isEqualTo("WL/2/Trhmm0BAAAjIADlyFkXrAQA")
|
||||
}
|
||||
|
||||
|
||||
private fun assertSuccessfullyParsedSegment(result: Response, segmentId: ISegmentId, segmentNumber: Int,
|
||||
segmentVersion: Int, referenceSegmentNumber: Int? = null) {
|
||||
|
||||
assertThat(result.successful).isTrue()
|
||||
assertThat(result.receivedResponse).isNotNull()
|
||||
assertThat(result.receivedSegments).hasSize(1)
|
||||
|
||||
val segment = result.receivedSegments.first()
|
||||
|
||||
assertThat(segment.segmentId).isEqualTo(segmentId.id)
|
||||
assertThat(segment.segmentNumber).isEqualTo(segmentNumber)
|
||||
assertThat(segment.segmentVersion).isEqualTo(segmentVersion)
|
||||
assertThat(segment.referenceSegmentNumber).isEqualTo(referenceSegmentNumber)
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue