Advertisement
Guest User

Untitled

a guest
Sep 11th, 2018
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Kotlin 6.79 KB | None | 0 0
  1. class ScreenParamsTable @Inject constructor(
  2.     private val db: SupportSQLiteDatabase
  3. ) {
  4.  
  5.   init {
  6.     db.execSQL(ScreenParamsModel.CREATE_TABLE)
  7.     db.execSQL(ScreenParamsModel.SCREEN_PARAMS_TYPE_IDX)
  8.   }
  9.  
  10.   @AutoValue
  11.   internal abstract class ScreenStateParams1 : ScreenParamsModel
  12.  
  13.   private val creator: Creator<ScreenParamsModel> =
  14.       object : Creator<ScreenParamsModel> by Creator(::AutoValue_ScreenParamsTable_ScreenStateParams1) {}
  15.   private val factory = Factory<ScreenParamsModel>(creator)
  16.  
  17.   private val mapper = factory.paramsMapper
  18.   private fun SupportSQLiteQuery.queryParams(): DynamicJson =
  19.     db
  20.       .query(this)
  21.       .mapConsume(mapper::map)
  22.       .toParams()
  23.  
  24.   private fun getRecursiveParamsByType(screen: Screen, type: Int): DynamicJson =
  25.     factory
  26.       .getRecursiveParams(type, screen.id)
  27.       .queryParams()
  28.  
  29.   private fun getParamsByType(screen: Screen, type: Int): DynamicJson =
  30.     factory
  31.       .getParams(type, screen.id)
  32.       .queryParams()
  33.  
  34.   private fun getParamByTypes(screen: Screen, vararg types: Int): DynamicJson =
  35.     factory
  36.       .getParamsByTypes(screen.id, types)
  37.       .queryParams()
  38.  
  39.   private fun getParamsByTypeAndNames(screen: Screen,
  40.                                       type: Int,
  41.                                       names: List<String>): DynamicJson =
  42.     factory
  43.       .getParamsByNames(type, screen.id, names.toTypedArray())
  44.       .queryParams()
  45.  
  46.   private fun getParamByType(screen: Screen, name: String, type: Int): Any? =
  47.     factory
  48.       .getParam(type, screen.id, name)
  49.       .let(db::query)
  50.       .firstConsume(mapper::map)
  51.       ?.let(::extractParam)
  52.  
  53.   private val addStm = ScreenParamsModel.SetParam(db)
  54.   private val delParamStm = ScreenParamsModel.DeleteParam(db)
  55.   private fun addParams(screen: Screen, params: DynamicJson, paramType: Int) {
  56.     if (params.isEmpty()) return
  57.     db.beginTransaction()
  58.     params.forEach { (name, value) ->
  59.       when(value) {
  60.         null -> delParamStm.exec { bind(paramType, screen.id, name) }
  61.         else -> {
  62.           val (type, stringValue) = packParam(value)
  63.           addStm.exec { bind(screen.id, name, paramType, type, stringValue) }
  64.         }
  65.       }
  66.     }
  67.     db.setTransactionSuccessful()
  68.     db.endTransaction()
  69.   }
  70.  
  71.   fun getInputAndReturnParams(screen: Screen) = getParamByTypes(screen, PARAM_TYPE_INPUT, PARAM_TYPE_RETURN_BACK)
  72.   fun getNonRecursiveParams(screen: Screen) = getParamByTypes(screen, PARAM_TYPE_INPUT, PARAM_TYPE_STATE, PARAM_TYPE_RETURN_BACK)
  73.  
  74.   fun setReturnParams(screen: Screen, params: DynamicJson) = addParams(screen, params, PARAM_TYPE_RETURN_BACK)
  75.  
  76.   fun getStackParam(screen: Screen, name: String) = getParamByType(screen, name, PARAM_TYPE_INPUT_STACK)
  77.   fun getStackParams(screen: Screen) = getRecursiveParamsByType(screen, PARAM_TYPE_INPUT_STACK)
  78.   fun setStackParams(screen: Screen, params: DynamicJson) = addParams(screen, params, PARAM_TYPE_INPUT_STACK)
  79.  
  80.   fun getInputParams(screen: Screen) = getParamsByType(screen, PARAM_TYPE_INPUT)
  81.   fun setInputParams(screen: Screen, params: DynamicJson) = addParams(screen, params, PARAM_TYPE_INPUT)
  82.  
  83.   fun getStateParam(screen: Screen, name: String) = getParamByType(screen, name, PARAM_TYPE_STATE)
  84.   fun getStateParams(screen: Screen) = getParamsByType(screen, PARAM_TYPE_STATE)
  85.   fun getStateParamsByNames(screen: Screen, names: List<String>) = getParamsByTypeAndNames(screen, PARAM_TYPE_STATE, names)
  86.   fun setStateParams(screen: Screen, params: DynamicJson) = addParams(screen, params, PARAM_TYPE_STATE)
  87.  
  88.   fun deleteParamsNotInScreens(screenIds: IntArray) =
  89.     factory
  90.       .deleteParamsNotInScreens(screenIds)
  91.       .let(db::query)
  92.       .close()
  93.  
  94.   companion object {
  95.     private const val LONG = 1
  96.     private const val STRING = 2
  97.     private const val BOOLEAN = 3
  98.     private const val DOUBLE = 4
  99.     private const val SERIALIZABLE = 5
  100.     private const val LONG_ARRAY = 6
  101.     private const val STRING_ARRAY = 7
  102.     private const val JSON = 9
  103.  
  104.     private const val PARAM_TYPE_INPUT = 0
  105.     private const val PARAM_TYPE_STATE = 1
  106.     private const val PARAM_TYPE_INPUT_STACK = 2
  107.     private const val PARAM_TYPE_RETURN_BACK = 3
  108.     private const val ARRAY_SEPARATOR = 0.toByte().toChar().toString()
  109.  
  110.     private val parser = moshiAdapter<Any>()
  111.     private val utf8 = Charset.defaultCharset()
  112.   }
  113.  
  114.   private fun packParam(value: Any): Pair<Int, String> {
  115.     return when (value) {
  116.       is Int, is Long     -> LONG to value.toString()
  117.       is Float, is Double -> DOUBLE to value.toString()
  118.       is String           -> STRING to value
  119.       is Boolean          -> BOOLEAN to value.toString()
  120.       is Map<*,*>         -> JSON to parser.toJson(value)
  121.       is Array<*>         -> when {
  122.         value.isArrayOf<String>()       -> STRING_ARRAY to value.joinToString(ARRAY_SEPARATOR)
  123.         value.isArrayOf<Long>()         -> LONG_ARRAY to value.joinToString(ARRAY_SEPARATOR)
  124.         value.isArrayOf<Serializable>() -> SERIALIZABLE to serialize(value)
  125.         else                            -> error("Array type not supported $value")
  126.       }
  127.       is Serializable     -> SERIALIZABLE to serialize(value)
  128.       else                -> error("Param type not supported $value ${value::class.java.canonicalName}")
  129.     }
  130.   }
  131.  
  132.   private fun List<ScreenParamsModel>.toParams(): DynamicJson {
  133.     val out: MutableDynamicJson = mutableMapOf()
  134.     for (param in this) {
  135.       out[param.name()] = extractParam(param)
  136.     }
  137.     return out
  138.   }
  139.  
  140.   private fun extractParam(param: ScreenParamsModel): Any? {
  141.     val value = param.value() ?: return null
  142.     return when (param.value_type()) {
  143.       LONG               -> value.toLong()
  144.       STRING             -> value
  145.       BOOLEAN            -> value.toBoolean()
  146.       DOUBLE             -> value.toDouble()
  147.       JSON               -> parser.fromJson(value) as DynamicJson
  148.       SERIALIZABLE       -> deserialize(value)
  149.       STRING_ARRAY       -> value
  150.           .takeIf { it.isNotBlank() }
  151.           ?.split(ARRAY_SEPARATOR)
  152.           ?.toTypedArray()
  153.           ?: emptyArray<String>()
  154.       LONG_ARRAY         -> value
  155.           .takeIf { it.isNotBlank() }
  156.           ?.split(ARRAY_SEPARATOR)
  157.           ?.map { it.toLong() }
  158.           ?.toTypedArray()
  159.           ?: emptyArray<Long>()
  160.       else               -> null
  161.     }
  162.   }
  163.  
  164.   private fun serialize(obj: Serializable): String {
  165.     val out = ByteArrayOutputStream()
  166.     ObjectOutputStream(out).use {
  167.       it.writeObject(obj)
  168.       it.flush()
  169.     }
  170.     val encoded = Base64.encode(out.toByteArray(), Base64.DEFAULT)
  171.     return encoded.toString(utf8)
  172.   }
  173.  
  174.   private fun deserialize(obj: String): Any? {
  175.     val decoded = Base64.decode(obj, Base64.DEFAULT)
  176.     return decoded
  177.         .inputStream()
  178.         .let(::ObjectInputStream)
  179.         .use { it.readObject() }
  180.   }
  181. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement