Merge branch 'master' into bug3294

Conflicts:
	java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java
This commit is contained in:
Axel Uhl committed 2015-09-29 09:19:55 +02:00
commit 5fe85aa465
48 files changed
+218 -335

No files matched your search

@@ -5,7 +5,6 @@ import com.sap.sailing.domain.common.Distance;
import com.sap.sailing.domain.common.Speed;
import com.sap.sse.datamining.annotations.Connector;
import com.sap.sse.datamining.annotations.Statistic;
import com.sap.sse.datamining.annotations.data.Unit;
public interface HasRaceOfCompetitorContext {
@@ -15,7 +14,7 @@ public interface HasRaceOfCompetitorContext {
@Connector(messageKey="Competitor")
public Competitor getCompetitor();
@Statistic(messageKey="DistanceAtStart", resultUnit=Unit.None, resultDecimals=2, ordinal=0)
@Statistic(messageKey="DistanceAtStart", resultDecimals=2, ordinal=0)
public Distance getDistanceToStartLineAtStart();
@Statistic(messageKey="DistanceToStarboardSideAtStart", resultDecimals=2, ordinal=1)
@@ -5,7 +5,6 @@ import com.sap.sailing.domain.common.Distance;
import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor;
import com.sap.sse.datamining.annotations.Connector;
import com.sap.sse.datamining.annotations.Statistic;
import com.sap.sse.datamining.annotations.data.Unit;
public interface HasTrackedLegOfCompetitorContext {
@@ -17,7 +16,7 @@ public interface HasTrackedLegOfCompetitorContext {
@Connector(messageKey="Competitor")
public Competitor getCompetitor();
@Statistic(messageKey="DistanceTraveled", resultUnit=Unit.None, resultDecimals=0, ordinal=0)
@Statistic(messageKey="DistanceTraveled", resultDecimals=0, ordinal=0)
public Distance getDistanceTraveled();
@Statistic(messageKey="RankGainsOrLosses", resultDecimals=2, ordinal=1)
@@ -5,7 +5,6 @@ import java.io.Serializable;
import com.sap.sse.common.Duration;
import com.sap.sse.common.TimePoint;
import com.sap.sse.datamining.annotations.Statistic;
import com.sap.sse.datamining.annotations.data.Unit;
/**
* A speed, convertible in various units of measure. Can be negative.
@@ -63,7 +62,7 @@ public interface Speed extends Comparable<Speed>, Serializable {
}
};
@Statistic(messageKey="", resultDecimals=2, resultUnit=Unit.Knots)
@Statistic(messageKey="", resultDecimals=2)
double getKnots();
double getMetersPerSecond();
@@ -11,7 +11,7 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
* the event-iterators of the {@code RaceLog} ({@link RaceLog#getUnrevokedEvents()},
* {@link RaceLog#getUnrevokedEventsDescending()}).
* <p>
* The event {@code r} can only successufully revoke {@code e}, if {@code r}'s priority is higher
* The event {@code r} can only successfully revoke {@code e}, if {@code r}'s priority is higher
* (author prio, timepoint), and if {@code e} is of an event type that implements {@code Revokable}.
* @author Fredrik Teschke
*
@@ -43,7 +43,7 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem
this.raceLogStore = raceLogStore;
this.regattaLikeParent = regattaLikeParent;
for (final Fleet fleet : getFleets()) {
reloadRaceLog(fleet);
reloadRaceLog(fleet);
}
}
@@ -57,6 +57,14 @@ public abstract class AbstractRaceRankComparator<C extends Comparable<C>> implem
this.lessIsBetter = lessIsBetter;
}
protected TimePoint getTimePoint() {
return timePoint;
}
protected TrackedRace getTrackedRace() {
return trackedRace;
}
@Override
public int compare(Competitor o1, Competitor o2) {
int result;
@@ -39,21 +39,24 @@ import com.sap.sse.common.TimePoint;
*/
public class RaceRankComparator extends AbstractRaceRankComparator<Distance> {
private final Map<Competitor, Distance> windwardDistanceToGoInLegCache;
private final WindLegTypeAndLegBearingCache cache;
public RaceRankComparator(TrackedRace trackedRace, TimePoint timePoint, WindLegTypeAndLegBearingCache cache) {
super(trackedRace, timePoint, /* lessIsBetter */ true);
this.cache = cache;
this.windwardDistanceToGoInLegCache = new HashMap<Competitor, Distance>();
for (Competitor competitor : trackedRace.getRace().getCompetitors()) {
final TrackedLegOfCompetitor trackedLegOfCompetitor = trackedRace.getTrackedLeg(competitor, timePoint);
if (trackedLegOfCompetitor != null) {
windwardDistanceToGoInLegCache.put(competitor, trackedLegOfCompetitor.getWindwardDistanceToGo(timePoint,
WindPositionMode.LEG_MIDDLE, cache));
}
}
}
@Override
protected Distance getComparisonValueForSameLeg(Competitor o1) {
return windwardDistanceToGoInLegCache.get(o1);
protected Distance getComparisonValueForSameLeg(Competitor competitor) {
Distance result = windwardDistanceToGoInLegCache.get(competitor);
if (result == null) {
final TrackedLegOfCompetitor trackedLegOfCompetitor = getTrackedRace().getTrackedLeg(competitor, getTimePoint());
if (trackedLegOfCompetitor != null) {
result = trackedLegOfCompetitor.getWindwardDistanceToGo(getTimePoint(), WindPositionMode.LEG_MIDDLE, cache);
windwardDistanceToGoInLegCache.put(competitor, result);
}
}
return result;
}
}
@@ -103,6 +103,7 @@ public abstract class CourseManagementWidget implements IsWidget {
}
}
});
waypoints.getTable().addColumn(waypointsActionColumn);
waypoints.getSelectionModel().addSelectionChangeHandler(new Handler() {
@@ -1,5 +1,7 @@
package com.sap.sailing.gwt.ui.adminconsole;
import java.util.Set;
import com.google.gwt.cell.client.FieldUpdater;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
@@ -47,7 +49,29 @@ public class RaceLogTrackingCourseDefinitionDialog extends RaceLogTrackingDialog
});
marksBtnsPanel.add(addMark);
Button removeMark = new Button(stringMessages.remove(stringMessages.mark()));
removeMark.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
Set<MarkDTO> marksToRemove = marks.getSelectionModel().getSelectedSet();
for (MarkDTO markToRemove : marksToRemove) {
sailingService.revokeMarkDefinitionEventInRaceLog(leaderboardName, raceColumnName, fleetName, markToRemove, new AsyncCallback<Void>() {
@Override
public void onSuccess(Void result) {
refresh();
}
@Override
public void onFailure(Throwable caught) {
}
});
}
}
});
marksBtnsPanel.add(removeMark);
Button cancel = new Button(stringMessages.cancel());
cancel.addClickHandler(new ClickHandler() {
@Override
@@ -30,7 +30,7 @@ public class RaceLogTrackingEventManagementImagesBarCell extends ImagesBarCell {
protected Iterable<ImageSpec> getImageSpecs() {
ArrayList<ImageSpec> result = new ArrayList<ImageSpec>();
result.add(new ImageSpec(ACTION_DENOTE_FOR_RACELOG_TRACKING, stringMessages.denoteForRaceLogTracking(),
result.add(new ImageSpec(ACTION_DENOTE_FOR_RACELOG_TRACKING, stringMessages.denoteAllRacesForRaceLogTrackingShorctut(),
makeImagePrototype(resources.denoteForRaceLogTracking())));
result.add(new ImageSpec(ACTION_COMPETITOR_REGISTRATIONS, stringMessages.competitorRegistrations(),
makeImagePrototype(resources.competitorRegistrations())));
@@ -616,4 +616,7 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS
void setTrackingTimes(RaceLogSetTrackingTimesDTO dto);
Pair<TimePoint, TimePoint> getTrackingTimes(String leaderboardName, String raceColumnName, String fleetName);
void revokeMarkDefinitionEventInRaceLog(String leaderboardName, String raceColumnName, String fleetName,
MarkDTO markDTO);
}
@@ -719,4 +719,7 @@ public interface SailingServiceAsync extends ServerInfoRetriever, FileStorageMan
void getTrackingTimes(String leaderboardName, String raceColumnName, String fleetName,
AsyncCallback<Pair<TimePoint, TimePoint>> callback);
void revokeMarkDefinitionEventInRaceLog(String leaderboardName, String raceColumnName, String fleetName,
MarkDTO markDTO, AsyncCallback<Void> callback);
}
@@ -1387,5 +1387,6 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, c
String tabbedResultsPresenter();
String polarResultsPresenter();
String dataMiningRetrieval();
String denoteAllRacesForRaceLogTrackingShorctut();
String createDefaultRegattaLeaderboard();
}
@@ -1356,3 +1356,4 @@ resultsChart=Results Chart
tabbedResultsPresenter=Tabbed Results Presenter
polarResultsPresenter=Polar Results Presenter
dataMiningRetrieval=Data Retrieval
denoteAllRacesForRaceLogTrackingShorctut=Shortcut to denote all races for racelog tracking
@@ -1345,3 +1345,4 @@ resultsChart=Ergebnis-Diagramm
tabbedResultsPresenter=Tab Ergebnis-Darsteller
polarResultsPresenter=Polar Ergebnis-Darsteller
dataMiningRetrieval=Datenbeschaffung
denoteAllRacesForRaceLogTrackingShorctut=Alle rennen für racelog tracking markieren
@@ -186,8 +186,7 @@ public class ResultsChart extends AbstractResultsPresenterWithDataProviders<Sett
private void updateChartLabels() {
chart.getYAxis().setAxisTitleText(getCurrentResult().getResultSignifier());
chart.setToolTip(new ToolTip().setValueDecimals(decimalsListBox.getValue())
.setValueSuffix(getCurrentResult().getUnitSignifier()));
chart.setToolTip(new ToolTip().setValueDecimals(decimalsListBox.getValue()));
}
private void updateChartSubtitle() {
@@ -79,6 +79,7 @@ import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.FlagPoleSta
import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.gate.ReadonlyGateStartRacingProcedure;
import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.rrs26.ReadonlyRRS26RacingProcedure;
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogCloseOpenEndedDeviceMappingEvent;
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDefineMarkEvent;
import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.DefinedMarkFinder;
import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RaceLogOpenEndedDeviceMappingCloser;
import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RaceLogTrackingStateAnalyzer;
@@ -4994,6 +4995,28 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
raceLog.add(event);
}
@Override
public void revokeMarkDefinitionEventInRaceLog(String leaderboardName, String raceColumnName, String fleetName, MarkDTO markDTO) {
RaceLog raceLog = getRaceLog(leaderboardName, raceColumnName, fleetName);
final List<RaceLogEvent> raceLogDeviceMarkMappingEvents = new AllEventsOfTypeFinder<>(raceLog, /* only unrevoked */ true, RaceLogDefineMarkEvent.class).analyze();
RaceLogEvent eventToRevoke = null;
for (RaceLogEvent event : raceLogDeviceMarkMappingEvents) {
RaceLogDefineMarkEvent defineMarkEvent = (RaceLogDefineMarkEvent) event;
if (defineMarkEvent.getMark().getId().toString().equals(markDTO.getIdAsString())){
eventToRevoke = event;
}
}
if (eventToRevoke != null){
RaceLogEvent event = RaceLogEventFactory.INSTANCE.createRevokeEvent(getService().getServerAuthor(), raceLog.getCurrentPassId(), eventToRevoke, "Revoked by AdminConsole (RaceLogTracking)");
raceLog.add(event);
} else {
logger.warning("Could not revoke event for mark "+markDTO.getIdAsString()+". Mark not found in RaceLog.");
}
}
@Override
public Iterable<MarkDTO> getMarksInRaceLog(String leaderboardName, String raceColumnName, String fleetName) {
RaceLog raceLog = getRaceLog(leaderboardName, raceColumnName, fleetName);
@@ -1,8 +1,6 @@
package com.sap.sailing.mongodb.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -11,11 +9,8 @@ import java.net.UnknownHostException;
import java.util.Collections;
import java.util.UUID;
import org.bson.types.ObjectId;
import org.junit.Test;
import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.MongoException;
import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl;
@@ -28,9 +23,7 @@ import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.common.racelog.Flags;
import com.sap.sailing.domain.persistence.PersistenceFactory;
import com.sap.sailing.domain.persistence.impl.DomainObjectFactoryImpl;
import com.sap.sailing.domain.persistence.impl.FieldNames;
import com.sap.sailing.domain.persistence.impl.MongoObjectFactoryImpl;
import com.sap.sailing.domain.persistence.impl.TripleSerializer;
import com.sap.sailing.domain.racelog.RaceLogIdentifier;
import com.sap.sailing.domain.racelog.impl.RaceLogIdentifierImpl;
import com.sap.sailing.domain.regattalike.RegattaLikeIdentifier;
@@ -97,93 +90,6 @@ public class StoreAndLoadRaceLogsTest extends AbstractMongoDBTest {
}
}
@Test
public void testdLoadObsoleteIdentifier() {
// Identifier is A.A B.B C.C
DBObject dbEvent1 = (DBObject) com.mongodb.util.JSON.parse(createOldFormatRaceLogEventJson(UUID.randomUUID()));
mongoFactory.getRaceLogCollection().insert(dbEvent1);
DBObject dbEvent2 = (DBObject) com.mongodb.util.JSON.parse(createOldFormatRaceLogEventJson(UUID.randomUUID()));
mongoFactory.getRaceLogCollection().insert(dbEvent2);
RaceLog raceLog = domainFactory.loadRaceLog(createIdentifier("A.A", "B.B", "C.C"));
try {
raceLog.lockForRead();
assertEquals(2, Util.size(raceLog.getRawFixes()));
} finally {
raceLog.unlockAfterRead();
}
}
@Test
public void testLoadObsoleteAndNewIdentifier() {
// event1 stored with obsolete identifier
DBObject dbEvent1 = (DBObject) com.mongodb.util.JSON.parse(createOldFormatRaceLogEventJson(UUID.randomUUID()));
mongoFactory.getRaceLogCollection().insert(dbEvent1);
// event2 stored with new identifier
RaceLogIdentifier identifier = createIdentifier("A.A", "B.B", "C.C");
RaceLogFlagEvent event2 = createRaceLogFlagEvent(UUID.randomUUID());
DBObject dbEvent2 = mongoFactory.storeRaceLogEntry(identifier, event2);
mongoFactory.getRaceLogCollection().insert(dbEvent2);
RaceLog raceLog = domainFactory.loadRaceLog(identifier);
try {
raceLog.lockForRead();
assertEquals(2, Util.size(raceLog.getRawFixes()));
} finally {
raceLog.unlockAfterRead();
}
}
@Test
public void testMigrateObsoleteIdentifier() {
DBCollection collection = mongoFactory.getRaceLogCollection();
RaceLogIdentifier identifier = createIdentifier("A.A", "B.B", "C.C");
// Insert new style event (which should be untouched by migration)...
RaceLogFlagEvent newStyleEvent = createRaceLogFlagEvent(UUID.randomUUID());
DBObject newStyleEventObject = mongoFactory.storeRaceLogEntry(identifier, newStyleEvent);
mongoFactory.getRaceLogCollection().insert(newStyleEventObject);
// ... insert old style event...
DBObject dbEvent1 = (DBObject) com.mongodb.util.JSON.parse(createOldFormatRaceLogEventJson(UUID.randomUUID()));
collection.insert(dbEvent1);
// ... ensure that it is in the database...
BasicDBObject query = new BasicDBObject();
query.put(FieldNames.RACE_LOG_IDENTIFIER.name(), OldFormatRaceLogIdentifier);
assertTrue(collection.find(query).hasNext());
// ... loading it should trigger the migration...
domainFactory.loadRaceLog(identifier);
// ... check that old event is gone...
assertFalse("Event with old identifier should be gone after migration", collection.find(query).hasNext());
// ... and new event is stored...
query.put(FieldNames.RACE_LOG_IDENTIFIER.name(), TripleSerializer.serialize(identifier.getIdentifier()));
assertTrue("After migration the event should be found with new identifier", collection.find(query).hasNext());
// ... finally loading this racelog should yield both our events
RaceLog raceLog = domainFactory.loadRaceLog(identifier);
try {
raceLog.lockForRead();
assertEquals(2, Util.size(raceLog.getRawFixes()));
} finally {
raceLog.unlockAfterRead();
}
}
private static final String OldFormatRaceLogIdentifier = "A%2EA%2EB%2EB%2EC%2EC";
private String createOldFormatRaceLogEventJson(Serializable id) {
return "{ \"_id\" : { \"$oid\" : \""+ new ObjectId().toHexString() + "\"} , \"RACE_LOG_IDENTIFIER\" : \"" + OldFormatRaceLogIdentifier + "\" , \"RACE_LOG_EVENT\" : "
+ "{ \"TIME_AS_MILLIS\" : 42 , \"RACE_LOG_EVENT_CREATED_AT\" : 1376058090051 , \"RACE_LOG_EVENT_ID\" : { \"$uuid\" : \"" + id.toString() + "\"} , "
+ "\"RACE_LOG_EVENT_PASS_ID\" : 42 , \"RACE_LOG_EVENT_INVOLVED_BOATS\" : [ ] , \"RACE_LOG_EVENT_CLASS\" : \"RaceLogFlagEvent\" , \"RACE_LOG_EVENT_FLAG_UPPER\" : \"ALPHA\" , "
+ "\"RACE_LOG_EVENT_FLAG_LOWER\" : \"BRAVO\" , \"RACE_LOG_EVENT_FLAG_DISPLAYED\" : \"true\"}}";
}
private RaceLogIdentifier createIdentifier(String groupName, String raceColumnName, String fleetName) {
RegattaLikeIdentifier regattaLike = mock(RegattaLikeIdentifier.class);
when(regattaLike.getName()).thenReturn(groupName);
@@ -249,8 +249,8 @@ public class ImportMasterDataOperation extends
}
if (leaderboard != null) {
toState.addLeaderboard(leaderboard);
storeRaceLogEvents(leaderboard, toState.getMongoObjectFactory(), toState.getDomainObjectFactory());
storeRegattaLogEvents(leaderboard, toState.getMongoObjectFactory(), toState.getDomainObjectFactory());
storeRaceLogEvents(leaderboard, toState.getMongoObjectFactory(), toState.getDomainObjectFactory(), override);
storeRegattaLogEvents(leaderboard, toState.getMongoObjectFactory(), toState.getDomainObjectFactory(), override);
creationCount.addOneLeaderboard(leaderboard.getName());
relinkTrackedRacesIfPossible(toState, leaderboard);
toState.updateStoredLeaderboard(leaderboard);
@@ -275,33 +275,46 @@ public class ImportMasterDataOperation extends
}
/**
* Ensures that the race log events are stored to the receiving instance's database. The race logs have been received
* in serialized form on the {@link RaceColumn} objects, but the database doesn't yet know about them. This method uses
* a <code>MongoRaceLogStoreVisitor</code> to store all race log events to the database.
* Ensures that the race log events are stored to the receiving instance's database. The race logs have been
* received in serialized form on the {@link RaceColumn} objects, but the database doesn't yet know about them. This
* method uses a <code>MongoRaceLogStoreVisitor</code> to store all race log events to the database.
*/
private void storeRaceLogEvents(Leaderboard leaderboard, MongoObjectFactory mongoObjectFactory, DomainObjectFactory domainObjectFactory) {
RaceLogStore mongoRaceLogStore = MongoRaceLogStoreFactory.INSTANCE.getMongoRaceLogStore(mongoObjectFactory, domainObjectFactory);
private void storeRaceLogEvents(Leaderboard leaderboard, MongoObjectFactory mongoObjectFactory,
DomainObjectFactory domainObjectFactory, boolean override) {
RaceLogStore mongoRaceLogStore = MongoRaceLogStoreFactory.INSTANCE.getMongoRaceLogStore(mongoObjectFactory,
domainObjectFactory);
for (RaceColumn raceColumn : leaderboard.getRaceColumns()) {
for (Fleet fleet : raceColumn.getFleets()) {
RaceLog log = raceColumn.getRaceLog(fleet);
if (log != null) {
RaceLogIdentifier identifier = raceColumn.getRaceLogIdentifier(fleet);
RaceLogEventVisitor storeVisitor = MongoRaceLogStoreFactory.INSTANCE.getMongoRaceLogStoreVisitor(
identifier, mongoObjectFactory);
log.lockForRead();
try {
for (RaceLogEvent event : log.getRawFixes()) {
event.accept(storeVisitor);
}
} finally {
log.unlockAfterRead();
RaceLog currentPersistedLog = mongoRaceLogStore.getRaceLog(identifier, true);
if (currentPersistedLog.isEmpty()) {
addAllmportedEvents(mongoObjectFactory, mongoRaceLogStore, log, identifier);
} else if (override) {
// Clear existing race log
mongoRaceLogStore.removeRaceLog(identifier);
addAllmportedEvents(mongoObjectFactory, mongoRaceLogStore, log, identifier);
}
// Make sure listener is added to race log
mongoRaceLogStore.addImportedRaceLog(log, identifier);
}
}
}
}
private void addAllmportedEvents(MongoObjectFactory mongoObjectFactory, RaceLogStore mongoRaceLogStore,
RaceLog log, RaceLogIdentifier identifier) {
RaceLogEventVisitor storeVisitor = MongoRaceLogStoreFactory.INSTANCE
.getMongoRaceLogStoreVisitor(identifier, mongoObjectFactory);
log.lockForRead();
try {
for (RaceLogEvent event : log.getRawFixes()) {
event.accept(storeVisitor);
}
} finally {
log.unlockAfterRead();
}
// Make sure listener is added to race log
mongoRaceLogStore.addImportedRaceLog(log, identifier);
}
/**
@@ -309,7 +322,8 @@ public class ImportMasterDataOperation extends
* potentially {@link HasRegattaLike has} an attached RegattaLog, which then must be stored in the database.
* @see #storeRaceLogEvents(Leaderboard, MongoObjectFactory)
*/
private void storeRegattaLogEvents(Leaderboard leaderboard, MongoObjectFactory mongoObjectFactory, DomainObjectFactory domainObjectFactory) {
private void storeRegattaLogEvents(Leaderboard leaderboard, MongoObjectFactory mongoObjectFactory, DomainObjectFactory domainObjectFactory,
boolean override) {
RegattaLogStore regattaLogStore = MongoRegattaLogStoreFactory.INSTANCE.getMongoRegattaLogStore(mongoObjectFactory, domainObjectFactory);
if (leaderboard instanceof HasRegattaLike) {
IsRegattaLike regattaLike = ((HasRegattaLike) leaderboard).getRegattaLike();
@@ -317,18 +331,30 @@ public class ImportMasterDataOperation extends
RegattaLikeIdentifier identifier = regattaLike.getRegattaLikeIdentifier();
RegattaLogEventVisitor storeVisitor = MongoRegattaLogStoreFactory.INSTANCE.getMongoRegattaLogStoreVisitor(
identifier, mongoObjectFactory);
log.lockForRead();
try {
for (RegattaLogEvent event : log.getRawFixes()) {
event.accept(storeVisitor);
}
} finally {
log.unlockAfterRead();
RegattaLog currentPersistedLog = regattaLogStore.getRegattaLog(identifier, true);
if (currentPersistedLog.isEmpty()) {
addAllImportedRegattaEvents(regattaLogStore, log, identifier, storeVisitor);
} else if (override) {
//Clear existing regatta log
regattaLogStore.removeRegattaLog(identifier);
addAllImportedRegattaEvents(regattaLogStore, log, identifier, storeVisitor);
}
regattaLogStore.addImportedRegattaLog(log, identifier);
}
}
private void addAllImportedRegattaEvents(RegattaLogStore regattaLogStore, RegattaLog log,
RegattaLikeIdentifier identifier, RegattaLogEventVisitor storeVisitor) {
log.lockForRead();
try {
for (RegattaLogEvent event : log.getRawFixes()) {
event.accept(storeVisitor);
}
} finally {
log.unlockAfterRead();
}
regattaLogStore.addImportedRegattaLog(log, identifier);
}
private void relinkTrackedRacesIfPossible(RacingEventService toState, Leaderboard newLeaderboard) {
if (newLeaderboard instanceof FlexibleLeaderboard) {
for (RaceColumn raceColumn : newLeaderboard.getRaceColumns()) {
@@ -5,5 +5,4 @@ Bundle-SymbolicName: com.sap.sse.datamining.annotations
Bundle-Version: 1.0.0.qualifier
Bundle-Vendor: SAP
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Export-Package: com.sap.sse.datamining.annotations,
com.sap.sse.datamining.annotations.data
Export-Package: com.sap.sse.datamining.annotations
@@ -7,8 +7,6 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Locale;
import com.sap.sse.datamining.annotations.data.Unit;
/**
* Methods marked with this annotation will be used as computable key figures for the data mining framework. The method will be called,
* if the key figure of a data element is requested.<br />
@@ -45,11 +43,6 @@ public @interface Statistic {
*/
public int ordinal() default Integer.MAX_VALUE;
/**
* The {@link Unit} of the methods return value. The default value is {@link Unit#None}.
*/
public Unit resultUnit() default Unit.None;
/**
* The number of decimals of the methods return value. The default value is <code>0</code>.
*/
@@ -1,14 +0,0 @@
package com.sap.sse.datamining.annotations.data;
/**
* Enum for the different Units of key figures.<br>
* <b>Every member needs a message key in <code>StringMessages*.properties</code> of {@link com.sap.sse.datamining}.</b>
*
* @author Lennart Hensler (D054527)
*
*/
public enum Unit {
None, Knots, Meters
}
@@ -2,8 +2,6 @@ package com.sap.sse.datamining.shared;
import java.io.Serializable;
import com.sap.sse.datamining.annotations.data.Unit;
public interface AdditionalResultData extends Serializable {
public int getRetrievedDataAmount();
@@ -12,9 +10,6 @@ public interface AdditionalResultData extends Serializable {
public String getResultSignifier();
public Unit getUnit();
public String getUnitSignifier();
public int getValueDecimals();
}
@@ -3,7 +3,6 @@ package com.sap.sse.datamining.shared;
import java.io.Serializable;
import java.util.Map;
import com.sap.sse.datamining.annotations.data.Unit;
import com.sap.sse.datamining.shared.data.QueryResultState;
public interface QueryResultBase<ResultType> extends Serializable {
@@ -18,8 +17,6 @@ public interface QueryResultBase<ResultType> extends Serializable {
*/
public String getResultSignifier();
public Unit getUnit();
public String getUnitSignifier();
public int getValueDecimals();
public boolean isEmpty();
@@ -1,8 +1,5 @@
package com.sap.sse.datamining.shared;
import java.io.Serializable;
import com.sap.sse.datamining.annotations.data.Unit;
import com.sap.sse.datamining.shared.impl.GenericGroupKey;
import com.sap.sse.datamining.shared.impl.dto.ClusterDTO;
@@ -13,7 +10,6 @@ public final class SSEDataMiningSerializationDummy implements SerializationDummy
private GenericGroupKey<String> groupKey;
private ClusterDTO cluster;
private Number n;
private Unit unit;
private SSEDataMiningSerializationDummy() { }
@@ -1,6 +1,5 @@
package com.sap.sse.datamining.shared.impl;
import com.sap.sse.datamining.annotations.data.Unit;
import com.sap.sse.datamining.shared.AdditionalResultData;
public class AdditionalResultDataImpl implements AdditionalResultData {
@@ -8,8 +7,6 @@ public class AdditionalResultDataImpl implements AdditionalResultData {
private int retrievedDataAmount;
private String resultSignifier;
private Unit unit;
private String unitSignifier;
private int valueDecimals;
private long calculationTimeInNanos;
@@ -19,14 +16,12 @@ public class AdditionalResultDataImpl implements AdditionalResultData {
@Deprecated
AdditionalResultDataImpl() { }
public AdditionalResultDataImpl(int retrievedDataAmount, String resultSignifier, Unit unit, String unitSignifier,
int valueDecimals, long calculationTimeInNanos) {
this.retrievedDataAmount = retrievedDataAmount;
this.resultSignifier = resultSignifier;
this.unit = unit;
this.unitSignifier = unitSignifier;
this.valueDecimals = valueDecimals;
this.calculationTimeInNanos = calculationTimeInNanos;
public AdditionalResultDataImpl(int retrievedDataAmount, String resultSignifier, int valueDecimals,
long calculationTimeInNanos) {
this.retrievedDataAmount = retrievedDataAmount;
this.resultSignifier = resultSignifier;
this.valueDecimals = valueDecimals;
this.calculationTimeInNanos = calculationTimeInNanos;
}
@Override
@@ -44,16 +39,6 @@ public class AdditionalResultDataImpl implements AdditionalResultData {
return resultSignifier;
}
@Override
public Unit getUnit() {
return unit;
}
@Override
public String getUnitSignifier() {
return unitSignifier;
}
@Override
public int getValueDecimals() {
return valueDecimals;
@@ -1,6 +1,5 @@
package com.sap.sse.datamining.shared.impl;
import com.sap.sse.datamining.annotations.data.Unit;
import com.sap.sse.datamining.shared.AdditionalResultData;
/**
@@ -34,16 +33,6 @@ public class NullAdditionalResultData implements AdditionalResultData {
return "";
}
@Override
public Unit getUnit() {
return Unit.None;
}
@Override
public String getUnitSignifier() {
return "";
}
@Override
public int getValueDecimals() {
return 0;
@@ -3,7 +3,6 @@ package com.sap.sse.datamining.shared.impl;
import java.util.HashMap;
import java.util.Map;
import com.sap.sse.datamining.annotations.data.Unit;
import com.sap.sse.datamining.shared.AdditionalResultData;
import com.sap.sse.datamining.shared.GroupKey;
import com.sap.sse.datamining.shared.QueryResultBase;
@@ -63,16 +62,6 @@ public abstract class QueryResultBaseImpl<ResultType> implements QueryResultBase
return additionalData.getResultSignifier();
}
@Override
public Unit getUnit() {
return additionalData.getUnit();
}
@Override
public String getUnitSignifier() {
return additionalData.getUnitSignifier();
}
@Override
public int getValueDecimals() {
return additionalData.getValueDecimals();
@@ -6,8 +6,8 @@ Bundle-Version: 1.0.0.qualifier
Bundle-Vendor: SAP
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Fragment-Host: com.sap.sse.datamining
Require-Bundle: org.mockito.mockito-core;bundle-version="1.9.5",
org.hamcrest;bundle-version="1.1.0",
Require-Bundle: org.hamcrest;bundle-version="1.1.0",
org.mockito.mockito-core;bundle-version="1.9.5",
com.sap.sse.datamining.annotations;bundle-version="1.0.0"
Import-Package: junit.framework;version="4.8.2",
org.junit;version="4.8.2",
+1 -1
View File
@@ -9,5 +9,5 @@
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>com.sap.sse.datamining.test</artifactId>
<packaging>eclipse-plugin</packaging>
<packaging>eclipse-test-plugin</packaging>
</project>
@@ -19,7 +19,6 @@ import com.sap.sse.datamining.ModifiableDataMiningServer;
import com.sap.sse.datamining.Query;
import com.sap.sse.datamining.QueryState;
import com.sap.sse.datamining.StatisticQueryDefinition;
import com.sap.sse.datamining.annotations.data.Unit;
import com.sap.sse.datamining.components.AggregationProcessorDefinition;
import com.sap.sse.datamining.components.DataRetrieverChainDefinition;
import com.sap.sse.datamining.components.Processor;
@@ -141,7 +140,7 @@ public class TestStatisticQuery {
results.put(new GenericGroupKey<Integer>(3), 3.0);
results.put(new GenericGroupKey<Integer>(4), 10.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));
QueryResultImpl<java.lang.Number> result = new QueryResultImpl<>(QueryResultState.NORMAL, java.lang.Number.class, results, new AdditionalResultDataImpl(dataSource.size() - 2, "Cross Sum (Sum)", 0, 0));
return result;
}
@@ -150,7 +149,6 @@ public class TestStatisticQuery {
assertThat("Result values aren't correct.", result.getResults(), is(expectedResult.getResults()));
assertThat("Retrieved data amount isn't correct.", result.getRetrievedDataAmount(), is(expectedResult.getRetrievedDataAmount()));
assertThat("Result signifier isn't correct.", result.getResultSignifier(), is(expectedResult.getResultSignifier()));
assertThat("Unit isn't correct.", result.getUnit(), is(expectedResult.getUnit()));
assertThat("Value decimals aren't correct.", result.getValueDecimals(), is(expectedResult.getValueDecimals()));
}
@@ -12,7 +12,6 @@ import java.util.List;
import org.junit.Before;
import org.junit.Test;
import com.sap.sse.common.Util;
import com.sap.sse.common.settings.SerializableSettings;
import com.sap.sse.datamining.components.DataRetrieverChainBuilder;
import com.sap.sse.datamining.components.DataRetrieverChainDefinition;
@@ -291,9 +290,9 @@ public class TestDataRetrieverChainCreation {
}
private Test_RetrievalProcessorWithSettings getLastRetriever(Processor<Collection<Test_Regatta>, ?> firstRetriever) {
TestRaceWithContextRetrievalProcessor raceRetriever = (TestRaceWithContextRetrievalProcessor) Util.get(((TestRegattaRetrievalProcessor) firstRetriever).getResultReceivers(), 0);
TestLegOfCompetitorWithContextRetrievalProcessor legRetriever = (TestLegOfCompetitorWithContextRetrievalProcessor) Util.get(raceRetriever.getResultReceivers(), 0);
Test_RetrievalProcessorWithSettings lastRetriever = (Test_RetrievalProcessorWithSettings) Util.get(legRetriever.getResultReceivers(), 0);
TestRaceWithContextRetrievalProcessor raceRetriever = (TestRaceWithContextRetrievalProcessor) ((TestRegattaRetrievalProcessor) firstRetriever).getResultReceivers()[0];
TestLegOfCompetitorWithContextRetrievalProcessor legRetriever = (TestLegOfCompetitorWithContextRetrievalProcessor) raceRetriever.getResultReceivers()[0];
Test_RetrievalProcessorWithSettings lastRetriever = (Test_RetrievalProcessorWithSettings) legRetriever.getResultReceivers()[0];
return lastRetriever;
}
@@ -1,8 +1,8 @@
package com.sap.sse.datamining.impl.components.management;
import static org.hamcrest.Matchers.anyOf;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.util.Arrays;
import java.util.Collections;
@@ -15,7 +15,6 @@ import com.sap.sse.datamining.test.util.components.management.Test_MemoryMonitor
public class TestMemoryMonitorAction {
@SuppressWarnings("unchecked")
@Test
public void testSimpleActionOrdering() {
MemoryMonitorAction low = new Test_MemoryMonitorAction(0.8);
@@ -27,7 +26,7 @@ public class TestMemoryMonitorAction {
List<MemoryMonitorAction> expectedOrder1 = Arrays.asList(high1, high2, medium, low);
List<MemoryMonitorAction> expectedOrder2 = Arrays.asList(high2, high1, medium, low);
assertThat(actions, anyOf(is(expectedOrder1), is(expectedOrder2)));
assertTrue(actions.equals(expectedOrder1) || actions.equals(expectedOrder2));
}
@Test
@@ -10,7 +10,6 @@ import java.util.Locale;
import org.junit.Before;
import org.junit.Test;
import com.sap.sse.datamining.annotations.data.Unit;
import com.sap.sse.datamining.functions.Function;
import com.sap.sse.datamining.test.data.impl.ContainerElement;
import com.sap.sse.datamining.test.data.impl.ContainerElementImpl;
@@ -52,7 +51,6 @@ public class TestCompoundFunction {
compoundFunction.getDeclaringType().equals(MarkedContainer.class), is(true));
assertThat(compoundFunction.getSimpleName(), is("getContainerElement -> getName"));
assertThat(compoundFunction.getLocalizedName(Locale.ENGLISH, TestsUtil.getTestStringMessages()), is("Name"));
assertThat(compoundFunction.getResultUnit(), is(Unit.None));
assertThat(compoundFunction.getResultDecimals(), is(0));
}
@@ -1,11 +1,10 @@
package com.sap.sse.datamining.test.data.impl;
import com.sap.sse.datamining.annotations.Statistic;
import com.sap.sse.datamining.annotations.data.Unit;
public interface DataTypeInterface {
@Statistic(messageKey="speedInKnots", resultUnit=Unit.Knots, resultDecimals=2)
@Statistic(messageKey="speedInKnots", resultDecimals=2)
public int getSpeedInKnots();
}
@@ -1,11 +1,10 @@
package com.sap.sse.datamining.test.domain;
import com.sap.sse.datamining.annotations.Statistic;
import com.sap.sse.datamining.annotations.data.Unit;
public interface Test_Leg {
@Statistic(messageKey="DistanceTraveled", resultUnit=Unit.Meters, resultDecimals=0)
@Statistic(messageKey="DistanceTraveled", resultDecimals=0)
public double getDistanceTraveled();
}
@@ -2,7 +2,6 @@ package com.sap.sse.datamining.components;
import java.util.Locale;
import com.sap.sse.datamining.annotations.data.Unit;
import com.sap.sse.datamining.functions.Function;
import com.sap.sse.datamining.shared.AdditionalResultData;
import com.sap.sse.i18n.ResourceBundleStringMessages;
@@ -20,12 +19,12 @@ public interface AdditionalResultDataBuilder {
public int getRetrievedDataAmount();
/**
* Sets the used {@link Function} for the statistic extraction. Also sets the {@linkplain Unit result unit} and the amount of
* decimals to the values of the <code>Function</code> ({@link Function#getResultUnit()} and {@link Function#getResultDecimals()}).
* Sets the used {@link Function} for the statistic extraction. Also sets the amount of decimals to the values of
* the <code>Function</code> ({@link Function#getResultDecimals()}).
*
* @param extractionFunction
*/
public void setExtractionFunction(Function<?> extractionFunction);
public void setResultUnit(Unit resultUnit);
public void setResultDecimals(int resultDecimals);
public void setAggregationNameMessageKey(String aggregationNameMessageKey);
@@ -3,7 +3,6 @@ package com.sap.sse.datamining.functions;
import java.lang.reflect.InvocationTargetException;
import java.util.Locale;
import com.sap.sse.datamining.annotations.data.Unit;
import com.sap.sse.i18n.ResourceBundleStringMessages;
public interface Function<ReturnType> {
@@ -44,8 +43,6 @@ public interface Function<ReturnType> {
*/
public ReturnType tryToInvoke(Object instance, ParameterProvider parameterProvider);
public Unit getResultUnit();
public int getResultDecimals();
public int getOrdinal();
@@ -1,13 +1,19 @@
package com.sap.sse.datamining.impl;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class DataMiningExecutorService extends ThreadPoolExecutor {
public DataMiningExecutorService(int corePoolSize) {
super(corePoolSize, corePoolSize, 60, TimeUnit.SECONDS, new PriorityBlockingQueue<Runnable>());
super(corePoolSize, corePoolSize, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(corePoolSize),
new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
r.run();
}
});
}
}
@@ -34,7 +34,7 @@ public abstract class AbstractParallelMultiDimensionalNestingGroupingProcessor<D
private void verifyThatDimensionsAreDimensions(Iterable<ParameterizedFunction<?>> parameterizedDimensions) {
if (parameterizedDimensions == null) {
throw new NullPointerException("The given dimensions mustn't be null.");
throw new IllegalArgumentException("The given dimensions mustn't be null.");
}
int size = 0;
@@ -1,8 +1,6 @@
package com.sap.sse.datamining.impl.components;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicInteger;
@@ -20,7 +18,7 @@ public abstract class AbstractParallelProcessor<InputType, ResultType> extends A
private static final Logger LOGGER = Logger.getLogger(AbstractParallelProcessor.class.getName());
private static final int SLEEP_TIME_DURING_FINISHING = 100;
private final Set<Processor<ResultType, ?>> resultReceivers;
private final Processor<ResultType, ?>[] resultReceivers;
private final ExecutorService executor;
private final AtomicInteger unfinishedInstructionsCounter;
@@ -30,7 +28,9 @@ public abstract class AbstractParallelProcessor<InputType, ResultType> extends A
public AbstractParallelProcessor(Class<InputType> inputType, Class<ResultType> resultType, ExecutorService executor, Collection<Processor<ResultType, ?>> resultReceivers) {
super(inputType, resultType);
this.executor = executor;
this.resultReceivers = new HashSet<Processor<ResultType, ?>>(resultReceivers);
@SuppressWarnings("unchecked")
final Processor<ResultType, ?>[] resultReceiversAsArray = (Processor<ResultType, ?>[]) new Processor<?, ?>[resultReceivers.size()];
this.resultReceivers = resultReceivers.toArray(resultReceiversAsArray);
unfinishedInstructionsCounter = new AtomicInteger();
}
@@ -74,7 +74,7 @@ public abstract class AbstractParallelProcessor<InputType, ResultType> extends A
unfinishedInstructionsCounter.getAndDecrement();
}
protected Iterable<Processor<ResultType, ?>> getResultReceivers() {
protected Processor<ResultType, ?>[] getResultReceivers() {
return resultReceivers;
}
@@ -2,7 +2,6 @@ package com.sap.sse.datamining.impl.components;
import java.util.Locale;
import com.sap.sse.datamining.annotations.data.Unit;
import com.sap.sse.datamining.components.AdditionalResultDataBuilder;
import com.sap.sse.datamining.functions.Function;
import com.sap.sse.datamining.shared.AdditionalResultData;
@@ -21,7 +20,6 @@ public class OverwritingResultDataBuilder implements AdditionalResultDataBuilder
private int retrievedDataAmount;
private Function<?> extractionFunction;
private String aggregationNameMessageKey;
private Unit resultUnit;
private int resultDecimals;
/**
@@ -29,16 +27,13 @@ public class OverwritingResultDataBuilder implements AdditionalResultDataBuilder
*/
public OverwritingResultDataBuilder() {
retrievedDataAmount = 0;
resultUnit = Unit.None;
resultDecimals = 0;
}
@Override
public AdditionalResultData build(long calculationTimeInNanos, ResourceBundleStringMessages stringMessages, Locale locale) {
String unitSignifier = buildUnitSignifier(stringMessages, locale);
String resultSignifier = buildResultSignifier(stringMessages, locale);
return new AdditionalResultDataImpl(retrievedDataAmount, resultSignifier, resultUnit, unitSignifier,
resultDecimals, calculationTimeInNanos);
return new AdditionalResultDataImpl(retrievedDataAmount, resultSignifier, resultDecimals, calculationTimeInNanos);
}
private String buildResultSignifier(ResourceBundleStringMessages stringMessages, Locale locale) {
@@ -51,14 +46,6 @@ public class OverwritingResultDataBuilder implements AdditionalResultDataBuilder
return stringMessages.get(locale, "ResultSignifier", extractedStatisticName, aggregationName);
}
private String buildUnitSignifier(ResourceBundleStringMessages stringMessages, Locale locale) {
if (resultUnit == null || resultUnit == Unit.None) {
return "";
}
return stringMessages.get(locale, resultUnit.toString());
}
@Override
public void setRetrievedDataAmount(int retrievedDataAmount) {
this.retrievedDataAmount = retrievedDataAmount;
@@ -72,15 +59,9 @@ public class OverwritingResultDataBuilder implements AdditionalResultDataBuilder
@Override
public void setExtractionFunction(Function<?> extractionFunction) {
this.extractionFunction = extractionFunction;
setResultUnit(extractionFunction.getResultUnit());
setResultDecimals(extractionFunction.getResultDecimals());
}
@Override
public void setResultUnit(Unit resultUnit) {
this.resultUnit = resultUnit;
}
@Override
public void setResultDecimals(int resultDecimals) {
this.resultDecimals = resultDecimals;
@@ -2,8 +2,6 @@ package com.sap.sse.datamining.impl.components.aggregators;
import java.util.Collection;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import com.sap.sse.datamining.components.AdditionalResultDataBuilder;
import com.sap.sse.datamining.components.Processor;
@@ -15,7 +13,7 @@ public abstract class AbstractParallelAggregationProcessor<InputType, Aggregated
extends AbstractParallelProcessor<InputType, AggregatedType> {
private final String aggregationNameMessageKey;
private final Lock lock;
private final Object monitor;
public AbstractParallelAggregationProcessor(Class<InputType> inputType,
Class<AggregatedType> resultType,
@@ -24,7 +22,7 @@ public abstract class AbstractParallelAggregationProcessor<InputType, Aggregated
String aggregationNameMessageKey) {
super(inputType, resultType, executor, resultReceivers);
this.aggregationNameMessageKey = aggregationNameMessageKey;
lock = new ReentrantLock();
monitor = new Object();
}
@Override
@@ -32,11 +30,8 @@ public abstract class AbstractParallelAggregationProcessor<InputType, Aggregated
return new AbstractProcessorInstruction<AggregatedType>(this, ProcessorInstructionPriority.Aggregation) {
@Override
public AggregatedType computeResult() {
lock.lock();
try {
synchronized (monitor) {
handleElement(element);
} finally {
lock.unlock();
}
return AbstractParallelAggregationProcessor.super.createInvalidResult();
}
@@ -5,7 +5,6 @@ import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import com.sap.sse.datamining.annotations.data.Unit;
import com.sap.sse.datamining.components.AdditionalResultDataBuilder;
import com.sap.sse.datamining.components.AggregationProcessorDefinition;
import com.sap.sse.datamining.components.Processor;
@@ -49,7 +48,6 @@ public class ParallelGroupedDataCountAggregationProcessor
@Override
protected void setAdditionalData(AdditionalResultDataBuilder additionalDataBuilder) {
super.setAdditionalData(additionalDataBuilder);
additionalDataBuilder.setResultUnit(Unit.None);
additionalDataBuilder.setResultDecimals(0);
}
@@ -14,6 +14,23 @@ import com.sap.sse.datamining.shared.GroupKey;
public class ParallelGroupedNumberDataAverageAggregationProcessor
extends AbstractParallelGroupedDataStoringAggregationProcessor<Number, Number> {
private static class IntHolder {
public int value;
public IntHolder(int value) {
super();
this.value = value;
}
}
private static class DoubleHolder {
public double value;
public DoubleHolder(double value) {
super();
this.value = value;
}
}
private static final AggregationProcessorDefinition<Number, Number> DEFINITION =
new SimpleAggregationProcessorDefinition<>(Number.class, Number.class, "Average", ParallelGroupedNumberDataAverageAggregationProcessor.class);
@@ -22,38 +39,44 @@ public class ParallelGroupedNumberDataAverageAggregationProcessor
return DEFINITION;
}
private final ParallelGroupedNumberDataSumAggregationProcessor sumAggregationProcessor;
private final Map<GroupKey, Integer> elementAmountPerKey;
private final Map<GroupKey, DoubleHolder> sumPerKey;
private final Map<GroupKey, IntHolder> elementAmountPerKey;
public ParallelGroupedNumberDataAverageAggregationProcessor(ExecutorService executor,
Collection<Processor<Map<GroupKey, Number>, ?>> resultReceivers) {
super(executor, resultReceivers, "Average");
elementAmountPerKey = new HashMap<>();
sumAggregationProcessor = new ParallelGroupedNumberDataSumAggregationProcessor(executor, resultReceivers);
sumPerKey = new HashMap<>();
}
@Override
protected void storeElement(GroupedDataEntry<Number> element) {
incrementElementAmount(element);
sumAggregationProcessor.handleElement(element);
DoubleHolder aggregate = sumPerKey.get(element.getKey());
if (aggregate == null) {
aggregate = new DoubleHolder(element.getDataEntry().doubleValue());
sumPerKey.put(element.getKey(), aggregate);
} else {
aggregate.value += element.getDataEntry().doubleValue();
}
}
private void incrementElementAmount(GroupedDataEntry<Number> element) {
GroupKey key = element.getKey();
if (!elementAmountPerKey.containsKey(key)) {
elementAmountPerKey.put(key, 0);
IntHolder currentAmount = elementAmountPerKey.get(key);
if (currentAmount == null) {
elementAmountPerKey.put(key, new IntHolder(1));
} else {
currentAmount.value++;
}
Integer currentAmount = elementAmountPerKey.get(key);
elementAmountPerKey.put(key, currentAmount + 1);
}
@Override
protected Map<GroupKey, Number> aggregateResult() {
Map<GroupKey, Number> result = new HashMap<>();
Map<GroupKey, Number> sumAggregation = sumAggregationProcessor.getResult();
for (Entry<GroupKey, Number> sumAggregationEntry : sumAggregation.entrySet()) {
for (Entry<GroupKey, DoubleHolder> sumAggregationEntry : sumPerKey.entrySet()) {
GroupKey key = sumAggregationEntry.getKey();
result.put(key, sumAggregationEntry.getValue().doubleValue() / elementAmountPerKey.get(key).doubleValue());
result.put(key, sumAggregationEntry.getValue().value / elementAmountPerKey.get(key).value);
}
return result;
}
@@ -1,17 +1,14 @@
package com.sap.sse.datamining.impl.functions;
import com.sap.sse.datamining.annotations.data.Unit;
public class AdditionalMethodWrappingFunctionData {
private final String messageKey;
private final Unit resultUnit;
private final int resultDecimals;
private final int ordinal;
public AdditionalMethodWrappingFunctionData(String messageKey, Unit resultUnit, int resultValueDecimals, int ordinal) {
public AdditionalMethodWrappingFunctionData(String messageKey, int resultValueDecimals, int ordinal) {
this.messageKey = messageKey;
this.resultUnit = resultUnit;
this.resultDecimals = resultValueDecimals;
this.ordinal = ordinal;
}
@@ -20,10 +17,6 @@ public class AdditionalMethodWrappingFunctionData {
return messageKey;
}
public Unit getResultUnit() {
return resultUnit;
}
public int getResultDecimals() {
return resultDecimals;
}
@@ -5,7 +5,6 @@ import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import com.sap.sse.datamining.annotations.data.Unit;
import com.sap.sse.datamining.functions.Function;
import com.sap.sse.datamining.functions.ParameterProvider;
import com.sap.sse.i18n.ResourceBundleStringMessages;
@@ -170,14 +169,6 @@ public class ConcatenatingCompoundFunction<ReturnType> extends AbstractFunction<
return typedResult;
}
/**
* @return the {@link Unit result Unit} of the last function.
*/
@Override
public Unit getResultUnit() {
return getLastFunction().getResultUnit();
}
/**
* @return the result decimals of the last function.
*/
@@ -9,7 +9,6 @@ import java.util.logging.Level;
import com.sap.sse.datamining.annotations.Connector;
import com.sap.sse.datamining.annotations.Dimension;
import com.sap.sse.datamining.annotations.Statistic;
import com.sap.sse.datamining.annotations.data.Unit;
import com.sap.sse.datamining.functions.ParameterProvider;
import com.sap.sse.i18n.ResourceBundleStringMessages;
@@ -44,21 +43,21 @@ public class MethodWrappingFunction<ReturnType> extends AbstractFunction<ReturnT
}
private void initializeAdditionalData() {
additionalData = new AdditionalMethodWrappingFunctionData("", Unit.None, 0, Integer.MAX_VALUE);
additionalData = new AdditionalMethodWrappingFunctionData("", 0, Integer.MAX_VALUE);
if (method.getAnnotation(Dimension.class) != null) {
Dimension dimensionData = method.getAnnotation(Dimension.class);
additionalData = new AdditionalMethodWrappingFunctionData(dimensionData.messageKey(), Unit.None, 0, dimensionData.ordinal());
additionalData = new AdditionalMethodWrappingFunctionData(dimensionData.messageKey(), 0, dimensionData.ordinal());
}
if (method.getAnnotation(Statistic.class) != null) {
Statistic statisticData = method.getAnnotation(Statistic.class);
additionalData = new AdditionalMethodWrappingFunctionData(statisticData.messageKey(), statisticData.resultUnit(), statisticData.resultDecimals(), statisticData.ordinal());
additionalData = new AdditionalMethodWrappingFunctionData(statisticData.messageKey(), statisticData.resultDecimals(), statisticData.ordinal());
}
if (method.getAnnotation(Connector.class) != null) {
Connector connectorData = method.getAnnotation(Connector.class);
additionalData = new AdditionalMethodWrappingFunctionData(connectorData.messageKey(), Unit.None, 0, connectorData.ordinal());
additionalData = new AdditionalMethodWrappingFunctionData(connectorData.messageKey(), 0, connectorData.ordinal());
}
}
@@ -99,11 +98,6 @@ public class MethodWrappingFunction<ReturnType> extends AbstractFunction<ReturnT
return null;
}
@Override
public Unit getResultUnit() {
return additionalData.getResultUnit();
}
@Override
public int getResultDecimals() {
return additionalData.getResultDecimals();
@@ -124,27 +118,16 @@ public class MethodWrappingFunction<ReturnType> extends AbstractFunction<ReturnT
if (!isLocalizable()) {
return getSimpleName();
}
String localizedName = "";
if (!additionalData.getMessageKey().isEmpty()) {
localizedName = stringMessages.get(locale, additionalData.getMessageKey());
}
if (hasUnit()) {
String unitSignifier = stringMessages.get(locale, getResultUnit().toString());
localizedName = stringMessages.get(locale, "SignifierInUnit", localizedName, unitSignifier);
}
return localizedName;
}
@Override
public boolean isLocalizable() {
return additionalData != null && (!additionalData.getMessageKey().isEmpty() || hasUnit());
}
private boolean hasUnit() {
return getResultUnit() != null && getResultUnit() != Unit.None;
return additionalData != null && (!additionalData.getMessageKey().isEmpty());
}
@Override