/* * * * Copyright (c) 2016. David Sowerby * * * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with * * the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * * * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * * specific language governing permissions and limitations under the License. * */ package uk.q3c.krail.core.guice.uiscope; import com.google.common.collect.ImmutableList; import com.google.inject.Key; import com.google.inject.Provider; import com.google.inject.Scope; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import uk.q3c.krail.core.ui.ScopedUI; import java.util.HashMap; import java.util.Map; import java.util.TreeMap; /** * Provides a Guice scope based on a Vaadin UI, generally equivalent to a browser tab * * @author Will Temperley 2014 * @author David Sowerby 2013 */ public class UIScope implements Scope { private static Logger log = LoggerFactory.getLogger(UIScope.class); private static volatile UIScope current; private final Map<UIKey, Map<Key<?>, Object>> cache = new TreeMap<UIKey, Map<Key<?>, Object>>(); public UIScope() { super(); log.debug("creating UIScope {}", this); } public static UIScope getCurrent() { // double-checked locking with volatile UIScope scope = current; if (scope == null) { synchronized (UIScope.class) { scope = current; if (scope == null) { current = new UIScope(); scope = current; } } } return scope; } Map<Key<?>, Object> getScopedObjectMap(UIKey uiKey) { // return an existing cache instance if (cache.containsKey(uiKey)) { Map<Key<?>, Object> scopedObjects = cache.get(uiKey); log.debug("scope cache retrieved for UI key: {}", uiKey); return scopedObjects; } else { return createCacheEntry(uiKey); } } private Map<Key<?>, Object> createCacheEntry(UIKey uiKey) { Map<Key<?>, Object> uiEntry = new HashMap<Key<?>, Object>(); cache.put(uiKey, uiEntry); log.debug("created a scope cache for UIScope with key: {}", uiKey); return uiEntry; } public void startScope(UIKey uiKey) { if (!cacheHasEntryFor(uiKey)) { createCacheEntry(uiKey); } } public boolean cacheHasEntryFor(UIKey uiKey) { return cache.containsKey(uiKey); } public boolean cacheHasEntryFor(ScopedUI ui) { return cacheHasEntryFor(ui.getInstanceKey()); } public void releaseScope(UIKey uiKey) { cache.remove(uiKey); } /** * Removes all entries in the cache */ public void flush() { cache.clear(); } @Override public <T> Provider<T> scope(Key<T> key, Provider<T> unscoped) { return new UIScopeProvider<T>(this, key, unscoped); } public ImmutableList<UIKey> scopeKeys() { return ImmutableList.copyOf(cache.keySet()); } public boolean containsInstance(UIKey uiKey, Object containedInstance) { return cache.get(uiKey) .containsValue(containedInstance); } }