/*
* 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.displayer.client.widgets;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.enterprise.context.Dependent;
import javax.enterprise.event.Event;
import javax.inject.Inject;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.Widget;
import org.dashbuilder.common.client.error.ClientRuntimeError;
import org.dashbuilder.dataset.DataColumn;
import org.dashbuilder.dataset.DataSet;
import org.dashbuilder.dataset.client.DataSetReadyCallback;
import org.dashbuilder.dataset.sort.SortOrder;
import org.dashbuilder.displayer.ColumnSettings;
import org.dashbuilder.displayer.DisplayerAttributeDef;
import org.dashbuilder.displayer.DisplayerAttributeGroupDef;
import org.dashbuilder.displayer.DisplayerConstraints;
import org.dashbuilder.displayer.DisplayerSettings;
import org.dashbuilder.displayer.Position;
import org.dashbuilder.displayer.client.Displayer;
import org.dashbuilder.displayer.client.DisplayerLocator;
import org.dashbuilder.displayer.client.RendererLibrary;
import org.dashbuilder.displayer.client.RendererManager;
import org.dashbuilder.displayer.client.events.DisplayerSettingsChangedEvent;
import org.uberfire.client.mvp.UberView;
import org.uberfire.ext.properties.editor.model.validators.PropertyFieldValidator;
import static org.dashbuilder.displayer.DisplayerAttributeDef.*;
import static org.dashbuilder.displayer.DisplayerAttributeGroupDef.*;
@Dependent
public class DisplayerSettingsEditor implements IsWidget {
public interface View extends UberView<DisplayerSettingsEditor> {
void clear();
void show();
void dataSetNotFound();
void error(String message);
void addCategory(DisplayerAttributeDef attributeDef);
void addTextProperty(DisplayerAttributeDef attributeDef, String value, PropertyFieldValidator... validators);
void addTextProperty(String propId, String propName, String value, PropertyFieldValidator... validators);
void addBooleanProperty(DisplayerAttributeDef attributeDef, boolean value);
void addColorProperty(DisplayerAttributeDef attributeDef, String color);
void addListProperty(DisplayerAttributeDef attributeDef, List<String> optionList, String selectedValue);
String getColumnNameI18n();
String getColumnExpressionI18n();
String getColumnPatternI18n();
String getPositionLiteralI18n(Position position);
String getIntegerValidationFailedI18n();
String getDoubleValidationFailedI18n();
String getMeterStartI18n();
String getMeterWarningI18n();
String getMeterCriticalI18n();
String getMeterEndI18n();
String getMeterUnknownI18n();
String getMeterValidationHigherI18n(String level);
String getMeterValidationLowerI18n(String level);
String getMeterValidationInvalidI18n();
}
protected View view;
protected DisplayerLocator displayerLocator;
protected RendererManager rendererManager;
protected Displayer displayer;
protected DisplayerSettings displayerSettings;
protected DisplayerConstraints displayerContraints;
private Set<DisplayerAttributeDef> supportedAttributes;
protected Event<DisplayerSettingsChangedEvent> settingsChangedEvent;
public static final String COLUMNS_PREFFIX = "columns.";
@Inject
public DisplayerSettingsEditor(View view,
DisplayerLocator displayerLocator,
RendererManager rendererManager,
Event<DisplayerSettingsChangedEvent> settingsChangedEvent) {
this.view = view;
this.displayerLocator = displayerLocator;
this.rendererManager = rendererManager;
this.settingsChangedEvent = settingsChangedEvent;
view.init(this);
}
@Override
public Widget asWidget() {
return view.asWidget();
}
public DisplayerSettings getDisplayerSettings() {
return displayerSettings;
}
public void init(Displayer displayer) {
try {
this.displayer = displayer;
this.displayerSettings = displayer.getDisplayerSettings();
this.displayerContraints = displayer.getDisplayerConstraints();
this.supportedAttributes = displayerContraints.getSupportedAttributes();
displayer.getDataSetHandler().lookupDataSet(new DataSetReadyCallback() {
public void callback(DataSet dataSet) {
show();
}
public void notFound() {
view.dataSetNotFound();
}
@Override
public boolean onError(final ClientRuntimeError error) {
view.error(error.getMessage());
return false;
}
});
} catch (Exception e) {
view.error(e.toString());
}
}
public boolean isSupported(DisplayerAttributeDef attributeDef) {
return supportedAttributes.contains(attributeDef);
}
public boolean isSupported(DisplayerAttributeGroupDef groupDef) {
if (supportedAttributes.contains(groupDef)) {
for (DisplayerAttributeDef attrDef : groupDef.getChildren()) {
if (attrDef instanceof DisplayerAttributeGroupDef) {
continue;
}
if (supportedAttributes.contains(attrDef)) {
return true;
}
}
}
return false;
}
void show() {
view.clear();
if (isSupported(GENERAL_GROUP)) {
view.addCategory(GENERAL_GROUP);
if (isSupported(TITLE)) {
view.addTextProperty(TITLE, displayerSettings.getTitle());
}
if (isSupported(TITLE_VISIBLE)) {
view.addBooleanProperty(TITLE_VISIBLE, displayerSettings.isTitleVisible());
}
if (isSupported(ALLOW_EXPORT_CSV)) {
view.addBooleanProperty(ALLOW_EXPORT_CSV, displayerSettings.isCSVExportAllowed());
}
if (isSupported(ALLOW_EXPORT_EXCEL)) {
view.addBooleanProperty(ALLOW_EXPORT_EXCEL, displayerSettings.isExcelExportAllowed());
}
}
if (isSupported(RENDERER)) {
view.addCategory(RENDERER);
List<String> optionList = new ArrayList<String>();
for (RendererLibrary option : rendererManager.getRenderersForType(displayerSettings.getType())) {
optionList.add(option.getUUID());
}
if (optionList.size() > 1) {
RendererLibrary renderer = rendererManager.getRendererForDisplayer(displayerSettings);
view.addListProperty(RENDERER, optionList, renderer.getUUID());
}
}
if (isSupported(CHART_GROUP)) {
view.addCategory(CHART_GROUP);
if (isSupported(CHART_WIDTH)) {
view.addTextProperty(CHART_WIDTH, String.valueOf(displayerSettings.getChartWidth()), createLongValidator());
}
if (isSupported(CHART_HEIGHT)) {
view.addTextProperty(CHART_HEIGHT, String.valueOf(displayerSettings.getChartHeight()), createLongValidator());
}
if (isSupported(CHART_BGCOLOR)) {
view.addColorProperty(CHART_BGCOLOR, displayerSettings.getChartBackgroundColor());
}
if (isSupported(CHART_3D)) {
view.addBooleanProperty(CHART_3D, displayerSettings.isChart3D());
}
}
if (isSupported(CHART_MARGIN_GROUP)) {
view.addCategory(CHART_MARGIN_GROUP);
if (isSupported(CHART_MARGIN_TOP)) {
view.addTextProperty(CHART_MARGIN_TOP, String.valueOf(displayerSettings.getChartMarginTop()), createLongValidator());
}
if (isSupported(CHART_MARGIN_BOTTOM)) {
view.addTextProperty(CHART_MARGIN_BOTTOM, String.valueOf(displayerSettings.getChartMarginBottom()), createLongValidator());
}
if (isSupported(CHART_MARGIN_LEFT)) {
view.addTextProperty(CHART_MARGIN_LEFT, String.valueOf(displayerSettings.getChartMarginLeft()), createLongValidator());
}
if (isSupported(CHART_MARGIN_RIGHT)) {
view.addTextProperty(CHART_MARGIN_RIGHT, String.valueOf(displayerSettings.getChartMarginRight()), createLongValidator());
}
}
if (isSupported(CHART_LEGEND_GROUP)) {
view.addCategory(CHART_LEGEND_GROUP);
if (isSupported(CHART_SHOWLEGEND)) {
view.addBooleanProperty(CHART_SHOWLEGEND, displayerSettings.isChartShowLegend());
}
if (isSupported(CHART_LEGENDPOSITION)) {
List<String> optionList = new ArrayList<String>();
for (Position position : Position.values()) {
String positionLabel = view.getPositionLiteralI18n(position);
optionList.add(positionLabel);
}
if (optionList.size() > 1) {
String positionLabel = view.getPositionLiteralI18n(displayerSettings.getChartLegendPosition());
view.addListProperty(CHART_LEGENDPOSITION, optionList, positionLabel);
}
}
}
if (isSupported(XAXIS_GROUP) || isSupported(YAXIS_GROUP)) {
view.addCategory(XAXIS_GROUP);
if (isSupported(XAXIS_SHOWLABELS)) {
view.addBooleanProperty(XAXIS_SHOWLABELS, displayerSettings.isXAxisShowLabels());
}
if (isSupported(XAXIS_TITLE)) {
view.addTextProperty(XAXIS_TITLE, displayerSettings.getXAxisTitle());
}
if (isSupported(YAXIS_SHOWLABELS)) {
view.addBooleanProperty(YAXIS_SHOWLABELS, displayerSettings.isXAxisShowLabels());
}
if (isSupported(YAXIS_TITLE)) {
view.addTextProperty(YAXIS_TITLE, displayerSettings.getYAxisTitle());
}
}
if (isSupported(TABLE_GROUP)) {
view.addCategory(TABLE_GROUP);
if (isSupported(TABLE_PAGESIZE)) {
view.addTextProperty(TABLE_PAGESIZE, String.valueOf(displayerSettings.getTablePageSize()), createLongValidator());
}
if (isSupported(TABLE_WIDTH)) {
view.addTextProperty(TABLE_WIDTH, String.valueOf(displayerSettings.getTableWidth()), createLongValidator());
}
if (isSupported(TABLE_SORTENABLED)) {
view.addBooleanProperty(TABLE_SORTENABLED, displayerSettings.isTableSortEnabled());
}
if (isSupported(TABLE_SORTCOLUMNID)) {
final List<String> optionList = new ArrayList<String>();
DataSet dataSet = displayer.getDataSetHandler().getLastDataSet();
List<DataColumn> dsColumns = dataSet.getColumns();
optionList.add("");
for (DataColumn column : dsColumns) {
optionList.add(column.getId());
}
view.addListProperty(TABLE_SORTCOLUMNID, optionList, displayerSettings.getTableDefaultSortColumnId());
}
if (isSupported(TABLE_SORTORDER)) {
List<String> optionList = new ArrayList<String>();
optionList.add(SortOrder.ASCENDING.toString());
optionList.add(SortOrder.DESCENDING.toString());
view.addListProperty(TABLE_SORTORDER, optionList, displayerSettings.getTableDefaultSortOrder().toString());
}
}
if (isSupported(METER_GROUP)) {
view.addCategory(METER_GROUP);
if (isSupported(METER_START)) {
view.addTextProperty(METER_START, String.valueOf(displayerSettings.getMeterStart()), createMeterValidator(displayerSettings, 0));
}
if (isSupported(METER_WARNING)) {
view.addTextProperty(METER_WARNING, String.valueOf(displayerSettings.getMeterWarning()), createMeterValidator(displayerSettings, 1));
}
if (isSupported(METER_CRITICAL)) {
view.addTextProperty(METER_CRITICAL, String.valueOf(displayerSettings.getMeterCritical()), createMeterValidator(displayerSettings, 2));
}
if (isSupported(METER_END)) {
view.addTextProperty(METER_END, String.valueOf(displayerSettings.getMeterEnd()), createMeterValidator(displayerSettings, 3));
}
}
if (isSupported(FILTER_GROUP)) {
view.addCategory(FILTER_GROUP);
if (isSupported(FILTER_ENABLED)) {
view.addBooleanProperty(FILTER_ENABLED, displayerSettings.isFilterEnabled());
}
if (isSupported(FILTER_SELFAPPLY_ENABLED)) {
view.addBooleanProperty(FILTER_SELFAPPLY_ENABLED, displayerSettings.isFilterSelfApplyEnabled());
}
if (isSupported(FILTER_LISTENING_ENABLED)) {
view.addBooleanProperty(FILTER_LISTENING_ENABLED, displayerSettings.isFilterListeningEnabled());
}
if (isSupported(FILTER_NOTIFICATION_ENABLED)) {
view.addBooleanProperty(FILTER_NOTIFICATION_ENABLED, displayerSettings.isFilterNotificationEnabled());
}
}
if (isSupported(REFRESH_GROUP)) {
view.addCategory(REFRESH_GROUP);
if (isSupported(REFRESH_INTERVAL)) {
view.addTextProperty(REFRESH_INTERVAL, String.valueOf(displayerSettings.getRefreshInterval()), createLongValidator());
}
if (isSupported(REFRESH_STALE_DATA)) {
view.addBooleanProperty(REFRESH_STALE_DATA, displayerSettings.isRefreshStaleData());
}
}
if (isSupported(COLUMNS_GROUP)) {
view.addCategory(COLUMNS_GROUP);
DataSet dataSet = displayer.getDataSetHandler().getLastDataSet();
for (int i=0; i<dataSet.getColumns().size(); i++) {
DataColumn dataColumn = dataSet.getColumnByIndex(i);
ColumnSettings cs = displayerSettings.getColumnSettings(dataColumn);
String fieldSuffix = COLUMNS_PREFFIX + cs.getColumnId() + ".";
String expression = cs.getValueExpression();
String pattern = cs.getValuePattern();
view.addTextProperty(fieldSuffix + "name", "\u25fe " + view.getColumnNameI18n() + (i + 1), cs.getColumnName());
if (expression != null) {
view.addTextProperty(fieldSuffix + "expression", " " + view.getColumnExpressionI18n(), expression);
}
if (pattern != null) {
view.addTextProperty(fieldSuffix + "pattern", " " + view.getColumnPatternI18n(), pattern);
}
/* Non-critical. Disable for the time being.
if (isSupported(COLUMN_EMPTY)) {
String empty = cs.getEmptyTemplate();
view.addTextProperty(fieldSuffix + "empty", " " + view.getColumnEmptyI18n(), empty);
}*/
}
}
view.show();
}
void onAttributeChanged(String attrKey, String attrValue) {
if (attrKey.startsWith(COLUMNS_PREFFIX)) {
String[] strings = attrKey.split("\\.");
if (strings.length == 3) {
String columnId = strings[1];
String setting = strings[2];
if ("name".equals(setting)) {
displayerSettings.setColumnName(columnId, attrValue);
}
else if ("empty".equals(setting)) {
displayerSettings.setColumnEmptyTemplate(columnId, attrValue);
}
else if ("pattern".equals(setting)) {
displayerSettings.setColumnValuePattern(columnId, attrValue);
}
else if ("expression".equals(setting)) {
displayerSettings.setColumnValueExpression(columnId, attrValue);
}
}
} else {
displayerSettings.setDisplayerSetting(attrKey, attrValue);
}
settingsChangedEvent.fire(new DisplayerSettingsChangedEvent(displayerSettings));
}
// Custom property validators
public LongValidator createLongValidator() {
return new LongValidator();
}
public DoubleValidator createDoubleValidator() {
return new DoubleValidator();
}
public MeterValidator createMeterValidator(DisplayerSettings settings, int level) {
return new MeterValidator(settings, level);
}
/**
* Property Editor Validator for integers
*/
public class LongValidator implements PropertyFieldValidator {
@Override
public boolean validate( Object value ) {
try {
Long.parseLong( value.toString() );
return true;
} catch ( Exception e ) {
return false;
}
}
@Override
public String getValidatorErrorMessage() {
return view.getIntegerValidationFailedI18n();
}
}
/**
* Property Editor Validator for doubles
*/
public class DoubleValidator implements PropertyFieldValidator {
@Override
public boolean validate( Object value ) {
try {
Double.parseDouble( value.toString() );
return true;
} catch ( Exception e ) {
return false;
}
}
@Override
public String getValidatorErrorMessage() {
return view.getDoubleValidationFailedI18n();
}
}
/**
* Property Editor Validator for meter intervals
*/
public class MeterValidator extends LongValidator {
private DisplayerSettings displayerSettings;
private int level;
private boolean lowerOk = true;
private boolean upperOk = true;
public MeterValidator(DisplayerSettings displayerSettings, int level) {
this.displayerSettings = displayerSettings;
this.level = level;
}
private long getLevelValue(int level) {
switch (level) {
case 0: return displayerSettings.getMeterStart();
case 1: return displayerSettings.getMeterWarning();
case 2: return displayerSettings.getMeterCritical();
case 3: return displayerSettings.getMeterEnd();
}
return level < 0 ? Long.MIN_VALUE : Long.MAX_VALUE;
}
private String getLevelDescr(int level) {
switch (level) {
case 0: return view.getMeterStartI18n();
case 1: return view.getMeterWarningI18n();
case 2: return view.getMeterCriticalI18n();
case 3: return view.getMeterEndI18n();
}
return view.getMeterUnknownI18n();
}
@Override
public boolean validate( Object value ) {
if (!super.validate(value)) {
return false;
}
long thisLevel = Long.parseLong(value.toString());
long lowerLevel = getLevelValue(level-1);
long upperLevel = getLevelValue(level + 1);
lowerOk = thisLevel >= lowerLevel;
upperOk = thisLevel <= upperLevel;
return lowerOk && upperOk;
}
@Override
public String getValidatorErrorMessage() {
if (!lowerOk) {
return view.getMeterValidationHigherI18n(getLevelDescr(level - 1));
}
if (!upperOk) {
return view.getMeterValidationLowerI18n(getLevelDescr(level + 1));
}
return view.getMeterValidationInvalidI18n();
}
}
}