iterate list of data classes not working as expected - kotlin

I have a list of data classes that I am trying to iterate over.
Here is the data class and where it is created.
data class BgaResponse(val columnName: String, val restricted: Boolean, val predictionValue: Double)
val bgaResponse: List<BgaResponse>? = callBgaEndpoint(bgaRequest)
printing bgaResponseshows this:
[{columnName=col1, restricted=false, predictionValue=0.9963}, {columnName=not_here, restricted=false, predictionValue=0.995941}]
I first tried using forEach:
bgaResponse?.forEach {
println(it)
}
this prints nothing. Next i tried accessing each element by index:
for(i in 0 until bgaResponse!!.size) {
println(bgaResponse[i])
}
this prints each element as expected:
{columnName=col1, restricted=false, predictionValue=0.9963}
{columnName=not_here, restricted=false, predictionValue=0.995941}
I tried printing bgaResponse[i].columnName but nothing prints again. Now this isnt making any sense.
Lastly I try:
for(i in 0 until bgaResponse!!.size) {
val x: BgaResponse= bgaResponse[i]
}
this should work, my IDE is telling me bgaResponse[i] is a BgaResponse. This throws back an error:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.package.something.placeholder.model.BgaResponse

Related

Kotlin Generic problem, UNCHECKED_CAST , required:Nothing

#file:Suppress("UNCHECKED_CAST")
data class Element<T>(
val key: String,
val valueOne: T,
val valueTwo: T,
val comparator: Comparator<T>,
val comparatorValue: CompareResult
)
enum class CompareResult(
val value: Int
) {
LESS(-1),
EQUAL(0),
GREATER_THAN(1)
}
fun <T> matchesComparison(list:Collection<Element<T>>): Pair<Boolean, List<String>> {
val failedComparisons = mutableListOf<String>()
for (element in list) {
val compareValue = element.comparator.compare(element.valueOne, element.valueTwo)
if (element.comparatorValue.value != compareValue) {
failedComparisons.add(element.key)
}
}
return Pair(failedComparisons.isEmpty(), failedComparisons)
}
val stringComparator = Comparator.comparing(String::toString)
val intComparator = Comparator.comparing(Int::toInt)
val elementsToCompare = listOf(
Element("number", 1, 2, intComparator, CompareResult.LESS),
Element("first name", "a", "a", stringComparator, CompareResult.EQUAL),
Element("last name", "a", "b", stringComparator, CompareResult.EQUAL)
)
matchesComparison(elementsToCompare).second.joinToString(", ","Failed elements: \"","\"")
I often get faced with comparing two different object properties with the same values.
As an example object A has props number,firstname,lastname. What i want to do is create a list have and have a function which goes over these Elements and returns which props have failed the comparison. I've managed to use generics for both the object and the matchesComparison function which returns the failed comparisons. The problem begins when i want to pass this list which is of type Collection<Element<out Any>> to this function is i get a type missmatch. instead of using unchecked casts to force the Comparator to be of type Any i would like to do this
val stringComparator = Comparator.comparing(String::toString)
val intComparator = Comparator.comparing(Int::toInt)
The result value that of the script above should be Failed elements: "last name"
I tried changing the signature of the function to out any but then the comparator.compare method has both params as of type Nothing. I really want to avoid unsing unchecked casts.
matchesComparison() doesn't need to be generic in this case. It doesn't really care what is the type of the whole input collection, so we can simply use * here.
Then we have another problem. The compiler isn't smart enough to notice that while we perform operations on a single element, all its properties are of matching types. As a result, it doesn't allow to use element.comparator on element.valueOne and element.valueTwo. To fix this problem, we simply need to create a separate function which works on a single Element, so it understand the type for all properties is the same:
fun matchesComparison(list:Collection<Element<*>>): Pair<Boolean, List<String>> {
fun <T> Element<T>.matches() = comparatorValue.value == comparator.compare(valueOne, valueTwo)
val failedComparisons = mutableListOf<String>()
for (element in list) {
if (!element.matches()) {
failedComparisons.add(element.key)
}
}
return Pair(failedComparisons.isEmpty(), failedComparisons)
}
Also, I believe such matches() function should be actually a member function of Element. It seems strange that while Element is pretty independent and it contains everything that is needed to perform a comparison, it still requires to use external code for this. If it would have a matches() function then we wouldn't need to care about its T. matches() would work with any Element.

Parse a line of input into different types in Kotlin

this problem need print data types
https://codeforces.com/group/MWSDmqGsZm/contest/219158/problem/B
but he need inputs on just one line with space between each data type
this is my code , what's the problem
import java.util.Scanner
fun main(args:Array){
val scanner = Scanner(System.`in`)
var a:Int=readLine()!!.toInt()
var b:Long=readLine()!!.toLong()
var c:Char=scanner.next().single()
var d:Float=readLine()!!.toFloat()
var e:Double=readLine()!!.toDouble()
println(a)
println(b)
println(c)
println(d)
println(e)
}
Exception in thread "main" java.lang.NumberFormatException: For input string: "45 65896532145 a 45.23 65423.325"
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
at java.base/java.lang.Integer.parseInt(Integer.java:660)
at java.base/java.lang.Integer.parseInt(Integer.java:778)
at Test_1Kt.main(test 1.kt:7)
The problem is that you cannot parse the entire input as integer, as the input you expect is set of values with space between. Space itself cannot be parsed into Integer (this is what cause the exception)
To solve this, first, you need to split the input and parse each of the element. You can split it using kotlin built in function, i.e.
val input = readLine() ?: ""
val inputElement = input.split(" ")
Here, the inputElement is a string array that consist all of element from your input. Next, you need to parse each of the element by the inputElement index
val a:Int=inputElement[0].toInt()
val b:Long=inputElement[1].toLong()
val c:Char=inputElement[2].single()
val d:Float=inputElement[3].toFloat()
val e:Double=inputElement[4].toDouble()
println(a)
println(b)
println(c)
println(d)
println(e)

Javalin 4: How to write properly check in call to Validator.check()?

I am trying to adopt existing code of parameter validation from Javalin 3 to Javalin 4. It uses Javalin's Validator class. Here's the code I've got (rewritten):
val messageId = ctx.pathParamAsClass<String>("messageId")
.check(check = { it.trim().matches(Uuid.REGEX) }, errorMessage = "message id must be a UUID")
.get()
.trim()
And I am getting compile error for the check() call:
e:
/home/ivan/.../SourceFile.kt: (53, 6): None of the following functions can be called with the arguments
supplied:
public final fun check(check: Check<String> /* = (String) -> Boolean */, error: ValidationError<String>):
Validator<String> defined in io.javalin.core.validation.Validator
public final fun check(check: Check<String> /* = (String) -> Boolean */, error: String): Validator<String> defined in
io.javalin.core.validation.Validator
I can't understand why there is an error. I assume I should have matched second overload of check(). How to write it correctly?
Note: I have read Javalin 3 to 4 migration guide, which gives example like this:
ctx.queryParamAsClass<Int>("age")
.check({ it >= 18 }, ValidationError("AGE_TOO_LOW", args = mapOf("minAge" to 18)))
.get()
which I seem to follow, except I give it error message as string, but there's matching overload. So what is wrong here?
The cause was that second parameter of check() is called error, not errorMessage, i.e. correct code is like this:
...
.check(check = { it.trim().matches(Uuid.REGEX) }, error = "...")
...

CodeBlock throwing IAE because CassName does not pass is TypeName check

I tried to initialize a property, though CodeBlock#of throws an IllegalArgumentException in CodeBlock#argToType
I looked into the root cause of the error which was at CodeBlock#argToType.
Even if o is a ClassName(which also is a TypeName) it does not pass the is TypeName -> o check and throws the IllegalArguementException.
val initString = "mutableMapOf(Pair(%T, %T), Pair(%T, %T))"
val initArgs = arraysOf(...)
CodeBlock.of(initString, initArgs)
I expected the CodeBlock to be built correctly, but instead it throws the IllegalArguementException
I reproduced you problem and was able to fix it; I think the key question is how you pass initArgs to CodeBlock.of: this method is expecting a second varargs parameter but you're passing a single Array<...> value.
Changing you code as follows seems to work:
fun main(args: Array<String>) {
val initString = "mutableMapOf(Pair(%T, %T), Pair(%T, %T))"
val initArgs = arrayOf(String::class.java, String::class.java, String::class.java, String::class.java)
val result = CodeBlock.of(initString, *initArgs)
println("result is $result")
}
The key point is to pass *initArgs, and not initArgs, as second parameter of CodeBlock.of.
I explicitly initialized initArgs' values witch type values, in order to match %T placeholder expectations.
I hope this can help you!

kotlin with fastjson parse object error: default constructor not found

I am trying use fastjson parse object in Kotlin code. but exception happened when I use JSON.parseObject, here are detail:
My data class:
import com.alibaba.fastjson.JSONObject
data class StatesMessage #JvmOverloads constructor(val command: String =
"states", var states: States = States()) {
fun toJsonString(): String {
return JSONObject.toJSONString(this)
}
data class States(var x: Double = 0.0, var y: Double = 0.0)
}
Then I try to get object from string:
val state = JSON.parseObject(s, StatesMessage::class.java)
But exception throw from fastjson:
Caused by: com.alibaba.fastjson.JSONException: default constructor not found.
class com.example.demo.StatesMessage
at com.alibaba.fastjson.util.JavaBeanInfo.build(JavaBeanInfo.java:475)
at com.alibaba.fastjson.util.JavaBeanInfo.build(JavaBeanInfo.java:221)
at com.alibaba.fastjson.parser.ParserConfig.createJavaBeanDeserializer(ParserConfig.java:670)
at com.alibaba.fastjson.parser.ParserConfig.getDeserializer(ParserConfig.java:587)
at com.alibaba.fastjson.parser.ParserConfig.getDeserializer(ParserConfig.java:398)
at com.alibaba.fastjson.parser.DefaultJSONParser.parseObject(DefaultJSONParser.java:665)
at com.alibaba.fastjson.JSON.parseObject(JSON.java:365)
at com.alibaba.fastjson.JSON.parseObject(JSON.java:269)
at com.alibaba.fastjson.JSON.parseObject(JSON.java:488)
at com.example.demo.StartupRunner.run(StartupRunner.kt:25)
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:813)
... 5 more
all code refer to https://github.com/forest-yang/koltinjson
I think it's a fastjson (till 1.2.54) bug.
When I change to gson, it's work.
/* it will throw exception
val state = JSON.parseObject(s, StatesMessage::class.java)
*/
val state = Gson().fromJson(s, StatesMessage::class.java)
logger.info(state.states.x)
logger.info(state.states.y)