正在从Kotlin中的位掩码获取枚举列表



我在数据库实体中有一个枚举类SettingsVisibility,我正在将其转换为位掩码以存储在数据库中。我正在尝试将转换反转为bitmask,并获得一个枚举列表作为返回值。因此,如果我有一个值为ONE(1), TWO(2), FOUR(4)的枚举,那么它将存储为Enum(7)。我想把7转换成{ONE, TWO, FOUR}

我的代码在下面。我有一个SettingsVisibility枚举,其中包含存储在数据库中的整数值。当我尝试从数据库中检索时,Objectbox将使用给定的PropertyConvertor来整理/取消整理数据。当我想要convertToEntityProperty时,它应该只返回保存的枚举的列表,但目前它返回所有枚举的列表。我可以传递12databaseValue,它将返回所有枚举,而不是仅返回2(位置和付款(。

我认为问题在于enumClass.enumConstants的使用,因为它获得了所有的值,但过滤器对此不起作用,所以我陷入了困境。

@Entity
data class Settings(
@Id override var id: Long = 0,
@Convert(converter = DocumentVisibilityConverter::class, dbType = Int::class)
val showItems: List<SettingsVisibility>
) : Identifiable<Long> {
lateinit var organisation: ToOne<Organisation>

constructor() : this(
showItems = emptyList(),
)
enum class SettingsVisibility(override val bit: Int) : Flags {
USERS(1),
FINANCE(2),
LOCATION(4),
PAYMENTS(8),
MESSAGES(16),
ERRORS(32),
CANCELLATIONS(64)
}
internal class DocumentVisibilityConverter
: BoxConverters.EnumFlagConverter<SettingsVisibility>(SettingsVisibility::class.java)
}

例如,如果我存储前3个,那么数据库值将为7(1+2+4(。

数据库是ObjectBox,这里是属性转换器:

abstract class EnumFlagConverter<E>(private val enumClass: Class<E>) : PropertyConverter<List<E>, Int> where E : Enum<E>, E : Flags {
override fun convertToDatabaseValue(entityProperty: List<E>?): Int? {
return entityProperty?.toBitMask()?.value
}
override fun convertToEntityProperty(databaseValue: Int?): List<E>? {
return databaseValue?.let(::BitMask)?.enabledValues(enumClass)
}
}
class BitMask(val value: Int)
interface Flags {
val bit: Int
fun toBitMask() = BitMask(bit)

fun <T> BitMask.enabledValues(enumClass: Class<T>): List<T>? where T : Enum<T>, T : Flags? {
return enumClass.enumConstants?.filter(::hasFlag)
}
infix fun <T : Flags?> BitMask.hasFlag(flag: T): Boolean {
if (value == 0 || (value > 0 && flag?.bit == 0)) {
return false
}
return true
}

也许hasFlag中的逻辑是错误的,因为我认为如果不是0,它只会得到每个枚举。

答案是将return true替换为:

if (flag?.bit?.toByte() == null) {
return false
}
return (this.value.toByte().and(flag.bit.toByte()) == flag.bit.toByte())

这基本上是:bit & mask == bit

最新更新