Java tutorial
/* * Copyright (C) 2013 the original author or authors. * See the notice.md file distributed with this work for additional * information regarding copyright ownership. * * 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 com.google.code.vaadin.application.ui; import com.google.code.vaadin.application.MVPApplicationInitParameters; import com.google.code.vaadin.application.uiscope.UIKey; import com.google.code.vaadin.application.uiscope.UIScope; import com.google.code.vaadin.components.eventhandling.configuration.EventBusBinder; import com.google.code.vaadin.internal.eventhandling.AbstractEventBusModule; import com.google.code.vaadin.internal.eventhandling.sharedmodel.SharedEventBusSubscribersRegistry; import com.google.code.vaadin.internal.uiscope.UIKeyProvider; import com.google.code.vaadin.mvp.eventhandling.EventBus; import com.google.code.vaadin.mvp.eventhandling.EventBusTypes; import com.google.common.base.Preconditions; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Key; import com.vaadin.server.ClientConnector; import com.vaadin.server.UIClassSelectionEvent; import com.vaadin.server.UICreateEvent; import com.vaadin.server.UIProvider; import com.vaadin.ui.UI; import com.vaadin.util.CurrentInstance; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.inject.Named; import static com.vaadin.server.ClientConnector.DetachListener; /** * A Vaadin UI provider adapted to Guice-Vaadin-MVP specifics. * It always returns UI class specified in webapp descriptor with {@link MVPApplicationInitParameters#P_APPLICATION_UI_CLASS} * context parameter. * * @author Alexey Krylov * @since 08.02.13 */ public class ScopedUIProvider extends UIProvider { /*===========================================[ STATIC VARIABLES ]=============*/ private static final long serialVersionUID = -5773777009877153344L; /*===========================================[ INSTANCE VARIABLES ]====!=======*/ protected Logger logger; protected UIKeyProvider uiKeyProvider; protected Injector injector; protected Class uiClass; protected EventBusBinder eventBusBinder; /*===========================================[ CONSTRUCTORS ]=================*/ @Inject protected void init(Injector injector, @Named(MVPApplicationInitParameters.P_APPLICATION_UI_CLASS) Class uiClass, UIKeyProvider uiKeyProvider, EventBusBinder eventBusBinder) { Preconditions.checkArgument(ScopedUI.class.isAssignableFrom(uiClass), String.format("ERROR: %s is not subclass of ScopedUI", uiClass.getName())); logger = LoggerFactory.getLogger(getClass()); this.injector = injector; this.uiClass = uiClass; this.uiKeyProvider = uiKeyProvider; this.eventBusBinder = eventBusBinder; } /*===========================================[ CLASS METHODS ]================*/ @Override public UI createInstance(UICreateEvent event) { return createInstance(event.getUIClass()); } @Override public Class<? extends UI> getUIClass(UIClassSelectionEvent event) { return uiClass; } public UI createInstance(Class<? extends UI> uiClass) { Preconditions.checkArgument(ScopedUI.class.isAssignableFrom(uiClass), "ERROR: Invalid configuration - using ScopedUIProvider to instantiate no ScopedUI subclass"); UIKey uiKey = uiKeyProvider.get(); // hold the key while UI is created CurrentInstance.set(UIKey.class, uiKey); // and set up the scope UIScope scope = UIScope.getCurrent(); scope.startScope(uiKey); // create the UI ScopedUI ui = (ScopedUI) injector.getInstance(uiClass); ui.setInstanceKey(uiKey); ui.setScope(scope); ui.addDetachListener(createScopedUIDetachListener(uiClass, uiKey)); logger.debug(String.format("Returning instance of [%s] with key [%s]", uiClass.getName(), uiKey)); return ui; } protected DetachListener createScopedUIDetachListener(final Class<? extends UI> uiClass, final UIKey uiKey) { return new DetachListener() { private static final long serialVersionUID = -3087386509047842913L; @Override public void detach(ClientConnector.DetachEvent event) { logger.debug(String.format("Detaching [%s] with key [%s]", uiClass.getName(), uiKey)); // If Shared Model EventBus is present if (eventBusBinder.getBinding(EventBusTypes.SHARED_MODEL) != null) { SharedEventBusSubscribersRegistry subscribersRegistry = injector .getInstance(SharedEventBusSubscribersRegistry.class); Iterable<Object> uiScopedSubscribers = subscribersRegistry.removeAndGetSubscribers(uiKey); EventBus sharedEventBus = injector.getInstance(Key.get(EventBus.class, AbstractEventBusModule.eventBusType(EventBusTypes.SHARED_MODEL))); // Unsubscribe all non-singletons (UIScoped, nonscoped, etc) from SharedEventBus for (Object subscriber : uiScopedSubscribers) { sharedEventBus.unsubscribe(subscriber); } } logger.info(String.format("Detached [%s] with key [%s]", uiClass.getName(), uiKey)); } }; } }