added replication capabilities for Regatta / Series manipulation

This commit is contained in:
Axel Uhl committed 2012-06-05 13:23:05 +02:00
1 parent bb48b4a227
commit eb6a1e6214
26 files changed
+559 -40

No files matched your search

@@ -20,6 +20,7 @@ import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.Series;
import com.sap.sailing.domain.common.RaceFetcher;
import com.sap.sailing.domain.common.RaceIdentifier;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
@@ -362,6 +363,9 @@ public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetch
Regatta getOrCreateRegatta(String regattaName, String boatClassName, boolean boatClassTypicallyStartsUpwind);
Regatta createRegatta(String baseName, String boatClassName, boolean boatClassTypicallyStartsUpwind,
Iterable<? extends Series> series, boolean persistent);
/**
* Adds <code>raceDefinition</code> to the {@link Regatta} such that it will appear in {@link Regatta#getAllRaces()}
* and {@link Regatta#getRaceByName(String)}.
@@ -35,6 +35,7 @@ import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.RegattaListener;
import com.sap.sailing.domain.base.Series;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.impl.EventImpl;
import com.sap.sailing.domain.base.impl.RegattaImpl;
@@ -91,8 +92,9 @@ import com.sap.sailing.operationaltransformation.Operation;
import com.sap.sailing.server.OperationExecutionListener;
import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.RacingEventServiceOperation;
import com.sap.sailing.server.operationaltransformation.AddDefaultRegatta;
import com.sap.sailing.server.operationaltransformation.AddRaceDefinition;
import com.sap.sailing.server.operationaltransformation.AddRegatta;
import com.sap.sailing.server.operationaltransformation.AddSpecificRegatta;
import com.sap.sailing.server.operationaltransformation.ConnectTrackedRaceToLeaderboardColumn;
import com.sap.sailing.server.operationaltransformation.CreateTrackedRace;
import com.sap.sailing.server.operationaltransformation.RecordBuoyGPSFix;
@@ -452,11 +454,22 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
if (result == null) {
result = regatta;
logger.info("Created regatta "+result.getName()+" ("+hashCode()+")");
cacheAndReplicateRegatta(result);
cacheAndReplicateDefaultRegatta(result);
}
return result;
}
@Override
public Regatta createRegatta(String baseEventName, String boatClassName,
boolean boatClassTypicallyStartsUpwind, Iterable<? extends Series> series, boolean persistent) {
Regatta regatta = new RegattaImpl(baseEventName,
com.sap.sailing.domain.base.DomainFactory.INSTANCE.getOrCreateBoatClass(boatClassName,
boatClassTypicallyStartsUpwind), series, persistent);
logger.info("Created regatta " + regatta.getName() + " (" + hashCode() + ")");
cacheAndReplicateSpecificRegattaWithoutRaceColumns(regatta);
return regatta;
}
@Override
public Pair<String, List<RaceRecord>> getTracTracRaceRecords(URL jsonURL) throws IOException, ParseException, org.json.simple.parser.ParseException, URISyntaxException {
JSONService jsonService = getDomainFactory().parseJSONURL(jsonURL);
@@ -467,9 +480,6 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
public List<com.sap.sailing.domain.swisstimingadapter.RaceRecord> getSwissTimingRaceRecords(String hostname,
int port, boolean canSendRequests) throws InterruptedException, UnknownHostException, IOException, ParseException {
List<com.sap.sailing.domain.swisstimingadapter.RaceRecord> result = new ArrayList<com.sap.sailing.domain.swisstimingadapter.RaceRecord>();
// SailMasterConnector swissTimingConnector = swissTimingFactory.getOrCreateSailMasterConnector(hostname, port, swissTimingAdapterPersistence,
// canSendRequests);
//TODO remove after testing and enable the upper code instead
SailMasterConnector swissTimingConnector = swissTimingFactory.getOrCreateSailMasterLiveSimulatorConnector(hostname, port, swissTimingAdapterPersistence,
canSendRequests);
//
@@ -548,13 +558,13 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
if (regattaWithName != tracker.getRegatta()) {
if (Util.isEmpty(regattaWithName.getAllRaces())) {
// probably, tracker removed the last races from the old regatta and created a new one
cacheAndReplicateRegatta(tracker.getRegatta());
cacheAndReplicateDefaultRegatta(tracker.getRegatta());
} else {
throw new RuntimeException("Internal error. Two Event objects with equal name "+regattaName);
}
}
} else {
cacheAndReplicateRegatta(tracker.getRegatta());
cacheAndReplicateDefaultRegatta(tracker.getRegatta());
}
} else {
WindStore existingTrackersWindStore = tracker.getWindStore();
@@ -571,14 +581,50 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
/**
* If <code>regatta</code> is not yet in {@link #regattasByName}, it is added, this service is
* {@link Regatta#addRegattaListener(RegattaListener) added} as regatta listener, and the regatta and all its contained
* {@link Regatta#getAllRaces() races} are replicated to all replica.
* {@link Regatta#addRegattaListener(RegattaListener) added} as regatta listener, and the regatta and all its
* contained {@link Regatta#getAllRaces() races} are replicated to all replica.
*
* @param regatta
* the series of this regatta must not have any {@link Series#getRaceColumns() race columns associated
* (yet)}.
*/
private void cacheAndReplicateRegatta(Regatta regatta) {
private void cacheAndReplicateSpecificRegattaWithoutRaceColumns(Regatta regatta) {
if (!regattasByName.containsKey(regatta.getName())) {
regattasByName.put(regatta.getName(), regatta);
regatta.addRegattaListener(this);
replicate(new AddRegatta(regatta.getBaseName(), regatta.getBoatClass() == null ? null : regatta.getBoatClass().getName(),
replicate(new AddSpecificRegatta(regatta.getBaseName(), regatta.getBoatClass() == null ? null : regatta
.getBoatClass().getName(), regatta.getBoatClass() == null ? false : regatta.getBoatClass()
.typicallyStartsUpwind(), getSeriesWithoutRaceColumnsConstructionParametersAsMap(regatta), regatta.isPersistent()));
RegattaIdentifier regattaIdentifier = regatta.getRegattaIdentifier();
for (RaceDefinition race : regatta.getAllRaces()) {
replicate(new AddRaceDefinition(regattaIdentifier, race));
}
}
}
private Map<String, Pair<List<Pair<String, Integer>>, Boolean>> getSeriesWithoutRaceColumnsConstructionParametersAsMap(Regatta regatta) {
Map<String, Pair<List<Pair<String, Integer>>, Boolean>> result = new HashMap<String, Pair<List<Pair<String, Integer>>, Boolean>>();
for (Series s : regatta.getSeries()) {
assert Util.isEmpty(s.getRaceColumns());
List<Pair<String, Integer>> fleetNamesAndOrdering = new ArrayList<Pair<String, Integer>>();
for (Fleet f : s.getFleets()) {
fleetNamesAndOrdering.add(new Pair<String, Integer>(f.getName(), f.getOrdering()));
}
result.put(s.getName(), new Pair<List<Pair<String, Integer>>, Boolean>(fleetNamesAndOrdering, s.isMedal()));
}
return result;
}
/**
* If <code>regatta</code> is not yet in {@link #regattasByName}, it is added, this service is
* {@link Regatta#addRegattaListener(RegattaListener) added} as regatta listener, and the regatta and all its contained
* {@link Regatta#getAllRaces() races} are replicated to all replica.
*/
private void cacheAndReplicateDefaultRegatta(Regatta regatta) {
if (!regattasByName.containsKey(regatta.getName())) {
regattasByName.put(regatta.getName(), regatta);
regatta.addRegattaListener(this);
replicate(new AddDefaultRegatta(regatta.getBaseName(), regatta.getBoatClass() == null ? null : regatta.getBoatClass().getName(),
regatta.getBoatClass() == null ? false : regatta.getBoatClass().typicallyStartsUpwind()));
RegattaIdentifier regattaIdentifier = regatta.getRegattaIdentifier();
for (RaceDefinition race : regatta.getAllRaces()) {
@@ -964,7 +1010,7 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
@Override
public DynamicTrackedRegatta getOrCreateTrackedRegatta(Regatta regatta) {
cacheAndReplicateRegatta(regatta);
cacheAndReplicateDefaultRegatta(regatta);
synchronized (regattaTrackingCache) {
DynamicTrackedRegatta result = regattaTrackingCache.get(regatta);
if (result == null) {
@@ -0,0 +1,30 @@
package com.sap.sailing.server.operationaltransformation;
import com.sap.sailing.domain.base.Regatta;
public abstract class AbstractAddRegattaOperation extends AbstractRacingEventServiceOperation<Regatta> {
private static final long serialVersionUID = 4596134166642095364L;
private final String baseEventName;
private final String boatClassName;
private final boolean boatClassTypicallyStartsUpwind;
public AbstractAddRegattaOperation(String regattaName, String boatClassName, boolean boatClassTypicallyStartsUpwind) {
super();
this.baseEventName = regattaName;
this.boatClassName = boatClassName;
this.boatClassTypicallyStartsUpwind = boatClassTypicallyStartsUpwind;
}
protected String getBaseEventName() {
return baseEventName;
}
protected String getBoatClassName() {
return boatClassName;
}
protected boolean isBoatClassTypicallyStartsUpwind() {
return boatClassTypicallyStartsUpwind;
}
}
@@ -0,0 +1,37 @@
package com.sap.sailing.server.operationaltransformation;
import java.util.logging.Logger;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.Series;
import com.sap.sailing.domain.common.RegattaIdentifier;
import com.sap.sailing.server.RacingEventService;
public abstract class AbstractColumnInSeriesOperation<ResultType> extends AbstractSeriesOperation<ResultType> {
private static final long serialVersionUID = -8985474505327170991L;
private static final Logger logger = Logger.getLogger(AbstractColumnInSeriesOperation.class.getName());
private final String columnName;
public AbstractColumnInSeriesOperation(RegattaIdentifier regattaIdentifier, String seriesName, String columnName) {
super(regattaIdentifier, seriesName);
this.columnName = columnName;
}
protected String getColumnName() {
return columnName;
}
protected Series getSeries(RacingEventService toState) {
Series series = null;
Regatta regatta = toState.getRegatta(getRegattaIdentifier());
if (regatta != null) {
series = regatta.getSeriesByName(getSeriesName());
if (series == null) {
logger.warning("series "+getSeriesName()+" not found in regatta "+regatta.getName());
}
} else {
logger.warning("regatta "+getRegattaIdentifier()+" not found");
}
return series;
}
}
@@ -0,0 +1,24 @@
package com.sap.sailing.server.operationaltransformation;
import com.sap.sailing.domain.common.RegattaIdentifier;
public abstract class AbstractSeriesOperation<ResultType> extends AbstractRacingEventServiceOperation<ResultType> {
private static final long serialVersionUID = -7786133902346491275L;
private final RegattaIdentifier regattaIdentifier;
private final String seriesName;
public AbstractSeriesOperation(RegattaIdentifier regattaIdentifier, String seriesName) {
super();
this.regattaIdentifier = regattaIdentifier;
this.seriesName = seriesName;
}
protected RegattaIdentifier getRegattaIdentifier() {
return regattaIdentifier;
}
protected String getSeriesName() {
return seriesName;
}
}
@@ -0,0 +1,38 @@
package com.sap.sailing.server.operationaltransformation;
import com.sap.sailing.domain.base.RaceColumnInSeries;
import com.sap.sailing.domain.base.Series;
import com.sap.sailing.domain.common.RegattaIdentifier;
import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.RacingEventServiceOperation;
public class AddColumnToSeries extends AbstractColumnInSeriesOperation<RaceColumnInSeries> {
private static final long serialVersionUID = 8987540636040301063L;
public AddColumnToSeries(RegattaIdentifier regattaIdentifier, String seriesName, String columnName) {
super(regattaIdentifier, seriesName, columnName);
}
@Override
public RaceColumnInSeries internalApplyTo(RacingEventService toState) throws Exception {
RaceColumnInSeries result = null;
Series series = getSeries(toState);
if (series != null) {
result = series.addRaceColumn(getColumnName());
}
return result;
}
@Override
public RacingEventServiceOperation<?> transformClientOp(RacingEventServiceOperation<?> serverOp) {
// TODO Auto-generated method stub
return null;
}
@Override
public RacingEventServiceOperation<?> transformServerOp(RacingEventServiceOperation<?> clientOp) {
// TODO Auto-generated method stub
return null;
}
}
@@ -4,17 +4,11 @@ import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.RacingEventServiceOperation;
public class AddRegatta extends AbstractRacingEventServiceOperation<Regatta> {
public class AddDefaultRegatta extends AbstractAddRegattaOperation {
private static final long serialVersionUID = -3550383541066673065L;
private final String baseEventName;
private final String boatClassName;
private final boolean boatClassTypicallyStartsUpwind;
public AddRegatta(String regattaName, String boatClassName, boolean boatClassTypicallyStartsUpwind) {
super();
this.baseEventName = regattaName;
this.boatClassName = boatClassName;
this.boatClassTypicallyStartsUpwind = boatClassTypicallyStartsUpwind;
public AddDefaultRegatta(String regattaName, String boatClassName, boolean boatClassTypicallyStartsUpwind) {
super(regattaName, boatClassName, boatClassTypicallyStartsUpwind);
}
@Override
@@ -31,7 +25,7 @@ public class AddRegatta extends AbstractRacingEventServiceOperation<Regatta> {
@Override
public Regatta internalApplyTo(RacingEventService toState) {
return toState.getOrCreateRegatta(baseEventName, boatClassName, boatClassTypicallyStartsUpwind);
return toState.getOrCreateRegatta(getBaseEventName(), getBoatClassName(), isBoatClassTypicallyStartsUpwind());
}
}
@@ -0,0 +1,65 @@
package com.sap.sailing.server.operationaltransformation;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.Series;
import com.sap.sailing.domain.base.impl.FleetImpl;
import com.sap.sailing.domain.base.impl.SeriesImpl;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.RacingEventServiceOperation;
public class AddSpecificRegatta extends AbstractAddRegattaOperation {
private static final long serialVersionUID = -8018855620167669352L;
private final Map<String, Pair<List<Pair<String, Integer>>, Boolean>> seriesNamesWithFleetNamesAndFleetOrderingAndMedal;
private final boolean persistent;
public AddSpecificRegatta(String regattaName, String boatClassName, boolean boatClassTypicallyStartsUpwind,
Map<String, Pair<List<Pair<String, Integer>>, Boolean>> seriesNamesWithFleetNamesAndFleetOrdering, boolean persistent) {
super(regattaName, boatClassName, boatClassTypicallyStartsUpwind);
this.seriesNamesWithFleetNamesAndFleetOrderingAndMedal = seriesNamesWithFleetNamesAndFleetOrdering;
this.persistent = persistent;
}
@Override
public Regatta internalApplyTo(RacingEventService toState) throws Exception {
return toState.createRegatta(getBaseEventName(), getBoatClassName(), isBoatClassTypicallyStartsUpwind(), createSeries(), persistent);
}
private Iterable<? extends Series> createSeries() {
List<Series> result = new ArrayList<Series>();
for (Map.Entry<String, Pair<List<Pair<String, Integer>>, Boolean>> e : seriesNamesWithFleetNamesAndFleetOrderingAndMedal.entrySet()) {
final List<String> emptyRaceColumnNamesList = Collections.emptyList();
Series s = new SeriesImpl(e.getKey(), /* isMedal */ e.getValue().getB(), createFleets(e.getValue().getA()), emptyRaceColumnNamesList);
result.add(s);
}
return result;
}
private Iterable<? extends Fleet> createFleets(List<Pair<String, Integer>> fleetNamesAndOrdering) {
List<Fleet> result = new ArrayList<Fleet>();
for (Pair<String, Integer> fleetNameAndOrdering : fleetNamesAndOrdering) {
Fleet fleet = new FleetImpl(fleetNameAndOrdering.getA(), fleetNameAndOrdering.getB());
result.add(fleet);
}
return result;
}
@Override
public RacingEventServiceOperation<?> transformClientOp(RacingEventServiceOperation<?> serverOp) {
// TODO Auto-generated method stub
return null;
}
@Override
public RacingEventServiceOperation<?> transformServerOp(RacingEventServiceOperation<?> clientOp) {
// TODO Auto-generated method stub
return null;
}
}
@@ -0,0 +1,36 @@
package com.sap.sailing.server.operationaltransformation;
import com.sap.sailing.domain.base.Series;
import com.sap.sailing.domain.common.RegattaIdentifier;
import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.RacingEventServiceOperation;
public class MoveColumnInSeriesDown extends AbstractColumnInSeriesOperation<Void> {
private static final long serialVersionUID = 1055871052852494542L;
public MoveColumnInSeriesDown(RegattaIdentifier regattaIdentifier, String seriesName, String columnName) {
super(regattaIdentifier, seriesName, columnName);
}
@Override
public Void internalApplyTo(RacingEventService toState) throws Exception {
Series series = getSeries(toState);
if (series != null) {
series.moveRaceColumnDown(getColumnName());
}
return null;
}
@Override
public RacingEventServiceOperation<?> transformClientOp(RacingEventServiceOperation<?> serverOp) {
// TODO Auto-generated method stub
return null;
}
@Override
public RacingEventServiceOperation<?> transformServerOp(RacingEventServiceOperation<?> clientOp) {
// TODO Auto-generated method stub
return null;
}
}
@@ -0,0 +1,36 @@
package com.sap.sailing.server.operationaltransformation;
import com.sap.sailing.domain.base.Series;
import com.sap.sailing.domain.common.RegattaIdentifier;
import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.RacingEventServiceOperation;
public class MoveColumnInSeriesUp extends AbstractColumnInSeriesOperation<Void> {
private static final long serialVersionUID = -4111158026632514462L;
public MoveColumnInSeriesUp(RegattaIdentifier regattaIdentifier, String seriesName, String columnName) {
super(regattaIdentifier, seriesName, columnName);
}
@Override
public Void internalApplyTo(RacingEventService toState) throws Exception {
Series series = getSeries(toState);
if (series != null) {
series.moveRaceColumnUp(getColumnName());
}
return null;
}
@Override
public RacingEventServiceOperation<?> transformClientOp(RacingEventServiceOperation<?> serverOp) {
// TODO Auto-generated method stub
return null;
}
@Override
public RacingEventServiceOperation<?> transformServerOp(RacingEventServiceOperation<?> clientOp) {
// TODO Auto-generated method stub
return null;
}
}
@@ -0,0 +1,36 @@
package com.sap.sailing.server.operationaltransformation;
import com.sap.sailing.domain.base.Series;
import com.sap.sailing.domain.common.RegattaIdentifier;
import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.RacingEventServiceOperation;
public class RemoveColumnFromSeries extends AbstractColumnInSeriesOperation<Void> {
private static final long serialVersionUID = -1923159034843767105L;
public RemoveColumnFromSeries(RegattaIdentifier regattaIdentifier, String seriesName, String columnName) {
super(regattaIdentifier, seriesName, columnName);
}
@Override
public Void internalApplyTo(RacingEventService toState) throws Exception {
Series series = getSeries(toState);
if (series != null) {
series.removeRaceColumn(getColumnName());
}
return null;
}
@Override
public RacingEventServiceOperation<?> transformClientOp(RacingEventServiceOperation<?> serverOp) {
// TODO Auto-generated method stub
return null;
}
@Override
public RacingEventServiceOperation<?> transformServerOp(RacingEventServiceOperation<?> clientOp) {
// TODO Auto-generated method stub
return null;
}
}