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

com.github.czyzby.kiwi.util.gdx.asset.lazy.Lazy Maven / Gradle / Ivy

There is a newer version: 1.9.1.9.6
Show newest version
package com.github.czyzby.kiwi.util.gdx.asset.lazy;

import com.badlogic.gdx.utils.Disposable;
import com.github.czyzby.kiwi.util.common.Nullables;
import com.github.czyzby.kiwi.util.gdx.asset.lazy.provider.ObjectProvider;

/** Wraps around an object, allowing to have a final reference to a lazy-initialized object. Adds a very small overhead,
 * without the usual boilerplate that lazy objects require. Should be used for objects that are expensive to create and
 * rarely (or - at least - not always) needed to ensure that they are created only when necessary. Concurrent use might
 * result in multiple provider method calls if a non-concurrent lazy variant is used. Note that this wrapper should not
 * be used for nullable objects - if the wrapped object is null, lazy considers that it was not initiated yet, so make
 * sure that your providers never return null.
 *
 * @author MJ
 * @param  type of wrapped value. */
public class Lazy {
    private ObjectProvider provider;
    private Type object;

    /** Constructs an empty lazy object with no provider. Stored variable has to be set manually. */
    public Lazy() {
        this(null);
    }

    /** @param provider will provide wrapped object on first call. */
    public Lazy(final ObjectProvider provider) {
        this.provider = provider;
    }

    /** @return a new instance of empty provider which can be managed manually.
     * @param  type of wrapped value. */
    public static  Lazy empty() {
        return new Lazy();
    }

    /** @param provider will provide wrapped object on first call.
     * @return a new {@link Lazy}.
     * @param  type of wrapped value. */
    public static  Lazy providedBy(final ObjectProvider provider) {
        return new Lazy(provider);
    }

    /** @param provider will provide wrapped object on first call. Lazy provides synchronization, provider can be not
     *            thread safe.
     * @return a new {@link ConcurrentLazy}.
     * @param  type of wrapped value. */
    public static  ConcurrentLazy concurrentProvidedBy(final ObjectProvider provider) {
        return new ConcurrentLazy(provider);
    }

    /** @param provider will provide wrapped disposable object on first call.
     * @return a new {@link DisposableLazy}.
     * @param  type of wrapped value. */
    public static  DisposableLazy disposableProvidedBy(
            final ObjectProvider provider) {
        return new DisposableLazy(provider);
    }

    /** @param provider will provide wrapped disposable object on first call. Lazy provides synchronization, provider
     *            can be not thread safe.
     * @return a new {@link ConcurrentDisposableLazy}.
     * @param  type of wrapped value. */
    public static  ConcurrentDisposableLazy concurrentDisposableProvidedBy(
            final ObjectProvider provider) {
        return new ConcurrentDisposableLazy(provider);
    }

    /** @return lazy-initiated object instance. Is never null, as long as the provider is properly created. */
    public final Type get() {
        if (object == null) {
            object = getObjectInstance();
            provider = null;
        }
        return object;
    }

    /** @return lazy-initiated object instance or null if not initiated. Will never invoke lazy object creation: this
     *         method avoids the null check and returns the current reference to the wrapped object as-is. */
    public final Type getIfCreated() {
        return object;
    }

    /** @param alternative will be returned if object is not initiated.
     * @return lazy-initiated object instance if it was already created or the passed alternative. Will never invoke
     *         lazy object initiation. */
    public final Type getOrElse(final Type alternative) {
        return object == null ? alternative : object;
    }

    /** Allows to manually set the object, not relying on a provider. Use with care - throws IllegalStateException if
     * variable is already not null. Although discouraged, using of this method can be preferred if extra overhead of
     * the provider is not an option.
     *
     * @param object will be set as wrapped object.
     * @throws IllegalStateException if wrapped object is already present. */
    public void set(final Type object) throws IllegalStateException {
        if (this.object != null) {
            throw new IllegalStateException("Cannot set lazy variable - already initiated.");
        }
        this.object = object;
    }

    /** @return object instance provided by provider. Should be called once, upon object initiation. Cannot return
     *         null. */
    protected Type getObjectInstance() {
        validateProvider();
        return provider.provide();
    }

    /** @throws IllegalStateException if provider is not set. */
    protected void validateProvider() {
        if (provider == null) {
            throw new IllegalStateException(
                    "Variable was not set and there is no provider - unable to retrieve lazy variable.");
        }
    }

    /** @return direct reference to lazy provider. */
    protected ObjectProvider getProvider() {
        return provider;
    }

    /** @return direct reference to lazy object. */
    protected Type getObject() {
        return object;
    }

    /** @return true if object is not null. */
    public boolean isInitialized() {
        return object != null;
    }

    @Override
    public boolean equals(final Object object) {
        return object instanceof Lazy && Nullables.areEqual(this.object, ((Lazy) object).object);
    }

    /** @return 0 if object was not initiated. Wrapped object's hash code otherwise. */
    @Override
    public int hashCode() {
        if (object == null) {
            return 0;
        }
        return object.hashCode();
    }

    @Override
    public String toString() {
        return "Lazy[" + object + "]";
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy