Merge branch 'master' into bug3237

This commit is contained in:
Axel Uhl committed 2015-08-20 17:00:08 +02:00
commit 291998ecd3
102 files changed
+1180 -628

No files matched your search

@@ -9,4 +9,5 @@ Bundle-ActivationPolicy: lazy
Bundle-ClassPath: .
Require-Bundle: com.sap.sse.datamining.shared,
com.sap.sailing.domain.common
Export-Package: com.sap.sailing.datamining.shared
Export-Package: com.sap.sailing.datamining.shared,
com.sap.sailing.datamining.shared.dto
@@ -1,15 +1,15 @@
package com.sap.sailing.datamining.shared;
import java.io.Serializable;
import com.sap.sailing.datamining.shared.dto.DistanceDTO;
import com.sap.sailing.domain.common.LegType;
import com.sap.sse.datamining.shared.impl.GenericGroupKey;
import com.sap.sse.datamining.shared.SerializationDummy;
@SuppressWarnings("unused")
public final class SailingDataMiningSerializationDummy implements Serializable {
public final class SailingDataMiningSerializationDummy implements SerializationDummy {
private static final long serialVersionUID = 2L;
private LegType legType;
private DistanceDTO distance;
private SailingDataMiningSerializationDummy() { }
@@ -0,0 +1,63 @@
package com.sap.sailing.datamining.shared.dto;
import java.io.Serializable;
public class DistanceDTO implements Serializable {
private static final long serialVersionUID = -4949861628112888523L;
private double geographicalMiles;
private double seaMiles;
private double nauticalMiles;
private double meters;
private double kilometers;
private double centralAngleDegree;
private double centralAngleRadian;
/**
* <b>Do NOT use!</b><br>
* Constructor for GWT-Serialization.
*/
@Deprecated
DistanceDTO() {
}
public DistanceDTO(double geographicalMiles, double seaMiles, double nauticalMiles, double meters,
double kilometers, double centralAngleDegree, double centralAngleRadian) {
this.geographicalMiles = geographicalMiles;
this.seaMiles = seaMiles;
this.nauticalMiles = nauticalMiles;
this.meters = meters;
this.kilometers = kilometers;
this.centralAngleDegree = centralAngleDegree;
this.centralAngleRadian = centralAngleRadian;
}
public double getGeographicalMiles() {
return geographicalMiles;
}
public double getSeaMiles() {
return seaMiles;
}
public double getNauticalMiles() {
return nauticalMiles;
}
public double getMeters() {
return meters;
}
public double getKilometers() {
return kilometers;
}
public double getCentralAngleDegree() {
return centralAngleDegree;
}
public double getCentralAngleRadian() {
return centralAngleRadian;
}
}
@@ -13,7 +13,8 @@ import com.sap.sailing.datamining.data.HasRaceResultOfCompetitorContext;
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.datamining.impl.components.aggregators.ParallelTrueSumAggregationProcessor;
import com.sap.sailing.datamining.impl.components.aggregators.ParallelBoolSumAggregationProcessor;
import com.sap.sailing.datamining.impl.components.aggregators.ParallelDistanceSumAggregationProcessor;
import com.sap.sailing.domain.common.Speed;
import com.sap.sse.datamining.DataMiningBundleService;
import com.sap.sse.datamining.DataSourceProvider;
@@ -98,7 +99,8 @@ public class Activator extends AbstractDataMiningActivator implements DataMining
@Override
public Iterable<AggregationProcessorDefinition<?, ?>> getAggregationProcessorDefinitions() {
HashSet<AggregationProcessorDefinition<?, ?>> aggregators = new HashSet<>();
aggregators.add(ParallelTrueSumAggregationProcessor.getDefinition());
aggregators.add(ParallelBoolSumAggregationProcessor.getDefinition());
aggregators.add(ParallelDistanceSumAggregationProcessor.getDefinition());
return aggregators;
}
@@ -1,5 +1,6 @@
package com.sap.sailing.datamining.data;
import com.sap.sailing.datamining.shared.dto.DistanceDTO;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.common.Speed;
import com.sap.sse.datamining.shared.annotations.Connector;
@@ -14,8 +15,8 @@ public interface HasRaceOfCompetitorContext {
@Connector(messageKey="Competitor")
public Competitor getCompetitor();
@Statistic(messageKey="DistanceAtStart", resultUnit=Unit.Meters, resultDecimals=0, ordinal=0)
public double getDistanceToStartLineAtStart();
@Statistic(messageKey="DistanceAtStart", resultUnit=Unit.None, resultDecimals=2, ordinal=0)
public DistanceDTO getDistanceToStartLineAtStart();
@Statistic(messageKey="DistanceToStarboardSideAtStart", resultDecimals=2, ordinal=1)
public Double getNormalizedDistanceToStarboardSideAtStart();
@@ -9,14 +9,14 @@ import com.sap.sse.datamining.components.AggregationProcessorDefinition;
import com.sap.sse.datamining.components.Processor;
import com.sap.sse.datamining.impl.components.GroupedDataEntry;
import com.sap.sse.datamining.impl.components.SimpleAggregationProcessorDefinition;
import com.sap.sse.datamining.impl.components.aggregators.AbstractParallelGroupedDataStoringAggregationProcessor;
import com.sap.sse.datamining.impl.components.aggregators.AbstractParallelGroupedDataAggregationProcessor;
import com.sap.sse.datamining.shared.GroupKey;
public class ParallelTrueSumAggregationProcessor
extends AbstractParallelGroupedDataStoringAggregationProcessor<Boolean, Double> {
public class ParallelBoolSumAggregationProcessor
extends AbstractParallelGroupedDataAggregationProcessor<Boolean, Double> {
private static final AggregationProcessorDefinition<Boolean, Double> DEFINITION =
new SimpleAggregationProcessorDefinition<>(Boolean.class, Double.class, "Sum", ParallelTrueSumAggregationProcessor.class);
new SimpleAggregationProcessorDefinition<>(Boolean.class, Double.class, "Sum", ParallelBoolSumAggregationProcessor.class);
public static AggregationProcessorDefinition<Boolean, Double> getDefinition() {
return DEFINITION;
@@ -24,14 +24,14 @@ public class ParallelTrueSumAggregationProcessor
private Map<GroupKey, Double> result;
public ParallelTrueSumAggregationProcessor(ExecutorService executor,
public ParallelBoolSumAggregationProcessor(ExecutorService executor,
Collection<Processor<Map<GroupKey, Double>, ?>> resultReceivers) {
super(executor, resultReceivers, "Sum");
result = new HashMap<>();
}
@Override
protected void storeElement(GroupedDataEntry<Boolean> element) {
protected void handleElement(GroupedDataEntry<Boolean> element) {
GroupKey key = element.getKey();
if (!result.containsKey(key)) {
result.put(key, 0.0);
@@ -43,7 +43,7 @@ public class ParallelTrueSumAggregationProcessor
}
@Override
protected Map<GroupKey, Double> aggregateResult() {
protected Map<GroupKey, Double> getResult() {
return result;
}
@@ -0,0 +1,59 @@
package com.sap.sailing.datamining.impl.components.aggregators;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import com.sap.sailing.datamining.shared.dto.DistanceDTO;
import com.sap.sse.datamining.components.AggregationProcessorDefinition;
import com.sap.sse.datamining.components.Processor;
import com.sap.sse.datamining.impl.components.GroupedDataEntry;
import com.sap.sse.datamining.impl.components.SimpleAggregationProcessorDefinition;
import com.sap.sse.datamining.impl.components.aggregators.AbstractParallelGroupedDataAggregationProcessor;
import com.sap.sse.datamining.shared.GroupKey;
public class ParallelDistanceSumAggregationProcessor extends
AbstractParallelGroupedDataAggregationProcessor<DistanceDTO, DistanceDTO> {
private static final AggregationProcessorDefinition<DistanceDTO, DistanceDTO> DEFINITION =
new SimpleAggregationProcessorDefinition<>(DistanceDTO.class, DistanceDTO.class, "Sum", ParallelDistanceSumAggregationProcessor.class);
public static AggregationProcessorDefinition<DistanceDTO, DistanceDTO> getDefinition() {
return DEFINITION;
}
private final Map<GroupKey, DistanceDTO> results;
public ParallelDistanceSumAggregationProcessor(ExecutorService executor, Collection<Processor<Map<GroupKey, DistanceDTO>, ?>> resultReceivers) {
super(executor, resultReceivers, "Sum");
results = new HashMap<>();
}
@Override
protected void handleElement(GroupedDataEntry<DistanceDTO> element) {
GroupKey key = element.getKey();
if (!results.containsKey(key)) {
results.put(key, element.getDataEntry());
} else {
results.put(key, add(results.get(key), element.getDataEntry()));
}
}
private DistanceDTO add(DistanceDTO distance1, DistanceDTO distance2) {
double geographicalMiles = distance1.getGeographicalMiles() + distance2.getGeographicalMiles();
double seaMiles = distance1.getSeaMiles() + distance2.getSeaMiles();
double nauticalMiles = distance1.getNauticalMiles() + distance2.getNauticalMiles();
double meters = distance1.getMeters() + distance2.getMeters();
double kilometers = distance1.getKilometers() + distance2.getKilometers();
double centralAngleDegree = distance1.getCentralAngleDegree() + distance2.getCentralAngleDegree();
double centralAngleRadian = distance1.getCentralAngleRadian() + distance2.getCentralAngleRadian();
return new DistanceDTO(geographicalMiles, seaMiles, nauticalMiles, meters, kilometers, centralAngleDegree, centralAngleRadian);
}
@Override
protected Map<GroupKey, DistanceDTO> getResult() {
return results;
}
}
@@ -4,9 +4,11 @@ import java.util.concurrent.TimeUnit;
import com.sap.sailing.datamining.data.HasRaceOfCompetitorContext;
import com.sap.sailing.datamining.data.HasTrackedRaceContext;
import com.sap.sailing.datamining.shared.dto.DistanceDTO;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Course;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.common.Distance;
import com.sap.sailing.domain.common.ManeuverType;
import com.sap.sailing.domain.common.Speed;
import com.sap.sailing.domain.tracking.Maneuver;
@@ -39,8 +41,12 @@ public class RaceOfCompetitorWithContext implements HasRaceOfCompetitorContext {
}
@Override
public double getDistanceToStartLineAtStart() {
return getTrackedRace().getDistanceToStartLine(getCompetitor(), 0).getMeters();
public DistanceDTO getDistanceToStartLineAtStart() {
Distance distance = getTrackedRace().getDistanceToStartLine(getCompetitor(), 0);
return new DistanceDTO(distance.getGeographicalMiles(), distance.getSeaMiles(),
distance.getNauticalMiles(), distance.getMeters(),
distance.getKilometers(), distance.getCentralAngleDeg(),
distance.getCentralAngleRad());
}
@Override
@@ -1862,6 +1862,8 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
@Override
public void waypointAdded(int zeroBasedIndex, Waypoint waypointThatGotAdded) {
logger.info("waypoint at zero-based index "+zeroBasedIndex+" ("+waypointThatGotAdded+") added; updating tracked race "+this+
"'s data structures...");
// expecting to hold the course's write lock
invalidateMarkPassingTimes();
LockUtil.lockForRead(getSerializationLock());
@@ -1892,6 +1894,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
}
updated(/* time point */null); // no maneuver cache invalidation required because we don't yet have mark
// passings for new waypoint
logger.info("done updating tracked race "+this+"'s data structures...");
} finally {
LockUtil.unlockAfterRead(getSerializationLock());
}
@@ -1961,6 +1964,8 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
@Override
public void waypointRemoved(int zeroBasedIndex, Waypoint waypointThatGotRemoved) {
logger.info("waypoint at zero-based index "+zeroBasedIndex+" ("+waypointThatGotRemoved+") removed; updating tracked race "+this+
"'s data structures...");
// expecting to hold the course's write lock
invalidateMarkPassingTimes();
LockUtil.lockForRead(getSerializationLock());
@@ -2017,6 +2022,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
triggerManeuverCacheRecalculation(competitor);
}
}
logger.info("done updating tracked race "+this+"'s data structures...");
} finally {
LockUtil.unlockAfterRead(getSerializationLock());
}
@@ -1362,6 +1362,8 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, c
String plainText();
String columnChart();
String choosePresentation();
String cantDisplayDataOfType(String resultType);
String shownDecimals();
String openFullscreenView();
String closeFullscreenView();
}
@@ -1331,5 +1331,7 @@ latestRegattaStandings=Latest Regatta Standings
plainText=Plain Text
columnChart=Column Chart
choosePresentation=Choose Presentation
cantDisplayDataOfType=Can''t display data of type {0}
shownDecimals=Shown Decimals
openFullscreenView=Open fullscreen view
closeFullscreenView=Close fullscreen view
@@ -1320,5 +1320,7 @@ latestRegattaStandings=Aktuelle Plazierungen
plainText=Einfacher Text
columnChart=Säulendiagramm
choosePresentation=Wähle Präsentation
cantDisplayDataOfType=Daten des Typs {0} können nicht dargestellt werden
shownDecimals=Angezeigte Nachkommastellen
openFullscreenView=Vollbildansicht öffnen
closeFullscreenView=Vollbildansicht schließen
@@ -1267,5 +1267,7 @@ latestRegattaStandings=Latest Regatta Standings
plainText=Plain Text
columnChart=Column Chart
choosePresentation=Choose Presentation
cantDisplayDataOfType=Can''t display data of type {0}
shownDecimals=Shown Decimals
openFullscreenView=Open fullscreen view
closeFullscreenView=Close fullscreen view
@@ -53,7 +53,7 @@ public class DataMiningEntryPoint extends AbstractSailingEntryPoint {
queryDefinitionProviderWithControls.getEntryWidget().addStyleName("dataMiningPanel");
selectionDockPanel.add(queryDefinitionProviderWithControls.getEntryWidget());
ResultsPresenter<Number> resultsPresenter = new TabbedResultsPresenter(getStringMessages());
ResultsPresenter resultsPresenter = new TabbedResultsPresenter(getStringMessages());
splitPanel.addSouth(resultsPresenter.getWidget(), 400);
splitPanel.add(selectionDockPanel);
@@ -6,14 +6,13 @@ import java.util.Map;
import java.util.Set;
import com.google.gwt.user.client.rpc.RemoteService;
import com.sap.sailing.datamining.shared.SailingDataMiningSerializationDummy;
import com.sap.sse.datamining.shared.DataMiningSession;
import com.sap.sse.datamining.shared.QueryResult;
import com.sap.sse.datamining.shared.SSEDataMiningSerializationDummy;
import com.sap.sse.datamining.shared.SerializationDummy;
import com.sap.sse.datamining.shared.dto.StatisticQueryDefinitionDTO;
import com.sap.sse.datamining.shared.impl.dto.AggregationProcessorDefinitionDTO;
import com.sap.sse.datamining.shared.impl.dto.DataRetrieverChainDefinitionDTO;
import com.sap.sse.datamining.shared.impl.dto.FunctionDTO;
import com.sap.sse.datamining.shared.impl.dto.QueryResultDTO;
public interface DataMiningService extends RemoteService {
@@ -30,13 +29,11 @@ public interface DataMiningService extends RemoteService {
Iterable<DataRetrieverChainDefinitionDTO> getDataRetrieverChainDefinitions(String localeName);
Iterable<DataRetrieverChainDefinitionDTO> getDataRetrieverChainDefinitionsFor(FunctionDTO statisticToCalculate, String localeInfoName);
QueryResult<Set<Object>> getDimensionValuesFor(DataMiningSession session, DataRetrieverChainDefinitionDTO dataRetrieverChainDefinitionDTO, int retrieverLevel,
QueryResultDTO<Set<Object>> getDimensionValuesFor(DataMiningSession session, DataRetrieverChainDefinitionDTO dataRetrieverChainDefinitionDTO, int retrieverLevel,
Iterable<FunctionDTO> dimensionDTOs, Map<Integer, Map<FunctionDTO, Collection<?>>> filterSelectionDTO, String localeInfoName);
<ResultType extends Number> QueryResult<ResultType> runQuery(DataMiningSession session, StatisticQueryDefinitionDTO queryDefinition);
<ResultType> QueryResultDTO<ResultType> runQuery(DataMiningSession session, StatisticQueryDefinitionDTO queryDefinition);
SSEDataMiningSerializationDummy pseudoMethodSoThatSomeSSEDataMiningClassesAreAddedToTheGWTSerializationPolicy();
SailingDataMiningSerializationDummy pseudoMethodSoThatSomeSailingDataMiningClassesAreAddedToTheGWTSerializationPolicy();
SerializationDummy pseudoMethodSoThatSomeClassesAreAddedToTheGWTSerializationPolicy();
}
@@ -6,15 +6,14 @@ import java.util.Map;
import java.util.Set;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.sap.sailing.datamining.shared.SailingDataMiningSerializationDummy;
import com.sap.sse.datamining.shared.DataMiningSession;
import com.sap.sse.datamining.shared.QueryResult;
import com.sap.sse.datamining.shared.SSEDataMiningSerializationDummy;
import com.sap.sse.datamining.shared.SerializationDummy;
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;
import com.sap.sse.datamining.shared.impl.dto.DataRetrieverChainDefinitionDTO;
import com.sap.sse.datamining.shared.impl.dto.FunctionDTO;
import com.sap.sse.datamining.shared.impl.dto.QueryResultDTO;
public interface DataMiningServiceAsync {
@@ -37,9 +36,9 @@ public interface DataMiningServiceAsync {
void getDimensionValuesFor(DataMiningSession session, DataRetrieverChainDefinitionDTO dataRetrieverChainDefinitionDTO, int retrieverLevel,
Iterable<FunctionDTO> dimensionDTOs, Map<Integer, Map<FunctionDTO, Collection<?>>> filterSelectionDTO,
String localeInfoName, AsyncCallback<QueryResult<Set<Object>>> callback);
String localeInfoName, AsyncCallback<QueryResultDTO<Set<Object>>> callback);
<ResultType extends Number> void runQuery(DataMiningSession session, StatisticQueryDefinitionDTO queryDefinition, AsyncCallback<QueryResult<ResultType>> callback);
<ResultType> void runQuery(DataMiningSession session, StatisticQueryDefinitionDTO queryDefinition, AsyncCallback<QueryResultDTO<ResultType>> callback);
/**
* This method does nothing, but is needed to ensure, that some classes for the data mining
@@ -47,14 +46,6 @@ public interface DataMiningServiceAsync {
* This is necessary, because the type is somehow hidden from GWT. For Further information
* look at bug 1503.<br />
*/
void pseudoMethodSoThatSomeSSEDataMiningClassesAreAddedToTheGWTSerializationPolicy(AsyncCallback<SSEDataMiningSerializationDummy> asyncCallback);
/**
* This method does nothing, but is needed to ensure, that some classes for the data mining
* (like {@link GenericGroupKey}) is added to the GWT serialization policy.<br />
* This is necessary, because the type is somehow hidden from GWT. For Further information
* look at bug 1503.<br />
*/
void pseudoMethodSoThatSomeSailingDataMiningClassesAreAddedToTheGWTSerializationPolicy(AsyncCallback<SailingDataMiningSerializationDummy> asyncCallback);
void pseudoMethodSoThatSomeClassesAreAddedToTheGWTSerializationPolicy(AsyncCallback<SerializationDummy> callback);
}
@@ -1,15 +1,15 @@
package com.sap.sailing.gwt.ui.datamining;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sse.datamining.shared.QueryResult;
import com.sap.sse.datamining.shared.impl.dto.QueryResultDTO;
public interface ResultsPresenter<ResultType> {
public interface ResultsPresenter {
public Widget getWidget();
public QueryResult<ResultType> getCurrentResult();
public QueryResultDTO<?> getCurrentResult();
public void showResult(QueryResult<ResultType> result);
public void showResult(QueryResultDTO<?> result);
public void showError(String error);
public void showError(String mainError, Iterable<String> detailedErrors);
@@ -1,5 +1,5 @@
package com.sap.sailing.gwt.ui.datamining;
public interface ResultsPresenterWithControls<ResultType> extends ResultsPresenter<ResultType>, WithControls {
public interface ResultsPresenterWithControls extends ResultsPresenter, WithControls {
}
@@ -11,7 +11,7 @@ import org.moxieapps.gwt.highcharts.client.plotOptions.LinePlotOptions;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.ui.datamining.ResultsPresenter;
import com.sap.sse.datamining.shared.GroupKey;
import com.sap.sse.datamining.shared.QueryResult;
import com.sap.sse.datamining.shared.impl.dto.QueryResultDTO;
/**
* Expects the inner key in the group key to be the angle for the polar chart. (x-value) Maybe the angle should be
@@ -21,7 +21,7 @@ import com.sap.sse.datamining.shared.QueryResult;
* @author Frederik Petersen D054528
*
*/
public class PolarChart implements ResultsPresenter<Number> {
public class PolarChart implements ResultsPresenter {
private final Chart chart = createPolarChartWidget();
@@ -44,9 +44,10 @@ public class PolarChart implements ResultsPresenter<Number> {
}
@Override
public void showResult(QueryResult<Number> result) {
public void showResult(QueryResultDTO<?> result) {
resetChartData();
Map<GroupKey, Number> results = result.getResults();
@SuppressWarnings("unchecked")
Map<GroupKey, Number> results = (Map<GroupKey, Number>) result.getResults();
if (!results.isEmpty()) {
for (Entry<GroupKey, Number> resultEntry : results.entrySet()) {
GroupKey key = resultEntry.getKey();
@@ -93,7 +94,7 @@ public class PolarChart implements ResultsPresenter<Number> {
}
@Override
public QueryResult<Number> getCurrentResult() {
public QueryResultDTO<Number> getCurrentResult() {
// TODO Auto-generated method stub
return null;
}
@@ -2,10 +2,10 @@ package com.sap.sailing.gwt.ui.datamining.execution;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.sap.sailing.gwt.ui.datamining.ManagedDataMiningQueriesCounter;
import com.sap.sse.datamining.shared.QueryResult;
import com.sap.sse.datamining.shared.data.QueryResultState;
import com.sap.sse.datamining.shared.impl.dto.QueryResultDTO;
public abstract class ManagedDataMiningQueryCallback<AggregatedType> implements AsyncCallback<QueryResult<AggregatedType>> {
public abstract class ManagedDataMiningQueryCallback<AggregatedType> implements AsyncCallback<QueryResultDTO<AggregatedType>> {
private final ManagedDataMiningQueriesCounter counter;
@@ -24,7 +24,7 @@ public abstract class ManagedDataMiningQueryCallback<AggregatedType> implements
protected abstract void handleFailure(Throwable caught);
@Override
public void onSuccess(QueryResult<AggregatedType> result) {
public void onSuccess(QueryResultDTO<AggregatedType> result) {
counter.decrease();
if (result.getState() == QueryResultState.NORMAL ||
counter.get() == 0) {
@@ -32,6 +32,6 @@ public abstract class ManagedDataMiningQueryCallback<AggregatedType> implements
}
}
protected abstract void handleSuccess(QueryResult<AggregatedType> result);
protected abstract void handleSuccess(QueryResultDTO<AggregatedType> result);
}
@@ -13,8 +13,8 @@ import com.sap.sailing.gwt.ui.datamining.ResultsPresenter;
import com.sap.sailing.gwt.ui.datamining.settings.QueryRunnerSettings;
import com.sap.sailing.gwt.ui.datamining.settings.QueryRunnerSettingsDialogComponent;
import com.sap.sse.datamining.shared.DataMiningSession;
import com.sap.sse.datamining.shared.QueryResult;
import com.sap.sse.datamining.shared.dto.StatisticQueryDefinitionDTO;
import com.sap.sse.datamining.shared.impl.dto.QueryResultDTO;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.shared.components.SettingsDialogComponent;
@@ -28,12 +28,12 @@ public class SimpleQueryRunner implements QueryRunner {
private QueryRunnerSettings settings;
private final QueryDefinitionProvider queryDefinitionProvider;
private final ResultsPresenter<Number> resultsPresenter;
private final ResultsPresenter resultsPresenter;
private final Button runButton;
public SimpleQueryRunner(DataMiningSession session, StringMessages stringMessages, DataMiningServiceAsync dataMiningService,
ErrorReporter errorReporter, QueryDefinitionProvider queryDefinitionProvider,
ResultsPresenter<Number> resultsPresenter) {
ResultsPresenter resultsPresenter) {
this.session = session;
this.stringMessages = stringMessages;
this.dataMiningService = dataMiningService;
@@ -70,7 +70,7 @@ public class SimpleQueryRunner implements QueryRunner {
resultsPresenter.showError(stringMessages.errorRunningDataMiningQuery() + ".");
}
@Override
protected void handleSuccess(QueryResult<Number> result) {
protected void handleSuccess(QueryResultDTO<Number> result) {
resultsPresenter.showResult(result);
}
});
@@ -1,21 +1,35 @@
package com.sap.sailing.gwt.ui.datamining.presentation;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DeckLayoutPanel;
import com.google.gwt.user.client.ui.DockLayoutPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.SimpleLayoutPanel;
import com.google.gwt.user.client.ui.ValueListBox;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.datamining.shared.dto.DistanceDTO;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.client.shared.controls.AbstractObjectRenderer;
import com.sap.sailing.gwt.ui.datamining.ResultsPresenterWithControls;
import com.sap.sse.datamining.shared.QueryResult;
import com.sap.sailing.gwt.ui.datamining.presentation.dataproviders.AbstractResultDataProvider;
import com.sap.sailing.gwt.ui.datamining.presentation.dataproviders.DistanceDataProvider;
import com.sap.sailing.gwt.ui.datamining.presentation.dataproviders.NumberDataProvider;
import com.sap.sse.datamining.shared.GroupKey;
import com.sap.sse.datamining.shared.impl.dto.QueryResultDTO;
public abstract class AbstractResultsPresenter<ResultType> implements ResultsPresenterWithControls<ResultType> {
public abstract class AbstractResultsPresenter implements ResultsPresenterWithControls {
private enum ResultsPresenterState { BUSY, ERROR, RESULT }
@@ -24,17 +38,26 @@ public abstract class AbstractResultsPresenter<ResultType> implements ResultsPre
private final DockLayoutPanel mainPanel;
private final HorizontalPanel controlsPanel;
private final SimpleLayoutPanel presentationPanel;
private final ValueListBox<String> dataSelectionListBox;
private final DeckLayoutPanel presentationPanel;
private final HTML errorLabel;
private final HTML labeledBusyIndicator;
private QueryResult<ResultType> currentResult;
private final NumberDataProvider numberDataProvider;
private final Map<String, AbstractResultDataProvider<?>> dataProviders;
private AbstractResultDataProvider<?> currentDataProvider;
private QueryResultDTO<?> currentResult;
public AbstractResultsPresenter(StringMessages stringMessages) {
this.stringMessages = stringMessages;
mainPanel = new DockLayoutPanel(Unit.PX);
numberDataProvider = new NumberDataProvider();
dataProviders = new HashMap<>();
AbstractResultDataProvider<DistanceDTO> distanceDataProvider = new DistanceDataProvider();
dataProviders.put(distanceDataProvider.getResultType().getName(), distanceDataProvider);
controlsPanel = new HorizontalPanel();
controlsPanel.setSpacing(5);
mainPanel.addNorth(controlsPanel, 40);
@@ -51,7 +74,23 @@ public abstract class AbstractResultsPresenter<ResultType> implements ResultsPre
});
addControl(exportButton);
presentationPanel = new SimpleLayoutPanel();
dataSelectionListBox = new ValueListBox<>(new AbstractObjectRenderer<String>() {
@Override
protected String convertObjectToString(String nonNullObject) {
// TODO I18N
return nonNullObject;
}
});
dataSelectionListBox.addValueChangeHandler(new ValueChangeHandler<String>() {
@Override
public void onValueChange(ValueChangeEvent<String> event) {
Map<GroupKey, Number> resultValues = currentDataProvider.getData(getCurrentResult(), dataSelectionListBox.getValue());
internalShowResult(resultValues);
}
});
addControl(dataSelectionListBox);
presentationPanel = new DeckLayoutPanel();
mainPanel.add(presentationPanel);
errorLabel = new HTML();
@@ -69,7 +108,7 @@ public abstract class AbstractResultsPresenter<ResultType> implements ResultsPre
}
@Override
public void showResult(QueryResult<ResultType> result) {
public void showResult(QueryResultDTO<?> result) {
if (result != null && !result.isEmpty()) {
if (state != ResultsPresenterState.RESULT) {
mainPanel.setWidgetHidden(controlsPanel, false);
@@ -78,22 +117,47 @@ public abstract class AbstractResultsPresenter<ResultType> implements ResultsPre
}
this.currentResult = result;
internalShowResult();
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
@Override
public void execute() {
presentationPanel.onResize();
}
});
currentDataProvider = selectCurrentDataProvider();
updateDataSelectionListBox();
if (currentDataProvider != null) {
Map<GroupKey, Number> resultValues = currentDataProvider.getData(getCurrentResult(), dataSelectionListBox.getValue());
internalShowResult(resultValues);
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
@Override
public void execute() {
presentationPanel.onResize();
}
});
} else {
showError(getStringMessages().cantDisplayDataOfType(getCurrentResult().getResultType()));
}
} else {
this.currentResult = null;
showError(getStringMessages().noDataFound() + ".");
}
}
private AbstractResultDataProvider<?> selectCurrentDataProvider() {
if (numberDataProvider.acceptsResultsOfType(getCurrentResult().getResultType())) {
return numberDataProvider;
}
return dataProviders.get(getCurrentResult().getResultType());
}
private void updateDataSelectionListBox() {
if (currentDataProvider == null) {
dataSelectionListBox.setAcceptableValues(Collections.<String>emptyList());
} else {
Collection<String> dataKeys = currentDataProvider.getDataKeys();
String keyToSelect = currentDataProvider.getDefaultDataKeyFor(getCurrentResult());
dataSelectionListBox.setValue(keyToSelect, false);
dataSelectionListBox.setAcceptableValues(dataKeys);
}
}
protected abstract Widget getPresentationWidget();
protected abstract void internalShowResult();
protected abstract void internalShowResult(Map<GroupKey, Number> resultValues);
@Override
public void showError(String error) {
@@ -132,7 +196,7 @@ public abstract class AbstractResultsPresenter<ResultType> implements ResultsPre
}
@Override
public QueryResult<ResultType> getCurrentResult() {
public QueryResultDTO<?> getCurrentResult() {
return currentResult;
}
@@ -16,16 +16,16 @@ import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.client.shared.controls.AbstractObjectRenderer;
import com.sap.sailing.gwt.ui.datamining.ResultsPresenter;
import com.sap.sailing.gwt.ui.datamining.ResultsPresenterWithControls;
import com.sap.sse.datamining.shared.QueryResult;
import com.sap.sse.datamining.shared.impl.dto.QueryResultDTO;
public class MultiResultsPresenter implements ResultsPresenter<Number> {
public class MultiResultsPresenter implements ResultsPresenter {
private final StringMessages stringMessages;
private final DeckLayoutPanel presentersPanel;
private final DeckLayoutPanel presenterPanel;
private final HorizontalPanel controlsPanel;
private final ValueListBox<Descriptor> presentersListBox;
private ResultsPresenter<Number> currentPresenter;
private ResultsPresenter currentPresenter;
private List<Descriptor> availableDescriptors;
@@ -35,7 +35,7 @@ public class MultiResultsPresenter implements ResultsPresenter<Number> {
availableDescriptors.add(new ColumnChartDescriptor());
availableDescriptors.add(new PlainDescriptor());
presentersPanel = new DeckLayoutPanel();
presenterPanel = new DeckLayoutPanel();
controlsPanel = new HorizontalPanel();
controlsPanel.setSpacing(5);
@@ -59,32 +59,32 @@ public class MultiResultsPresenter implements ResultsPresenter<Number> {
setCurrentPresenter(availableDescriptors.get(0).getPresenter());
}
private void setCurrentPresenter(ResultsPresenterWithControls<Number> presenter) {
private void setCurrentPresenter(ResultsPresenterWithControls presenter) {
controlsPanel.removeFromParent();
presenter.addControl(controlsPanel);
currentPresenter = presenter;
presentersPanel.setWidget(currentPresenter.getWidget());
presenterPanel.setWidget(currentPresenter.getWidget());
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
@Override
public void execute() {
presentersPanel.onResize();
presenterPanel.onResize();
}
});
}
@Override
public Widget getWidget() {
return presentersPanel;
return presenterPanel;
}
@Override
public QueryResult<Number> getCurrentResult() {
public QueryResultDTO<?> getCurrentResult() {
return currentPresenter.getCurrentResult();
}
@Override
public void showResult(QueryResult<Number> result) {
public void showResult(QueryResultDTO<?> result) {
for (Descriptor descriptor : availableDescriptors) {
descriptor.getPresenter().showResult(result);
}
@@ -115,13 +115,13 @@ public class MultiResultsPresenter implements ResultsPresenter<Number> {
public String getName();
public ResultsPresenterWithControls<Number> getPresenter();
public ResultsPresenterWithControls getPresenter();
}
private class PlainDescriptor implements Descriptor {
private final AbstractResultsPresenter<Number> presenter;
private final AbstractResultsPresenter presenter;
public PlainDescriptor() {
presenter = new PlainResultsPresenter(stringMessages);
@@ -133,7 +133,7 @@ public class MultiResultsPresenter implements ResultsPresenter<Number> {
}
@Override
public AbstractResultsPresenter<Number> getPresenter() {
public AbstractResultsPresenter getPresenter() {
return presenter;
}
@@ -153,7 +153,7 @@ public class MultiResultsPresenter implements ResultsPresenter<Number> {
}
@Override
public AbstractResultsPresenter<Number> getPresenter() {
public AbstractResultsPresenter getPresenter() {
return presenter;
}
@@ -10,9 +10,9 @@ import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sse.datamining.shared.GroupKey;
import com.sap.sse.datamining.shared.QueryResult;
import com.sap.sse.datamining.shared.impl.dto.QueryResultDTO;
public class PlainResultsPresenter extends AbstractResultsPresenter<Number> {
public class PlainResultsPresenter extends AbstractResultsPresenter {
private final ScrollPanel scrollPanel;
private final HTML resultsLabel;
@@ -25,12 +25,10 @@ public class PlainResultsPresenter extends AbstractResultsPresenter<Number> {
}
@Override
protected void internalShowResult() {
QueryResult<Number> result = getCurrentResult();
Map<GroupKey, Number> resultValues = result.getResults();
protected void internalShowResult(Map<GroupKey, Number> resultValues) {
QueryResultDTO<?> result = getCurrentResult();
StringBuilder resultsBuilder = new StringBuilder("<b>" + result.getResultSignifier() + "</b></ br>");
resultsBuilder.append("<table>");
for (GroupKey key : getSortedKeys(result)) {
resultsBuilder.append("<tr>");
@@ -43,7 +41,7 @@ public class PlainResultsPresenter extends AbstractResultsPresenter<Number> {
resultsLabel.setHTML(resultsBuilder.toString());
}
private Iterable<GroupKey> getSortedKeys(QueryResult<Number> result) {
private Iterable<GroupKey> getSortedKeys(QueryResultDTO<?> result) {
List<GroupKey> sortedKeys = new ArrayList<>(result.getResults().keySet());
Collections.sort(sortedKeys);
return sortedKeys;
@@ -1,6 +1,7 @@
package com.sap.sailing.gwt.ui.datamining.presentation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
@@ -32,10 +33,11 @@ import com.google.gwt.user.client.ui.SimpleLayoutPanel;
import com.google.gwt.user.client.ui.ValueListBox;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.client.shared.controls.SimpleObjectRenderer;
import com.sap.sse.datamining.shared.GroupKey;
import com.sap.sse.datamining.shared.impl.GenericGroupKey;
public class ResultsChart extends AbstractResultsPresenter<Number> {
public class ResultsChart extends AbstractResultsPresenter {
private final Comparator<GroupKey> standardKeyComparator = new Comparator<GroupKey>() {
@Override
@@ -50,9 +52,8 @@ public class ResultsChart extends AbstractResultsPresenter<Number> {
private final Comparator<GroupKey> ascendingByValueKeyComparator = new Comparator<GroupKey>() {
@Override
public int compare(GroupKey key1, GroupKey key2) {
Map<GroupKey, ? extends Number> resultData = getCurrentResult().getResults();
double doubleValue1 = resultData.get(key1).doubleValue();
double doubleValue2 = resultData.get(key2).doubleValue();
double doubleValue1 = currentResultValues.get(key1).doubleValue();
double doubleValue2 = currentResultValues.get(key2).doubleValue();
return Double.compare(doubleValue1, doubleValue2);
}
@Override
@@ -73,19 +74,21 @@ public class ResultsChart extends AbstractResultsPresenter<Number> {
private final HorizontalPanel sortByPanel;
private final ValueListBox<Comparator<GroupKey>> keyComparatorListBox;
private final ValueListBox<Integer> decimalsListBox;
private final SimpleLayoutPanel chartPanel;
private final Chart chart;
private Map<GroupKey, Series> seriesMappedByGroupKey;
private final GroupKey simpleResultSeriesKey;
private Map<GroupKey, Integer> mainKeyToXValueMap;
private Map<GroupKey, Number> currentResultValues;
public ResultsChart(StringMessages stringMessages) {
super(stringMessages);
sortByPanel = new HorizontalPanel();
sortByPanel.setSpacing(5);
sortByPanel.add(new Label(stringMessages.sortBy()));
sortByPanel.add(new Label(stringMessages.sortBy() + ":"));
keyComparatorListBox = new ValueListBox<>(new AbstractRenderer<Comparator<?>>() {
@Override
public String render(Comparator<?> object) {
@@ -103,6 +106,23 @@ public class ResultsChart extends AbstractResultsPresenter<Number> {
sortByPanel.setVisible(false);
addControl(sortByPanel);
HorizontalPanel decimalsPanel = new HorizontalPanel();
decimalsPanel.setSpacing(5);
decimalsPanel.add(new Label(getStringMessages().shownDecimals() + ":"));
decimalsListBox = new ValueListBox<Integer>(new SimpleObjectRenderer<Integer>());
decimalsPanel.add(decimalsListBox);
decimalsListBox.setValue(0);
decimalsListBox.setAcceptableValues(Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
decimalsListBox.addValueChangeHandler(new ValueChangeHandler<Integer>() {
@Override
public void onValueChange(ValueChangeEvent<Integer> event) {
updateChartLabels();
resetChartSeries();
showResultData();
}
});
addControl(decimalsPanel);
chartPanel = new SimpleLayoutPanel() {
@Override
public void onResize() {
@@ -123,11 +143,12 @@ public class ResultsChart extends AbstractResultsPresenter<Number> {
}
@Override
protected void internalShowResult() {
protected void internalShowResult(Map<GroupKey, Number> resultValues) {
this.currentResultValues = resultValues;
updateKeyComparatorListBox();
resetChartSeries();
updateYAxisLabels();
updateChartSubtitleAndSetChartAsWidget();
updateChartLabels();
updateChartSubtitle();
showResultData();
}
@@ -161,13 +182,13 @@ public class ResultsChart extends AbstractResultsPresenter<Number> {
seriesMappedByGroupKey = new HashMap<GroupKey, Series>();
}
private void updateYAxisLabels() {
private void updateChartLabels() {
chart.getYAxis().setAxisTitleText(getCurrentResult().getResultSignifier());
chart.setToolTip(new ToolTip().setValueDecimals(getCurrentResult().getValueDecimals()).setValueSuffix(
getCurrentResult().getUnitSignifier()));
chart.setToolTip(new ToolTip().setValueDecimals(decimalsListBox.getValue())
.setValueSuffix(getCurrentResult().getUnitSignifier()));
}
private void updateChartSubtitleAndSetChartAsWidget() {
private void updateChartSubtitle() {
chart.setChartSubtitle(new ChartSubtitle().setText(getStringMessages().queryResultsChartSubtitle(
getCurrentResult().getRetrievedDataAmount(), getCurrentResult().getCalculationTimeInSeconds())));
}
@@ -176,7 +197,7 @@ public class ResultsChart extends AbstractResultsPresenter<Number> {
buildMainKeyMapAndSetXAxisCategories();
createAndAddSeriesToChart();
for (Entry<GroupKey, ? extends Number> resultEntry : getCurrentResult().getResults().entrySet()) {
for (Entry<GroupKey, ? extends Number> resultEntry : currentResultValues.entrySet()) {
GroupKey mainKey = resultEntry.getKey().getMainKey();
Point point = new Point(mainKeyToXValueMap.get(mainKey), resultEntry.getValue());
point.setName(mainKey.asString());
@@ -18,16 +18,16 @@ import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.client.shared.controls.ScrolledTabLayoutPanel;
import com.sap.sailing.gwt.ui.datamining.DataMiningResources;
import com.sap.sailing.gwt.ui.datamining.ResultsPresenter;
import com.sap.sse.datamining.shared.QueryResult;
import com.sap.sse.datamining.shared.impl.dto.QueryResultDTO;
public class TabbedResultsPresenter implements ResultsPresenter<Number> {
public class TabbedResultsPresenter implements ResultsPresenter {
private static final DataMiningResources resources = GWT.create(DataMiningResources.class);
private final StringMessages stringMessages;
private final ScrolledTabLayoutPanel tabPanel;
private final Map<Widget, ResultsPresenter<Number>> presentersMappedByHeader;
private final Map<Widget, ResultsPresenter> presentersMappedByHeader;
public TabbedResultsPresenter(StringMessages stringMessages) {
this.stringMessages = stringMessages;
@@ -63,7 +63,7 @@ public class TabbedResultsPresenter implements ResultsPresenter<Number> {
}
@Override
public void showResult(QueryResult<Number> result) {
public void showResult(QueryResultDTO<?> result) {
getSelectedHeader().setText(result.getResultSignifier());
getSelectedPresenter().showResult(result);
}
@@ -87,7 +87,7 @@ public class TabbedResultsPresenter implements ResultsPresenter<Number> {
}
@Override
public QueryResult<Number> getCurrentResult() {
public QueryResultDTO<?> getCurrentResult() {
return getSelectedPresenter().getCurrentResult();
}
@@ -95,13 +95,13 @@ public class TabbedResultsPresenter implements ResultsPresenter<Number> {
return (CloseableTabHeader) tabPanel.getTabWidget(tabPanel.getSelectedIndex());
}
private ResultsPresenter<Number> getSelectedPresenter() {
private ResultsPresenter getSelectedPresenter() {
return presentersMappedByHeader.get(getSelectedHeader());
}
private void addTabAndFocus() {
CloseableTabHeader tabHeader = new CloseableTabHeader();
ResultsPresenter<Number> tabPresenter = new MultiResultsPresenter(stringMessages);
ResultsPresenter tabPresenter = new MultiResultsPresenter(stringMessages);
presentersMappedByHeader.put(tabHeader, tabPresenter);
tabPanel.insert(tabPresenter.getWidget(), tabHeader, tabPanel.getWidgetCount() - 1);
@@ -0,0 +1,45 @@
package com.sap.sailing.gwt.ui.datamining.presentation.dataproviders;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import com.sap.sse.datamining.shared.GroupKey;
import com.sap.sse.datamining.shared.impl.dto.QueryResultDTO;
public abstract class AbstractResultDataProvider<ResultType> {
private final Class<ResultType> resultType;
public AbstractResultDataProvider(Class<ResultType> resultType) {
this.resultType = resultType;
}
public Class<ResultType> getResultType() {
return resultType;
}
public abstract Collection<String> getDataKeys();
public Map<GroupKey, Number> getData(QueryResultDTO<?> result, String dataKey) {
if (!acceptsResultsOfType(result.getResultType())) {
throw new IllegalArgumentException("This data provider doesn't work for results of the type '" + result.getResultType() + "'");
}
Map<GroupKey, Number> data = new HashMap<>();
Map<GroupKey, ?> results = result.getResults();
for (GroupKey groupKey : results.keySet()) {
@SuppressWarnings("unchecked")
ResultType value = (ResultType) results.get(groupKey);
data.put(groupKey, getData(value, dataKey));
}
return data;
}
public abstract boolean acceptsResultsOfType(String type);
protected abstract Number getData(ResultType result, String dataKey);
public abstract String getDefaultDataKeyFor(QueryResultDTO<?> result);
}
@@ -0,0 +1,62 @@
package com.sap.sailing.gwt.ui.datamining.presentation.dataproviders;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import com.sap.sailing.datamining.shared.dto.DistanceDTO;
import com.sap.sse.datamining.shared.impl.dto.QueryResultDTO;
public class DistanceDataProvider extends AbstractResultDataProvider<DistanceDTO> {
private final List<String> dataKeys;
public DistanceDataProvider() {
super(DistanceDTO.class);
dataKeys = new ArrayList<>();
dataKeys.add("Geographical Miles");
dataKeys.add("Sea Miles");
dataKeys.add("Nautical Miles");
dataKeys.add("Meters");
dataKeys.add("Kilometers");
dataKeys.add("Central Angle Degree");
dataKeys.add("Central Angle Radian");
}
@Override
public Collection<String> getDataKeys() {
return dataKeys;
}
@Override
public boolean acceptsResultsOfType(String type) {
return getResultType().getName().equals(type);
}
@Override
protected Number getData(DistanceDTO distance, String dataKey) {
switch (dataKey) {
case "Geographical Miles":
return distance.getGeographicalMiles();
case "Sea Miles":
return distance.getSeaMiles();
case "Nautical Miles":
return distance.getNauticalMiles();
case "Meters":
return distance.getMeters();
case "Kilometers":
return distance.getKilometers();
case "Central Angle Degree":
return distance.getCentralAngleDegree();
case "Central Angle Radian":
return distance.getCentralAngleRadian();
}
throw new IllegalArgumentException("The given data key '" + dataKey + "' isn't valid");
}
@Override
public String getDefaultDataKeyFor(QueryResultDTO<?> result) {
return dataKeys.get(0);
}
}
@@ -0,0 +1,59 @@
package com.sap.sailing.gwt.ui.datamining.presentation.dataproviders;
import java.util.ArrayList;
import java.util.Collection;
import com.sap.sse.datamining.shared.impl.dto.QueryResultDTO;
public class NumberDataProvider extends AbstractResultDataProvider<Number> {
private final static String FLOAT = "Float";
private final static String INTEGER = "Integer";
private final Collection<String> dataKeys;
public NumberDataProvider() {
super(Number.class);
dataKeys = new ArrayList<>();
dataKeys.add(FLOAT);
dataKeys.add(INTEGER);
}
@Override
public Collection<String> getDataKeys() {
return dataKeys;
}
@Override
public boolean acceptsResultsOfType(String type) {
return type.equals(Number.class.getName()) ||
type.equals(Double.class.getName()) ||
type.equals(Float.class.getName()) ||
type.equals(Long.class.getName()) ||
type.equals(Integer.class.getName()) ||
type.equals(Short.class.getName()) ||
type.equals(Byte.class.getName()) ||
type.equals(double.class.getName()) ||
type.equals(float.class.getName()) ||
type.equals(long.class.getName()) ||
type.equals(int.class.getName()) ||
type.equals(short.class.getName()) ||
type.equals(byte.class.getName());
}
@Override
protected Number getData(Number number, String dataKey) {
switch (dataKey) {
case FLOAT:
return number.doubleValue();
case INTEGER:
return number.intValue();
}
throw new IllegalArgumentException("The given data key '" + dataKey + "' isn't valid");
}
@Override
public String getDefaultDataKeyFor(QueryResultDTO<?> result) {
return result.getValueDecimals() == 0 ? INTEGER : FLOAT;
}
}
@@ -29,9 +29,9 @@ import com.sap.sailing.gwt.ui.datamining.execution.ManagedDataMiningQueryCallbac
import com.sap.sailing.gwt.ui.datamining.execution.SimpleManagedDataMiningQueriesCounter;
import com.sap.sse.datamining.shared.DataMiningSession;
import com.sap.sse.datamining.shared.GroupKey;
import com.sap.sse.datamining.shared.QueryResult;
import com.sap.sse.datamining.shared.impl.GenericGroupKey;
import com.sap.sse.datamining.shared.impl.dto.FunctionDTO;
import com.sap.sse.datamining.shared.impl.dto.QueryResultDTO;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.controls.busyindicator.SimpleBusyIndicator;
@@ -74,6 +74,7 @@ class DimensionFilterSelectionProvider {
return function.getDisplayName();
}
});
dimensionListBox.setWidth("100%");
dimensionChangedHandler = new DimensionChangedHandler();
dimensionListBox.addValueChangeHandler(dimensionChangedHandler);
controlsPanel.add(dimensionListBox);
@@ -100,7 +101,7 @@ class DimensionFilterSelectionProvider {
}
});
selectionTable.setVisible(false);
mainPanel.add(selectionTable);
mainPanel.add(selectionTable.getWidget());
}
private class DimensionChangedHandler implements ValueChangeHandler<FunctionDTO> {
@@ -164,7 +165,7 @@ class DimensionFilterSelectionProvider {
retrieverLevelSelectionProvider.getRetrieverLevel(), dimensionDTOs, filterSelectionDTO,
LocaleInfo.getCurrentLocale().getLocaleName(), new ManagedDataMiningQueryCallback<Set<Object>>(counter) {
@Override
protected void handleSuccess(QueryResult<Set<Object>> result) {
protected void handleSuccess(QueryResultDTO<Set<Object>> result) {
Map<GroupKey, Set<Object>> results = result.getResults();
List<Object> content = new ArrayList<Object>();
@@ -237,13 +238,5 @@ class DimensionFilterSelectionProvider {
public Widget getEntryWidget() {
return mainPanel;
}
public void resizeToHeight(int heightInPX) {
int widthInPX = controlsPanel.getOffsetWidth();
mainPanel.setSize(widthInPX + "px", heightInPX + "px");
int remainingHeightInPX = Math.max(0, heightInPX - controlsPanel.getOffsetHeight());
selectionTable.resizeTo(widthInPX, remainingHeightInPX);
}
}
@@ -6,26 +6,27 @@ import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import com.google.gwt.user.cellview.client.DataGrid;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.TextColumn;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.ProvidesKey;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.sap.sailing.gwt.ui.datamining.FilterSelectionChangedListener;
import com.sap.sse.gwt.client.panels.AbstractFilterablePanel;
public class FilterableSelectionTable<ContentType extends Serializable> extends FlowPanel {
public class FilterableSelectionTable<ContentType extends Serializable> {
private final Set<FilterSelectionChangedListener> listeners;
private final Collection<ContentType> allData;
private int width;
private int height;
private final FlowPanel mainPanel;
private final AbstractFilterablePanel<ContentType> filterPanel;
private String filterText;
private final DataGrid<ContentType> table;
private final CellTable<ContentType> table;
private final ControllableMultiSelectionModel<ContentType> selectionModel;
private final ListDataProvider<ContentType> dataProvider;
@@ -34,7 +35,8 @@ public class FilterableSelectionTable<ContentType extends Serializable> extends
allData = new ArrayList<ContentType>();
table = new DataGrid<ContentType>();
table = new CellTable<>();
table.setWidth("100%");
table.setAutoHeaderRefreshDisabled(true);
table.setAutoFooterRefreshDisabled(true);
@@ -44,6 +46,7 @@ public class FilterableSelectionTable<ContentType extends Serializable> extends
return FilterableSelectionTable.this.getElementAsString(content);
}
};
contentColumn.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
table.addColumn(contentColumn);
selectionModel = new ControllableMultiSelectionModel<ContentType>();
@@ -77,8 +80,9 @@ public class FilterableSelectionTable<ContentType extends Serializable> extends
filterPanel.setVisible(false);
filterText = "";
add(filterPanel);
add(table);
mainPanel = new FlowPanel();
mainPanel.add(filterPanel);
mainPanel.add(table);
}
private String getElementAsString(ContentType element) {
@@ -214,26 +218,14 @@ public class FilterableSelectionTable<ContentType extends Serializable> extends
}
filterPanel.setVisible(visible);
resizeTo(width, height);
}
@Override
public void setVisible(boolean visible) {
super.setVisible(visible);
//FIXME Force a rerendering of the table. Switching the retriever level fixes the display
table.redraw();
mainPanel.setVisible(visible);
}
public void resizeTo(int widthInPX, int heightInPX) {
width = widthInPX;
height = heightInPX;
setSize(width + "px", height+ "px");
filterPanel.setWidth(width + "px");
int tableHeight = filterPanel.isVisible() ? Math.max(0, height - filterPanel.getOffsetHeight()) : height;
table.setSize(width + "px", tableHeight + "px");
//FIXME Force a rerendering of the table. Switching the retriever level fixes the display
table.redraw();
public Widget getWidget() {
return mainPanel;
}
}
@@ -17,7 +17,6 @@ import com.google.gwt.i18n.client.LocaleInfo;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.cellview.client.CellList;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.CustomScrollPanel;
import com.google.gwt.user.client.ui.DockLayoutPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ScrollPanel;
@@ -58,7 +57,7 @@ public class ListRetrieverChainFilterSelectionProvider implements FilterSelectio
private final CellList<LocalizedTypeDTO> retrieverLevelList;
private final SingleSelectionModel<LocalizedTypeDTO> retrieverLevelSelectionModel;
private final ListDataProvider<LocalizedTypeDTO> retrieverLevelDataProvider;
private final SizeProvidingScrollPanel selectionPanel;
private final ScrollPanel selectionPanel;
private final FilterSelectionPresenter selectionPresenter;
private final ScrollPanel selectionPresenterScrollPanel;
@@ -86,7 +85,7 @@ public class ListRetrieverChainFilterSelectionProvider implements FilterSelectio
DockLayoutPanel selectionDockLayoutPanel = new DockLayoutPanel(Unit.PX);
selectionDockLayoutPanel.addNorth(new Label(this.stringMessages.filterBy()), 18);
selectionPanel = new SizeProvidingScrollPanel();
selectionPanel = new ScrollPanel();
selectionDockLayoutPanel.add(selectionPanel);
selectionPresenter = new PlainFilterSelectionPresenter(stringMessages, retrieverChainProvider, this);
@@ -149,7 +148,7 @@ public class ListRetrieverChainFilterSelectionProvider implements FilterSelectio
LocalizedTypeDTO retrievedDataType = retrieverChain.getRetrievedDataType(retrieverLevel);
RetrieverLevelFilterSelectionProvider selectionProvider =
new RetrieverLevelFilterSelectionProvider(session, dataMiningService, errorReporter, ListRetrieverChainFilterSelectionProvider.this, retrieverChain,
retrievedDataType, retrieverLevel, selectionPanel);
retrievedDataType, retrieverLevel);
selectionProvider.setAvailableDimensions(dimensionsEntry.getValue());
selectionProvidersMappedByRetrievedDataType.put(retrievedDataType, selectionProvider);
@@ -337,18 +336,6 @@ public class ListRetrieverChainFilterSelectionProvider implements FilterSelectio
super.setSelected(item, selected);
}
}
private class SizeProvidingScrollPanel extends CustomScrollPanel implements RetrieverLevelFilterSelectionProvider.SizeProvider {
@Override
public int getFreeWidthInPX() {
return getOffsetWidth() - getVerticalScrollbar().asWidget().getOffsetWidth();
}
@Override
public int getFreeHeightInPX() {
//Subtracting a value prevents weird scroll behavior
return getOffsetHeight() - getHorizontalScrollbar().asWidget().getOffsetHeight() - 3;
}
}
@Override
public String getLocalizedShortName() {
@@ -9,9 +9,8 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.ProvidesResize;
import com.google.gwt.user.client.ui.RequiresResize;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.ui.datamining.DataMiningServiceAsync;
import com.sap.sse.common.settings.AbstractSettings;
@@ -35,13 +34,12 @@ public class RetrieverLevelFilterSelectionProvider implements Component<Abstract
private final int retrieverLevel;
private final Collection<FunctionDTO> availableDimensions;
private final HorizontalLayoutPanel mainPanel;
private final HorizontalPanel mainPanel;
private final Collection<DimensionFilterSelectionProvider> dimensionSelectionProviders;
private final SizeProvider sizeProvider;
public RetrieverLevelFilterSelectionProvider(DataMiningSession session, DataMiningServiceAsync dataMiningService,
ErrorReporter errorReporter, ListRetrieverChainFilterSelectionProvider retrieverChainSelectionProvider, DataRetrieverChainDefinitionDTO retrieverChain,
LocalizedTypeDTO retrievedDataType, int retrieverLevel, SizeProvider sizeProvider) {
LocalizedTypeDTO retrievedDataType, int retrieverLevel) {
this.dataMiningService = dataMiningService;
this.errorReporter = errorReporter;
@@ -52,10 +50,8 @@ public class RetrieverLevelFilterSelectionProvider implements Component<Abstract
this.retrieverLevel = retrieverLevel;
availableDimensions = new ArrayList<>();
mainPanel = new HorizontalLayoutPanel();
mainPanel = new HorizontalPanel();
dimensionSelectionProviders = new ArrayList<>();
this.sizeProvider = sizeProvider;
}
public void setAvailableDimensions(Collection<FunctionDTO> dimensions) {
@@ -87,8 +83,8 @@ public class RetrieverLevelFilterSelectionProvider implements Component<Abstract
private void addDimensionSelectionProvider(DimensionFilterSelectionProvider dimensionFilter) {
dimensionSelectionProviders.add(dimensionFilter);
dimensionFilter.getEntryWidget().getElement().getStyle().setDisplay(Display.INLINE);
mainPanel.add(dimensionFilter.getEntryWidget());
mainPanel.onResize();
}
boolean shouldRemoveDimensionSelectionProvider() {
@@ -99,7 +95,6 @@ public class RetrieverLevelFilterSelectionProvider implements Component<Abstract
dimensionFilter.clearSelection(); // Notifies the listeners, if values were selected
dimensionSelectionProviders.remove(dimensionFilter);
mainPanel.remove(dimensionFilter.getEntryWidget());
mainPanel.onResize();
}
void updateAvailableDimensions() {
@@ -115,7 +110,6 @@ public class RetrieverLevelFilterSelectionProvider implements Component<Abstract
remainingDimensions.add(null);
dimensionFilter.setAvailableDimensions(remainingDimensions);
}
mainPanel.onResize();
}
private Collection<FunctionDTO> getSelectedDimensions() {
@@ -245,23 +239,5 @@ public class RetrieverLevelFilterSelectionProvider implements Component<Abstract
public String getDependentCssClassName() {
return "singleRetrieverLevelSelectionPanel";
}
interface SizeProvider {
public int getFreeWidthInPX();
public int getFreeHeightInPX();
}
private class HorizontalLayoutPanel extends HorizontalPanel implements RequiresResize, ProvidesResize {
@Override
public void onResize() {
int heightInPX = sizeProvider.getFreeHeightInPX();
setHeight(heightInPX + "px");
for (DimensionFilterSelectionProvider selectionProvider : dimensionSelectionProviders) {
selectionProvider.resizeToHeight(heightInPX);
}
}
}
}
@@ -14,7 +14,6 @@ import org.osgi.framework.BundleContext;
import org.osgi.util.tracker.ServiceTracker;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.sap.sailing.datamining.shared.SailingDataMiningSerializationDummy;
import com.sap.sailing.gwt.ui.datamining.DataMiningService;
import com.sap.sailing.server.RacingEventService;
import com.sap.sse.datamining.DataMiningServer;
@@ -22,17 +21,18 @@ import com.sap.sse.datamining.Query;
import com.sap.sse.datamining.StatisticQueryDefinition;
import com.sap.sse.datamining.components.AggregationProcessorDefinition;
import com.sap.sse.datamining.components.DataRetrieverChainDefinition;
import com.sap.sse.datamining.data.QueryResult;
import com.sap.sse.datamining.factories.DataMiningDTOFactory;
import com.sap.sse.datamining.functions.Function;
import com.sap.sse.datamining.impl.components.DataRetrieverTypeWithInformation;
import com.sap.sse.datamining.shared.DataMiningSession;
import com.sap.sse.datamining.shared.QueryResult;
import com.sap.sse.datamining.shared.SSEDataMiningSerializationDummy;
import com.sap.sse.datamining.shared.SerializationDummy;
import com.sap.sse.datamining.shared.dto.StatisticQueryDefinitionDTO;
import com.sap.sse.datamining.shared.impl.dto.AggregationProcessorDefinitionDTO;
import com.sap.sse.datamining.shared.impl.dto.DataRetrieverChainDefinitionDTO;
import com.sap.sse.datamining.shared.impl.dto.FunctionDTO;
import com.sap.sse.datamining.shared.impl.dto.LocalizedTypeDTO;
import com.sap.sse.datamining.shared.impl.dto.QueryResultDTO;
import com.sap.sse.i18n.ResourceBundleStringMessages;
public class DataMiningServiceImpl extends RemoteServiceServlet implements DataMiningService {
@@ -172,7 +172,7 @@ public class DataMiningServiceImpl extends RemoteServiceServlet implements DataM
}
@Override
public QueryResult<Set<Object>> getDimensionValuesFor(DataMiningSession session, DataRetrieverChainDefinitionDTO dataRetrieverChainDefinitionDTO,
public QueryResultDTO<Set<Object>> getDimensionValuesFor(DataMiningSession session, DataRetrieverChainDefinitionDTO dataRetrieverChainDefinitionDTO,
int retrieverLevel, Iterable<FunctionDTO> dimensionDTOs, Map<Integer, Map<FunctionDTO, Collection<?>>> filterSelectionDTO, String localeInfoName) {
DataMiningServer dataMiningServer = getDataMiningServer();
DataRetrieverChainDefinition<RacingEventService, ?> retrieverChainDefinition = dataMiningServer.getDataRetrieverChainDefinition(dataRetrieverChainDefinitionDTO.getId());
@@ -180,8 +180,8 @@ public class DataMiningServiceImpl extends RemoteServiceServlet implements DataM
Map<Integer, Map<Function<?>, Collection<?>>> filterSelection = filterSelectionDTOAsFilterSelection(filterSelectionDTO);
Locale locale = ResourceBundleStringMessages.Util.getLocaleFor(localeInfoName);
Query<Set<Object>> dimensionValuesQuery = dataMiningServer.createDimensionValuesQuery(retrieverChainDefinition, retrieverLevel, dimensions, filterSelection, locale);
QueryResult<Set<Object>> result = getDataMiningServer().runNewQueryAndAbortPreviousQueries(session, dimensionValuesQuery);
return result;
QueryResult<Set<Object>> result = dataMiningServer.runNewQueryAndAbortPreviousQueries(session, dimensionValuesQuery);
return dataMiningServer.convertToDTO(result);
}
private Collection<Function<?>> functionDTOsAsFunctions(Iterable<FunctionDTO> functionDTOs) {
@@ -217,20 +217,16 @@ public class DataMiningServiceImpl extends RemoteServiceServlet implements DataM
}
@Override
public <ResultType extends Number> QueryResult<ResultType> runQuery(DataMiningSession session, StatisticQueryDefinitionDTO queryDefinitionDTO) {
StatisticQueryDefinition<RacingEventService, ?, ?, ResultType> queryDefinition = getDataMiningServer().getQueryDefinitionForDTO(queryDefinitionDTO);
Query<ResultType> query = getDataMiningServer().createQuery(queryDefinition);
QueryResult<ResultType> result = getDataMiningServer().runNewQueryAndAbortPreviousQueries(session, query);
return result;
public <ResultType> QueryResultDTO<ResultType> runQuery(DataMiningSession session, StatisticQueryDefinitionDTO queryDefinitionDTO) {
DataMiningServer dataMiningServer = getDataMiningServer();
StatisticQueryDefinition<RacingEventService, ?, ?, ResultType> queryDefinition = dataMiningServer.getQueryDefinitionForDTO(queryDefinitionDTO);
Query<ResultType> query = dataMiningServer.createQuery(queryDefinition);
QueryResult<ResultType> result = dataMiningServer.runNewQueryAndAbortPreviousQueries(session, query);
return dataMiningServer.convertToDTO(result);
}
@Override
public SSEDataMiningSerializationDummy pseudoMethodSoThatSomeSSEDataMiningClassesAreAddedToTheGWTSerializationPolicy() {
return null;
}
@Override
public SailingDataMiningSerializationDummy pseudoMethodSoThatSomeSailingDataMiningClassesAreAddedToTheGWTSerializationPolicy() {
public SerializationDummy pseudoMethodSoThatSomeClassesAreAddedToTheGWTSerializationPolicy() {
return null;
}
@@ -22,10 +22,12 @@ import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.impl.BoatImpl;
import com.sap.sailing.domain.base.impl.CourseImpl;
import com.sap.sailing.domain.base.impl.MarkImpl;
import com.sap.sailing.domain.base.impl.PersonImpl;
import com.sap.sailing.domain.base.impl.RaceDefinitionImpl;
import com.sap.sailing.domain.base.impl.RegattaImpl;
import com.sap.sailing.domain.base.impl.TeamImpl;
import com.sap.sailing.domain.base.impl.WaypointImpl;
import com.sap.sailing.domain.common.RegattaName;
import com.sap.sailing.domain.common.RegattaNameAndRaceName;
import com.sap.sailing.domain.common.impl.DegreeBearingImpl;
@@ -124,14 +126,35 @@ public class TrackedRaceWithGPSFixStoreContentsReplicationTest extends AbstractS
return trackedRegatta;
}
/**
* See bugs 3249 and 3006. The hypothesis for these two bugs is that the TrackedRace, when replicated through the initial load,
* loses its listener relationship with the CourseImpl object because the course's listener collection is transient.
*/
@Test
public void testReplicatedTrackedRaceIsRegisteredAsCourseListener() throws InterruptedException {
final String HUMBA = "Humba";
final TrackedRace replicaTrackedRace = replica.getTrackedRace(raceIdentifier);
final Waypoint newMasterWaypoint = new WaypointImpl(new MarkImpl(HUMBA));
trackedRace.getRace().getCourse().addWaypoint(/* zeroBasedPosition */ 0, newMasterWaypoint);
assertEquals(newMasterWaypoint, trackedRace.getRace().getCourse().getWaypoints().iterator().next());
assertEquals(newMasterWaypoint, trackedRace.getRace().getCourse().getLegs().iterator().next().getFrom());
assertEquals(newMasterWaypoint, trackedRace.getTrackedLegs().iterator().next().getLeg().getFrom());
Thread.sleep(1000); // wait until course change has been replicated
assertEquals(HUMBA, replicaTrackedRace.getRace().getCourse().getWaypoints().iterator().next().getName());
assertEquals(HUMBA, replicaTrackedRace.getRace().getCourse().getLegs().iterator().next().getFrom().getName());
assertEquals(Util.size(trackedRace.getTrackedLegs()), Util.size(replicaTrackedRace.getTrackedLegs()));
}
@Test
public void testGPSFixReplication() throws InterruptedException {
final GPSFixMovingImpl fix = new GPSFixMovingImpl(new DegreePosition(1, 2), new MillisecondsTimePoint(12345),
new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123)));
trackedRace.recordFix(competitor, fix);
Thread.sleep(1000);
TrackedRace replicaTrackedRace = replica.getTrackedRace(raceIdentifier);
Competitor replicaCompetitor = replicaTrackedRace.getRace().getCompetitors().iterator().next();
final TrackedRace replicaTrackedRace = replica.getTrackedRace(raceIdentifier);
final Competitor replicaCompetitor = replicaTrackedRace.getRace().getCompetitors().iterator().next();
assertNotNull(replicaCompetitor);
GPSFixTrack<Competitor, GPSFixMoving> competitorTrack = replicaTrackedRace.getTrack(replicaCompetitor);
competitorTrack.lockForRead();
@@ -6,7 +6,7 @@ import java.util.Map;
import com.sap.sse.datamining.shared.data.QueryResultState;
import com.sap.sse.datamining.shared.data.Unit;
public interface QueryResult<AggregatedType> extends Serializable {
public interface QueryResultBase<ResultType> extends Serializable {
public QueryResultState getState();
@@ -23,6 +23,6 @@ public interface QueryResult<AggregatedType> extends Serializable {
public int getValueDecimals();
public boolean isEmpty();
public Map<GroupKey, AggregatedType> getResults();
public Map<GroupKey, ResultType> getResults();
}
@@ -6,11 +6,12 @@ import com.sap.sse.datamining.shared.impl.GenericGroupKey;
import com.sap.sse.datamining.shared.impl.dto.ClusterDTO;
@SuppressWarnings("unused")
public final class SSEDataMiningSerializationDummy implements Serializable {
public final class SSEDataMiningSerializationDummy implements SerializationDummy {
private static final long serialVersionUID = 1L;
private GenericGroupKey<String> groupKey;
private ClusterDTO cluster;
private Number n;
private SSEDataMiningSerializationDummy() { }
@@ -0,0 +1,10 @@
package com.sap.sse.datamining.shared;
import java.io.Serializable;
/**
* Marker interface, to include types forcefully in the GWT serialization policy
*/
public interface SerializationDummy extends Serializable {
}
@@ -5,38 +5,44 @@ import java.util.Map;
import com.sap.sse.datamining.shared.AdditionalResultData;
import com.sap.sse.datamining.shared.GroupKey;
import com.sap.sse.datamining.shared.QueryResult;
import com.sap.sse.datamining.shared.QueryResultBase;
import com.sap.sse.datamining.shared.data.QueryResultState;
import com.sap.sse.datamining.shared.data.Unit;
public class QueryResultImpl<AggregatedType> implements QueryResult<AggregatedType> {
private static final long serialVersionUID = 5173796619174827696L;
public abstract class QueryResultBaseImpl<ResultType> implements QueryResultBase<ResultType> {
private static final long serialVersionUID = 5696532932535299241L;
private QueryResultState state;
private Map<GroupKey, AggregatedType> results;
private Map<GroupKey, ResultType> results;
private AdditionalResultData additionalData;
/**
* Constructor for the GWT-Serialization. Don't use this!
*/
@Deprecated
QueryResultImpl() { }
public QueryResultImpl(QueryResultState state, Map<GroupKey, AggregatedType> results) {
public QueryResultBaseImpl() {
}
public QueryResultBaseImpl(QueryResultState state, Map<GroupKey, ResultType> results) {
this(state, results, new NullAdditionalResultData());
}
public QueryResultImpl(QueryResultState state, Map<GroupKey, AggregatedType> results, AdditionalResultData additionalData) {
public QueryResultBaseImpl(QueryResultState state, Map<GroupKey, ResultType> results,
AdditionalResultData additionalData) {
this.state = state;
this.results = new HashMap<GroupKey, AggregatedType>(results);
this.results = new HashMap<GroupKey, ResultType>(results);
this.additionalData = additionalData;
}
@Override
public QueryResultState getState() {
return state;
}
protected AdditionalResultData getAdditionalData() {
return additionalData;
}
@Override
public int getRetrievedDataAmount() {
return additionalData.getRetrievedDataAmount();
@@ -56,12 +62,12 @@ public class QueryResultImpl<AggregatedType> implements QueryResult<AggregatedTy
public String getResultSignifier() {
return additionalData.getResultSignifier();
}
@Override
public Unit getUnit() {
return additionalData.getUnit();
return additionalData.getUnit();
}
@Override
public String getUnitSignifier() {
return additionalData.getUnitSignifier();
@@ -73,12 +79,12 @@ public class QueryResultImpl<AggregatedType> implements QueryResult<AggregatedTy
}
@Override
public Map<GroupKey, AggregatedType> getResults() {
public Map<GroupKey, ResultType> getResults() {
return results;
}
public void addResult(GroupKey key, AggregatedType value) {
public void addResult(GroupKey key, ResultType value) {
results.put(key, value);
}
}
}
@@ -5,6 +5,7 @@ import java.io.Serializable;
public class AggregationProcessorDefinitionDTO implements Serializable, Comparable<AggregationProcessorDefinitionDTO> {
private static final long serialVersionUID = -434497637456305118L;
private String messageKey;
private String extractedTypeName;
private String aggregatedTypeName;
@@ -16,7 +17,8 @@ public class AggregationProcessorDefinitionDTO implements Serializable, Comparab
@Deprecated
AggregationProcessorDefinitionDTO() { }
public AggregationProcessorDefinitionDTO(String extractedTypeName, String aggregatedTypeName, String displayName) {
public AggregationProcessorDefinitionDTO(String messageKey, String extractedTypeName, String aggregatedTypeName, String displayName) {
this.messageKey = messageKey;
this.extractedTypeName = extractedTypeName;
this.aggregatedTypeName = aggregatedTypeName;
this.displayName = displayName;
@@ -44,8 +46,8 @@ public class AggregationProcessorDefinitionDTO implements Serializable, Comparab
final int prime = 31;
int result = 1;
result = prime * result + ((aggregatedTypeName == null) ? 0 : aggregatedTypeName.hashCode());
result = prime * result + ((displayName == null) ? 0 : displayName.hashCode());
result = prime * result + ((extractedTypeName == null) ? 0 : extractedTypeName.hashCode());
result = prime * result + ((messageKey == null) ? 0 : messageKey.hashCode());
return result;
}
@@ -63,16 +65,16 @@ public class AggregationProcessorDefinitionDTO implements Serializable, Comparab
return false;
} else if (!aggregatedTypeName.equals(other.aggregatedTypeName))
return false;
if (displayName == null) {
if (other.displayName != null)
return false;
} else if (!displayName.equals(other.displayName))
return false;
if (extractedTypeName == null) {
if (other.extractedTypeName != null)
return false;
} else if (!extractedTypeName.equals(other.extractedTypeName))
return false;
if (messageKey == null) {
if (other.messageKey != null)
return false;
} else if (!messageKey.equals(other.messageKey))
return false;
return true;
}
@@ -0,0 +1,38 @@
package com.sap.sse.datamining.shared.impl.dto;
import java.util.Map;
import com.sap.sse.datamining.shared.AdditionalResultData;
import com.sap.sse.datamining.shared.GroupKey;
import com.sap.sse.datamining.shared.QueryResultBase;
import com.sap.sse.datamining.shared.data.QueryResultState;
import com.sap.sse.datamining.shared.impl.NullAdditionalResultData;
import com.sap.sse.datamining.shared.impl.QueryResultBaseImpl;
public class QueryResultDTO<ResultType> extends QueryResultBaseImpl<ResultType> implements QueryResultBase<ResultType> {
private static final long serialVersionUID = 3639302996859873603L;
private String resultTypeName;
/**
* Constructor for the GWT-Serialization. Don't use this!
*/
@Deprecated
QueryResultDTO() {
}
public QueryResultDTO(QueryResultState state, Class<ResultType> resultType, Map<GroupKey, ResultType> results) {
this(state, resultType, results, new NullAdditionalResultData());
}
public QueryResultDTO(QueryResultState state, Class<ResultType> resultType, Map<GroupKey, ResultType> results,
AdditionalResultData additionalData) {
super(state, results, additionalData);
this.resultTypeName = resultType.getName();
}
public String getResultType() {
return resultTypeName;
}
}
@@ -18,10 +18,10 @@ import com.sap.sse.datamining.ModifiableDataMiningServer;
import com.sap.sse.datamining.Query;
import com.sap.sse.datamining.components.DataRetrieverChainDefinition;
import com.sap.sse.datamining.components.Processor;
import com.sap.sse.datamining.data.QueryResult;
import com.sap.sse.datamining.functions.Function;
import com.sap.sse.datamining.impl.components.SimpleDataRetrieverChainDefinition;
import com.sap.sse.datamining.shared.GroupKey;
import com.sap.sse.datamining.shared.QueryResult;
import com.sap.sse.datamining.shared.impl.GenericGroupKey;
import com.sap.sse.datamining.shared.impl.dto.FunctionDTO;
import com.sap.sse.datamining.test.data.Test_HasLegOfCompetitorContext;
@@ -25,11 +25,11 @@ import com.sap.sse.datamining.QueryState;
import com.sap.sse.datamining.components.AdditionalResultDataBuilder;
import com.sap.sse.datamining.components.Processor;
import com.sap.sse.datamining.components.ProcessorInstruction;
import com.sap.sse.datamining.data.QueryResult;
import com.sap.sse.datamining.functions.Function;
import com.sap.sse.datamining.impl.components.AbstractParallelProcessor;
import com.sap.sse.datamining.impl.components.AbstractProcessorInstruction;
import com.sap.sse.datamining.shared.GroupKey;
import com.sap.sse.datamining.shared.QueryResult;
import com.sap.sse.datamining.shared.data.QueryResultState;
import com.sap.sse.datamining.shared.impl.GenericGroupKey;
import com.sap.sse.datamining.test.util.ConcurrencyTestsUtil;
@@ -57,7 +57,7 @@ public class TestProcessorQuery {
Collection<Number> dataSource = new ArrayList<>();
dataSource.add(new Number(10));
ProcessorQuery<Double, Iterable<Number>> query = new ProcessorQuery<Double, Iterable<Number>>(
dataSource, stringMessages, Locale.ENGLISH, AdditionalQueryData.NULL_INSTANCE) {
dataSource, stringMessages, Locale.ENGLISH, Double.class, AdditionalQueryData.NULL_INSTANCE) {
@SuppressWarnings("unchecked")
@Override
protected Processor<Iterable<Number>, ?> createFirstProcessor() {
@@ -95,7 +95,7 @@ public class TestProcessorQuery {
Collection<Number> dataSource = new ArrayList<>();
dataSource.add(new Number(10));
ProcessorQuery<Double, Iterable<Number>> query = new ProcessorQuery<Double, Iterable<Number>>(
dataSource, stringMessages, Locale.ENGLISH, AdditionalQueryData.NULL_INSTANCE) {
dataSource, stringMessages, Locale.ENGLISH, Double.class, AdditionalQueryData.NULL_INSTANCE) {
@SuppressWarnings("unchecked")
@Override
protected Processor<Iterable<Number>, ?> createFirstProcessor() {
@@ -161,7 +161,7 @@ public class TestProcessorQuery {
public void testQueryWithTimeoutAndNonBlockingProcess() throws TimeoutException {
final String keyValue = "Sum";
ProcessorQuery<Double, Iterable<Number>> query = new ProcessorQuery<Double, Iterable<Number>>(
createDataSource(), stringMessages, Locale.ENGLISH, AdditionalQueryData.NULL_INSTANCE) {
createDataSource(), stringMessages, Locale.ENGLISH, Double.class, AdditionalQueryData.NULL_INSTANCE) {
@SuppressWarnings("unchecked")
@Override
protected Processor<Iterable<Number>, ?> createFirstProcessor() {
@@ -235,7 +235,7 @@ public class TestProcessorQuery {
@Test
public void testQueryWithError() {
Query<Double> query = new ProcessorQuery<Double, Double>(0.0) {
Query<Double> query = new ProcessorQuery<Double, Double>(0.0, Double.class) {
@SuppressWarnings("unchecked")
@Override
protected Processor<Double, ?> createFirstProcessor() {
@@ -275,7 +275,7 @@ public class TestProcessorQuery {
@Test
public void testQueryWithFailure() {
Query<Double> query = new ProcessorQuery<Double, Double>(0.0) {
Query<Double> query = new ProcessorQuery<Double, Double>(0.0, Double.class) {
@SuppressWarnings("unchecked")
@Override
protected Processor<Double, ?> createFirstProcessor() {
@@ -307,7 +307,7 @@ public class TestProcessorQuery {
@Test
public void testQueryAdditionalData() {
AdditionalQueryData additionalData = new AdditionalStatisticQueryData(UUID.randomUUID());
Query<?> query = new ProcessorQuery<Double, Double>(0.0, additionalData) {
Query<?> query = new ProcessorQuery<Double, Double>(0.0, Double.class, additionalData) {
@Override
protected Processor<Double, ?> createFirstProcessor() {
return null;
@@ -318,7 +318,7 @@ public class TestProcessorQuery {
assertThat(query.getAdditionalData(AdditionalDimensionValuesQueryData.class), nullValue());
additionalData = new AdditionalDimensionValuesQueryData(UUID.randomUUID(), new ArrayList<Function<?>>());
query = new ProcessorQuery<Double, Double>(0.0, additionalData) {
query = new ProcessorQuery<Double, Double>(0.0, Double.class, additionalData) {
@Override
protected Processor<Double, ?> createFirstProcessor() {
return null;
@@ -22,16 +22,16 @@ import com.sap.sse.datamining.StatisticQueryDefinition;
import com.sap.sse.datamining.components.AggregationProcessorDefinition;
import com.sap.sse.datamining.components.DataRetrieverChainDefinition;
import com.sap.sse.datamining.components.Processor;
import com.sap.sse.datamining.data.QueryResult;
import com.sap.sse.datamining.factories.FunctionFactory;
import com.sap.sse.datamining.impl.components.AbstractRetrievalProcessor;
import com.sap.sse.datamining.impl.components.aggregators.ParallelGroupedDoubleDataSumAggregationProcessor;
import com.sap.sse.datamining.impl.components.aggregators.ParallelGroupedNumberDataSumAggregationProcessor;
import com.sap.sse.datamining.impl.data.QueryResultImpl;
import com.sap.sse.datamining.shared.GroupKey;
import com.sap.sse.datamining.shared.QueryResult;
import com.sap.sse.datamining.shared.data.QueryResultState;
import com.sap.sse.datamining.shared.data.Unit;
import com.sap.sse.datamining.shared.impl.AdditionalResultDataImpl;
import com.sap.sse.datamining.shared.impl.GenericGroupKey;
import com.sap.sse.datamining.shared.impl.QueryResultImpl;
import com.sap.sse.datamining.test.util.FunctionTestsUtil;
import com.sap.sse.datamining.test.util.TestsUtil;
import com.sap.sse.datamining.test.util.components.Number;
@@ -56,9 +56,9 @@ public class TestStatisticQuery {
}
});
Query<Double> query = server.createQuery(createQueryDefinition());
Query<java.lang.Number> query = server.createQuery(createQueryDefinition());
assertThat(query.getState(), is(QueryState.NOT_STARTED));
QueryResult<Double> expectedResult = buildExpectedResult(dataSource);
QueryResult<java.lang.Number> expectedResult = buildExpectedResult(dataSource);
verifyResult(query.run(), expectedResult);
}
@@ -66,7 +66,7 @@ public class TestStatisticQuery {
* Creates a query definition, that filters all numbers < 10, groups them by
* their length, extracts the cross sum and aggregates their sum.
*/
private StatisticQueryDefinition<Collection<Number>, Number, Double, Double> createQueryDefinition() {
private StatisticQueryDefinition<Collection<Number>, Number, java.lang.Number, java.lang.Number> createQueryDefinition() {
FunctionFactory functionFactory = FunctionTestsUtil.getFunctionFactory();
@SuppressWarnings("unchecked")
@@ -74,8 +74,8 @@ public class TestStatisticQuery {
retrieverChain.startWith(NumberRetrievalProcessor.class, Number.class, "Number");
Method getCrossSumMethod = FunctionTestsUtil.getMethodFromClass(Number.class, "getCrossSum");
AggregationProcessorDefinition<Double, Double> sumAggregatorDefinition = ParallelGroupedDoubleDataSumAggregationProcessor.getDefinition();
ModifiableStatisticQueryDefinition<Collection<Number>, Number, Double, Double> definition =
AggregationProcessorDefinition<java.lang.Number, java.lang.Number> sumAggregatorDefinition = ParallelGroupedNumberDataSumAggregationProcessor.getDefinition();
ModifiableStatisticQueryDefinition<Collection<Number>, Number, java.lang.Number, java.lang.Number> definition =
new ModifiableStatisticQueryDefinition<>(Locale.ENGLISH, retrieverChain, functionFactory.createMethodWrappingFunction(getCrossSumMethod), sumAggregatorDefinition);
Method getLengthMethod = FunctionTestsUtil.getMethodFromClass(Number.class, "getLength");
@@ -135,17 +135,17 @@ public class TestStatisticQuery {
return dataSource;
}
private QueryResult<Double> buildExpectedResult(Collection<Number> dataSource) {
Map<GroupKey, Double> results = new HashMap<>();
private QueryResult<java.lang.Number> buildExpectedResult(Collection<Number> dataSource) {
Map<GroupKey, java.lang.Number> results = new HashMap<>();
results.put(new GenericGroupKey<Integer>(2), 5.0);
results.put(new GenericGroupKey<Integer>(3), 3.0);
results.put(new GenericGroupKey<Integer>(4), 10.0);
QueryResultImpl<Double> result = new QueryResultImpl<>(QueryResultState.NORMAL, results, new AdditionalResultDataImpl(dataSource.size() - 2, "Cross Sum (Sum)", Unit.None, "", 0, 0));
QueryResultImpl<java.lang.Number> result = new QueryResultImpl<>(QueryResultState.NORMAL, java.lang.Number.class, results, new AdditionalResultDataImpl(dataSource.size() - 2, "Cross Sum (Sum)", Unit.None, "", 0, 0));
return result;
}
private void verifyResult(QueryResult<Double> result, QueryResult<Double> expectedResult) {
private void verifyResult(QueryResult<java.lang.Number> result, QueryResult<java.lang.Number> expectedResult) {
assertThat("The result State isn't correct.", result.getState(), is(expectedResult.getState()));
assertThat("Result values aren't correct.", result.getResults(), is(expectedResult.getResults()));
assertThat("Retrieved data amount isn't correct.", result.getRetrievedDataAmount(), is(expectedResult.getRetrievedDataAmount()));
@@ -5,29 +5,36 @@ import static org.junit.Assert.assertThat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import com.sap.sse.datamining.components.Processor;
import com.sap.sse.datamining.impl.components.GroupedDataEntry;
import com.sap.sse.datamining.shared.GroupKey;
import com.sap.sse.datamining.shared.impl.GenericGroupKey;
import com.sap.sse.datamining.test.util.ConcurrencyTestsUtil;
import com.sap.sse.datamining.test.util.components.NullProcessor;
public class TestAbstractStoringParallelAggregationProcessor {
private Collection<Processor<Integer, ?>> receivers;
private Collection<Processor<Map<GroupKey, Integer>, ?>> receivers;
private boolean receiverWasToldToFinish = false;
private Integer receivedElement = null;
private GroupKey groupKey = new GenericGroupKey<>("Key");
private Map<GroupKey, Integer> result = null;
private Collection<Integer> elementStore = new ArrayList<>();
private Collection<GroupedDataEntry<Integer>> elementStore = new ArrayList<>();
@Before
public void initializeReceivers() {
Processor<Integer, Void> receiver = new NullProcessor<Integer, Void>(Integer.class, Void.class) {
@SuppressWarnings("unchecked")
Processor<Map<GroupKey, Integer>, Void> receiver = new NullProcessor<Map<GroupKey,Integer>, Void>((Class<Map<GroupKey, Integer>>)(Class<?>) Map.class, Void.class) {
@Override
public void processElement(Integer element) {
receivedElement = element;
public void processElement(Map<GroupKey, Integer> element) {
result = element;
}
@Override
public void finish() throws InterruptedException {
@@ -41,43 +48,48 @@ public class TestAbstractStoringParallelAggregationProcessor {
@Test
public void testAbstractAggregationHandling() throws InterruptedException {
Processor<Integer, Integer> processor = new AbstractParallelStoringAggregationProcessor<Integer, Integer>(Integer.class, Integer.class, ConcurrencyTestsUtil.getExecutor(), receivers, "Sum") {
Processor<GroupedDataEntry<Integer>, Map<GroupKey, Integer>> processor = new AbstractParallelGroupedDataStoringAggregationProcessor<Integer, Integer>(ConcurrencyTestsUtil.getExecutor(), receivers, "Sum") {
@Override
protected void storeElement(Integer element) {
protected void storeElement(GroupedDataEntry<Integer> element) {
elementStore.add(element);
}
@Override
protected Integer aggregateResult() {
Integer sum = 0;
for (Integer element : elementStore) {
sum += element;
protected Map<GroupKey, Integer> aggregateResult() {
Map<GroupKey, Integer> result = new HashMap<>();
for (GroupedDataEntry<Integer> element : elementStore) {
GroupKey key = element.getKey();
if (!result.containsKey(key)) {
result.put(key, 0);
}
result.put(key, result.get(key) + element.getDataEntry());
}
return sum;
return result;
}
};
processElementAndVerifyThatItWasStored(processor, 42);
processElementAndVerifyThatItWasStored(processor, 7);
processElementAndVerifyThatItWasStored(processor, new GroupedDataEntry<>(groupKey, 42));
processElementAndVerifyThatItWasStored(processor, new GroupedDataEntry<>(groupKey, 7));
processor.finish();
assertThat("The receiver wasn't told to finish", receiverWasToldToFinish, is(true));
Integer expectedReceivedElement = 42 + 7;
assertThat(receivedElement, is(expectedReceivedElement));
int expectedData = 42 + 7;
assertThat(result.get(groupKey), is(expectedData));
}
private void processElementAndVerifyThatItWasStored(Processor<Integer, Integer> processor, int element) {
private void processElementAndVerifyThatItWasStored(Processor<GroupedDataEntry<Integer>, ?> processor, GroupedDataEntry<Integer> element) {
processor.processElement(element);
ConcurrencyTestsUtil.sleepFor(100); //Giving the processor time to process the instructions
assertThat("The element store doesn't contain the previously processed element '" + element + "'", elementStore.contains(element), is(true));
}
@SuppressWarnings("unchecked")
@Test(timeout=5000)
public void testThatTheLockIsReleasedAfterStoringFailed() throws InterruptedException {
Collection<Processor<Integer, ?>> receivers = new HashSet<>();
receivers.add(new NullProcessor<Integer, Void>(Integer.class, Void.class) {
Collection<Processor<Map<GroupKey, Integer>, ?>> receivers = new HashSet<>();
receivers.add(new NullProcessor<Map<GroupKey, Integer>, Void>((Class<Map<GroupKey, Integer>>)(Class<?>) Map.class, Void.class) {
@Override
public void processElement(Integer element) {
receivedElement = element;
public void processElement(Map<GroupKey, Integer> element) {
result = element;
}
@Override
public void finish() throws InterruptedException {
@@ -92,32 +104,36 @@ public class TestAbstractStoringParallelAggregationProcessor {
}
}
});
Processor<Integer, Integer> processor = new AbstractParallelStoringAggregationProcessor<Integer, Integer>(Integer.class, Integer.class, ConcurrencyTestsUtil.getExecutor(), receivers, "Sum") {
Processor<GroupedDataEntry<Integer>, Map<GroupKey, Integer>> processor = new AbstractParallelGroupedDataStoringAggregationProcessor<Integer, Integer>(ConcurrencyTestsUtil.getExecutor(), receivers, "Sum") {
@Override
protected void storeElement(Integer element) {
if (element < 0) {
protected void storeElement(GroupedDataEntry<Integer> element) {
if (element.getDataEntry() < 0) {
throw new IllegalArgumentException("The element mustn't be negative");
}
elementStore.add(element);
}
@Override
protected Integer aggregateResult() {
Integer sum = 0;
for (Integer element : elementStore) {
sum += element;
protected Map<GroupKey, Integer> aggregateResult() {
Map<GroupKey, Integer> result = new HashMap<>();
for (GroupedDataEntry<Integer> element : elementStore) {
GroupKey key = element.getKey();
if (!result.containsKey(key)) {
result.put(key, 0);
}
result.put(key, result.get(key) + element.getDataEntry());
}
return sum;
return result;
}
};
processor.processElement(-1);
processor.processElement(42);
processor.processElement(7);
processor.processElement(new GroupedDataEntry<>(groupKey, -1));
processor.processElement(new GroupedDataEntry<>(groupKey, 42));
processor.processElement(new GroupedDataEntry<>(groupKey, 7));
processor.finish();
assertThat("The receiver wasn't told to finish", receiverWasToldToFinish, is(true));
Integer expectedReceivedElement = 42 + 7;
assertThat(receivedElement, is(expectedReceivedElement));
int expectedData = 42 + 7;
assertThat(result.get(groupKey), is(expectedData));
}
}
@@ -16,61 +16,61 @@ import com.sap.sse.datamining.shared.impl.GenericGroupKey;
import com.sap.sse.datamining.test.util.ConcurrencyTestsUtil;
import com.sap.sse.datamining.test.util.components.NullProcessor;
public class TestParallelDoubleAggregationProcessors {
public class TestParallelAggregationProcessors {
private Collection<Processor<Map<GroupKey, Double>, ?>> receivers;
private Map<GroupKey, Double> receivedAggregations;
private Collection<Processor<Map<GroupKey, Number>, ?>> receivers;
private Map<GroupKey, Number> receivedAggregations;
@Test
public void testSumAggregationProcessor() throws InterruptedException {
Processor<GroupedDataEntry<Double>, Map<GroupKey, Double>> sumAggregationProcessor = ParallelGroupedDoubleDataSumAggregationProcessor.getDefinition().construct(ConcurrencyTestsUtil.getExecutor(), receivers);
Collection<GroupedDataEntry<Double>> elements = createElements();
Processor<GroupedDataEntry<Number>, Map<GroupKey, Number>> sumAggregationProcessor = ParallelGroupedNumberDataSumAggregationProcessor.getDefinition().construct(ConcurrencyTestsUtil.getExecutor(), receivers);
Collection<GroupedDataEntry<Number>> elements = createElements();
ConcurrencyTestsUtil.processElements(sumAggregationProcessor, elements);
sumAggregationProcessor.finish();
Map<GroupKey, Double> expectedReceivedAggregations = computeExpectedSumAggregations(elements);
Map<GroupKey, Number> expectedReceivedAggregations = computeExpectedSumAggregations(elements);
ConcurrencyTestsUtil.verifyResultData(receivedAggregations, expectedReceivedAggregations);
}
private Map<GroupKey, Double> computeExpectedSumAggregations(Collection<GroupedDataEntry<Double>> elements) {
Map<GroupKey, Double> expectedSumAggregations = new HashMap<>();
for (GroupedDataEntry<Double> element : elements) {
private Map<GroupKey, Number> computeExpectedSumAggregations(Collection<GroupedDataEntry<Number>> elements) {
Map<GroupKey, Number> expectedSumAggregations = new HashMap<>();
for (GroupedDataEntry<Number> element : elements) {
GroupKey key = element.getKey();
if (!expectedSumAggregations.containsKey(key)) {
expectedSumAggregations.put(key, 0.0);
}
Double currentValue = expectedSumAggregations.get(key);
expectedSumAggregations.put(key, currentValue + element.getDataEntry());
Number currentValue = expectedSumAggregations.get(key);
expectedSumAggregations.put(key, currentValue.doubleValue() + element.getDataEntry().doubleValue());
}
return expectedSumAggregations;
}
@Test
public void testAverageAggregationProcessor() throws InterruptedException {
Processor<GroupedDataEntry<Double>, Map<GroupKey, Double>> averageAggregationProcessor = ParallelGroupedDoubleDataAverageAggregationProcessor.getDefinition().construct(ConcurrencyTestsUtil.getExecutor(), receivers);
Collection<GroupedDataEntry<Double>> elements = createElements();
Processor<GroupedDataEntry<Number>, Map<GroupKey, Number>> averageAggregationProcessor = ParallelGroupedNumberDataAverageAggregationProcessor.getDefinition().construct(ConcurrencyTestsUtil.getExecutor(), receivers);
Collection<GroupedDataEntry<Number>> elements = createElements();
ConcurrencyTestsUtil.processElements(averageAggregationProcessor, elements);
averageAggregationProcessor.finish();
Map<GroupKey, Double> expectedReceivedAggregations = computeExpectedAverageAggregations(elements);
Map<GroupKey, Number> expectedReceivedAggregations = computeExpectedAverageAggregations(elements);
ConcurrencyTestsUtil.verifyResultData(receivedAggregations, expectedReceivedAggregations);
}
private Map<GroupKey, Double> computeExpectedAverageAggregations(Collection<GroupedDataEntry<Double>> elements) {
Map<GroupKey, Double> result = new HashMap<>();
private Map<GroupKey, Number> computeExpectedAverageAggregations(Collection<GroupedDataEntry<Number>> elements) {
Map<GroupKey, Number> result = new HashMap<>();
Map<GroupKey, Double> sumAggregations = computeExpectedSumAggregations(elements);
Map<GroupKey, Number> sumAggregations = computeExpectedSumAggregations(elements);
Map<GroupKey, Double> elementAmountPerKey = countElementAmountPerKey(elements);
for (Entry<GroupKey, Double> sumAggregationEntry : sumAggregations.entrySet()) {
for (Entry<GroupKey, Number> sumAggregationEntry : sumAggregations.entrySet()) {
GroupKey key = sumAggregationEntry.getKey();
result.put(key, sumAggregationEntry.getValue() / elementAmountPerKey.get(key));
result.put(key, sumAggregationEntry.getValue().doubleValue() / elementAmountPerKey.get(key));
}
return result;
}
private Map<GroupKey, Double> countElementAmountPerKey(Collection<GroupedDataEntry<Double>> elements) {
private Map<GroupKey, Double> countElementAmountPerKey(Collection<GroupedDataEntry<Number>> elements) {
Map<GroupKey, Double> elementAmountPerKey = new HashMap<>();
for (GroupedDataEntry<Double> element : elements) {
for (GroupedDataEntry<?> element : elements) {
GroupKey key = element.getKey();
if (!elementAmountPerKey.containsKey(key)) {
elementAmountPerKey.put(key, 0.0);
@@ -83,17 +83,17 @@ public class TestParallelDoubleAggregationProcessors {
@Test
public void testMedianAggregationProcessor() throws InterruptedException {
Processor<GroupedDataEntry<Double>, Map<GroupKey, Double>> medianAggregationProcessor = ParallelGroupedDoubleDataMedianAggregationProcessor.getDefinition().construct(ConcurrencyTestsUtil.getExecutor(), receivers);
Collection<GroupedDataEntry<Double>> elements = createElements();
Processor<GroupedDataEntry<Number>, Map<GroupKey, Number>> medianAggregationProcessor = ParallelGroupedNumberDataMedianAggregationProcessor.getDefinition().construct(ConcurrencyTestsUtil.getExecutor(), receivers);
Collection<GroupedDataEntry<Number>> elements = createElements();
ConcurrencyTestsUtil.processElements(medianAggregationProcessor, elements);
medianAggregationProcessor.finish();
Map<GroupKey, Double> expectedReceivedAggregations = computeExpectedMedianAggregations();
Map<GroupKey, Number> expectedReceivedAggregations = computeExpectedMedianAggregations();
ConcurrencyTestsUtil.verifyResultData(receivedAggregations, expectedReceivedAggregations);
}
private Map<GroupKey, Double> computeExpectedMedianAggregations() {
Map<GroupKey, Double> result = new HashMap<>();
private Map<GroupKey, Number> computeExpectedMedianAggregations() {
Map<GroupKey, Number> result = new HashMap<>();
result.put(new GenericGroupKey<Integer>(1), 7.0);
result.put(new GenericGroupKey<Integer>(2), 6.0);
result.put(new GenericGroupKey<Integer>(3), 5.0);
@@ -102,17 +102,17 @@ public class TestParallelDoubleAggregationProcessors {
@Test
public void testMaxAggregationProcessor() throws InterruptedException {
Processor<GroupedDataEntry<Double>, Map<GroupKey, Double>> maxAggregationProcessor = ParallelGroupedDoubleDataMaxAggregationProcessor.getDefinition().construct(ConcurrencyTestsUtil.getExecutor(), receivers);
Collection<GroupedDataEntry<Double>> elements = createElements();
Processor<GroupedDataEntry<Number>, Map<GroupKey, Number>> maxAggregationProcessor = ParallelGroupedNumberDataMaxAggregationProcessor.getDefinition().construct(ConcurrencyTestsUtil.getExecutor(), receivers);
Collection<GroupedDataEntry<Number>> elements = createElements();
ConcurrencyTestsUtil.processElements(maxAggregationProcessor, elements);
maxAggregationProcessor.finish();
Map<GroupKey, Double> expectedReceivedAggregations = computeExpectedMaxAggregations();
Map<GroupKey, Number> expectedReceivedAggregations = computeExpectedMaxAggregations();
ConcurrencyTestsUtil.verifyResultData(receivedAggregations, expectedReceivedAggregations);
}
private Map<GroupKey, Double> computeExpectedMaxAggregations() {
Map<GroupKey, Double> result = new HashMap<>();
private Map<GroupKey, Number> computeExpectedMaxAggregations() {
Map<GroupKey, Number> result = new HashMap<>();
result.put(new GenericGroupKey<Integer>(1), 10.0);
result.put(new GenericGroupKey<Integer>(2), 7.0);
result.put(new GenericGroupKey<Integer>(3), 5.0);
@@ -121,17 +121,17 @@ public class TestParallelDoubleAggregationProcessors {
@Test
public void testMinAggregationProcessor() throws InterruptedException {
Processor<GroupedDataEntry<Double>, Map<GroupKey, Double>> minAggregationProcessor = ParallelGroupedDoubleDataMinAggregationProcessor.getDefinition().construct(ConcurrencyTestsUtil.getExecutor(), receivers);
Collection<GroupedDataEntry<Double>> elements = createElements();
Processor<GroupedDataEntry<Number>, Map<GroupKey, Number>> minAggregationProcessor = ParallelGroupedNumberDataMinAggregationProcessor.getDefinition().construct(ConcurrencyTestsUtil.getExecutor(), receivers);
Collection<GroupedDataEntry<Number>> elements = createElements();
ConcurrencyTestsUtil.processElements(minAggregationProcessor, elements);
minAggregationProcessor.finish();
Map<GroupKey, Double> expectedReceivedAggregations = computeExpectedMinAggregations();
Map<GroupKey, Number> expectedReceivedAggregations = computeExpectedMinAggregations();
ConcurrencyTestsUtil.verifyResultData(receivedAggregations, expectedReceivedAggregations);
}
private Map<GroupKey, Double> computeExpectedMinAggregations() {
Map<GroupKey, Double> result = new HashMap<>();
private Map<GroupKey, Number> computeExpectedMinAggregations() {
Map<GroupKey, Number> result = new HashMap<>();
result.put(new GenericGroupKey<Integer>(1), 5.0);
result.put(new GenericGroupKey<Integer>(2), 3.0);
result.put(new GenericGroupKey<Integer>(3), 5.0);
@@ -140,42 +140,42 @@ public class TestParallelDoubleAggregationProcessors {
@Test
public void testCountAggregationProcessor() throws InterruptedException {
Processor<GroupedDataEntry<Object>, Map<GroupKey, Double>> countAggregationProcessor = ParallelGroupedDataCountAggregationProcessor.getDefinition().construct(ConcurrencyTestsUtil.getExecutor(), receivers);
Processor<GroupedDataEntry<Object>, Map<GroupKey, Number>> countAggregationProcessor = ParallelGroupedDataCountAggregationProcessor.getDefinition().construct(ConcurrencyTestsUtil.getExecutor(), receivers);
@SuppressWarnings("unchecked")
Collection<GroupedDataEntry<Object>> elements = (Collection<GroupedDataEntry<Object>>)(Collection<?>) createElements();
ConcurrencyTestsUtil.processElements(countAggregationProcessor, elements);
countAggregationProcessor.finish();
Map<GroupKey, Double> expectedReceivedAggregations = computeExpectedCountAggregations();
Map<GroupKey, Number> expectedReceivedAggregations = computeExpectedCountAggregations();
ConcurrencyTestsUtil.verifyResultData(receivedAggregations, expectedReceivedAggregations);
}
private Map<GroupKey, Double> computeExpectedCountAggregations() {
Map<GroupKey, Double> result = new HashMap<>();
private Map<GroupKey, Number> computeExpectedCountAggregations() {
Map<GroupKey, Number> result = new HashMap<>();
result.put(new GenericGroupKey<Integer>(1), 3.0);
result.put(new GenericGroupKey<Integer>(2), 4.0);
result.put(new GenericGroupKey<Integer>(3), 3.0);
return result;
}
private Collection<GroupedDataEntry<Double>> createElements() {
Collection<GroupedDataEntry<Double>> elements = new ArrayList<>();
private Collection<GroupedDataEntry<Number>> createElements() {
Collection<GroupedDataEntry<Number>> elements = new ArrayList<>();
GroupKey firstGroupKey = new GenericGroupKey<Integer>(1);
elements.add(new GroupedDataEntry<Double>(firstGroupKey, 5.0));
elements.add(new GroupedDataEntry<Double>(firstGroupKey, 10.0));
elements.add(new GroupedDataEntry<Double>(firstGroupKey, 7.0));
elements.add(new GroupedDataEntry<Number>(firstGroupKey, 5.0));
elements.add(new GroupedDataEntry<Number>(firstGroupKey, 10.0));
elements.add(new GroupedDataEntry<Number>(firstGroupKey, 7.0));
GroupKey secondGroupKey = new GenericGroupKey<Integer>(2);
elements.add(new GroupedDataEntry<Double>(secondGroupKey, 5.0));
elements.add(new GroupedDataEntry<Double>(secondGroupKey, 3.0));
elements.add(new GroupedDataEntry<Double>(secondGroupKey, 7.0));
elements.add(new GroupedDataEntry<Double>(secondGroupKey, 7.0));
elements.add(new GroupedDataEntry<Number>(secondGroupKey, 5.0));
elements.add(new GroupedDataEntry<Number>(secondGroupKey, 3.0));
elements.add(new GroupedDataEntry<Number>(secondGroupKey, 7.0));
elements.add(new GroupedDataEntry<Number>(secondGroupKey, 7.0));
GroupKey thirdGroupKey = new GenericGroupKey<Integer>(3);
elements.add(new GroupedDataEntry<Double>(thirdGroupKey, 5.0));
elements.add(new GroupedDataEntry<Double>(thirdGroupKey, 5.0));
elements.add(new GroupedDataEntry<Double>(thirdGroupKey, 5.0));
elements.add(new GroupedDataEntry<Number>(thirdGroupKey, 5.0));
elements.add(new GroupedDataEntry<Number>(thirdGroupKey, 5.0));
elements.add(new GroupedDataEntry<Number>(thirdGroupKey, 5.0));
return elements;
}
@@ -183,9 +183,9 @@ public class TestParallelDoubleAggregationProcessors {
@Before
public void initializeResultReceivers() {
@SuppressWarnings("unchecked")
Processor<Map<GroupKey, Double>, Void> receiver = new NullProcessor<Map<GroupKey, Double>, Void>((Class<Map<GroupKey, Double>>)(Class<?>) Map.class, Void.class) {
Processor<Map<GroupKey, Number>, Void> receiver = new NullProcessor<Map<GroupKey, Number>, Void>((Class<Map<GroupKey, Number>>)(Class<?>) Map.class, Void.class) {
@Override
public void processElement(Map<GroupKey, Double> element) {
public void processElement(Map<GroupKey, Number> element) {
receivedAggregations = element;
}
};
@@ -19,13 +19,13 @@ import com.sap.sse.datamining.AdditionalQueryData;
import com.sap.sse.datamining.DataMiningServer;
import com.sap.sse.datamining.Query;
import com.sap.sse.datamining.QueryState;
import com.sap.sse.datamining.data.QueryResult;
import com.sap.sse.datamining.factories.FunctionFactory;
import com.sap.sse.datamining.functions.Function;
import com.sap.sse.datamining.impl.AdditionalDimensionValuesQueryData;
import com.sap.sse.datamining.impl.AdditionalOtherQueryData;
import com.sap.sse.datamining.impl.AdditionalStatisticQueryData;
import com.sap.sse.datamining.shared.DataMiningSession;
import com.sap.sse.datamining.shared.QueryResult;
import com.sap.sse.datamining.shared.impl.UUIDDataMiningSession;
import com.sap.sse.datamining.test.data.Test_HasLegOfCompetitorContext;
import com.sap.sse.datamining.test.data.Test_HasRaceContext;
@@ -48,8 +48,8 @@ public class TestServerQueryManagement {
DataMiningSession session = new UUIDDataMiningSession(UUID.randomUUID());
AdditionalQueryData additionalData = new AdditionalStatisticQueryData(new UUID(0, 0));
final ControllablePseudoQuery<Double> firstQuery = new ControllablePseudoQuery<Double>(additionalData);
final ControllablePseudoQuery<Double> secondQuery = new ControllablePseudoQuery<Double>(additionalData);
final ControllablePseudoQuery<Double> firstQuery = new ControllablePseudoQuery<Double>(Double.class, additionalData);
final ControllablePseudoQuery<Double> secondQuery = new ControllablePseudoQuery<Double>(Double.class, additionalData);
runQueriesAndVerifyConflict(session, firstQuery, session, secondQuery);
}
@@ -59,8 +59,8 @@ public class TestServerQueryManagement {
DataMiningSession secondQuerySession = new UUIDDataMiningSession(UUID.randomUUID());
AdditionalQueryData additionalData = new AdditionalStatisticQueryData(new UUID(0, 0));
final ControllablePseudoQuery<Double> firstQuery = new ControllablePseudoQuery<Double>(additionalData);
final ControllablePseudoQuery<Double> secondQuery = new ControllablePseudoQuery<Double>(additionalData);
final ControllablePseudoQuery<Double> firstQuery = new ControllablePseudoQuery<Double>(Double.class, additionalData);
final ControllablePseudoQuery<Double> secondQuery = new ControllablePseudoQuery<Double>(Double.class, additionalData);
runQueriesAndVerifyNoConflict(firstQuerySession, firstQuery, secondQuerySession, secondQuery);
}
@@ -72,8 +72,8 @@ public class TestServerQueryManagement {
dimensions.add(functionFactory.createMethodWrappingFunction(getYear));
AdditionalQueryData additionalData = new AdditionalDimensionValuesQueryData(new UUID(0, 0), dimensions);
final ControllablePseudoQuery<Double> firstQuery = new ControllablePseudoQuery<Double>(additionalData);
final ControllablePseudoQuery<Double> secondQuery = new ControllablePseudoQuery<Double>(additionalData);
final ControllablePseudoQuery<Double> firstQuery = new ControllablePseudoQuery<Double>(Double.class, additionalData);
final ControllablePseudoQuery<Double> secondQuery = new ControllablePseudoQuery<Double>(Double.class, additionalData);
runQueriesAndVerifyConflict(session, firstQuery, session, secondQuery);
}
@@ -85,13 +85,13 @@ public class TestServerQueryManagement {
Method getYear = FunctionTestsUtil.getMethodFromClass(Test_HasRaceContext.class, "getYear");
firstQueryDimensions.add(functionFactory.createMethodWrappingFunction(getYear));
AdditionalQueryData firstQueryAdditionalData = new AdditionalDimensionValuesQueryData(new UUID(0, 0), firstQueryDimensions);
final ControllablePseudoQuery<Double> firstQuery = new ControllablePseudoQuery<Double>(firstQueryAdditionalData);
final ControllablePseudoQuery<Double> firstQuery = new ControllablePseudoQuery<Double>(Double.class, firstQueryAdditionalData);
Collection<Function<?>> secondQueryDimensions = new ArrayList<>();
Method getLegNumber = FunctionTestsUtil.getMethodFromClass(Test_HasLegOfCompetitorContext.class, "getLegNumber");
secondQueryDimensions.add(functionFactory.createMethodWrappingFunction(getLegNumber));
AdditionalQueryData secondQueryAdditionalData = new AdditionalDimensionValuesQueryData(new UUID(0, 0), secondQueryDimensions);
final ControllablePseudoQuery<Double> secondQuery = new ControllablePseudoQuery<Double>(secondQueryAdditionalData);
final ControllablePseudoQuery<Double> secondQuery = new ControllablePseudoQuery<Double>(Double.class, secondQueryAdditionalData);
runQueriesAndVerifyNoConflict(session, firstQuery, session, secondQuery);
}
@@ -105,9 +105,9 @@ public class TestServerQueryManagement {
dimensions.add(functionFactory.createMethodWrappingFunction(getYear));
AdditionalQueryData firstQueryAdditionalData = new AdditionalDimensionValuesQueryData(new UUID(0, 0), dimensions);
final ControllablePseudoQuery<Double> firstQuery = new ControllablePseudoQuery<Double>(firstQueryAdditionalData);
final ControllablePseudoQuery<Double> firstQuery = new ControllablePseudoQuery<Double>(Double.class, firstQueryAdditionalData);
AdditionalQueryData secondQueryAdditionalData = new AdditionalDimensionValuesQueryData(new UUID(0, 0), dimensions);
final ControllablePseudoQuery<Double> secondQuery = new ControllablePseudoQuery<Double>(secondQueryAdditionalData);
final ControllablePseudoQuery<Double> secondQuery = new ControllablePseudoQuery<Double>(Double.class, secondQueryAdditionalData);
runQueriesAndVerifyNoConflict(firstQuerySession, firstQuery, secondQuerySession, secondQuery);
}
@@ -117,8 +117,8 @@ public class TestServerQueryManagement {
DataMiningSession session = new UUIDDataMiningSession(UUID.randomUUID());
AdditionalQueryData additionalData = new AdditionalOtherQueryData(new UUID(0, 0));
final ControllablePseudoQuery<Double> firstQuery = new ControllablePseudoQuery<Double>(additionalData);
final ControllablePseudoQuery<Double> secondQuery = new ControllablePseudoQuery<Double>(additionalData);
final ControllablePseudoQuery<Double> firstQuery = new ControllablePseudoQuery<Double>(Double.class, additionalData);
final ControllablePseudoQuery<Double> secondQuery = new ControllablePseudoQuery<Double>(Double.class, additionalData);
runQueriesAndVerifyNoConflict(session, firstQuery, session, secondQuery);
}
@@ -159,7 +159,7 @@ public class TestServerQueryManagement {
public void testControllablePseudoQuery() {
AdditionalQueryData additionalData = new AdditionalOtherQueryData(new UUID(0, 0));
final ControllablePseudoQuery<Double> normalQuery = new ControllablePseudoQuery<Double>(additionalData);
final ControllablePseudoQuery<Double> normalQuery = new ControllablePseudoQuery<Double>(Double.class, additionalData);
assertThat(normalQuery.getState(), is(QueryState.NOT_STARTED));
Thread thread = new Thread(new Runnable() {
@Override
@@ -177,7 +177,7 @@ public class TestServerQueryManagement {
ConcurrencyTestsUtil.sleepFor(50);
assertThat(normalQuery.getState(), is(QueryState.NORMAL));
final Query<Double> abortedQuery = new ControllablePseudoQuery<Double>(additionalData);
final Query<Double> abortedQuery = new ControllablePseudoQuery<Double>(Double.class, additionalData);
thread = new Thread(new Runnable() {
@Override
public void run() {
@@ -190,23 +190,30 @@ public class TestServerQueryManagement {
assertThat(abortedQuery.getState(), is(QueryState.ABORTED));
}
private static class ControllablePseudoQuery<AggregatedType> implements Query<AggregatedType> {
private static class ControllablePseudoQuery<ResultType> implements Query<ResultType> {
private final AdditionalQueryData additionalData;
private QueryState state;
private final Class<ResultType> resultType;
private final AdditionalQueryData additionalData;
private boolean processEnabled;
private boolean aborted;
public ControllablePseudoQuery(AdditionalQueryData additionalData) {
this.additionalData = additionalData;
public ControllablePseudoQuery(Class<ResultType> resultType, AdditionalQueryData additionalData) {
state = QueryState.NOT_STARTED;
this.resultType = resultType;
this.additionalData = additionalData;
}
@Override
public QueryState getState() {
return state;
}
@Override
public Class<ResultType> getResultType() {
return resultType;
}
@Override
public AdditionalQueryData getAdditionalData() {
@@ -227,7 +234,7 @@ public class TestServerQueryManagement {
}
@Override
public QueryResult<AggregatedType> run() {
public QueryResult<ResultType> run() {
state = QueryState.RUNNING;
while (!processEnabled && !aborted) {
ConcurrencyTestsUtil.sleepFor(100);
@@ -244,7 +251,7 @@ public class TestServerQueryManagement {
}
@Override
public QueryResult<AggregatedType> run(long timeout, TimeUnit unit) throws TimeoutException {
public QueryResult<ResultType> run(long timeout, TimeUnit unit) throws TimeoutException {
throw new UnsupportedOperationException();
}
@@ -288,19 +295,23 @@ public class TestServerQueryManagement {
}
try {
Query<Double> query = new NullQuery<Double>();
Query<Object> query = new NullQuery();
server.runNewQueryAndAbortPreviousQueries(null, query);
fail("Expected a NullPointerException");
} catch (NullPointerException e) {
}
}
private static class NullQuery<AggregatedType> implements Query<AggregatedType> {
private static class NullQuery implements Query<Object> {
@Override
public QueryState getState() {
return QueryState.NOT_STARTED;
}
@Override
public Class<Object> getResultType() {
return Object.class;
}
@Override
public AdditionalQueryData getAdditionalData() {
return new AdditionalStatisticQueryData(new UUID(0, 0));
}
@@ -309,11 +320,11 @@ public class TestServerQueryManagement {
return null;
}
@Override
public QueryResult<AggregatedType> run() {
public QueryResult<Object> run() {
return null;
}
@Override
public QueryResult<AggregatedType> run(long timeout, TimeUnit unit) throws TimeoutException {
public QueryResult<Object> run(long timeout, TimeUnit unit) throws TimeoutException {
return null;
}
@Override
@@ -6,11 +6,11 @@ import java.util.concurrent.ExecutorService;
import com.sap.sse.datamining.components.Processor;
import com.sap.sse.datamining.impl.components.GroupedDataEntry;
import com.sap.sse.datamining.impl.components.aggregators.AbstractParallelGroupedDataStoringAggregationProcessor;
import com.sap.sse.datamining.impl.components.aggregators.AbstractParallelGroupedDataAggregationProcessor;
import com.sap.sse.datamining.shared.GroupKey;
public class TestAggregationProcessorDummyWithInvalidConstructor extends
AbstractParallelGroupedDataStoringAggregationProcessor<Object, Double> {
AbstractParallelGroupedDataAggregationProcessor<Object, Double> {
public TestAggregationProcessorDummyWithInvalidConstructor(ExecutorService executor,
Collection<Processor<Map<GroupKey, Double>, ?>> resultReceivers, Object constructorInvalidator) {
@@ -18,11 +18,11 @@ public class TestAggregationProcessorDummyWithInvalidConstructor extends
}
@Override
protected void storeElement(GroupedDataEntry<Object> element) {
protected void handleElement(GroupedDataEntry<Object> element) {
}
@Override
protected Map<GroupKey, Double> aggregateResult() {
protected Map<GroupKey, Double> getResult() {
return null;
}
@@ -6,11 +6,11 @@ import java.util.concurrent.ExecutorService;
import com.sap.sse.datamining.components.Processor;
import com.sap.sse.datamining.impl.components.GroupedDataEntry;
import com.sap.sse.datamining.impl.components.aggregators.AbstractParallelGroupedDataStoringAggregationProcessor;
import com.sap.sse.datamining.impl.components.aggregators.AbstractParallelGroupedDataAggregationProcessor;
import com.sap.sse.datamining.shared.GroupKey;
public class TestAnyDataTypeAggregationProcessorDummy extends
AbstractParallelGroupedDataStoringAggregationProcessor<Object, Double> {
AbstractParallelGroupedDataAggregationProcessor<Object, Double> {
public TestAnyDataTypeAggregationProcessorDummy(ExecutorService executor,
Collection<Processor<Map<GroupKey, Double>, ?>> resultReceivers) {
@@ -18,11 +18,11 @@ public class TestAnyDataTypeAggregationProcessorDummy extends
}
@Override
protected void storeElement(GroupedDataEntry<Object> element) {
protected void handleElement(GroupedDataEntry<Object> element) {
}
@Override
protected Map<GroupKey, Double> aggregateResult() {
protected Map<GroupKey, Double> getResult() {
return null;
}
@@ -6,12 +6,12 @@ import java.util.concurrent.ExecutorService;
import com.sap.sse.datamining.components.Processor;
import com.sap.sse.datamining.impl.components.GroupedDataEntry;
import com.sap.sse.datamining.impl.components.aggregators.AbstractParallelGroupedDataStoringAggregationProcessor;
import com.sap.sse.datamining.impl.components.aggregators.AbstractParallelGroupedDataAggregationProcessor;
import com.sap.sse.datamining.shared.GroupKey;
import com.sap.sse.datamining.test.domain.Test_Competitor;
public class TestCompetitorAggregationProcessorDummy extends
AbstractParallelGroupedDataStoringAggregationProcessor<Test_Competitor, Test_Competitor> {
AbstractParallelGroupedDataAggregationProcessor<Test_Competitor, Test_Competitor> {
public TestCompetitorAggregationProcessorDummy(ExecutorService executor,
Collection<Processor<Map<GroupKey, Test_Competitor>, ?>> resultReceivers) {
@@ -19,11 +19,11 @@ public class TestCompetitorAggregationProcessorDummy extends
}
@Override
protected void storeElement(GroupedDataEntry<Test_Competitor> element) {
protected void handleElement(GroupedDataEntry<Test_Competitor> element) {
}
@Override
protected Map<GroupKey, Test_Competitor> aggregateResult() {
protected Map<GroupKey, Test_Competitor> getResult() {
return null;
}
@@ -6,12 +6,12 @@ import java.util.concurrent.ExecutorService;
import com.sap.sse.datamining.components.Processor;
import com.sap.sse.datamining.impl.components.GroupedDataEntry;
import com.sap.sse.datamining.impl.components.aggregators.AbstractParallelGroupedDataStoringAggregationProcessor;
import com.sap.sse.datamining.impl.components.aggregators.AbstractParallelGroupedDataAggregationProcessor;
import com.sap.sse.datamining.shared.GroupKey;
import com.sap.sse.datamining.test.domain.Test_Named;
public class TestNamedAggregationProcessorDummy extends
AbstractParallelGroupedDataStoringAggregationProcessor<Test_Named, Test_Named> {
AbstractParallelGroupedDataAggregationProcessor<Test_Named, Test_Named> {
public TestNamedAggregationProcessorDummy(ExecutorService executor,
Collection<Processor<Map<GroupKey, Test_Named>, ?>> resultReceivers) {
@@ -19,11 +19,11 @@ public class TestNamedAggregationProcessorDummy extends
}
@Override
protected void storeElement(GroupedDataEntry<Test_Named> element) {
protected void handleElement(GroupedDataEntry<Test_Named> element) {
}
@Override
protected Map<GroupKey, Test_Named> aggregateResult() {
protected Map<GroupKey, Test_Named> getResult() {
return null;
}
@@ -6,12 +6,12 @@ import java.util.concurrent.ExecutorService;
import com.sap.sse.datamining.components.Processor;
import com.sap.sse.datamining.impl.components.GroupedDataEntry;
import com.sap.sse.datamining.impl.components.aggregators.AbstractParallelGroupedDataStoringAggregationProcessor;
import com.sap.sse.datamining.impl.components.aggregators.AbstractParallelGroupedDataAggregationProcessor;
import com.sap.sse.datamining.shared.GroupKey;
import com.sap.sse.datamining.test.domain.Test_Race;
public class TestRaceAggregationProcessorDummy extends
AbstractParallelGroupedDataStoringAggregationProcessor<Test_Race, Test_Race> {
AbstractParallelGroupedDataAggregationProcessor<Test_Race, Test_Race> {
public TestRaceAggregationProcessorDummy(ExecutorService executor,
Collection<Processor<Map<GroupKey, Test_Race>, ?>> resultReceivers) {
@@ -19,11 +19,11 @@ public class TestRaceAggregationProcessorDummy extends
}
@Override
protected void storeElement(GroupedDataEntry<Test_Race> element) {
protected void handleElement(GroupedDataEntry<Test_Race> element) {
}
@Override
protected Map<GroupKey, Test_Race> aggregateResult() {
protected Map<GroupKey, Test_Race> getResult() {
return null;
}
@@ -12,13 +12,14 @@ import com.sap.sse.datamining.components.AggregationProcessorDefinition;
import com.sap.sse.datamining.components.DataRetrieverChainDefinition;
import com.sap.sse.datamining.components.management.AggregationProcessorDefinitionProvider;
import com.sap.sse.datamining.components.management.DataRetrieverChainDefinitionProvider;
import com.sap.sse.datamining.data.QueryResult;
import com.sap.sse.datamining.functions.Function;
import com.sap.sse.datamining.functions.FunctionProvider;
import com.sap.sse.datamining.shared.DataMiningSession;
import com.sap.sse.datamining.shared.QueryResult;
import com.sap.sse.datamining.shared.dto.StatisticQueryDefinitionDTO;
import com.sap.sse.datamining.shared.impl.dto.AggregationProcessorDefinitionDTO;
import com.sap.sse.datamining.shared.impl.dto.FunctionDTO;
import com.sap.sse.datamining.shared.impl.dto.QueryResultDTO;
import com.sap.sse.i18n.ResourceBundleStringMessages;
@@ -61,4 +62,6 @@ public interface DataMiningServer {
public <ExtractedType> AggregationProcessorDefinition<? super ExtractedType, ?> getAggregationProcessorDefinition(Class<ExtractedType> extractedType, String aggregationNameMessageKey);
public <ExtractedType, ResultType> AggregationProcessorDefinition<ExtractedType, ResultType> getAggregationProcessorDefinitionForDTO(AggregationProcessorDefinitionDTO aggregatorDefinitionDTO);
public <ResultType> QueryResultDTO<ResultType> convertToDTO(QueryResult<ResultType> result);
}
@@ -3,21 +3,23 @@ package com.sap.sse.datamining;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import com.sap.sse.datamining.shared.QueryResult;
import com.sap.sse.datamining.data.QueryResult;
public interface Query<AggregatedType> {
public interface Query<ResultType> {
public enum QueryType { STATISTIC, DIMENSION_VALUES, OTHER }
public QueryState getState();
public Class<ResultType> getResultType();
public AdditionalQueryData getAdditionalData();
public <T extends AdditionalQueryData> T getAdditionalData(Class<T> additionalDataType);
public QueryResult<AggregatedType> run();
public QueryResult<ResultType> run();
public QueryResult<AggregatedType> run(long timeout, TimeUnit unit) throws TimeoutException;
public QueryResult<ResultType> run(long timeout, TimeUnit unit) throws TimeoutException;
public void abort();
@@ -5,7 +5,7 @@ import java.util.Map;
import java.util.concurrent.ExecutorService;
import com.sap.sse.datamining.impl.components.GroupedDataEntry;
import com.sap.sse.datamining.impl.components.aggregators.AbstractParallelGroupedDataStoringAggregationProcessor;
import com.sap.sse.datamining.impl.components.aggregators.AbstractParallelGroupedDataAggregationProcessor;
import com.sap.sse.datamining.shared.GroupKey;
public interface AggregationProcessorDefinition<ExtractedType, AggregatedType> {
@@ -15,7 +15,7 @@ public interface AggregationProcessorDefinition<ExtractedType, AggregatedType> {
public String getAggregationNameMessageKey();
public Class<? extends AbstractParallelGroupedDataStoringAggregationProcessor<ExtractedType, AggregatedType>> getAggregationProcessor();
public Class<? extends AbstractParallelGroupedDataAggregationProcessor<ExtractedType, AggregatedType>> getAggregationProcessor();
public Processor<GroupedDataEntry<ExtractedType>, Map<GroupKey, AggregatedType>> construct(ExecutorService executor, Collection<Processor<Map<GroupKey, AggregatedType>, ?>> resultReceivers);
}
@@ -1,9 +1,9 @@
package com.sap.sse.datamining.components.management;
import com.sap.sse.datamining.Query;
import com.sap.sse.datamining.data.QueryResult;
import com.sap.sse.datamining.impl.components.management.NullDataMiningQueryManager;
import com.sap.sse.datamining.shared.DataMiningSession;
import com.sap.sse.datamining.shared.QueryResult;
public interface DataMiningQueryManager {
@@ -0,0 +1,12 @@
package com.sap.sse.datamining.data;
import com.sap.sse.datamining.shared.AdditionalResultData;
import com.sap.sse.datamining.shared.QueryResultBase;
public interface QueryResult<ResultType> extends QueryResultBase<ResultType> {
public Class<ResultType> getResultType();
public AdditionalResultData getAdditionalData();
}
@@ -66,7 +66,8 @@ public class DataMiningDTOFactory {
}
private AggregationProcessorDefinitionDTO createAggregationProcessorDefinitionDTO(AggregationProcessorDefinition<?, ?> aggregatorDefinition, String displayName) {
return new AggregationProcessorDefinitionDTO(aggregatorDefinition.getExtractedType().getSimpleName(),
return new AggregationProcessorDefinitionDTO(aggregatorDefinition.getAggregationNameMessageKey(),
aggregatorDefinition.getExtractedType().getSimpleName(),
aggregatorDefinition.getAggregatedType().getSimpleName(),
displayName);
}
@@ -35,7 +35,7 @@ public class QueryFactory {
public <DataSourceType, DataType, ExtractedType, ResultType> Query<ResultType> createQuery(DataSourceType dataSource, StatisticQueryDefinition<DataSourceType, DataType, ExtractedType, ResultType> queryDefinition,
ResourceBundleStringMessages stringMessages, ExecutorService executor) {
return new ProcessorQuery<ResultType, DataSourceType>(dataSource, stringMessages, queryDefinition.getLocale(), new AdditionalStatisticQueryData(queryDefinition.getDataRetrieverChainDefinition().getID())) {
return new ProcessorQuery<ResultType, DataSourceType>(dataSource, stringMessages, queryDefinition.getLocale(), queryDefinition.getResultType(), new AdditionalStatisticQueryData(queryDefinition.getDataRetrieverChainDefinition().getID())) {
@Override
protected Processor<DataSourceType, ?> createFirstProcessor() {
ProcessorFactory processorFactory = new ProcessorFactory(executor);
@@ -121,7 +121,9 @@ public class QueryFactory {
final DataRetrieverChainDefinition<DataSource, ?> dataRetrieverChainDefinition, final int retrieverLevel,
final Iterable<Function<?>> dimensions, final Map<Integer, Map<Function<?>, Collection<?>>> filterSelection, final Locale locale,
final ResourceBundleStringMessages stringMessages, final ExecutorService executor) {
return new ProcessorQuery<Set<Object>, DataSource>(dataSource, stringMessages, locale, new AdditionalDimensionValuesQueryData(dataRetrieverChainDefinition.getID(), dimensions)) {
@SuppressWarnings("unchecked")
Class<Set<Object>> resultType = (Class<Set<Object>>)(Class<?>) Set.class;
return new ProcessorQuery<Set<Object>, DataSource>(dataSource, stringMessages, locale, resultType, new AdditionalDimensionValuesQueryData(dataRetrieverChainDefinition.getID(), dimensions)) {
@Override
protected Processor<DataSource, ?> createFirstProcessor() {
ProcessorFactory processorFactory = new ProcessorFactory(executor);
@@ -21,11 +21,11 @@ import com.sap.sse.datamining.components.DataRetrieverChainDefinition;
import com.sap.sse.datamining.components.management.AggregationProcessorDefinitionRegistry;
import com.sap.sse.datamining.components.management.DataRetrieverChainDefinitionRegistry;
import com.sap.sse.datamining.impl.components.aggregators.ParallelGroupedDataCountAggregationProcessor;
import com.sap.sse.datamining.impl.components.aggregators.ParallelGroupedDoubleDataAverageAggregationProcessor;
import com.sap.sse.datamining.impl.components.aggregators.ParallelGroupedDoubleDataMaxAggregationProcessor;
import com.sap.sse.datamining.impl.components.aggregators.ParallelGroupedDoubleDataMedianAggregationProcessor;
import com.sap.sse.datamining.impl.components.aggregators.ParallelGroupedDoubleDataMinAggregationProcessor;
import com.sap.sse.datamining.impl.components.aggregators.ParallelGroupedDoubleDataSumAggregationProcessor;
import com.sap.sse.datamining.impl.components.aggregators.ParallelGroupedNumberDataAverageAggregationProcessor;
import com.sap.sse.datamining.impl.components.aggregators.ParallelGroupedNumberDataMaxAggregationProcessor;
import com.sap.sse.datamining.impl.components.aggregators.ParallelGroupedNumberDataMedianAggregationProcessor;
import com.sap.sse.datamining.impl.components.aggregators.ParallelGroupedNumberDataMinAggregationProcessor;
import com.sap.sse.datamining.impl.components.aggregators.ParallelGroupedNumberDataSumAggregationProcessor;
import com.sap.sse.datamining.impl.components.management.AggregationProcessorDefinitionManager;
import com.sap.sse.datamining.impl.components.management.DataRetrieverChainDefinitionManager;
import com.sap.sse.datamining.impl.functions.FunctionManager;
@@ -64,11 +64,11 @@ public class DataMiningFrameworkActivator implements BundleActivator {
private Iterable<AggregationProcessorDefinition<?, ?>> getDefaultAggregationProcessors() {
Collection<AggregationProcessorDefinition<?, ?>> defaultAggregationProcessors = new HashSet<>();
defaultAggregationProcessors.add(ParallelGroupedDataCountAggregationProcessor.getDefinition());
defaultAggregationProcessors.add(ParallelGroupedDoubleDataAverageAggregationProcessor.getDefinition());
defaultAggregationProcessors.add(ParallelGroupedDoubleDataMaxAggregationProcessor.getDefinition());
defaultAggregationProcessors.add(ParallelGroupedDoubleDataMedianAggregationProcessor.getDefinition());
defaultAggregationProcessors.add(ParallelGroupedDoubleDataMinAggregationProcessor.getDefinition());
defaultAggregationProcessors.add(ParallelGroupedDoubleDataSumAggregationProcessor.getDefinition());
defaultAggregationProcessors.add(ParallelGroupedNumberDataAverageAggregationProcessor.getDefinition());
defaultAggregationProcessors.add(ParallelGroupedNumberDataMaxAggregationProcessor.getDefinition());
defaultAggregationProcessors.add(ParallelGroupedNumberDataMedianAggregationProcessor.getDefinition());
defaultAggregationProcessors.add(ParallelGroupedNumberDataMinAggregationProcessor.getDefinition());
defaultAggregationProcessors.add(ParallelGroupedNumberDataSumAggregationProcessor.getDefinition());
return defaultAggregationProcessors;
}
@@ -22,16 +22,17 @@ import com.sap.sse.datamining.components.management.AggregationProcessorDefiniti
import com.sap.sse.datamining.components.management.DataMiningQueryManager;
import com.sap.sse.datamining.components.management.DataRetrieverChainDefinitionProvider;
import com.sap.sse.datamining.components.management.DataRetrieverChainDefinitionRegistry;
import com.sap.sse.datamining.data.QueryResult;
import com.sap.sse.datamining.factories.QueryFactory;
import com.sap.sse.datamining.functions.Function;
import com.sap.sse.datamining.functions.FunctionProvider;
import com.sap.sse.datamining.functions.FunctionRegistry;
import com.sap.sse.datamining.impl.components.management.StrategyPerQueryTypeManager;
import com.sap.sse.datamining.shared.DataMiningSession;
import com.sap.sse.datamining.shared.QueryResult;
import com.sap.sse.datamining.shared.dto.StatisticQueryDefinitionDTO;
import com.sap.sse.datamining.shared.impl.dto.AggregationProcessorDefinitionDTO;
import com.sap.sse.datamining.shared.impl.dto.FunctionDTO;
import com.sap.sse.datamining.shared.impl.dto.QueryResultDTO;
import com.sap.sse.i18n.ResourceBundleStringMessages;
import com.sap.sse.i18n.impl.CompoundResourceBundleStringMessages;
@@ -333,4 +334,10 @@ public class DataMiningServerImpl implements ModifiableDataMiningServer {
return dataMiningQueryManager.runNewAndAbortPrevious(session, query);
}
@Override
public <ResultType> QueryResultDTO<ResultType> convertToDTO(QueryResult<ResultType> result) {
return new QueryResultDTO<ResultType>(result.getState(), result.getResultType(), result.getResults(), result.getAdditionalData());
}
}
@@ -19,21 +19,23 @@ import com.sap.sse.datamining.Query;
import com.sap.sse.datamining.QueryState;
import com.sap.sse.datamining.components.AdditionalResultDataBuilder;
import com.sap.sse.datamining.components.Processor;
import com.sap.sse.datamining.data.QueryResult;
import com.sap.sse.datamining.impl.components.OverwritingResultDataBuilder;
import com.sap.sse.datamining.impl.data.QueryResultImpl;
import com.sap.sse.datamining.shared.AdditionalResultData;
import com.sap.sse.datamining.shared.GroupKey;
import com.sap.sse.datamining.shared.QueryResult;
import com.sap.sse.datamining.shared.data.QueryResultState;
import com.sap.sse.datamining.shared.impl.NullAdditionalResultData;
import com.sap.sse.datamining.shared.impl.QueryResultImpl;
import com.sap.sse.i18n.ResourceBundleStringMessages;
public abstract class ProcessorQuery<AggregatedType, DataSourceType> implements Query<AggregatedType> {
public abstract class ProcessorQuery<ResultType, DataSourceType> implements Query<ResultType> {
private static final Logger LOGGER = Logger.getLogger(ProcessorQuery.class.getSimpleName());
private final DataSourceType dataSource;
private final Processor<DataSourceType, ?> firstProcessor;
private QueryState state;
private final Class<ResultType> resultType;
private final ProcessResultReceiver resultReceiver;
@@ -43,7 +45,6 @@ public abstract class ProcessorQuery<AggregatedType, DataSourceType> implements
private final Object monitorObject = new Object();
private Thread workingThread;
private QueryState state;
/**
* Creates a query
@@ -52,8 +53,8 @@ public abstract class ProcessorQuery<AggregatedType, DataSourceType> implements
* <li> that returns a result without {@link AdditionalResultData} (more exactly with {@link NullAdditionalResultData} as additional data).</li>
* </ul>
*/
public ProcessorQuery(DataSourceType dataSource) {
this(dataSource, AdditionalQueryData.NULL_INSTANCE);
public ProcessorQuery(DataSourceType dataSource, Class<ResultType> resultType) {
this(dataSource, resultType, AdditionalQueryData.NULL_INSTANCE);
}
@@ -61,19 +62,20 @@ public abstract class ProcessorQuery<AggregatedType, DataSourceType> implements
* Creates a query that returns a result without {@link AdditionalResultData}
* (more exactly with {@link NullAdditionalResultData} as additional data).
*/
public ProcessorQuery(DataSourceType dataSource, AdditionalQueryData additionalData) {
this(dataSource, null, null, additionalData);
public ProcessorQuery(DataSourceType dataSource, Class<ResultType> resultType, AdditionalQueryData additionalData) {
this(dataSource, null, null, resultType, additionalData);
}
/**
* Creates a query that returns a result with additional data.
*/
public ProcessorQuery(DataSourceType dataSource, ResourceBundleStringMessages stringMessages, Locale locale, AdditionalQueryData additionalData) {
public ProcessorQuery(DataSourceType dataSource, ResourceBundleStringMessages stringMessages, Locale locale, Class<ResultType> resultType, AdditionalQueryData additionalData) {
this.dataSource = dataSource;
this.stringMessages = stringMessages;
this.locale = locale;
this.additionalData = additionalData;
state = QueryState.NOT_STARTED;
this.resultType = resultType;
this.additionalData = additionalData;
resultReceiver = new ProcessResultReceiver();
firstProcessor = createFirstProcessor();
@@ -86,6 +88,11 @@ public abstract class ProcessorQuery<AggregatedType, DataSourceType> implements
return state;
}
@Override
public Class<ResultType> getResultType() {
return resultType;
}
@Override
public AdditionalQueryData getAdditionalData() {
return additionalData;
@@ -101,7 +108,7 @@ public abstract class ProcessorQuery<AggregatedType, DataSourceType> implements
}
@Override
public QueryResult<AggregatedType> run() {
public QueryResult<ResultType> run() {
try {
return run(0, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
@@ -113,7 +120,7 @@ public abstract class ProcessorQuery<AggregatedType, DataSourceType> implements
}
@Override
public QueryResult<AggregatedType> run(long timeout, TimeUnit unit) throws TimeoutException {
public QueryResult<ResultType> run(long timeout, TimeUnit unit) throws TimeoutException {
try {
return processQuery(unit.toMillis(timeout));
} catch (InterruptedException e) {
@@ -123,7 +130,7 @@ public abstract class ProcessorQuery<AggregatedType, DataSourceType> implements
return null;
}
private QueryResult<AggregatedType> processQuery(long timeoutInMillis) throws InterruptedException, TimeoutException {
private QueryResult<ResultType> processQuery(long timeoutInMillis) throws InterruptedException, TimeoutException {
state = QueryState.RUNNING;
final long startTime = System.nanoTime();
startWorking();
@@ -133,15 +140,15 @@ public abstract class ProcessorQuery<AggregatedType, DataSourceType> implements
logOccuredFailuresAndThrowSevereFailure();
long calculationTimeInNanos = endTime - startTime;
Map<GroupKey, AggregatedType> results = resultReceiver.getResult();
Map<GroupKey, ResultType> results = resultReceiver.getResult();
QueryResultState resultState = state.asResultState();
if (stringMessages != null && locale != null) {
AdditionalResultDataBuilder additionalDataBuilder = new OverwritingResultDataBuilder();
additionalDataBuilder = firstProcessor.getAdditionalResultData(additionalDataBuilder);
return new QueryResultImpl<>(resultState, results, additionalDataBuilder.build(calculationTimeInNanos, stringMessages, locale));
return new QueryResultImpl<>(resultState, getResultType(), results, additionalDataBuilder.build(calculationTimeInNanos, stringMessages, locale));
} else {
return new QueryResultImpl<>(resultState, results);
return new QueryResultImpl<>(resultState, getResultType(), results);
}
}
@@ -222,14 +229,14 @@ public abstract class ProcessorQuery<AggregatedType, DataSourceType> implements
}
}
public Processor<Map<GroupKey, AggregatedType>, Void> getResultReceiver() {
public Processor<Map<GroupKey, ResultType>, Void> getResultReceiver() {
return resultReceiver;
}
private class ProcessResultReceiver implements Processor<Map<GroupKey, AggregatedType>, Void> {
private class ProcessResultReceiver implements Processor<Map<GroupKey, ResultType>, Void> {
private final ReentrantLock resultsLock;
private Map<GroupKey, AggregatedType> results;
private Map<GroupKey, ResultType> results;
private List<Throwable> occuredFailures;
private Throwable severeFailure;
@@ -245,7 +252,7 @@ public abstract class ProcessorQuery<AggregatedType, DataSourceType> implements
}
@Override
public void processElement(Map<GroupKey, AggregatedType> groupedAggregations) {
public void processElement(Map<GroupKey, ResultType> groupedAggregations) {
resultsLock.lock();
try {
results.putAll(groupedAggregations);
@@ -296,7 +303,7 @@ public abstract class ProcessorQuery<AggregatedType, DataSourceType> implements
return false;
}
public Map<GroupKey, AggregatedType> getResult() {
public Map<GroupKey, ResultType> getResult() {
return results;
}
@@ -315,8 +322,8 @@ public abstract class ProcessorQuery<AggregatedType, DataSourceType> implements
@SuppressWarnings("unchecked")
@Override
public Class<Map<GroupKey, AggregatedType>> getInputType() {
return (Class<Map<GroupKey, AggregatedType>>)(Class<?>) Map.class;
public Class<Map<GroupKey, ResultType>> getInputType() {
return (Class<Map<GroupKey, ResultType>>)(Class<?>) Map.class;
}
@Override
@@ -9,7 +9,7 @@ import java.util.concurrent.ExecutorService;
import com.sap.sse.datamining.components.AggregationProcessorDefinition;
import com.sap.sse.datamining.components.Processor;
import com.sap.sse.datamining.impl.components.aggregators.AbstractParallelGroupedDataStoringAggregationProcessor;
import com.sap.sse.datamining.impl.components.aggregators.AbstractParallelGroupedDataAggregationProcessor;
import com.sap.sse.datamining.shared.GroupKey;
public class SimpleAggregationProcessorDefinition<ExtractedType, AggregatedType> implements
@@ -18,14 +18,14 @@ public class SimpleAggregationProcessorDefinition<ExtractedType, AggregatedType>
private final Class<ExtractedType> extractedType;
private final Class<AggregatedType> aggregatedType;
private final String aggregationNameMessageKey;
private final Class<? extends AbstractParallelGroupedDataStoringAggregationProcessor<ExtractedType, AggregatedType>> aggregationProcessor;
private final Constructor<? extends AbstractParallelGroupedDataStoringAggregationProcessor<ExtractedType, AggregatedType>> constructor;
private final Class<? extends AbstractParallelGroupedDataAggregationProcessor<ExtractedType, AggregatedType>> aggregationProcessor;
private final Constructor<? extends AbstractParallelGroupedDataAggregationProcessor<ExtractedType, AggregatedType>> constructor;
public SimpleAggregationProcessorDefinition(
Class<ExtractedType> extractedType,
Class<AggregatedType> aggregatedType,
String aggregationNameMessageKey,
Class<? extends AbstractParallelGroupedDataStoringAggregationProcessor<ExtractedType, AggregatedType>> aggregationProcessor) {
Class<? extends AbstractParallelGroupedDataAggregationProcessor<ExtractedType, AggregatedType>> aggregationProcessor) {
this.extractedType = extractedType;
this.aggregatedType = aggregatedType;
this.aggregationNameMessageKey = aggregationNameMessageKey;
@@ -33,9 +33,9 @@ public class SimpleAggregationProcessorDefinition<ExtractedType, AggregatedType>
constructor = ensureValidConstructor(aggregationProcessor);
}
private Constructor<? extends AbstractParallelGroupedDataStoringAggregationProcessor<ExtractedType, AggregatedType>> ensureValidConstructor(Class<? extends AbstractParallelGroupedDataStoringAggregationProcessor<ExtractedType, AggregatedType>> aggregationProcessor) {
private Constructor<? extends AbstractParallelGroupedDataAggregationProcessor<ExtractedType, AggregatedType>> ensureValidConstructor(Class<? extends AbstractParallelGroupedDataAggregationProcessor<ExtractedType, AggregatedType>> aggregationProcessor) {
try {
Constructor<? extends AbstractParallelGroupedDataStoringAggregationProcessor<ExtractedType, AggregatedType>> constructor = aggregationProcessor.getConstructor(ExecutorService.class, Collection.class);
Constructor<? extends AbstractParallelGroupedDataAggregationProcessor<ExtractedType, AggregatedType>> constructor = aggregationProcessor.getConstructor(ExecutorService.class, Collection.class);
if (Modifier.isPublic(constructor.getModifiers())) {
// Preventing IllegalAccessExceptions of public constructors due to weird package behaviour
constructor.setAccessible(true);
@@ -63,7 +63,7 @@ public class SimpleAggregationProcessorDefinition<ExtractedType, AggregatedType>
}
@Override
public Class<? extends AbstractParallelGroupedDataStoringAggregationProcessor<ExtractedType, AggregatedType>> getAggregationProcessor() {
public Class<? extends AbstractParallelGroupedDataAggregationProcessor<ExtractedType, AggregatedType>> getAggregationProcessor() {
return aggregationProcessor;
}
@@ -11,20 +11,20 @@ import com.sap.sse.datamining.impl.components.AbstractParallelProcessor;
import com.sap.sse.datamining.impl.components.AbstractProcessorInstruction;
import com.sap.sse.datamining.impl.components.ProcessorInstructionPriority;
public abstract class AbstractParallelStoringAggregationProcessor<InputType, AggregatedType>
public abstract class AbstractParallelAggregationProcessor<InputType, AggregatedType>
extends AbstractParallelProcessor<InputType, AggregatedType> {
private final Lock storeLock;
private final String aggregationNameMessageKey;
private final Lock writeLock;
public AbstractParallelStoringAggregationProcessor(Class<InputType> inputType,
Class<AggregatedType> resultType,
ExecutorService executor,
Collection<Processor<AggregatedType, ?>> resultReceivers,
String aggregationNameMessageKey) {
public AbstractParallelAggregationProcessor(Class<InputType> inputType,
Class<AggregatedType> resultType,
ExecutorService executor,
Collection<Processor<AggregatedType, ?>> resultReceivers,
String aggregationNameMessageKey) {
super(inputType, resultType, executor, resultReceivers);
storeLock = new ReentrantLock();
this.aggregationNameMessageKey = aggregationNameMessageKey;
writeLock = new ReentrantLock();
}
@Override
@@ -32,31 +32,32 @@ public abstract class AbstractParallelStoringAggregationProcessor<InputType, Agg
return new AbstractProcessorInstruction<AggregatedType>(this, ProcessorInstructionPriority.Aggregation) {
@Override
public AggregatedType computeResult() {
storeLock.lock();
writeLock.lock();
try {
storeElement(element);
handleElement(element);
} finally {
storeLock.unlock();
writeLock.unlock();
}
return AbstractParallelStoringAggregationProcessor.super.createInvalidResult();
return AbstractParallelAggregationProcessor.super.createInvalidResult();
}
};
}
/**
* Method to store the element in the concrete store. This method is only called in a way, that is thread safe, so
* that multiple threads can't corrupt the store.
* Method to handle the element. This method is only called in a way, that is thread safe, so
* that multiple threads can't corrupt the data.
*/
protected abstract void storeElement(InputType element);
protected abstract void handleElement(InputType element);
@Override
public void finish() throws InterruptedException {
super.sleepUntilAllInstructionsFinished();
super.forwardResultToReceivers(aggregateResult());
super.forwardResultToReceivers(getResult());
super.tellResultReceiversToFinish();
}
protected abstract AggregatedType aggregateResult();
protected abstract AggregatedType getResult();
@Override
protected void setAdditionalData(AdditionalResultDataBuilder additionalDataBuilder) {
@@ -0,0 +1,20 @@
package com.sap.sse.datamining.impl.components.aggregators;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import com.sap.sse.datamining.components.Processor;
import com.sap.sse.datamining.impl.components.GroupedDataEntry;
import com.sap.sse.datamining.shared.GroupKey;
public abstract class AbstractParallelGroupedDataAggregationProcessor<ExtractedType, AggregatedType>
extends AbstractParallelAggregationProcessor<GroupedDataEntry<ExtractedType>, Map<GroupKey, AggregatedType>> {
@SuppressWarnings("unchecked")
public AbstractParallelGroupedDataAggregationProcessor(ExecutorService executor, Collection<Processor<Map<GroupKey, AggregatedType>, ?>> resultReceivers, String aggregationNameMessageKey) {
super((Class<GroupedDataEntry<ExtractedType>>)(Class<?>) GroupedDataEntry.class, (Class<Map<GroupKey, AggregatedType>>)(Class<?>) Map.class,
executor, resultReceivers, aggregationNameMessageKey);
}
}
@@ -8,13 +8,31 @@ import com.sap.sse.datamining.components.Processor;
import com.sap.sse.datamining.impl.components.GroupedDataEntry;
import com.sap.sse.datamining.shared.GroupKey;
public abstract class AbstractParallelGroupedDataStoringAggregationProcessor<ExtractedType, AggregatedType>
extends AbstractParallelStoringAggregationProcessor<GroupedDataEntry<ExtractedType>, Map<GroupKey, AggregatedType>> {
public abstract class AbstractParallelGroupedDataStoringAggregationProcessor<InputType, AggregatedType>
extends AbstractParallelGroupedDataAggregationProcessor<InputType, AggregatedType> {
@SuppressWarnings("unchecked")
public AbstractParallelGroupedDataStoringAggregationProcessor(ExecutorService executor, Collection<Processor<Map<GroupKey, AggregatedType>, ?>> resultReceivers, String aggregationNameMessageKey) {
super((Class<GroupedDataEntry<ExtractedType>>)(Class<?>) GroupedDataEntry.class, (Class<Map<GroupKey, AggregatedType>>)(Class<?>) Map.class,
executor, resultReceivers, aggregationNameMessageKey);
public AbstractParallelGroupedDataStoringAggregationProcessor(ExecutorService executor,
Collection<Processor<Map<GroupKey, AggregatedType>, ?>> resultReceivers,
String aggregationNameMessageKey) {
super(executor, resultReceivers, aggregationNameMessageKey);
}
@Override
protected void handleElement(GroupedDataEntry<InputType> element) {
storeElement(element);
}
/**
* Method to store the element in the concrete store. This method is only called in a way, that is thread safe, so
* that multiple threads can't corrupt the store.
*/
protected abstract void storeElement(GroupedDataEntry<InputType> element);
@Override
protected Map<GroupKey, AggregatedType> getResult() {
return aggregateResult();
}
protected abstract Map<GroupKey, AggregatedType> aggregateResult();
}
@@ -14,35 +14,35 @@ import com.sap.sse.datamining.shared.GroupKey;
import com.sap.sse.datamining.shared.data.Unit;
public class ParallelGroupedDataCountAggregationProcessor
extends AbstractParallelGroupedDataStoringAggregationProcessor<Object, Double> {
extends AbstractParallelGroupedDataAggregationProcessor<Object, Number> {
private static final AggregationProcessorDefinition<Object, Double> DEFINITION =
new SimpleAggregationProcessorDefinition<>(Object.class, Double.class, "Count", ParallelGroupedDataCountAggregationProcessor.class);
private static final AggregationProcessorDefinition<Object, Number> DEFINITION =
new SimpleAggregationProcessorDefinition<>(Object.class, Number.class, "Count", ParallelGroupedDataCountAggregationProcessor.class);
public static AggregationProcessorDefinition<Object, Double> getDefinition() {
public static AggregationProcessorDefinition<Object, Number> getDefinition() {
return DEFINITION;
}
private Map<GroupKey, Double> countMap;
private Map<GroupKey, Number> countMap;
public ParallelGroupedDataCountAggregationProcessor(ExecutorService executor,
Collection<Processor<Map<GroupKey, Double>, ?>> resultReceivers) {
Collection<Processor<Map<GroupKey, Number>, ?>> resultReceivers) {
super(executor, resultReceivers, "Count");
countMap = new HashMap<>();
}
@Override
protected void storeElement(GroupedDataEntry<Object> element) {
protected void handleElement(GroupedDataEntry<Object> element) {
GroupKey key = element.getKey();
if (!countMap.containsKey(key)) {
countMap.put(key, 0.0);
}
Double currentAmount = countMap.get(key);
Double currentAmount = countMap.get(key).doubleValue();
countMap.put(key, currentAmount + 1.0);
}
@Override
protected Map<GroupKey, Double> aggregateResult() {
protected Map<GroupKey, Number> getResult() {
return countMap;
}
@@ -1,72 +0,0 @@
package com.sap.sse.datamining.impl.components.aggregators;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ExecutorService;
import com.sap.sse.datamining.components.AggregationProcessorDefinition;
import com.sap.sse.datamining.components.Processor;
import com.sap.sse.datamining.impl.components.GroupedDataEntry;
import com.sap.sse.datamining.impl.components.SimpleAggregationProcessorDefinition;
import com.sap.sse.datamining.shared.GroupKey;
public class ParallelGroupedDoubleDataSumAggregationProcessor
extends AbstractParallelGroupedDataStoringAggregationProcessor<Double, Double> {
private static final AggregationProcessorDefinition<Double, Double> DEFINITION =
new SimpleAggregationProcessorDefinition<>(Double.class, Double.class, "Sum", ParallelGroupedDoubleDataSumAggregationProcessor.class);
public static AggregationProcessorDefinition<Double, Double> getDefinition() {
return DEFINITION;
}
private Map<GroupedDataEntry<Double>, Integer> elementAmountMap;
public ParallelGroupedDoubleDataSumAggregationProcessor(ExecutorService executor,
Collection<Processor<Map<GroupKey, Double>, ?>> resultReceivers) {
super(executor, resultReceivers, "Sum");
elementAmountMap = new HashMap<>();
}
@Override
protected void storeElement(GroupedDataEntry<Double> element) {
if (!elementAmountMap.containsKey(element)) {
elementAmountMap.put(element, 0);
}
Integer currentAmount = elementAmountMap.get(element);
elementAmountMap.put(element, currentAmount + 1);
}
@Override
protected Map<GroupKey, Double> aggregateResult() {
Map<GroupKey, Double> result = new HashMap<>();
for (Entry<GroupedDataEntry<Double>, Integer> elementAmountEntry : elementAmountMap.entrySet()) {
Number element = elementAmountEntry.getKey().getDataEntry();
Integer times = elementAmountEntry.getValue();
Double multipliedElementValue = multiply(element.doubleValue(), times);
GroupKey groupKey = elementAmountEntry.getKey().getKey();
Double groupResult = result.get(groupKey);
result.put(groupKey, addToGroupResult(groupResult, multipliedElementValue));
}
return result;
}
private Double multiply(Double element, Integer times) {
return element * times;
}
private Double add(Double firstSummand, Double secondSummand) {
return firstSummand + secondSummand;
}
private Double addToGroupResult(Double groupResult, Double multipliedElementValue) {
if (groupResult == null) {
return multipliedElementValue;
}
return add(groupResult, multipliedElementValue);
}
}
@@ -12,33 +12,33 @@ import com.sap.sse.datamining.impl.components.GroupedDataEntry;
import com.sap.sse.datamining.impl.components.SimpleAggregationProcessorDefinition;
import com.sap.sse.datamining.shared.GroupKey;
public class ParallelGroupedDoubleDataAverageAggregationProcessor
extends AbstractParallelGroupedDataStoringAggregationProcessor<Double, Double> {
public class ParallelGroupedNumberDataAverageAggregationProcessor
extends AbstractParallelGroupedDataStoringAggregationProcessor<Number, Number> {
private static final AggregationProcessorDefinition<Double, Double> DEFINITION =
new SimpleAggregationProcessorDefinition<>(Double.class, Double.class, "Average", ParallelGroupedDoubleDataAverageAggregationProcessor.class);
private static final AggregationProcessorDefinition<Number, Number> DEFINITION =
new SimpleAggregationProcessorDefinition<>(Number.class, Number.class, "Average", ParallelGroupedNumberDataAverageAggregationProcessor.class);
public static AggregationProcessorDefinition<Double, Double> getDefinition() {
public static AggregationProcessorDefinition<Number, Number> getDefinition() {
return DEFINITION;
}
private final AbstractParallelGroupedDataStoringAggregationProcessor<Double, Double> sumAggregationProcessor;
private final ParallelGroupedNumberDataSumAggregationProcessor sumAggregationProcessor;
private final Map<GroupKey, Integer> elementAmountPerKey;
public ParallelGroupedDoubleDataAverageAggregationProcessor(ExecutorService executor,
Collection<Processor<Map<GroupKey, Double>, ?>> resultReceivers) {
public ParallelGroupedNumberDataAverageAggregationProcessor(ExecutorService executor,
Collection<Processor<Map<GroupKey, Number>, ?>> resultReceivers) {
super(executor, resultReceivers, "Average");
elementAmountPerKey = new HashMap<>();
sumAggregationProcessor = new ParallelGroupedDoubleDataSumAggregationProcessor(executor, resultReceivers);
sumAggregationProcessor = new ParallelGroupedNumberDataSumAggregationProcessor(executor, resultReceivers);
}
@Override
protected void storeElement(GroupedDataEntry<Double> element) {
protected void storeElement(GroupedDataEntry<Number> element) {
incrementElementAmount(element);
sumAggregationProcessor.storeElement(element);
sumAggregationProcessor.handleElement(element);
}
private void incrementElementAmount(GroupedDataEntry<Double> element) {
private void incrementElementAmount(GroupedDataEntry<Number> element) {
GroupKey key = element.getKey();
if (!elementAmountPerKey.containsKey(key)) {
elementAmountPerKey.put(key, 0);
@@ -48,12 +48,12 @@ public class ParallelGroupedDoubleDataAverageAggregationProcessor
}
@Override
protected Map<GroupKey, Double> aggregateResult() {
Map<GroupKey, Double> result = new HashMap<>();
Map<GroupKey, Double> sumAggregation = sumAggregationProcessor.aggregateResult();
for (Entry<GroupKey, Double> sumAggregationEntry : sumAggregation.entrySet()) {
protected Map<GroupKey, Number> aggregateResult() {
Map<GroupKey, Number> result = new HashMap<>();
Map<GroupKey, Number> sumAggregation = sumAggregationProcessor.getResult();
for (Entry<GroupKey, Number> sumAggregationEntry : sumAggregation.entrySet()) {
GroupKey key = sumAggregationEntry.getKey();
result.put(key, sumAggregationEntry.getValue() / elementAmountPerKey.get(key));
result.put(key, sumAggregationEntry.getValue().doubleValue() / elementAmountPerKey.get(key).doubleValue());
}
return result;
}
@@ -11,35 +11,35 @@ import com.sap.sse.datamining.impl.components.GroupedDataEntry;
import com.sap.sse.datamining.impl.components.SimpleAggregationProcessorDefinition;
import com.sap.sse.datamining.shared.GroupKey;
public class ParallelGroupedDoubleDataMaxAggregationProcessor
extends AbstractParallelGroupedDataStoringAggregationProcessor<Double, Double> {
public class ParallelGroupedNumberDataMaxAggregationProcessor
extends AbstractParallelGroupedDataAggregationProcessor<Number, Number> {
private static final AggregationProcessorDefinition<Double, Double> DEFINITION =
new SimpleAggregationProcessorDefinition<>(Double.class, Double.class, "Maximum", ParallelGroupedDoubleDataMaxAggregationProcessor.class);
private static final AggregationProcessorDefinition<Number, Number> DEFINITION =
new SimpleAggregationProcessorDefinition<>(Number.class, Number.class, "Maximum", ParallelGroupedNumberDataMaxAggregationProcessor.class);
public static AggregationProcessorDefinition<Double, Double> getDefinition() {
public static AggregationProcessorDefinition<Number, Number> getDefinition() {
return DEFINITION;
}
private Map<GroupKey, Double> maxMap;
private Map<GroupKey, Number> maxMap;
public ParallelGroupedDoubleDataMaxAggregationProcessor(ExecutorService executor,
Collection<Processor<Map<GroupKey, Double>, ?>> resultReceivers) {
public ParallelGroupedNumberDataMaxAggregationProcessor(ExecutorService executor,
Collection<Processor<Map<GroupKey, Number>, ?>> resultReceivers) {
super(executor, resultReceivers, "Maximum");
maxMap = new HashMap<>();
}
@Override
protected void storeElement(GroupedDataEntry<Double> element) {
protected void handleElement(GroupedDataEntry<Number> element) {
GroupKey key = element.getKey();
Double value = element.getDataEntry();
if (!maxMap.containsKey(key) || value > maxMap.get(key)) {
Number value = element.getDataEntry();
if (!maxMap.containsKey(key) || value.doubleValue() > maxMap.get(key).doubleValue()) {
maxMap.put(key, value);
}
}
@Override
protected Map<GroupKey, Double> aggregateResult() {
protected Map<GroupKey, Number> getResult() {
return maxMap;
}
@@ -3,6 +3,7 @@ package com.sap.sse.datamining.impl.components.aggregators;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -15,55 +16,60 @@ import com.sap.sse.datamining.impl.components.GroupedDataEntry;
import com.sap.sse.datamining.impl.components.SimpleAggregationProcessorDefinition;
import com.sap.sse.datamining.shared.GroupKey;
public class ParallelGroupedDoubleDataMedianAggregationProcessor
extends AbstractParallelGroupedDataStoringAggregationProcessor<Double, Double> {
public class ParallelGroupedNumberDataMedianAggregationProcessor
extends AbstractParallelGroupedDataStoringAggregationProcessor<Number, Number> {
private static final AggregationProcessorDefinition<Double, Double> DEFINITION =
new SimpleAggregationProcessorDefinition<>(Double.class, Double.class, "Median", ParallelGroupedDoubleDataMedianAggregationProcessor.class);
private static final AggregationProcessorDefinition<Number, Number> DEFINITION =
new SimpleAggregationProcessorDefinition<>(Number.class, Number.class, "Median", ParallelGroupedNumberDataMedianAggregationProcessor.class);
public static AggregationProcessorDefinition<Double, Double> getDefinition() {
public static AggregationProcessorDefinition<Number, Number> getDefinition() {
return DEFINITION;
}
private Map<GroupKey, List<Double>> groupedValues;
private Map<GroupKey, List<Number>> groupedValues;
public ParallelGroupedDoubleDataMedianAggregationProcessor(ExecutorService executor,
Collection<Processor<Map<GroupKey, Double>, ?>> resultReceivers) {
public ParallelGroupedNumberDataMedianAggregationProcessor(ExecutorService executor,
Collection<Processor<Map<GroupKey, Number>, ?>> resultReceivers) {
super(executor, resultReceivers, "Median");
groupedValues = new HashMap<>();
}
@Override
protected void storeElement(GroupedDataEntry<Double> element) {
protected void storeElement(GroupedDataEntry<Number> element) {
GroupKey key = element.getKey();
if (!groupedValues.containsKey(key)) {
groupedValues.put(key, new ArrayList<Double>());
groupedValues.put(key, new ArrayList<Number>());
}
groupedValues.get(key).add(element.getDataEntry());
}
@Override
protected Map<GroupKey, Double> aggregateResult() {
Map<GroupKey, Double> result = new HashMap<>();
for (Entry<GroupKey, List<Double>> groupedValuesEntry : groupedValues.entrySet()) {
protected Map<GroupKey, Number> aggregateResult() {
Map<GroupKey, Number> result = new HashMap<>();
for (Entry<GroupKey, List<Number>> groupedValuesEntry : groupedValues.entrySet()) {
result.put(groupedValuesEntry.getKey(), getMedianOf(groupedValuesEntry.getValue()));
}
return result;
}
private Double getMedianOf(List<Double> values) {
Collections.sort(values);
private Double getMedianOf(List<Number> values) {
Collections.sort(values, new Comparator<Number>() {
@Override
public int compare(Number n1, Number n2) {
return Double.compare(n1.doubleValue(), n2.doubleValue());
}
});
if (listSizeIsEven(values)) {
int index1 = (values.size() / 2) - 1;
int index2 = index1 + 1;
return (values.get(index1) + values.get(index2)) / 2;
return (values.get(index1).doubleValue() + values.get(index2).doubleValue()) / 2;
} else {
int index = ((values.size() + 1) / 2) - 1;
return values.get(index);
return values.get(index).doubleValue();
}
}
private boolean listSizeIsEven(List<Double> values) {
private boolean listSizeIsEven(List<?> values) {
return values.size() % 2 == 0;
}
@@ -11,35 +11,35 @@ import com.sap.sse.datamining.impl.components.GroupedDataEntry;
import com.sap.sse.datamining.impl.components.SimpleAggregationProcessorDefinition;
import com.sap.sse.datamining.shared.GroupKey;
public class ParallelGroupedDoubleDataMinAggregationProcessor
extends AbstractParallelGroupedDataStoringAggregationProcessor<Double, Double> {
public class ParallelGroupedNumberDataMinAggregationProcessor
extends AbstractParallelGroupedDataAggregationProcessor<Number, Number> {
private static final AggregationProcessorDefinition<Double, Double> DEFINITION =
new SimpleAggregationProcessorDefinition<>(Double.class, Double.class, "Minimum", ParallelGroupedDoubleDataMinAggregationProcessor.class);
private static final AggregationProcessorDefinition<Number, Number> DEFINITION =
new SimpleAggregationProcessorDefinition<>(Number.class, Number.class, "Minimum", ParallelGroupedNumberDataMinAggregationProcessor.class);
public static AggregationProcessorDefinition<Double, Double> getDefinition() {
public static AggregationProcessorDefinition<Number, Number> getDefinition() {
return DEFINITION;
}
private Map<GroupKey, Double> minMap;
private Map<GroupKey, Number> minMap;
public ParallelGroupedDoubleDataMinAggregationProcessor(ExecutorService executor,
Collection<Processor<Map<GroupKey, Double>, ?>> resultReceivers) {
public ParallelGroupedNumberDataMinAggregationProcessor(ExecutorService executor,
Collection<Processor<Map<GroupKey, Number>, ?>> resultReceivers) {
super(executor, resultReceivers, "Minimum");
minMap = new HashMap<>();
}
@Override
protected void storeElement(GroupedDataEntry<Double> element) {
protected void handleElement(GroupedDataEntry<Number> element) {
GroupKey key = element.getKey();
Double value = element.getDataEntry();
if (!minMap.containsKey(key) || value < minMap.get(key)) {
Number value = element.getDataEntry();
if (!minMap.containsKey(key) || value.doubleValue() < minMap.get(key).doubleValue()) {
minMap.put(key, value);
}
}
@Override
protected Map<GroupKey, Double> aggregateResult() {
protected Map<GroupKey, Number> getResult() {
return minMap;
}
@@ -0,0 +1,47 @@
package com.sap.sse.datamining.impl.components.aggregators;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import com.sap.sse.datamining.components.AggregationProcessorDefinition;
import com.sap.sse.datamining.components.Processor;
import com.sap.sse.datamining.impl.components.GroupedDataEntry;
import com.sap.sse.datamining.impl.components.SimpleAggregationProcessorDefinition;
import com.sap.sse.datamining.shared.GroupKey;
public class ParallelGroupedNumberDataSumAggregationProcessor
extends AbstractParallelGroupedDataAggregationProcessor<Number, Number> {
private static final AggregationProcessorDefinition<Number, Number> DEFINITION =
new SimpleAggregationProcessorDefinition<>(Number.class, Number.class, "Sum", ParallelGroupedNumberDataSumAggregationProcessor.class);
public static AggregationProcessorDefinition<Number, Number> getDefinition() {
return DEFINITION;
}
private Map<GroupKey, Number> result;
public ParallelGroupedNumberDataSumAggregationProcessor(ExecutorService executor,
Collection<Processor<Map<GroupKey, Number>, ?>> resultReceivers) {
super(executor, resultReceivers, "Sum");
result = new HashMap<>();
}
@Override
protected void handleElement(GroupedDataEntry<Number> element) {
GroupKey key = element.getKey();
if (!result.containsKey(key)) {
result.put(key, element.getDataEntry());
} else {
result.put(key, result.get(key).doubleValue() + element.getDataEntry().doubleValue());
}
}
@Override
protected Map<GroupKey, Number> getResult() {
return result;
}
}
@@ -2,8 +2,8 @@ package com.sap.sse.datamining.impl.components.management;
import com.sap.sse.datamining.Query;
import com.sap.sse.datamining.components.management.DataMiningQueryManager;
import com.sap.sse.datamining.data.QueryResult;
import com.sap.sse.datamining.shared.DataMiningSession;
import com.sap.sse.datamining.shared.QueryResult;
public class NullDataMiningQueryManager implements DataMiningQueryManager {
@@ -6,8 +6,8 @@ import java.util.concurrent.ConcurrentMap;
import com.sap.sse.datamining.Query;
import com.sap.sse.datamining.QueryState;
import com.sap.sse.datamining.components.management.DataMiningQueryManager;
import com.sap.sse.datamining.data.QueryResult;
import com.sap.sse.datamining.shared.DataMiningSession;
import com.sap.sse.datamining.shared.QueryResult;
public abstract class SingleQueryPerKeyManager<T> implements DataMiningQueryManager {
@@ -6,8 +6,8 @@ import java.util.Map;
import com.sap.sse.datamining.Query;
import com.sap.sse.datamining.Query.QueryType;
import com.sap.sse.datamining.components.management.DataMiningQueryManager;
import com.sap.sse.datamining.data.QueryResult;
import com.sap.sse.datamining.shared.DataMiningSession;
import com.sap.sse.datamining.shared.QueryResult;
public class StrategyPerQueryTypeManager implements DataMiningQueryManager {
@@ -0,0 +1,44 @@
package com.sap.sse.datamining.impl.data;
import java.util.Map;
import com.sap.sse.datamining.data.QueryResult;
import com.sap.sse.datamining.shared.AdditionalResultData;
import com.sap.sse.datamining.shared.GroupKey;
import com.sap.sse.datamining.shared.data.QueryResultState;
import com.sap.sse.datamining.shared.impl.NullAdditionalResultData;
import com.sap.sse.datamining.shared.impl.QueryResultBaseImpl;
public class QueryResultImpl<ResultType> extends QueryResultBaseImpl<ResultType> implements QueryResult<ResultType> {
private static final long serialVersionUID = 5173796619174827696L;
private Class<ResultType> resultType;
/**
* Constructor for the GWT-Serialization. Don't use this!
*/
@Deprecated
QueryResultImpl() {
super();
}
public QueryResultImpl(QueryResultState state, Class<ResultType> resultType, Map<GroupKey, ResultType> results) {
this(state, resultType, results, new NullAdditionalResultData());
}
public QueryResultImpl(QueryResultState state, Class<ResultType> resultType, Map<GroupKey, ResultType> results, AdditionalResultData additionalData) {
super(state, results, additionalData);
this.resultType = resultType;
}
@Override
public Class<ResultType> getResultType() {
return resultType;
}
@Override
public AdditionalResultData getAdditionalData() {
return super.getAdditionalData();
}
}
@@ -115,7 +115,9 @@ public abstract class AbstractServerReplicationTestSetUp<ReplicableInterface ext
}
/**
* Calls {@link #persistenceSetUp(boolean)} first.
* Calls {@link #persistenceSetUp(boolean)} first. Doesn't {@link
* ReplicationServiceImpl#registerReplica(ReplicaDescriptor) register the replica} yet with the master.
*
* @param master
* if not <code>null</code>, the value will be used for {@link #master}; otherwise, a new racing event
* service will be created as master
@@ -146,7 +148,7 @@ public abstract class AbstractServerReplicationTestSetUp<ReplicableInterface ext
ReplicationInstancesManager rim = new ReplicationInstancesManager();
masterReplicator = new ReplicationServiceImpl(exchangeName, exchangeHost, 0, rim, new SingletonReplicablesProvider(this.master));
replicaDescriptor = new ReplicaDescriptor(InetAddress.getLocalHost(), serverUuid, "");
masterReplicator.registerReplica(replicaDescriptor);
// connect to exchange host and local server running as master
// master server and exchange host can be two different hosts
ReplicationServiceTestImpl<ReplicableInterface> replicaReplicator = new ReplicationServiceTestImpl<ReplicableInterface>(exchangeName, exchangeHost, rim, replicaDescriptor,
@@ -281,6 +283,7 @@ public abstract class AbstractServerReplicationTestSetUp<ReplicableInterface ext
} else if (request.contains("REGISTER")) {
final String uuid = UUID.randomUUID().toString();
registerReplicaUuidForMaster(uuid, masterDescriptor);
masterReplicationService.registerReplica(replicaDescriptor);
pw.print(uuid.getBytes());
} else if (request.contains("INITIAL_LOAD")) {
Channel channel = masterReplicationService.createMasterChannel();