All Downloads are FREE. Search and download functionalities are using the official Maven repository.

dev.thecodewarrior.prism.Prism.kt Maven / Gradle / Ivy

The newest version!
package dev.thecodewarrior.prism

import dev.thecodewarrior.mirror.type.ConcreteTypeMirror
import dev.thecodewarrior.mirror.type.TypeMirror
import dev.thecodewarrior.mirror.type.TypeSpecificityComparator
import dev.thecodewarrior.mirror.type.WildcardMirror
import dev.thecodewarrior.prism.internal.unmodifiableView
import java.lang.IllegalArgumentException

public class Prism> {
    private val _serializers = mutableMapOf>()
    public val serializers: Map> = _serializers.unmodifiableView()

    private val _factories = mutableListOf>()
    public val factories: List> = _factories.unmodifiableView()

    public operator fun get(type: TypeMirror): Lazy {
        var mirror = type
        if(mirror is WildcardMirror) {
            mirror = mirror.upperBound
                ?: throw InvalidTypeException("Wildcard `$mirror` can't be serialized since it has no upper bound")

            if(mirror !is ConcreteTypeMirror) {
                throw InvalidTypeException(
                    "${mirror.javaClass.simpleName} `$mirror` (the extracted upper bound from `$type`) can't " +
                            "be serialized. Only concrete types (or type variables specialized to be concrete types) " +
                            "can be serialized"
                )
            }
        }
        if(mirror !is ConcreteTypeMirror) {
            throw InvalidTypeException(
                "${mirror.javaClass.simpleName} `$mirror` can't be serialized. Only concrete types " +
                        "(or type variables specialized to be concrete types) can be serialized"
            )
        }

        _serializers[mirror]?.also {
            return it
        }
        val unannotated = mirror.withTypeAnnotations(listOf())
        _serializers[unannotated]?.also {
            _serializers[mirror] = it
            return it
        }

        val factory = _factories.fold, SerializerFactory?>(null) { acc, factory ->
            val applicable = factory.pattern.isAssignableFrom(mirror) && factory.predicate?.invoke(mirror) != false
            if (applicable) {
                val moreSpecific = acc == null || TypeSpecificityComparator.compare(acc.pattern, factory.pattern) <= 0 ||
                    (acc.predicate == null && factory.predicate != null && TypeSpecificityComparator.compare(acc.pattern, factory.pattern) == 0)
                if (moreSpecific)
                    factory
                else
                    acc
            } else {
                acc
            }
        }
            ?: throw SerializerNotFoundException("Could not find a serializer or factory for $mirror")

        val lazy = lazy { factory.create(mirror) }
        _serializers[mirror] = lazy
        lazy.value
        return lazy
    }

    public fun register(vararg factories: SerializerFactory): Prism {
        factories.forEach { factory ->
            _factories.removeIf { it === factory }
            _factories.add(factory)
        }
        return this
    }

    public fun register(vararg serializers: T): Prism {
        serializers.forEach { serializer ->
            if(serializer.type in _serializers)
                throw IllegalArgumentException("Duplicate serializer for ${serializer.type}")
            _serializers[serializer.type] = lazyOf(serializer)
        }
        return this
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy