Skip to content

Commit

Permalink
Merge pull request #550 from smeup/feature/display_file_from_cli
Browse files Browse the repository at this point in the history
Example: display file from CLI
  • Loading branch information
lanarimarco authored Jun 19, 2024
2 parents 24a3914 + 3d80a0a commit d5e1d0f
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 4 deletions.
118 changes: 118 additions & 0 deletions examples/src/main/kotlin/com/jariko/samples/DisplayFileFromCLI.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package com.jariko.samples

import com.smeup.dspfparser.linesclassifier.DSPFField
import com.smeup.dspfparser.linesclassifier.DSPFFieldType
import com.smeup.rpgparser.execution.Configuration
import com.smeup.rpgparser.execution.DspfConfig
import com.smeup.rpgparser.execution.JarikoCallback
import com.smeup.rpgparser.execution.SimpleDspfConfig
import com.smeup.rpgparser.execution.getProgram
import com.smeup.rpgparser.interpreter.DecimalValue
import com.smeup.rpgparser.interpreter.IntValue
import com.smeup.rpgparser.interpreter.OnExfmtResponse
import com.smeup.rpgparser.interpreter.RuntimeInterpreterSnapshot
import com.smeup.rpgparser.interpreter.StringValue
import com.smeup.rpgparser.interpreter.Value
import com.smeup.rpgparser.rpginterop.DirRpgProgramFinder
import java.io.File

// UI control functions

class UnknownVariable(name: String) : Exception("`$name`")
class WrongInputSyntax : Exception("Should be: `VAR1=VALUE;VAR2=23`")

private fun parseInput(input: String): Map<String, String> {
try {
val assignments = input.split(';')
val variablesAndValues = mutableMapOf<String, String>()

assignments.forEach {
val tokens = it.split('=')
variablesAndValues[tokens[0]] = tokens[1]
}

return variablesAndValues
} catch (e: Exception) {
throw WrongInputSyntax()
}
}

private fun printFields(fields: List<DSPFField>) {
println()
print("OUTPUT fields:\n")
fields.filter { it.type == DSPFFieldType.OUTPUT }.forEach {
println("\t|${it.name}=${(it.value as Value).asString().value}|")
}
println()
print("INPUT fields:\n")
fields.filter { it.type == DSPFFieldType.INPUT }.forEach {
println("\t|${it.name}=${(it.value as Value).asString().value}|")
}
println()
println("Insert input: ")
}

private fun askInputFor(fields: List<DSPFField>): Map<String, Value> {
val variablesAndValues = mutableMapOf<String, Value>()
val line = readln()
val updatedVariables = parseInput(line)

updatedVariables.keys.forEach { variable ->
fields.find { field -> field.name == variable } ?: throw UnknownVariable(variable)
}

fields.filter { it.type == DSPFFieldType.INPUT && updatedVariables[it.name] != null }.forEach {
if (it.isNumeric && it.precision!! == 0)
variablesAndValues[it.name] = IntValue(updatedVariables[it.name]!!.toLong())
if (it.isNumeric && it.precision!! > 0)
variablesAndValues[it.name] = DecimalValue(updatedVariables[it.name]!!.toBigDecimal())
else if (!it.isNumeric)
variablesAndValues[it.name] = StringValue(updatedVariables[it.name]!!)
}

return variablesAndValues
}

private fun onExfmt(fields: List<DSPFField>, runtimeInterpreterSnapshot: RuntimeInterpreterSnapshot): OnExfmtResponse? {
printFields(fields)
while (true) {
try {
val variablesAndValues = askInputFor(fields)
return OnExfmtResponse(runtimeInterpreterSnapshot, variablesAndValues)
} catch (e: Exception) {
e.printStackTrace()
continue
}
}
}

// Jariko call setup functions

private fun createDspfConfig(): DspfConfig {
val simpleDspfConfig = SimpleDspfConfig({ }.javaClass.getResource("/metadata")!!.path)
return DspfConfig(
metadataProducer = simpleDspfConfig::getMetadata,
dspfProducer = simpleDspfConfig::dspfProducer
)
}

private fun createJarikoCallback(): JarikoCallback {
val jarikoCallback = JarikoCallback()
jarikoCallback.onExfmt = ::onExfmt
return jarikoCallback
}

private fun createConfig(): Configuration {
return Configuration(
dspfConfig = createDspfConfig(),
jarikoCallback = createJarikoCallback()
)
}

fun main() {
val programSource = "ADD01.rpgle"
val programFinders = listOf(DirRpgProgramFinder(File({ }.javaClass.getResource("/rpg")!!.path)))
val program = getProgram(nameOrSource = programSource, programFinders = programFinders)

program.singleCall(emptyList(), configuration = createConfig())
}
5 changes: 5 additions & 0 deletions examples/src/main/resources/metadata/ADD01V.dspf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
R FMT01
A 2 2I 0 0
B 2 2I 0 0
RESULT 2 2O 0 0
PGMCTL 1 0I 0 0
4 changes: 4 additions & 0 deletions examples/src/main/resources/metadata/TRIM01V.dspf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
R FMT01
STR 10 I 0 0
TRM 10 O 0 0
PGMCTL 1 0I 0 0
5 changes: 5 additions & 0 deletions examples/src/main/resources/rpg/ADD01.rpgle
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FADD01V CF E WORKSTN USROPN
C PGMCTL DOWEQ 0
C EXFMT FMT01
C EVAL RESULT=A+B
C ENDDO
5 changes: 5 additions & 0 deletions examples/src/main/resources/rpg/TRIM01.rpgle
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FTRIM01V CF E WORKSTN USROPN
C PGMCTL DOWEQ 0
C EXFMT FMT01
C EVAL TRM=%TRIM(STR)
C ENDDO
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import kotlinx.serialization.Serializable
import java.io.File

/**
* Helper class used to load dspf configuration from a display file
* Helper class used to load dspf configuration from a display file.
* @param displayFilePath path where display file is located
* */
@Serializable
internal data class SimpleDspfConfig(var displayFilePath: String? = null) {
data class SimpleDspfConfig(var displayFilePath: String? = null) {

internal fun dspfProducer(displayFile: String): DSPF {
fun dspfProducer(displayFile: String): DSPF {
val videoFile = File(displayFilePath, "$displayFile.dspf")
require(videoFile.exists()) { "$videoFile doesn't exist" }

Expand All @@ -23,7 +23,7 @@ internal data class SimpleDspfConfig(var displayFilePath: String? = null) {
}
}

internal fun getMetadata(displayFile: String): FileMetadata {
fun getMetadata(displayFile: String): FileMetadata {
val videoFile = File(displayFilePath, "$displayFile.dspf")
require(videoFile.exists()) { "$videoFile doesn't exist" }

Expand Down

0 comments on commit d5e1d0f

Please sign in to comment.