mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-11-04 01:59:35 +00:00
Implemented the dimension values retrieval mechanism for the selection
tables
This commit is contained in:
1 parent
9e2dde79b4
commit
3e6df27ef1
11 files changed
+247
-56
No files matched your search
+65
-12
@@ -1,12 +1,19 @@
|
||||
package com.sap.sailing.datamining.factories;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.sap.sailing.datamining.data.HasGPSFixContext;
|
||||
import com.sap.sailing.datamining.data.HasTrackedLegContext;
|
||||
import com.sap.sailing.datamining.data.HasTrackedLegOfCompetitorContext;
|
||||
import com.sap.sailing.datamining.data.HasTrackedRaceContext;
|
||||
import com.sap.sailing.server.RacingEventService;
|
||||
import com.sap.sse.datamining.Query;
|
||||
import com.sap.sse.datamining.components.Processor;
|
||||
import com.sap.sse.datamining.factories.ProcessorFactory;
|
||||
@@ -24,51 +31,97 @@ public final class DataMiningFactory {
|
||||
private DataMiningFactory() {
|
||||
}
|
||||
|
||||
public static <DataSourceType, ElementType> Query<Double> createQuery(DataSourceType dataSource, final QueryDefinition queryDefinition, final FunctionProvider functionProvider) {
|
||||
return new ProcessorQuery<Double, DataSourceType>(DataMiningActivator.getExecutor(), dataSource,
|
||||
public static <ElementType> Query<Double> createQuery(RacingEventService dataSource, final QueryDefinition queryDefinition, final FunctionProvider functionProvider) {
|
||||
return new ProcessorQuery<Double, RacingEventService>(DataMiningActivator.getExecutor(), dataSource,
|
||||
DataMiningActivator.getStringMessages(), DataMiningStringMessages.Util.getLocaleFor(queryDefinition.getLocaleInfoName())) {
|
||||
|
||||
@Override
|
||||
protected Processor<DataSourceType> createFirstProcessor() {
|
||||
protected Processor<RacingEventService> createFirstProcessor() {
|
||||
Processor<GroupedDataEntry<Double>> aggregationProcessor = ProcessorFactory.createAggregationProcessor(/*query*/ this, queryDefinition.getAggregatorType());
|
||||
|
||||
@SuppressWarnings("unchecked") // TODO Clean, after the deprecated components have been removed
|
||||
Function<Double> extractionFunction = (Function<Double>) functionProvider.getFunctionForDTO(queryDefinition.getStatisticToCalculate());
|
||||
Processor<GroupedDataEntry<ElementType>> extractionProcessor = ProcessorFactory.createExtractionProcessor(aggregationProcessor, extractionFunction);
|
||||
|
||||
List<Function<?>> dimensionsToGroupBy = getDimensionsToGroupBy(queryDefinition, functionProvider);
|
||||
List<Function<?>> dimensionsToGroupBy = convertDTOsToFunctions(queryDefinition.getDimensionsToGroupBy(), functionProvider);
|
||||
Processor<ElementType> groupingProcessor = ProcessorFactory.createGroupingProcessor(extractionProcessor, dimensionsToGroupBy);
|
||||
|
||||
SailingDataRetrievalLevels dataRetrievalLevel = calculateDataRetrievalLevel(extractionFunction);
|
||||
Processor<DataSourceType> firstRetrievalProcessor = SailingDataRetrieverFactory.createRetrievalProcessorChain(dataRetrievalLevel, groupingProcessor, queryDefinition.getFilterSelection(), functionProvider);
|
||||
Processor<RacingEventService> firstRetrievalProcessor = SailingDataRetrieverFactory.createRetrievalProcessorChain(dataRetrievalLevel, groupingProcessor, queryDefinition.getFilterSelection(), functionProvider);
|
||||
return firstRetrievalProcessor;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
private static List<Function<?>> getDimensionsToGroupBy(QueryDefinition queryDefinition, FunctionProvider functionProvider) {
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Query<Set<Object>> createDimensionValuesQuery(RacingEventService dataSource, final Collection<FunctionDTO> dimensionDTOs, final FunctionProvider functionProvider) {
|
||||
return new ProcessorQuery<Set<Object>, RacingEventService>(DataMiningActivator.getExecutor(), dataSource) {
|
||||
@Override
|
||||
protected Processor<RacingEventService> createFirstProcessor() {
|
||||
Processor<GroupedDataEntry<Object>> valueCollector = ProcessorFactory.createGroupedDataCollectingAsSetProcessor(/*query*/ this);
|
||||
|
||||
Collection<Function<?>> dimensions = convertDTOsToFunctions(dimensionDTOs, functionProvider);
|
||||
Map<SailingDataRetrievalLevels, Collection<Function<?>>> dimensionsMappedByRetrievalLevel = mapFunctionsByRetrievalLevel(dimensions);
|
||||
SailingDataRetrievalLevels deepestRetrievalLevel = getDeepestRetrievalLevel(dimensionsMappedByRetrievalLevel.keySet());
|
||||
|
||||
Processor<?> retrievalProcessor = null;
|
||||
for (int i = deepestRetrievalLevel.ordinal(); i >= 0; i--) {
|
||||
SailingDataRetrievalLevels retrievalLevel = SailingDataRetrievalLevels.values()[i];
|
||||
|
||||
Collection<Function<?>> dimensionsForRetrievalLevel = dimensionsMappedByRetrievalLevel.containsKey(retrievalLevel) ? dimensionsMappedByRetrievalLevel.get(retrievalLevel) : new ArrayList<Function<?>>();
|
||||
Collection<Processor<?>> retrievalResultReceivers = ProcessorFactory.createGroupingExtractorsForDimensions(valueCollector, dimensionsForRetrievalLevel);
|
||||
if (retrievalProcessor != null) {
|
||||
retrievalResultReceivers.add(retrievalProcessor);
|
||||
}
|
||||
|
||||
retrievalProcessor = SailingDataRetrieverFactory.createRetrievalProcessorWithoutFilter(retrievalLevel, retrievalResultReceivers);
|
||||
}
|
||||
|
||||
// A retrieval processor created this way results always in a Processor<RacingEventService>
|
||||
return (Processor<RacingEventService>) retrievalProcessor;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static List<Function<?>> convertDTOsToFunctions(Collection<FunctionDTO> functionDTOs, FunctionProvider functionProvider) {
|
||||
List<Function<?>> dimensionsToGroupBy = new ArrayList<>();
|
||||
for (FunctionDTO functionDTO : queryDefinition.getDimensionsToGroupBy()) {
|
||||
for (FunctionDTO functionDTO : functionDTOs) {
|
||||
dimensionsToGroupBy.add(functionProvider.getFunctionForDTO(functionDTO));
|
||||
}
|
||||
return dimensionsToGroupBy;
|
||||
}
|
||||
|
||||
private static SailingDataRetrievalLevels calculateDataRetrievalLevel(Function<Double> extractionFunction) {
|
||||
if (extractionFunction.getDeclaringType().equals(HasTrackedRaceContext.class)) {
|
||||
private static Map<SailingDataRetrievalLevels, Collection<Function<?>>> mapFunctionsByRetrievalLevel(Collection<Function<?>> functions) {
|
||||
Map<SailingDataRetrievalLevels, Collection<Function<?>>> mappedFunctions = new HashMap<>();
|
||||
for (Function<?> function : functions) {
|
||||
SailingDataRetrievalLevels retrievalLevel = calculateDataRetrievalLevel(function);
|
||||
if (!mappedFunctions.containsKey(retrievalLevel)) {
|
||||
mappedFunctions.put(retrievalLevel, new HashSet<Function<?>>());
|
||||
}
|
||||
mappedFunctions.get(retrievalLevel).add(function);
|
||||
}
|
||||
return mappedFunctions;
|
||||
}
|
||||
|
||||
private static SailingDataRetrievalLevels calculateDataRetrievalLevel(Function<?> function) {
|
||||
if (function.getDeclaringType().equals(HasTrackedRaceContext.class)) {
|
||||
return SailingDataRetrievalLevels.TrackedRace;
|
||||
}
|
||||
if (extractionFunction.getDeclaringType().equals(HasTrackedLegContext.class)) {
|
||||
if (function.getDeclaringType().equals(HasTrackedLegContext.class)) {
|
||||
return SailingDataRetrievalLevels.TrackedLeg;
|
||||
}
|
||||
if (extractionFunction.getDeclaringType().equals(HasTrackedLegOfCompetitorContext.class)) {
|
||||
if (function.getDeclaringType().equals(HasTrackedLegOfCompetitorContext.class)) {
|
||||
return SailingDataRetrievalLevels.TrackedLegOfCompetitor;
|
||||
}
|
||||
if (extractionFunction.getDeclaringType().equals(HasGPSFixContext.class)) {
|
||||
if (function.getDeclaringType().equals(HasGPSFixContext.class)) {
|
||||
return SailingDataRetrievalLevels.GPSFix;
|
||||
}
|
||||
return SailingDataRetrievalLevels.GPSFix;
|
||||
}
|
||||
|
||||
private static SailingDataRetrievalLevels getDeepestRetrievalLevel(Collection<SailingDataRetrievalLevels> retrievalLevels) {
|
||||
return Collections.max(retrievalLevels);
|
||||
}
|
||||
|
||||
}
|
||||
+37
-2
@@ -20,6 +20,7 @@ import com.sap.sailing.datamining.impl.components.TrackedLegOfCompetitorFilterin
|
||||
import com.sap.sailing.datamining.impl.components.TrackedRaceFilteringRetrievalProcessor;
|
||||
import com.sap.sailing.domain.leaderboard.LeaderboardGroup;
|
||||
import com.sap.sailing.domain.leaderboard.RegattaLeaderboard;
|
||||
import com.sap.sailing.server.RacingEventService;
|
||||
import com.sap.sse.datamining.components.FilterCriteria;
|
||||
import com.sap.sse.datamining.components.Processor;
|
||||
import com.sap.sse.datamining.functions.Function;
|
||||
@@ -44,12 +45,12 @@ public final class SailingDataRetrieverFactory {
|
||||
* @return The first processor of the retrieval chain.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <DataSourceType, ElementType> Processor<DataSourceType> createRetrievalProcessorChain(SailingDataRetrievalLevels dataRetrievalLevel, Processor<ElementType> groupingProcessor, Map<FunctionDTO, Iterable<? extends Serializable>> filterSelection, FunctionProvider functionProvider) {
|
||||
public static <ElementType> Processor<RacingEventService> createRetrievalProcessorChain(SailingDataRetrievalLevels dataRetrievalLevel, Processor<ElementType> groupingProcessor, Map<FunctionDTO, Iterable<? extends Serializable>> filterSelection, FunctionProvider functionProvider) {
|
||||
Processor<?> resultReceiver = groupingProcessor;
|
||||
for (int i = dataRetrievalLevel.ordinal(); i >= 0; i--) {
|
||||
resultReceiver = createDataRetrieverFor(SailingDataRetrievalLevels.values()[i], resultReceiver, filterSelection, functionProvider);
|
||||
}
|
||||
return (Processor<DataSourceType>) resultReceiver;
|
||||
return (Processor<RacingEventService>) resultReceiver;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -103,4 +104,38 @@ public final class SailingDataRetrieverFactory {
|
||||
return criteria != null ? criteria : new NonFilteringFilterCriteria<BaseDataType>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a retrieval processor without filter for the given retrieval level and result receivers.<br>
|
||||
* The input type of the result receivers has to match the result type of the created retrieval processor for the given retrievel level or a {@link ClassCastException} can be thrown.
|
||||
* For example, if the retrieval Level is {@link SailingDataRetrievalLevels#TrackedRace} the input must be {@link HasTrackedRaceContext}.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Processor<?> createRetrievalProcessorWithoutFilter(SailingDataRetrievalLevels retrievalLevel,
|
||||
Collection<Processor<?>> retrievalResultReceivers) throws ClassCastException {
|
||||
ThreadPoolExecutor executor = DataMiningActivator.getExecutor();
|
||||
|
||||
switch (retrievalLevel) {
|
||||
case GPSFix:
|
||||
Collection<Processor<HasGPSFixContext>> gpsFixSpecificResultReceivers = (Collection<Processor<HasGPSFixContext>>)(Collection<?>) retrievalResultReceivers;
|
||||
return new GPSFixRetrievalProcessor(executor, gpsFixSpecificResultReceivers);
|
||||
case LeaderboardGroup:
|
||||
Collection<Processor<LeaderboardGroup>> leaderboardGroupSpecificResultReceivers = (Collection<Processor<LeaderboardGroup>>)(Collection<?>) retrievalResultReceivers;
|
||||
return new LeaderboardGroupRetrievalProcessor(executor, leaderboardGroupSpecificResultReceivers);
|
||||
case RegattaLeaderboard:
|
||||
Collection<Processor<RegattaLeaderboard>> regattaLeaderboardSpecificResultReceivers = (Collection<Processor<RegattaLeaderboard>>)(Collection<?>) retrievalResultReceivers;
|
||||
return new RegattaLeaderboardFilteringRetrievalProcessor(executor, regattaLeaderboardSpecificResultReceivers, new NonFilteringFilterCriteria<RegattaLeaderboard>());
|
||||
case TrackedLeg:
|
||||
Collection<Processor<HasTrackedLegContext>> trackedLegSpecificResultReceivers = (Collection<Processor<HasTrackedLegContext>>)(Collection<?>) retrievalResultReceivers;
|
||||
return new TrackedLegFilteringRetrievalProcessor(executor, trackedLegSpecificResultReceivers, new NonFilteringFilterCriteria<HasTrackedLegContext>());
|
||||
case TrackedLegOfCompetitor:
|
||||
Collection<Processor<HasTrackedLegOfCompetitorContext>> trackedLegOfCompetitorSpecificResultReceivers = (Collection<Processor<HasTrackedLegOfCompetitorContext>>)(Collection<?>) retrievalResultReceivers;
|
||||
return new TrackedLegOfCompetitorFilteringRetrievalProcessor(executor, trackedLegOfCompetitorSpecificResultReceivers, new NonFilteringFilterCriteria<HasTrackedLegOfCompetitorContext>());
|
||||
case TrackedRace:
|
||||
Collection<Processor<HasTrackedRaceContext>> trackedRaceSpecificResultReceivers = (Collection<Processor<HasTrackedRaceContext>>)(Collection<?>) retrievalResultReceivers;
|
||||
return new TrackedRaceFilteringRetrievalProcessor(executor, trackedRaceSpecificResultReceivers, new NonFilteringFilterCriteria<HasTrackedRaceContext>());
|
||||
}
|
||||
throw new IllegalArgumentException("No data retriever implemented for the given data retrieval level '"
|
||||
+ retrievalLevel + "'");
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -16,7 +16,7 @@ public interface DataMiningService extends RemoteService {
|
||||
|
||||
Collection<FunctionDTO> getDimensionsFor(FunctionDTO statisticToCalculate, String localeInfoName);
|
||||
|
||||
QueryResult<Set<Object>> getDimensionValuesFor(Collection<FunctionDTO> dimensions);
|
||||
QueryResult<Set<Object>> getDimensionValuesFor(Collection<FunctionDTO> dimensions) throws Exception;
|
||||
|
||||
<ResultType extends Number> QueryResult<ResultType> runQuery(QueryDefinition queryDefinition) throws Exception;
|
||||
|
||||
|
||||
+42
-31
@@ -22,7 +22,6 @@ import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.ui.HorizontalPanel;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.google.gwt.view.client.SelectionChangeEvent;
|
||||
import com.google.gwt.view.client.SelectionChangeEvent.Handler;
|
||||
import com.sap.sailing.gwt.ui.client.ErrorReporter;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.client.shared.components.SettingsDialogComponent;
|
||||
@@ -38,6 +37,7 @@ import com.sap.sse.datamining.shared.QueryDefinition;
|
||||
import com.sap.sse.datamining.shared.QueryResult;
|
||||
import com.sap.sse.datamining.shared.components.AggregatorType;
|
||||
import com.sap.sse.datamining.shared.dto.FunctionDTO;
|
||||
import com.sap.sse.datamining.shared.impl.GenericGroupKey;
|
||||
|
||||
public class RefreshingSelectionTablesPanel implements SelectionProvider<RefreshingSelectionTablesSettings>,
|
||||
StatisticChangedListener {
|
||||
@@ -55,7 +55,7 @@ public class RefreshingSelectionTablesPanel implements SelectionProvider<Refresh
|
||||
|
||||
private RefreshingSelectionTablesSettings settings;
|
||||
private Timer timer;
|
||||
private Map<FunctionDTO, SelectionTable<?>> tablesMappedByDimension;
|
||||
private Map<GenericGroupKey<FunctionDTO>, SelectionTable<?>> tablesMappedByDimensionAsKeys;
|
||||
private Set<SelectionChangedListener> listeners;
|
||||
|
||||
private FunctionDTO currentStatisticToCalculate;
|
||||
@@ -69,7 +69,7 @@ public class RefreshingSelectionTablesPanel implements SelectionProvider<Refresh
|
||||
listeners = new HashSet<SelectionChangedListener>();
|
||||
currentStatisticToCalculate = null;
|
||||
|
||||
tablesMappedByDimension = new HashMap<FunctionDTO, SelectionTable<?>>();
|
||||
tablesMappedByDimensionAsKeys = new HashMap<GenericGroupKey<FunctionDTO>, SelectionTable<?>>();
|
||||
|
||||
tablesPanel = new HorizontalPanel();
|
||||
|
||||
@@ -93,7 +93,6 @@ public class RefreshingSelectionTablesPanel implements SelectionProvider<Refresh
|
||||
}
|
||||
});
|
||||
|
||||
updateTables();
|
||||
doLayout(Window.getClientWidth(), Window.getClientHeight());
|
||||
statisticProvider.addStatisticChangedListener(this);
|
||||
}
|
||||
@@ -114,24 +113,41 @@ public class RefreshingSelectionTablesPanel implements SelectionProvider<Refresh
|
||||
}
|
||||
@Override
|
||||
public void onSuccess(Collection<FunctionDTO> dimensions) {
|
||||
Collection<FunctionDTO> dimensionsToBeRemoved = new HashSet<>(tablesMappedByDimension.keySet());
|
||||
dimensionsToBeRemoved.removeAll(dimensions);
|
||||
for (FunctionDTO dimensionToBeRemoved : dimensionsToBeRemoved) {
|
||||
tablesMappedByDimension.remove(dimensionToBeRemoved);
|
||||
Collection<GenericGroupKey<FunctionDTO>> dimensionsAsKeys = new HashSet<>();
|
||||
for (FunctionDTO dimension : dimensions) {
|
||||
dimensionsAsKeys.add(new GenericGroupKey<FunctionDTO>(dimension));
|
||||
}
|
||||
|
||||
for (FunctionDTO dimension : dimensions) {
|
||||
if (!tablesMappedByDimension.containsKey(dimension)) {
|
||||
SelectionTable<?> table = new SelectionTable<>(dimension);
|
||||
tablesMappedByDimension.put(table.getDimension(), table);
|
||||
Collection<GenericGroupKey<FunctionDTO>> dimensionTablesToBeRemoved = new HashSet<>(tablesMappedByDimensionAsKeys.keySet());
|
||||
dimensionTablesToBeRemoved.removeAll(dimensionsAsKeys);
|
||||
for (GenericGroupKey<FunctionDTO> dimensionToBeRemoved : dimensionTablesToBeRemoved) {
|
||||
tablesMappedByDimensionAsKeys.remove(dimensionToBeRemoved);
|
||||
}
|
||||
|
||||
for (GenericGroupKey<FunctionDTO> dimensionAsKey : dimensionsAsKeys) {
|
||||
if (!tablesMappedByDimensionAsKeys.containsKey(dimensionAsKey)) {
|
||||
SelectionTable<?> table = new SelectionTable<>(dimensionAsKey.getValue());
|
||||
table.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
|
||||
@Override
|
||||
public void onSelectionChange(SelectionChangeEvent event) {
|
||||
notifySelectionChanged();
|
||||
}
|
||||
});
|
||||
|
||||
tablesMappedByDimensionAsKeys.put(dimensionAsKey, table);
|
||||
}
|
||||
}
|
||||
|
||||
List<FunctionDTO> sortedDimensions = new ArrayList<>(tablesMappedByDimension.keySet());
|
||||
Collections.sort(sortedDimensions);
|
||||
List<GenericGroupKey<FunctionDTO>> sortedDimensions = new ArrayList<>(tablesMappedByDimensionAsKeys.keySet());
|
||||
Collections.sort(sortedDimensions, new Comparator<GenericGroupKey<FunctionDTO>>() {
|
||||
@Override
|
||||
public int compare(GenericGroupKey<FunctionDTO> k1, GenericGroupKey<FunctionDTO> k2) {
|
||||
return k1.getValue().compareTo(k2.getValue());
|
||||
}
|
||||
});
|
||||
tablesPanel.clear();
|
||||
for (FunctionDTO dimension : sortedDimensions) {
|
||||
tablesPanel.add(tablesMappedByDimension.get(dimension));
|
||||
for (GenericGroupKey<FunctionDTO> dimension : sortedDimensions) {
|
||||
tablesPanel.add(tablesMappedByDimensionAsKeys.get(dimension));
|
||||
}
|
||||
|
||||
updateTables();
|
||||
@@ -147,7 +163,7 @@ public class RefreshingSelectionTablesPanel implements SelectionProvider<Refresh
|
||||
tablesPanel.setWidth(absoluteWidth + "px");
|
||||
tablesPanel.setHeight(absoluteHeight + "px");
|
||||
|
||||
Collection<SelectionTable<?>> tables = tablesMappedByDimension.values();
|
||||
Collection<SelectionTable<?>> tables = tablesMappedByDimensionAsKeys.values();
|
||||
for (SelectionTable<?> table : tables) {
|
||||
table.setWidth((absoluteWidth / tables.size()) + "px");
|
||||
table.setHeight(absoluteHeight + "px");
|
||||
@@ -155,8 +171,11 @@ public class RefreshingSelectionTablesPanel implements SelectionProvider<Refresh
|
||||
}
|
||||
|
||||
private void updateTables() {
|
||||
//It's necessary to create a new Collection for the dimensions, since using the key set directly results in a serialization error
|
||||
Collection<FunctionDTO> dimensions = new HashSet<>(tablesMappedByDimension.keySet());
|
||||
Collection<FunctionDTO> dimensions = new HashSet<>();
|
||||
for (GenericGroupKey<FunctionDTO> dimensionAsKey : tablesMappedByDimensionAsKeys.keySet()) {
|
||||
dimensions.add(dimensionAsKey.getValue());
|
||||
}
|
||||
|
||||
dataMiningService.getDimensionValuesFor(dimensions, new AsyncCallback<QueryResult<Set<Object>>>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
@@ -173,7 +192,7 @@ public class RefreshingSelectionTablesPanel implements SelectionProvider<Refresh
|
||||
return o1.toString().compareTo(o2.toString());
|
||||
}
|
||||
});
|
||||
boolean currentTableContentChanged = tablesMappedByDimension.get(resultEntry.getKey()).updateContent(sortedDimensionValues);
|
||||
boolean currentTableContentChanged = tablesMappedByDimensionAsKeys.get(resultEntry.getKey()).updateContent(sortedDimensionValues);
|
||||
if (!tableContentChanged) {
|
||||
tableContentChanged = currentTableContentChanged;
|
||||
}
|
||||
@@ -194,14 +213,6 @@ public class RefreshingSelectionTablesPanel implements SelectionProvider<Refresh
|
||||
@Override
|
||||
public void addSelectionChangedListener(SelectionChangedListener listener) {
|
||||
listeners.add(listener);
|
||||
for (SelectionTable<?> table : tablesMappedByDimension.values()) {
|
||||
table.addSelectionChangeHandler(new Handler() {
|
||||
@Override
|
||||
public void onSelectionChange(SelectionChangeEvent event) {
|
||||
notifySelectionChanged();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void notifySelectionChanged() {
|
||||
@@ -213,7 +224,7 @@ public class RefreshingSelectionTablesPanel implements SelectionProvider<Refresh
|
||||
@Override
|
||||
public Map<FunctionDTO, Collection<? extends Serializable>> getFilterSelection() {
|
||||
Map<FunctionDTO, Collection<? extends Serializable>> selection = new HashMap<>();
|
||||
for (SelectionTable<?> table : tablesMappedByDimension.values()) {
|
||||
for (SelectionTable<?> table : tablesMappedByDimensionAsKeys.values()) {
|
||||
Collection<? extends Serializable> specificSelection = table.getSelectionAsValues();
|
||||
if (!specificSelection.isEmpty()) {
|
||||
selection.put(table.getDimension(), specificSelection);
|
||||
@@ -225,14 +236,14 @@ public class RefreshingSelectionTablesPanel implements SelectionProvider<Refresh
|
||||
@Override
|
||||
public void applySelection(QueryDefinition queryDefinition) {
|
||||
for (Entry<FunctionDTO, Iterable<? extends Serializable>> selectionEntry : queryDefinition.getFilterSelection().entrySet()) {
|
||||
SelectionTable<?> selectionTable = tablesMappedByDimension.get(selectionEntry.getKey());
|
||||
SelectionTable<?> selectionTable = tablesMappedByDimensionAsKeys.get(selectionEntry.getKey());
|
||||
selectionTable.setSelection((Iterable<?>) selectionEntry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearSelection() {
|
||||
for (SelectionTable<?> table : tablesMappedByDimension.values()) {
|
||||
for (SelectionTable<?> table : tablesMappedByDimensionAsKeys.values()) {
|
||||
table.clearSelection();
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -90,9 +90,9 @@ public class DataMiningServiceImpl extends RemoteServiceServlet implements DataM
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryResult<Set<Object>> getDimensionValuesFor(Collection<FunctionDTO> dimensions) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
public QueryResult<Set<Object>> getDimensionValuesFor(Collection<FunctionDTO> dimensions) throws Exception {
|
||||
Query<Set<Object>> dimensionValuesQuery = DataMiningFactory.createDimensionValuesQuery(getRacingEventService(), dimensions, getDataMiningServer().getFunctionProvider());
|
||||
return dimensionValuesQuery.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+4
@@ -17,6 +17,10 @@ public class GenericGroupKey<T> extends AbstractGroupKey {
|
||||
public GenericGroupKey(T value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public T getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSubKey() {
|
||||
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
package com.sap.sse.datamining.shared.impl;
|
||||
|
||||
import com.sap.sse.datamining.shared.AdditionalResultData;
|
||||
import com.sap.sse.datamining.shared.Unit;
|
||||
|
||||
public class NullAdditionalResultData implements AdditionalResultData {
|
||||
private static final long serialVersionUID = -8129840449690994767L;
|
||||
|
||||
@Override
|
||||
public int getRetrievedDataAmount() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getCalculationTimeInSeconds() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getResultSignifier() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Unit getUnit() {
|
||||
return Unit.None;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getValueDecimals() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
+4
@@ -20,6 +20,10 @@ public class QueryResultImpl<AggregatedType> implements QueryResult<AggregatedTy
|
||||
@Deprecated
|
||||
QueryResultImpl() { }
|
||||
|
||||
public QueryResultImpl(Map<GroupKey, AggregatedType> results) {
|
||||
this(results, new NullAdditionalResultData());
|
||||
}
|
||||
|
||||
public QueryResultImpl(Map<GroupKey, AggregatedType> results, AdditionalResultData additionalData) {
|
||||
this.results = new HashMap<GroupKey, AggregatedType>(results);
|
||||
this.additionalData = additionalData;
|
||||
|
||||
+4
-5
@@ -6,7 +6,6 @@ import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
@@ -71,7 +70,7 @@ public class TestDimensionsValuesQuery {
|
||||
}
|
||||
|
||||
private Query<Set<Object>> createDimensionsValuesQuery() {
|
||||
return new ProcessorQuery<Set<Object>, Collection<Test_Regatta>>(ConcurrencyTestsUtil.getExecutor(), dataSource, ConcurrencyTestsUtil.getTestStringMessagesWithProductiveMessages(), Locale.ENGLISH) {
|
||||
return new ProcessorQuery<Set<Object>, Collection<Test_Regatta>>(ConcurrencyTestsUtil.getExecutor(), dataSource) {
|
||||
@Override
|
||||
protected Processor<Collection<Test_Regatta>> createFirstProcessor() {
|
||||
Collection<Processor<Map<GroupKey, Set<Object>>>> collectorResultReceivers = Arrays.asList(/*query*/ this.getResultReceiver());
|
||||
@@ -128,13 +127,13 @@ public class TestDimensionsValuesQuery {
|
||||
@SuppressWarnings("unchecked")
|
||||
private <DataType> Collection<Processor<DataType>> createGroupingExtractorsForDimensions(
|
||||
Collection<Processor<GroupedDataEntry<Object>>> extractionResultReceivers, Collection<Function<?>> dimensions) {
|
||||
Collection<Processor<DataType>> legGroupers = new ArrayList<>();
|
||||
Collection<Processor<DataType>> groupingExtractors = new ArrayList<>();
|
||||
for (Function<?> dimension : dimensions) {
|
||||
Processor<GroupedDataEntry<DataType>> dimensionValueExtractor = new ParallelGroupedElementsValueExtractionProcessor<DataType, Object>(ConcurrencyTestsUtil.getExecutor(), extractionResultReceivers, (Function<Object>) dimension);
|
||||
Processor<DataType> byDimensionGrouper = new ParallelByDimensionGroupingProcessor<>(ConcurrencyTestsUtil.getExecutor(), Arrays.asList(dimensionValueExtractor), dimension);
|
||||
legGroupers.add(byDimensionGrouper);
|
||||
groupingExtractors.add(byDimensionGrouper);
|
||||
}
|
||||
return legGroupers;
|
||||
return groupingExtractors;
|
||||
}
|
||||
|
||||
private Map<GroupKey, Set<Object>> buildExpectedResultData() {
|
||||
|
||||
+34
@@ -1,9 +1,11 @@
|
||||
package com.sap.sse.datamining.factories;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import com.sap.sse.datamining.components.Processor;
|
||||
@@ -11,8 +13,10 @@ import com.sap.sse.datamining.functions.Function;
|
||||
import com.sap.sse.datamining.impl.DataMiningActivator;
|
||||
import com.sap.sse.datamining.impl.ProcessorQuery;
|
||||
import com.sap.sse.datamining.impl.components.GroupedDataEntry;
|
||||
import com.sap.sse.datamining.impl.components.ParallelByDimensionGroupingProcessor;
|
||||
import com.sap.sse.datamining.impl.components.ParallelGroupedElementsValueExtractionProcessor;
|
||||
import com.sap.sse.datamining.impl.components.ParallelMultiDimensionsValueNestingGroupingProcessor;
|
||||
import com.sap.sse.datamining.impl.components.aggregators.ParallelGroupedDataCollectingAsSetProcessor;
|
||||
import com.sap.sse.datamining.impl.components.aggregators.ParallelGroupedDoubleDataAverageAggregationProcessor;
|
||||
import com.sap.sse.datamining.impl.components.aggregators.ParallelGroupedDoubleDataMedianAggregationProcessor;
|
||||
import com.sap.sse.datamining.impl.components.aggregators.ParallelGroupedDoubleDataSumAggregationProcessor;
|
||||
@@ -53,6 +57,16 @@ public class ProcessorFactory {
|
||||
throw new IllegalArgumentException("No aggregation processor implemented for the aggregation type '" + aggregatorType + "'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a collecting processor with the given ProcessorQuery as result receiver, that stores all received grouped
|
||||
* data in a Set.<br />
|
||||
* The {@link DataMiningActivator} will be used to get the missing objects for the construction (like the executor).
|
||||
*/
|
||||
public static Processor<GroupedDataEntry<Object>> createGroupedDataCollectingAsSetProcessor(ProcessorQuery<Set<Object>, ?> query) {
|
||||
Collection<Processor<Map<GroupKey, Set<Object>>>> resultReceivers = Arrays.asList(query.getResultReceiver());
|
||||
return new ParallelGroupedDataCollectingAsSetProcessor<>(DataMiningActivator.getExecutor(), resultReceivers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an extraction processor with the given aggregation processor as result receiver.<br />
|
||||
@@ -93,4 +107,24 @@ public class ProcessorFactory {
|
||||
return new ParallelMultiDimensionsValueNestingGroupingProcessor<>(DataMiningActivator.getExecutor(), resultReceivers, dimensionsToGroupBy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a dimension grouping processor followed by a function value extraction processor for each given dimension.<br>
|
||||
* The {@link DataMiningActivator} will be used to get the missing objects for the construction (like
|
||||
* the executor).
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <DataType> Collection<Processor<?>> createGroupingExtractorsForDimensions(
|
||||
Processor<GroupedDataEntry<Object>> valueCollector, Collection<Function<?>> dimensions) {
|
||||
Collection<Processor<GroupedDataEntry<Object>>> extractionResultReceivers = new ArrayList<>();
|
||||
extractionResultReceivers.add(valueCollector);
|
||||
|
||||
Collection<Processor<?>> groupingExtractors = new ArrayList<>();
|
||||
for (Function<?> dimension : dimensions) {
|
||||
Processor<GroupedDataEntry<DataType>> dimensionValueExtractor = new ParallelGroupedElementsValueExtractionProcessor<DataType, Object>(DataMiningActivator.getExecutor(), extractionResultReceivers, (Function<Object>) dimension);
|
||||
Processor<DataType> byDimensionGrouper = new ParallelByDimensionGroupingProcessor<>(DataMiningActivator.getExecutor(), Arrays.asList(dimensionValueExtractor), dimension);
|
||||
groupingExtractors.add(byDimensionGrouper);
|
||||
}
|
||||
return groupingExtractors;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import java.util.Map;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
@@ -39,7 +40,18 @@ public abstract class ProcessorQuery<AggregatedType, DataSourceType> implements
|
||||
private final Object monitorObject = new Object();
|
||||
private boolean workIsDone = false;
|
||||
private boolean processorTimedOut = false;
|
||||
|
||||
/**
|
||||
* Creates a query that returns a result without any additional data (like the calculation time or the retrieved data amount).<br>
|
||||
* This is useful for non user specific queries, like retrieving the dimension values.
|
||||
*/
|
||||
public ProcessorQuery(ThreadPoolExecutor executor, DataSourceType dataSource) {
|
||||
this(executor, dataSource, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a query that returns a result with additional data.
|
||||
*/
|
||||
public ProcessorQuery(Executor executor, DataSourceType dataSource, DataMiningStringMessages stringMessages, Locale locale) {
|
||||
this.executor = executor;
|
||||
this.dataSource = dataSource;
|
||||
@@ -49,7 +61,7 @@ public abstract class ProcessorQuery<AggregatedType, DataSourceType> implements
|
||||
resultReceiver = new ProcessResultReceiver();
|
||||
firstProcessor = createFirstProcessor();
|
||||
}
|
||||
|
||||
|
||||
protected abstract Processor<DataSourceType> createFirstProcessor();
|
||||
|
||||
@Override
|
||||
@@ -102,7 +114,12 @@ public abstract class ProcessorQuery<AggregatedType, DataSourceType> implements
|
||||
AdditionalResultDataBuilder additionalDataBuilder = new OverwritingResultDataBuilder();
|
||||
additionalDataBuilder = firstProcessor.getAdditionalResultData(additionalDataBuilder);
|
||||
Map<GroupKey, AggregatedType> results = resultReceiver.getResult();
|
||||
return new QueryResultImpl<>(results, additionalDataBuilder.build(calculationTimeInNanos, stringMessages, locale));
|
||||
|
||||
if (stringMessages != null && locale != null) {
|
||||
return new QueryResultImpl<>(results, additionalDataBuilder.build(calculationTimeInNanos, stringMessages, locale));
|
||||
} else {
|
||||
return new QueryResultImpl<>(results);
|
||||
}
|
||||
}
|
||||
|
||||
private void logOccuredFailures() {
|
||||
|
||||
Reference in new issue
Block a user