From 83c9409cd3b3299ba93d01fcee24e66ea58f4989 Mon Sep 17 00:00:00 2001 From: fmittag Date: Tue, 22 Nov 2011 16:12:53 +0100 Subject: [PATCH 01/11] fixed two minor problems with css and dateformat --- .../gwt/ui/client/TrackedEventsComposite.java | 39 ++++++++++++++----- .../war/AdminConsole.css | 6 ++- 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TrackedEventsComposite.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TrackedEventsComposite.java index 41d5f529002..dca04100eba 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TrackedEventsComposite.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TrackedEventsComposite.java @@ -1,5 +1,6 @@ package com.sap.sailing.gwt.ui.client; +import java.text.DateFormat; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -35,12 +36,16 @@ public class TrackedEventsComposite extends FormPanel implements EventDisplayer, private CellTable> raceTable; - private ListBox regattaComboBox = null; + private ListBox regattasComboBox = null; + + private ListBox eventsComboBox = null; private ListDataProvider> raceList; private VerticalPanel panel; - + + private final DateFormat df = DateFormat.getDateTimeInstance(); + public TrackedEventsComposite(StringConstants stringConstants, boolean multiSelection) { this.multiSelection = multiSelection; this.raceSelectionChangeListeners = new HashSet(); @@ -115,12 +120,19 @@ public class TrackedEventsComposite extends FormPanel implements EventDisplayer, if(raceTable == null) { panel = new VerticalPanel(); - - regattaComboBox = new ListBox(); - regattaComboBox.addItem("All Regattas"); - - panel.add(regattaComboBox); +/* + HorizontalPanel regattaFilterPanel = new HorizontalPanel(); + panel.add(regattaFilterPanel); + Label regattaFilterLabel = new Label("Filter by regatta: "); + regattaFilterLabel.setWordWrap(false); + regattaFilterPanel.add(regattaFilterLabel); + + regattasComboBox = new ListBox(); + regattasComboBox.addItem("All Regattas"); + + regattaFilterPanel.add(regattasComboBox); +*/ AdminConsoleTableResources tableRes = GWT.create(AdminConsoleTableResources.class); raceTable = new CellTable>(/* pageSize */ 200, tableRes); @@ -131,6 +143,13 @@ public class TrackedEventsComposite extends FormPanel implements EventDisplayer, } }; + TextColumn> regattaNameColumn = new TextColumn>() { + @Override + public String getValue(Triple object) { + return object.getB().boatClass.name; + } + }; + TextColumn> raceNameColumn = new TextColumn>() { @Override public String getValue(Triple object) { @@ -141,8 +160,9 @@ public class TrackedEventsComposite extends FormPanel implements EventDisplayer, TextColumn> raceStartColumn = new TextColumn>() { @Override public String getValue(Triple object) { - if(object.getC().startOfRace != null) - return object.getC().startOfRace.toString(); + if(object.getC().startOfRace != null) { + return df.format(object.getC().startOfRace); + } return ""; } @@ -159,6 +179,7 @@ public class TrackedEventsComposite extends FormPanel implements EventDisplayer, }; raceTable.addColumn(eventNameColumn, "Event"); + raceTable.addColumn(regattaNameColumn, "Regatta"); raceTable.addColumn(raceNameColumn, "Race"); raceTable.addColumn(raceStartColumn, "Start time"); raceTable.addColumn(raceTrackedColumn, "Tracked"); diff --git a/java/com.sap.sailing.gwt.ui/war/AdminConsole.css b/java/com.sap.sailing.gwt.ui/war/AdminConsole.css index bbb53db62de..ee54900065a 100644 --- a/java/com.sap.sailing.gwt.ui/war/AdminConsole.css +++ b/java/com.sap.sailing.gwt.ui/war/AdminConsole.css @@ -11,4 +11,8 @@ .paddedPanel { padding: 10px; -} \ No newline at end of file +} + +.linkNoBorder { + border: none; +} From 25ac5e52062a312dba0629193f20c8fd40aa1642 Mon Sep 17 00:00:00 2001 From: fmittag Date: Tue, 22 Nov 2011 16:21:48 +0100 Subject: [PATCH 02/11] added default css styles from the leaderboard.css as default --- .../war/AdminConsole.css | 135 +++++++++++++++++- 1 file changed, 131 insertions(+), 4 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/war/AdminConsole.css b/java/com.sap.sailing.gwt.ui/war/AdminConsole.css index ee54900065a..c34f6cffdc8 100644 --- a/java/com.sap.sailing.gwt.ui/war/AdminConsole.css +++ b/java/com.sap.sailing.gwt.ui/war/AdminConsole.css @@ -5,14 +5,141 @@ font-size: 12px; } -.bold { - font-weight: bold; +/** Example rules used by the template application (remove for your app) */ +h1 { + font-size: 2em; + font-weight: bold; + color: #777777; + margin: 40px 0px 70px; + text-align: center; } -.paddedPanel { - padding: 10px; +.sendButton { + display: block; + font-size: 16pt; +} + +/** Most GWT widgets already have a style name defined */ +.gwt-DialogBox { + width: 400px; +} + +.dialogVPanel { + margin: 5px; +} + +.serverResponseLabelError { + color: red; +} + +/** Set ids using widget.getElement().setId("idOfElement") */ +#closeButton { + margin: 15px 6px 6px; +} + +.gwt-TabPanelBottom { + height: 100%; +} + +.errorLabel { + color: #FF0000; } .linkNoBorder { border: none; } + +.refreshLink { + border: none; + position: relative; + vertical-align: middle; +} + +.valignMiddle { + position: relative; + vertical-align: middle; +} + +.boldLabel { + font-size: 14px; + font-weight: bold; +} + +.boldAnchor { + font-weight: bold; + vertical-align: middle; +} + +.gwt-ListBox { + font-size: 12px; +} + +.legColumnHeader { + background-color: #FFFFFF; + padding: 0 0 0 0; +} + +.dialogMessageLabel { + font-weight: bold; +} + +.gwt-DialogBox .Caption { + background: none repeat scroll 0 0 #e5e5e5; +} + +.gwt-DialogBox .dialogTopLeft { + background: none repeat scroll 0 0 #e5e5e5; +} + +.gwt-DialogBox .dialogTopRight { + background: none repeat scroll 0 0 #e5e5e5; +} + +.gwt-DialogBox .dialogMiddleLeft { + background: none repeat scroll 0 0 #e5e5e5; +} + +.gwt-DialogBox .dialogMiddleRight { + background: none repeat scroll 0 0 #e5e5e5; +} + +.gwt-DialogBox .dialogBottomCenter { + background: none repeat scroll 0 0 #e5e5e5; +} + +.gwt-DialogBox .dialogBottomLeft { + background: none repeat scroll 0 0 #e5e5e5; +} + +.gwt-DialogBox .dialogBottomRight { + background: none repeat scroll 0 0 #e5e5e5; +} + +.gwt-Button { + background-color: #e2e2e2; + border-color: #a3a3a3 !important; +} + +.gwt-TextBox { + font-family: Arial !important; + font-size: 12px !important; +} + +select { + font-family: Arial !important; + font-size: 12px !important; +} + +button { + font-family: Arial !important; + font-size: 12px !important; +} + +.leftPaddedPanel { + padding-left: 50px; + padding-right: 50px; +} + +.paddedPanel { + padding: 10px; +} From 7267c35a24e239bac6c0cac210d5204f564b007b Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Tue, 22 Nov 2011 16:29:56 +0100 Subject: [PATCH 03/11] made robust against missing canSendRequest in DB; added logging for getLeaderboardByName handling time; remove race from default leaderboard if tracking of single race was stopped --- .../persistence/impl/SwissTimingAdapterPersistenceImpl.java | 3 ++- .../com/sap/sailing/gwt/ui/server/SailingServiceImpl.java | 6 ++++++ .../src/com/sap/sailing/server/RacingEventServiceImpl.java | 5 +++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/java/com.sap.sailing.domain.swisstimingadapter.persistence/src/com/sap/sailing/domain/swisstimingadapter/persistence/impl/SwissTimingAdapterPersistenceImpl.java b/java/com.sap.sailing.domain.swisstimingadapter.persistence/src/com/sap/sailing/domain/swisstimingadapter/persistence/impl/SwissTimingAdapterPersistenceImpl.java index 973caa87e18..1e0abc56295 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter.persistence/src/com/sap/sailing/domain/swisstimingadapter/persistence/impl/SwissTimingAdapterPersistenceImpl.java +++ b/java/com.sap.sailing.domain.swisstimingadapter.persistence/src/com/sap/sailing/domain/swisstimingadapter/persistence/impl/SwissTimingAdapterPersistenceImpl.java @@ -85,10 +85,11 @@ public class SwissTimingAdapterPersistenceImpl implements SwissTimingAdapterPers } private SwissTimingConfiguration loadSwissTimingConfiguration(DBObject object) { + Boolean canSendRequests = (Boolean) object.get(FieldNames.ST_CONFIG_CAN_SEND_REQUESTS.name()); return swissTimingFactory.createSwissTimingConfiguration((String) object.get(FieldNames.ST_CONFIG_NAME.name()), (String) object.get(FieldNames.ST_CONFIG_HOSTNAME.name()), (Integer) object.get(FieldNames.ST_CONFIG_PORT.name()), - (Boolean) object.get(FieldNames.ST_CONFIG_CAN_SEND_REQUESTS.name())); + canSendRequests==null?false:canSendRequests); } @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java index 8e8e86a98ab..b8fc6273247 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java @@ -18,6 +18,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.logging.Logger; import org.osgi.framework.BundleContext; import org.osgi.util.tracker.ServiceTracker; @@ -97,6 +98,8 @@ import com.sap.sailing.util.CountryCode; * The server side implementation of the RPC service. */ public class SailingServiceImpl extends RemoteServiceServlet implements SailingService { + private static final Logger logger = Logger.getLogger(SailingServiceImpl.class.getName()); + private static final long serialVersionUID = 9031688830194537489L; private static final long TIMEOUT_FOR_RECEIVING_RACE_DEFINITION_IN_MILLISECONDS = 60000; @@ -136,6 +139,7 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS public LeaderboardDAO getLeaderboardByName(String leaderboardName, Date date, Collection namesOfRacesForWhichToLoadLegDetails) throws Exception { + long startOfRequestHandling = System.currentTimeMillis(); LeaderboardDAO result = null; Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); if (leaderboard != null) { @@ -173,6 +177,8 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS } } } + logger.fine("getLeaderboardByName("+leaderboardName+", "+date+", "+namesOfRacesForWhichToLoadLegDetails+") took "+ + (System.currentTimeMillis()-startOfRequestHandling)+"ms"); return result; } diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/RacingEventServiceImpl.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/RacingEventServiceImpl.java index 66c9bc61b66..3f656dec2bd 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/RacingEventServiceImpl.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/RacingEventServiceImpl.java @@ -417,6 +417,11 @@ public class RacingEventServiceImpl implements RacingEventService { raceTracker.stop(); // this also removes the TrackedRace from trackedEvent trackerIter.remove(); raceTrackersByID.remove(raceTracker.getID()); + for (RaceDefinition trackerRace : raceTracker.getRaces()) { + // remove from default leaderboard + Leaderboard defaultLeaderboard = getLeaderboardByName(DEFAULT_LEADERBOARD_NAME); + defaultLeaderboard.removeRaceColumn(trackerRace.getName()); + } } } } else { From 0972a2c1b269d51e76b81e63b6cb01fb2a65e44e Mon Sep 17 00:00:00 2001 From: fmittag Date: Tue, 22 Nov 2011 17:03:43 +0100 Subject: [PATCH 04/11] some css adjustments --- .../SwissTimingEventManagementPanel.java | 47 +++++++++++-------- .../gwt/ui/client/TrackedEventsComposite.java | 15 ++++-- .../war/AdminConsole.css | 1 + 3 files changed, 39 insertions(+), 24 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SwissTimingEventManagementPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SwissTimingEventManagementPanel.java index ab50f5ecf12..06102709ce7 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SwissTimingEventManagementPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SwissTimingEventManagementPanel.java @@ -21,6 +21,7 @@ import com.google.gwt.user.client.ui.CaptionPanel; import com.google.gwt.user.client.ui.CheckBox; import com.google.gwt.user.client.ui.FormPanel; import com.google.gwt.user.client.ui.Grid; +import com.google.gwt.user.client.ui.HasVerticalAlignment; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.IntegerBox; import com.google.gwt.user.client.ui.Label; @@ -72,7 +73,7 @@ public class SwissTimingEventManagementPanel extends FormPanel implements EventD VerticalPanel mainPanel = new VerticalPanel(); this.setWidget(mainPanel); - mainPanel.setSize("100%", "100%"); + mainPanel.setWidth("100%"); CaptionPanel captionPanelConnections = new CaptionPanel("Connections"); mainPanel.add(captionPanelConnections); @@ -222,23 +223,14 @@ public class SwissTimingEventManagementPanel extends FormPanel implements EventD trackedEventsComposite = new TrackedEventsComposite(stringConstants, /* multiselection */ true); trackedRacesPanel.add(trackedEventsComposite); + + HorizontalPanel trackedRacesButtonPanel = new HorizontalPanel(); + + trackedRacesButtonPanel.setSpacing(10); + trackedRacesPanel.add(trackedRacesButtonPanel); - HorizontalPanel buttonPanel = new HorizontalPanel(); - racesPanel.add(buttonPanel); - - Button btnTrack = new Button("Start tracking"); -// Button btnTrack = new Button(stringConstants.btnTrack()); - buttonPanel.add(btnTrack); - buttonPanel.setSpacing(10); - btnTrack.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - trackSelectedRaces(trackWindCheckbox.getValue(), declinationCheckbox.getValue()); - } - }); - Button btnRemove = new Button("Stop tracking"); -// Button btnRemove = new Button(stringConstants.remove()); +// Button btnRemove = new Button(stringConstants.remove()); btnRemove.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent click) { @@ -249,9 +241,8 @@ public class SwissTimingEventManagementPanel extends FormPanel implements EventD } } }); - btnRemove.setWidth("100%"); - buttonPanel.add(btnRemove); - + trackedRacesButtonPanel.add(btnRemove); + Button btnRefresh = new Button(stringConstants.refresh()); btnRefresh.addClickHandler(new ClickHandler() { @Override @@ -259,7 +250,23 @@ public class SwissTimingEventManagementPanel extends FormPanel implements EventD SwissTimingEventManagementPanel.this.eventRefresher.fillEvents(); } }); - buttonPanel.add(btnRefresh); + trackedRacesButtonPanel.add(btnRefresh); + + + HorizontalPanel racesButtonPanel = new HorizontalPanel(); + racesPanel.add(racesButtonPanel); + + Button btnTrack = new Button("Start tracking"); + +// Button btnTrack = new Button(stringConstants.btnTrack()); + racesButtonPanel.add(btnTrack); + racesButtonPanel.setSpacing(10); + btnTrack.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + trackSelectedRaces(trackWindCheckbox.getValue(), declinationCheckbox.getValue()); + } + }); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TrackedEventsComposite.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TrackedEventsComposite.java index dca04100eba..c38bcb464cf 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TrackedEventsComposite.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TrackedEventsComposite.java @@ -1,12 +1,12 @@ package com.sap.sailing.gwt.ui.client; -import java.text.DateFormat; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import com.google.gwt.core.client.GWT; +import com.google.gwt.text.client.DateTimeFormatRenderer; import com.google.gwt.user.cellview.client.CellTable; import com.google.gwt.user.cellview.client.TextColumn; import com.google.gwt.user.client.ui.FormPanel; @@ -44,8 +44,8 @@ public class TrackedEventsComposite extends FormPanel implements EventDisplayer, private VerticalPanel panel; - private final DateFormat df = DateFormat.getDateTimeInstance(); - + private DateTimeFormatRenderer dateFormatter = new DateTimeFormatRenderer(); + public TrackedEventsComposite(StringConstants stringConstants, boolean multiSelection) { this.multiSelection = multiSelection; this.raceSelectionChangeListeners = new HashSet(); @@ -161,7 +161,7 @@ public class TrackedEventsComposite extends FormPanel implements EventDisplayer, @Override public String getValue(Triple object) { if(object.getC().startOfRace != null) { - return df.format(object.getC().startOfRace); + return dateFormatter.render(object.getC().startOfRace); } return ""; @@ -199,6 +199,13 @@ public class TrackedEventsComposite extends FormPanel implements EventDisplayer, }); setWidget(panel); } + + + if(events.size() == 0) + raceTable.setVisible(false); + else + raceTable.setVisible(true); + raceList.getList().clear(); // Handler columnSortHandler = getRaceTableColumnSortHandler(raceList.getList(), raceNameColumn, raceStartTrackingColumn); diff --git a/java/com.sap.sailing.gwt.ui/war/AdminConsole.css b/java/com.sap.sailing.gwt.ui/war/AdminConsole.css index c34f6cffdc8..cef1fde1d6e 100644 --- a/java/com.sap.sailing.gwt.ui/war/AdminConsole.css +++ b/java/com.sap.sailing.gwt.ui/war/AdminConsole.css @@ -118,6 +118,7 @@ h1 { .gwt-Button { background-color: #e2e2e2; border-color: #a3a3a3 !important; + white-space: nowrap; } .gwt-TextBox { From 8260d887947fcc840c77784111dca70cdb5721d3 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Tue, 22 Nov 2011 17:20:05 +0100 Subject: [PATCH 05/11] removed raw message store for SwissTiming; added StressTest button for leaderboard logic --- .../SwissTimingAdapterPersistence.java | 2 - .../persistence/impl/CollectionNames.java | 2 +- .../SwissTimingAdapterPersistenceImpl.java | 15 ----- .../SwissTimingFactory.java | 10 ++- .../gwt/ui/client/LeaderboardConfigPanel.java | 63 +++++++++++++------ .../sailing/gwt/ui/client/SailingService.java | 2 + .../gwt/ui/client/SailingServiceAsync.java | 7 +++ .../gwt/ui/client/StringConstants.java | 1 + .../gwt/ui/client/StringConstants.properties | 1 + .../ui/client/StringConstants_de.properties | 3 +- .../gwt/ui/server/SailingServiceImpl.java | 23 ++++++- 11 files changed, 87 insertions(+), 42 deletions(-) diff --git a/java/com.sap.sailing.domain.swisstimingadapter.persistence/src/com/sap/sailing/domain/swisstimingadapter/persistence/SwissTimingAdapterPersistence.java b/java/com.sap.sailing.domain.swisstimingadapter.persistence/src/com/sap/sailing/domain/swisstimingadapter/persistence/SwissTimingAdapterPersistence.java index 3e2c932e26a..7b50a0feb1c 100644 --- a/java/com.sap.sailing.domain.swisstimingadapter.persistence/src/com/sap/sailing/domain/swisstimingadapter/persistence/SwissTimingAdapterPersistence.java +++ b/java/com.sap.sailing.domain.swisstimingadapter.persistence/src/com/sap/sailing/domain/swisstimingadapter/persistence/SwissTimingAdapterPersistence.java @@ -38,8 +38,6 @@ public interface SwissTimingAdapterPersistence extends RaceSpecificMessageLoader void storeSwissTimingConfiguration(SwissTimingConfiguration swissTimingConfiguration); - void storeRawSailMasterMessage(SailMasterMessage message); - void storeSailMasterMessage(SailMasterMessage message); void storeRace(Race race); diff --git a/java/com.sap.sailing.domain.swisstimingadapter.persistence/src/com/sap/sailing/domain/swisstimingadapter/persistence/impl/CollectionNames.java b/java/com.sap.sailing.domain.swisstimingadapter.persistence/src/com/sap/sailing/domain/swisstimingadapter/persistence/impl/CollectionNames.java index 3643e8dd54c..23f5b6fb07f 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter.persistence/src/com/sap/sailing/domain/swisstimingadapter/persistence/impl/CollectionNames.java +++ b/java/com.sap.sailing.domain.swisstimingadapter.persistence/src/com/sap/sailing/domain/swisstimingadapter/persistence/impl/CollectionNames.java @@ -1,6 +1,6 @@ package com.sap.sailing.domain.swisstimingadapter.persistence.impl; public enum CollectionNames { - SWISSTIMING_CONFIGURATIONS, LAST_MESSAGE_COUNT, RAW_MESSAGES, + SWISSTIMING_CONFIGURATIONS, LAST_MESSAGE_COUNT, RACES_MASTERDATA, RACES_MESSAGES, COMMAND_MESSAGES } diff --git a/java/com.sap.sailing.domain.swisstimingadapter.persistence/src/com/sap/sailing/domain/swisstimingadapter/persistence/impl/SwissTimingAdapterPersistenceImpl.java b/java/com.sap.sailing.domain.swisstimingadapter.persistence/src/com/sap/sailing/domain/swisstimingadapter/persistence/impl/SwissTimingAdapterPersistenceImpl.java index 1e0abc56295..ca93940d540 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter.persistence/src/com/sap/sailing/domain/swisstimingadapter/persistence/impl/SwissTimingAdapterPersistenceImpl.java +++ b/java/com.sap.sailing.domain.swisstimingadapter.persistence/src/com/sap/sailing/domain/swisstimingadapter/persistence/impl/SwissTimingAdapterPersistenceImpl.java @@ -40,9 +40,6 @@ public class SwissTimingAdapterPersistenceImpl implements SwissTimingAdapterPers } private void init() { - DBCollection rawMessages = database.getCollection(CollectionNames.RAW_MESSAGES.name()); - rawMessages.ensureIndex(new BasicDBObject().append(FieldNames.MESSAGE_SEQUENCE_NUMBER.name(), 1)); - // ensure the required indexes for the collection of race specific messages DBCollection racesMessageCollection = database.getCollection(CollectionNames.RACES_MESSAGES.name()); @@ -184,13 +181,6 @@ public class SwissTimingAdapterPersistenceImpl implements SwissTimingAdapterPers stConfigCollection.insert(result); } - @Override - public void storeRawSailMasterMessage(SailMasterMessage message) { - DBCollection rawMessageCollection = database.getCollection(CollectionNames.RAW_MESSAGES.name()); - rawMessageCollection.insert(new BasicDBObject().append(FieldNames.MESSAGE_SEQUENCE_NUMBER.name(), message.getSequenceNumber()). - append(FieldNames.MESSAGE_CONTENT.name(), message.getMessage())); - } - @Override public void storeSailMasterMessage(SailMasterMessage message) { // Attention: this method is very time critical as we will receive thousands of messages in a short time @@ -264,13 +254,8 @@ public class SwissTimingAdapterPersistenceImpl implements SwissTimingAdapterPers @Override public void dropAllMessageData() { - - DBCollection rawMessageCollection = database.getCollection(CollectionNames.RAW_MESSAGES.name()); - rawMessageCollection.drop(); - DBCollection racesMessageCollection = database.getCollection(CollectionNames.RACES_MESSAGES.name()); racesMessageCollection.drop(); - DBCollection cmdMessageCollection = database.getCollection(CollectionNames.COMMAND_MESSAGES.name()); cmdMessageCollection.drop(); } diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/SwissTimingFactory.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/SwissTimingFactory.java index fc6ac98eff6..7be0153817b 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/SwissTimingFactory.java +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/SwissTimingFactory.java @@ -34,10 +34,14 @@ public interface SwissTimingFactory { * {@link SailMasterConnector#trackRace} and {@link SailMasterConnector#stopTrackingRace} operations. * {@link MessageType#isRaceSpecific() Race-specific messages} for other races are ignored and not forwarded to any * listener. - * @param canSendRequests TODO + * + * @param canSendRequests + * tells whether the hostname/port combination is able to receive and process SailMaster request messages; + * if false, only events are sent by the host to which the connector connects. */ - SailMasterConnector getOrCreateSailMasterConnector(String hostname, int port, RaceSpecificMessageLoader messageLoader, boolean canSendRequests) throws InterruptedException; - + SailMasterConnector getOrCreateSailMasterConnector(String hostname, int port, + RaceSpecificMessageLoader messageLoader, boolean canSendRequests) throws InterruptedException; + SailMasterTransceiver createSailMasterTransceiver(); SwissTimingConfiguration createSwissTimingConfiguration(String name, String hostname, int port, boolean canSendRequests); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/LeaderboardConfigPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/LeaderboardConfigPanel.java index 07812bf65c5..ec77561ed15 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/LeaderboardConfigPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/LeaderboardConfigPanel.java @@ -151,7 +151,15 @@ public class LeaderboardConfigPanel extends FormPanel implements EventDisplayer, removeSelectedLeaderboard(); } }); - + Button stressTestButton = new Button(stringConstants.stressTest()); + verticalPanel.add(stressTestButton); + stressTestButton.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + performStressTestForSelectedLeaderboard(); + } + }); + // ------------ specific to selected leaderboard ---------------- Label lblRaceNamesIn = new Label(stringConstants.columnNamesInSelectedLeaderboard()); grid.setWidget(2, 0, lblRaceNamesIn); @@ -245,6 +253,25 @@ public class LeaderboardConfigPanel extends FormPanel implements EventDisplayer, leaderboardRaceColumnSelectionChanged(); } + private void performStressTestForSelectedLeaderboard() { + final int selectedIndex = leaderboardsListBox.getSelectedIndex(); + if (selectedIndex >= 0) { + final String leaderboardName = leaderboardsListBox.getItemText(selectedIndex); + sailingService.stressTestLeaderboardByName(leaderboardName, 100, new AsyncCallback() { + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError("Error during leaderboard stress test for " + leaderboardName + ": " + + caught.getMessage()); + } + + @Override + public void onSuccess(Void result) { + errorReporter.reportError("Stress test for " + leaderboardName + " finished successfully "); + } + }); + } + } + private void unlinkSelectedRaceColumnFromTrackedRace() { final String selectedRaceColumnName = getSelectedRaceColumnName(); final String selectedLeaderboardName = getSelectedLeaderboardName(); @@ -719,10 +746,10 @@ public class LeaderboardConfigPanel extends FormPanel implements EventDisplayer, selectedRace.getA().name, selectedRace.getC().name, new AsyncCallback() { @Override public void onFailure(Throwable t) { - errorReporter.reportError("Error trying to link tracked race "+selectedRace.getC().name+ - " of event "+selectedRace.getA().name+" to race column named "+ - getSelectedRaceColumnName()+" of leaderboard "+getSelectedLeaderboardName()+": "+ - t.getMessage()); + errorReporter.reportError("Error trying to link tracked race " + selectedRace.getC().name + + " of event " + selectedRace.getA().name + " to race column named " + + getSelectedRaceColumnName() + " of leaderboard " + getSelectedLeaderboardName() + + ": " + t.getMessage()); raceTree.clearSelection(); } @@ -732,20 +759,20 @@ public class LeaderboardConfigPanel extends FormPanel implements EventDisplayer, } }); } - - private void changeIsMedalRace(final boolean isMedalRace){ - sailingService.updateIsMedalRace(getSelectedLeaderboardName(), getSelectedRaceColumnName(), isMedalRace, new AsyncCallback() { - @Override - public void onFailure(Throwable caught) { - errorReporter.reportError("Error trying to change isMedalRace of "+getSelectedRaceColumnName()+": "+caught.getMessage()); - } + private void changeIsMedalRace(final boolean isMedalRace) { + sailingService.updateIsMedalRace(getSelectedLeaderboardName(), getSelectedRaceColumnName(), isMedalRace, + new AsyncCallback() { + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError("Error trying to change isMedalRace of " + + getSelectedRaceColumnName() + ": " + caught.getMessage()); + } - @Override - public void onSuccess(Void result) { - // TODO Punkte in spalte updaten. - selectedLeaderboard.setIsMedalRace(getSelectedRaceColumnName(), isMedalRace); - } - }); + @Override + public void onSuccess(Void result) { + selectedLeaderboard.setIsMedalRace(getSelectedRaceColumnName(), isMedalRace); + } + }); } } \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java index d99f0d89c77..132587bbd3f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java @@ -114,4 +114,6 @@ public interface SailingService extends RemoteService { void trackWithSwissTiming(SwissTimingRaceRecordDAO rr, String hostname, int port, boolean canSendRequests, boolean trackWind, boolean correctWindByDeclination) throws Exception; + + void stressTestLeaderboardByName(String leaderboardName, int times) throws Exception; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java index eb485eea242..38bbd86e202 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java @@ -173,4 +173,11 @@ public interface SailingServiceAsync { void trackWithSwissTiming(SwissTimingRaceRecordDAO rr, String hostname, int port, boolean canSendRequests, boolean trackWind, boolean correctWindByDeclination, AsyncCallback asyncCallback); + + /** + * Requests the computation of the {@link LeaderboardDAO} for leaderboardName times times. + * The date used for the {@link #getLeaderboardByName(String, Date, Collection, AsyncCallback)} call is iterated + * in 10ms time steps, going backwards from "now." For all races, all details are requested. + */ + void stressTestLeaderboardByName(String leaderboardName, int times, AsyncCallback callback); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringConstants.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringConstants.java index 2655a5c3230..9b09aa9af2f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringConstants.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringConstants.java @@ -112,4 +112,5 @@ public interface StringConstants extends Constants { String raceStartTimeColumn(); String showOnlySelected(); String tailLength(); + String stressTest(); } \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringConstants.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringConstants.properties index 22f8ab90ff3..7c4e7c771eb 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringConstants.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringConstants.properties @@ -107,3 +107,4 @@ port=Port raceStartTimeColumn=Race Started showOnlySelected=Show only selected tailLength=Tail length (s) +stressTest=Stress Test \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringConstants_de.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringConstants_de.properties index 4a929a9b3ed..188887c9630 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringConstants_de.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringConstants_de.properties @@ -106,4 +106,5 @@ columnMoveDown=Runter port=Port raceStartTimeColumn=Rennstart showOnlySelected=Nur ausgewählte anzeigen -tailLengt=Schweiflänge (s) +tailLength=Schweiflänge (s) +stressTest=Stresstest \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java index b8fc6273247..4bef639b2e2 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java @@ -137,6 +137,7 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS return result; } + @Override public LeaderboardDAO getLeaderboardByName(String leaderboardName, Date date, Collection namesOfRacesForWhichToLoadLegDetails) throws Exception { long startOfRequestHandling = System.currentTimeMillis(); @@ -182,6 +183,24 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS return result; } + @Override + public void stressTestLeaderboardByName(String leaderboardName, int times) throws Exception { + Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); + if (leaderboard != null) { + List raceColumnNames = new ArrayList(); + for (RaceInLeaderboard column : leaderboard.getRaceColumns()) { + raceColumnNames.add(column.getName()); + } + int i=0; + for (Date date = new Date(); i(); for (Leg leg : trackedRace.getRace().getCourse().getLegs()) { TrackedLegOfCompetitor trackedLeg = trackedRace.getTrackedLeg(competitor, leg); From 841dec7e94d9d9eb89eac1a94a356197c6ce4b5d Mon Sep 17 00:00:00 2001 From: fmittag Date: Tue, 22 Nov 2011 18:16:38 +0100 Subject: [PATCH 06/11] moved 'Stop tracking' and 'Refresh' to the new Composite View --- .../SwissTimingEventManagementPanel.java | 51 +--- .../gwt/ui/client/TrackedEventsComposite.java | 226 ++++++++++++------ 2 files changed, 151 insertions(+), 126 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SwissTimingEventManagementPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SwissTimingEventManagementPanel.java index 06102709ce7..bf707c8bc8c 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SwissTimingEventManagementPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SwissTimingEventManagementPanel.java @@ -21,7 +21,6 @@ import com.google.gwt.user.client.ui.CaptionPanel; import com.google.gwt.user.client.ui.CheckBox; import com.google.gwt.user.client.ui.FormPanel; import com.google.gwt.user.client.ui.Grid; -import com.google.gwt.user.client.ui.HasVerticalAlignment; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.IntegerBox; import com.google.gwt.user.client.ui.Label; @@ -31,11 +30,8 @@ import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.view.client.ListDataProvider; import com.google.gwt.view.client.MultiSelectionModel; import com.sap.sailing.gwt.ui.shared.EventDAO; -import com.sap.sailing.gwt.ui.shared.RaceDAO; -import com.sap.sailing.gwt.ui.shared.RegattaDAO; import com.sap.sailing.gwt.ui.shared.SwissTimingConfigurationDAO; import com.sap.sailing.gwt.ui.shared.SwissTimingRaceRecordDAO; -import com.sap.sailing.gwt.ui.shared.Triple; /** * Allows the user to start and stop tracking of events, regattas and races using the TracTrac connector. In particular, @@ -221,38 +217,10 @@ public class SwissTimingEventManagementPanel extends FormPanel implements EventD // trackedRacesTreeView = new RaceTreeView(stringConstants, /* multiselection */ true); // trackedRacesPanel.add(trackedRacesTreeView); - trackedEventsComposite = new TrackedEventsComposite(stringConstants, /* multiselection */ true); + trackedEventsComposite = new TrackedEventsComposite(sailingService, errorReporter, eventRefresher, + stringConstants, /* multiselection */ true); trackedRacesPanel.add(trackedEventsComposite); - HorizontalPanel trackedRacesButtonPanel = new HorizontalPanel(); - - trackedRacesButtonPanel.setSpacing(10); - trackedRacesPanel.add(trackedRacesButtonPanel); - - Button btnRemove = new Button("Stop tracking"); -// Button btnRemove = new Button(stringConstants.remove()); - btnRemove.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent click) { - for (Triple selection : trackedEventsComposite.getSelectedEventAndRace()) { - if (selection.getC().currentlyTracked) { - stopTrackingRace(selection.getA(), selection.getC()); - } - } - } - }); - trackedRacesButtonPanel.add(btnRemove); - - Button btnRefresh = new Button(stringConstants.refresh()); - btnRefresh.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - SwissTimingEventManagementPanel.this.eventRefresher.fillEvents(); - } - }); - trackedRacesButtonPanel.add(btnRefresh); - - HorizontalPanel racesButtonPanel = new HorizontalPanel(); racesPanel.add(racesButtonPanel); @@ -270,21 +238,6 @@ public class SwissTimingEventManagementPanel extends FormPanel implements EventD } - private void stopTrackingRace(final EventDAO event, final RaceDAO race) { - sailingService.stopTrackingRace(event.name, race.name, new AsyncCallback() { - @Override - public void onFailure(Throwable caught) { - errorReporter.reportError("Exception trying to stop tracking race " + race.name + "in event "+event.name+": " - + caught.getMessage()); - } - - @Override - public void onSuccess(Void result) { - eventRefresher.fillEvents(); - } - }); - } - private ListHandler getRaceTableColumnSortHandler(List raceRecords, Column nameColumn, Column trackingStartColumn) { ListHandler result = new ListHandler(raceRecords); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TrackedEventsComposite.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TrackedEventsComposite.java index c38bcb464cf..2ec1632f208 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TrackedEventsComposite.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TrackedEventsComposite.java @@ -6,10 +6,15 @@ import java.util.List; import java.util.Set; import com.google.gwt.core.client.GWT; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.text.client.DateTimeFormatRenderer; import com.google.gwt.user.cellview.client.CellTable; import com.google.gwt.user.cellview.client.TextColumn; +import com.google.gwt.user.client.rpc.AsyncCallback; +import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.FormPanel; +import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.ListBox; import com.google.gwt.user.client.ui.VerticalPanel; @@ -37,7 +42,6 @@ public class TrackedEventsComposite extends FormPanel implements EventDisplayer, private CellTable> raceTable; private ListBox regattasComboBox = null; - private ListBox eventsComboBox = null; private ListDataProvider> raceList; @@ -46,15 +50,128 @@ public class TrackedEventsComposite extends FormPanel implements EventDisplayer, private DateTimeFormatRenderer dateFormatter = new DateTimeFormatRenderer(); - public TrackedEventsComposite(StringConstants stringConstants, boolean multiSelection) { + private Label noTrackedRacesLabel = null; + + private final SailingServiceAsync sailingService; + private final ErrorReporter errorReporter; + private final EventRefresher eventRefresher; + + private Button btnRemove = null; + private Button btnRefresh = null; + + public TrackedEventsComposite(final SailingServiceAsync sailingService, final ErrorReporter errorReporter, final EventRefresher eventRefresher, + StringConstants stringConstants, boolean multiSelection) { + this.sailingService = sailingService; + this.errorReporter = errorReporter; + this.eventRefresher = eventRefresher; this.multiSelection = multiSelection; this.raceSelectionChangeListeners = new HashSet(); selectionModel = multiSelection ? new MultiSelectionModel>() : new SingleSelectionModel>(); - Label label = new Label("NEW TRACKED RACES VIEW: " + stringConstants.noRacesYet()); - label.setWordWrap(false); - setWidget(label); + panel = new VerticalPanel(); + setWidget(panel); + + noTrackedRacesLabel = new Label(stringConstants.noRacesYet()); + noTrackedRacesLabel.setWordWrap(false); + panel.add(noTrackedRacesLabel); + + AdminConsoleTableResources tableRes = GWT.create(AdminConsoleTableResources.class); + raceTable = new CellTable>(/* pageSize */ 200, tableRes); + + TextColumn> eventNameColumn = new TextColumn>() { + @Override + public String getValue(Triple object) { + return object.getA().name; + } + }; + + TextColumn> regattaNameColumn = new TextColumn>() { + @Override + public String getValue(Triple object) { + return object.getB().boatClass.name; + } + }; + + TextColumn> raceNameColumn = new TextColumn>() { + @Override + public String getValue(Triple object) { + return object.getC().name; + } + }; + + TextColumn> raceStartColumn = new TextColumn>() { + @Override + public String getValue(Triple object) { + if(object.getC().startOfRace != null) { + return dateFormatter.render(object.getC().startOfRace); + } + + return ""; + } + }; + + TextColumn> raceTrackedColumn = new TextColumn>() { + @Override + public String getValue(Triple object) { + if(object.getC().currentlyTracked == true) + return "tracked"; + + return ""; + } + }; + + raceTable.addColumn(eventNameColumn, "Event"); + raceTable.addColumn(regattaNameColumn, "Regatta"); + raceTable.addColumn(raceNameColumn, "Race"); + raceTable.addColumn(raceStartColumn, "Start time"); + raceTable.addColumn(raceTrackedColumn, "Tracked"); + raceTable.setWidth("300px"); + raceTable.setSelectionModel(selectionModel); + + raceTable.setVisible(false); + panel.add(raceTable); + + raceList = new ListDataProvider>(); + raceList.addDataDisplay(raceTable); + + raceTable.getSelectionModel().addSelectionChangeHandler(new Handler() { + @Override + public void onSelectionChange(SelectionChangeEvent event) { + fireRaceSelectionChanged(getSelectedEventAndRace()); + } + }); + + + + HorizontalPanel trackedRacesButtonPanel = new HorizontalPanel(); + + trackedRacesButtonPanel.setSpacing(10); + panel.add(trackedRacesButtonPanel); + + btnRemove = new Button("Stop tracking"); +// btnRemove = new Button(stringConstants.remove()); + btnRemove.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent click) { + for (Triple selection : getSelectedEventAndRace()) { + if (selection.getC().currentlyTracked) { + stopTrackingRace(selection.getA(), selection.getC()); + } + } + } + }); + trackedRacesButtonPanel.add(btnRemove); + + btnRefresh = new Button(stringConstants.refresh()); + btnRefresh.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + eventRefresher.fillEvents(); + } + }); + trackedRacesButtonPanel.add(btnRefresh); + } @Override @@ -117,9 +234,6 @@ public class TrackedEventsComposite extends FormPanel implements EventDisplayer, @Override public void fillEvents(List events) { - if(raceTable == null) - { - panel = new VerticalPanel(); /* HorizontalPanel regattaFilterPanel = new HorizontalPanel(); panel.add(regattaFilterPanel); @@ -133,79 +247,21 @@ public class TrackedEventsComposite extends FormPanel implements EventDisplayer, regattaFilterPanel.add(regattasComboBox); */ - AdminConsoleTableResources tableRes = GWT.create(AdminConsoleTableResources.class); - raceTable = new CellTable>(/* pageSize */ 200, tableRes); - - TextColumn> eventNameColumn = new TextColumn>() { - @Override - public String getValue(Triple object) { - return object.getA().name; - } - }; - - TextColumn> regattaNameColumn = new TextColumn>() { - @Override - public String getValue(Triple object) { - return object.getB().boatClass.name; - } - }; - - TextColumn> raceNameColumn = new TextColumn>() { - @Override - public String getValue(Triple object) { - return object.getC().name; - } - }; - - TextColumn> raceStartColumn = new TextColumn>() { - @Override - public String getValue(Triple object) { - if(object.getC().startOfRace != null) { - return dateFormatter.render(object.getC().startOfRace); - } - - return ""; - } - }; - - TextColumn> raceTrackedColumn = new TextColumn>() { - @Override - public String getValue(Triple object) { - if(object.getC().currentlyTracked == true) - return "tracked"; - - return ""; - } - }; - - raceTable.addColumn(eventNameColumn, "Event"); - raceTable.addColumn(regattaNameColumn, "Regatta"); - raceTable.addColumn(raceNameColumn, "Race"); - raceTable.addColumn(raceStartColumn, "Start time"); - raceTable.addColumn(raceTrackedColumn, "Tracked"); - raceTable.setWidth("300px"); - raceTable.setSelectionModel(selectionModel); - - panel.add(raceTable); - - raceList = new ListDataProvider>(); - raceList.addDataDisplay(raceTable); - - raceTable.getSelectionModel().addSelectionChangeHandler(new Handler() { - @Override - public void onSelectionChange(SelectionChangeEvent event) { - fireRaceSelectionChanged(getSelectedEventAndRace()); - } - }); - setWidget(panel); - } - if(events.size() == 0) + if(events.size() == 0) { raceTable.setVisible(false); - else + btnRemove.setVisible(false); + btnRefresh.setVisible(false); + noTrackedRacesLabel.setVisible(true); + } else { raceTable.setVisible(true); - + if(eventRefresher != null) { + btnRemove.setVisible(true); + btnRefresh.setVisible(true); + } + noTrackedRacesLabel.setVisible(false); + } raceList.getList().clear(); // Handler columnSortHandler = getRaceTableColumnSortHandler(raceList.getList(), raceNameColumn, raceStartTrackingColumn); @@ -220,4 +276,20 @@ public class TrackedEventsComposite extends FormPanel implements EventDisplayer, } } + private void stopTrackingRace(final EventDAO event, final RaceDAO race) { + sailingService.stopTrackingRace(event.name, race.name, new AsyncCallback() { + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError("Exception trying to stop tracking race " + race.name + "in event "+event.name+": " + + caught.getMessage()); + } + + @Override + public void onSuccess(Void result) { + eventRefresher.fillEvents(); + } + }); + } + + } From 33207d102d0e546fba1a3d38d56e81ce3833fe12 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Tue, 22 Nov 2011 22:19:39 +0100 Subject: [PATCH 07/11] added a failing test case for adding a fix to a GPS fix track while iterating over a subset of it --- .../sap/sailing/domain/test/TrackTest.java | 56 +++++++++++++++++-- .../domain/base/impl/AbstractBearing.java | 10 ++++ .../domain/base/impl/AbstractSpeedImpl.java | 12 ++++ .../impl/AbstractSpeedWithBearingImpl.java | 10 ++++ ...KilometersPerHourSpeedWithBearingImpl.java | 11 ++++ .../sailing/domain/tracking/DynamicTrack.java | 6 ++ .../tracking/impl/AbstractGPSFixImpl.java | 36 ++++++++++++ .../tracking/impl/CompactGPSFixImpl.java | 3 +- .../impl/CompactGPSFixMovingImpl.java | 20 +++++++ .../domain/tracking/impl/GPSFixImpl.java | 8 ++- .../tracking/impl/GPSFixMovingImpl.java | 10 ++++ .../gwt/ui/client/LeaderboardPanel.java | 3 +- 12 files changed, 176 insertions(+), 9 deletions(-) create mode 100755 java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/AbstractGPSFixImpl.java diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackTest.java index 2300ccb4f5f..74af9a7745d 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackTest.java @@ -3,10 +3,15 @@ package com.sap.sailing.domain.test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import java.lang.reflect.Field; import java.util.ArrayList; +import java.util.ConcurrentModificationException; import java.util.Iterator; import java.util.List; +import java.util.NavigableSet; +import java.util.SortedSet; import org.junit.Before; import org.junit.Test; @@ -27,35 +32,41 @@ import com.sap.sailing.domain.tracking.GPSFixMoving; import com.sap.sailing.domain.tracking.impl.DynamicGPSFixMovingTrackImpl; import com.sap.sailing.domain.tracking.impl.DynamicTrackImpl; import com.sap.sailing.domain.tracking.impl.GPSFixMovingImpl; +import com.sap.sailing.domain.tracking.impl.TrackImpl; public class TrackTest { private DynamicTrackImpl track; + private GPSFixMovingImpl gpsFix1; + private GPSFixMovingImpl gpsFix2; + private GPSFixMovingImpl gpsFix3; + private GPSFixMovingImpl gpsFix4; + private GPSFixMovingImpl gpsFix5; @Before public void setUp() throws InterruptedException { track = new DynamicGPSFixMovingTrackImpl(new BoatImpl("MyFirstBoat", new BoatClassImpl("505"), null), /* millisecondsOverWhichToAverage */ 5000); - GPSFixMovingImpl gpsFix1 = new GPSFixMovingImpl( + gpsFix1 = new GPSFixMovingImpl( new DegreePosition(1, 2), new MillisecondsTimePoint( System.currentTimeMillis()), new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(90))); waitThreeMillis(); - GPSFixMovingImpl gpsFix2 = new GPSFixMovingImpl( + gpsFix2 = new GPSFixMovingImpl( new DegreePosition(1, 3), new MillisecondsTimePoint( System.currentTimeMillis()), new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(90))); waitThreeMillis(); - GPSFixMovingImpl gpsFix3 = new GPSFixMovingImpl( + gpsFix3 = new GPSFixMovingImpl( new DegreePosition(1, 4), new MillisecondsTimePoint( System.currentTimeMillis()), new KnotSpeedWithBearingImpl(2, new DegreeBearingImpl(0))); waitThreeMillis(); - GPSFixMovingImpl gpsFix4 = new GPSFixMovingImpl( + gpsFix4 = new GPSFixMovingImpl( new DegreePosition(3, 4), new MillisecondsTimePoint( System.currentTimeMillis()), new KnotSpeedWithBearingImpl(2, new DegreeBearingImpl(0))); waitThreeMillis(); - GPSFixMovingImpl gpsFix5 = new GPSFixMovingImpl( + gpsFix5 = new GPSFixMovingImpl( new DegreePosition(5, 4), new MillisecondsTimePoint( System.currentTimeMillis()), new KnotSpeedWithBearingImpl(2, new DegreeBearingImpl(0))); track.addGPSFix(gpsFix1); @@ -65,6 +76,41 @@ public class TrackTest { track.addGPSFix(gpsFix5); } + /** + * Bug #70: modify a track while iterating over a subset of it; ensure that this doesn't cause a + * {@link ConcurrentModificationException}. + * @throws InterruptedException + * @throws IllegalAccessException + * @throws IllegalArgumentException + * @throws NoSuchFieldException + * @throws SecurityException + */ + @Test + public void testAddingWhileIteratingOverSubset() throws InterruptedException, IllegalArgumentException, + IllegalAccessException, SecurityException, NoSuchFieldException { + Field fixesField = TrackImpl.class.getDeclaredField("fixes"); + fixesField.setAccessible(true); + @SuppressWarnings("unchecked") + NavigableSet fixes = (NavigableSet) fixesField.get(track); + SortedSet subset = fixes.subSet(gpsFix2, gpsFix5); + assertEquals(3, subset.size()); + Iterator subsetIter = subset.iterator(); + // start iteration + GPSFixMoving firstOfSubset = subsetIter.next(); + assertEquals(gpsFix2, firstOfSubset); + // now add a fix: + waitThreeMillis(); + track.addGPSFix(new GPSFixMovingImpl( + new DegreePosition(6, 5), new MillisecondsTimePoint( + System.currentTimeMillis()), new KnotSpeedWithBearingImpl(2, new DegreeBearingImpl(0)))); + try { + GPSFixMoving secondOfSubset = subsetIter.next(); + assertEquals(gpsFix3, secondOfSubset); + } catch (ConcurrentModificationException e) { + fail("adding a fix interferes with iteration over subSet of track's fixes"); + } + } + /** * Used to ensure that for the test fixes there is always a time point between the two that * is different from the time points of the adjacent fixes diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractBearing.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractBearing.java index a5c1018901b..737301c4317 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractBearing.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractBearing.java @@ -47,4 +47,14 @@ public abstract class AbstractBearing implements Bearing { public String toString() { return ""+getDegrees()+"°"; } + + @Override + public int hashCode() { + return (int) (1023 ^ Double.doubleToLongBits(getDegrees())); + } + + @Override + public boolean equals(Object object) { + return object != null && object instanceof Bearing && getDegrees() == ((Bearing) object).getDegrees(); + } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractSpeedImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractSpeedImpl.java index 98802a65ed2..0fbbb6cc3cb 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractSpeedImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractSpeedImpl.java @@ -37,4 +37,16 @@ public abstract class AbstractSpeedImpl implements Speed { return ""+getKnots()+"kn"; } + @Override + public int hashCode() { + return (int) (31 * Double.doubleToLongBits(getMetersPerSecond())); + } + + @Override + public boolean equals(Object object) { + if (object == null || !(object instanceof Speed)) { + return false; + } + return getMetersPerSecond() == ((Speed) object).getMetersPerSecond(); + } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractSpeedWithBearingImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractSpeedWithBearingImpl.java index 6044814761d..7c17f28037b 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractSpeedWithBearingImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractSpeedWithBearingImpl.java @@ -27,4 +27,14 @@ public abstract class AbstractSpeedWithBearingImpl extends AbstractSpeedImpl imp return super.toString()+" to "+getBearing().getDegrees()+"°"; } + @Override + public int hashCode() { + return super.hashCode() ^ getBearing().hashCode(); + } + + @Override + public boolean equals(Object object) { + return super.equals(object) && object instanceof SpeedWithBearing + && getBearing().equals(((SpeedWithBearing) object).getBearing()); + } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/KilometersPerHourSpeedWithBearingImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/KilometersPerHourSpeedWithBearingImpl.java index 14df4472654..dcd080ee581 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/KilometersPerHourSpeedWithBearingImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/KilometersPerHourSpeedWithBearingImpl.java @@ -27,4 +27,15 @@ public class KilometersPerHourSpeedWithBearingImpl extends KilometersPerHourSpee public String toString() { return super.toString()+" to "+getBearing().getDegrees()+"°"; } + + @Override + public int hashCode() { + return super.hashCode() ^ getBearing().hashCode(); + } + + @Override + public boolean equals(Object object) { + return super.equals(object) && object instanceof SpeedWithBearing + && getBearing().equals(((SpeedWithBearing) object).getBearing()); + } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/DynamicTrack.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/DynamicTrack.java index f17a01c1717..d5cf5e0cdf3 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/DynamicTrack.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/DynamicTrack.java @@ -7,6 +7,12 @@ package com.sap.sailing.domain.tracking; */ public interface DynamicTrack extends GPSFixTrack { + /** + * Adds the gpsFix (or an object equal to it) to this track. Note: depending on the implementation, + * it's not the same object actually added to the track but only an equal one. This is particularly + * important when constructing test cases. Don't expect objects returned by {@link #getFixes()} to be the same + * as those added; they will only be equal. + */ void addGPSFix(FixType gpsFix); /** diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/AbstractGPSFixImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/AbstractGPSFixImpl.java new file mode 100755 index 00000000000..81cdcc21136 --- /dev/null +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/AbstractGPSFixImpl.java @@ -0,0 +1,36 @@ +package com.sap.sailing.domain.tracking.impl; + +import com.sap.sailing.domain.tracking.GPSFix; + +public abstract class AbstractGPSFixImpl implements GPSFix { + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((getPosition() == null) ? 0 : getPosition().hashCode()); + result = prime * result + ((getTimePoint() == null) ? 0 : getTimePoint().hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (!(obj instanceof GPSFix)) + return false; + GPSFix other = (GPSFix) obj; + if (getPosition() == null) { + if (other.getPosition() != null) + return false; + } else if (!getPosition().equals(other.getPosition())) + return false; + if (getTimePoint() == null) { + if (other.getTimePoint() != null) + return false; + } else if (!getTimePoint().equals(other.getTimePoint())) + return false; + return true; + } +} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CompactGPSFixImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CompactGPSFixImpl.java index 932c39328dc..5c20d5ecaf0 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CompactGPSFixImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CompactGPSFixImpl.java @@ -6,7 +6,7 @@ import com.sap.sailing.domain.base.impl.AbstractPosition; import com.sap.sailing.domain.base.impl.AbstractTimePoint; import com.sap.sailing.domain.tracking.GPSFix; -public class CompactGPSFixImpl implements GPSFix { +public class CompactGPSFixImpl extends AbstractGPSFixImpl implements GPSFix { private final double latDeg; private final double lngDeg; private final long timePointAsMillis; @@ -54,4 +54,5 @@ public class CompactGPSFixImpl implements GPSFix { public TimePoint getTimePoint() { return new CompactTimePoint(); } + } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CompactGPSFixMovingImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CompactGPSFixMovingImpl.java index cb875804eaa..1dfe82c3d34 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CompactGPSFixMovingImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CompactGPSFixMovingImpl.java @@ -41,6 +41,16 @@ public class CompactGPSFixMovingImpl extends CompactGPSFixImpl implements GPSFix public String toString() { return super.toString()+" to "+getBearing().getDegrees()+"°"; } + @Override + public int hashCode() { + return super.hashCode() ^ getBearing().hashCode(); + } + + @Override + public boolean equals(Object object) { + return super.equals(object) && object instanceof SpeedWithBearing + && getBearing().equals(((SpeedWithBearing) object).getBearing()); + } } private class CompactBearing extends AbstractBearing { @@ -74,4 +84,14 @@ public class CompactGPSFixMovingImpl extends CompactGPSFixImpl implements GPSFix public String toString() { return super.toString() + " with " + getSpeed(); } + + @Override + public int hashCode() { + return super.hashCode() ^ getSpeed().hashCode(); + } + + @Override + public boolean equals(Object other) { + return super.equals(other) && other instanceof GPSFixMoving && getSpeed().equals(((GPSFixMoving) other).getSpeed()); + } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/GPSFixImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/GPSFixImpl.java index 947b8dcd142..575eea1ed32 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/GPSFixImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/GPSFixImpl.java @@ -4,7 +4,13 @@ import com.sap.sailing.domain.base.Position; import com.sap.sailing.domain.base.TimePoint; import com.sap.sailing.domain.tracking.GPSFix; -public class GPSFixImpl implements GPSFix { +/** + * Equality / hash code are based on {@link #getPosition()}'s and {@link #getTimePoint()}'s equality / hash code. + * + * @author Axel Uhl (d043530) + * + */ +public class GPSFixImpl extends AbstractGPSFixImpl implements GPSFix { private final Position position; private final TimePoint timePoint; diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/GPSFixMovingImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/GPSFixMovingImpl.java index af3b657eca1..7cb8b8195c7 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/GPSFixMovingImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/GPSFixMovingImpl.java @@ -22,4 +22,14 @@ public class GPSFixMovingImpl extends GPSFixImpl implements GPSFixMoving { public String toString() { return super.toString()+" with "+getSpeed(); } + + @Override + public int hashCode() { + return super.hashCode() ^ getSpeed().hashCode(); + } + + @Override + public boolean equals(Object other) { + return super.equals(other) && other instanceof GPSFixMoving && getSpeed().equals(((GPSFixMoving) other).getSpeed()); + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/LeaderboardPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/LeaderboardPanel.java index 1f09ae6f78c..b45cbbfbaf7 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/LeaderboardPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/LeaderboardPanel.java @@ -719,8 +719,7 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta leaderboardTable = new CellTableWithStylableHeaders( /* pageSize */100, resources); getLeaderboardTable().setWidth("100%"); - getLeaderboardTable().setSelectionModel(new MultiSelectionModel() { - }); + getLeaderboardTable().setSelectionModel(new MultiSelectionModel() {}); setData(new ListDataProvider()); getData().addDataDisplay(getLeaderboardTable()); listHandler = new ListHandler(getData().getList()); From f4e26e0012117521d7d57550a587cf24266ed8a4 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Tue, 22 Nov 2011 22:59:16 +0100 Subject: [PATCH 08/11] changed test verdict to ensure ConcurrentModificationException is thrown when adding GPS fixes --- .../src/com/sap/sailing/domain/test/TrackTest.java | 10 +++------- .../sap/sailing/util/impl/ArrayListNavigableSet.java | 12 ++++++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackTest.java index 74af9a7745d..9e1a80cfb6d 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackTest.java @@ -77,13 +77,8 @@ public class TrackTest { } /** - * Bug #70: modify a track while iterating over a subset of it; ensure that this doesn't cause a + * Bug #70: modify a track while iterating over a subset of it; ensure that this causes a * {@link ConcurrentModificationException}. - * @throws InterruptedException - * @throws IllegalAccessException - * @throws IllegalArgumentException - * @throws NoSuchFieldException - * @throws SecurityException */ @Test public void testAddingWhileIteratingOverSubset() throws InterruptedException, IllegalArgumentException, @@ -106,8 +101,9 @@ public class TrackTest { try { GPSFixMoving secondOfSubset = subsetIter.next(); assertEquals(gpsFix3, secondOfSubset); - } catch (ConcurrentModificationException e) { fail("adding a fix interferes with iteration over subSet of track's fixes"); + } catch (ConcurrentModificationException e) { + // this is what we expected } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/util/impl/ArrayListNavigableSet.java b/java/com.sap.sailing.domain/src/com/sap/sailing/util/impl/ArrayListNavigableSet.java index 4098dc52fda..62c0a5d1639 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/util/impl/ArrayListNavigableSet.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/util/impl/ArrayListNavigableSet.java @@ -19,7 +19,7 @@ import java.util.SortedSet; * at the expense of always performing one comparison in case the collection is not empty, before resorting to * binary search.

* - * Computing subsets is mapped to computing sub-lists (see {@link List#subList(int, int)}), with all the same effects + * Computing subsets is mapped to computing sub-lists (see {@link #subList(int, int)}), with all the same effects * on how the resulting collection is backed by the original collection.

* * The iterators returned by {@link #iterator()} and {@link #descendingIterator()} are special in that they do not @@ -323,7 +323,7 @@ public class ArrayListNavigableSet implements NavigableSet { if (to < from) { to = from; // will still produce an empty list instead of failing with an exception } - return new ArrayListNavigableSet(list.subList(from, to), comparator()); + return new ArrayListNavigableSet(subList(from, to), comparator()); } @Override @@ -339,7 +339,7 @@ public class ArrayListNavigableSet implements NavigableSet { if (to < 0) { to = 0; // will still produce an empty list instead of failing with an exception } - return new ArrayListNavigableSet(list.subList(0, to), comparator()); + return new ArrayListNavigableSet(subList(0, to), comparator()); } @Override @@ -355,7 +355,11 @@ public class ArrayListNavigableSet implements NavigableSet { if (from > list.size()) { from = list.size(); // will still produce an empty list instead of failing with an exception } - return new ArrayListNavigableSet(list.subList(from, list.size()), comparator()); + return new ArrayListNavigableSet(subList(from, list.size()), comparator()); + } + + private List subList(int from, int to) { + return list.subList(from, to); } @Override From bf773f8f26df748e9d2a8e0443cb25a0b156b4fe Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Tue, 22 Nov 2011 23:22:58 +0100 Subject: [PATCH 09/11] added synchronization to all iterations over a track's fixes --- .../domain/base/impl/DouglasPeucker.java | 22 ++++--- .../sailing/domain/tracking/DynamicTrack.java | 12 +++- .../sap/sailing/domain/tracking/Track.java | 15 ++++- .../tracking/impl/DynamicTrackImpl.java | 4 +- .../domain/tracking/impl/GPSFixTrackImpl.java | 2 +- .../domain/tracking/impl/WindTrackImpl.java | 28 ++++---- .../gwt/ui/server/SailingServiceImpl.java | 64 +++++++++++-------- .../src/com/sap/sailing/server/AdminApp.java | 51 ++++++++------- .../com/sap/sailing/server/ModeratorApp.java | 39 +++++------ 9 files changed, 142 insertions(+), 95 deletions(-) diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DouglasPeucker.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DouglasPeucker.java index 7a866875e9f..cf8b4ad68e8 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DouglasPeucker.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DouglasPeucker.java @@ -30,16 +30,18 @@ public class DouglasPeucker { Position fromPosition = track.getFirstFixAtOrAfter(from).getPosition(); FixType toFix = track.getLastFixAtOrBefore(to); Bearing bearing = fromPosition.getBearingGreatCircle(toFix.getPosition()); - Iterator fixIter = track.getFixesIterator(from, /* inclusive */ false); - while (fixIter.hasNext()) { - FixType fix = fixIter.next(); - if (fix.getTimePoint().compareTo(to) > 0) { - break; - } - Distance crossTrackError = fix.getPosition().crossTrackError(fromPosition, bearing); - if (crossTrackError.compareTo(maxDistance) > 0) { - maxDistance = crossTrackError; - fixFurthestAway = fix; + synchronized (track) { + Iterator fixIter = track.getFixesIterator(from, /* inclusive */ false); + while (fixIter.hasNext()) { + FixType fix = fixIter.next(); + if (fix.getTimePoint().compareTo(to) > 0) { + break; + } + Distance crossTrackError = fix.getPosition().crossTrackError(fromPosition, bearing); + if (crossTrackError.compareTo(maxDistance) > 0) { + maxDistance = crossTrackError; + fixFurthestAway = fix; + } } } return new Pair(fixFurthestAway, maxDistance); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/DynamicTrack.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/DynamicTrack.java index d5cf5e0cdf3..2eba3038173 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/DynamicTrack.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/DynamicTrack.java @@ -1,7 +1,12 @@ package com.sap.sailing.domain.tracking; +import java.util.ConcurrentModificationException; + /** - * An extensible track that can still grow by adding more GPS fixes to it. + * An extensible track that can still grow by adding more GPS fixes to it. Callers of {@link GPSFixTrack#getFixes()} + * or {@link #getRawFixes()} or {@link #getFixesIterator(com.sap.sailing.domain.base.TimePoint, boolean)} or + * {@link #getRawFixesIterator(com.sap.sailing.domain.base.TimePoint, boolean)} must make sure they synchronize + * on this object before starting an iteration. Otherwise, {@link ConcurrentModificationException} may result. * * @author Axel Uhl (d043530) */ @@ -11,7 +16,10 @@ public interface DynamicTrack extends * Adds the gpsFix (or an object equal to it) to this track. Note: depending on the implementation, * it's not the same object actually added to the track but only an equal one. This is particularly * important when constructing test cases. Don't expect objects returned by {@link #getFixes()} to be the same - * as those added; they will only be equal. + * as those added; they will only be equal.

+ * + * Implementations will usually implement this as a synchronized operation that is mutual exclusive + * to iterating over the fixes of the track or any subset thereof. */ void addGPSFix(FixType gpsFix); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/Track.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/Track.java index d923064f3e1..d14cc432c84 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/Track.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/Track.java @@ -13,11 +13,18 @@ import com.sap.sailing.domain.base.Timed; */ public interface Track { /** + * Callers must synchronize on this object before iterating the result if they have to expect concurrent + * modifications. + * * @return the raw fixes as recorded by this track; in particular, no smoothening or dampening of any kind is * applied to the fixes returned by this method. */ Iterable getFixes(); - + + /** + * Callers must synchronize on this object before iterating the result if they have to expect concurrent + * modifications. + */ Iterable getRawFixes(); FixType getLastFixAtOrBefore(TimePoint timePoint); @@ -50,6 +57,9 @@ public interface Track { * Returns an iterator starting at the first fix after startingAt (or "at or after" in case * inclusive is true). The fixes returned by the iterator are the smoothened fixes (see * also {@link #getFixes()}, without any smoothening or dampening applied. + * + * Callers must synchronize on this object before iterating the result if they have to expect concurrent + * modifications. */ Iterator getFixesIterator(TimePoint startingAt, boolean inclusive); @@ -57,6 +67,9 @@ public interface Track { * Returns an iterator starting at the first raw fix after startingAt (or "at or after" in case * inclusive is true). The fixes returned by the iterator are the raw fixes (see also * {@link #getRawFixes()}, without any smoothening or dampening applied. + * + * Callers must synchronize on this object before iterating the result if they have to expect concurrent + * modifications. */ Iterator getRawFixesIterator(TimePoint startingAt, boolean inclusive); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackImpl.java index 7d390ff423c..425cce87f88 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackImpl.java @@ -18,7 +18,9 @@ public class DynamicTrackImpl extends @Override public void addGPSFix(FixType gpsFix) { - getInternalRawFixes().add(gpsFix); + synchronized (this) { + getInternalRawFixes().add(gpsFix); + } for (RaceChangeListener listener : listeners) { listener.gpsFixReceived(gpsFix, getTrackedItem()); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/GPSFixTrackImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/GPSFixTrackImpl.java index 849387cbf05..fe3228e7cf3 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/GPSFixTrackImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/GPSFixTrackImpl.java @@ -95,7 +95,7 @@ public class GPSFixTrackImpl extends TrackImpl } @Override - public Speed getMaximumSpeedOverGround(TimePoint from, TimePoint to) { + public synchronized Speed getMaximumSpeedOverGround(TimePoint from, TimePoint to) { // fetch all fixes on this leg so far and determine their maximum speed Iterator iter = getFixesIterator(from, /* inclusive */ true); Speed max = Speed.NULL; diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/WindTrackImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/WindTrackImpl.java index 94ca85d4104..538f76e4aeb 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/WindTrackImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/WindTrackImpl.java @@ -167,24 +167,28 @@ public class WindTrackImpl extends TrackImpl implements WindTrack { @Override public String toString() { StringBuilder result = new StringBuilder(); - for (Wind wind : getRawFixes()) { - result.append(wind); - result.append(" avg("); - result.append(millisecondsOverWhichToAverage); - result.append("ms): "); - result.append(getEstimatedWind(wind.getPosition(), wind.getTimePoint())); - result.append("\n"); + synchronized (this) { + for (Wind wind : getRawFixes()) { + result.append(wind); + result.append(" avg("); + result.append(millisecondsOverWhichToAverage); + result.append("ms): "); + result.append(getEstimatedWind(wind.getPosition(), wind.getTimePoint())); + result.append("\n"); + } } return result.toString(); } public String toCSV() { StringBuilder result = new StringBuilder(); - for (Wind wind : getRawFixes()) { - append(result, wind); - Wind estimate = getEstimatedWind(wind.getPosition(), wind.getTimePoint()); - append(result, estimate); - result.append("\n"); + synchronized (this) { + for (Wind wind : getRawFixes()) { + append(result, wind); + Wind estimate = getEstimatedWind(wind.getPosition(), wind.getTimePoint()); + append(result, estimate); + result.append("\n"); + } } return result.toString(); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java index 4bef639b2e2..c2bf365eacb 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java @@ -497,7 +497,11 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS windTrackInfoDAOs.put("COURSEBASED", createWindTrackInfoDAO(windwardMarkWindTrack)); } if (includeTrackBasedWindEstimation && estimatedTrack != null) { - if (!estimatedTrack.getFixes().iterator().hasNext()) { + boolean hasNext; + synchronized (estimatedTrack) { + hasNext = estimatedTrack.getFixes().iterator().hasNext(); + } + if (!hasNext) { // empty wind estimation track; add at least one estimate for the current time for the start gate Wind estimatedWindDirectionForNow; try { @@ -519,8 +523,10 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS WindTrackInfoDAO windEstimations = new WindTrackInfoDAO(); windEstimations.dampeningIntervalInMilliseconds = estimatedTrack.getMillisecondsOverWhichToAverageWind(); windEstimations.windFixes = new ArrayList(); - for (Wind estimatedWind : estimatedTrack.getFixes()) { - windEstimations.windFixes.add(createWindDAO(estimatedWind, estimatedTrack)); + synchronized (estimatedTrack) { + for (Wind estimatedWind : estimatedTrack.getFixes()) { + windEstimations.windFixes.add(createWindDAO(estimatedWind, estimatedTrack)); + } } return windEstimations; } @@ -672,30 +678,36 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS TimePoint fromTimePoint = new MillisecondsTimePoint(from.get(competitorDAO)); TimePoint toTimePointExcluding = new MillisecondsTimePoint(to.get(competitorDAO)); Iterator fixIter; - fixIter = track.getFixesIterator(fromTimePoint, /* inclusive */ true); - if (fixIter.hasNext()) { - GPSFixMoving fix = fixIter.next(); - while (fix != null && fix.getTimePoint().compareTo(toTimePointExcluding) < 0) { - Tack tack = trackedRace.getTack(competitor, fix.getTimePoint()); - GPSFixDAO fixDAO = new GPSFixDAO(fix.getTimePoint().asDate(), new PositionDAO(fix - .getPosition().getLatDeg(), fix.getPosition().getLngDeg()), - new SpeedWithBearingDAO(fix.getSpeed().getKnots(), fix.getSpeed().getBearing() - .getDegrees()), tack.name(), /* extrapolated */ false); - fixesForCompetitor.add(fixDAO); - if (fixIter.hasNext()) { - fix = fixIter.next(); - } else { - // check if fix was at date and if extrapolation is requested - if (!fix.getTimePoint().equals(toTimePointExcluding) && extrapolate) { - Position position = track.getEstimatedPosition(toTimePointExcluding, extrapolate); - Tack tack2 = trackedRace.getTack(competitor, toTimePointExcluding); - SpeedWithBearing speedWithBearing = track.getEstimatedSpeed(toTimePointExcluding); - GPSFixDAO extrapolated = new GPSFixDAO(to.get(competitorDAO), new PositionDAO(position.getLatDeg(), - position.getLngDeg()), new SpeedWithBearingDAO(speedWithBearing.getKnots(), - speedWithBearing.getBearing().getDegrees()), tack2.name(), /* extrapolated */ true); - fixesForCompetitor.add(extrapolated); + synchronized (track) { + fixIter = track.getFixesIterator(fromTimePoint, /* inclusive */true); + if (fixIter.hasNext()) { + GPSFixMoving fix = fixIter.next(); + while (fix != null && fix.getTimePoint().compareTo(toTimePointExcluding) < 0) { + Tack tack = trackedRace.getTack(competitor, fix.getTimePoint()); + GPSFixDAO fixDAO = new GPSFixDAO(fix.getTimePoint().asDate(), new PositionDAO(fix + .getPosition().getLatDeg(), fix.getPosition().getLngDeg()), + new SpeedWithBearingDAO(fix.getSpeed().getKnots(), fix.getSpeed().getBearing() + .getDegrees()), tack.name(), /* extrapolated */false); + fixesForCompetitor.add(fixDAO); + if (fixIter.hasNext()) { + fix = fixIter.next(); + } else { + // check if fix was at date and if extrapolation is requested + if (!fix.getTimePoint().equals(toTimePointExcluding) && extrapolate) { + Position position = track.getEstimatedPosition(toTimePointExcluding, + extrapolate); + Tack tack2 = trackedRace.getTack(competitor, toTimePointExcluding); + SpeedWithBearing speedWithBearing = track + .getEstimatedSpeed(toTimePointExcluding); + GPSFixDAO extrapolated = new GPSFixDAO(to.get(competitorDAO), new PositionDAO( + position.getLatDeg(), position.getLngDeg()), + new SpeedWithBearingDAO(speedWithBearing.getKnots(), speedWithBearing + .getBearing().getDegrees()), tack2.name(), /* extrapolated */ + true); + fixesForCompetitor.add(extrapolated); + } + fix = null; } - fix = null; } } } diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/AdminApp.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/AdminApp.java index 4dcd9223205..90b60692f57 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/AdminApp.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/AdminApp.java @@ -266,31 +266,34 @@ public class AdminApp extends Servlet { for (WindSource windSource : WindSource.values()) { JSONArray jsonWindArray = new JSONArray(); WindTrack windTrack = trackedRace.getWindTrack(windSource); - Iterator windIter = windTrack.getFixesIterator(from, /* inclusive */true); - while (windIter.hasNext()) { - Wind wind = windIter.next(); - if (wind.getTimePoint().compareTo(to) > 0) { - break; + synchronized (windTrack) { + Iterator windIter = windTrack.getFixesIterator(from, /* inclusive */true); + while (windIter.hasNext()) { + Wind wind = windIter.next(); + if (wind.getTimePoint().compareTo(to) > 0) { + break; + } + JSONObject jsonWind = new JSONObject(); + jsonWind.put("truebearingdeg", wind.getBearing().getDegrees()); + jsonWind.put("knotspeed", wind.getKnots()); + jsonWind.put("meterspersecondspeed", wind.getMetersPerSecond()); + if (wind.getTimePoint() != null) { + jsonWind.put("timepoint", wind.getTimePoint().asMillis()); + jsonWind.put("dampenedtruebearingdeg", + windTrack.getEstimatedWind(wind.getPosition(), wind.getTimePoint()) + .getBearing().getDegrees()); + jsonWind.put("dampenedknotspeed", + windTrack.getEstimatedWind(wind.getPosition(), wind.getTimePoint()).getKnots()); + jsonWind.put("dampenedmeterspersecondspeed", + windTrack.getEstimatedWind(wind.getPosition(), wind.getTimePoint()) + .getMetersPerSecond()); + } + if (wind.getPosition() != null) { + jsonWind.put("latdeg", wind.getPosition().getLatDeg()); + jsonWind.put("lngdeg", wind.getPosition().getLngDeg()); + } + jsonWindArray.add(jsonWind); } - JSONObject jsonWind = new JSONObject(); - jsonWind.put("truebearingdeg", wind.getBearing().getDegrees()); - jsonWind.put("knotspeed", wind.getKnots()); - jsonWind.put("meterspersecondspeed", wind.getMetersPerSecond()); - if (wind.getTimePoint() != null) { - jsonWind.put("timepoint", wind.getTimePoint().asMillis()); - jsonWind.put("dampenedtruebearingdeg", - windTrack.getEstimatedWind(wind.getPosition(), wind.getTimePoint()).getBearing() - .getDegrees()); - jsonWind.put("dampenedknotspeed", - windTrack.getEstimatedWind(wind.getPosition(), wind.getTimePoint()).getKnots()); - jsonWind.put("dampenedmeterspersecondspeed", - windTrack.getEstimatedWind(wind.getPosition(), wind.getTimePoint()).getMetersPerSecond()); - } - if (wind.getPosition() != null) { - jsonWind.put("latdeg", wind.getPosition().getLatDeg()); - jsonWind.put("lngdeg", wind.getPosition().getLngDeg()); - } - jsonWindArray.add(jsonWind); } jsonWindTracks.put(windSource.toString(), jsonWindArray); } diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/ModeratorApp.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/ModeratorApp.java index 2412d6e1f07..75efc030481 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/ModeratorApp.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/ModeratorApp.java @@ -98,26 +98,29 @@ public class ModeratorApp extends Servlet { JSONObject jsonCompetitor = new JSONObject(); jsonCompetitor.put("name", competitor.getName()); GPSFixTrack track = trackedRace.getTrack(competitor); - Iterator fixIter; - if (sinceTimePoint == null) { - fixIter = track.getFixes().iterator(); - } else { - fixIter = track.getFixesIterator(sinceTimePoint, /* inclusive */ true); - } JSONArray jsonFixes = new JSONArray(); - while (fixIter.hasNext()) { - GPSFixMoving fix = fixIter.next(); - if (toTimePoint != null && fix.getTimePoint() != null && toTimePoint.compareTo(fix.getTimePoint()) < 0) { - break; + synchronized (track) { + Iterator fixIter; + if (sinceTimePoint == null) { + fixIter = track.getFixes().iterator(); + } else { + fixIter = track.getFixesIterator(sinceTimePoint, /* inclusive */true); + } + while (fixIter.hasNext()) { + GPSFixMoving fix = fixIter.next(); + if (toTimePoint != null && fix.getTimePoint() != null + && toTimePoint.compareTo(fix.getTimePoint()) < 0) { + break; + } + JSONObject jsonFix = new JSONObject(); + jsonFix.put("timepoint", fix.getTimePoint().asMillis()); + jsonFix.put("latdeg", fix.getPosition().getLatDeg()); + jsonFix.put("lngdeg", fix.getPosition().getLngDeg()); + jsonFix.put("truebearingdeg", fix.getSpeed().getBearing().getDegrees()); + jsonFix.put("knotspeed", fix.getSpeed().getKnots()); + jsonFix.put("tack", trackedRace.getTack(competitor, fix.getTimePoint()).name()); + jsonFixes.add(jsonFix); } - JSONObject jsonFix = new JSONObject(); - jsonFix.put("timepoint", fix.getTimePoint().asMillis()); - jsonFix.put("latdeg", fix.getPosition().getLatDeg()); - jsonFix.put("lngdeg", fix.getPosition().getLngDeg()); - jsonFix.put("truebearingdeg", fix.getSpeed().getBearing().getDegrees()); - jsonFix.put("knotspeed", fix.getSpeed().getKnots()); - jsonFix.put("tack", trackedRace.getTack(competitor, fix.getTimePoint()).name()); - jsonFixes.add(jsonFix); } jsonCompetitor.put("track", jsonFixes); jsonCompetitors.add(jsonCompetitor); From 0dc8149f1a3411de817f61739f35c4f1d3f2bd4e Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Tue, 22 Nov 2011 23:44:17 +0100 Subject: [PATCH 10/11] added tests asserting equality but non-identity after putting position/speed/bearing into compact form --- .../sap/sailing/domain/test/PositionTest.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/PositionTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/PositionTest.java index f959c5d4dbf..1ef2d8e562f 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/PositionTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/PositionTest.java @@ -1,6 +1,7 @@ package com.sap.sailing.domain.test; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertTrue; import org.junit.Test; @@ -9,11 +10,35 @@ import com.sap.sailing.domain.base.Bearing; import com.sap.sailing.domain.base.Distance; import com.sap.sailing.domain.base.Mile; import com.sap.sailing.domain.base.Position; +import com.sap.sailing.domain.base.SpeedWithBearing; import com.sap.sailing.domain.base.impl.DegreeBearingImpl; import com.sap.sailing.domain.base.impl.DegreePosition; +import com.sap.sailing.domain.base.impl.KnotSpeedWithBearingImpl; +import com.sap.sailing.domain.base.impl.MillisecondsTimePoint; import com.sap.sailing.domain.base.impl.NauticalMileDistance; +import com.sap.sailing.domain.tracking.impl.CompactGPSFixImpl; +import com.sap.sailing.domain.tracking.impl.CompactGPSFixMovingImpl; public class PositionTest { + @Test + public void testEqualityBetweenCompactAndVerbosePosition() { + Position p1 = new DegreePosition(49.2, 008.3); + CompactGPSFixImpl compactFix = new CompactGPSFixImpl(p1, MillisecondsTimePoint.now()); + assertNotSame(p1, compactFix.getPosition()); + assertEquals(p1, compactFix.getPosition()); + } + + @Test + public void testEqualityBetweenCompactAndVerboseSpeedWithBearing() { + Position p1 = new DegreePosition(49.2, 008.3); + SpeedWithBearing swb = new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123)); + CompactGPSFixMovingImpl compactFix = new CompactGPSFixMovingImpl(p1, MillisecondsTimePoint.now(), swb); + assertNotSame(p1, compactFix.getPosition()); + assertEquals(p1, compactFix.getPosition()); + assertNotSame(swb, compactFix.getSpeed()); + assertEquals(swb, compactFix.getSpeed()); + } + @Test public void translateTwoDegreesSouth() { Distance distance = new NauticalMileDistance(120/Mile.METERS_PER_GEOGRAPHICAL_MILE*Mile.METERS_PER_NAUTICAL_MILE); From 02191cc929b02817e2e58f7b64b305ba9a044323 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Tue, 22 Nov 2011 23:50:50 +0100 Subject: [PATCH 11/11] removed unused fields --- .../com/sap/sailing/gwt/ui/client/TrackedEventsComposite.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TrackedEventsComposite.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TrackedEventsComposite.java index 2ec1632f208..8ca37e2c2d0 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TrackedEventsComposite.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TrackedEventsComposite.java @@ -16,7 +16,6 @@ import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.FormPanel; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Label; -import com.google.gwt.user.client.ui.ListBox; import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.view.client.ListDataProvider; import com.google.gwt.view.client.MultiSelectionModel; @@ -41,9 +40,6 @@ public class TrackedEventsComposite extends FormPanel implements EventDisplayer, private CellTable> raceTable; - private ListBox regattasComboBox = null; - private ListBox eventsComboBox = null; - private ListDataProvider> raceList; private VerticalPanel panel;