Corda vault batch query by arbitrary indexed object property - corda

looking for help regarding queries. if i'm looking for the latest LinearState of SomeObjectState by property someProp i can do the following:
private fun lookupBySomeProp(someProp: String) : List<StateAndRef<SomeObjectState>> {
val generalCriteria = VaultQueryCriteria(Vault.StateStatus.UNCONSUMED)
val somePropIdx = builder { SomePersistentObject::someProp.equal(someProp) }
val somePropQueryCriteria = VaultCustomQueryCriteria(somePropIdx)
val queryCriteria = generalCriteria.and(somePropQueryCriteria)
val results = serviceHub.vaultService.queryBy<SomeObjectState>(queryCriteria)
// ... handle results here
}
how would i go about doing a single batch lookup for multiple SomeObjectState objects given a list of someProp identifiers?
private fun lookupBySomeProps(somePropList: List<String>) : List<StateAndRef<SomeObjectState>> {
val generalCriteria = VaultQueryCriteria(Vault.StateStatus.UNCONSUMED)
// how do i build efficiently build my bulk query?
}
i'm expecting to have to do something along the lines of the following in order return multiple states matching the list but have been have trouble properly implementing it
val somePropeIdx = builder { SomePersistentObject::someProp.in(somePropList) }

From this link: https://docs.corda.net/api-vault-query.html you can use .in() in your criteria among many other things:
Binary logical (AND, OR)
Comparison (LESS_THAN, LESS_THAN_OR_EQUAL, GREATER_THAN, GREATER_THAN_OR_EQUAL)
Equality (EQUAL, NOT_EQUAL)
Likeness (LIKE, NOT_LIKE)
Nullability (IS_NULL, NOT_NULL)
Collection based (IN, NOT_IN)
Standard SQL-92 aggregate functions (SUM, AVG, MIN, MAX, COUNT)

The reason why your query in the question didn't work is because how Corda has defined the .in() function.
You had:
val somePropeIdx = builder { SomePersistentObject::someProp.in(somePropList) }
Substituting notIn works fine:
val somePropeIdx = builder { SomePersistentObject::someProp.notIn(somePropList) }
However, in order to use .in() you have to include backticks.
So your query would be:
val somePropeIdx = builder { SomePersistentObject::someProp.`in`(somePropList) }
You can see this difference in definition in the source here.

Related

Referencing list element inside of map in Kotlin

I am new to Kotlin and am still trying to learn it. I have been researching this problem for several hours now and still have not figured it out. I want to get an element from inside of a list by it's index. I figured out how to do this with a plain list, like so
val my_list = listOf(1,2,3)
println(my_list.get(0))
The above works, but when I try to do this with a list that is stored inside of a map
val my_list = mutableMapOf<String, Any>()
my_list["set1"] = listOf(1,2,3)
my_list["set2"] = listOf("A","B","C")
my_list["set3"] = listOf("d","e","f")
val sub_list = my_list["set1"]
println(sub_list.get(0))
I get the following error
Unresolved reference. None of the following candidates is applicable
because of receiver type mismatch: #InlineOnly public inline operator
fun <#OnlyInputTypes K, V> Map.get(key: Int): ???
defined in kotlin.collections #SinceKotlin public operator fun
MatchGroupCollection.get(name: String): MatchGroup? defined in
kotlin.text
Note: I primarily use Python, so that is what I am used to. The functionality from Python that I am trying to reproduce in Kotlin is having a dictionary of lists.
The problem is the type declaration of your map, it should be:
val my_list = mutableMapOf<String, List<Any>>()
Any doesn't have a get() method, so there's no way to invoke it.
Even when that problem is solved, you'll probably have to deal with nullability, though, as:
val sub_list = my_list["set1"]
Will return List<Any>?, which means that my_list might not have a value for the specified key. If that's the case, you'll have to do something like:
sub_list?.get(0)?.run { println(it) }
Which in turn, could also cause an exception if the sub_list is empty. That could be solved with something more like:
vsub_list?.firstOrNull()?.run { println(it) }

Is there a way to filter out null Any? values in Kotlin Map?

I'm trying to think of a function that would allow a Map<String, Any?> object to be treated as Map<String,Any> through type inference through applying a single function.
I am pretty new to the transformation functions in Kotlin and have tried the various filter and filterValues filterNot on the map like so:
val input = mapOf(Pair("first",null))
val filtered: Map<String,Any> = input.filter { it.value!=null }
it also fails to compile with any of these
input.filterValues { it!=null }
input.filterNot { it.value==null }
input.filterNot { it.value is Nothing }
The closest I can seem to get is applying multiple steps or having an Unchecked cast warning. I would have thought that filtering the values to be !=null would suffice. My only other thought is that it's due to the generics?
The filter functions return a Map with the same generic types as the original map. To transform the type of the value, you need to map the values from Any? to Any, by doing a cast. The compiler can't know that the predicate you pass to filter() makes sure all the values of the filtered map are non-null, so it can't use type inference. So your best et is to use
val filtered: Map<String, Any> = map.filterValues { it != null }.mapValues { it -> it.value as Any }
or to define a function doing the filtering and the transformation in a single pass, and thus be able to use smart casts:
fun filterNotNullValues(map: Map<String, Any?>): Map<String, Any> {
val result = LinkedHashMap<String, Any>()
for ((key, value) in map) {
if (value != null) result[key] = value
}
return result
}
The compiler just doesn't perform type analysis deep enough to infer that, for example, input.filterValues { it != null } filters out null values from the map and thus the resulting map should have a not-null value type. Basically there can be arbitrary predicate with arbitrary meaning in terms of types and nullability.
There is no special case function for filtering null values out of a map in the stdlib (like there is .filterIsInstance<T>() for iterables). Therefore your easiest solution is to apply an unchecked cast thus telling the compiler that you are sure about the type safety not being violated:
#Suppress("UNCHECKED_CAST")
fun <K, V> Map<K, V?>.filterNotNullValues() = filterValues { it != null } as Map<K, V>
See also: another question with a similar problem about is-check.
This yields no warnings kotlin 1.5.30
listOfNotNull(
nullableString?.let { "key1" to it },
nullableString?.let { "key2" to it }
).toMap()

Kotlin invoke getter/setter reflectively

Beginner in Kotlin here.
I try to create and populate objects by reflection in a program. I cannot find the equivalent functionality in pure kotlin so my solution resembles the code below which works fine, but requires the use of dirty references like java.lang.String::class.java and intelliJ, understandably, doesn't seem to like this. Is there a simpler way that I am missing to do this?
val jclass = myObject::class.java
val setters = jclass.declaredMethods.filter { it.name.startsWith("set") }
for (s in setters) {
val paramType = s.parameterTypes.first()
val data = when(paramType) {
java.lang.Integer::class.java -> foo
java.lang.Double::class.java -> bar
java.lang.String::class.java -> baz
}
s.invoke(myObject, data)
}
You can use Kotlin reflection, which requires you to add kotlin-reflect as a dependency to your project.
Here you can find kotlin-reflect for Kotlin 1.0.5, or pick another version if you use different Kotlin version.
After that, you can rewrite your code as follows:
val properties = myObject.javaClass.kotlin.memberProperties
for (p in properties.filterIsInstance<KMutableProperty<*>>()) {
val data = when (p.returnType.javaType) {
Int::class.javaPrimitiveType,
Int::class.javaObjectType -> foo
Double::class.javaPrimitiveType,
Double::class.javaObjectType -> bar
String::class.java -> baz
else -> null
}
if (data != null)
p.setter.call(myObject, data)
}
Some details:
Despite using Kotlin reflection, this approach works with Java classes as well, their fields and accessors will be seen as properties, as described here.
Just like with Java reflection, memberProperties returns public properties of this type and all its supertypes. To get all the properties declared in the type (including the private ones, but not those from the supertypes), use declaredMemberProperties instead.
.filterIsInstance<KMutableProperty<*> returns only the mutable properties, so that you can use their p.setter later. If you need to iterate over the getters of all the properties, remove it.
In the when block, I compared p.returnType.javaType to Int::class.javaPrimitiveType and Int::class.javaObjectType, because what's Int in Kotlin can be mapped to either Java int or java.lang.Integer depending on its usage. In Kotlin 1.1, it will be enough to check p.returnType.classifier == Int::class.
If You need to get property getter/setter, there is a couple of built-in constructions for it YourClass::propertyName
have a look at example bellow
fun main(args: Array<String>) {
val myObject = Cat("Tom", 3, 35)
println(Cat::age.getter.call(myObject)) // will print 3
Cat::age.setter.call(myObject, 45)
print(myObject) // will print Cat(name=Tom, age=45, height=35)
}
data class Cat(var name : String, var age : Int, val height : Int)
but sometimes you don't know class exactly(working with generics) or need to get list of properties, then use val <T : Any> KClass<T>.declaredMemberProperties: Collection<KProperty1<T, *>> it will return all properties, some of them can be mutable(var) and some immutable(val), you can find out immutability by checking belonging to KMutableProperty<*> (by filtering with is operator or using convenience methods such as filterIsInstance<KMutableProperty<*>>)
about your code snippet
I absolutely agree with hotkey, but now it is better to use myObject::class.declaredMemberProperties instead of myObject.javaClass.kotlin.memberProperties
because the second one is deprecated
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.jvm/java-class.html
data class Cat(var name : String, var age : Int, val height : Int)
#JvmStatic
fun main(args: Array<String>) {
val myObject = Cat("Tom", 3, 35)
val properties = myObject::class.declaredMemberProperties
for (p in properties.filterIsInstance<KMutableProperty<*>>()) {
val data = when (p.returnType.javaType) {
Int::class.javaPrimitiveType,
Int::class.javaObjectType -> 5
String::class.java -> "Rob"
else -> null
}
if (data != null)
p.setter.call(myObject, data)
}
println(myObject)
// it will print Cat(name=Rob, age=5, height=35),
// because height isn't var(immutable)
}
in general, I would approach similar problems with such construction in mind
val myObject = Cat("Tom", 3, 35)
Cat::class.declaredMemberProperties
//if we want only public ones
.filter{ it.visibility == KVisibility.PUBLIC }
// We only want strings
.filter{ it.returnType.isSubtypeOf(String::class.starProjectedType) }
.filterIsInstance<KMutableProperty<*>>()
.forEach { prop ->
prop.setter.call(myObject, "Rob")
}
println(myObject)
//it will print Cat(name=Rob, age=3, height=35),
//because name is only eligible in this case

Kotlin's List missing "add", "remove", Map missing "put", etc?

In Java we could do the following
public class TempClass {
List<Integer> myList = null;
void doSomething() {
myList = new ArrayList<>();
myList.add(10);
myList.remove(10);
}
}
But if we rewrite it to Kotlin directly as below
class TempClass {
var myList: List<Int>? = null
fun doSomething() {
myList = ArrayList<Int>()
myList!!.add(10)
myList!!.remove(10)
}
}
I got the error of not finding add and remove function from my List
I work around casting it to ArrayList, but that is odd needing to cast it, while in Java casting is not required. And that defeats the purpose of having the abstract class List
class TempClass {
var myList: List<Int>? = null
fun doSomething() {
myList = ArrayList<Int>()
(myList!! as ArrayList).add(10)
(myList!! as ArrayList).remove(10)
}
}
Is there a way for me to use List but not needing to cast it, like what could be done in Java?
Unlike many languages, Kotlin distinguishes between mutable and immutable collections (lists, sets, maps, etc). Precise control over exactly when collections can be edited is useful for eliminating bugs, and for designing good APIs.
https://kotlinlang.org/docs/reference/collections.html
You'll need to use a MutableList list.
class TempClass {
var myList: MutableList<Int> = mutableListOf<Int>()
fun doSomething() {
// myList = ArrayList<Int>() // initializer is redundant
myList.add(10)
myList.remove(10)
}
}
MutableList<Int> = arrayListOf() should also work.
Defining a List collection in Kotlin in different ways:
Immutable variable with immutable (read only) list:
val users: List<User> = listOf( User("Tom", 32), User("John", 64) )
Immutable variable with mutable list:
val users: MutableList<User> = mutableListOf( User("Tom", 32), User("John", 64) )
or without initial value - empty list and without explicit variable type:
val users = mutableListOf<User>()
//or
val users = ArrayList<User>()
you can add items to list:
users.add(anohterUser) or
users += anotherUser (under the hood it's users.add(anohterUser))
Mutable variable with immutable list:
var users: List<User> = listOf( User("Tom", 32), User("John", 64) )
or without initial value - empty list and without explicit variable type:
var users = emptyList<User>()
NOTE: you can add* items to list:
users += anotherUser - *it creates new ArrayList and assigns it to users
Mutable variable with mutable list:
var users: MutableList<User> = mutableListOf( User("Tom", 32), User("John", 64) )
or without initial value - empty list and without explicit variable type:
var users = emptyList<User>().toMutableList()
//or
var users = ArrayList<User>()
NOTE: you can add items to list:
users.add(anohterUser)
but not using users += anotherUser
Error: Kotlin: Assignment operators ambiguity:
public operator fun Collection.plus(element: String): List defined in kotlin.collections
#InlineOnly public inline operator fun MutableCollection.plusAssign(element: String): Unit defined in kotlin.collections
see also:
https://kotlinlang.org/docs/reference/collections.html
Agree with all above answers of using MutableList but you can also add/remove from List and get a new list as below.
val newListWithElement = existingList + listOf(element)
val newListMinusElement = existingList - listOf(element)
Or
val newListWithElement = existingList.plus(element)
val newListMinusElement = existingList.minus(element)
Apparently, the default List of Kotlin is immutable.
To have a List that could change, one should use MutableList as below
class TempClass {
var myList: MutableList<Int>? = null
fun doSomething() {
myList = ArrayList<Int>()
myList!!.add(10)
myList!!.remove(10)
}
}
Updated
Nonetheless, it is not recommended to use MutableList unless for a list that you really want to change. Refers to https://hackernoon.com/read-only-collection-in-kotlin-leads-to-better-coding-40cdfa4c6359 for how Read-only collection provides better coding.
In Kotlin you must use MutableList or ArrayList.
Let's see how the methods of MutableList work:
var listNumbers: MutableList<Int> = mutableListOf(10, 15, 20)
// Result: 10, 15, 20
listNumbers.add(1000)
// Result: 10, 15, 20, 1000
listNumbers.add(1, 250)
// Result: 10, 250, 15, 20, 1000
listNumbers.removeAt(0)
// Result: 250, 15, 20, 1000
listNumbers.remove(20)
// Result: 250, 15, 1000
for (i in listNumbers) {
println(i)
}
Let's see how the methods of ArrayList work:
var arrayNumbers: ArrayList<Int> = arrayListOf(1, 2, 3, 4, 5)
// Result: 1, 2, 3, 4, 5
arrayNumbers.add(20)
// Result: 1, 2, 3, 4, 5, 20
arrayNumbers.remove(1)
// Result: 2, 3, 4, 5, 20
arrayNumbers.clear()
// Result: Empty
for (j in arrayNumbers) {
println(j)
}
UPDATE: As of Kotlin 1.3.70, the exact buildList function below is available in the standard library as an experimental function, along with its analogues buildSet and buildMap. See https://blog.jetbrains.com/kotlin/2020/03/kotlin-1-3-70-released/.
Confining Mutability to Builders
The top answers here correctly speak to the difference in Kotlin between read-only List (NOTE: it's read-only, not "immutable"), and MutableList.
In general, one should strive to use read-only lists, however, mutability is still often useful at construction time, especially when dealing with third-party libraries with non-functional interfaces. For cases in which alternate construction techniques are not available, such as using listOf directly, or applying a functional construct like fold or reduce, a simple "builder function" construct like the following nicely produces a read-only list from a temporary mutable one:
val readonlyList = mutableListOf<...>().apply {
// manipulate your list here using whatever logic you need
// the `apply` function sets `this` to the `MutableList`
add(foo1)
addAll(foos)
// etc.
}.toList()
and this can be nicely encapsulated into a re-usable inline utility function:
inline fun <T> buildList(block: MutableList<T>.() -> Unit) =
mutableListOf<T>().apply(block).toList()
which can be called like this:
val readonlyList = buildList<String> {
add("foo")
add("bar")
}
Now, all of the mutability is isolated to one block scope used for construction of the read-only list, and the rest of your code uses the read-only list that is output from the builder.
You can do with create new one like this.
var list1 = ArrayList<Int>()
var list2 = list1.toMutableList()
list2.add(item)
Now you can use list2, Thank you.
https://kotlinlang.org/docs/reference/collections.html
According to above link List<E> is immutable in Kotlin.
However this would work:
var list2 = ArrayList<String>()
list2.removeAt(1)
A list is immutable by Default, you can use ArrayList instead. like this :
val orders = arrayListOf<String>()
then you can add/delete items from this like below:
orders.add("Item 1")
orders.add("Item 2")
by default ArrayList is mutable so you can perform the operations on it.
In concept of immutable data, maybe this is a better way:
class TempClass {
val list: List<Int> by lazy {
listOf<Int>()
}
fun doSomething() {
list += 10
list -= 10
}
}

How convert any record into a map/dictionary in F#?

I need to serialize arbitrary records into maps/dictionary.
I imagine my end type look like this:
type TabularData= array<Map<string, obj>>
But I have problems in build a generic function that accept any record and turn them into Map.
In practice, the best advice is probably to use some existing serialization library like FsPickler. However, if you really want to write your own serialization for records, then GetRecordFields (as mentioned in the comments) is the way to go.
The following takes a record and creates a map from string field names to obj values of the fields. Note that it does not handle nested records and it is not particularly fast:
open Microsoft.FSharp.Reflection
let asMap (recd:'T) =
[ for p in FSharpType.GetRecordFields(typeof<'T>) ->
p.Name, p.GetValue(recd) ]
|> Map.ofSeq
Here is a little example that calls this with a simple record:
type Person =
{ Name : string
Age : int }
asMap { Name = "Tomas"; Age = -1 }
Using the same idea mentioned by Tomas, you can create a IDictionary<K,V> from a record like this:
let asDictionary (entity: 'T) =
seq {
for prop in FSharpType.GetRecordFields(typeof<'T>) ->
prop.Name, prop.GetValue(entity)
} |> dict

Resources