001/*
002 * (C) Copyright 2013 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     vpasquier <vpasquier@nuxeo.com>
018 *     slacoin <slacoin@nuxeo.com>
019 */
020package org.nuxeo.ecm.automation.test;
021
022import java.util.HashMap;
023import java.util.Map;
024
025import com.google.inject.Key;
026import com.google.inject.OutOfScopeException;
027import com.google.inject.Provider;
028import com.google.inject.Scope;
029
030/**
031 * @since 5.7.3
032 */
033public class AutomationScope implements Scope {
034
035    public final static AutomationScope INSTANCE = new AutomationScope();
036
037    protected final ThreadLocal<Map<Key<?>, Object>> values = new ThreadLocal<Map<Key<?>, Object>>() {
038        protected Map<Key<?>, Object> initialValue() {
039            return new HashMap<Key<?>, Object>();
040        };
041    };
042
043    protected AutomationScope() {;
044    }
045
046    public void enter() {
047        values.get();
048    }
049
050    public void exit() {
051        values.remove();
052    }
053
054    @Override
055    public <T> Provider<T> scope(final Key<T> key, final Provider<T> unscoped) {
056        return new Provider<T>() {
057
058            @Override
059            public T get() {
060                Map<Key<?>, Object> scopedMap = getScopedObjectMap(key);
061                @SuppressWarnings("unchecked")
062                T current = (T) scopedMap.get(key);
063                if (current == null && !scopedMap.containsKey(key)) {
064                    current = unscoped.get();
065                    scopedMap.put(key, current);
066                }
067                return current;
068            }
069
070        };
071    }
072
073    private <T> Map<Key<?>, Object> getScopedObjectMap(Key<T> key) {
074        Map<Key<?>, Object> scopedObjects = values.get();
075        if (scopedObjects == null) {
076            throw new OutOfScopeException("Cannot access " + key + " outside of a scoping block");
077        }
078        return scopedObjects;
079    }
080
081}