Mocking scope function in Kotlin - kotlin

I am using following object creation methods in kotlin
class Resource(
referenceFactory: ReferenceFactory,
id: String,
name: String,
role: String,
odi_runs: int,
odi_wickets: int,
test_runs: int,
test_wickets: int){
referenceFactory.calculateRank(Player().apply {
id = id
name = name
role = role
odi_runs = odi_runs
odi_wicket = odi_wickets
test_runs = test_runs
test_wicket = test_wicket
})
}
then I use this created object for calculate the rank of the player. To get the valid test result from reference factory, I need to mock this 'Player' object creating scope method.

Related

Values loss for copy() for Kotlin data class

I have such data class:
data class BookObject(
val description: String?,
val owningCompanyData: OwningCompanyData?,
) {
var id: String? = null
var createdAt: Instant? = null
var createdBy: String? = null
var modifiedAt: Instant? = null
fun update(command: CreateOrUpdateBookObjectCommand): BookObject =
this.copy(
description = command.description,
owningCompanyData = command.owningCompanyData
)
}
When I use the update function for an object with completely filled fields, I get an object with empty id, createdAt, createdBy, modifiedAt fields (they become equal to null). But why is this happening? Why do these fields lose their values?
The kotlin documentation says:
Use the copy() function to copy an object, allowing you to alter some
of its properties while keeping the rest unchanged.
The answer actually is present in your link, located in the paragraph just before "Copying".
The compiler only uses the properties defined inside the primary constructor for the automatically generated functions.

Kotlin create new object using another object as the default constructor params

data class Person(val age: Int, val name: String)
Is there a simple way to create a new Person object using another object as a template to fill in the required constructor params?
// Example of what I'd like to be able to do
val person1 = Person(age = 35, name = "Cory")
val person2 = Person(person1, name = "Jeff")
You can use copy() method, available in data classes, and override parameters you want to change:
val person1 = Person(age = 35, name = "Cory")
val person2 = person1.copy(name = "Jeff")
https://kotlinlang.org/docs/reference/data-classes.html#copying
Every data class in Kotlin has a copy function:
val person2 = person1.copy(name = "Jeff") // but its age is still 35 (from Cory)
All parameters are optional in the copy function, so you can overwrite / change the ones you like.
Note that the copy() call performs a shallow copy
See: Data Class Copying

Kotlin ktor exposed DSL insert with reference

I am developing a Kotlin with ktor application and I am using exposed as ORM. I have a table with a reference to another table. The relationship is many to one. ex:
object Users : IdTable<String>() {
override val id: Column<EntityID<String>> = varchar("user_id", 64).entityId().primaryKey()
val email = varchar("email", 128).uniqueIndex()
val firstName = varchar("first_name", 64)
val lastName = varchar("last_name", 64)
}
& User Attendance table as -
object UserAttendances : IntIdTable() {
val userId = reference("user_id", Users).index()
val checkInTime = date("check_in")
val checkOutTime = date("check_out")
}
Now when I am trying to insert into the attendance table, i am not sure how to map the insert to users. I tried the following -
StaffAttendances.insert {
it[date] = DateTime.now()
it[checkInTime] = DateTime.now()
it[userId] = userId
}
This gives a compilation error that the required type is EntityId<String> but found String. Any help on how i can insert into a reference. This could possibly be because I have String as ID column with UUIDs
The userId must take an EntityId<String>. So you should pass your userId as it[userId] = EntityId(userId, Users).
To avoid this, I use plain Table instead of IntIdTable and manually create my primary key. This way I can pass directly the value without wrapping it in an EntityId<>.

Define collection of data class

If I've the below data class
data class User(val name: String = "", val age: Int = 0)
How can I define a collection of it, like:
var user = User [] // this is not working
I need to be able to call the users by:
user[0].name // something like this!
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
You do it like this in Kotlin:
val array = arrayOf(User("name1"), User("name2"))
If you want to create an Array without adding elements right away, use
val arrayList = ArrayList<User>()
In this case you have to specify the element type explicitely because there is nothing to infer it from.
From the ArrayList docu:
Povides a MutableList implementation, which uses a
resizable array as its backing storage

Analogue of #Formula annotation from JPA for Spring data neo4j?

I'd like to calculate some properties of my domain objects at DB level using neo4j and return the read-only results. In JPA one can achieve this via #Formula annotation over field of domain object entity:
#Formula("(select avg(f.rating) from Feedback f where f.offer_id = offer_id)")
private Double rating;
What should one do to achieve the same behavior in Spring data neo4j? I wrote a Cypher query, but don't know where to use it.
A similar outcome can be achieved using #QueryResult
Create a class with fields to hold return data.
Annotate it with #QueryResult
Example: (in Kotlin, which is what I had on hand)
#QueryResult
open class Principal constructor(applicationToken: String,
profileId: String,
stageName: String,
showMeLaterDays: Float,
roles: Array<Role>)
{
var applicationToken: String
var profileId: String
var stageName: String
var showMeLaterDays: Float
#Convert(RoleArrayAttributeConverter::class)
var roles: Array<Role>
init
{
this.applicationToken = applicationToken
this.profileId = profileId
this.stageName = stageName
this.showMeLaterDays = showMeLaterDays
this.roles = roles
}
//Provide a default constructor for OGM
constructor() : this(applicationToken = "", profileId = "", stageName = "", showMeLaterDays = 0f,
roles = emptyArray())
}
Then use it with a repository as follows:
#Query("MATCH (n:CandidateProfile {applicationToken: {0} })
RETURN n.id as profileId, n.applicationToken as applicationToken, n.stageName as stageName, n.showMeLaterDays as showMeLaterDays, n.roles as roles;")
fun findByApplicationToken(token: String): Principal?
Note the way that node properties are returned to correspond with the class field names.
The same can be done with function results.