uk.q3c.krail.core.ui.ScopedUIProvider.java Source code

Java tutorial

Introduction

Here is the source code for uk.q3c.krail.core.ui.ScopedUIProvider.java

Source

/*
 * Copyright (c) 2015. 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.ui;

import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Provider;
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 uk.q3c.krail.core.guice.uiscope.UIKey;
import uk.q3c.krail.core.guice.uiscope.UIKeyProvider;
import uk.q3c.krail.core.guice.uiscope.UIScope;
import uk.q3c.krail.core.guice.uiscope.UIScoped;

import java.util.Map;

/**
 * A Vaadin UI provider which supports the use of Guice scoped UI (see {@link UIScoped}). If you do not need UIScope,
 * then just extend from UIProvider directly
 * <p>
 * Subclasses should implement getUIClass(UIClassSelectionEvent event) to provide logic for selecting the UI class.
 *
 * @author David Sowerby, Will Temperley
 */
public class ScopedUIProvider extends UIProvider implements Provider<ScopedUI> {
    private static Logger log = LoggerFactory.getLogger(ScopedUIProvider.class);
    protected UIKeyProvider uiKeyProvider;
    protected Injector injector;
    private Map<String, Class<? extends ScopedUI>> uiMapBinder;

    @Inject
    protected void init(Injector injector, UIKeyProvider uiKeyProvider,
            Map<String, Class<? extends ScopedUI>> uiMapBinder) {
        this.injector = injector;
        this.uiKeyProvider = uiKeyProvider;
        this.uiMapBinder = uiMapBinder;
    }

    /**
     * Default implementation assumes that only one ScopedUI implementation is used in the application, and it is held in {@link #uiMapBinder}.  If more than
     * entry is present in {@link #uiMapBinder}, the selection is indeterminate, and a warning is logged.
     * <p>
     * Override this method to provide logic for selecting from multiple UIs, then change the binging for ScopedUIProvider in a sub-class of {@link
     * DefaultUIModule}
     *
     * @param event
     *         the event which triggers the selection of a UI
     *
     * @return the class of the selected UI;  in this implementation, this is the only or first selected from {@link #uiMapBinder}
     */
    @Override
    public Class<? extends UI> getUIClass(UIClassSelectionEvent event) {
        if (uiMapBinder.size() == 0) {
            throw new UIProviderException("At least one UI must be defined in the UIModule, uiBinder");
        }
        if (uiMapBinder.size() > 1) {
            log.warn("More than one UI class has been defined, but there is o logic to determine which to use.");
        }
        return uiMapBinder.get(uiMapBinder.keySet().iterator().next());
    }

    @Override
    public UI createInstance(UICreateEvent event) {
        Class<? extends UI> uiClass = event.getUIClass();
        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);

        log.debug("Returning instance of {} with key {}", uiClass.getName(), uiKey);
        return ui;
    }

    @Override
    public ScopedUI get() {
        return (ScopedUI) UI.getCurrent();
    }
}