bug4789: compilable but entirely untested major refactoring of data mining report parameters

This commit is contained in:
Axel Uhl committed 2023-02-10 17:37:26 +01:00
1 parent 4edb8ce912
commit a94dbadc0d
25 files changed
+376 -189

No files matched your search

@@ -33,7 +33,9 @@ import com.sap.sailing.gwt.ui.client.AbstractSailingReadEntryPoint;
import com.sap.sailing.gwt.ui.datamining.presentation.TabbedSailingResultsPresenter;
import com.sap.sailing.gwt.ui.shared.settings.SailingSettingsConstants;
import com.sap.sailing.landscape.common.RemoteServiceMappingConstants;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.datamining.shared.DataMiningSession;
import com.sap.sse.datamining.shared.data.ReportParameterToDimensionFilterBindings;
import com.sap.sse.datamining.shared.dto.DataMiningReportDTO;
import com.sap.sse.datamining.shared.dto.FilterDimensionParameter;
import com.sap.sse.datamining.shared.dto.StatisticQueryDefinitionDTO;
@@ -150,7 +152,9 @@ import com.sap.sse.security.ui.client.premium.PaywallResolver;
* through which the parameter was edited will be run. The query currently shown in the editor will run first, followed
* in the background by those dependent "to also run" queries whose results then update their respective result
* presenter tab in the background such that when the user switches to those tabs then the query will either still be
* running or the new results will be shown already.
* running or the new results will be shown already. The handling of the "to also run" flag could be combined with a
* new setting that lets the user choose how to deal with the other queries affected (run immediately, run in background,
* run when panel / tab is selected, ...).
* <p>
*
* When switching to a result presenter tab that has remembered a query that is then
@@ -220,7 +224,25 @@ public class DataMiningEntryPoint extends AbstractSailingReadEntryPoint implemen
private final DataMiningWriteServiceAsync dataMiningWriteService = GWT.create(DataMiningWriteService.class);
private DataMiningSession session;
/**
* The editor for queries of type {@link StatisticQueryDefinitionDTO}. The editor can be
* {@link QueryDefinitionProvider#applyQueryDefinition(StatisticQueryDefinitionDTO) filled} from
* an existing query which is used by this entry point whenever the composite {@link #resultsPresenter}
* switches tabs, so that the query editor shows the query that pertains to the tab selected.
* The editor, however, does not keep a live mutable copy of a query during the editing process
* but creates a new one in its {@link QueryDefinitionProvider#getQueryDefinition()} method which
* is then submitted for execution or storage and is then used to update the {@link #currentReport}
* consistently with the {@link #resultsPresenter} so that the queries of the composite result
* presenter correspond to the {@link DataMiningReportDTO#getQueryDefinitions() queries} managed
* in the current report.
*/
private QueryDefinitionProviderWithControls queryDefinitionProvider;
/**
* Manages multiple queries and their results or error states. The user can switch between them,
* and this entry point acts as a change listener in order to synchronize the {@link #currentReport}
* with the queries from this result presenter.
*/
private CompositeResultsPresenter<?> resultsPresenter;
/**
@@ -274,23 +296,33 @@ public class DataMiningEntryPoint extends AbstractSailingReadEntryPoint implemen
resultsPresenter = new TabbedSailingResultsPresenter(/* parent */ null, /* context */ null,
/* drillDownCallback */ groupKey -> {
queryDefinitionProvider.drillDown(groupKey, () -> {
queryRunner.run(queryDefinitionProvider.getQueryDefinition());
final Pair<ModifiableStatisticQueryDefinitionDTO, ReportParameterToDimensionFilterBindings> queryDefinitionAndReportParameterBindings =
queryDefinitionProvider.getQueryDefinitionAndReportParameterBinding();
queryRunner.run(queryDefinitionAndReportParameterBindings.getA(), queryDefinitionAndReportParameterBindings.getB());
});
}, getStringMessages());
// when switching to a different result presenter tab, that tab's query shall be loaded into the query editor:
resultsPresenter.addCurrentPresenterChangedListener(presenterId -> {
StatisticQueryDefinitionDTO queryDefinition = resultsPresenter.getQueryDefinition(presenterId);
if (queryDefinition != null) {
queryDefinitionProvider.applyQueryDefinition(queryDefinition);
}
});
// removing a tab from the result presenter shall remove its query from the current report
resultsPresenter.addPresenterRemovedListener((String presenterId, int presenterIndex, StatisticQueryDefinitionDTO queryDefinition) -> {
currentReport.removeQueryDefinition(queryDefinition);
if (queryDefinition != null) {
currentReport.removeQueryDefinition(queryDefinition);
}
});
queryDefinitionProvider = new QueryDefinitionProviderWithControls(null, null, session,
dataMiningService, DataMiningEntryPoint.this, settingsControl, settingsManager,
queryDefinition -> queryRunner.run(queryDefinition));
queryRunner = new SimpleQueryRunner(null, null, session, dataMiningService, DataMiningEntryPoint.this,
queryDefinitionProvider, resultsPresenter);
dataMiningService, /* report provider */ DataMiningEntryPoint.this,
/* error reporter */ DataMiningEntryPoint.this, settingsControl, settingsManager,
queryDefinitionAndReportParameterBindings -> queryRunner.run(
queryDefinitionAndReportParameterBindings.getA(),
queryDefinitionAndReportParameterBindings.getB()));
queryRunner = new SimpleQueryRunner(null, null, session,
dataMiningService, DataMiningEntryPoint.this,
queryDefinitionProvider, resultsPresenter, /* reportProvider */ DataMiningEntryPoint.this);
queryDefinitionProvider.addControl(queryRunner.getEntryWidget());
if (getUserService().hasServerPermission(ServerActions.DATA_MINING)) {
StoredDataMiningQueryDataProvider queryProvider = new StoredDataMiningQueryDataProvider(
@@ -298,7 +330,7 @@ public class DataMiningEntryPoint extends AbstractSailingReadEntryPoint implemen
queryDefinitionProvider.addControl(new StoredDataMiningQueryPanel(queryProvider));
StoredDataMiningReportsProvider reportsProvider = new StoredDataMiningReportsProvider(
dataMiningService, dataMiningWriteService);
queryDefinitionProvider.addControl(new DataMiningReportStoreControls(DataMiningEntryPoint.this,
queryDefinitionProvider.addControl(new DataMiningReportStoreControls(/* error reporter */ DataMiningEntryPoint.this,
session, dataMiningService, reportsProvider, mainPanel, queryDefinitionProvider.getRetrieverChainProvider(), resultsPresenter,
/* report provider */ DataMiningEntryPoint.this));
}
@@ -337,7 +369,7 @@ public class DataMiningEntryPoint extends AbstractSailingReadEntryPoint implemen
@Override
public void onSuccess(ModifiableStatisticQueryDefinitionDTO result) {
queryDefinitionProvider.applyQueryDefinition(result);
queryRunner.run(result);
queryRunner.run(result, /* reportParameterBindings */ null);
}
@Override
@@ -3,12 +3,9 @@ package com.sap.sailing.gwt.ui.datamining;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
@@ -32,22 +29,15 @@ import com.sap.sse.common.Util;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.datamining.shared.DataMiningSession;
import com.sap.sse.datamining.shared.dto.DataMiningReportDTO;
import com.sap.sse.datamining.shared.dto.FilterDimensionParameter;
import com.sap.sse.datamining.shared.dto.StatisticQueryDefinitionDTO;
import com.sap.sse.datamining.shared.dto.StoredDataMiningReportDTO;
import com.sap.sse.datamining.shared.impl.dto.DataRetrieverChainDefinitionDTO;
import com.sap.sse.datamining.shared.impl.dto.ModifiableDataMiningReportDTO;
import com.sap.sse.datamining.shared.impl.dto.ModifiableStatisticQueryDefinitionDTO;
import com.sap.sse.datamining.shared.impl.dto.QueryResultDTO;
import com.sap.sse.datamining.shared.impl.dto.parameters.ModifiableDataMiningReportParametersDTO;
import com.sap.sse.datamining.ui.client.CompositeResultsPresenter;
import com.sap.sse.datamining.ui.client.DataMiningServiceAsync;
import com.sap.sse.datamining.ui.client.DataRetrieverChainDefinitionProvider;
import com.sap.sse.datamining.ui.client.ReportProvider;
import com.sap.sse.datamining.ui.client.StringMessages;
import com.sap.sse.datamining.ui.client.event.DataMiningEventBus;
import com.sap.sse.datamining.ui.client.presentation.TabbedResultsPresenter;
import com.sap.sse.datamining.ui.client.selection.HierarchicalDimensionListFilterSelectionProvider;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
@@ -176,23 +166,7 @@ public class DataMiningReportStoreControls extends Composite {
* {@link #resultsPresenter}.
*/
private DataMiningReportDTO buildReport() {
// TODO bug4789: can we simply use reportProvider.getCurrentReport()?
final ArrayList<StatisticQueryDefinitionDTO> queryDefinitions = new ArrayList<>(StreamSupport
.stream(resultsPresenter.getPresenterIds().spliterator(), false)
.map(resultsPresenter::getQueryDefinition).filter(Objects::nonNull).collect(Collectors.toList()));
if (!queryDefinitions.isEmpty()) {
for (int i = 0; i < queryDefinitions.size(); i++) {
final DataRetrieverChainDefinitionDTO retrieverChain = queryDefinitions.get(i).getDataRetrieverChainDefinition();
final HashSet<FilterDimensionParameter> parameters = filterParameters.getUsages(i);
// TODO bug4789 / bug5804: at most check the parameter type for conformance; retriever levels / dimension functions should not restrict parameter applicability
if (parameters.stream().anyMatch(p -> !retrieverChain.getRetrieverLevel(p.getRetrieverLevel().getLevel()).equals(p.getRetrieverLevel()))) {
throw new IllegalStateException("The parameters retriever level is not contained by the associated queries data retriever definition");
}
}
return new ModifiableDataMiningReportDTO(queryDefinitions, new ModifiableDataMiningReportParametersDTO(filterParameters));
} else {
return null;
}
return reportProvider.getCurrentReport();
}
private Void applyReport(StoredDataMiningReportDTO storedReport) {
@@ -22,6 +22,7 @@ import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sse.common.settings.Settings;
import com.sap.sse.common.util.NaturalComparator;
import com.sap.sse.datamining.shared.GroupKey;
import com.sap.sse.datamining.shared.dto.StatisticQueryDefinitionDTO;
import com.sap.sse.datamining.shared.impl.dto.QueryResultDTO;
import com.sap.sse.datamining.ui.client.ChartToCsvExporter;
import com.sap.sse.gwt.client.shared.components.Component;
@@ -115,17 +116,14 @@ public class ManeuverSpeedDetailsResultsPresenter extends AbstractSailingResults
minDataCount = chartConfigPanel.getMinDataCount();
minValue = chartConfigPanel.getMinValue();
maxValue = chartConfigPanel.getMaxValue();
boolean zeroTo360AxisLabeling = chartConfigPanel.isZeroTo360AxisLabeling();
xAxisMin = zeroTo360AxisLabeling ? 0 : -179;
xAxisMax = zeroTo360AxisLabeling ? 359 : 180;
polarChart.getXAxis().setMin(xAxisMin).setMax(xAxisMax);
lineChart.getXAxis().setMin(xAxisMin).setMax(xAxisMax);
dataCountHistogramChart.getXAxis().setMin(xAxisMin).setMax(xAxisMax);
if (result != null) {
internalShowResults(result);
internalShowResults(/* queryDefinition */ null, result);
}
}
@@ -135,11 +133,10 @@ public class ManeuverSpeedDetailsResultsPresenter extends AbstractSailingResults
}
@Override
protected void internalShowResults(QueryResultDTO<?> result) {
protected void internalShowResults(StatisticQueryDefinitionDTO queryDefinition, QueryResultDTO<?> result) {
polarChart.removeAllSeries(false);
lineChart.removeAllSeries(false);
dataCountHistogramChart.removeAllSeries(false);
this.result = result;
Map<GroupKey, ?> results = result.getResults();
List<GroupKey> sortedNaturally = new ArrayList<GroupKey>(results.keySet());
@@ -185,7 +182,6 @@ public class ManeuverSpeedDetailsResultsPresenter extends AbstractSailingResults
dataCountHistogramChart.redraw();
// Initially resize the chart. Otherwise it's too big. FIXME with a better solution
Timer timer = new Timer() {
@Override
public void run() {
polarChart.setSizeToMatchContainer();
@@ -26,6 +26,7 @@ import com.sap.sse.common.Util.Pair;
import com.sap.sse.common.settings.Settings;
import com.sap.sse.datamining.shared.GroupKey;
import com.sap.sse.datamining.shared.data.PairWithStats;
import com.sap.sse.datamining.shared.dto.StatisticQueryDefinitionDTO;
import com.sap.sse.datamining.shared.impl.CompoundGroupKey;
import com.sap.sse.datamining.shared.impl.dto.QueryResultDTO;
import com.sap.sse.gwt.client.shared.components.Component;
@@ -85,10 +86,9 @@ public class NumberPairResultsPresenter extends AbstractSailingResultsPresenter<
}
@Override
protected void internalShowResults(QueryResultDTO<?> res) {
protected void internalShowResults(StatisticQueryDefinitionDTO queryDefinition, QueryResultDTO<?> res) {
chart.removeAllSeries(false);
seriesMappedByGroupKey.clear();
result = res;
createAndAddSeriesToChart();
for (Entry<GroupKey, ?> resultEntry : result.getResults().entrySet()) {
@@ -26,6 +26,7 @@ import com.sap.sailing.polars.datamining.shared.PolarBackendData;
import com.sap.sse.common.settings.Settings;
import com.sap.sse.common.util.NaturalComparator;
import com.sap.sse.datamining.shared.GroupKey;
import com.sap.sse.datamining.shared.dto.StatisticQueryDefinitionDTO;
import com.sap.sse.datamining.shared.impl.dto.QueryResultDTO;
import com.sap.sse.datamining.ui.client.ChartToCsvExporter;
import com.sap.sse.gwt.client.shared.components.Component;
@@ -107,7 +108,7 @@ public class PolarBackendResultsPresenter extends AbstractSailingResultsPresente
}
@Override
protected void internalShowResults(QueryResultDTO<?> result) {
protected void internalShowResults(StatisticQueryDefinitionDTO queryDefinition, QueryResultDTO<?> result) {
polarChart.removeAllSeries(false);
speedChart.removeAllSeries(false);
angleChart.removeAllSeries(false);
@@ -129,7 +130,6 @@ public class PolarBackendResultsPresenter extends AbstractSailingResultsPresente
double[] upwindSpeedOverWindSpeed = aggregation.getUpwindSpeedOverWindSpeed();
for (int i = 0; i < 30; i++) {
upwindSpeedSeries.addPoint(i, upwindSpeedOverWindSpeed[i], false, false, false);
}
speedChart.addSeries(upwindSpeedSeries, false, false);
}
@@ -149,7 +149,6 @@ public class PolarBackendResultsPresenter extends AbstractSailingResultsPresente
double[] upwindAngleOverWindSpeed = aggregation.getUpwindAngleOverWindSpeed();
for (int i = 0; i < 30; i++) {
upwindAngleSeries.addPoint(i, upwindAngleOverWindSpeed[i], false, false, false);
}
angleChart.addSeries(upwindAngleSeries, false, false);
}
@@ -159,7 +158,6 @@ public class PolarBackendResultsPresenter extends AbstractSailingResultsPresente
double[] downwindAngleOverWindSpeed = aggregation.getDownwindAngleOverWindSpeed();
for (int i = 0; i < 30; i++) {
downwindAngleSeries.addPoint(i, downwindAngleOverWindSpeed[i], false, false, false);
}
angleChart.addSeries(downwindAngleSeries, false, false);
}
@@ -36,6 +36,7 @@ import com.sap.sailing.polars.datamining.shared.PolarDataMiningSettings;
import com.sap.sse.common.settings.Settings;
import com.sap.sse.common.util.NaturalComparator;
import com.sap.sse.datamining.shared.GroupKey;
import com.sap.sse.datamining.shared.dto.StatisticQueryDefinitionDTO;
import com.sap.sse.datamining.shared.impl.dto.QueryResultDTO;
import com.sap.sse.datamining.ui.client.ChartToCsvExporter;
import com.sap.sse.gwt.client.shared.components.Component;
@@ -187,7 +188,7 @@ public class PolarResultsPresenter extends AbstractSailingResultsPresenter<Setti
}
@Override
protected void internalShowResults(QueryResultDTO<?> result) {
protected void internalShowResults(StatisticQueryDefinitionDTO queryDefinition, QueryResultDTO<?> result) {
polarChart.removeAllSeries(false);
dataCountHistogramChart.removeAllSeries(false);
dataCountPerAngleHistogramChart.removeAllSeries(false);
@@ -1,20 +1,22 @@
package com.sap.sse.datamining.ui.client;
package com.sap.sse.datamining.shared.data;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.datamining.shared.dto.DataMiningReportDTO;
import com.sap.sse.datamining.shared.dto.FilterDimensionIdentifier;
import com.sap.sse.datamining.shared.dto.FilterDimensionParameter;
import com.sap.sse.datamining.shared.dto.StatisticQueryDefinitionDTO;
import com.sap.sse.datamining.ui.client.selection.DimensionFilterSelectionProvider;
import com.sap.sse.datamining.ui.client.selection.QueryDefinitionProviderWithControls;
/**
* Tracks the use of {@link FilterDimensionParameter}s in the scope of a {@link QueryDefinitionProviderWithControls
* query editor} with its {@link DimensionFilterSelectionProvider} components where dimension filters can be bound to
* report parameters.<p>
* Tracks the use of {@link FilterDimensionParameter}s in the scope of a {@code QueryDefinitionProviderWithControls}
* query editor with its {@code DimensionFilterSelectionProvider} components where dimension filters can be bound to
* report parameters. Instances of this class are mutable, and a single instance is assumed to represent the temporary
* parameter binding information of a {@code QueryDefinitionProvider} before that provider is asked to
* {@link QueryDefinitionProvider#getQueryDefinition() produce its query}.
* <p>
*
* The query editor is not constantly maintaining a {@link StatisticQueryDefinitionDTO query object} but can only
* be filled from one and can produce a new one based on its UI state. Therefore, the parameter binding model as
@@ -24,8 +26,10 @@ import com.sap.sse.datamining.ui.client.selection.QueryDefinitionProviderWithCon
* binding information is converted into an object of this type, tracked by this object while editing the query
* and transformed back into the report's parameter usage model when running the query successfully and hence
* updating the report accordingly.
*
* @see DataMiningReportDTO#getParameterUsages(StatisticQueryDefinitionDTO)
*/
public class ReportParameterToDimensionFilterBindings {
public class ReportParameterToDimensionFilterBindings implements Iterable<Entry<FilterDimensionIdentifier, FilterDimensionParameter>> {
private final Map<FilterDimensionIdentifier, FilterDimensionParameter> parameterBindings;
public ReportParameterToDimensionFilterBindings() {
@@ -37,16 +41,14 @@ public class ReportParameterToDimensionFilterBindings {
this.parameterBindings = new HashMap<>(parameterBindings);
}
public ReportParameterToDimensionFilterBindings(DataMiningReportDTO report, StatisticQueryDefinitionDTO query) {
this(fillFromReportAndQuery(report, query));
}
private static Map<FilterDimensionIdentifier, FilterDimensionParameter> fillFromReportAndQuery(DataMiningReportDTO report, StatisticQueryDefinitionDTO query) {
final Map<FilterDimensionIdentifier, FilterDimensionParameter> result = new HashMap<>();
for (final Pair<FilterDimensionIdentifier, FilterDimensionParameter> usage : report.getParameterUsages(query)) {
result.put(usage.getA(), usage.getB());
/**
* Copy constructor
*/
public ReportParameterToDimensionFilterBindings(ReportParameterToDimensionFilterBindings other) {
this();
for (final Entry<FilterDimensionIdentifier, FilterDimensionParameter> e : other) {
setParameterBinding(e.getKey(), e.getValue());
}
return result;
}
public FilterDimensionParameter getParameterBinding(FilterDimensionIdentifier filterDimensionIdentifier) {
@@ -60,4 +62,9 @@ public class ReportParameterToDimensionFilterBindings {
public void removeParameterBinding(FilterDimensionIdentifier filterDimensionIdentifier) {
parameterBindings.remove(filterDimensionIdentifier);
}
@Override
public Iterator<Entry<FilterDimensionIdentifier, FilterDimensionParameter>> iterator() {
return parameterBindings.entrySet().iterator();
}
}
@@ -1,10 +1,12 @@
package com.sap.sse.datamining.shared.dto;
import java.io.Serializable;
import java.util.Map.Entry;
import java.util.stream.StreamSupport;
import com.sap.sse.common.Util;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.datamining.shared.data.ReportParameterToDimensionFilterBindings;
import com.sap.sse.datamining.shared.impl.dto.ModifiableStatisticQueryDefinitionDTO;
import com.sap.sse.datamining.shared.impl.dto.parameters.ParameterModelListener;
@@ -12,8 +14,8 @@ import com.sap.sse.datamining.shared.impl.dto.parameters.ParameterModelListener;
* Manages a sequence of {@link ModifiableStatisticQueryDefinitionDTO queries} and a model of
* {@link FilterDimensionParameter parameters} used by those queries. The queries are unaware of parameters. It is this
* object keeping track of the binding. Usages of a parameter in a query must be managed explicitly by invoking
* {@link #addParameterUsage(StatisticQueryDefinitionDTO, FilterDimensionParameter, FilterDimensionIdentifier)} and
* {@link #removeParameterUsage(StatisticQueryDefinitionDTO, FilterDimensionParameter, FilterDimensionIdentifier)}.
* {@link #addParameterUsage(StatisticQueryDefinitionDTO, FilterDimensionIdentifier, FilterDimensionParameter)} and
* {@link #removeParameterUsage(StatisticQueryDefinitionDTO, FilterDimensionIdentifier, FilterDimensionParameter)}.
* If a parameter is {@link #removeParameter(FilterDimensionParameter) removed} altogether, its usages are cleared
* implicitly.<p>
*
@@ -39,14 +41,63 @@ public interface DataMiningReportDTO extends Serializable {
* If the query is not yet part of this report, the query is added. Otherwise, it simply remains part
* of this report, and this method does nothing.
*/
void addQueryDefinition(ModifiableStatisticQueryDefinitionDTO queryDefinition);
default void addQueryDefinition(ModifiableStatisticQueryDefinitionDTO queryDefinition) {
addQueryDefinition(Util.size(getQueryDefinitions()), queryDefinition);
}
/**
* If the query is not yet part of this report, the query is added at the index specified. Otherwise, it simply
* remains part of this report, regardless its current position, and this method does nothing.
*
* @param index
* must be between 0 (inclusive) and the number of {@link #getQueryDefinitions() queries} currently in
* this report (exclusive)
* @throws IndexOutOfBoundsException
* if {@code index} is negative or greater or equals to the current number of
* {@link #getQueryDefinitions() queries} in this report
*/
void addQueryDefinition(int index, ModifiableStatisticQueryDefinitionDTO queryDefinition);
/**
* If the {@code toReplace} query is found, it is replaced by {@code replaceWith} in this report's
* {@link #getQueryDefinitions() query sequence}. Otherwise, {@code replaceWith} is appended to its end.
* The parameter usages are recorded if {@code parameterBindings} is not {@code null}.
*
* @param toReplace
* may be {@code null} in case no query is being replaced by {@code replaceWith}; otherwise, assumed to
* be in {@link #getQueryDefinitions()} and will be removed before adding {@code replaceWith} at the same
* index in the query definitions sequence.
* @param parameterBindings
* may be {@code null}; if not {@code null}, the parameter bindings described therein will be
* {@link #addParameterUsage(StatisticQueryDefinitionDTO, FilterDimensionIdentifier, FilterDimensionParameter)
* added} to this report as used by the {@code replaceWith} query.
*/
default void replaceQueryDefinition(StatisticQueryDefinitionDTO toReplace,
ModifiableStatisticQueryDefinitionDTO replaceWith,
ReportParameterToDimensionFilterBindings parameterBindings) {
final int index;
if (toReplace != null) {
index = removeQueryDefinition(toReplace);
} else {
index = Util.size(getQueryDefinitions());
}
addQueryDefinition(index, replaceWith);
if (parameterBindings != null) {
for (final Entry<FilterDimensionIdentifier, FilterDimensionParameter> e : parameterBindings) {
addParameterUsage(replaceWith, e.getKey(), e.getValue());
}
}
}
/**
* Removes the query definition from this reports and adjustes the
* {@link #getParameterUsages(FilterDimensionParameter) parameter usages} accordingly, removing all usages within
* the query removed.
*
* @return the index into {@link #getQueryDefinitions()} where the {@code queryDefinition} was found, or -1 if the
* query was not found
*/
boolean removeQueryDefinition(StatisticQueryDefinitionDTO queryDefinition);
int removeQueryDefinition(StatisticQueryDefinitionDTO queryDefinition);
/**
* Records a parameter's usage in one of this report's {@link #getQueryDefinitions() queries}. The usage will then
@@ -54,23 +105,23 @@ public interface DataMiningReportDTO extends Serializable {
* {@link #removeParameterUsage removed} again.
* @param query
* a query from {@link #getQueryDefinitions()}
* @param parameter
* a parameter from {@link #getParameters()}
* @param filterDimensionIdentifier
* a {@link FilterDimensionIdentifier#getRetrieverLevel() retriever level} that occurs in the
* {@link StatisticQueryDefinitionDTO#getDataRetrieverChainDefinition() query's retriever chain} and a
* {@link FilterDimensionIdentifier#getDimensionFunction() dimension} for which a
* {@link StatisticQueryDefinitionDTO#getFilterSelection() filter} exists in the query.
* @param parameter
* a parameter from {@link #getParameters()}
*/
void addParameterUsage(StatisticQueryDefinitionDTO query, FilterDimensionParameter parameter,
FilterDimensionIdentifier filterDimensionIdentifier);
void addParameterUsage(StatisticQueryDefinitionDTO query, FilterDimensionIdentifier filterDimensionIdentifier,
FilterDimensionParameter parameter);
void removeParameterUsage(StatisticQueryDefinitionDTO query, FilterDimensionParameter parameter,
FilterDimensionIdentifier filterDimensionIdentifier);
void removeParameterUsage(StatisticQueryDefinitionDTO query, FilterDimensionIdentifier filterDimensionIdentifier,
FilterDimensionParameter parameter);
Iterable<Pair<StatisticQueryDefinitionDTO, FilterDimensionIdentifier>> getParameterUsages(FilterDimensionParameter parameter);
Iterable<Pair<FilterDimensionIdentifier, FilterDimensionParameter>> getParameterUsages(StatisticQueryDefinitionDTO query);
ReportParameterToDimensionFilterBindings getParameterUsages(StatisticQueryDefinitionDTO query);
FilterDimensionParameter getUsedParameter(StatisticQueryDefinitionDTO query, FilterDimensionIdentifier filterDimensionIdentifier);
@@ -66,7 +66,6 @@ public class FunctionDTO implements Serializable, Comparable<FunctionDTO> {
this.sourceTypeName = sourceTypeName;
this.returnTypeName = returnTypeName;
this.parameterTypeNames = new ArrayList<String>(parameterTypeNames);
this.displayName = displayName;
this.ordinal = ordinal;
}
@@ -5,6 +5,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -13,6 +14,7 @@ import java.util.Set;
import com.sap.sse.common.Util;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.datamining.shared.data.ReportParameterToDimensionFilterBindings;
import com.sap.sse.datamining.shared.dto.DataMiningReportDTO;
import com.sap.sse.datamining.shared.dto.FilterDimensionIdentifier;
import com.sap.sse.datamining.shared.dto.FilterDimensionParameter;
@@ -25,7 +27,7 @@ public class ModifiableDataMiningReportDTO implements DataMiningReportDTO {
private ArrayList<ModifiableStatisticQueryDefinitionDTO> queryDefinitions;
private HashSet<FilterDimensionParameter> parameters;
private HashMap<StatisticQueryDefinitionDTO, HashMap<FilterDimensionIdentifier, FilterDimensionParameter>> parameterUsages;
private IdentityHashMap<StatisticQueryDefinitionDTO, HashMap<FilterDimensionIdentifier, FilterDimensionParameter>> parameterUsages;
/**
* Objects of this type entertain one value change listener for each parameter in {@link #getParameters()} so
@@ -98,8 +100,10 @@ public class ModifiableDataMiningReportDTO implements DataMiningReportDTO {
}
@Override
public void addQueryDefinition(ModifiableStatisticQueryDefinitionDTO queryDefinition) {
queryDefinitions.add(queryDefinition);
public void addQueryDefinition(int index, ModifiableStatisticQueryDefinitionDTO queryDefinition) {
if (!queryDefinitions.contains(queryDefinition)) {
queryDefinitions.add(index, queryDefinition);
}
}
/**
@@ -107,9 +111,11 @@ public class ModifiableDataMiningReportDTO implements DataMiningReportDTO {
* removing all usages within the query removed.
*/
@Override
public boolean removeQueryDefinition(StatisticQueryDefinitionDTO queryDefinition) {
public int removeQueryDefinition(StatisticQueryDefinitionDTO queryDefinition) {
parameterUsages.remove(queryDefinition);
return queryDefinitions.remove(queryDefinition);
final int result = queryDefinitions.indexOf(queryDefinition);
queryDefinitions.remove(queryDefinition);
return result;
}
@Override
@@ -129,12 +135,8 @@ public class ModifiableDataMiningReportDTO implements DataMiningReportDTO {
}
@Override
public Iterable<Pair<FilterDimensionIdentifier, FilterDimensionParameter>> getParameterUsages(StatisticQueryDefinitionDTO query) {
final List<Pair<FilterDimensionIdentifier, FilterDimensionParameter>> result = new ArrayList<>();
for (final Entry<FilterDimensionIdentifier, FilterDimensionParameter> e : parameterUsages.get(query).entrySet()) {
result.add(new Pair<>(e.getKey(), e.getValue()));
}
return result;
public ReportParameterToDimensionFilterBindings getParameterUsages(StatisticQueryDefinitionDTO query) {
return new ReportParameterToDimensionFilterBindings(parameterUsages.get(query));
}
@Override
@@ -161,7 +163,7 @@ public class ModifiableDataMiningReportDTO implements DataMiningReportDTO {
}
@Override
public void addParameterUsage(StatisticQueryDefinitionDTO query, FilterDimensionParameter parameter, FilterDimensionIdentifier filterDimensionIdentifier) {
public void addParameterUsage(StatisticQueryDefinitionDTO query, FilterDimensionIdentifier filterDimensionIdentifier, FilterDimensionParameter parameter) {
if (!Util.contains(getParameters(), parameter)) {
throw new IllegalArgumentException("Parameter "+parameter.getName()+" is not part of this report");
}
@@ -172,8 +174,8 @@ public class ModifiableDataMiningReportDTO implements DataMiningReportDTO {
}
@Override
public void removeParameterUsage(StatisticQueryDefinitionDTO query, FilterDimensionParameter parameter,
FilterDimensionIdentifier filterDimensionIdentifier) {
public void removeParameterUsage(StatisticQueryDefinitionDTO query, FilterDimensionIdentifier filterDimensionIdentifier,
FilterDimensionParameter parameter) {
if (parameterUsages.containsKey(query)) {
parameterUsages.get(query).remove(filterDimensionIdentifier);
}
@@ -35,7 +35,8 @@ public class ValueListFilterParameter extends AbstractParameterizedDimensionFilt
final HashSet<T> set = new HashSet<>();
Util.addAll(newValue, set);
this.values = set;
getParameterModelListeners().forEach(l->l.parameterValueChanged(this, oldValues));
// iterate on a copy because listeners may choose to unregister due to the event being sent
new HashSet<>(getParameterModelListeners()).forEach(l->l.parameterValueChanged(this, oldValues));
}
@Override
@@ -80,7 +80,7 @@ public class DummyResultsPresenter extends AbstractResultsPresenter<Settings> {
}
@Override
protected void internalShowResults(QueryResultDTO<?> result) {
protected void internalShowResults(StatisticQueryDefinitionDTO queryDefinition, QueryResultDTO<?> result) {
}
}
@@ -111,22 +111,24 @@ public interface CompositeResultsPresenter<SettingsType extends Settings> extend
*
* @param presenterId
* The id of the presenter used to show the error
* @param queryDefinition TODO
* @param error
* The error message
*/
void showError(String presenterId, String error);
void showError(String presenterId, StatisticQueryDefinitionDTO queryDefinition, String error);
/**
* Shows the given error in the presenter for the given id. Does nothing if no presenter for the given id exists.
*
* @param presenterId
* The id of the presenter used to show the error
* @param queryDefinition TODO
* @param mainError
* The main error message
* @param detailedErrors
* The detailed error messages
*/
void showError(String presenterId, String mainError, Iterable<String> detailedErrors);
void showError(String presenterId, StatisticQueryDefinitionDTO queryDefinition, String mainError, Iterable<String> detailedErrors);
/**
* Shows the busy indicator of the presenter for the given id. Does nothing if no presenter for the given id exists.
@@ -163,13 +165,13 @@ public interface CompositeResultsPresenter<SettingsType extends Settings> extend
}
@Override
default void showError(String error) {
showError(getCurrentPresenterId(), error);
default void showError(StatisticQueryDefinitionDTO queryDefinition, String error) {
showError(getCurrentPresenterId(), queryDefinition, error);
}
@Override
default void showError(String mainError, Iterable<String> detailedErrors) {
showError(getCurrentPresenterId(), mainError, detailedErrors);
default void showError(String mainError, Iterable<String> detailedErrors, StatisticQueryDefinitionDTO queryDefinition) {
showError(getCurrentPresenterId(), queryDefinition, mainError, detailedErrors);
}
@Override
@@ -1,18 +1,22 @@
package com.sap.sse.datamining.ui.client;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.common.settings.Settings;
import com.sap.sse.datamining.shared.data.ReportParameterToDimensionFilterBindings;
import com.sap.sse.datamining.shared.dto.StatisticQueryDefinitionDTO;
import com.sap.sse.datamining.shared.impl.dto.ModifiableStatisticQueryDefinitionDTO;
import com.sap.sse.gwt.client.shared.components.Component;
public interface QueryDefinitionProvider<SettingsType extends Settings> extends Component<SettingsType> {
void reloadComponents();
/**
* Constructs a new query based on the aggregator, statistic, grouping and dimension filter specifications
*/
StatisticQueryDefinitionDTO getQueryDefinition();
Pair<ModifiableStatisticQueryDefinitionDTO, ReportParameterToDimensionFilterBindings> getQueryDefinitionAndReportParameterBinding();
/**
* Checks whether a valid non-{@code null} statistic selection, aggregator selection, and grouping definition exist.
* Otherwise, localized error messages describing the respective problem(s) are returned.
@@ -28,5 +32,4 @@ public interface QueryDefinitionProvider<SettingsType extends Settings> extends
void addQueryDefinitionChangedListener(QueryDefinitionChangedListener listener);
void removeQueryDefinitionChangedListener(QueryDefinitionChangedListener listener);
}
@@ -1,11 +1,20 @@
package com.sap.sse.datamining.ui.client;
import com.sap.sse.datamining.shared.dto.StatisticQueryDefinitionDTO;
import com.sap.sse.datamining.shared.data.ReportParameterToDimensionFilterBindings;
import com.sap.sse.datamining.shared.dto.FilterDimensionIdentifier;
import com.sap.sse.datamining.shared.dto.FilterDimensionParameter;
import com.sap.sse.datamining.shared.impl.dto.ModifiableStatisticQueryDefinitionDTO;
import com.sap.sse.datamining.ui.client.settings.QueryRunnerSettings;
import com.sap.sse.gwt.client.shared.components.Component;
public interface QueryRunner extends QueryDefinitionChangedListener, Component<QueryRunnerSettings> {
void run(StatisticQueryDefinitionDTO queryDefinition);
/**
* @param queryDefinition
* the query to run
* @param reportParameterBindings
* either {@code null}, or a possibly empty set of bindings of {@link FilterDimensionParameter report
* parameters} to usages in the query in the form of {@link FilterDimensionIdentifier}s pointing to the
* retriever level and dimension function to identify the place of the parameter use
*/
void run(ModifiableStatisticQueryDefinitionDTO queryDefinition, ReportParameterToDimensionFilterBindings reportParameterBindings);
}
@@ -33,8 +33,8 @@ public interface ResultsPresenter<SettingsType extends Settings> extends Compone
*/
void showResult(StatisticQueryDefinitionDTO queryDefinition, QueryResultDTO<?> result);
void showError(String error);
void showError(String mainError, Iterable<String> detailedErrors);
void showError(StatisticQueryDefinitionDTO queryDefinition, String error);
void showError(String mainError, Iterable<String> detailedErrors, StatisticQueryDefinitionDTO queryDefinition);
void showBusyIndicator();
}
@@ -17,7 +17,8 @@ import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ValueListBox;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sse.common.Util;
import com.sap.sse.datamining.shared.dto.StatisticQueryDefinitionDTO;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.datamining.shared.data.ReportParameterToDimensionFilterBindings;
import com.sap.sse.datamining.shared.impl.PredefinedQueryIdentifier;
import com.sap.sse.datamining.shared.impl.dto.ModifiableStatisticQueryDefinitionDTO;
import com.sap.sse.datamining.ui.client.DataMiningServiceAsync;
@@ -36,7 +37,7 @@ public class PredefinedQueryRunner extends ComponentWithoutSettings {
private final DataMiningServiceAsync dataMiningService;
private final ErrorReporter errorReporter;
private final QueryDefinitionProvider<?> queryDefinitionProvider;
private final Consumer<StatisticQueryDefinitionDTO> queryRunner;
private final Consumer<Pair<ModifiableStatisticQueryDefinitionDTO, ReportParameterToDimensionFilterBindings>> queryRunner;
private final Button showDialogButton;
private final DialogBox dialogBox;
@@ -46,7 +47,8 @@ public class PredefinedQueryRunner extends ComponentWithoutSettings {
public PredefinedQueryRunner(Component<?> parent, ComponentContext<?> context, StringMessages stringMessages,
DataMiningServiceAsync dataMiningService, ErrorReporter errorReporter,
QueryDefinitionProvider<?> queryDefinitionProvider, Consumer<StatisticQueryDefinitionDTO> queryRunner) {
QueryDefinitionProvider<?> queryDefinitionProvider,
Consumer<Pair<ModifiableStatisticQueryDefinitionDTO, ReportParameterToDimensionFilterBindings>> queryRunner) {
super(parent, context);
this.stringMessages = stringMessages;
this.dataMiningService = dataMiningService;
@@ -146,7 +148,7 @@ public class PredefinedQueryRunner extends ComponentWithoutSettings {
@Override
public void onSuccess(ModifiableStatisticQueryDefinitionDTO queryDefinition) {
queryDefinitionProvider.applyQueryDefinition(queryDefinition);
queryRunner.accept(queryDefinition);
queryRunner.accept(new Pair<>(queryDefinition, /* parameter bindings */ null));
}
@Override
public void onFailure(Throwable error) {
@@ -9,7 +9,11 @@ import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sse.common.Util;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.datamining.shared.DataMiningSession;
import com.sap.sse.datamining.shared.data.ReportParameterToDimensionFilterBindings;
import com.sap.sse.datamining.shared.dto.DataMiningReportDTO;
import com.sap.sse.datamining.shared.dto.FilterDimensionParameter;
import com.sap.sse.datamining.shared.dto.StatisticQueryDefinitionDTO;
import com.sap.sse.datamining.shared.impl.dto.ModifiableStatisticQueryDefinitionDTO;
import com.sap.sse.datamining.shared.impl.dto.QueryResultDTO;
@@ -20,6 +24,7 @@ import com.sap.sse.datamining.ui.client.DataMiningServiceAsync;
import com.sap.sse.datamining.ui.client.ManagedDataMiningQueriesCounter;
import com.sap.sse.datamining.ui.client.QueryDefinitionProvider;
import com.sap.sse.datamining.ui.client.QueryRunner;
import com.sap.sse.datamining.ui.client.ReportProvider;
import com.sap.sse.datamining.ui.client.settings.QueryRunnerSettings;
import com.sap.sse.datamining.ui.client.settings.QueryRunnerSettingsDialogComponent;
import com.sap.sse.gwt.client.ErrorReporter;
@@ -29,7 +34,7 @@ import com.sap.sse.gwt.client.shared.settings.ComponentContext;
/**
* The "Run" button with settings and the event handler for the "Run" button which triggers the
* {@link #run(StatisticQueryDefinitionDTO)} method where the query to run is obtained from the
* {@link #run(StatisticQueryDefinitionDTO, ReportParameterToDimensionFilterBindings)} method where the query to run is obtained from the
* {@link QueryDefinitionProvider} passed to the constructor. Results received from successful query execution through
* the {@link DataMiningServiceAsync} are shown in the {@link CompositeResultsPresenter} that was passed to the
* constructor, in the currently active tab.<p>
@@ -61,13 +66,35 @@ public class SimpleQueryRunner extends AbstractDataMiningComponent<QueryRunnerSe
*/
private final Timer queryReleaseTimer;
private QueryRunnerSettings settings;
/**
* The query and its optional {@link ReportParameterToDimensionFilterBindings use} of
* {@link FilterDimensionParameter report parameters} is fetched from here.
*/
private final QueryDefinitionProvider<?> queryDefinitionProvider;
/**
* Query execution results are sent to the presenter within this result presenter that
* was current (e.g., the selected tab) when running the query was triggered.
*/
private final CompositeResultsPresenter<?> resultsPresenter;
/**
* That's where we can obtain the {@link DataMiningReportDTO} from that is considered the "current" report shown and
* manipulated by the entry point in whose context this query runner is used. When a query and its parameterization
* if fetched from the {@link #queryDefinitionProvider} for execution, it is updated in the
* {@link ReportProvider#getCurrentReport() current report}, replacing the query previously shown in the
* {@link #resultsPresenter}'s {@link CompositeResultsPresenter#getCurrentPresenterId() current presenter}.
*/
private final ReportProvider reportProvider;
private final Button runButton;
public SimpleQueryRunner(Component<?> parent, ComponentContext<?> context, DataMiningSession session,
DataMiningServiceAsync dataMiningService, ErrorReporter errorReporter,
QueryDefinitionProvider<?> queryDefinitionProvider, CompositeResultsPresenter<?> resultsPresenter) {
QueryDefinitionProvider<?> queryDefinitionProvider, CompositeResultsPresenter<?> resultsPresenter,
ReportProvider reportProvider) {
super(parent, context);
this.session = session;
this.dataMiningService = dataMiningService;
@@ -77,32 +104,40 @@ public class SimpleQueryRunner extends AbstractDataMiningComponent<QueryRunnerSe
this.settings = new QueryRunnerSettings();
this.queryDefinitionProvider = queryDefinitionProvider;
this.resultsPresenter = resultsPresenter;
this.reportProvider = reportProvider;
runButton = new Button(getDataMiningStringMessages().run());
runButton.ensureDebugId("RunDataminingQueryButton");
runButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
run(queryDefinitionProvider.getQueryDefinition());
final Pair<ModifiableStatisticQueryDefinitionDTO, ReportParameterToDimensionFilterBindings> queryDefinitionAndParameterBindings = queryDefinitionProvider
.getQueryDefinitionAndReportParameterBinding();
run(queryDefinitionAndParameterBindings.getA(), queryDefinitionAndParameterBindings.getB());
}
});
queryReleaseTimer = new Timer() {
@Override
public void run() {
SimpleQueryRunner.this.run(queryDefinitionProvider.getQueryDefinition());
final Pair<ModifiableStatisticQueryDefinitionDTO, ReportParameterToDimensionFilterBindings> queryDefinitionAndParameterBindings = queryDefinitionProvider
.getQueryDefinitionAndReportParameterBinding();
SimpleQueryRunner.this.run(queryDefinitionAndParameterBindings.getA(), queryDefinitionAndParameterBindings.getB());
}
};
queryDefinitionChanged(queryDefinitionProvider.getQueryDefinition());
}
@Override
public void run(StatisticQueryDefinitionDTO queryDefinition) {
public void run(ModifiableStatisticQueryDefinitionDTO queryDefinition, ReportParameterToDimensionFilterBindings reportParameterBindings) {
final Iterable<String> errorMessages = queryDefinitionProvider.validateQueryDefinition(queryDefinition);
final String presenterId = resultsPresenter.getCurrentPresenterId();
final StatisticQueryDefinitionDTO oldPresenterQuery = resultsPresenter.getCurrentQueryDefinition();
reportProvider.getCurrentReport().replaceQueryDefinition(oldPresenterQuery, queryDefinition, reportParameterBindings);
if (errorMessages == null || !errorMessages.iterator().hasNext()) {
counter.increase();
resultsPresenter.showBusyIndicator(presenterId);
dataMiningService.runQuery(session, (ModifiableStatisticQueryDefinitionDTO) queryDefinition,
new ManagedDataMiningQueryCallback<Serializable>(counter) {
// TODO bug4789: consistently update the entry point's currentReport, also using the QueryDefinitionProvider's parameter mappings (ReportParameterToDimensionFilterBindings)
@Override
protected void handleSuccess(QueryResultDTO<Serializable> result) {
resultsPresenter.showResult(presenterId, queryDefinition, result);
@@ -111,12 +146,12 @@ public class SimpleQueryRunner extends AbstractDataMiningComponent<QueryRunnerSe
@Override
protected void handleFailure(Throwable caught) {
errorReporter.reportError("Error running the query: " + caught.getMessage());
resultsPresenter.showError(presenterId,
getDataMiningStringMessages().errorRunningDataMiningQuery() + ".");
resultsPresenter.showError(presenterId, // this also clears the query in the result presenter
queryDefinition, getDataMiningStringMessages().errorRunningDataMiningQuery() + ".");
}
});
} else {
resultsPresenter.showError(presenterId, getDataMiningStringMessages().queryNotValidBecause(), errorMessages);
resultsPresenter.showError(presenterId, queryDefinition, getDataMiningStringMessages().queryNotValidBecause(), errorMessages);
}
}
@@ -16,6 +16,7 @@ import com.google.gwt.user.client.ui.ValueListBox;
import com.sap.sse.common.Util.Triple;
import com.sap.sse.common.settings.Settings;
import com.sap.sse.datamining.shared.GroupKey;
import com.sap.sse.datamining.shared.dto.StatisticQueryDefinitionDTO;
import com.sap.sse.datamining.shared.impl.dto.QueryResultDTO;
import com.sap.sse.datamining.ui.client.presentation.dataproviders.AbstractNumericDataProvider;
import com.sap.sse.datamining.ui.client.presentation.dataproviders.AverageWithStatsDataProvider;
@@ -70,7 +71,7 @@ public abstract class AbstractNumericResultsPresenter<SettingsType extends Setti
* {@link Number}s returned by the provider will then be passed to {@link #internalShowNumericResults(Map, Map)} for
* display.
*/
protected void internalShowResults(QueryResultDTO<?> result) {
protected void internalShowResults(StatisticQueryDefinitionDTO queryDefinition, QueryResultDTO<?> result) {
currentDataProvider = dataProviders.selectCurrentDataProvider(result.getResultType());
updateDataSelectionListBox();
if (currentDataProvider != null) {
@@ -86,7 +87,7 @@ public abstract class AbstractNumericResultsPresenter<SettingsType extends Setti
}
});
} else {
showError(getDataMiningStringMessages().cantDisplayDataOfType(getCurrentResult().getResultType()));
showError(queryDefinition, getDataMiningStringMessages().cantDisplayDataOfType(getCurrentResult().getResultType()));
}
}
@@ -66,7 +66,7 @@ public abstract class AbstractResultsPresenter<SettingsType extends Settings>
errorLabel.setStyleName("chart-importantMessage");
labeledBusyIndicator = new HTML(getDataMiningStringMessages().runningQuery());
labeledBusyIndicator.setStyleName("chart-busyMessage");
showError(getDataMiningStringMessages().runAQuery());
showError(/* query definition */ null, getDataMiningStringMessages().runAQuery());
}
@Override
@@ -86,37 +86,37 @@ public abstract class AbstractResultsPresenter<SettingsType extends Settings>
this.currentResult = result;
this.currentQueryDefinition = queryDefinition;
updateCurrentResultInfo();
internalShowResults(getCurrentResult());
internalShowResults(queryDefinition, getCurrentResult());
if (state != ResultsPresenterState.RESULT) {
mainPanel.setWidgetHidden(controlsPanel, controlsPanel.getWidgetCount() == 0);
presentationPanel.setWidget(getPresentationWidget());
state = ResultsPresenterState.RESULT;
}
} else {
showError(getDataMiningStringMessages().noDataFound() + ".");
showError(queryDefinition, getDataMiningStringMessages().noDataFound() + ".");
}
}
abstract protected void internalShowResults(QueryResultDTO<?> result);
abstract protected void internalShowResults(StatisticQueryDefinitionDTO queryDefinition, QueryResultDTO<?> result);
protected abstract Widget getPresentationWidget();
@Override
public void showError(String error) {
showError(SafeHtmlUtils.fromString(error));
public void showError(StatisticQueryDefinitionDTO queryDefinition, String error) {
showError(queryDefinition, SafeHtmlUtils.fromString(error));
}
@Override
public void showError(String mainError, Iterable<String> detailedErrors) {
public void showError(String mainError, Iterable<String> detailedErrors, StatisticQueryDefinitionDTO queryDefinition) {
StringBuilder errorBuilder = new StringBuilder(mainError + ":<br /><ul>");
for (String detailedError : detailedErrors) {
errorBuilder.append("<li>" + detailedError + "</li>");
}
errorBuilder.append("</ul>");
showError(SafeHtmlUtils.fromTrustedString(errorBuilder.toString()));
showError(queryDefinition, SafeHtmlUtils.fromTrustedString(errorBuilder.toString()));
}
private void showError(SafeHtml error) {
private void showError(StatisticQueryDefinitionDTO queryDefinition, SafeHtml error) {
if (state != ResultsPresenterState.ERROR) {
mainPanel.setWidgetHidden(controlsPanel, true);
presentationPanel.setWidget(errorLabel);
@@ -124,7 +124,7 @@ public abstract class AbstractResultsPresenter<SettingsType extends Settings>
}
errorLabel.setHTML(error);
currentResult = null;
currentQueryDefinition = null;
currentQueryDefinition = queryDefinition;
updateCurrentResultInfo();
}
@@ -136,7 +136,6 @@ public abstract class AbstractResultsPresenter<SettingsType extends Settings>
state = ResultsPresenterState.BUSY;
}
currentResult = null;
currentQueryDefinition = null;
updateCurrentResultInfo();
}
@@ -99,16 +99,16 @@ public class MultiResultsPresenter extends AbstractDataMiningComponent<Settings>
}
@Override
public void showError(String error) {
public void showError(StatisticQueryDefinitionDTO queryDefinition, String error) {
for (PresenterDescriptor<Object> descriptor : availablePresenters) {
descriptor.getPresenter().showError(error);
descriptor.getPresenter().showError(queryDefinition, error);
}
}
@Override
public void showError(String mainError, Iterable<String> detailedErrors) {
public void showError(String mainError, Iterable<String> detailedErrors, StatisticQueryDefinitionDTO queryDefinition) {
for (PresenterDescriptor<Object> descriptor : availablePresenters) {
descriptor.getPresenter().showError(mainError, detailedErrors);
descriptor.getPresenter().showError(mainError, detailedErrors, queryDefinition);
}
}
@@ -179,24 +179,24 @@ public class TabbedResultsPresenter extends AbstractDataMiningComponent<Settings
break;
}
}
tabPanel.selectTab(0); // this will also fire the selection event, so the query provider will update according to the query
tabPanel.selectTab(0, /* fire events */ true); // this will also fire the selection event, so the query provider will update according to the query
}
@Override
public void showError(String presenterId, String error) {
public void showError(String presenterId, StatisticQueryDefinitionDTO queryDefinition, String error) {
CloseablePresenterTab tab = getTab(presenterId);
if (tab != null) {
tab.setText(getDataMiningStringMessages().error());
tab.getPresenter().showError(error);
tab.getPresenter().showError(queryDefinition, error);
}
}
@Override
public void showError(String presenterId, String mainError, Iterable<String> detailedErrors) {
public void showError(String presenterId, StatisticQueryDefinitionDTO queryDefinition, String mainError, Iterable<String> detailedErrors) {
CloseablePresenterTab tab = getTab(presenterId);
if (tab != null) {
tab.setText(getDataMiningStringMessages().error());
tab.getPresenter().showError(mainError, detailedErrors);
tab.getPresenter().showError(mainError, detailedErrors, queryDefinition);
}
}
@@ -44,28 +44,29 @@ import com.sap.sse.common.settings.SerializableSettings;
import com.sap.sse.common.util.NaturalComparator;
import com.sap.sse.datamining.shared.DataMiningSession;
import com.sap.sse.datamining.shared.GroupKey;
import com.sap.sse.datamining.shared.data.ReportParameterToDimensionFilterBindings;
import com.sap.sse.datamining.shared.dto.DataMiningReportDTO;
import com.sap.sse.datamining.shared.dto.FilterDimensionIdentifier;
import com.sap.sse.datamining.shared.dto.FilterDimensionParameter;
import com.sap.sse.datamining.shared.impl.GenericGroupKey;
import com.sap.sse.datamining.shared.impl.dto.DataRetrieverLevelDTO;
import com.sap.sse.datamining.shared.impl.dto.FunctionDTO;
import com.sap.sse.datamining.shared.impl.dto.QueryResultDTO;
import com.sap.sse.datamining.shared.impl.dto.parameters.ParameterModelListener;
import com.sap.sse.datamining.ui.client.AbstractDataMiningComponent;
import com.sap.sse.datamining.ui.client.DataMiningServiceAsync;
import com.sap.sse.datamining.ui.client.DataRetrieverChainDefinitionProvider;
import com.sap.sse.datamining.ui.client.FilterSelectionChangedListener;
import com.sap.sse.datamining.ui.client.FilterSelectionProvider;
import com.sap.sse.datamining.ui.client.ManagedDataMiningQueriesCounter;
import com.sap.sse.datamining.ui.client.event.CreateFilterParameterEvent;
import com.sap.sse.datamining.ui.client.event.DataMiningEventBus;
import com.sap.sse.datamining.ui.client.event.EditFilterParameterEvent;
import com.sap.sse.datamining.ui.client.event.FilterParametersChangedEvent;
import com.sap.sse.datamining.ui.client.event.FilterParametersDialogClosedEvent;
import com.sap.sse.datamining.ui.client.ReportProvider;
import com.sap.sse.datamining.ui.client.execution.ManagedDataMiningQueryCallback;
import com.sap.sse.datamining.ui.client.execution.SimpleManagedDataMiningQueriesCounter;
import com.sap.sse.datamining.ui.client.resources.DataMiningDataGridResources;
import com.sap.sse.datamining.ui.client.resources.DataMiningResources;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.controls.busyindicator.SimpleBusyIndicator;
import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback;
import com.sap.sse.gwt.client.panels.AbstractFilterablePanel;
import com.sap.sse.gwt.client.shared.components.Component;
import com.sap.sse.gwt.client.shared.components.SettingsDialogComponent;
@@ -80,7 +81,7 @@ import com.sap.sse.gwt.client.shared.settings.ComponentContext;
*
* Items of this type are arranged by the {@link HierarchicalDimensionListFilterSelectionProvider}.
*/
public class DimensionFilterSelectionProvider extends AbstractDataMiningComponent<SerializableSettings> {
public class DimensionFilterSelectionProvider extends AbstractDataMiningComponent<SerializableSettings> implements ParameterModelListener {
private static final DataMiningResources Resources = GWT.create(DataMiningResources.class);
private static final NaturalComparator NaturalComparator = new NaturalComparator();
@@ -121,6 +122,8 @@ public class DimensionFilterSelectionProvider extends AbstractDataMiningComponen
* any other filters / queries.
*/
private FilterDimensionParameter parameter;
private ReportProvider reportProvider;
private final ReportParameterToDimensionFilterBindings reportParameterBindings;
private String searchInputToApply;
@@ -131,9 +134,12 @@ public class DimensionFilterSelectionProvider extends AbstractDataMiningComponen
private Iterable<? extends Serializable> selectionToBeApplied;
private Consumer<Iterable<String>> selectionCallback;
public DimensionFilterSelectionProvider(Component<?> parent, ComponentContext<?> componentContext, DataMiningServiceAsync dataMiningService,
ErrorReporter errorReporter, DataMiningSession session, DataRetrieverChainDefinitionProvider retrieverChainProvider,
FilterSelectionProvider filterSelectionProvider, DataRetrieverLevelDTO retrieverLevel, FunctionDTO dimension) {
public DimensionFilterSelectionProvider(Component<?> parent, ComponentContext<?> componentContext,
DataMiningServiceAsync dataMiningService, ErrorReporter errorReporter, DataMiningSession session,
DataRetrieverChainDefinitionProvider retrieverChainProvider,
FilterSelectionProvider filterSelectionProvider, DataRetrieverLevelDTO retrieverLevel,
FunctionDTO dimension, ReportParameterToDimensionFilterBindings reportParameterBindings,
ReportProvider reportProvider) {
super(parent, componentContext);
this.dataMiningService = dataMiningService;
this.errorReporter = errorReporter;
@@ -142,6 +148,12 @@ public class DimensionFilterSelectionProvider extends AbstractDataMiningComponen
this.filterSelectionProvider = filterSelectionProvider;
this.retrieverLevel = retrieverLevel;
this.dimension = dimension;
this.reportParameterBindings = reportParameterBindings;
this.reportProvider = reportProvider;
parameter = reportParameterBindings.getParameterBinding(new FilterDimensionIdentifier(retrieverLevel, dimension));
if (parameter != null) {
parameter.addParameterModelListener(this);
}
counter = new SimpleManagedDataMiningQueriesCounter();
listeners = new HashSet<>();
DataMiningDataGridResources dataGridResources = GWT.create(DataMiningDataGridResources.class);
@@ -197,21 +209,6 @@ public class DimensionFilterSelectionProvider extends AbstractDataMiningComponen
mainPanel.addNorth(filterPanel, 35);
mainPanel.setWidgetHidden(filterPanel, true);
mainPanel.add(contentContainer);
DataMiningEventBus.addHandler(FilterParametersChangedEvent.TYPE, event -> {
this.parameter = event.getUsedParameter(this.retrieverLevel, this.dimension);
this.filterPanel.filter();
if (this.parameter != null) {
boolean selectionChanged = false;
for (final Serializable value : this.filterPanel.getAll()) {
final boolean matchedByParameter = parameter.matches(value);
selectionChanged = selectionChanged || selectionModel.isSelected(value) == matchedByParameter;
selectionModel.setSelected(value, matchedByParameter);
}
if (!selectionChanged) {
this.selectionChanged(null);
}
}
});
updateContent(null);
}
@@ -235,19 +232,26 @@ public class DimensionFilterSelectionProvider extends AbstractDataMiningComponen
parameterSettingsButton.addStyleName("query-parameter");
parameterSettingsButton.addClickHandler(e -> {
if (this.parameter == null) {
DataMiningEventBus.fire(
// FIXME I think "create" is not necessarily right here; couldn't this also be "use existing" when the parameter model of the current report has one for that dimension already?
new CreateFilterParameterEvent(this.retrieverLevel, this.dimension, this.getSelection())
);
// TODO bug4789: when binding a parameter to this dimension filter, observe its value set and record usage in temporary structure ReportParameterToDimensionFilterBindings
new PickOrCreateReportParameterDialog(reportProvider.getCurrentReport(), dimension.getReturnTypeName(), getDataMiningStringMessages(),
new DialogCallback<FilterDimensionParameter>() {
@Override
public void ok(FilterDimensionParameter editedObject) {
parameter = editedObject;
reportParameterBindings.setParameterBinding(new FilterDimensionIdentifier(retrieverLevel, dimension), editedObject);
editedObject.addParameterModelListener(DimensionFilterSelectionProvider.this);
parameterValueChanged(editedObject, Collections.emptySet()); // update this dimension filter's selection based on parameter value set
}
@Override
public void cancel() {
parameterSettingsButton.setDown(false);
}
}).center();
} else {
DataMiningEventBus.fire(new EditFilterParameterEvent(parameter));
unbindFromParameter(this.parameter);
}
});
// FIXME bug4789: this isn't enough; the "P" button must always correspond to the current report's parameter binding regarding this dimension filter so that switching tabs updates accordingly
DataMiningEventBus.addHandler(FilterParametersDialogClosedEvent.TYPE, event -> {
this.parameter = event.getUsedParameter(this.retrieverLevel, this.dimension);
parameterSettingsButton.setDown(parameter != null);
});
headerPanel.add(parameterSettingsButton);
headerPanel.setCellHorizontalAlignment(parameterSettingsButton, HasHorizontalAlignment.ALIGN_RIGHT);
// toggle button to display the filter/search text field:
@@ -323,7 +327,22 @@ public class DimensionFilterSelectionProvider extends AbstractDataMiningComponen
return element.toString();
}
/**
* If a {@link #parameter} is bound to this dimension filter, the parameter's value is updated to reflect the new
* selection.
* <p>
*
* TODO bug4789: consider finding out whether this was an incremental or "radical" selection change and try to
* update the parameter value set accordingly: incrementally if the change seems to be incremental, or by simply
* setting the current selected set as the new parameter value set if considered "radical."
* <p>
*
* Then, all {@link #listeners} are notified.
*/
private void selectionChanged(SelectionChangeEvent event) {
if (parameter != null) {
parameter.setValues(selectionModel.getSelectedSet());
}
notifyListeners();
}
@@ -354,7 +373,6 @@ public class DimensionFilterSelectionProvider extends AbstractDataMiningComponen
missingValues.add(value);
}
}
if (!missingValues.isEmpty()) {
String listedValues = missingValues.stream().map(this::elementAsString).collect(Collectors.joining(", "));
callback.accept(Collections.singleton(getDataMiningStringMessages()
@@ -457,4 +475,29 @@ public class DimensionFilterSelectionProvider extends AbstractDataMiningComponen
}
@Override
public void parameterAdded(DataMiningReportDTO report, FilterDimensionParameter parameter) {
// we don't care about new parameters here; a user has to pick it for binding this dimension filter to it
}
@Override
public void parameterRemoved(DataMiningReportDTO report, FilterDimensionParameter parameter) {
if (parameter == this.parameter) {
unbindFromParameter(parameter);
}
}
private void unbindFromParameter(FilterDimensionParameter parameter) {
parameter.removeParameterModelListener(this);
reportParameterBindings.removeParameterBinding(new FilterDimensionIdentifier(retrieverLevel, dimension));
this.parameter = null; // unbind this dimension filter;
}
@Override
public void parameterValueChanged(FilterDimensionParameter parameter, Iterable<? extends Serializable> oldValues) {
selectionModel.clear();
for (final Serializable newValue : parameter.getValues()) {
selectionModel.setSelected(newValue, true);
}
}
}
@@ -48,6 +48,7 @@ import com.google.gwt.view.client.SelectionChangeEvent;
import com.sap.sse.common.Util;
import com.sap.sse.common.settings.SerializableSettings;
import com.sap.sse.datamining.shared.DataMiningSession;
import com.sap.sse.datamining.shared.data.ReportParameterToDimensionFilterBindings;
import com.sap.sse.datamining.shared.dto.StatisticQueryDefinitionDTO;
import com.sap.sse.datamining.shared.impl.dto.DataRetrieverChainDefinitionDTO;
import com.sap.sse.datamining.shared.impl.dto.DataRetrieverLevelDTO;
@@ -59,6 +60,7 @@ import com.sap.sse.datamining.ui.client.DataRetrieverChainDefinitionProvider;
import com.sap.sse.datamining.ui.client.FilterSelectionChangedListener;
import com.sap.sse.datamining.ui.client.FilterSelectionPresenter;
import com.sap.sse.datamining.ui.client.FilterSelectionProvider;
import com.sap.sse.datamining.ui.client.ReportProvider;
import com.sap.sse.datamining.ui.client.StringMessages;
import com.sap.sse.datamining.ui.client.presentation.PlainFilterSelectionPresenter;
import com.sap.sse.datamining.ui.client.resources.DataMiningDataGridResources;
@@ -131,14 +133,20 @@ public class HierarchicalDimensionListFilterSelectionProvider extends AbstractDa
private HashMap<DataRetrieverLevelDTO, HashMap<FunctionDTO, HashSet<? extends Serializable>>> selectionToBeApplied;
private Consumer<Iterable<String>> selectionCallback;
private final ReportProvider reportProvider;
private final ReportParameterToDimensionFilterBindings reportParameterBindings;
public HierarchicalDimensionListFilterSelectionProvider(Component<?> parent, ComponentContext<?> context,
DataMiningSession session, DataMiningServiceAsync dataMiningService, ErrorReporter errorReporter,
DataRetrieverChainDefinitionProvider retrieverChainProvider) {
DataRetrieverChainDefinitionProvider retrieverChainProvider, ReportProvider reportProvider,
ReportParameterToDimensionFilterBindings reportParameterBindings) {
super(parent, context);
this.session = session;
this.dataMiningService = dataMiningService;
this.errorReporter = errorReporter;
this.retrieverChainProvider = retrieverChainProvider;
this.reportProvider = reportProvider;
this.reportParameterBindings = reportParameterBindings;
retrieverChainProvider.addDataRetrieverChainDefinitionChangedListener(this);
listeners = new HashSet<>();
isAwaitingReload = false;
@@ -445,7 +453,8 @@ public class HierarchicalDimensionListFilterSelectionProvider extends AbstractDa
private DimensionFilterSelectionProvider addDimensionFilterSelectionProvider(final DimensionWithContext dimension) {
final DimensionFilterSelectionProvider selectionProvider = new DimensionFilterSelectionProvider(this, getComponentContext(),
dataMiningService, errorReporter, session, retrieverChainProvider, this, dimension.getRetrieverLevel(), dimension.getDimension());
dataMiningService, errorReporter, session, retrieverChainProvider, this, dimension.getRetrieverLevel(), dimension.getDimension(),
reportParameterBindings, reportProvider);
selectionProvider.addListener(() -> filterSelectionChanged(dimension));
dimensionFilterSelectionProviders.put(dimension, selectionProvider);
DimensionWithContext nextDimension = null;
@@ -606,7 +615,6 @@ public class HierarchicalDimensionListFilterSelectionProvider extends AbstractDa
}
private static class DimensionWithContext implements Comparable<DimensionWithContext> {
private final FunctionDTO dimension;
private final DataRetrieverLevelDTO retrieverLevel;
private Collection<String> matchingStrings;
@@ -671,7 +679,6 @@ public class HierarchicalDimensionListFilterSelectionProvider extends AbstractDa
return false;
return true;
}
}
/**
@@ -34,9 +34,13 @@ import com.google.gwt.user.client.ui.ValueListBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sse.common.Util;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.common.settings.SerializableSettings;
import com.sap.sse.datamining.shared.DataMiningSession;
import com.sap.sse.datamining.shared.GroupKey;
import com.sap.sse.datamining.shared.data.ReportParameterToDimensionFilterBindings;
import com.sap.sse.datamining.shared.dto.DataMiningReportDTO;
import com.sap.sse.datamining.shared.dto.FilterDimensionParameter;
import com.sap.sse.datamining.shared.dto.StatisticQueryDefinitionDTO;
import com.sap.sse.datamining.shared.impl.GenericGroupKey;
import com.sap.sse.datamining.shared.impl.dto.AggregationProcessorDefinitionDTO;
@@ -53,6 +57,7 @@ import com.sap.sse.datamining.ui.client.FilterSelectionChangedListener;
import com.sap.sse.datamining.ui.client.FilterSelectionProvider;
import com.sap.sse.datamining.ui.client.GroupingChangedListener;
import com.sap.sse.datamining.ui.client.GroupingProvider;
import com.sap.sse.datamining.ui.client.ReportProvider;
import com.sap.sse.datamining.ui.client.StatisticChangedListener;
import com.sap.sse.datamining.ui.client.StatisticProvider;
import com.sap.sse.datamining.ui.client.StringMessages;
@@ -106,11 +111,26 @@ public class QueryDefinitionProviderWithControls extends AbstractQueryDefinition
private final Panel applyQueryBusyIndicator;
private boolean queryDefinitionChanged;
/**
* Maintains the UI state regarding the binding of {@link FilterDimensionParameter report parameters} to dimension
* filters. Within this editor, users can bind / unbind dimensions to / from parameters from a
* {@link DataMiningReportDTO}. These bindings cannot be updated into the report as they occur in the UI because no
* {@link StatisticQueryDefinitionDTO} object will exist until one of the {@link #getQueryDefinition()} or
* {@link #getQueryDefinitionAndReportParameterBinding()} methods are invoked, which is when a new query object is
* created from the UI state.
* <p>
*
* A copy of these parameter bindings will be returned by {@link #getQueryDefinitionAndReportParameterBinding()}
* together with the query so that the current report can be updated from it. See also
* {@link DataMiningReportDTO#replaceQueryDefinition(StatisticQueryDefinitionDTO, ModifiableStatisticQueryDefinitionDTO, ReportParameterToDimensionFilterBindings)}.
*/
private ReportParameterToDimensionFilterBindings reportParameterBindings;
public QueryDefinitionProviderWithControls(Component<?> parent, ComponentContext<?> context,
DataMiningSession session, DataMiningServiceAsync dataMiningService, ErrorReporter errorReporter,
DataMiningSettingsControl settingsControl, DataMiningSettingsInfoManager settingsManager,
Consumer<StatisticQueryDefinitionDTO> queryRunner) {
DataMiningSession session, DataMiningServiceAsync dataMiningService, ReportProvider reportProvider,
ErrorReporter errorReporter, DataMiningSettingsControl settingsControl,
DataMiningSettingsInfoManager settingsManager, Consumer<Pair<ModifiableStatisticQueryDefinitionDTO, ReportParameterToDimensionFilterBindings>> queryRunner) {
super(parent, context, dataMiningService, errorReporter);
providerListener = new ProviderListener();
mainPanel = new LayoutPanel();
@@ -163,7 +183,7 @@ public class QueryDefinitionProviderWithControls extends AbstractQueryDefinition
groupingProvider.addGroupingChangedListener(providerListener);
groupingProvider.getEntryWidget().addStyleName("dataMiningMarginBase");
filterSelectionProvider = new HierarchicalDimensionListFilterSelectionProvider(parent, context, session,
dataMiningService, errorReporter, statisticProvider);
dataMiningService, errorReporter, statisticProvider, reportProvider, reportParameterBindings);
filterSelectionProvider.addSelectionChangedListener(providerListener);
filterSelectionProvider.getEntryWidget().addStyleName("dataMiningBorderTop");
filterSplitPanel = new SplitLayoutPanel(SplitterSize);
@@ -302,7 +322,7 @@ public class QueryDefinitionProviderWithControls extends AbstractQueryDefinition
}
@Override
public StatisticQueryDefinitionDTO getQueryDefinition() {
public ModifiableStatisticQueryDefinitionDTO getQueryDefinition() {
ModifiableStatisticQueryDefinitionDTO queryDTO = new ModifiableStatisticQueryDefinitionDTO(
LocaleInfo.getCurrentLocale().getLocaleName(), statisticProvider.getExtractionFunction(),
statisticProvider.getAggregatorDefinition(), statisticProvider.getDataRetrieverChainDefinition());
@@ -319,6 +339,11 @@ public class QueryDefinitionProviderWithControls extends AbstractQueryDefinition
return queryDTO;
}
@Override
public Pair<ModifiableStatisticQueryDefinitionDTO, ReportParameterToDimensionFilterBindings> getQueryDefinitionAndReportParameterBinding() {
return new Pair<>(getQueryDefinition(), new ReportParameterToDimensionFilterBindings(reportParameterBindings));
}
@Override
public void applyQueryDefinition(StatisticQueryDefinitionDTO queryDefinition) {
applyQueryDefinition(queryDefinition, settings.getChangeLossStrategy());
@@ -357,7 +382,7 @@ public class QueryDefinitionProviderWithControls extends AbstractQueryDefinition
* its constituents to the various elements of this UI widget. A new query definition will be produced from this
* editor UI in {@link #getQueryDefinition()}.
*/
private void setQueryDefinition(StatisticQueryDefinitionDTO queryDefinition) {
private void setQueryDefinition(StatisticQueryDefinitionDTO queryDefinition) { // TODO bug4789: deliver parameter bindings and establish in local temporary model of type ReportParameterToDimensionFilterBindings
final Set<ApplyCallback> callbacks = new HashSet<>();
final Collection<String> errorMessages = new ArrayList<>();
final String retrieverChainName = queryDefinition.getDataRetrieverChainDefinition().getName();