/* * Copyright 2014 Red Hat, Inc. and/or its affiliates. * * 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 org.dashbuilder.client.widgets.dataset.editor; import com.google.gwt.editor.client.EditorDelegate; import com.google.gwt.safehtml.shared.SafeHtml; import com.google.gwt.safehtml.shared.SafeHtmlBuilder; import com.google.gwt.user.client.ui.IsWidget; import com.google.gwt.user.client.ui.Widget; import org.dashbuilder.client.widgets.common.LoadingBox; import org.dashbuilder.client.widgets.dataset.editor.attributes.*; import org.dashbuilder.client.widgets.dataset.event.ColumnsChangedEvent; import org.dashbuilder.client.widgets.dataset.event.ErrorEvent; import org.dashbuilder.client.widgets.dataset.event.FilterChangedEvent; import org.dashbuilder.client.widgets.dataset.event.TabChangedEvent; import org.dashbuilder.client.widgets.resources.i18n.DataSetEditorConstants; import org.dashbuilder.common.client.error.ClientRuntimeError; import org.dashbuilder.dataprovider.DataSetProviderType; import org.dashbuilder.dataset.DataSet; import org.dashbuilder.dataset.client.DataSetClientServices; import org.dashbuilder.dataset.client.editor.DataSetDefEditor; import org.dashbuilder.dataset.def.DataColumnDef; import org.dashbuilder.dataset.def.DataSetDef; import org.dashbuilder.dataset.filter.DataSetFilter; import org.dashbuilder.dataset.group.DataSetGroup; import org.dashbuilder.displayer.client.Displayer; import org.dashbuilder.displayer.client.DisplayerListener; import org.uberfire.client.mvp.UberView; import org.uberfire.mvp.Command; import javax.enterprise.event.Event; import javax.enterprise.event.Observes; import javax.inject.Inject; import java.util.List; import static org.dashbuilder.dataprovider.DataSetProviderType.*; import static org.uberfire.commons.validation.PortablePreconditions.checkNotNull; /** * <p>Data Set Editor presenter.</p> * * @since 0.4.0 */ public abstract class DataSetEditor<T extends DataSetDef> implements IsWidget, DataSetDefEditor<T> { public static final String TAB_CONFIGURATION = "configuration"; public static final String TAB_PREVIEW = "preview"; public static final String TAB_ADVANCED = "advanced"; public interface View extends UberView<DataSetEditor> { /** * <p>Specify the views to use for each sub-editor before calling <code>initWidget</code>.</p> */ void initWidgets(DataSetDefBasicAttributesEditor.View basicAttributesEditorView, IsWidget providerAttributesEditorView, DataSetDefColumnsFilterEditor.View columnsAndFilterEditorView, DataSetDefPreviewTable.View previewTableView, DataSetDefCacheAttributesEditorView backendCacheAttributesEditorView, DataSetDefCacheAttributesEditorView clientCacheAttributesEditorView, DataSetDefRefreshAttributesEditor.View refreshEditorView); void setConfigurationTabTitle(String title); void showConfigurationTab(); void addConfigurationTabItemClickHandler(final Command command); void showPreviewTab(); void addPreviewTabItemClickHandler(final Command command); void showAdvancedTab(); void addAdvancedTabItemClickHandler(final Command command); void openColumnsFilterPanel(String title); void closeColumnsFilterPanel(String title); void showErrorNotification(final SafeHtml text); void clearErrorNotification(); } protected DataSetDefBasicAttributesEditor basicAttributesEditor; protected IsWidget providerAttributesEditorView; protected DataSetDefColumnsFilterEditor columnsAndFilterEditor; protected DataSetDefPreviewTable previewTable; protected DataSetDefBackendCacheAttributesEditor backendCacheAttributesEditor; protected DataSetDefClientCacheAttributesEditor clientCacheAttributesEditor; private DataSetDefRefreshAttributesEditor refreshEditor; protected DataSetClientServices clientServices; protected LoadingBox loadingBox; protected Event<ErrorEvent> errorEvent; protected Event<TabChangedEvent> tabChangedEvent; /* The Data Set Editor view. */ public View view; protected DataSetDef dataSetDef; protected Command afterPreviewCommand; @Inject public DataSetEditor(final DataSetDefBasicAttributesEditor basicAttributesEditor, final IsWidget providerAttributesEditorView, final DataSetDefColumnsFilterEditor columnsAndFilterEditor, final DataSetDefPreviewTable previewTable, final DataSetDefBackendCacheAttributesEditor backendCacheAttributesEditor, final DataSetDefClientCacheAttributesEditor clientCacheAttributesEditor, final DataSetDefRefreshAttributesEditor refreshEditor, final DataSetClientServices clientServices, final LoadingBox loadingBox, final Event<ErrorEvent> errorEvent, final Event<TabChangedEvent> tabChangedEvent, final View view) { this.basicAttributesEditor = basicAttributesEditor; this.providerAttributesEditorView = providerAttributesEditorView; this.columnsAndFilterEditor = columnsAndFilterEditor; this.previewTable = previewTable; this.backendCacheAttributesEditor = backendCacheAttributesEditor; this.clientCacheAttributesEditor = clientCacheAttributesEditor; this.refreshEditor = refreshEditor; this.clientServices = clientServices; this.loadingBox = loadingBox; this.errorEvent = errorEvent; this.tabChangedEvent = tabChangedEvent; this.view = view; } public void init() { view.init(this); view.initWidgets(basicAttributesEditor.view, providerAttributesEditorView, columnsAndFilterEditor.view, previewTable.view, backendCacheAttributesEditor.view, clientCacheAttributesEditor.view, refreshEditor.view); view.addConfigurationTabItemClickHandler(configurationTabItemClickHandler); view.addPreviewTabItemClickHandler(previewTabItemClickHandler); view.addAdvancedTabItemClickHandler(advancedTabItemClickHandler); columnsAndFilterEditor.setMaxHeight("400px"); backendCacheAttributesEditor.setRange(200d, 10000d); clientCacheAttributesEditor.setRange(00d, 4096d); } /************************************************************* ** PUBLIC EDITOR METHODS ** *************************************************************/ @Override public Widget asWidget() { return view.asWidget(); } public void showConfigurationTab() { afterPreviewCommand = new Command() { @Override public void execute() { view.showConfigurationTab(); } }; } public void showPreviewTab() { afterPreviewCommand = new Command() { @Override public void execute() { view.showPreviewTab(); } }; } public void showAdvancedTab() { afterPreviewCommand = new Command() { @Override public void execute() { view.showAdvancedTab(); } }; } /************************************************************* ** GWT EDITOR CONTRACT METHODS ** *************************************************************/ @Override public void setAcceptableValues(final List<DataColumnDef> acceptableValues) { columnsAndFilterEditor.setAcceptableValues(acceptableValues); } @Override public void flush() { } @Override public void onPropertyChange(final String... paths) { } @Override public void setValue(final T value) { this.dataSetDef = value; // Check specific provider type constraints. final DataSetProviderType type = value.getProvider() != null ? value.getProvider() : null; final String typeTitle = getTypeTitle(type); view.setConfigurationTabTitle(new StringBuffer(typeTitle).append(" ") .append(DataSetEditorConstants.INSTANCE.tab_configguration()).toString()); final boolean isBean = type != null && DataSetProviderType.BEAN.equals(type); if (isBean) { // Bean data sets do not support backend cache, its used by its own nature... backendCacheAttributesEditor = null; } // Load the preview table and update filter editor when having the resulting data set. doPreview(true); } @Override public void setDelegate(final EditorDelegate<T> delegate) { // No delegation required. } @Override public org.dashbuilder.dataset.client.editor.DataSetDefBasicAttributesEditor basicAttributesEditor() { return basicAttributesEditor; } @Override public org.dashbuilder.dataset.client.editor.DataSetDefColumnsFilterEditor columnsAndFilterEditor() { return columnsAndFilterEditor; } @Override public DataSetDefBackendCacheAttributesEditor backendCacheEditor() { return backendCacheAttributesEditor; } @Override public org.dashbuilder.dataset.client.editor.DataSetDefClientCacheAttributesEditor clientCacheEditor() { return clientCacheAttributesEditor; } @Override public org.dashbuilder.dataset.client.editor.DataSetDefRefreshAttributesEditor refreshEditor() { return refreshEditor; } /************************************************************* ** VIEW CALLBACK METHODS ** *************************************************************/ void onOpenColumnsFilterPanel() { view.openColumnsFilterPanel(DataSetEditorConstants.INSTANCE.hideColumnsAndFilter()); } void onCloseColumnsFilterPanel() { view.closeColumnsFilterPanel(DataSetEditorConstants.INSTANCE.showColumnsAndFilter()); } /************************************************************* ** PRIVATE EDITOR METHODS ** *************************************************************/ protected void doPreview(final boolean isUpdateFilter) { loadingBox.show(); previewTable.show(dataSetDef, dataSetDef.getColumns(), new DataSetEditorListener(isUpdateFilter)); } protected void afterPreview(final DataSet dataSet, final boolean isUpdateFilter) { view.clearErrorNotification(); if (isUpdateFilter) { columnsAndFilterEditor.dataSetFilter().init(dataSet.getMetadata()); } if (afterPreviewCommand != null) { afterPreviewCommand.execute(); afterPreviewCommand = null; } loadingBox.hide(); } private class DataSetEditorListener implements DisplayerListener { private boolean isUpdateFilter; public DataSetEditorListener(final boolean isUpdateFilter) { this.isUpdateFilter = isUpdateFilter; } @Override public void onDataLookup(final Displayer displayer) { } @Override public void onDraw(final Displayer displayer) { final DataSet dataSet = displayer.getDataSetHandler().getLastDataSet(); afterPreview(dataSet, isUpdateFilter); } @Override public void onRedraw(final Displayer displayer) { final DataSet dataSet = displayer.getDataSetHandler().getLastDataSet(); afterPreview(dataSet, isUpdateFilter); } @Override public void onClose(final Displayer displayer) { loadingBox.hide(); } @Override public void onFilterEnabled(final Displayer displayer, final DataSetGroup groupOp) { } @Override public void onFilterEnabled(final Displayer displayer, final DataSetFilter filter) { } @Override public void onFilterReset(final Displayer displayer, final List<DataSetGroup> groupOps) { } @Override public void onFilterReset(final Displayer displayer, final DataSetFilter filter) { } @Override public void onError(final Displayer displayer, final ClientRuntimeError error) { showError(error); } } protected void showError(final ClientRuntimeError error) { loadingBox.hide(); final String message = error.getCause() != null ? error.getCause() : error.getMessage(); view.showErrorNotification(new SafeHtmlBuilder().appendEscaped(message).toSafeHtml()); errorEvent.fire(new ErrorEvent(this, error)); if (afterPreviewCommand != null) { this.afterPreviewCommand.execute(); } } private String getTypeTitle(final DataSetProviderType type) { if (BEAN.equals(type)) { return DataSetEditorConstants.INSTANCE.bean(); } if (CSV.equals(type)) { return DataSetEditorConstants.INSTANCE.csv(); } if (SQL.equals(type)) { return DataSetEditorConstants.INSTANCE.sql(); } if (ELASTICSEARCH.equals(type)) { return DataSetEditorConstants.INSTANCE.elasticSearch(); } return ""; } protected final Command configurationTabItemClickHandler = new Command() { @Override public void execute() { tabChangedEvent.fire(new TabChangedEvent(DataSetEditor.this, TAB_CONFIGURATION)); } }; protected final Command previewTabItemClickHandler = new Command() { @Override public void execute() { tabChangedEvent.fire(new TabChangedEvent(DataSetEditor.this, TAB_PREVIEW)); } }; protected final Command advancedTabItemClickHandler = new Command() { @Override public void execute() { tabChangedEvent.fire(new TabChangedEvent(DataSetEditor.this, TAB_ADVANCED)); } }; void onColumnsChangedEvent(@Observes ColumnsChangedEvent columnsChangedEvent) { checkNotNull("columnsChangedEvent", columnsChangedEvent); if (columnsChangedEvent.getContext().equals(columnsAndFilterEditor.columnListEditor().columns())) { final List<DataColumnDef> cols = columnsChangedEvent.getColumns(); dataSetDef.setColumns(cols); doPreview(true); } } void onFilterChangedEvent(@Observes FilterChangedEvent filterChangedEvent) { checkNotNull("filterChangedEvent", filterChangedEvent); if (filterChangedEvent.getContext().equals(columnsAndFilterEditor.dataSetFilter())) { final DataSetFilter f = filterChangedEvent.getFilter(); dataSetDef.setDataSetFilter(f); // Do not update filter, as the component status has been already updated by the user interaction. doPreview(false); } } }