com.atlan.pkg.serde.cell.CellXformer.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of package-toolkit-runtime Show documentation
Show all versions of package-toolkit-runtime Show documentation
Atlan custom package runtime toolkit
/* SPDX-License-Identifier: Apache-2.0
Copyright 2023 Atlan Pte. Ltd. */
package com.atlan.pkg.serde.cell
import com.atlan.cache.ReflectionCache
import com.atlan.model.assets.Asset
import com.atlan.model.core.AtlanTag
import com.atlan.model.enums.AtlanEnum
import com.atlan.model.structs.AtlanStruct
import com.atlan.pkg.PackageContext
import java.io.IOException
import java.util.SortedSet
import java.util.TreeSet
object CellXformer {
const val LIST_DELIMITER = "\n"
private const val NEWLINE_SENTINEL = "§LF±"
fun encode(
ctx: PackageContext<*>,
value: Any?,
guid: String? = null,
dates: Boolean = false,
): String {
return when (value) {
is String -> encodeString(value)
is Collection<*> -> {
val list = mutableListOf()
for (element in value) {
val encoded = encode(ctx, element, guid, dates)
list.add(encoded)
}
return getDelimitedList(list)
}
is Map<*, *> -> {
val list = mutableListOf()
for ((key, embeddedValue) in value) {
list.add(key.toString() + "=" + encode(ctx, embeddedValue, guid, dates))
}
return getDelimitedList(list)
}
is Asset -> AssetRefXformer.encode(ctx, value)
is AtlanEnum -> EnumXformer.encode(value)
is AtlanStruct -> StructXformer.encode(ctx.client, value)
is AtlanTag -> AtlanTagXformer.encode(ctx.client, guid!!, value)
is Long -> {
if (dates) {
TimestampXformer.encode(value)
} else {
value.toString()
}
}
is Any -> value.toString()
else -> ""
}
}
@Suppress("UNCHECKED_CAST")
fun decode(
ctx: PackageContext<*>,
assetClass: Class<*>?,
value: String?,
type: Class<*>,
innerType: Class<*>?,
fieldName: String,
): Any? {
return if (value.isNullOrEmpty()) {
null
} else if (String::class.java.isAssignableFrom(type)) {
when (fieldName) {
in UserXformer.FIELDS -> UserXformer.decode(ctx.client, value, fieldName)
in GroupXformer.FIELDS -> GroupXformer.decode(ctx.client, value, fieldName)
in RoleXformer.FIELDS -> RoleXformer.decode(ctx.client, value, fieldName)
in DataTypeXformer.FIELDS -> DataTypeXformer.decode(value, fieldName)
else -> decodeString(value)
}
} else if (Boolean::class.java.isAssignableFrom(type) || java.lang.Boolean::class.java.isAssignableFrom(type)) {
decodeBoolean(value)
} else if (Integer::class.java.isAssignableFrom(type) || java.lang.Integer::class.java.isAssignableFrom(type)) {
decodeInt(value)
} else if (Long::class.java.isAssignableFrom(type) || java.lang.Long::class.java.isAssignableFrom(type)) {
if (ReflectionCache.isDate(assetClass, fieldName)) {
TimestampXformer.decode(value, fieldName)
} else {
decodeLong(value)
}
} else if (Double::class.java.isAssignableFrom(type) || java.lang.Double::class.java.isAssignableFrom(type)) {
decodeDouble(value)
} else if (Collection::class.java.isAssignableFrom(type)) {
// Start by checking whether the list is simple or complex
val values = parseDelimitedList(value)
val list = mutableListOf()
if (innerType != null) {
for (element in values) {
val decoded = decode(ctx, assetClass, element, innerType, null, fieldName)
if (decoded != null) {
list.add(decoded)
}
}
}
when (type) {
Collection::class.java, List::class.java -> list
Set::class.java, SortedSet::class.java -> TreeSet(list)
else -> throw IOException("Unable to deserialize cell to Java class (in $fieldName): $type")
}
} else if (Map::class.java.isAssignableFrom(type)) {
TODO("Not yet implemented for import")
} else if (Asset::class.java.isAssignableFrom(type)) {
AssetRefXformer.decode(ctx, value, fieldName)
} else if (AtlanEnum::class.java.isAssignableFrom(type)) {
EnumXformer.decode(value, type as Class)
} else if (AtlanStruct::class.java.isAssignableFrom(type)) {
StructXformer.decode(ctx.client, value, type as Class)
} else if (AtlanTag::class.java.isAssignableFrom(type)) {
AtlanTagXformer.decode(ctx.client, value)
} else if (type.isInterface) {
// Relationships between assets are defined via interfaces, so this would mean
// there should be asset references
AssetRefXformer.decode(ctx, value, fieldName)
} else {
throw IOException("Unhandled data type (in $fieldName): $type")
}
}
private fun getDelimitedList(values: List?): String {
return if (values.isNullOrEmpty()) {
""
} else {
values.joinToString(LIST_DELIMITER)
}
}
private fun parseDelimitedList(values: String?): List {
return if (values.isNullOrEmpty()) {
listOf()
} else {
values.split(LIST_DELIMITER).map { it.trim() }
}
}
fun encodeString(value: String): String {
return if (value.contains(LIST_DELIMITER)) {
value.replace(LIST_DELIMITER, NEWLINE_SENTINEL)
} else {
value
}
}
fun decodeString(value: String): String {
return if (value.contains(NEWLINE_SENTINEL)) {
value.replace(NEWLINE_SENTINEL, LIST_DELIMITER)
} else {
value
}
}
fun decodeBoolean(value: String): Boolean {
return value.toBoolean()
}
fun decodeInt(value: String): Int {
return value.toInt()
}
fun decodeLong(value: String): Long {
return value.toLong()
}
fun decodeDouble(value: String): Double {
return value.toDouble()
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy