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

se.ansman.dagger.auto.AutoDaggerInitializer.kt Maven / Gradle / Ivy

package se.ansman.dagger.auto

import javax.inject.Inject

/**
 * A class that can initialize multiple [Initializable] in order of their [priority][AutoInitialize.priority].
 *
 * @since 1.0.0
 */
public class AutoDaggerInitializer @Inject constructor(
    private val initializables: Set<@JvmSuppressWildcards Initializable>
) : Initializable {
    /**
     * If the initializer has been initialized or not (i.e. if [initialize] has been called).
     */
    @Volatile
    public var isInitialized: Boolean = false
        private set

    private var isInitializing: Boolean = false

    /**
     * Initializes the provided [Initializable]. This method is thread safe and calling it multiple
     * times will only initialize the initializables once.
     *
     * If any initializable throws an exception the remaining initializes are still initialized before rethrowing the
     * exception. If multiple initializables throw then the first one is thrown with the other exceptions added as
     * suppressed exceptions.
     *
     * If this method fails, calling it again will complete successfully without attempting to initialize the failed
     * initializables again.
     */
    public override fun initialize() {
        if (isInitialized) {
            return
        }
        synchronized(this) {
            if (isInitialized) return
            check(!isInitializing) {
                "Calls to AutoDaggerInitializable.initialize is from an initializer is not allowed"
            }
            isInitializing = true
            var exception: Exception? = null
            for (initializable in initializables.sortedWith(InitializableComparator)) {
                try {
                    initializable.initialize()
                } catch (e: Exception) {
                    if (exception == null) {
                        exception = e
                    } else {
                        exception.addSuppressed(e)
                    }
                }
            }
            exception?.let { throw it }

            isInitialized = true
            isInitializing = false
        }
    }
}

private val InitializableComparator = Comparator { i1, i2 -> i2.priority.compareTo(i1.priority) }

internal val Initializable.priority: Int
    get() = if (this is OrderedInitializable) priority else AutoInitialize.defaultPriority




© 2015 - 2024 Weber Informatics LLC | Privacy Policy