Search code examples
javakotlinkotlin-interop

Kotlin - attribute visibility to companion object


So I have the code below, written in Kotlin.

I'm getting a compilation error on the last instruction line (return params.keys.containsAll(MANDATORY_PARAMS)), the compiler says Unsolved reference: MANDATORY_PARAMS, but I don't really get why.

I thought companion objects were supposed to have some kind of visibility into the attributes of the classes they "keep company to".

What could I do to solve this? How could I make MANDATORY_PARAMS visible to both MandatoryParametersValidator and its companion object?

(disclaimer: this code is being migrated from Java to Kotlin. On Java version, mandatoryParametersHaveBeenProvided used to be a static method on the same class.)

import javax.validation.ConstraintValidator
import javax.validation.ConstraintValidatorContext

class MandatoryParametersValidator : ConstraintValidator<EnforceMandatoryParameters, Map<String, String>> {

    val MANDATORY_PARAMS = arrayOf("bookingReference", "lastName")

    override fun initialize(constraintAnnotation: EnforceMandatoryParameters?) {
        // do nothing
    }

    override fun isValid(params: Map<String, String>, context: ConstraintValidatorContext?): Boolean {
        MANDATORY_PARAMS
                .filter { !params.containsKey(it) }
                .forEach { parameterName ->
                    context?.disableDefaultConstraintViolation()
                    context?.buildConstraintViolationWithTemplate("Mandatory parameter $parameterName is missing.")?.addConstraintViolation()
                }

        return mandatoryParametersHaveBeenProvided(params)
    }

    companion object {
        fun mandatoryParametersHaveBeenProvided(params: Map<String, String>) : Boolean {
            return params.keys.containsAll(MANDATORY_PARAMS)
        }
    }
}

Thanks a lot!


Solution

  • You need to do two things to get this working

    1. Move MANDATORY_PARAMS into the companion object. The companion object is like the static parts of the class in Java. And MANDATORY_PARAMS would be static final in Java.

    2. Change the type of MANDATORY_PARAMS from Array<String> to List<String> (since containsAll requires a Collection.)

    The fixed code looks like this.

        ...
    
        companion object {
            val MANDATORY_PARAMS = listOf("bookingReference", "lastName")
            fun mandatoryParametersHaveBeenProvided(params: Map<String, String>) : Boolean {
                return params.keys.containsAll(MANDATORY_PARAMS)
            }
        }
    }