-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a646e68
commit 7ed8816
Showing
11 changed files
with
226 additions
and
33 deletions.
There are no files selected for viewing
22 changes: 22 additions & 0 deletions
22
...erializer/src/androidTest/java/com/marcinmoskala/kotlinpreferences/DeserializationTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package com.marcinmoskala.kotlinpreferences | ||
|
||
import android.support.test.runner.AndroidJUnit4 | ||
import com.google.gson.Gson | ||
import com.marcinmoskala.kotlinpreferences.gson.GsonSerializer | ||
import org.junit.Assert | ||
import org.junit.Test | ||
import org.junit.runner.RunWith | ||
|
||
@RunWith(AndroidJUnit4::class) | ||
class DeserializationTest : GsonBaseTest() { | ||
|
||
data class User(var name: String, var age: Int = 0) | ||
|
||
@Test | ||
fun listDeserializationTest() { | ||
val json = "[{\"age\"=\"0\", \"name\"=\"Name0\"}, {\"age\"=\"1\", \"name\"=\"Name1\"}, {\"age\"=\"2\", \"name\"=\"Name2\"}]" | ||
val users = GsonSerializer(Gson()).deserialize(json, object : TypeToken<List<User>>() {}.type) | ||
val expected = List(3) { i -> User("Name$i", i) } | ||
Assert.assertEquals(expected, users) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 3 additions & 1 deletion
4
preferenceholder/src/main/java/com/marcinmoskala/kotlinpreferences/Serializer.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,10 @@ | ||
package com.marcinmoskala.kotlinpreferences | ||
|
||
import java.lang.reflect.Type | ||
|
||
interface Serializer { | ||
|
||
fun serialize(toSerialize: Any?): String? | ||
|
||
fun <T> deserialize(serialized: String?): Any? | ||
fun deserialize(serialized: String?, type: Type): Any? | ||
} |
129 changes: 129 additions & 0 deletions
129
preferenceholder/src/main/java/com/marcinmoskala/kotlinpreferences/TypeToken.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
package com.marcinmoskala.kotlinpreferences | ||
|
||
import java.io.Serializable | ||
import java.lang.reflect.GenericArrayType | ||
import java.lang.reflect.Modifier | ||
import java.lang.reflect.ParameterizedType | ||
import java.lang.reflect.Type | ||
import java.lang.reflect.WildcardType | ||
import java.util.Arrays | ||
|
||
open class TypeToken<T> protected constructor() { | ||
|
||
private val superclass = javaClass.genericSuperclass as ParameterizedType | ||
val type: Type = canonicalize(superclass.actualTypeArguments[0]) | ||
|
||
private class ParameterizedTypeImpl(ownerType: Type?, rawType: Type, vararg typeArguments: Type) : ParameterizedType, Serializable { | ||
private val ownerType: Type? | ||
private val rawType: Type | ||
private val typeArguments: List<Type> | ||
|
||
init { | ||
// require an owner type if the raw type needs it | ||
if (rawType is Class<*>) { | ||
val isStaticOrTopLevelClass = Modifier.isStatic(rawType.modifiers) || rawType.enclosingClass == null | ||
checkArgument(ownerType != null || isStaticOrTopLevelClass) | ||
} | ||
|
||
this.ownerType = if (ownerType == null) null else canonicalize(ownerType) | ||
this.rawType = canonicalize(rawType) | ||
this.typeArguments = typeArguments.map { canonicalize(it) } | ||
} | ||
|
||
override fun getActualTypeArguments() = typeArguments.toTypedArray() | ||
|
||
override fun getRawType() = rawType | ||
|
||
override fun getOwnerType() = ownerType | ||
|
||
override fun toString(): String { | ||
val stringBuilder = StringBuilder(30 * (typeArguments.size + 1)) | ||
stringBuilder.append(typeToString(rawType)) | ||
|
||
if (typeArguments.isEmpty()) { | ||
return stringBuilder.toString() | ||
} | ||
|
||
stringBuilder.append("<").append(typeToString(typeArguments[0])) | ||
for (i in 1 until typeArguments.size) { | ||
stringBuilder.append(", ").append(typeToString(typeArguments[i])) | ||
} | ||
return stringBuilder.append(">").toString() | ||
} | ||
} | ||
|
||
private class GenericArrayTypeImpl(componentType: Type) : GenericArrayType, Serializable { | ||
|
||
private val componentType: Type = canonicalize(componentType) | ||
|
||
override fun getGenericComponentType() = componentType | ||
|
||
override fun toString() = typeToString(componentType) + "[]" | ||
} | ||
|
||
private class WildcardTypeImpl(upperBounds: Array<Type>, lowerBounds: Array<Type>) : WildcardType, Serializable { | ||
private val upperBound: Type | ||
private val lowerBound: Type? | ||
|
||
init { | ||
checkArgument(lowerBounds.size <= 1) | ||
checkArgument(upperBounds.size == 1) | ||
|
||
if (lowerBounds.size == 1) { | ||
checkNotNull(lowerBounds[0]) | ||
checkNotPrimitive(lowerBounds[0]) | ||
checkArgument(upperBounds[0] === Any::class.java) | ||
this.lowerBound = canonicalize(lowerBounds[0]) | ||
this.upperBound = Any::class.java | ||
|
||
} else { | ||
checkNotNull(upperBounds[0]) | ||
checkNotPrimitive(upperBounds[0]) | ||
this.lowerBound = null | ||
this.upperBound = canonicalize(upperBounds[0]) | ||
} | ||
} | ||
|
||
override fun getUpperBounds() = arrayOf(upperBound) | ||
|
||
override fun getLowerBounds() = | ||
if (lowerBound != null) arrayOf(lowerBound) else EMPTY_TYPE_ARRAY | ||
|
||
override fun toString(): String = when { | ||
lowerBound != null -> "? super " + typeToString(lowerBound) | ||
upperBound === Any::class.java -> "?" | ||
else -> "? extends " + typeToString(upperBound) | ||
} | ||
} | ||
|
||
companion object { | ||
|
||
internal val EMPTY_TYPE_ARRAY = arrayOf<Type>() | ||
|
||
internal fun canonicalize(type: Type): Type = if (type is Class<*>) { | ||
if (type.isArray) GenericArrayTypeImpl(canonicalize(type.componentType)) else type | ||
} else if (type is ParameterizedType) { | ||
ParameterizedTypeImpl(type.ownerType, type.rawType, *type.actualTypeArguments) | ||
} else if (type is GenericArrayType) { | ||
GenericArrayTypeImpl(type.genericComponentType) | ||
} else if (type is WildcardType) { | ||
WildcardTypeImpl(type.upperBounds, type.lowerBounds) | ||
} else { | ||
type | ||
} | ||
|
||
internal fun typeToString(type: Type): String { | ||
return if (type is Class<*>) type.name else type.toString() | ||
} | ||
|
||
internal fun checkNotPrimitive(type: Type) { | ||
checkArgument(type !is Class<*> || !type.isPrimitive) | ||
} | ||
|
||
internal fun <T> checkNotNull(obj: T?): T = if (obj != null) obj else throw NullPointerException() | ||
|
||
internal fun checkArgument(condition: Boolean) { | ||
if (!condition) throw IllegalArgumentException() | ||
} | ||
} | ||
} |
9 changes: 9 additions & 0 deletions
9
preferenceholder/src/main/java/com/marcinmoskala/kotlinpreferences/bindings/Clearable.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package com.marcinmoskala.kotlinpreferences.bindings | ||
|
||
import com.marcinmoskala.kotlinpreferences.PreferenceHolder | ||
import kotlin.reflect.KProperty | ||
|
||
interface Clearable { | ||
fun clear(thisRef: PreferenceHolder, property: KProperty<*>) | ||
fun clearCache() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.