uniVocity / univocity-parsers

uniVocity-parsers is a suite of extremely fast and reliable parsers for Java. It provides a consistent interface for handling different file formats, and a solid framework for the development of new parsers.
915 stars 251 forks source link

[BUG] Custom conversion not working on enum fields #470

Open kas1337 opened 3 years ago

kas1337 commented 3 years ago
Description

Since v2.9.1 the custom conversion for enum fields seems to be broken. It fails throwing the exception "MyEnum cannot be cast to java.lang.String"

Example

With the following enum field

    @Parsed(field = "BrakeSpecialCharacteristics", index = 60, applyDefaultConversion = false)
    @Convert(conversionClass = MyEnumConversion.class)
    private MyEnum myEnum;

and the conversion class

class MyEnumConversion : Conversion<String?, MyEnum?> {

    override fun execute(input: String?): MyEnum? {
        require(input != null) { "Error" }

        return input.toIntOrNull()
            ?.let { MyEnum.forIdentifier(it) }
            ?: throw IllegalArgumentException("Error")
    }

    override fun revert(input: MyEnum?): String? {
        require(input != null) { "Error" }

        return input.identifier.toString()
    }

}

parsing the enum field fails.

The enum looks like this

enum class MyEnum(
    val identifier: Int
) {
    YES(1),
    NO(2);

    companion object {
        fun forIdentifier(identifier: Int): MyEnum? {
            return values().find { it.identifier == identifier }
        }
    }
}

Evaluation

It seems like the field is passed as a String to execute in the conversion class. Debugging through https://github.com/uniVocity/univocity-parsers/blob/master/src/main/java/com/univocity/parsers/common/fields/FieldConversionMapping.java shows that the conversions list in https://github.com/uniVocity/univocity-parsers/blob/7e7d1b3c0a3dceaed4a8413875eb1500f2a028ec/src/main/java/com/univocity/parsers/common/fields/FieldConversionMapping.java#L265 contains two conversions for the enum field: the custom conversion AND the default enum conversion. Thus the default conversion is applied after (or vice versa) the custom conversion which fails because the second time result is being passed as an enum and not as a string.

Assumption

Several changes where made in https://github.com/uniVocity/univocity-parsers/compare/v2.9.0...v2.9.1

Maybe the changes made from here https://github.com/uniVocity/univocity-parsers/compare/v2.9.0...v2.9.1#diff-b30623f01abb657ccdaf4b0c4a22c0f8407a485fc27ac969c3c34aec8fc09769R364 could be the culprit.

It would be nice if you could have a look into this. Thanks!