Corda - Checking equality of AbstractParty, Party and AnonymousParty - kotlin

In Corda we have the following type hierarchy for providing ledger identities:
abstract class AbstractParty(val owningKey: PublicKey): Destination {
/** Anonymised parties do not include any detail apart from owning key,
so equality is dependent solely on the key */
override fun equals(other: Any?): Boolean {
return other === this
|| other is AbstractParty
&& other.owningKey == owningKey
}
...
}
// Shortened for brevity
class Party(...) : AbstractParty(...) { ... }
class AnonymousParty(...) : AbstractParty(...) { ... }
Note the comment:
Anonymised parties do not include any detail apart from owning key, so equality is dependent solely on the key
What I want to know is, why is equality defined at the root of the hierarchy, but nowhere else?
For example:
val wellKnownAlice = Party(aliceKey, aliceX500name)
val anonymousAlice = AnonymousParty(aliceKey)
wellKnownAlice == anonymousAlice
// true
Whilst I hold an opinionated view, I don't feel like these should be equal when they are fundamentally different things. I feel like this would have been better implemented like so:
abstract class AbstractParty(val owningKey: PublicKey): Destination {
override fun equals(other: Any?): Boolean {
return other === this
|| other is AbstractParty
&& other.javaClass == javaClass
&& equalsByKey(other)
}
fun equalsByKey(other: AbstractParty): Boolean {
return other === this || other.owningKey == owningKey
}
...
}
class Party(...) : AbstractParty(...) {
override fun equals(other: Any?): Boolean {
return other === this
|| other is Party
&& other.name == name
&& equalsByKey(other)
}
...
}
class AnonymousParty(...) : AbstractParty(...) { ... }
Thoughts on this much appreciated.

I agree it is a bit of an inconsistency. I know you are a more experienced CorDapp developer than I am (because your previous questions have helped me learn Corda) but I will share my own experience.
When I first started working with Corda I thought (and coded) in terms of Party. However the more I introduced Confidential Identities into my CorDapps the more I began to think in terms of PublicKey (AnonymousParty).
So I actually find this “inconsistency” somewhat handy.
I wonder if the developers at R3 knew that CorDapps should generally always use AnonymousParty so wanted to make comparing AnonymousParty and Party as easy as possible. Just a guess.

Consider the case where you have name: CordaX500Name and key: PublicKey. Then define
val p1 = AnonymousParty(key)
val p2 = Party(name, key)
With your proposed implementation you would have p1 == p2 but not p2 == p1, so the relation is not symmetric and hence not a valid equivalence relation.
The well-known name is supposed to be unique for any given key, so I think that the current implementation is reasonable. Otherwise we would distinguish otherwise equal identities based on whether they were resolved to a name or not.

Related

Validating combination of values in constructor

I'm trying to make a class Box<T>. It should have two public immutable(val) properties, isContentMandatory: Boolean, content: T?. This is which combination of values I want to accept:
isContentMandatory
content
Should allow?
false
null
YES
false
non-null
YES
true
null
NO
true
non-null
YES
I want to make sure that the constructor(s) I provide won't allow the illegal state of an object. Also, I want multiple constructors(or use default values) so that creation of an object is straight-forward for the client. Following are examples of instantiations:
Box() // OK -> isContentMandatory = false, content = null
Box("some-content") // OK -> isContentMandatory = false, content = "some-content"
Box(false, "some-content") // OK -> isContentMandatory = false, content = "some-content"
Box(true, "some-content") // OK -> isContentMandatory = true, content = "some-content"
Box(true, null) // DON'T ALLOW
Box(true) // DON'T ALLOW
The DON'T ALLOWs from above should preferably be forbidden at compile-time(no constructor available for that combination) if it's possible. Otherwise, fail with the exception during creation.
I'm coming from Java world so all those primary/secondary constructors, default values and etc. are a bit fuzzy so please explain along with a solution. I'm also open to different class design if it supports the same business logic.
EDIT: this is how it would look in Java.
public class Box<T> {
private final boolean isContentMandatory;
private final T content;
public Box() {
this(null);
}
public Box(T content) {
this(false, content);
}
public Box(boolean isContentMandatory, T content) {
if (isContentMandatory && content == null) {
throw new IllegalArgumentException("Invalid combination of parameters");
}
this.isContentMandatory = isContentMandatory;
this.content = content;
}
...getters...
}
Whether or not this is a good approach for the problem is hard to answer without actual domain knowledge of your use case, but it feels to me like it makes little sense that you would make a single class to model those cases which carries around an (otherwise pointless?) boolean to separate the cases.
You could just have 2 classes BoxWithOptionalcontent<T?> and BoxWithContent<T> and you wouldn't need more than the default constructor for either afaict.
sealed interface Box<T: Any?> {
abstract val content: T?
}
data class BoxWithContent<T: Any>(override val content: T): Box<T>
data class BoxWithOptionalContent<T: Any?>(override val content: T? = null): Box<T?>
This shouldn't change much on the initialization site, on the side of the usage you will probably need to add a case statement to decide which case it is and handle appropriately. But you probably already have some similar logic there anyway, and this will probably be a bit more typesafe and readable.
From your Java approach it seems you just want a runtime check, not really preventing bad calls. Just having default arguments and one init block to validate should work:
class Box(val content: T? = null, val isContentMandatory: Boolean = false)
init {
if(content == null && isContentMandatory)
throw RuntimeException("Cannot have no content if content is mandatory")
}
}
Any content given though as a first argument will be valid, so to make this break you have to try harder using Box(isContentMandatory=true) or Box(null, true) explicitly.

How about "this" as a type? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed last year.
Improve this question
I will simplify the problem that got me to this point, but I was thinking about this block of code :
abstract class A {
fun myCustomApply(block: A.() -> Unit): A {
this.block() // block() would have the same effect
// Do something else here
return this
}
}
class B : A() {
fun anotherFunction() {
// Do something
}
}
This code looks (and is) ok. But consider the following snippet :
fun doSomethingVeryUseful(): B /* Won't work */ {
val b = B()
return b.myCustomApply {
anotherFunction() // Nope
}
}
Here, the compiler will complain, for two reasons, that may not seem obvious at first glance. First of all, myCustomApply's block parameter was declared with type A.() -> Unit, so we can't call anotherFunction() within its scope, because it was declared in class B.
Then, it appears that doSomethingVeryUseful's return type was declared as B, but myCustomApply returns A, so we have to use an as A cast.
Both errors are logical, because the compiler can't guess by itself "Oh yeah, the return type is A but it always returns this, so it is perfectly fine to do that !", but these are kinda painful to handle properly because I personnally can't think of a proper workaround.
Of course, you could do something like this :
abstract class A
class B : A() {
fun anotherFunction() {
// Do something
}
}
fun <T : A> T.myCustomApply(block: T.() -> Unit): T {
this.block()
// Do something else
return this
}
But I personnally think this is not a good idea, because it confuses the code (where does the myCustomApply come from ? Why isn't it in class A ?), and is a bit complicated for such a simple problem. You're free to think this is a good solution, but I don't really agree.
My idea was to do something like this (don't try this in your IDE, it will just complain that you're the worst developper ever and that you doesn't even deserve to exist because it isn't actual syntax) :
abstract class A {
fun myCustomApply(block: this.() -> Unit): this {
block()
// Do something else
return this
}
}
class B : A() {
fun anotherFunction() {
// Do something
}
}
fun doSomethingVeryUseful(): B {
val b = B()
return b.myCustomApply {
anotherFunction() // YEAH
}
}
Note that this is used in two places : as a receiver type and as a return type.
As this already is a keyword, it wouldn't break any existing code, so backward compatibility is assured.
this as a type would have a single accepted value, that is, this. Why use this as a type ? This will garantee to the compiler that the value is effectively of the type of the receiver, that is b.myCustomApply now accepts a lambda of type B.() -> Unit, and has a return type of type B, since b itself is of type B.
Another (purely aesthetic) advantage would be that it is now clear that the same object (that is, the receiver) will be passed to the lambda, and then returned to the caller of the method.
This would translate to something like this :
abstract class A<_this : A<_this>> {
private fun _this(): _this =
#Suppress("UNCHECKED_CAST") (this as _this)
fun myCustomApply(block: _this.() -> Unit): _this {
_this().block()
// You got the idea
return _this()
}
}
class B : A<B>() {
fun anotherFunction() {
// Do something
}
}
The _this type parameter's name is pretty self-explaining of its role, if A already has type parameters then _this should be added at the beggining of them, and any type expression of the form A<T, U, V, ...> should expand to A<A, T, U, V, ...>.
this as return type would require that return this and return /* something that has this as type */ are the only return statements that are allowed, as we couldn't ensure that any other value is actually always of the same type as this.
I propose this (what a great pun huh) because it has been several times that I felt a need for such a feature, but I'm unsure whether this is a good idea or not, if it is feasible, and if there actually are people that are interested.
In either cases, thank you for reading, have a great day !
On thread "Self Types", from Andrey Breslav, lead language designer for Kotlin, in December 2014:
Unfortunately, self types turn out to be a challenge when it comes to type system design. We don't see a sane way of implementing them at the moment
See also:
"This type", an adjacent forum thread
"Emulating self types in Kotlin", a Medium post by Jerzy Chałupski
It does not really answer your question (assuming there was any question at all), but note you can do something like this:
abstract class A<T : A<T>> {
fun myCustomApply(block: T.() -> Unit): T {
(this as T).block() // block() would have the same effect
// Do something else here
return this
}
}
class B : A<B>() { ... }

Nested safe call Null check Kotlin

I need to display an image in an ImageView, so I need to make sure that the image url is not null first. Are these 3 options valid?
Answer data class
data class Answer(
val id: Long?,
val title: String?,
val answerImage: AnswerImage?
) {
data class AnswerImage(
val x0: AnswerImageData?,
val x1: AnswerImageData?,
val x2: AnswerImageData?
) {
data class AnswerImageData(
val id: String?,
val url: String?
)
}
}
Option 1
answer.answerImage?.let { answerImage ->
answerImage.x0?.let { answerImageData ->
answerImageData.url?.let {
//display image
}
}
}
Option 2
if (answer.answerImage?.x0?.url != null)
{
//display image
}
Option 3
answer.answerImage?.x0?.url?.let {
//display image
}
Short answer: yes.
Option 1: Would only be a good choice if you actually need to do more things with answerImage and answerImageData rather than just cast it safely. In this specific case, we don't have a use for declaring those variables explicitly. To conclude: option 1 in this case is not a very neat solution, but it does work.
Option 2: should work, because all attributes are immutable. The compiler can then deduce on the next line (inside if scope), that the url property will still be non-null.
Option 3: this is in my opinion the best one: it's the easiest one to process as a reader of the code, as you would generally finish it with code like this: .let { safeUrl -> .. }.
As specified by #Ken Van Hoeylandt all 3 options are valid, another valid option could be to use elvis operator:
fun attemptDisplayingImage(answer: Answer) {
val answerImage = answer.answerImage ?: return
val answerImageData = answerImage.x0 ?: return
val answerImageDataUrl = answerImageData.url ?: return
// display image
}
There's an interesting article about this topic here
Ken covered the answers (they're all fine and do the same thing, the last one is how the language is designed to be used really, nice and neat!) but I wanted to touch on your actual data model.
First, you say you need to check that an AnswerImageData's url isn't null. But the only reason it could be null, is because you've explicitly made it nullable, with a String? type. Is an AnswerImageData with a null url ever valid? Or does it always need to have one? I'm guessing it does, and I'm guessing it always needs an id too - so just make them non-null!
data class AnswerImageData(
val id: String,
val url: String
)
Now all your AnswerImageData objects are guaranteed to have non-null values - they're all valid in that sense, it's baked into your design. So you don't need to null check them anymore!
And the same goes for your other classes - can you have an AnswerImage with null values? This might be a trickier one, let's assume there needs to always be at least one AnswerImageData in an AnswerImage - in which case you can make the first non-null, and the others optional:
data class AnswerImage(
val x0: AnswerImageData,
val x1: AnswerImageData?,
val x2: AnswerImageData?
)
This isn't necessarily the best way to do this - I'd personally prefer a vararg parameter, or some kind of collection, so you can have an arbitrary number of AnswerImageDatas and do operations like .first(predicate) to loop over them all easily. But if you want exactly three slots, three parameters is a way to do it!
Same goes for Answer - I'm guessing that requires an id, title and answerImage - if so, don't let them be null. Enforce that valid structure through your types, it'll make your life a lot easier! And so will avoiding nullable types unless you actually need them!
I don't know if that applies to what you're doing, but it probably does, so it's worth mentioning. (This kind of thing is called *Domain-Driven Design if you want to look into it - basically enforcing the rules and structure of your business logic through the way you design your code, your types, your objects etc.)
All the answers above were great but I wanted to mention something. You declared your properties as nullable so I'm guessing you are getting them from somewhere else (from your data layer if you're familiar with clean architecture).
my recommendation is to create a domain model for your class and map the data to your domain model(which has non-null properties). this way you handle nulls in the mapper. it's cleaner and follows the separation of concerns and single responsibility principles.
interface Mapper<F, S> {
fun firstToSecond(first: F): S
fun secondToFirst(second: S): F
}
data class DataModel(
val id: Long?,
val title: String?,
val answerImage: AnswerImage?
)
data class DomainModel(
val id: Long,
val title: String,
val answerImage: AnswerImage
)
class DataToDomainMapper: Mapper<DataModel, DomainModel> {
override fun firstToSecond(first: DataModel): DomainModel {
return DomainModel(
id = first.id ?: -1,
title = first.title ?: "no title",
answerImage = first.answerImage ?: AnswerImage()
)
}
override fun secondToFirst(second: DomainModel): DataModel {
return DataModel(
id = second.id,
title = second.title,
answerImage = second.answerImage
)
}
}
this way you don't have to handle nulls anywhere else in your code. and for data validation, you can check the id not to be negative. I've shortened your models, but you get the idea

Smart casting not working when statement is refactored. How to solve?

I have something simple below (I use when instead of if, as I simplified from some code that uses when)
fun simplePresent(presentable: Presentable?) {
when {
presentable != null -> execute(presentable)
else -> skip()
}
}
fun execute(presentable: Presentable) { // Do something }
It's all good. But when I refactor the checking code out into Function
fun simplePresent(presentable: Presentable?) {
when {
hasPresentable(presentable) -> execute(presentable)
else -> skip()
}
}
fun execute(presentable: Presentable) { // Do something }
fun hasPresentable(presentable: Presentable?) = presentable != null
the smart casting to non-null fail for the value pass to execute function, causing a compile time error reporting required Presentable found Presentable?
How could I prevent that error, while I still retain my refactor code?
Functions are meant to be independent to each other. There is just no constraint to enforce hasPresentable to return true iff presentable is not null at type level.
So it's kind of impossible without Kotlin team deciding to enhance the type system.
Why not using something like presentable?.execute() ?: skip() instead?
If you want to do more checking in hasPresentable you can do this:
fun checkPresentable(presentable: Presentable?): Presentable? =
presentable?.takeIf { do your check here }
fun simplePresent(presentable: Presentable?) =
checkPresentable(presentable)?.execute() ?: skip()
fun Presentable.execute() { }

Create a list from statements in a DSL block

In an attempt to build a DSL for validation, I am looking for ways to collect the statements inside a block/lambda with receiver. To illustrate, here is a minimal example without the actual validation logic:
data class Constraint(val hint: String)
class Validation(val constraints: List<Constraint>) {
companion object {
operator fun invoke(init: (ValidationBuilder.() -> Unit)): Validation {
return ValidationBuilder().apply(init).build()
}
}
class ValidationBuilder {
private var constraints: MutableList<Constraint> = mutableListOf()
operator fun Constraint.unaryPlus() {
constraints.add(this)
}
fun build() = Validation(constraints)
}
}
This can then be used to build a Validation like so
val validation = Validation {
+Constraint("First constraint")
val secondConstraintHint = "Second constraint"
+Constraint(secondConstraintHint)
}
I would like to get rid of the unaryPlus operator and directly collect the individual statements in the block that are evaluated to a Constraint so that I can do something like:
val validation = Validation {
Constraint("First constraint")
val secondConstraintHint = "Second constraint"
Constraint(secondConstraintHint)
}
Is that possible somehow?
To give a little bit more context, the actual result I am aiming for will look more like this:
Validation<User> {
User::firstName {
val min = 2
minLength(min) hint "Please provide a first name"
maxLength(200) // uses default hint
}
}
Well, there seems to be no straightforward solution, because Kotlin provides no way to handle an evaluated expression result that is not assigned, returned or passed anywhere.
A possible workaround is to mimic the constructor you need with a function defined for your builder:
class ValidationBuilder {
/* ... */
fun Constraint(name: String) =
full.qualified.name.of.Constraint(name).also(constraints::add)
}
Unfortunately, this will require you to duplicate all the signatures that you want to call in this way.
UPD (answering to the comment): I believe the idiomatic way for users to customize a DSL is defining their own extensions for the DSL builders:
fun ValidationBuilder.nonEmptyText(min: Int = 1, max: Int = 65.536) = TODO()
If a Constraint that comes from outside the DSL is an important use case, you can cover it with a special function (e.g. fun ValidationBuilder.constraint(...)) and let the users delegate their extensions to it.