org.eclipse.kapua.app.console.client.device.DeviceConfigComponents.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.kapua.app.console.client.device.DeviceConfigComponents.java

Source

/*******************************************************************************
 * Copyright (c) 2011, 2016 Eurotech and/or its affiliates and others
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Eurotech - initial API and implementation
 *
 *******************************************************************************/
package org.eclipse.kapua.app.console.client.device;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.kapua.app.console.client.messages.ConsoleMessages;
import org.eclipse.kapua.app.console.client.resources.Resources;
import org.eclipse.kapua.app.console.client.util.KapuaLoadListener;
import org.eclipse.kapua.app.console.client.util.FailureHandler;
import org.eclipse.kapua.app.console.client.util.ScaledAbstractImagePrototype;
import org.eclipse.kapua.app.console.shared.model.GwtConfigComponent;
import org.eclipse.kapua.app.console.shared.model.GwtDevice;
import org.eclipse.kapua.app.console.shared.model.GwtSession;
import org.eclipse.kapua.app.console.shared.model.GwtXSRFToken;
import org.eclipse.kapua.app.console.shared.service.GwtDeviceManagementService;
import org.eclipse.kapua.app.console.shared.service.GwtDeviceManagementServiceAsync;
import org.eclipse.kapua.app.console.shared.service.GwtDeviceService;
import org.eclipse.kapua.app.console.shared.service.GwtDeviceServiceAsync;
import org.eclipse.kapua.app.console.shared.service.GwtSecurityTokenService;
import org.eclipse.kapua.app.console.shared.service.GwtSecurityTokenServiceAsync;

import com.extjs.gxt.ui.client.Style.LayoutRegion;
import com.extjs.gxt.ui.client.Style.Scroll;
import com.extjs.gxt.ui.client.data.BaseTreeLoader;
import com.extjs.gxt.ui.client.data.LoadEvent;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.data.ModelIconProvider;
import com.extjs.gxt.ui.client.data.RpcProxy;
import com.extjs.gxt.ui.client.event.BaseEvent;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.MessageBoxEvent;
import com.extjs.gxt.ui.client.event.SelectionEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.store.TreeStore;
import com.extjs.gxt.ui.client.util.IconHelper;
import com.extjs.gxt.ui.client.util.Margins;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.Dialog;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.extjs.gxt.ui.client.widget.MessageBox;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.layout.BorderLayout;
import com.extjs.gxt.ui.client.widget.layout.BorderLayoutData;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.extjs.gxt.ui.client.widget.toolbar.SeparatorToolItem;
import com.extjs.gxt.ui.client.widget.toolbar.ToolBar;
import com.extjs.gxt.ui.client.widget.treepanel.TreePanel;
import com.extjs.gxt.ui.client.widget.treepanel.TreePanelSelectionModel;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AbstractImagePrototype;

public class DeviceConfigComponents extends LayoutContainer {

    private static final ConsoleMessages MSGS = GWT.create(ConsoleMessages.class);

    private final GwtDeviceServiceAsync gwtDeviceService = GWT.create(GwtDeviceService.class);
    private final GwtDeviceManagementServiceAsync gwtDeviceManagementService = GWT
            .create(GwtDeviceManagementService.class);
    private final GwtSecurityTokenServiceAsync gwtXSRFService = GWT.create(GwtSecurityTokenService.class);

    @SuppressWarnings("unused")
    private GwtSession m_currentSession;

    private boolean m_dirty;
    private boolean m_initialized;
    private GwtDevice m_selectedDevice;
    private DeviceTabConfiguration m_tabConfig;

    private ToolBar m_toolBar;

    private Button m_refreshButton;
    private boolean refreshProcess;

    private Button m_apply;
    private Button m_reset;

    private ContentPanel m_configPanel;
    private DeviceConfigPanel m_devConfPanel;
    private BorderLayoutData m_centerData;

    @SuppressWarnings("rawtypes")
    private BaseTreeLoader m_loader;
    private TreeStore<ModelData> m_treeStore;
    private TreePanel<ModelData> m_tree;

    protected boolean resetProcess;

    protected boolean applyProcess;

    public DeviceConfigComponents(GwtSession currentSession, DeviceTabConfiguration tabConfig) {
        m_currentSession = currentSession;
        m_tabConfig = tabConfig;
        m_dirty = false;
        m_initialized = false;
    }

    public void setDevice(GwtDevice selectedDevice) {
        m_dirty = true;
        m_selectedDevice = selectedDevice;
    }

    protected void onRender(Element parent, int index) {
        super.onRender(parent, index);
        setLayout(new FitLayout());
        setBorders(false);

        // init components
        initToolBar();
        initConfigPanel();

        ContentPanel devicesConfigurationPanel = new ContentPanel();
        devicesConfigurationPanel.setBorders(false);
        devicesConfigurationPanel.setBodyBorder(false);
        devicesConfigurationPanel.setHeaderVisible(false);
        devicesConfigurationPanel.setLayout(new FitLayout());
        devicesConfigurationPanel.setScrollMode(Scroll.AUTO);
        devicesConfigurationPanel.setTopComponent(m_toolBar);
        devicesConfigurationPanel.add(m_configPanel);

        add(devicesConfigurationPanel);
        m_initialized = true;
    }

    private void initToolBar() {
        m_toolBar = new ToolBar();
        m_toolBar.setBorders(false);

        //
        // Refresh Button
        m_refreshButton = new Button(MSGS.refreshButton(),
                AbstractImagePrototype.create(Resources.INSTANCE.refresh()), new SelectionListener<ButtonEvent>() {

                    @Override
                    public void componentSelected(ButtonEvent ce) {
                        if (!refreshProcess) {
                            refreshProcess = true;
                            m_refreshButton.setEnabled(false);

                            m_dirty = true;
                            refresh();

                            m_refreshButton.setEnabled(true);
                            refreshProcess = false;
                        }
                    }
                });

        m_refreshButton.setEnabled(true);
        m_toolBar.add(m_refreshButton);
        m_toolBar.add(new SeparatorToolItem());

        m_apply = new Button(MSGS.apply(), AbstractImagePrototype.create(Resources.INSTANCE.accept16()),
                new SelectionListener<ButtonEvent>() {

                    @Override
                    public void componentSelected(ButtonEvent ce) {
                        if (!applyProcess) {
                            applyProcess = true;
                            m_apply.setEnabled(false);

                            apply();

                            m_apply.setEnabled(true);
                            applyProcess = false;
                        }
                    }
                });

        m_reset = new Button(MSGS.reset(), AbstractImagePrototype.create(Resources.INSTANCE.cancel16()),
                new SelectionListener<ButtonEvent>() {

                    @Override
                    public void componentSelected(ButtonEvent ce) {
                        if (!resetProcess) {
                            resetProcess = true;
                            m_reset.setEnabled(false);

                            reset();

                            m_reset.setEnabled(true);
                            resetProcess = false;
                        }
                    }
                });

        m_apply.setEnabled(false);
        m_reset.setEnabled(false);

        m_toolBar.add(m_apply);
        m_toolBar.add(new SeparatorToolItem());
        m_toolBar.add(m_reset);
    }

    @SuppressWarnings("unchecked")
    private void initConfigPanel() {
        m_configPanel = new ContentPanel();
        m_configPanel.setBorders(false);
        m_configPanel.setBodyBorder(false);
        m_configPanel.setHeaderVisible(false);
        m_configPanel.setStyleAttribute("background-color", "white");
        m_configPanel.setScrollMode(Scroll.AUTO);

        BorderLayout borderLayout = new BorderLayout();
        m_configPanel.setLayout(borderLayout);

        // center
        m_centerData = new BorderLayoutData(LayoutRegion.CENTER);
        m_centerData.setMargins(new Margins(0));

        // west
        BorderLayoutData westData = new BorderLayoutData(LayoutRegion.WEST, 200);
        westData.setSplit(true);
        westData.setCollapsible(true);
        westData.setMargins(new Margins(0, 5, 0, 0));

        // loader and store
        RpcProxy<List<GwtConfigComponent>> proxy = new RpcProxy<List<GwtConfigComponent>>() {

            @Override
            protected void load(Object loadConfig, AsyncCallback<List<GwtConfigComponent>> callback) {
                if (m_selectedDevice != null && m_dirty && m_initialized) {
                    if (m_selectedDevice.isOnline()) {
                        m_tree.mask(MSGS.loading());
                        gwtDeviceManagementService.findDeviceConfigurations(m_selectedDevice, callback);
                    } else {
                        List<GwtConfigComponent> comps = new ArrayList<GwtConfigComponent>();
                        GwtConfigComponent comp = new GwtConfigComponent();
                        comp.setId(MSGS.deviceNoDeviceSelected());
                        comp.setName(MSGS.deviceNoComponents());
                        comp.setDescription(MSGS.deviceNoConfigSupported());
                        comps.add(comp);
                        callback.onSuccess(comps);
                    }
                } else {
                    List<GwtConfigComponent> comps = new ArrayList<GwtConfigComponent>();
                    GwtConfigComponent comp = new GwtConfigComponent();
                    comp.setId(MSGS.deviceNoDeviceSelected());
                    comp.setName(MSGS.deviceNoDeviceSelected());
                    comp.setDescription(MSGS.deviceNoDeviceSelected());
                    comps.add(comp);
                    callback.onSuccess(comps);
                }
                m_dirty = false;
            }
        };

        m_loader = new BaseTreeLoader<GwtConfigComponent>(proxy);
        m_loader.addLoadListener(new DataLoadListener());

        m_treeStore = new TreeStore<ModelData>(m_loader);

        m_tree = new TreePanel<ModelData>(m_treeStore);
        m_tree.setWidth(200);
        m_tree.setDisplayProperty("componentName");
        m_tree.setBorders(true);
        m_tree.setAutoSelect(true);
        m_tree.setStyleAttribute("background-color", "white");
        m_configPanel.add(m_tree, westData);

        //
        // Selection Listener for the component
        // make sure the form is not dirty before switching.
        m_tree.getSelectionModel().addListener(Events.BeforeSelect, new Listener<BaseEvent>() {

            @SuppressWarnings("rawtypes")
            @Override
            public void handleEvent(BaseEvent be) {

                final BaseEvent theEvent = be;
                SelectionEvent<ModelData> se = (SelectionEvent<ModelData>) be;

                final GwtConfigComponent componentToSwitchTo = (GwtConfigComponent) se.getModel();
                if (m_devConfPanel != null && m_devConfPanel.isDirty()) {

                    // cancel the event first
                    theEvent.setCancelled(true);

                    // need to reselect the current entry
                    // as the BeforeSelect event cleared it
                    // we need to do this without raising events
                    TreePanelSelectionModel selectionModel = (TreePanelSelectionModel) m_tree.getSelectionModel();
                    selectionModel.setFiresEvents(false);
                    selectionModel.select(false, m_devConfPanel.getConfiguration());
                    selectionModel.setFiresEvents(true);

                    // ask for confirmation before switching
                    MessageBox.confirm(MSGS.confirm(), MSGS.deviceConfigDirty(), new Listener<MessageBoxEvent>() {

                        public void handleEvent(MessageBoxEvent ce) {
                            // if confirmed, delete
                            Dialog dialog = ce.getDialog();
                            if (dialog.yesText.equals(ce.getButtonClicked().getText())) {
                                m_devConfPanel.removeFromParent();
                                m_devConfPanel = null;
                                m_tree.getSelectionModel().select(false, componentToSwitchTo);
                            }
                        }
                    });
                } else {
                    refreshConfigPanel(componentToSwitchTo);

                    // this is needed to select the item in the Tree
                    // Temporarly disable the firing of the selection events
                    // to avoid an infinite loop as BeforeSelect would be invoked again.
                    TreePanelSelectionModel selectionModel = (TreePanelSelectionModel) m_tree.getSelectionModel();
                    selectionModel.setFiresEvents(false);
                    selectionModel.select(false, componentToSwitchTo);

                    // renable firing of the events
                    selectionModel.setFiresEvents(true);
                }
            }
        });

        m_tree.setIconProvider(new ModelIconProvider<ModelData>() {

            public AbstractImagePrototype getIcon(ModelData model) {
                if (model instanceof GwtConfigComponent) {
                    String icon = ((GwtConfigComponent) model).getComponentIcon();
                    if ("CloudService".equals(icon)) {
                        return AbstractImagePrototype.create(Resources.INSTANCE.cloud16());
                    } else if ("ClockService".equals(icon)) {
                        return AbstractImagePrototype.create(Resources.INSTANCE.clock16());
                    } else if ("DataService".equals(icon)) {
                        return AbstractImagePrototype.create(Resources.INSTANCE.databaseConnect());
                    } else if ("DiagnosticsService".equals(icon)) {
                        return AbstractImagePrototype.create(Resources.INSTANCE.diagnostics());
                    } else if ("MqttDataTransport".equals(icon)) {
                        return AbstractImagePrototype.create(Resources.INSTANCE.mqtt());
                    } else if ("PositionService".equals(icon)) {
                        return AbstractImagePrototype.create(Resources.INSTANCE.gps16());
                    } else if ("SslManagerService".equals(icon)) {
                        return AbstractImagePrototype.create(Resources.INSTANCE.lock16());
                    } else if ("WatchdogService".equals(icon)) {
                        return AbstractImagePrototype.create(Resources.INSTANCE.dog16());
                    } else if ("CommandPasswordService".equals(icon)) {
                        return AbstractImagePrototype.create(Resources.INSTANCE.terminal());
                    } else if ("VpnService".equals(icon)) {
                        return AbstractImagePrototype.create(Resources.INSTANCE.vpn());
                    } else if ("ProvisioningService".equals(icon)) {
                        return AbstractImagePrototype.create(Resources.INSTANCE.provisioning16());
                    } else if ("DenaliService".equals(icon)) {
                        // WebConsole: DenaliService
                        return AbstractImagePrototype.create(Resources.INSTANCE.monitorDenali());
                    } else if ("BluetoothService".equals(icon)) {
                        // Bluetooth: BluetoothService
                        return AbstractImagePrototype.create(Resources.INSTANCE.bluetooth());
                    } else if (icon != null && icon.toLowerCase().startsWith("img://")) {
                        // Replace the base fake protocol with the console base URL
                        // that was not available on the server side.
                        icon = icon.replaceFirst("img://", GWT.getHostPageBaseURL());
                        return new ScaledAbstractImagePrototype(IconHelper.createPath(icon, 16, 16));
                    } else {
                        return AbstractImagePrototype.create(Resources.INSTANCE.plugin16());
                    }
                }
                return null;
            }
        });
    }

    // --------------------------------------------------------------------------------------
    //
    // Device Configuration Management
    //
    // --------------------------------------------------------------------------------------

    public void refreshWhenOnline() {
        final int PERIOD_MILLIS = 1000;

        Timer timer = new Timer() {

            private int TIMEOUT_MILLIS = 30000;
            private int countdownMillis = TIMEOUT_MILLIS;

            public void run() {
                if (m_selectedDevice != null) {
                    countdownMillis -= PERIOD_MILLIS;

                    //
                    // Poll the current status of the device until is online again or timeout.
                    gwtDeviceService.findDevice(m_selectedDevice.getScopeId(),
                            m_selectedDevice.getUnescapedClientId(), new AsyncCallback<GwtDevice>() {

                                @Override
                                public void onFailure(Throwable t) {
                                    done();
                                }

                                @Override
                                public void onSuccess(GwtDevice gwtDevice) {
                                    if (countdownMillis <= 0 ||
                                    // Allow the device to disconnect before checking if it's online again.
                                    ((TIMEOUT_MILLIS - countdownMillis) > 5000 && gwtDevice.isOnline())) {
                                        done();
                                    }
                                }

                                private void done() {
                                    cancel();
                                    refresh();
                                    if (m_devConfPanel != null) {
                                        m_devConfPanel.unmask();
                                    }
                                }
                            });
                }
            }
        };
        m_devConfPanel.mask(MSGS.waiting());
        timer.scheduleRepeating(PERIOD_MILLIS);
    }

    public void refresh() {
        if (m_dirty && m_initialized) {

            // clear the tree and disable the toolbar
            m_apply.setEnabled(false);
            m_reset.setEnabled(false);
            m_refreshButton.setEnabled(false);

            m_treeStore.removeAll();

            // clear the panel
            if (m_devConfPanel != null) {
                m_devConfPanel.removeAll();
                m_devConfPanel.removeFromParent();
                m_devConfPanel = null;
                m_configPanel.layout();
            }

            m_loader.load();
        }
    }

    public void refreshConfigPanel(GwtConfigComponent configComponent) {
        m_apply.setEnabled(false);
        m_reset.setEnabled(false);

        if (m_devConfPanel != null) {
            m_devConfPanel.removeFromParent();
        }
        if (configComponent != null) {

            m_devConfPanel = new DeviceConfigPanel(configComponent);
            m_devConfPanel.addListener(Events.Change, new Listener<BaseEvent>() {

                @Override
                public void handleEvent(BaseEvent be) {
                    m_apply.setEnabled(true);
                    m_reset.setEnabled(true);
                }
            });
            m_configPanel.add(m_devConfPanel, m_centerData);
            m_configPanel.layout();
        }
    }

    public void apply() {
        if (!m_devConfPanel.isValid()) {
            MessageBox mb = new MessageBox();
            mb.setIcon(MessageBox.ERROR);
            mb.setMessage(MSGS.deviceConfigError());
            mb.show();
            return;
        }

        // ask for confirmation
        String componentName = m_devConfPanel.getConfiguration().getComponentName();
        String message = MSGS.deviceConfigConfirmation(componentName);
        final boolean isCloudUpdate = "CloudService".equals(componentName);
        if (isCloudUpdate) {
            message = MSGS.deviceCloudConfigConfirmation(componentName);
        }

        MessageBox.confirm(MSGS.confirm(), message, new Listener<MessageBoxEvent>() {

            public void handleEvent(MessageBoxEvent ce) {

                // if confirmed, push the update
                // if confirmed, delete
                Dialog dialog = ce.getDialog();
                if (dialog.yesText.equals(ce.getButtonClicked().getText())) {

                    // mark the whole config panel dirty and for reload
                    m_tabConfig.setDevice(m_selectedDevice);

                    m_devConfPanel.mask(MSGS.applying());
                    m_tree.mask();
                    m_apply.setEnabled(false);
                    m_reset.setEnabled(false);
                    m_refreshButton.setEnabled(false);

                    //
                    // Getting XSRF token
                    gwtXSRFService.generateSecurityToken(new AsyncCallback<GwtXSRFToken>() {

                        @Override
                        public void onFailure(Throwable ex) {
                            FailureHandler.handle(ex);
                        }

                        @Override
                        public void onSuccess(GwtXSRFToken token) {
                            final GwtConfigComponent configComponent = m_devConfPanel.getUpdatedConfiguration();
                            gwtDeviceManagementService.updateComponentConfiguration(token, m_selectedDevice,
                                    configComponent, new AsyncCallback<Void>() {

                                        public void onFailure(Throwable caught) {
                                            FailureHandler.handle(caught);
                                            m_dirty = true;
                                        }

                                        public void onSuccess(Void arg0) {
                                            m_dirty = true;
                                            if (isCloudUpdate) {
                                                refreshWhenOnline();
                                            } else {
                                                refresh();
                                            }
                                        }
                                    });
                        }
                    });

                    // start the configuration update
                }
            }
        });
    }

    public void reset() {
        final GwtConfigComponent comp = (GwtConfigComponent) m_tree.getSelectionModel().getSelectedItem();
        if (m_devConfPanel != null && comp != null && m_devConfPanel.isDirty()) {
            MessageBox.confirm(MSGS.confirm(), MSGS.deviceConfigDirty(), new Listener<MessageBoxEvent>() {

                public void handleEvent(MessageBoxEvent ce) {
                    // if confirmed, delete
                    Dialog dialog = ce.getDialog();
                    if (dialog.yesText.equals(ce.getButtonClicked().getText())) {
                        refreshConfigPanel(comp);
                    }
                }
            });
        }
    }

    // --------------------------------------------------------------------------------------
    //
    // Data Load Listener
    //
    // --------------------------------------------------------------------------------------

    private class DataLoadListener extends KapuaLoadListener {

        public DataLoadListener() {
        }

        public void loaderLoad(LoadEvent le) {
            if (le.exception != null) {
                FailureHandler.handle(le.exception);
            }
            m_tree.unmask();
            m_refreshButton.setEnabled(true);
        }

        public void loaderLoadException(LoadEvent le) {

            if (le.exception != null) {
                FailureHandler.handle(le.exception);
            }

            List<ModelData> comps = new ArrayList<ModelData>();
            GwtConfigComponent comp = new GwtConfigComponent();
            comp.setId(MSGS.deviceNoDeviceSelected());
            comp.setName(MSGS.deviceNoComponents());
            comp.setDescription(MSGS.deviceNoConfigSupported());
            comps.add(comp);
            m_treeStore.removeAll();
            m_treeStore.add(comps, false);

            m_tree.unmask();
        }
    }
}