Hi,

some time ago I wrote my own implementation of custom scope (attached
below) that, in order to cache objects, returns a Provider that keeps
its cached instance (like com.google.inject.Scopes.SINGLETON).

Today, looking at the wiki page I saw that the suggested
implementation of custom scope maintain its own map for caching
instances. Is this map needed? is my implementation broken?

Thanks,
Davide


/**
 * Simple implementation of Guice scope, that admit a single active
scope a time
 * and identify the lifespan of a scope with an object of type S.
 */
public class SimpleScope<S> implements Scope {

    /**
     * A listener for the scope event [EMAIL PROTECTED] SimpleScope#end()}
     */
    public interface Listener {
        void scopeBegin(Object scopeId);
        void scopeEnd();
    }

    private S scopeId;
    private List<Listener> listeners;

    private final Provider<S> SCOPE_ID_PROVIDER = new Provider<S>() {
        public S get() {
            if (scopeId == null)
                throw new IllegalStateException("In "+SimpleScope.this+" 
requested
value when inactive");
            return scopeId;
        }
    };

    protected <T> SimpleScope(SimpleScope<T> parentScope) {
        listeners = new ArrayList<Listener>();
        if (parentScope != null) {
            final Listener parentListener = new Listener() {
                public void scopeEnd() {
                    if (scopeId != null)
                        end();
                }
                public void scopeBegin(Object x) {}
            };
            parentScope.registerListener( parentListener );
        }
    }

    protected SimpleScope() {
        this(null);
    }

    public void registerListener(Listener listener) {
        listeners.add(listener);
    }

    public Provider<S> getActiveProvider() {
        return SCOPE_ID_PROVIDER;
    }

    public void begin(S scopeId) {
        if (scopeId == null)
            throw new NullPointerException("In "+this+" null scope
identifier");
        if (this.scopeId != null)
            throw new IllegalStateException("In "+this+", attempted begin
("+scopeId+") when already active");
        this.scopeId = scopeId;
        for (Listener observer : listeners)
            observer.scopeBegin(scopeId);
    }

    public <T> Provider<T> scope(Key<T> key, Provider<T> creator) {
        SimpleScopeProvider<T> cachingProvider = new SimpleScopeProvider<T>
(creator);
        listeners.add(cachingProvider);
        return cachingProvider;
    }

    public void end() {
        if (this.scopeId == null)
            throw new IllegalStateException("In "+this+", attempted end()
when inactive");
        for (Listener observer : listeners)
            observer.scopeEnd();
        scopeId = null;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder(getClass().getName());
        if (scopeId != null)
            sb.append('(').append(scopeId).append(')');
        return sb.toString();
    }
}

/**
 * Caching provider used in SimpleScope
 * @author davide
 */
class SimpleScopeProvider<T> implements Provider<T>,
SimpleScope.Listener {

    private final Provider<T> creator;
    private volatile T instance;

    public SimpleScopeProvider(Provider<T> creator) {
        this.creator = creator;
    }

    public T get() {
        if (instance == null) {
            // see com.google.inject.Scopes.SINGLETON
            synchronized (Injector.class) {
                if (instance == null) {
                    instance = creator.get();
                }
            }
        }
        return instance;
    }

    public void scopeBegin(Object scopeId) {
        T i = instance;
        if (i instanceof SimpleScope.Listener)
            ((SimpleScope.Listener) i).scopeBegin(scopeId);
    }

    public void scopeEnd() {
        // TODO check if any race condition may occur
        T i = instance;
        if (i instanceof SimpleScope.Listener)
            ((SimpleScope.Listener) i).scopeEnd();
        instance = null;

    }

    public String toString() {
        return creator.toString();
    }
}

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"google-guice" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/google-guice?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to