mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-27 06:17:27 +00:00
removed the tests that tested only StoreAndForward which is no longer needed for the new SwissTiming architecture;
SwissTiming will be providing an "SAP Gateway" which stores messages for us. We'll be able to query messages even for a live race, using an "LSN" message sent to the gateway. Therefore, StoreAndForward as well as the tests specific to this architecture are no longer required. The remaining tests are all green now.
This commit is contained in:
1 parent
54bcc75920
commit
1e4544ba50
25 files changed
+29
-1677
No files matched your search
@@ -1,13 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication">
|
||||
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
|
||||
<listEntry value="/com.sap.sailing.domain.swisstimingadapter.persistence/src/com/sap/sailing/domain/swisstimingadapter/persistence/StoreAndForward.java"/>
|
||||
</listAttribute>
|
||||
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
|
||||
<listEntry value="1"/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.sap.sailing.domain.swisstimingadapter.persistence.StoreAndForward"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="3500 3501"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.domain.swisstimingadapter.persistence"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Djava.util.logging.config.file=${project_loc:com.sap.sailing.server}/../target/configuration/logging_debug.properties"/>
|
||||
</launchConfiguration>
|
||||
-437
@@ -1,437 +0,0 @@
|
||||
package com.sap.sailing.domain.swisstimingadapter.persistence;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DB;
|
||||
import com.mongodb.DBCollection;
|
||||
import com.mongodb.DBObject;
|
||||
import com.sap.sailing.domain.common.impl.Util.Pair;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SailMasterMessage;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SailMasterTransceiver;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SwissTimingFactory;
|
||||
import com.sap.sailing.domain.swisstimingadapter.persistence.impl.CollectionNames;
|
||||
import com.sap.sailing.domain.swisstimingadapter.persistence.impl.FieldNames;
|
||||
import com.sap.sailing.mongodb.MongoDBConfiguration;
|
||||
import com.sap.sailing.mongodb.MongoDBService;
|
||||
|
||||
/**
|
||||
* Receives events from a SwissTiming SailMaster server, stores valid messages received persistently and forward them
|
||||
* to a port specified. The messages forwarded are augmented by sending a counter in ASCII encoding before the
|
||||
* message's <code>STX</code> start byte. This allows a receiver to optionally record the counter value after
|
||||
* having processed the message. When messages have to be retrieved from the database at a later point, a
|
||||
* client can request only those message starting at a specific counter value.<p>
|
||||
*
|
||||
* The connectivity to the SailMaster system can operate in one of two modes. Either a TCP connection to the
|
||||
* SailMaster is initiated by this client. When the connection is lost or a connect is unsuccessful, the client
|
||||
* will try again periodically. In the other mode of operation, this client will act as a TCP server and accepts
|
||||
* inbound requests from the SailMaster system (typically a bridge that forwards messages from multiple
|
||||
* SailMaster systems). In this mode of operation it's up to the SailMaster environment to re-initiate
|
||||
* connects after a connection loss.
|
||||
*
|
||||
* @author Axel Uhl (d043530)
|
||||
*
|
||||
*/
|
||||
public class StoreAndForward implements Runnable {
|
||||
private static final Logger logger = Logger.getLogger(StoreAndForward.class.getName());
|
||||
|
||||
private final DB db;
|
||||
private final int listenPort;
|
||||
private final SailMasterTransceiver transceiver;
|
||||
private final int portForClients;
|
||||
private long lastMessageCount;
|
||||
private boolean stopped;
|
||||
private final Thread clientListener;
|
||||
private final List<Socket> socketsToForwardTo;
|
||||
private final List<OutputStream> streamsToForwardTo;
|
||||
private boolean listeningForClients;
|
||||
private boolean receivingFromSailMaster;
|
||||
|
||||
private final DBCollection lastMessageCountCollection;
|
||||
|
||||
private final SwissTimingAdapterPersistence swissTimingAdapterPersistence;
|
||||
|
||||
private final SwissTimingFactory swissTimingFactory;
|
||||
|
||||
private final Thread storeAndForwardThread;
|
||||
|
||||
private final Set<ReceivingThread> receivingThreads;
|
||||
|
||||
/**
|
||||
* Use of this server socket is optional and happens if and only if this object is operated in
|
||||
* "listening" mode. This means that the SailMaster system / bridge is expected to initiate TCP
|
||||
* connections to this object.
|
||||
*/
|
||||
private ServerSocket serverSocketListeningForSailMasterBridge;
|
||||
|
||||
private final int sailMasterPort;
|
||||
|
||||
private final String sailMasterHostname;
|
||||
|
||||
/**
|
||||
* When initialized using this constructor, the resulting object proactively connects and re-connects to the
|
||||
* SailMaster server specified by <code>sailMasterHostname</code>/<code>sailMasterPort</code>. The
|
||||
* {@link #serverSocketListeningForSailMasterBridge} remains <code>null</code> and {@link #listenPort} is set
|
||||
* to <code>-1</code>, indicating that this object is not listening on any port for incoming
|
||||
* SailMaster connections.
|
||||
*/
|
||||
public StoreAndForward(String sailMasterHostname, int sailMasterPort, int portForClients, SwissTimingFactory swissTimingFactory,
|
||||
SwissTimingAdapterPersistence swissTimingAdapterPersistence, MongoDBService mongoDBService) throws InterruptedException, IOException {
|
||||
this.receivingThreads = new HashSet<>();
|
||||
this.db = mongoDBService.getDB();
|
||||
this.listenPort = -1;
|
||||
this.transceiver = swissTimingFactory.createSailMasterTransceiver();
|
||||
this.portForClients = portForClients;
|
||||
this.sailMasterHostname = sailMasterHostname;
|
||||
this.sailMasterPort = sailMasterPort;
|
||||
this.streamsToForwardTo = Collections.synchronizedList(new ArrayList<OutputStream>());
|
||||
this.socketsToForwardTo = new ArrayList<Socket>();
|
||||
this.swissTimingAdapterPersistence = swissTimingAdapterPersistence;
|
||||
this.swissTimingFactory = swissTimingFactory;
|
||||
lastMessageCountCollection = db.getCollection(CollectionNames.LAST_MESSAGE_COUNT.name());
|
||||
lastMessageCount = getLastMessageCount();
|
||||
clientListener = createClientListenerThread(portForClients);
|
||||
clientListener.start();
|
||||
storeAndForwardThread = new Thread(this, "StoreAndForward");
|
||||
storeAndForwardThread.start();
|
||||
synchronized (this) {
|
||||
while (!listeningForClients) {
|
||||
wait();
|
||||
}
|
||||
while (!receivingFromSailMaster) {
|
||||
wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a storing message forwarder in listening mode. In this mode, this object won't actively try to open
|
||||
* TCP connections to a SailMaster system / bridge but instead listen for inbound TCP connections on port
|
||||
* <code>listenPort</code>.
|
||||
*
|
||||
* @param listenPort
|
||||
* listens on this port for messages coming in from a real SwissTiming SailMaster
|
||||
* @param portForClients
|
||||
* clients can connect to this port and will receive forwarded and sequence-numbered messages over those
|
||||
* sockets
|
||||
* @throws IOException
|
||||
*/
|
||||
public StoreAndForward(final int listenPort, final int portForClients, SwissTimingFactory swissTimingFactory,
|
||||
SwissTimingAdapterPersistence swissTimingAdapterPersistence, MongoDBService mongoDBService) throws InterruptedException, IOException {
|
||||
this.receivingThreads = new HashSet<>();
|
||||
this.db = mongoDBService.getDB();
|
||||
this.listenPort = listenPort;
|
||||
this.transceiver = swissTimingFactory.createSailMasterTransceiver();
|
||||
this.portForClients = portForClients;
|
||||
this.streamsToForwardTo = Collections.synchronizedList(new ArrayList<OutputStream>());
|
||||
this.socketsToForwardTo = new ArrayList<Socket>();
|
||||
this.swissTimingAdapterPersistence = swissTimingAdapterPersistence;
|
||||
this.swissTimingFactory = swissTimingFactory;
|
||||
this.sailMasterHostname = null;
|
||||
this.sailMasterPort = -1;
|
||||
lastMessageCountCollection = db.getCollection(CollectionNames.LAST_MESSAGE_COUNT.name());
|
||||
lastMessageCount = getLastMessageCount();
|
||||
serverSocketListeningForSailMasterBridge = new ServerSocket(listenPort);
|
||||
clientListener = createClientListenerThread(portForClients);
|
||||
clientListener.start();
|
||||
storeAndForwardThread = new Thread(this, "StoreAndForward");
|
||||
storeAndForwardThread.start();
|
||||
synchronized (this) {
|
||||
while (!listeningForClients) {
|
||||
wait();
|
||||
}
|
||||
while (!receivingFromSailMaster) {
|
||||
wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private long getLastMessageCount() {
|
||||
DBObject lastMessageCountRecord = lastMessageCountCollection.findOne();
|
||||
if (lastMessageCountRecord == null) {
|
||||
lastMessageCountCollection.insert(new BasicDBObject().append(FieldNames.LAST_MESSAGE_COUNT.name(), 0l));
|
||||
}
|
||||
return lastMessageCountRecord == null ? 0 : ((Number) lastMessageCountRecord.get(FieldNames.LAST_MESSAGE_COUNT.name())).longValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if and only if this object is listening for incoming SailMaster TCP
|
||||
* connections instead of actively connecting / reconnecting to a SailMaster server by itself.
|
||||
*/
|
||||
private boolean isInSailMasterListeningMode() {
|
||||
return serverSocketListeningForSailMasterBridge != null;
|
||||
}
|
||||
|
||||
private Thread createClientListenerThread(final int portForClients) {
|
||||
return new Thread(new Runnable() {
|
||||
public void run() {
|
||||
ServerSocket ss;
|
||||
try {
|
||||
synchronized (StoreAndForward.this) {
|
||||
ss = new ServerSocket(portForClients);
|
||||
listeningForClients = true;
|
||||
logger.info("StoreAndForward listening for clients on port "+portForClients);
|
||||
StoreAndForward.this.notifyAll();
|
||||
}
|
||||
while (!stopped) {
|
||||
Socket s = ss.accept();
|
||||
logger.info("StoreAndForward received connector's connect request on port "+portForClients);
|
||||
if (!stopped) {
|
||||
synchronized (StoreAndForward.this) {
|
||||
socketsToForwardTo.add(s);
|
||||
streamsToForwardTo.add(s.getOutputStream());
|
||||
}
|
||||
} else {
|
||||
s.close();
|
||||
}
|
||||
}
|
||||
ss.close();
|
||||
logger.info("StoreAndForward client listener thread stopped.");
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}, "StoreAndForwardClientListener");
|
||||
}
|
||||
|
||||
/**
|
||||
* Depending on the mode of operation, accepts an inbound connect from a SailMaster server / bridge or actively
|
||||
* initiates a TCP connection to the SailMaster address/port configured. When a connection has been established, a
|
||||
* new {@link ReceivingThread} is spawned for the new socket. If in listening mode, the
|
||||
* {@link ServerSocket#accept()} call is repeated until the instance is {@link #stop()}ed.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
private ReceivingThread establishConnection() throws IOException {
|
||||
Socket socket;
|
||||
ReceivingThread receivingThread = null;
|
||||
if (isInSailMasterListeningMode()) {
|
||||
while (!stopped) {
|
||||
synchronized (this) {
|
||||
receivingFromSailMaster = true;
|
||||
logger.info("StoreAndForward waiting for inbound SailMaster connections on port " + listenPort);
|
||||
notifyAll();
|
||||
}
|
||||
socket = serverSocketListeningForSailMasterBridge.accept();
|
||||
logger.info("StoreAndForward received SailMaster connect on port " + listenPort);
|
||||
receivingThread = new ReceivingThread("SwissTiming SailMaster ReceivingThread for "+socket, socket);
|
||||
receivingThreads.add(receivingThread);
|
||||
receivingThread.start();
|
||||
}
|
||||
} else {
|
||||
synchronized (this) {
|
||||
receivingFromSailMaster = true;
|
||||
logger.info("StoreAndForward issuing SailMaster connection to "+sailMasterHostname+":"+sailMasterPort);
|
||||
notifyAll();
|
||||
}
|
||||
socket = new Socket(sailMasterHostname, sailMasterPort);
|
||||
logger.info("StoreAndForward connections to SailMaster "+sailMasterHostname+":"+sailMasterPort+" established");
|
||||
receivingThread = new ReceivingThread("SwissTiming SailMaster ReceivingThread for "+socket, socket);
|
||||
receivingThreads.add(receivingThread);
|
||||
receivingThread.start();
|
||||
}
|
||||
return receivingThread;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the actual receiving. Is initialized with the socket on which to receive.
|
||||
*
|
||||
* @author Axel Uhl (D043530)
|
||||
*
|
||||
*/
|
||||
private class ReceivingThread extends Thread {
|
||||
private final Socket socket;
|
||||
private boolean stopped;
|
||||
|
||||
public ReceivingThread(String threadName, Socket socket) {
|
||||
super(threadName);
|
||||
this.socket = socket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
logger.entering(getClass().getName(), "run");
|
||||
while (!stopped) {
|
||||
try {
|
||||
InputStream is = socket.getInputStream();
|
||||
try {
|
||||
Pair<String, Long> messageAndOptionalSequenceNumber = transceiver.receiveMessage(is);
|
||||
if (messageAndOptionalSequenceNumber == null) {
|
||||
// found EOF; stopping
|
||||
stopped = true;
|
||||
} else {
|
||||
// ignore any sequence number contained in the message; we'll create our own
|
||||
DBObject emptyQuery = new BasicDBObject();
|
||||
DBObject incrementLastMessageCountQuery = new BasicDBObject().append("$inc",
|
||||
new BasicDBObject().append(FieldNames.LAST_MESSAGE_COUNT.name(), 1));
|
||||
while (!stopped && messageAndOptionalSequenceNumber != null) {
|
||||
logger.fine("Thread " + this + " received message: "
|
||||
+ messageAndOptionalSequenceNumber.getA());
|
||||
DBObject newCountRecord = lastMessageCountCollection.findAndModify(emptyQuery,
|
||||
incrementLastMessageCountQuery);
|
||||
lastMessageCount = ((newCountRecord == null) ? 0l : ((Number) newCountRecord
|
||||
.get(FieldNames.LAST_MESSAGE_COUNT.name())).longValue());
|
||||
SailMasterMessage message = swissTimingFactory.createMessage(
|
||||
messageAndOptionalSequenceNumber.getA(), lastMessageCount);
|
||||
swissTimingAdapterPersistence.storeSailMasterMessage(message);
|
||||
synchronized (StoreAndForward.this) {
|
||||
for (OutputStream os : new ArrayList<OutputStream>(streamsToForwardTo)) {
|
||||
// write the sequence number of the message into the stream before actually
|
||||
// writing
|
||||
// the
|
||||
// SwissTiming message
|
||||
try {
|
||||
transceiver.sendMessage(message, os);
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "Error sending message to " + os, e);
|
||||
int i = streamsToForwardTo.indexOf(os);
|
||||
try {
|
||||
os.close();
|
||||
} catch (Exception exc) {
|
||||
logger.log(Level.SEVERE, "Exception closing socket output stream " + os
|
||||
+ " after being unable to forward message " + message, exc);
|
||||
}
|
||||
streamsToForwardTo.remove(os);
|
||||
Socket s = socketsToForwardTo.remove(i);
|
||||
logger.info("Unable to send to socket " + s
|
||||
+ ". Trying to close. Removing from sockets to forward to.");
|
||||
try {
|
||||
s.close();
|
||||
} catch (Exception exc) {
|
||||
logger.log(Level.WARNING, "Exception trying to close socket " + s
|
||||
+ " after being unable to forward message " + message, exc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!stopped) {
|
||||
messageAndOptionalSequenceNumber = transceiver.receiveMessage(is);
|
||||
if (messageAndOptionalSequenceNumber == null) {
|
||||
// received EOF; stopping received
|
||||
stopped = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (SocketException e) {
|
||||
logger.log(
|
||||
Level.INFO,
|
||||
"Error during receiving message. Terminating this receiver and waiting for another inbound connection.",
|
||||
e);
|
||||
stopped = true;
|
||||
}
|
||||
// note that we're not changing anything with the sockets to which we forward messages; that will only happen
|
||||
// if forwarding to any of those sockets fails
|
||||
} catch (Exception e) {
|
||||
if (!stopped) {
|
||||
logger.log(Level.INFO, "Error during forwarding message. Continuing...", e);
|
||||
try {
|
||||
Thread.sleep(1000l); // wait a little bit before trying to re-establish a connection
|
||||
} catch (InterruptedException e1) {
|
||||
logger.log(Level.INFO, "Can't find any sleep...", e1);
|
||||
}
|
||||
} else {
|
||||
logger.info("StoreAndForward socket was closed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
logger.info("Terminating StoreAndForward ReceivingThread for socket "+socket);
|
||||
receivingThreads.remove(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops execution after having received the next message
|
||||
*/
|
||||
public void stopReceiver() throws UnknownHostException, IOException, InterruptedException {
|
||||
logger.entering(getClass().getName(), "stop");
|
||||
stopped = true;
|
||||
logger.info("closing socket");
|
||||
socket.close(); // will let a read terminate abnormally
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops execution after having received the next message
|
||||
*/
|
||||
public void stop() throws UnknownHostException, IOException, InterruptedException {
|
||||
logger.entering(getClass().getName(), "stop");
|
||||
stopped = true;
|
||||
Socket closer = new Socket("localhost", portForClients); // this is to stop the client listener thread
|
||||
closer.close();
|
||||
logger.info("joining clientListener thread "+clientListener);
|
||||
clientListener.join();
|
||||
for (ReceivingThread receivingThread : receivingThreads) {
|
||||
receivingThread.stopReceiver();
|
||||
logger.info("joining storeAndForwardThread "+storeAndForwardThread);
|
||||
receivingThread.join();
|
||||
}
|
||||
logger.info("StoreAndForward is closing receiving server socket");
|
||||
if (serverSocketListeningForSailMasterBridge != null && !serverSocketListeningForSailMasterBridge.isClosed()) {
|
||||
serverSocketListeningForSailMasterBridge.close();
|
||||
}
|
||||
logger.info("Stopping StoreAndForward server.");
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws InterruptedException, IOException {
|
||||
String hostname = null;
|
||||
int i=0;
|
||||
if (args[i].equals("-h")) {
|
||||
hostname = args[++i];
|
||||
i++;
|
||||
}
|
||||
int sailMasterPort = Integer.valueOf(args[i++]);
|
||||
int clientPort = Integer.valueOf(args[i++]);
|
||||
|
||||
MongoDBService mongoDBService = MongoDBConfiguration.getDefaultConfiguration().getService();
|
||||
SwissTimingAdapterPersistence swissTimingAdapterPersistence = SwissTimingAdapterPersistence.INSTANCE;
|
||||
if (hostname == null) {
|
||||
new StoreAndForward(sailMasterPort, clientPort, SwissTimingFactory.INSTANCE, swissTimingAdapterPersistence, mongoDBService);
|
||||
} else {
|
||||
new StoreAndForward(hostname, sailMasterPort, clientPort, SwissTimingFactory.INSTANCE, swissTimingAdapterPersistence, mongoDBService);
|
||||
}
|
||||
}
|
||||
|
||||
public void run() {
|
||||
logger.entering(getClass().getName(), "run");
|
||||
try {
|
||||
while (!stopped) {
|
||||
try {
|
||||
ReceivingThread receivingThread = establishConnection();
|
||||
if (!isInSailMasterListeningMode()) {
|
||||
receivingThread.join(); // we're in active connecting mode; wait for thread to die, then try again
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "Exception in StoreAndForward", e);
|
||||
try {
|
||||
Thread.sleep(100); // if the exception persists, wait a little, hoping something may recover
|
||||
} catch (InterruptedException e1) {
|
||||
logger.log(Level.INFO, "StoreAndForward.run interrupted; setting stopped=true", e1);
|
||||
stopped = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
logger.info("StoreAndForward is closing receiving server socket");
|
||||
if (serverSocketListeningForSailMasterBridge != null && !serverSocketListeningForSailMasterBridge.isClosed()) {
|
||||
serverSocketListeningForSailMasterBridge.close();
|
||||
}
|
||||
logger.info("Stopping StoreAndForward server.");
|
||||
} catch (IOException e) {
|
||||
logger.throwing(getClass().getName(), "run", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
logger.exiting(getClass().getName(), "run");
|
||||
}
|
||||
}
|
||||
+3
-6
@@ -132,8 +132,7 @@ public class SwissTimingAdapterPersistenceImpl implements SwissTimingAdapterPers
|
||||
DBCursor results = commandMessages.find(query);
|
||||
List<SailMasterMessage> result = new ArrayList<SailMasterMessage>();
|
||||
for (DBObject o : results) {
|
||||
result.add(swissTimingFactory.createMessage((String) o.get(FieldNames.MESSAGE_CONTENT.name()),
|
||||
(Long) o.get(FieldNames.MESSAGE_SEQUENCE_NUMBER.name())));
|
||||
result.add(swissTimingFactory.createMessage((String) o.get(FieldNames.MESSAGE_CONTENT.name())));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -148,8 +147,7 @@ public class SwissTimingAdapterPersistenceImpl implements SwissTimingAdapterPers
|
||||
new BasicDBObject().append(FieldNames.MESSAGE_SEQUENCE_NUMBER.name(), 1));
|
||||
List<SailMasterMessage> result = new ArrayList<SailMasterMessage>();
|
||||
for (DBObject o : results) {
|
||||
SailMasterMessage msg = swissTimingFactory.createMessage((String) o.get(FieldNames.MESSAGE_CONTENT.name()),
|
||||
((Number) o.get(FieldNames.MESSAGE_SEQUENCE_NUMBER.name())).longValue());
|
||||
SailMasterMessage msg = swissTimingFactory.createMessage((String) o.get(FieldNames.MESSAGE_CONTENT.name()));
|
||||
result.add(msg);
|
||||
}
|
||||
return result;
|
||||
@@ -162,8 +160,7 @@ public class SwissTimingAdapterPersistenceImpl implements SwissTimingAdapterPers
|
||||
new BasicDBObject().append(FieldNames.MESSAGE_SEQUENCE_NUMBER.name(), 1));
|
||||
List<SailMasterMessage> result = new ArrayList<SailMasterMessage>();
|
||||
for (DBObject o : results) {
|
||||
SailMasterMessage msg = swissTimingFactory.createMessage((String) o.get(FieldNames.MESSAGE_CONTENT.name()),
|
||||
(Long) o.get(FieldNames.MESSAGE_SEQUENCE_NUMBER.name()));
|
||||
SailMasterMessage msg = swissTimingFactory.createMessage((String) o.get(FieldNames.MESSAGE_CONTENT.name()));
|
||||
result.add(msg);
|
||||
}
|
||||
return result;
|
||||
|
||||
-156
@@ -1,156 +0,0 @@
|
||||
package com.sap.sailing.domain.swisstimingadapter.test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.BindException;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.Timeout;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DB;
|
||||
import com.mongodb.DBCollection;
|
||||
import com.sap.sailing.domain.swisstimingadapter.Race;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SailMasterAdapter;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SailMasterConnector;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SailMasterMessage;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SailMasterTransceiver;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SwissTimingFactory;
|
||||
import com.sap.sailing.domain.swisstimingadapter.persistence.StoreAndForward;
|
||||
import com.sap.sailing.domain.swisstimingadapter.persistence.SwissTimingAdapterPersistence;
|
||||
import com.sap.sailing.domain.swisstimingadapter.persistence.impl.CollectionNames;
|
||||
import com.sap.sailing.domain.swisstimingadapter.persistence.impl.FieldNames;
|
||||
import com.sap.sailing.mongodb.MongoDBService;
|
||||
|
||||
public class ActivelyConnectingStoreAndForwardTest {
|
||||
private static final Logger logger = Logger.getLogger(ActivelyConnectingStoreAndForwardTest.class.getName());
|
||||
|
||||
private static final int RECEIVE_PORT = 6543;
|
||||
private static final int CLIENT_PORT = 6544;
|
||||
|
||||
private DB db;
|
||||
private StoreAndForward storeAndForward;
|
||||
private Socket sendingSocket;
|
||||
private OutputStream sendingStream;
|
||||
private SailMasterTransceiver transceiver;
|
||||
private SailMasterConnector connector;
|
||||
private SwissTimingAdapterPersistence swissTimingAdapterPersistence;
|
||||
private SwissTimingFactory swissTimingFactory;
|
||||
|
||||
private Thread sailMasterDummyListenerThread;
|
||||
|
||||
@Rule public Timeout AbstractTracTracLiveTestTimeout = new Timeout(5 * 60 * 1000); // timeout after 5 minutes
|
||||
|
||||
@Before
|
||||
public void setUp() throws UnknownHostException, IOException, InterruptedException {
|
||||
MongoDBService mongoDBService = MongoDBService.INSTANCE;
|
||||
db = mongoDBService.getDB();
|
||||
sailMasterDummyListenerThread = new Thread("ActivelyConnectingStoreAndForwardTest-Listener") {
|
||||
public void run() {
|
||||
try {
|
||||
ServerSocket ss = null;
|
||||
for (int numberOfTries=0; numberOfTries<3 && ss == null; numberOfTries++) {
|
||||
try {
|
||||
ss = new ServerSocket(RECEIVE_PORT);
|
||||
} catch (BindException be) {
|
||||
logger.log(Level.INFO, "Couldn't bind server socket in StoreAndForward"+
|
||||
(numberOfTries<2?". Trying again...":""), be);
|
||||
if (numberOfTries == 2) {
|
||||
throw be;
|
||||
}
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
synchronized (ActivelyConnectingStoreAndForwardTest.this) {
|
||||
sendingSocket = ss.accept();
|
||||
logger.info("ActivelyConnectingStoreAndForwardTest-Listener accepted socket connect request on port "+RECEIVE_PORT);
|
||||
sendingStream = sendingSocket.getOutputStream();
|
||||
ActivelyConnectingStoreAndForwardTest.this.notifyAll();
|
||||
}
|
||||
logger.info("ActivelyConnectingStoreAndForwardTest-Listener closing server socket on port "+RECEIVE_PORT);
|
||||
ss.close();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
sailMasterDummyListenerThread.start();
|
||||
swissTimingAdapterPersistence = SwissTimingAdapterPersistence.INSTANCE;
|
||||
swissTimingAdapterPersistence.dropAllMessageData();
|
||||
storeAndForward = new StoreAndForward("localhost", RECEIVE_PORT, CLIENT_PORT, SwissTimingFactory.INSTANCE,
|
||||
swissTimingAdapterPersistence, mongoDBService);
|
||||
synchronized (this) {
|
||||
while (sendingStream == null) {
|
||||
wait();
|
||||
}
|
||||
}
|
||||
swissTimingFactory = SwissTimingFactory.INSTANCE;
|
||||
transceiver = swissTimingFactory.createSailMasterTransceiver();
|
||||
connector = swissTimingFactory.getOrCreateSailMasterConnector("localhost", CLIENT_PORT, null, /* canSendRequests */ true); // will connect to RECEIVE_PORT
|
||||
DBCollection lastMessageCountCollection = db.getCollection(CollectionNames.LAST_MESSAGE_COUNT.name());
|
||||
lastMessageCountCollection.update(new BasicDBObject(), new BasicDBObject().append(FieldNames.LAST_MESSAGE_COUNT.name(), 0l),
|
||||
/* upsert */ true, /* multi */ false);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws InterruptedException, IOException {
|
||||
logger.entering(getClass().getName(), "tearDown");
|
||||
storeAndForward.stop();
|
||||
sailMasterDummyListenerThread.join();
|
||||
connector.stop();
|
||||
logger.exiting(getClass().getName(), "tearDown");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleRACMessage() throws IOException, InterruptedException {
|
||||
final List<Race> racesReceived = new ArrayList<Race>();
|
||||
final boolean[] receivedSomething = new boolean[1];
|
||||
connector.addSailMasterListener(new SailMasterAdapter() {
|
||||
@Override
|
||||
public void receivedAvailableRaces(Iterable<Race> races) {
|
||||
for (Race race : races) {
|
||||
racesReceived.add(race);
|
||||
}
|
||||
synchronized (ActivelyConnectingStoreAndForwardTest.this) {
|
||||
receivedSomething[0] = true;
|
||||
ActivelyConnectingStoreAndForwardTest.this.notifyAll();
|
||||
}
|
||||
}
|
||||
});
|
||||
String rawMessage = "0|RAC|2|c34c423c-0295-4fe5-91ca-336681624711;A wonderful test race|c34c423c-0295-4fe5-91ca-336681624712;Not such a wonderful race";
|
||||
transceiver.sendMessage(rawMessage, sendingStream);
|
||||
synchronized (this) {
|
||||
for (int i=0; i<1000 && !receivedSomething[0]; i++) {
|
||||
wait(100l); // wait for 1/10 of a second (up to 1000 times = 100s) to receive the message
|
||||
}
|
||||
}
|
||||
assertTrue(receivedSomething[0]);
|
||||
assertEquals(2, racesReceived.size());
|
||||
db.getLastError(); // synchronize on DB and wait for last write to have completed
|
||||
DBCollection lastMessageCountCollection = db.getCollection(CollectionNames.LAST_MESSAGE_COUNT.name());
|
||||
Long lastMessageCount = (Long) lastMessageCountCollection.findOne().get(FieldNames.LAST_MESSAGE_COUNT.name());
|
||||
assertEquals((Long) 1l, lastMessageCount);
|
||||
List<SailMasterMessage> rawMessages = swissTimingAdapterPersistence.loadCommandMessages(0);
|
||||
assertEquals(1, rawMessages.size());
|
||||
assertEquals(rawMessage, rawMessages.get(0).getMessage());
|
||||
assertEquals(0l, (long) rawMessages.get(0).getSequenceNumber());
|
||||
}
|
||||
|
||||
}
|
||||
-411
@@ -1,411 +0,0 @@
|
||||
package com.sap.sailing.domain.swisstimingadapter.test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.BindException;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.Timeout;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DB;
|
||||
import com.mongodb.DBCollection;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.Mark;
|
||||
import com.sap.sailing.domain.base.RaceDefinition;
|
||||
import com.sap.sailing.domain.base.Regatta;
|
||||
import com.sap.sailing.domain.base.Waypoint;
|
||||
import com.sap.sailing.domain.common.TrackedRaceStatusEnum;
|
||||
import com.sap.sailing.domain.common.impl.Util;
|
||||
import com.sap.sailing.domain.persistence.PersistenceFactory;
|
||||
import com.sap.sailing.domain.persistence.media.MediaDB;
|
||||
import com.sap.sailing.domain.racelog.impl.EmptyRaceLogStore;
|
||||
import com.sap.sailing.domain.swisstimingadapter.MessageType;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SailMasterConnector;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SailMasterTransceiver;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SwissTimingAdapter;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SwissTimingFactory;
|
||||
import com.sap.sailing.domain.swisstimingadapter.impl.SwissTimingAdapterFactoryImpl;
|
||||
import com.sap.sailing.domain.swisstimingadapter.persistence.StoreAndForward;
|
||||
import com.sap.sailing.domain.swisstimingadapter.persistence.SwissTimingAdapterPersistence;
|
||||
import com.sap.sailing.domain.swisstimingadapter.persistence.impl.CollectionNames;
|
||||
import com.sap.sailing.domain.swisstimingadapter.persistence.impl.FieldNames;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRegatta;
|
||||
import com.sap.sailing.domain.tracking.GPSFix;
|
||||
import com.sap.sailing.domain.tracking.GPSFixMoving;
|
||||
import com.sap.sailing.domain.tracking.GPSFixTrack;
|
||||
import com.sap.sailing.domain.tracking.MarkPassing;
|
||||
import com.sap.sailing.domain.tracking.RacesHandle;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.domain.tracking.impl.EmptyWindStore;
|
||||
import com.sap.sailing.domain.tracking.impl.TrackedRaceStatusImpl;
|
||||
import com.sap.sailing.mongodb.MongoDBService;
|
||||
import com.sap.sailing.server.RacingEventService;
|
||||
import com.sap.sailing.server.impl.RacingEventServiceImpl;
|
||||
|
||||
public class EndToEndListeningStoreAndFowardTest {
|
||||
private static final Logger logger = Logger.getLogger(EndToEndListeningStoreAndFowardTest.class.getName());
|
||||
|
||||
private static final int RECEIVE_PORT = 6543;
|
||||
private static final int CLIENT_PORT = 6544;
|
||||
|
||||
private DB db;
|
||||
private StoreAndForward storeAndForward;
|
||||
private Socket sendingSocket;
|
||||
private OutputStream sendingStream;
|
||||
private SailMasterTransceiver transceiver;
|
||||
private SailMasterConnector connector;
|
||||
private SwissTimingAdapterPersistence swissTimingAdapterPersistence;
|
||||
private SwissTimingFactory swissTimingFactory;
|
||||
|
||||
private EmptyRaceLogStore emptyRaceLogStore;
|
||||
private RacingEventService racingEventService;
|
||||
private SwissTimingAdapter swissTimingAdapter;
|
||||
private List<RacesHandle> raceHandles;
|
||||
|
||||
@Rule public Timeout AbstractTracTracLiveTestTimeout = new Timeout(5 * 60 * 1000); // timeout after 5 minutes
|
||||
|
||||
@Before
|
||||
public void setUp() throws UnknownHostException, IOException, InterruptedException {
|
||||
logger.info("EndToEndListeningStoreAndFowardTest.setUp");
|
||||
MongoDBService mongoDBService = MongoDBService.INSTANCE;
|
||||
db = mongoDBService.getDB();
|
||||
db.getCollection(com.sap.sailing.domain.persistence.impl.CollectionNames.REGATTAS.name()).drop();
|
||||
swissTimingAdapterPersistence = SwissTimingAdapterPersistence.INSTANCE;
|
||||
swissTimingAdapterPersistence.dropAllMessageData();
|
||||
swissTimingAdapterPersistence.dropAllRaceMasterData();
|
||||
storeAndForward = null;
|
||||
for (int numberOfTries = 0; numberOfTries < 3 && storeAndForward == null; numberOfTries++) {
|
||||
try {
|
||||
storeAndForward = new StoreAndForward(RECEIVE_PORT, CLIENT_PORT, SwissTimingFactory.INSTANCE,
|
||||
swissTimingAdapterPersistence, mongoDBService);
|
||||
} catch (BindException be) {
|
||||
logger.log(Level.INFO, "Couldn't bind server socket in StoreAndForward"+
|
||||
(numberOfTries<2?". Trying again...":""), be);
|
||||
if (numberOfTries == 2) {
|
||||
throw be;
|
||||
}
|
||||
Thread.sleep(100);
|
||||
}
|
||||
}
|
||||
sendingSocket = new Socket("localhost", RECEIVE_PORT);
|
||||
sendingStream = sendingSocket.getOutputStream();
|
||||
swissTimingFactory = SwissTimingFactory.INSTANCE;
|
||||
EmptyWindStore emptyWindStore = EmptyWindStore.INSTANCE;
|
||||
emptyRaceLogStore = EmptyRaceLogStore.INSTANCE;
|
||||
transceiver = swissTimingFactory.createSailMasterTransceiver();
|
||||
DBCollection lastMessageCountCollection = db.getCollection(CollectionNames.LAST_MESSAGE_COUNT.name());
|
||||
lastMessageCountCollection.update(new BasicDBObject(),
|
||||
new BasicDBObject().append(FieldNames.LAST_MESSAGE_COUNT.name(), 0l),
|
||||
/* upsert */true, /* multi */false);
|
||||
// important: construct a new domain factory each time to make sure the competitor cache starts out empty
|
||||
final com.sap.sailing.domain.base.impl.DomainFactoryImpl baseDomainFactory = new com.sap.sailing.domain.base.impl.DomainFactoryImpl();
|
||||
swissTimingAdapter = new SwissTimingAdapterFactoryImpl().getOrCreateSwissTimingAdapter(baseDomainFactory, swissTimingAdapterPersistence);
|
||||
racingEventService = new RacingEventServiceImpl(PersistenceFactory.INSTANCE.getDomainObjectFactory(
|
||||
mongoDBService, baseDomainFactory), PersistenceFactory.INSTANCE.getMongoObjectFactory(mongoDBService), MediaDB.TEST_STUB, emptyWindStore);
|
||||
raceHandles = new ArrayList<RacesHandle>();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws InterruptedException, IOException {
|
||||
logger.entering(getClass().getName(), "tearDown");
|
||||
for (RacesHandle raceHandle : raceHandles) {
|
||||
racingEventService.stopTracking(raceHandle.getRegatta());
|
||||
}
|
||||
logger.info("Calling StoreAndForward.stop() in tearDown");
|
||||
if (storeAndForward != null) {
|
||||
storeAndForward.stop();
|
||||
}
|
||||
logger.exiting(getClass().getName(), "tearDown");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEndToEndScenarioWithInitMessages() throws Exception {
|
||||
String[] racesToTrack = new String[] { "c34c423c-0295-4fe5-91ca-336681624711", "c34c423c-0295-4fe5-91ca-336681624712" };
|
||||
String scriptName = "/InitMessagesScript.txt";
|
||||
setUpUsingScript(racesToTrack, scriptName);
|
||||
|
||||
Set<TrackedRace> allTrackedRaces = getAllTrackedRaces();
|
||||
assertEquals(2, Util.size(allTrackedRaces));
|
||||
Set<String> raceIDs = new HashSet<String>();
|
||||
for (TrackedRace trackedRace : allTrackedRaces) {
|
||||
RaceDefinition race = trackedRace.getRace();
|
||||
raceIDs.add(race.getName());
|
||||
}
|
||||
Set<String> expectedRaceIDs = new HashSet<String>();
|
||||
for (String raceIDToTrack : new String[] { "c34c423c-0295-4fe5-91ca-336681624711", "c34c423c-0295-4fe5-91ca-336681624712" }) {
|
||||
expectedRaceIDs.add(raceIDToTrack);
|
||||
}
|
||||
assertEquals(expectedRaceIDs, raceIDs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLongRaceLog() throws Exception {
|
||||
String[] racesToTrack = new String[] { "c34c423c-0295-4fe5-91ca-336681624702" };
|
||||
String scriptName1 = "/SailMasterDataInterfaceRACandSTL.txt";
|
||||
String scriptName2 = "/SailMasterDataInterface-ExampleAsText.txt";
|
||||
setUpUsingScript(racesToTrack, scriptName1, scriptName2);
|
||||
coreOfTestLongRaceLog();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLongRaceLogNewVersion() throws Exception {
|
||||
String[] racesToTrack = new String[] { "c34c423c-0295-4fe5-91ca-336681624702" };
|
||||
String scriptName1 = "/W4702RACandSTLandCCG.txt";
|
||||
String scriptName2 = "/W4702AsText.txt";
|
||||
setUpUsingScript(racesToTrack, scriptName1, scriptName2);
|
||||
coreOfTestLongRaceLog();
|
||||
}
|
||||
|
||||
private void coreOfTestLongRaceLog() {
|
||||
Set<TrackedRace> allTrackedRaces = getAllTrackedRaces();
|
||||
assertEquals(1, Util.size(allTrackedRaces));
|
||||
Set<RaceDefinition> races = raceHandles.iterator().next().getRaceTracker().getRaces();
|
||||
assertEquals(1, races.size());
|
||||
RaceDefinition raceFromTracker = races.iterator().next();
|
||||
assertNotNull(raceFromTracker);
|
||||
Set<String> raceIDs = new HashSet<String>();
|
||||
for (TrackedRace trackedRace : allTrackedRaces) {
|
||||
RaceDefinition race = trackedRace.getRace();
|
||||
raceIDs.add(race.getName());
|
||||
assertEquals(46, Util.size(race.getCompetitors()));
|
||||
assertEquals(7, Util.size(race.getCourse().getWaypoints()));
|
||||
assertEquals(6, Util.size(race.getCourse().getLegs()));
|
||||
for (Competitor competitor : race.getCompetitors()) {
|
||||
if (!competitor.getName().equals("Competitor 35") && !competitor.getName().equals("Competitor 20")
|
||||
&& !competitor.getName().equals("GBR 831") && !competitor.getName().equals("NED 24")) {
|
||||
final GPSFixTrack<Competitor, GPSFixMoving> track = trackedRace.getTrack(competitor);
|
||||
track.lockForRead();
|
||||
try {
|
||||
assertTrue("Track of competitor " + competitor + " empty", !Util.isEmpty(track.getRawFixes()));
|
||||
} finally {
|
||||
track.unlockAfterRead();
|
||||
}
|
||||
}
|
||||
}
|
||||
Set<Mark> marks = new HashSet<Mark>();
|
||||
for (Waypoint waypoint : race.getCourse().getWaypoints()) {
|
||||
for (Mark mark : waypoint.getMarks()) {
|
||||
marks.add(mark);
|
||||
}
|
||||
}
|
||||
for (Mark mark : marks) {
|
||||
final GPSFixTrack<Mark, GPSFix> track = trackedRace.getOrCreateTrack(mark);
|
||||
track.lockForRead();
|
||||
try {
|
||||
assertTrue("Track of mark " + mark + " empty",
|
||||
!Util.isEmpty(track.getRawFixes()));
|
||||
} finally {
|
||||
track.unlockAfterRead();
|
||||
}
|
||||
}
|
||||
}
|
||||
Set<String> expectedRaceIDs = new HashSet<String>();
|
||||
for (String raceIDToTrack : new String[] { "W4702" }) {
|
||||
expectedRaceIDs.add(raceIDToTrack);
|
||||
}
|
||||
assertEquals(expectedRaceIDs, raceIDs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLongLogRaceNewConfig() throws Exception {
|
||||
String[] racesToTrack = new String[] { "c34c423c-0295-4fe5-91ca-336681624702" };
|
||||
String scriptName1 = "/SailMasterDataInterfaceRACandSTL.txt";
|
||||
String scriptName2 = "/SailMasterDataInterface-ExampleAsText.txt";
|
||||
String scriptNewCourseConfig = "/SailMasterDataInterfaceNewCourseConfig.txt";
|
||||
setUpUsingScript(racesToTrack, scriptName1, scriptName2, scriptNewCourseConfig);
|
||||
Set<TrackedRace> allNewTrackedRaces = getAllTrackedRaces();
|
||||
assertEquals(1, Util.size(allNewTrackedRaces));
|
||||
Set<RaceDefinition> races = raceHandles.iterator().next().getRaceTracker().getRaces();
|
||||
assertEquals(1, races.size());
|
||||
RaceDefinition raceFromTracker = races.iterator().next();
|
||||
assertNotNull(raceFromTracker);
|
||||
Set<String> raceIDs = new HashSet<String>();
|
||||
for (TrackedRace trackedRace : allNewTrackedRaces) {
|
||||
RaceDefinition race = trackedRace.getRace();
|
||||
raceIDs.add(race.getName());
|
||||
assertEquals(46, Util.size(race.getCompetitors()));
|
||||
assertEquals(3, Util.size(race.getCourse().getWaypoints()));
|
||||
assertEquals(2, Util.size(race.getCourse().getLegs()));
|
||||
for (Competitor competitor : race.getCompetitors()) {
|
||||
if (!competitor.getName().equals("NED 24") && !competitor.getName().equals("Competitor 35")
|
||||
&& !competitor.getName().equals("Competitor 20") && !competitor.getName().equals("GBR 831")) {
|
||||
final GPSFixTrack<Competitor, GPSFixMoving> track = trackedRace.getTrack(competitor);
|
||||
track.lockForRead();
|
||||
try {
|
||||
assertTrue("Track of competitor " + competitor + " empty", !Util.isEmpty(track.getRawFixes()));
|
||||
} finally {
|
||||
track.unlockAfterRead();
|
||||
}
|
||||
}
|
||||
}
|
||||
Set<Mark> marks = new HashSet<Mark>();
|
||||
for (Waypoint waypoint : race.getCourse().getWaypoints()) {
|
||||
for (Mark mark : waypoint.getMarks()) {
|
||||
marks.add(mark);
|
||||
}
|
||||
}
|
||||
for (Mark mark : marks) {
|
||||
final GPSFixTrack<Mark, GPSFix> track = trackedRace.getOrCreateTrack(mark);
|
||||
track.lockForRead();
|
||||
try {
|
||||
assertTrue("Track of mark " + mark + " empty", !Util.isEmpty(track.getRawFixes()));
|
||||
} finally {
|
||||
track.unlockAfterRead();
|
||||
}
|
||||
}
|
||||
}
|
||||
Set<String> expectedRaceIDs = new HashSet<String>();
|
||||
for (String raceIDToTrack : new String[] { "c34c423c-0295-4fe5-91ca-336681624702" }) {
|
||||
expectedRaceIDs.add(raceIDToTrack);
|
||||
}
|
||||
assertEquals(expectedRaceIDs, raceIDs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDuplicateCCGMessageAndWaypointUniqueness() throws Exception {
|
||||
String[] racesToTrack = new String[] { "c34c423c-0295-4fe5-91ca-336681624702" };
|
||||
setUpUsingScript(racesToTrack, "/DuplicateCCG.txt");
|
||||
|
||||
Set<TrackedRace> allTrackedRaces = getAllTrackedRaces();
|
||||
assertEquals(1, allTrackedRaces.size());
|
||||
TrackedRace trackedRace = allTrackedRaces.iterator().next();
|
||||
List<Waypoint> waypoints = new ArrayList<Waypoint>();
|
||||
for (Waypoint waypoint : trackedRace.getRace().getCourse().getWaypoints()) {
|
||||
waypoints.add(waypoint);
|
||||
}
|
||||
assertEquals(7, Util.size(waypoints));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTMDMessageBeforeReceivingStartTime() throws Exception {
|
||||
final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
|
||||
String[] racesToTrack = new String[] { "c34c423c-0295-4fe5-91ca-336681625923" };
|
||||
setUpUsingScript(racesToTrack, "/TMDBeforeStartTimeExample.txt");
|
||||
Set<TrackedRace> allTrackedRaces = getAllTrackedRaces();
|
||||
assertEquals(1, allTrackedRaces.size());
|
||||
TrackedRace trackedRace = allTrackedRaces.iterator().next();
|
||||
assertEquals("c34c423c-0295-4fe5-91ca-336681625923", trackedRace.getRace().getName());
|
||||
assertEquals(dateFormat.parse("2013-04-04T13:45:00+0200"), trackedRace.getStartOfRace().asDate());
|
||||
for (Competitor competitor : trackedRace.getRace().getCompetitors()) {
|
||||
if (competitor.getBoat().getSailID().equals("GBR-828")) {
|
||||
NavigableSet<MarkPassing> markPassings = trackedRace.getMarkPassings(competitor);
|
||||
assertEquals(1, markPassings.size());
|
||||
assertNotNull(markPassings.iterator().next().getTimePoint());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Set<TrackedRace> getAllTrackedRaces() {
|
||||
Set<TrackedRace> allTrackedRaces = new HashSet<TrackedRace>();
|
||||
Iterable<Regatta> allEvents = racingEventService.getAllRegattas();
|
||||
for (Regatta event : allEvents) {
|
||||
DynamicTrackedRegatta trackedRegatta = racingEventService.getTrackedRegatta(event);
|
||||
Iterable<TrackedRace> trackedRaces = trackedRegatta.getTrackedRaces();
|
||||
for (TrackedRace trackedRace : trackedRaces) {
|
||||
allTrackedRaces.add(trackedRace);
|
||||
}
|
||||
}
|
||||
return allTrackedRaces;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTMDMessageBeforeReceivingStartTimeWithManyTMDs() throws Exception {
|
||||
final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
|
||||
String[] racesToTrack = new String[] { "c34c423c-0295-4fe5-91ca-336681625923" };
|
||||
setUpUsingScript(racesToTrack, "/TMDBeforeStartTimeExample_ManyTMDs.txt");
|
||||
Set<TrackedRace> allTrackedRaces = getAllTrackedRaces();
|
||||
assertEquals(1, allTrackedRaces.size());
|
||||
TrackedRace trackedRace = allTrackedRaces.iterator().next();
|
||||
assertEquals("c34c423c-0295-4fe5-91ca-336681625923", trackedRace.getRace().getName());
|
||||
assertEquals(dateFormat.parse("2013-04-04T13:45:00+0200"), trackedRace.getStartOfRace().asDate());
|
||||
for (Competitor competitor : trackedRace.getRace().getCompetitors()) {
|
||||
NavigableSet<MarkPassing> markPassings = trackedRace.getMarkPassings(competitor);
|
||||
if (competitor.getBoat().getSailID().equals("GBR-828")) {
|
||||
assertEquals(7, markPassings.size());
|
||||
}
|
||||
assertNotNull(markPassings.iterator().next().getTimePoint());
|
||||
assertEquals(trackedRace.getStartOfRace(), markPassings.iterator().next().getTimePoint());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRongRaceLogRACZero() throws Exception{
|
||||
String[] racesToTrack = new String[] { "c34c423c-0295-4fe5-91ca-336681624702" };
|
||||
String scriptName2 = "/SailMasterDataInterfaceRACZero.txt";
|
||||
setUpUsingScript(racesToTrack, scriptName2);
|
||||
Set<TrackedRace> allNewTrackedRaces = getAllTrackedRaces();
|
||||
assertEquals(0, Util.size(allNewTrackedRaces));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEndToEndWithSwissTimingData() throws Exception {
|
||||
String[] racesToTrack = new String[] { "c34c423c-0295-4fe5-91ca-336681624702" };
|
||||
String scriptName1 = "/SailMasterDataInterfaceRACandSTL.txt";
|
||||
String scriptName2 = "/SailMasterDataInterface-ExampleAsText.txt";
|
||||
setUpUsingScript(racesToTrack, scriptName1, scriptName2);
|
||||
assertFalse(getAllTrackedRaces().isEmpty());
|
||||
}
|
||||
|
||||
private void setUpUsingScript(String[] racesToTrack, String... scriptNames) throws Exception {
|
||||
for (String raceToTrack : racesToTrack) {
|
||||
RacesHandle raceHandle = swissTimingAdapter.addSwissTimingRace(racingEventService,
|
||||
/* regattaToAddTo */ null /* use a default regatta */, raceToTrack, /* canSendRequests */
|
||||
"localhost", CLIENT_PORT, false, emptyRaceLogStore, -1);
|
||||
raceHandles.add(raceHandle);
|
||||
if (connector == null) {
|
||||
connector = swissTimingAdapter.getSwissTimingFactory().getOrCreateSailMasterConnector("localhost",
|
||||
CLIENT_PORT, swissTimingAdapterPersistence, /* canSendRequests */false);
|
||||
}
|
||||
}
|
||||
ScriptedMessagesReader scriptedMessagesReader = new ScriptedMessagesReader();
|
||||
for (String scriptName : scriptNames) {
|
||||
InputStream is = getClass().getResourceAsStream(scriptName);
|
||||
scriptedMessagesReader.addMessagesFromTextFile(is);
|
||||
}
|
||||
Set<TrackedRace> trackedRacesSoFar = new HashSet<>();
|
||||
int i=0;
|
||||
int numberOfMessages = scriptedMessagesReader.getMessages().size();
|
||||
for (String msg : scriptedMessagesReader.getMessages()) {
|
||||
transceiver.sendMessage(msg, sendingStream);
|
||||
i++;
|
||||
for (TrackedRace trackedRace : getAllTrackedRaces()) {
|
||||
if (!trackedRacesSoFar.contains(trackedRace)) {
|
||||
trackedRacesSoFar.add(trackedRace);
|
||||
((DynamicTrackedRace) trackedRace).setStatus(new TrackedRaceStatusImpl(TrackedRaceStatusEnum.LOADING, ((double) i) / (double) numberOfMessages));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (TrackedRace trackedRace : getAllTrackedRaces()) {
|
||||
((DynamicTrackedRace) trackedRace).setStatus(new TrackedRaceStatusImpl(TrackedRaceStatusEnum.FINISHED, 1.0));
|
||||
}
|
||||
transceiver.sendMessage(swissTimingFactory.createMessage(MessageType._STOPSERVER.name(), null), sendingStream);
|
||||
synchronized (connector) {
|
||||
while (!connector.isStopped()) {
|
||||
connector.wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-113
@@ -1,113 +0,0 @@
|
||||
package com.sap.sailing.domain.swisstimingadapter.test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.Timeout;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DB;
|
||||
import com.mongodb.DBCollection;
|
||||
import com.sap.sailing.domain.swisstimingadapter.Race;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SailMasterAdapter;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SailMasterConnector;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SailMasterMessage;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SailMasterTransceiver;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SwissTimingFactory;
|
||||
import com.sap.sailing.domain.swisstimingadapter.persistence.StoreAndForward;
|
||||
import com.sap.sailing.domain.swisstimingadapter.persistence.SwissTimingAdapterPersistence;
|
||||
import com.sap.sailing.domain.swisstimingadapter.persistence.impl.CollectionNames;
|
||||
import com.sap.sailing.domain.swisstimingadapter.persistence.impl.FieldNames;
|
||||
import com.sap.sailing.mongodb.MongoDBService;
|
||||
|
||||
public class ListeningStoreAndForwardTest {
|
||||
private static final Logger logger = Logger.getLogger(ListeningStoreAndForwardTest.class.getName());
|
||||
|
||||
private static final int RECEIVE_PORT = 6543;
|
||||
private static final int CLIENT_PORT = 6544;
|
||||
|
||||
private DB db;
|
||||
private StoreAndForward storeAndForward;
|
||||
private Socket sendingSocket;
|
||||
private OutputStream sendingStream;
|
||||
private SailMasterTransceiver transceiver;
|
||||
private SailMasterConnector connector;
|
||||
private SwissTimingAdapterPersistence swissTimingAdapterPersistence;
|
||||
private SwissTimingFactory swissTimingFactory;
|
||||
|
||||
@Rule public Timeout AbstractTracTracLiveTestTimeout = new Timeout(5 * 60 * 1000); // timeout after 5 minutes
|
||||
|
||||
@Before
|
||||
public void setUp() throws UnknownHostException, IOException, InterruptedException {
|
||||
logger.info("ListeningStoreAndForwardTest.setUp");
|
||||
MongoDBService mongoDBService = MongoDBService.INSTANCE;
|
||||
db = mongoDBService.getDB();
|
||||
swissTimingAdapterPersistence = SwissTimingAdapterPersistence.INSTANCE;
|
||||
swissTimingAdapterPersistence.dropAllMessageData();
|
||||
storeAndForward = new StoreAndForward(RECEIVE_PORT, CLIENT_PORT, SwissTimingFactory.INSTANCE, swissTimingAdapterPersistence, mongoDBService);
|
||||
sendingSocket = new Socket("localhost", RECEIVE_PORT);
|
||||
sendingStream = sendingSocket.getOutputStream();
|
||||
swissTimingFactory = SwissTimingFactory.INSTANCE;
|
||||
transceiver = swissTimingFactory.createSailMasterTransceiver();
|
||||
connector = swissTimingFactory.getOrCreateSailMasterConnector("localhost", CLIENT_PORT, null, /* canSendRequests */ false);
|
||||
DBCollection lastMessageCountCollection = db.getCollection(CollectionNames.LAST_MESSAGE_COUNT.name());
|
||||
lastMessageCountCollection.update(new BasicDBObject(), new BasicDBObject().append(FieldNames.LAST_MESSAGE_COUNT.name(), 0l),
|
||||
/* upsert */ true, /* multi */ false);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws InterruptedException, IOException {
|
||||
logger.entering(getClass().getName(), "tearDown");
|
||||
storeAndForward.stop();
|
||||
connector.stop();
|
||||
logger.exiting(getClass().getName(), "tearDown");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleRACMessage() throws IOException, InterruptedException {
|
||||
logger.info("Starting ListeningStoreAndForwardTest.testSimpleRACMessage");
|
||||
final List<Race> racesReceived = new ArrayList<Race>();
|
||||
final boolean[] receivedSomething = new boolean[1];
|
||||
connector.addSailMasterListener(new SailMasterAdapter() {
|
||||
@Override
|
||||
public void receivedAvailableRaces(Iterable<Race> races) {
|
||||
for (Race race : races) {
|
||||
racesReceived.add(race);
|
||||
}
|
||||
synchronized (ListeningStoreAndForwardTest.this) {
|
||||
receivedSomething[0] = true;
|
||||
ListeningStoreAndForwardTest.this.notifyAll();
|
||||
}
|
||||
}
|
||||
});
|
||||
String rawMessage = "RAC|2|4711;A wonderful test race|4712;Not such a wonderful race";
|
||||
transceiver.sendMessage(rawMessage, sendingStream);
|
||||
synchronized (this) {
|
||||
if (!receivedSomething[0]) {
|
||||
wait(2000l); // wait for two seconds to receive the message
|
||||
}
|
||||
}
|
||||
assertTrue(receivedSomething[0]);
|
||||
assertEquals(2, racesReceived.size());
|
||||
DBCollection lastMessageCountCollection = db.getCollection(CollectionNames.LAST_MESSAGE_COUNT.name());
|
||||
Long lastMessageCount = (Long) lastMessageCountCollection.findOne().get(FieldNames.LAST_MESSAGE_COUNT.name());
|
||||
assertEquals((Long) 1l, lastMessageCount);
|
||||
List<SailMasterMessage> rawMessages = swissTimingAdapterPersistence.loadCommandMessages(0);
|
||||
assertEquals(1, rawMessages.size());
|
||||
assertEquals(rawMessage, rawMessages.get(0).getMessage());
|
||||
assertEquals(0l, (long) rawMessages.get(0).getSequenceNumber());
|
||||
}
|
||||
|
||||
}
|
||||
+4
-4
@@ -53,7 +53,7 @@ public class OverlappingStoredAndReceivedMessagesTest implements RaceSpecificMes
|
||||
public void setUp() throws UnknownHostException, IOException, InterruptedException {
|
||||
messagesToLoad = new ArrayList<SailMasterMessage>();
|
||||
new Thread("OverlappingStoredAndReceivedMessages-Connector") {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
serverSocket = new ServerSocket(PORT);
|
||||
@@ -111,7 +111,7 @@ public class OverlappingStoredAndReceivedMessagesTest implements RaceSpecificMes
|
||||
for (int i=0; i<COUNT; i++) {
|
||||
rawMessage[i] = ""+i+"|CCG|c34c423c-0295-4fe5-91ca-336681624711|2|1;Lee Gate;LG1;LG2|"+i+";Windward;WW1";
|
||||
if (i<STORED) {
|
||||
messagesToLoad.add(swissTimingFactory.createMessage(rawMessage[i], (long) i));
|
||||
messagesToLoad.add(swissTimingFactory.createMessage(rawMessage[i]));
|
||||
}
|
||||
}
|
||||
logger.info("starting StoreAndForwardTest-testBufferingMessageSender thread");
|
||||
@@ -130,7 +130,7 @@ public class OverlappingStoredAndReceivedMessagesTest implements RaceSpecificMes
|
||||
// unblocked by us sending the STORED-OVERLAPth message
|
||||
for (int i = 0; i < COUNT-UNBUFFERED; i++) {
|
||||
if (i >= STORED-OVERLAP) {
|
||||
transceiver.sendMessage(swissTimingFactory.createMessage(rawMessage[i], (long) i), sendingStream);
|
||||
transceiver.sendMessage(swissTimingFactory.createMessage(rawMessage[i]), sendingStream);
|
||||
}
|
||||
synchronized (OverlappingStoredAndReceivedMessagesTest.this) {
|
||||
messagesSent++;
|
||||
@@ -147,7 +147,7 @@ public class OverlappingStoredAndReceivedMessagesTest implements RaceSpecificMes
|
||||
assertTrue(loadMessagesCalled);
|
||||
// send more messages after buffering
|
||||
for (int i=COUNT-UNBUFFERED; i<COUNT; i++) {
|
||||
transceiver.sendMessage(swissTimingFactory.createMessage(rawMessage[i], (long) i), sendingStream);
|
||||
transceiver.sendMessage(swissTimingFactory.createMessage(rawMessage[i]), sendingStream);
|
||||
}
|
||||
synchronized (this) {
|
||||
int attempts = 0;
|
||||
|
||||
+5
-6
@@ -7,7 +7,6 @@ import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.sap.sailing.domain.common.impl.Util.Pair;
|
||||
import com.sap.sailing.domain.swisstimingadapter.MessageType;
|
||||
import com.sap.sailing.domain.swisstimingadapter.impl.SailMasterMessageImpl;
|
||||
import com.sap.sailing.domain.swisstimingadapter.impl.SailMasterTransceiverImpl;
|
||||
@@ -53,13 +52,13 @@ public class SailMasterDummy implements Runnable {
|
||||
|
||||
private void processRequests() throws IOException {
|
||||
InputStream is = socket.getInputStream();
|
||||
Pair<String, Long> messageAndOptionalSequenceNumber = transceiver.receiveMessage(is);
|
||||
while (messageAndOptionalSequenceNumber != null) {
|
||||
respondToMessage(messageAndOptionalSequenceNumber.getA(), socket.getOutputStream());
|
||||
String message = transceiver.receiveMessage(is);
|
||||
while (message != null) {
|
||||
respondToMessage(message, socket.getOutputStream());
|
||||
if (stopped) {
|
||||
messageAndOptionalSequenceNumber = null;
|
||||
message = null;
|
||||
} else {
|
||||
messageAndOptionalSequenceNumber = transceiver.receiveMessage(is);
|
||||
message = transceiver.receiveMessage(is);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-152
@@ -1,152 +0,0 @@
|
||||
package com.sap.sailing.domain.swisstimingadapter.test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DB;
|
||||
import com.mongodb.DBCollection;
|
||||
import com.sap.sailing.domain.swisstimingadapter.Competitor;
|
||||
import com.sap.sailing.domain.swisstimingadapter.Course;
|
||||
import com.sap.sailing.domain.swisstimingadapter.Race;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SailMasterAdapter;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SailMasterConnector;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SailMasterTransceiver;
|
||||
import com.sap.sailing.domain.swisstimingadapter.StartList;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SwissTimingFactory;
|
||||
import com.sap.sailing.domain.swisstimingadapter.persistence.StoreAndForward;
|
||||
import com.sap.sailing.domain.swisstimingadapter.persistence.SwissTimingAdapterPersistence;
|
||||
import com.sap.sailing.domain.swisstimingadapter.persistence.impl.CollectionNames;
|
||||
import com.sap.sailing.domain.swisstimingadapter.persistence.impl.FieldNames;
|
||||
import com.sap.sailing.mongodb.MongoDBService;
|
||||
|
||||
public class ScriptedStoreAndForwardTest {
|
||||
private static final Logger logger = Logger.getLogger(ScriptedStoreAndForwardTest.class.getName());
|
||||
|
||||
private static final int RECEIVE_PORT = 6543;
|
||||
private static final int CLIENT_PORT = 6544;
|
||||
|
||||
private DB db;
|
||||
private StoreAndForward storeAndForward;
|
||||
private Socket sendingSocket;
|
||||
private OutputStream sendingStream;
|
||||
private SailMasterTransceiver transceiver;
|
||||
private SailMasterConnector connector;
|
||||
private SwissTimingAdapterPersistence swissTimingAdapterPersistence;
|
||||
private SwissTimingFactory swissTimingFactory;
|
||||
|
||||
@Before
|
||||
public void setUp() throws UnknownHostException, IOException, InterruptedException, ParseException {
|
||||
MongoDBService mongoDBService = MongoDBService.INSTANCE;
|
||||
db = mongoDBService.getDB();
|
||||
swissTimingAdapterPersistence = SwissTimingAdapterPersistence.INSTANCE;
|
||||
swissTimingAdapterPersistence.dropAllRaceMasterData();
|
||||
swissTimingAdapterPersistence.dropAllMessageData();
|
||||
|
||||
storeAndForward = new StoreAndForward(RECEIVE_PORT, CLIENT_PORT, SwissTimingFactory.INSTANCE,
|
||||
swissTimingAdapterPersistence, mongoDBService);
|
||||
sendingSocket = new Socket("localhost", RECEIVE_PORT);
|
||||
sendingStream = sendingSocket.getOutputStream();
|
||||
swissTimingFactory = SwissTimingFactory.INSTANCE;
|
||||
transceiver = swissTimingFactory.createSailMasterTransceiver();
|
||||
connector = swissTimingFactory.getOrCreateSailMasterConnector("localhost", CLIENT_PORT, swissTimingAdapterPersistence, /* canSendRequests */ false);
|
||||
DBCollection lastMessageCountCollection = db.getCollection(CollectionNames.LAST_MESSAGE_COUNT.name());
|
||||
lastMessageCountCollection.update(new BasicDBObject(),
|
||||
new BasicDBObject().append(FieldNames.LAST_MESSAGE_COUNT.name(), 0l),
|
||||
/* upsert */true, /* multi */false);
|
||||
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws InterruptedException, IOException {
|
||||
logger.entering(getClass().getName(), "tearDown");
|
||||
storeAndForward.stop();
|
||||
connector.stop();
|
||||
logger.exiting(getClass().getName(), "tearDown");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitMessages() throws IOException, InterruptedException, ParseException {
|
||||
String[] racesToTrack = new String[] { "4711", "4712" };
|
||||
|
||||
for (String raceToTrack : racesToTrack)
|
||||
connector.trackRace(raceToTrack);
|
||||
|
||||
InputStream is = getClass().getResourceAsStream("/InitMessagesScript.txt");
|
||||
|
||||
ScriptedMessages scriptedMessages = new ScriptedMessages(is);
|
||||
|
||||
final int messageCount = scriptedMessages.getMessages().size();
|
||||
|
||||
final int[] receivedMessagesCount = new int[] { 0 };
|
||||
final List<Race> racesReceived = new ArrayList<Race>();
|
||||
final boolean[] receivedAll = new boolean[1];
|
||||
final List<Competitor> receivedCompetitors = new ArrayList<Competitor>();
|
||||
final List<Course> receivedCourses = new ArrayList<Course>();
|
||||
|
||||
connector.addSailMasterListener(new SailMasterAdapter() {
|
||||
@Override
|
||||
public void receivedStartList(String raceID, StartList startList) {
|
||||
|
||||
for (Competitor competitor : startList.getCompetitors())
|
||||
receivedCompetitors.add(competitor);
|
||||
|
||||
receivedMessagesCount[0] = receivedMessagesCount[0] + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receivedCourseConfiguration(String raceID, Course course) {
|
||||
|
||||
receivedCourses.add(course);
|
||||
|
||||
receivedMessagesCount[0] = receivedMessagesCount[0] + 1;
|
||||
|
||||
if (messageCount == receivedMessagesCount[0]) {
|
||||
synchronized (ScriptedStoreAndForwardTest.this) {
|
||||
receivedAll[0] = true;
|
||||
ScriptedStoreAndForwardTest.this.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receivedAvailableRaces(Iterable<Race> races) {
|
||||
|
||||
for (Race race : races) {
|
||||
racesReceived.add(race);
|
||||
}
|
||||
receivedMessagesCount[0] = receivedMessagesCount[0] + 1;
|
||||
}
|
||||
});
|
||||
|
||||
for(String msg: scriptedMessages.getMessages()) {
|
||||
transceiver.sendMessage(msg, sendingStream);
|
||||
}
|
||||
synchronized (this) {
|
||||
while (!receivedAll[0]) {
|
||||
wait(2000l); // wait for two seconds to receive the messages
|
||||
}
|
||||
}
|
||||
assertEquals(2, racesReceived.size());
|
||||
assertEquals(5, receivedCompetitors.size());
|
||||
assertEquals(2, receivedCourses.size());
|
||||
|
||||
for(String raceToTrack: racesToTrack)
|
||||
connector.stopTrackingRace(raceToTrack);
|
||||
}
|
||||
|
||||
}
|
||||
+1
-2
@@ -4,7 +4,6 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import com.sap.sailing.domain.common.impl.Util.Pair;
|
||||
|
||||
public interface SailMasterTransceiver {
|
||||
/**
|
||||
@@ -28,6 +27,6 @@ public interface SailMasterTransceiver {
|
||||
* @return the message read, or <code>null</code> if the end of the stream has been reached without finding a
|
||||
* message start byte.
|
||||
*/
|
||||
Pair<String, Long> receiveMessage(InputStream inputStream) throws IOException;
|
||||
String receiveMessage(InputStream inputStream) throws IOException;
|
||||
|
||||
}
|
||||
-3
@@ -15,7 +15,6 @@ public interface SwissTimingAdapter {
|
||||
boolean canSendRequests) throws InterruptedException, UnknownHostException, IOException, ParseException;
|
||||
|
||||
/**
|
||||
* @param trackerManager TODO
|
||||
* @param regattaToAddTo
|
||||
* if <code>null</code>, an existing regatta by the name of the TracTrac event with the boat class name
|
||||
* appended in parentheses will be looked up; if not found, a default regatta with that name will be
|
||||
@@ -29,8 +28,6 @@ public interface SwissTimingAdapter {
|
||||
|
||||
SwissTimingFactory getSwissTimingFactory();
|
||||
|
||||
void storeSwissTimingDummyRace(String racMessage, String stlMesssage, String ccgMessage) throws IllegalArgumentException;
|
||||
|
||||
com.sap.sailing.domain.swisstimingadapter.DomainFactory getSwissTimingDomainFactory();
|
||||
|
||||
}
|
||||
+1
-1
@@ -61,7 +61,7 @@ public interface SwissTimingFactory {
|
||||
|
||||
Race createRace(String raceId, String description, TimePoint startTime);
|
||||
|
||||
SailMasterMessage createMessage(String message, Long sequenceNumber);
|
||||
SailMasterMessage createMessage(String message);
|
||||
|
||||
SwissTimingArchiveConfiguration createSwissTimingArchiveConfiguration(String string);
|
||||
|
||||
|
||||
+3
-4
@@ -227,16 +227,15 @@ public class SailMasterConnectorImpl extends SailMasterTransceiverImpl implement
|
||||
while (!stopped) {
|
||||
try {
|
||||
ensureSocketIsOpen();
|
||||
Pair<String, Long> receivedMessageAndOptionalSequenceNumber = receiveMessage(socket.getInputStream());
|
||||
if (receivedMessageAndOptionalSequenceNumber == null) {
|
||||
String receivedMessage = receiveMessage(socket.getInputStream());
|
||||
if (receivedMessage == null) {
|
||||
// reached EOF; this means the socket is or can be closed
|
||||
if (socket != null && !socket.isClosed()) {
|
||||
socket.close();
|
||||
}
|
||||
socket = null;
|
||||
} else {
|
||||
SailMasterMessage message = new SailMasterMessageImpl(
|
||||
receivedMessageAndOptionalSequenceNumber.getA());
|
||||
SailMasterMessage message = new SailMasterMessageImpl(receivedMessage);
|
||||
// drop race-specific messages for non-tracked races
|
||||
if (!message.getType().isRaceSpecific() || idsOfTrackedRaces.contains(message.getRaceID())) {
|
||||
boolean messageProcessed = false;
|
||||
|
||||
+11
-31
@@ -7,7 +7,6 @@ import java.io.OutputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.sap.sailing.domain.common.impl.Util.Pair;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SailMasterMessage;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SailMasterTransceiver;
|
||||
|
||||
@@ -35,8 +34,11 @@ public class SailMasterTransceiverImpl implements SailMasterTransceiver {
|
||||
|
||||
@Override
|
||||
public synchronized void sendMessage(SailMasterMessage message, OutputStream os) throws IOException {
|
||||
os.write(("" + message.getSequenceNumber()).getBytes());
|
||||
sendMessage(message.getMessage(), os);
|
||||
if (message.getSequenceNumber()==null) {
|
||||
sendMessage(message.getMessage(), os);
|
||||
} else {
|
||||
sendMessage(""+message.getSequenceNumber()+"|"+message.getMessage(), os);
|
||||
}
|
||||
os.flush();
|
||||
}
|
||||
|
||||
@@ -45,23 +47,13 @@ public class SailMasterTransceiverImpl implements SailMasterTransceiver {
|
||||
* marker bytes are removed from the message. The message is decoded into a string using the cp1252 character
|
||||
* encoding.
|
||||
*
|
||||
* @return <code>null</code> if the end of the stream has been reached without finding a
|
||||
* message start byte; a pair containing the message and, optionally, an integer number
|
||||
* telling the message's sequence number which may be merged into the data stream by
|
||||
* a filter to identify the message up to which the content has already been transformed
|
||||
* into an internal domain model. The sequence number may be used to request messages
|
||||
* from the database starting with this number. If no sequence number was received
|
||||
* along with the message, the pair's second component is <code>null</code>.
|
||||
* @return <code>null</code> if the end of the stream has been reached without finding a message start byte; the
|
||||
* message otherwise.
|
||||
*/
|
||||
public Pair<String, Long> receiveMessage(InputStream inputStream) throws IOException {
|
||||
ByteArrayOutputStream bufferForOptionalSequenceNumber = new ByteArrayOutputStream(8);
|
||||
Long sequenceNumber = null;
|
||||
public String receiveMessage(InputStream inputStream) throws IOException {
|
||||
// read until an STX byte comes along
|
||||
int read = inputStream.read();
|
||||
while (read != -1 && read != STX) {
|
||||
bufferForOptionalSequenceNumber.write(read);
|
||||
read = inputStream.read();
|
||||
}
|
||||
int read;
|
||||
while ((read = inputStream.read()) != -1 && read != STX);
|
||||
// now either we've read an STX byte or reached EOF
|
||||
String message = null;
|
||||
if (read == STX) {
|
||||
@@ -70,19 +62,7 @@ public class SailMasterTransceiverImpl implements SailMasterTransceiver {
|
||||
// EOF; indicate by returning null
|
||||
logger.info("Received EOF in SailMasterTransceiver. Returning null as message.");
|
||||
}
|
||||
if (bufferForOptionalSequenceNumber.size() > 0) {
|
||||
sequenceNumber = getSequenceNumber(bufferForOptionalSequenceNumber);
|
||||
}
|
||||
return message == null ? null : new Pair<String, Long>(message, sequenceNumber);
|
||||
}
|
||||
|
||||
private Long getSequenceNumber(ByteArrayOutputStream bufferForOptionalSequenceNumber) {
|
||||
String s = new String(bufferForOptionalSequenceNumber.toByteArray());
|
||||
StringBuilder trailingDigits = new StringBuilder();
|
||||
for (int i=s.length()-1; i>=0 && s.charAt(i) >= '0' && s.charAt(i) <= '9'; i--) {
|
||||
trailingDigits.insert(0, s.charAt(i));
|
||||
}
|
||||
return trailingDigits.length() > 0 ? Long.valueOf(trailingDigits.toString()) : null;
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
-15
@@ -13,7 +13,6 @@ import com.sap.sailing.domain.racelog.RaceLogStore;
|
||||
import com.sap.sailing.domain.swisstimingadapter.Race;
|
||||
import com.sap.sailing.domain.swisstimingadapter.RaceSpecificMessageLoader;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SailMasterConnector;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SailMasterMessage;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SwissTimingAdapter;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SwissTimingFactory;
|
||||
import com.sap.sailing.domain.tracking.RacesHandle;
|
||||
@@ -72,18 +71,4 @@ public class SwissTimingAdapterImpl implements SwissTimingAdapter {
|
||||
timeoutInMilliseconds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeSwissTimingDummyRace(String racMessage, String stlMessage, String ccgMessage) {
|
||||
SailMasterMessage racSMMessage = swissTimingFactory.createMessage(racMessage, null);
|
||||
SailMasterMessage stlSMMessage = swissTimingFactory.createMessage(stlMessage, null);
|
||||
SailMasterMessage ccgSMMessage = swissTimingFactory.createMessage(ccgMessage, null);
|
||||
if (raceSpecificMessageLoader.getRace(stlSMMessage.getRaceID()) != null) {
|
||||
throw new IllegalArgumentException("Race with raceID \"" + stlSMMessage.getRaceID() + "\" already exists.");
|
||||
} else {
|
||||
raceSpecificMessageLoader.storeSailMasterMessage(racSMMessage);
|
||||
raceSpecificMessageLoader.storeSailMasterMessage(stlSMMessage);
|
||||
raceSpecificMessageLoader.storeSailMasterMessage(ccgSMMessage);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -102,7 +102,7 @@ public class SwissTimingFactoryImpl implements SwissTimingFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SailMasterMessage createMessage(String message, Long sequenceNumber) {
|
||||
public SailMasterMessage createMessage(String message) {
|
||||
return new SailMasterMessageImpl(message);
|
||||
}
|
||||
|
||||
|
||||
-7
@@ -122,13 +122,6 @@ public class SailingServiceImplMock extends SailingServiceImpl {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeSwissTimingDummyRace(String racMessage, String stlMesssage, String ccgMessage)
|
||||
throws IllegalArgumentException {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.sap.sailing.domain.swisstimingadapter.DomainFactory getSwissTimingDomainFactory() {
|
||||
return com.sap.sailing.domain.swisstimingadapter.DomainFactory.INSTANCE;
|
||||
|
||||
-6
@@ -91,12 +91,6 @@ public class AdminConsoleEntryPoint extends AbstractEntryPoint implements Regatt
|
||||
addScrollableTab(tabPanel, swisstimingEventManagementPanel, stringMessages.swissTimingEvents());
|
||||
regattaDisplayers.add(swisstimingEventManagementPanel);
|
||||
|
||||
CreateSwissTimingRacePanel createSwissTimingRacePanel = new CreateSwissTimingRacePanel(sailingService, this,
|
||||
stringMessages);
|
||||
// createSwissTimingRacePanel.ensureDebugId("CreateSwissTimingRace");
|
||||
createSwissTimingRacePanel.setSize("90%", "90%");
|
||||
addScrollableTab(tabPanel, createSwissTimingRacePanel, stringMessages.createSwissTimingRace());
|
||||
|
||||
IgtimiAccountsPanel igtimiAccountsPanel = new IgtimiAccountsPanel(sailingService, this, stringMessages);
|
||||
igtimiAccountsPanel.ensureDebugId("IgtimiAccounts");
|
||||
igtimiAccountsPanel.setSize("90%", "90%");
|
||||
|
||||
-297
@@ -1,297 +0,0 @@
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gwt.event.dom.client.ChangeEvent;
|
||||
import com.google.gwt.event.dom.client.ChangeHandler;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.ClickHandler;
|
||||
import com.google.gwt.event.logical.shared.ValueChangeEvent;
|
||||
import com.google.gwt.event.logical.shared.ValueChangeHandler;
|
||||
import com.google.gwt.user.client.Window;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.ui.Button;
|
||||
import com.google.gwt.user.client.ui.CaptionPanel;
|
||||
import com.google.gwt.user.client.ui.FormPanel;
|
||||
import com.google.gwt.user.client.ui.Grid;
|
||||
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.MultiWordSuggestOracle;
|
||||
import com.google.gwt.user.client.ui.SuggestBox;
|
||||
import com.google.gwt.user.client.ui.TextBox;
|
||||
import com.google.gwt.user.client.ui.VerticalPanel;
|
||||
import com.sap.sailing.gwt.ui.client.ErrorReporter;
|
||||
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
|
||||
public class CreateSwissTimingRacePanel extends FormPanel {
|
||||
private TextBox txtbRaceName;
|
||||
private TextBox txtbRaceDesc;
|
||||
private TextBox txtbCompName;
|
||||
private TextBox txtbCompSailNr;
|
||||
private MultiWordSuggestOracle suggestionsCompCountr;
|
||||
private SuggestBox listbCompCountr;
|
||||
private ListBox listbCompetitorList;
|
||||
private List<Competitor> competitors;
|
||||
private int selectedIndex;
|
||||
private int id = 0;
|
||||
private final SailingServiceAsync service;
|
||||
private ErrorReporter errorReporter;
|
||||
|
||||
public CreateSwissTimingRacePanel(final SailingServiceAsync sailingService, ErrorReporter errorReporter, final StringMessages stringConstants){
|
||||
this.service = sailingService;
|
||||
this.errorReporter = errorReporter;
|
||||
competitors = new ArrayList<CreateSwissTimingRacePanel.Competitor>();
|
||||
|
||||
VerticalPanel mainPanel = new VerticalPanel();
|
||||
Grid mainGrid = new Grid(3,1);
|
||||
mainGrid.setWidth("100%");
|
||||
mainPanel.add(mainGrid);
|
||||
mainPanel.setSize("100%", "100%");
|
||||
this.setWidget(mainPanel);
|
||||
|
||||
//Race data panel
|
||||
CaptionPanel raceDataPanel = new CaptionPanel("Race");
|
||||
raceDataPanel.setSize("90%", "90%");
|
||||
mainGrid.setWidget(0, 0, raceDataPanel);
|
||||
Grid grid = new Grid(2,2);
|
||||
raceDataPanel.add(grid);
|
||||
Label lblRaceName = new Label(stringConstants.race() + " " + stringConstants.name() + ":");
|
||||
grid.setWidget(0, 0, lblRaceName);
|
||||
txtbRaceName = new TextBox();
|
||||
grid.setWidget(0, 1, txtbRaceName);
|
||||
Label lblRaceDesc = new Label(stringConstants.race() + " " + stringConstants.description()+":");
|
||||
grid.setWidget(1, 0, lblRaceDesc);
|
||||
txtbRaceDesc = new TextBox();
|
||||
grid.setWidget(1, 1, txtbRaceDesc);
|
||||
|
||||
//Competitor panel
|
||||
CaptionPanel competitorPanel = new CaptionPanel(stringConstants.competitor());
|
||||
competitorPanel.setSize("90%", "90%");
|
||||
mainGrid.setWidget(1, 0, competitorPanel);
|
||||
grid = new Grid(3,3);
|
||||
competitorPanel.add(grid);
|
||||
|
||||
Label lblCompetitorListTitle = new Label(stringConstants.competitor());
|
||||
grid.setWidget(0, 0, lblCompetitorListTitle);
|
||||
listbCompetitorList = new ListBox(false);
|
||||
listbCompetitorList.setVisibleItemCount(10);
|
||||
listbCompetitorList.setWidth("200px");
|
||||
listbCompetitorList.addChangeHandler(new ChangeHandler() {
|
||||
|
||||
@Override
|
||||
public void onChange(ChangeEvent event) {
|
||||
competitorSelectionChanged();
|
||||
}
|
||||
});
|
||||
grid.setWidget(1, 0, listbCompetitorList);
|
||||
|
||||
VerticalPanel compData = new VerticalPanel();
|
||||
grid.setWidget(1, 1, compData);
|
||||
Grid subGrid = new Grid(3,2);
|
||||
compData.add(subGrid);
|
||||
Label lblName = new Label(stringConstants.name() + ":");
|
||||
subGrid.setWidget(0, 0, lblName);
|
||||
txtbCompName = new TextBox();
|
||||
txtbCompName.addValueChangeHandler(new ValueChangeHandler<String>() {
|
||||
|
||||
@Override
|
||||
public void onValueChange(ValueChangeEvent<String> event) {
|
||||
competitorChanged();
|
||||
}
|
||||
});
|
||||
subGrid.setWidget(0, 1, txtbCompName);
|
||||
Label lblSailNr = new Label(stringConstants.sailNumber()+":");
|
||||
subGrid.setWidget(1, 0, lblSailNr);
|
||||
txtbCompSailNr = new TextBox();
|
||||
txtbCompSailNr.addValueChangeHandler(new ValueChangeHandler<String>() {
|
||||
|
||||
@Override
|
||||
public void onValueChange(ValueChangeEvent<String> event) {
|
||||
competitorChanged();
|
||||
}
|
||||
});
|
||||
subGrid.setWidget(1, 1, txtbCompSailNr);
|
||||
Label lblCountr = new Label(stringConstants.country()+":");
|
||||
subGrid.setWidget(2, 0, lblCountr);
|
||||
suggestionsCompCountr = new MultiWordSuggestOracle();
|
||||
service.getCountryCodes(new AsyncCallback<String[]>() {
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
CreateSwissTimingRacePanel.this.errorReporter.reportError(stringConstants.no3LetterCodes());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(String[] result) {
|
||||
for (String cc : result){
|
||||
suggestionsCompCountr.add(cc);
|
||||
}
|
||||
}
|
||||
});
|
||||
listbCompCountr = new SuggestBox(suggestionsCompCountr);
|
||||
listbCompCountr.addValueChangeHandler(new ValueChangeHandler<String>() {
|
||||
|
||||
@Override
|
||||
public void onValueChange(ValueChangeEvent<String> event) {
|
||||
competitorChanged();
|
||||
}
|
||||
});
|
||||
subGrid.setWidget(2, 1, listbCompCountr);
|
||||
|
||||
HorizontalPanel horizontalPanel = new HorizontalPanel();
|
||||
grid.setWidget(2, 0, horizontalPanel);
|
||||
|
||||
Button bttAddCompetitor = new Button(stringConstants.add());
|
||||
bttAddCompetitor.setWidth("100px");
|
||||
bttAddCompetitor.addClickHandler(new ClickHandler() {
|
||||
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
addCompetitor();
|
||||
}
|
||||
});
|
||||
horizontalPanel.add(bttAddCompetitor);
|
||||
|
||||
Button bttDeleteCompetitor = new Button(stringConstants.delete());
|
||||
bttDeleteCompetitor.setWidth("100px");
|
||||
bttDeleteCompetitor.addClickHandler(new ClickHandler() {
|
||||
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
deleteCompetitor();
|
||||
}
|
||||
});
|
||||
horizontalPanel.add(bttDeleteCompetitor);
|
||||
|
||||
Button bttAddRace = new Button(stringConstants.add() + " " + stringConstants.race());
|
||||
bttAddRace.addClickHandler(new ClickHandler() {
|
||||
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
addRace();
|
||||
}
|
||||
});
|
||||
mainGrid.setWidget(2, 0, bttAddRace);
|
||||
}
|
||||
|
||||
private void competitorSelectionChanged(){
|
||||
selectedIndex = listbCompetitorList.getSelectedIndex();
|
||||
if (selectedIndex < 0){
|
||||
return;
|
||||
}
|
||||
Competitor c = getCompetitorById(Integer.parseInt(listbCompetitorList.getValue(selectedIndex)));
|
||||
if (c != null){
|
||||
txtbCompName.setText(c.getName());
|
||||
txtbCompSailNr.setText(c.getSailNumber());
|
||||
listbCompCountr.setText(c.getCountry());
|
||||
}
|
||||
}
|
||||
|
||||
private void addCompetitor(){
|
||||
Competitor c = new Competitor(id++,"Noname","","");
|
||||
listbCompetitorList.addItem(c.toString(), ""+c.getId());
|
||||
competitors.add(c);
|
||||
listbCompetitorList.setSelectedIndex(listbCompetitorList.getItemCount()-1);
|
||||
competitorSelectionChanged();
|
||||
txtbCompName.setFocus(true);
|
||||
}
|
||||
|
||||
private void deleteCompetitor(){
|
||||
selectedIndex = listbCompetitorList.getSelectedIndex();
|
||||
if (selectedIndex < 0){
|
||||
return;
|
||||
}
|
||||
competitors.remove(getCompetitorById(Integer.parseInt(listbCompetitorList.getValue(selectedIndex))));
|
||||
listbCompetitorList.removeItem(selectedIndex);
|
||||
}
|
||||
|
||||
private void competitorChanged(){
|
||||
if (selectedIndex < 0){
|
||||
return;
|
||||
}
|
||||
Competitor c = getCompetitorById(Integer.parseInt(listbCompetitorList.getValue(selectedIndex)));
|
||||
if (!txtbCompName.getText().equals(c.getName())){
|
||||
c.setName(txtbCompName.getText());
|
||||
listbCompetitorList.setItemText(selectedIndex, c.toString());
|
||||
}
|
||||
c.setCountry(listbCompCountr.getText());
|
||||
c.setSailNumber(txtbCompSailNr.getText());
|
||||
}
|
||||
|
||||
private Competitor getCompetitorById(int id){
|
||||
for (Competitor c : competitors){
|
||||
if (c.getId() == id)
|
||||
return c;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void addRace(){
|
||||
String racMessage = "RAC|1|" + txtbRaceName.getText()+";" + txtbRaceDesc.getText();
|
||||
|
||||
String stlMessage = "STL|" + txtbRaceName.getText()+"|" + competitors.size();
|
||||
for (Competitor c : competitors){
|
||||
stlMessage += "|" + c.getSailNumber()+";" + c.getCountry() +";" + c.getName();
|
||||
}
|
||||
|
||||
String ccgMessage = "CCG|" + txtbRaceName.getText() +"|3|0;LeeGate;LG1;LG2|1;Windwards;WW1|2;LeeGate;LG1;LG2";
|
||||
|
||||
service.sendSwissTimingDummyRace(racMessage,stlMessage,ccgMessage, new AsyncCallback<Void>() {
|
||||
|
||||
@Override
|
||||
public void onSuccess(Void result) {
|
||||
Window.alert("Succesfully sended new race.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter.reportError("Race with raceID \"" + txtbRaceName.getText() + "\" already exists.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private class Competitor{
|
||||
private String name;
|
||||
private String sailNumber;
|
||||
private String country;
|
||||
private final int id;
|
||||
|
||||
|
||||
public final int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public Competitor(int id, String name, String sailNumber, String country) {
|
||||
super();
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.sailNumber = sailNumber;
|
||||
this.country = country;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public String getSailNumber() {
|
||||
return sailNumber;
|
||||
}
|
||||
public void setSailNumber(String sailNumber) {
|
||||
this.sailNumber = sailNumber;
|
||||
}
|
||||
public String getCountry() {
|
||||
return country;
|
||||
}
|
||||
public void setCountry(String country) {
|
||||
this.country = country;
|
||||
}
|
||||
|
||||
public String toString(){
|
||||
return getName();
|
||||
}
|
||||
}
|
||||
}
|
||||
-2
@@ -215,8 +215,6 @@ public interface SailingService extends RemoteService {
|
||||
|
||||
void storeSwissTimingConfiguration(String configName, String hostname, int port, boolean canSendRequests);
|
||||
|
||||
void sendSwissTimingDummyRace(String racMessage, String stlMesssage, String ccgMessage) throws IllegalArgumentException;
|
||||
|
||||
String[] getCountryCodes();
|
||||
|
||||
Map<CompetitorDTO, List<GPSFixDTO>> getDouglasPoints(RegattaAndRaceIdentifier raceIdentifier,
|
||||
|
||||
-2
@@ -255,8 +255,6 @@ public interface SailingServiceAsync {
|
||||
|
||||
void storeSwissTimingConfiguration(String configName, String hostname, int port, boolean canSendRequests, AsyncCallback<Void> asyncCallback);
|
||||
|
||||
void sendSwissTimingDummyRace(String racMessage, String stlMesssage, String ccgMessage, AsyncCallback<Void> callback);
|
||||
|
||||
void getCountryCodes(AsyncCallback<String[]> callback);
|
||||
|
||||
void getDouglasPoints(RegattaAndRaceIdentifier raceIdentifier, Map<CompetitorDTO, Date> from, Map<CompetitorDTO, Date> to,
|
||||
|
||||
-1
@@ -923,7 +923,6 @@ public interface StringMessages extends Messages {
|
||||
String hasAdditionalGolfDownTime();
|
||||
String additionalGolfDownTimeHelpText();
|
||||
String invalidColor(String message);
|
||||
String createSwissTimingRace();
|
||||
String igtimiAccounts();
|
||||
String errorFetchingIgtimiAccounts(String message);
|
||||
String addIgtimiAccount();
|
||||
|
||||
-1
@@ -912,7 +912,6 @@ setStartTimeDescription=Select a new start time for the race
|
||||
hasAdditionalGolfDownTime=Activate additional golf down time
|
||||
additionalGolfDownTimeHelpText=Activate additional golf down time
|
||||
invalidColor=Invalid color: {0}
|
||||
createSwissTimingRace=Create SwissTiming race
|
||||
igtimiAccounts=Igtimi Accounts
|
||||
errorFetchingIgtimiAccounts=Error fetching all Igtimi accounts: {0}
|
||||
addIgtimiAccount=Add Igtimi Account
|
||||
|
||||
-1
@@ -908,7 +908,6 @@ setStartTimeDescription=Wähle eine Startzeit für das Rennen aus
|
||||
hasAdditionalGolfDownTime=Aktiviere Golf-Flaggen Zusatzzeit
|
||||
additionalGolfDownTimeHelpText=Aktiviere Golf-Flaggen Zusatzzeit
|
||||
invalidColor=Ungültige Farbangabe: {0}
|
||||
createSwissTimingRace=SwissTiming-Rennen anlegen
|
||||
igtimiAccounts=Igtimi-Konten
|
||||
errorFetchingIgtimiAccounts=Fehler beim Laden aller Igtimi-Konten: {0}
|
||||
addIgtimiAccount=Igtimi-Konto hinzufügen
|
||||
|
||||
-5
@@ -2204,11 +2204,6 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendSwissTimingDummyRace(String racMessage, String stlMesssage, String ccgMessage) {
|
||||
getSwissTimingAdapter().storeSwissTimingDummyRace(racMessage,stlMesssage,ccgMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SwissTimingReplayRaceDTO> listSwissTiminigReplayRaces(String swissTimingUrl) {
|
||||
List<SwissTimingReplayRace> replayRaces = getSwissTimingReplayService().listReplayRaces(swissTimingUrl);
|
||||
|
||||
Reference in new issue
Block a user