Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Detect messages split over multiple lines #27

Merged
merged 3 commits into from
Oct 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
.kotlin
notes.txt
build
.DS_STORE
41 changes: 33 additions & 8 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,37 @@

## [Unreleased]

## [0.5.0]

### Added
- Detects messages split over multiple lines
- Add a new column to display field type H for header, M for message, T for trailer


## [0.4.0]

### Added
- Mouse hovering over a fix message will display the fix message details

## [0.3.0]

### Added
- Cmd click for fields and groups to go to the field definition
- Mouse hovering over a field or group name will display the field definition
- Add Inspection to replace component reference with the full component definition

## [0.2.0]

### Added
- Add possibility to ctrl/cmd + click on the component name to navigate to the definition
- Mouse hovering over a component name will display the component definition

## [0.1.0]

### Added
- Add type next to the field name

## [0.0.1]

### Added
- v0.0.1 Add tag number next to the field name
- v0.1.0 Add type next to the field name
- v0.2.0 Add possibility to ctrl/cmd + click on the component name to navigate to the definition
- v0.2.0 Mouse hovering over a component name will display the component definition
- v0.3.0 Cmd click for fields and groups to go to the field definition
- v0.3.0 Mouse hovering over a field or group name will display the field definition
- v0.3.0 Add Inspection to replace component reference with the full component definition
- v0.4.0 Mouse hovering over a fix message will display the fix message details
- add tag number next to the field name
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pluginGroup = ac.quant.quickfixspec
pluginName = quickfix-spec
pluginRepositoryUrl = https://github.com/dantimofte/quickfix-spec
# SemVer format -> https://semver.org
pluginVersion = 0.4.0
pluginVersion = 0.5.0

# Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
pluginSinceBuild = 233
Expand Down

This file was deleted.

44 changes: 0 additions & 44 deletions src/main/kotlin/ac/quant/quickfixspec/common/FixField.kt

This file was deleted.

38 changes: 0 additions & 38 deletions src/main/kotlin/ac/quant/quickfixspec/common/FixFields.kt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package ac.quant.quickfixspec.common.parsed

import ac.quant.quickfixspec.common.spec.FieldElement
import ac.quant.quickfixspec.common.spec.IFixDataDictionaryService

class ParsedFixMessage(private val message: String, private val delimiter: String, private val fixDataDictionary: IFixDataDictionaryService) {
private lateinit var msgType: String
lateinit var msgName: String

private val headerFields = mutableListOf<FieldElement>()

init {
parseMessage()
}

private fun parseMessage() {
val messageParts = message.split(delimiter)

for (part in messageParts) {
val tagNumber = clean(part.substringBefore("="))

if (tagNumber.isEmpty()) {
continue
}

val tagValue = part.substringAfter("=")
val field = fixDataDictionary.getFieldByNumber(tagNumber)
val fieldWithValue = field.withValue(tagValue)
maybeAddHeaderField(fieldWithValue)
maybeSetMessageTypeAndName(fieldWithValue)
}
}

private fun maybeAddHeaderField(field: FieldElement) {
if (field.isHeaderField()) {
headerFields.add(field)
}
}

private fun maybeSetMessageTypeAndName(field: FieldElement) {
if (field.number == "35") {
msgType = field.number
msgName = field.name
}
}

private fun clean(value: String): String {
var cleanedValue = value.trim()
cleanedValue = cleanedValue.replace("'", "")
cleanedValue = cleanedValue.replace("\"", "")
cleanedValue = cleanedValue.trim()
return cleanedValue
}

fun getMessageDetails(): String {
val messageParts = message.split(delimiter)

val formattedMessage = messageParts.subList(0, messageParts.size - 1).joinToString("\n") {
val fieldNumber = clean(it.substringBefore("="))
val fieldValue = it.substringAfter("=")
val field = fixDataDictionary.getFieldByNumber(fieldNumber)
val fieldValueDefinition = field.values[fieldValue] ?: ""
val msgPart = getMsgParts(field)
"<tr><td>$msgPart<td><td>$fieldNumber</td><td>${field.name}</td><td>$fieldValue</td><td>$fieldValueDefinition</td></tr>"
}

val displayText = "<html><head><style> table { width: 100%; } td, th { border-bottom: 1px solid; text-align: left; padding: 1px; } </style></head><body><table>$formattedMessage</table></html>"

return displayText
}

private fun getMsgParts(field: FieldElement): String {
return when (true) {
field.isHeaderField() -> "H"
field.isTrailerField() -> "T"
else -> "M"
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package ac.quant.quickfixspec.common.spec

import com.intellij.psi.xml.XmlTag

class ComponentElement(override val name: String,override val type : ElementType,override val elementTag: XmlTag,override val fixDataDictionary: IFixDataDictionaryService): IElement {
override val number: String = ""

override val fields: MutableList<FieldElement> = mutableListOf()
override val components: MutableMap<String, ComponentElement> = mutableMapOf()
override val groups: MutableMap<String, GroupElement> = mutableMapOf()

private val componentsNames : MutableList<String> = mutableListOf()
private val groupsTags: MutableMap<String, XmlTag> = mutableMapOf()

init {
parseSubTags(elementTag)
}

private fun parseSubTags(tag: XmlTag) {
for (subTag in tag.subTags) {
when (subTag.name) {
"field" -> {
val fieldName = subTag.getAttribute("name")?.value ?: ""
val field = fixDataDictionary.fields.valuesByName[fieldName] as FieldElement
fields.add(field)
}
"component" -> {
val componentName = subTag.getAttribute("name")?.value ?: ""
componentsNames.add(componentName)
}
"group" -> {
val groupName = subTag.getAttribute("name")?.value ?: ""
groupsTags[groupName] = subTag
}
else -> {
println("Unprocessed component tag name: ${subTag.name}")
}
}
}
}

fun setSubComponents() {
for (componentName in componentsNames) {
val component = fixDataDictionary.components.valuesByName[componentName] as ComponentElement
components[componentName] = component
}
}

override fun parseGroups() {
for (groupName in groupsTags.keys) {
val group = GroupElement(groupName, ElementType.GROUP, groupsTags[groupName]!!, fixDataDictionary)
groups[groupName] = group
}
}

override fun toString(): String {
return "ComponentElement(name='$name', fields=${fields.size}, components=${components.size}, groups=${groups.size})"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package ac.quant.quickfixspec.common.spec

import com.intellij.psi.xml.XmlTag

class DefaultElement(override val name: String,override val number:String,override val type : ElementType, override val elementTag: XmlTag, override val fixDataDictionary: IFixDataDictionaryService): IElement {
override val fields: MutableList<FieldElement> = mutableListOf()
override val components: MutableMap<String, ComponentElement> = mutableMapOf()
override val groups: MutableMap<String, GroupElement> = mutableMapOf()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package ac.quant.quickfixspec.common.spec

enum class ElementType(val xmlContainerName: String) {
FIELD("fields"),
GROUP("groups"),
COMPONENT("components"),
MESSAGE("messages")
}
Loading