From 091ee4735b5a4c25fe878c5394c12859facb8b19 Mon Sep 17 00:00:00 2001 From: fjc40 Date: Mon, 24 Apr 2017 20:19:39 +1200 Subject: [PATCH 1/4] Race.simulateRace() function now generates a BoatLocationMessage after updating the position of each boat. Currently we just print the message to stdout. Added functions to convert knots (as a double) to mm/sec (as an int) to BoatLocationMessage class. Added toString function to BoatLocationMessage class. Added a sequence number member to the BoatInRace class. Added Knots to meters per second conversion factor to Contants class. #story[788] --- mock/src/main/java/seng302/Constants.java | 3 + .../main/java/seng302/Model/BoatInRace.java | 17 +++ mock/src/main/java/seng302/Model/Race.java | 52 ++++++++- .../BoatLocationMessage.java | 110 ++++++++++++++++++ 4 files changed, 177 insertions(+), 5 deletions(-) diff --git a/mock/src/main/java/seng302/Constants.java b/mock/src/main/java/seng302/Constants.java index b4b3033f..a052b2b0 100644 --- a/mock/src/main/java/seng302/Constants.java +++ b/mock/src/main/java/seng302/Constants.java @@ -11,6 +11,9 @@ public class Constants { public static final int NMToMetersConversion = 1852; // 1 nautical mile = 1852 meters + //Knots x this = meters per second. + public static final double KnotsToMetersPerSecondConversionFactor = 0.514444; + public static final GPSCoordinate startLineMarker1 = new GPSCoordinate(32.296577, -64.854304); public static final GPSCoordinate startLineMarker2 = new GPSCoordinate(32.293771, -64.855242); public static final GPSCoordinate mark1 = new GPSCoordinate(32.293039, -64.843983); diff --git a/mock/src/main/java/seng302/Model/BoatInRace.java b/mock/src/main/java/seng302/Model/BoatInRace.java index 50ef24e9..2935d5c9 100644 --- a/mock/src/main/java/seng302/Model/BoatInRace.java +++ b/mock/src/main/java/seng302/Model/BoatInRace.java @@ -29,6 +29,9 @@ public class BoatInRace extends Boat { private StringProperty position; private double heading; + ///While generating BoatLocationMessages, each one needs a sequence number relating to each boat. + private long sequenceNumber = 0; + private boolean trackVisible = true; /** @@ -263,4 +266,18 @@ public class BoatInRace extends Boat { this.position.set(position); } + + /** + * Returns the current sequence number, and increments the internal value, such that that next call will return a value 1 larger than the current call. + * @return Current sequence number. + */ + public long getNextSequenceNumber(){ + //Make a copy of current value. + long oldNumber = this.sequenceNumber; + //Increment. + this.sequenceNumber += 1; + //Return the previous value. + return oldNumber; + } + } diff --git a/mock/src/main/java/seng302/Model/Race.java b/mock/src/main/java/seng302/Model/Race.java index 0de5c45f..3e7de7bc 100644 --- a/mock/src/main/java/seng302/Model/Race.java +++ b/mock/src/main/java/seng302/Model/Race.java @@ -11,6 +11,7 @@ import org.geotools.referencing.GeodeticCalculator; import seng302.Constants; import seng302.GPSCoordinate; import seng302.RaceDataSource; +import seng302.RaceEventMessages.BoatLocationMessage; import java.awt.geom.Point2D; @@ -158,20 +159,61 @@ public class Race implements Runnable { } new AnimationTimer() { - - long timeRaceStarted = System.currentTimeMillis(); //start time of loop + //Start time of loop. + long timeRaceStarted = System.currentTimeMillis(); @Override public void handle(long arg0) { if (boatsFinished < startingBoats.size()) { - totalTimeElapsed = System.currentTimeMillis() - timeRaceStarted; + //Get the current time. + long currentTime = System.currentTimeMillis(); + //Update the total elapsed time. + totalTimeElapsed = currentTime - timeRaceStarted; + //For each boat, we update it's position, and generate a BoatLocationMessage. for (BoatInRace boat : startingBoats) { if (boat != null && !boat.isFinished()) { + //Update position. updatePosition(boat, Math.round(1000 / lastFPS) > 20 ? 15 : Math.round(1000 / lastFPS)); checkPosition(boat, totalTimeElapsed); + + + //Generate a boat location message for the updated boat. + BoatLocationMessage boatLocationMessage = new BoatLocationMessage(); + boatLocationMessage.setTime(currentTime); + boatLocationMessage.setSourceID(boat.getSourceID()); + boatLocationMessage.setSequenceNumber(boat.getNextSequenceNumber()); + boatLocationMessage.setDeviceType(BoatLocationMessage.RacingYacht); + + boatLocationMessage.setLatitude(BoatLocationMessage.convertCoordinateDoubleToInt(boat.getCurrentPosition().getLatitude())); + boatLocationMessage.setLongitude(BoatLocationMessage.convertCoordinateDoubleToInt(boat.getCurrentPosition().getLongitude())); + + boatLocationMessage.setAltitude(0);//Junk value. + boatLocationMessage.setHeading(BoatLocationMessage.convertHeadingDoubleToInt(boat.getHeading())); + + boatLocationMessage.setPitch((short)0);//Junk value. + boatLocationMessage.setRoll((short)0);//Junk value. + + boatLocationMessage.setBoatSpeed(BoatLocationMessage.convertBoatSpeedDoubleToInt(boat.getVelocity())); + boatLocationMessage.setBoatCOG(0);//Junk value. + boatLocationMessage.setBoatSOG(0);//Junk value. + + boatLocationMessage.setApparentWindSpeed(0);//Junk value. + boatLocationMessage.setApparentWindAngle((short)0);//Junk value. + boatLocationMessage.setTrueWindSpeed(0);//Junk value. + boatLocationMessage.setTrueWindAngle((short)0);//Junk value. + + boatLocationMessage.setCurrentDrift(0);//Junk value. + boatLocationMessage.setCurrentSet(0);//Junk value. + boatLocationMessage.setRudderAngle((short)0);//Junk value. + + //We have finished creating the message. + //TODO at this point, we need to send the event to the visualiser. + System.out.println(boatLocationMessage);//TEMP debug print + + } else { - System.out.println("Race is over"); + System.out.println("Race is over");//TEMP debug print //raceFinish = true; stop(); } @@ -194,7 +236,7 @@ public class Race implements Runnable { boat.setPosition("-"); } } - System.out.println("====="); + System.out.println("=====");//TEMP debug print } public void initialiseBoats() { diff --git a/mock/src/main/java/seng302/RaceEventMessages/BoatLocationMessage.java b/mock/src/main/java/seng302/RaceEventMessages/BoatLocationMessage.java index 9bacd840..425b86f0 100644 --- a/mock/src/main/java/seng302/RaceEventMessages/BoatLocationMessage.java +++ b/mock/src/main/java/seng302/RaceEventMessages/BoatLocationMessage.java @@ -4,6 +4,8 @@ package seng302.RaceEventMessages; * Created by f123 on 21-Apr-17. */ +import seng302.Constants; + /** * Represents the information in a boat location message (AC streaming spec: 4.9). */ @@ -442,4 +444,112 @@ public class BoatLocationMessage return angleShort; } + + /** + * Converts a double representing the speed of a boat in knots to an int in millimeters per second, as required by the streaming spec format. + * @param speed Speed in knots, stored as a double. + * @return Speed in millimeters per second, stored as an int (using only the two least significant bytes). + */ + public static int convertBoatSpeedDoubleToInt(double speed) + { + //Calculate meters per second. + double metersPerSecond = speed * Constants.KnotsToMetersPerSecondConversionFactor; + + //Calculate millimeters per second. + double millimetersPerSecond = metersPerSecond * 1000.0; + + //Convert to an int. + int millimetersPerSecondInt = (int)Math.round(millimetersPerSecond); + + return millimetersPerSecondInt; + } + + + /** + * Converts an int representing the speed of a boat in millimeters per second to a double in knots, as required by the streaming spec format. + * @param speed Speed in millimeters per second, stored as an int. + * @return Speed in knots, stored as a double. + */ + public static double convertBoatSpeedIntToDouble(int speed) + { + //Calculate meters per second. + double metersPerSecond = speed / 1000.0; + + //Calculate knots. + double knots = metersPerSecond / Constants.KnotsToMetersPerSecondConversionFactor; + + return knots; + } + + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + + builder.append("Message version number: "); + builder.append(this.getMessageVersionNumber()); + + builder.append("\nTime: "); + builder.append(this.getTime()); + + builder.append("\nSource ID: "); + builder.append(this.getSourceID()); + + builder.append("\nSequence number: "); + builder.append(this.getSequenceNumber()); + + builder.append("\nDevice type: "); + builder.append(this.getDeviceType()); + + builder.append("\nLatitude: "); + builder.append(this.getLatitude()); + + builder.append("\nLongitude: "); + builder.append(this.getLongitude()); + + builder.append("\nAltitude: "); + builder.append(this.getAltitude()); + + builder.append("\nHeading: "); + builder.append(this.getHeading()); + + builder.append("\nPitch: "); + builder.append(this.getPitch()); + + builder.append("\nRoll: "); + builder.append(this.getRoll()); + + builder.append("\nBoat speed (mm/sec): "); + builder.append(this.getBoatSpeed()); + + builder.append("\nBoat COG: "); + builder.append(this.getBoatCOG()); + + builder.append("\nBoat SOG: "); + builder.append(this.getBoatSOG()); + + builder.append("\nApparent wind speed: "); + builder.append(this.getApparentWindSpeed()); + + builder.append("\nApparent wind angle: "); + builder.append(this.getApparentWindAngle()); + + builder.append("\nTrue wind speed: "); + builder.append(this.getTrueWindSpeed()); + + builder.append("\nTrue wind angle: "); + builder.append(this.getTrueWindAngle()); + + builder.append("\nCurrent drift: "); + builder.append(this.getCurrentDrift()); + + builder.append("\nCurrent set: "); + builder.append(this.getCurrentSet()); + + builder.append("\nRudder angle: "); + builder.append(this.getRudderAngle()); + + return builder.toString(); + } } From 2ce84e3be49b410576e1b80459e80b18d3640e02 Mon Sep 17 00:00:00 2001 From: fjc40 Date: Mon, 24 Apr 2017 20:23:29 +1200 Subject: [PATCH 2/4] Added myself to the .mailmap file. --- .mailmap | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.mailmap b/.mailmap index 667de320..c5401576 100644 --- a/.mailmap +++ b/.mailmap @@ -16,4 +16,5 @@ # https://www.kernel.org/pub/software/scm/git/docs/git-shortlog.html # http://stacktoheap.com/blog/2013/01/06/using-mailmap-to-fix-authors-list-in-git/ Erika Savell -Connor Taylor-Brown \ No newline at end of file +Connor Taylor-Brown +Fraser Cope From bf5ea193af63f4c5d8b14c30a730b9e95cfa2f9b Mon Sep 17 00:00:00 2001 From: fjc40 Date: Mon, 24 Apr 2017 21:53:51 +1200 Subject: [PATCH 3/4] Mock App now passes an OutputStream into the "Event" class. This is where data is written to (i.e., writing data over tcp socket). Updated Event and Race class to write to this stream, and added some TODO notes which point out where we need to properly serialize messages, when merged with networking code. --- mock/src/main/java/seng302/App.java | 4 +- mock/src/main/java/seng302/Data/RaceData.java | 15 +++-- mock/src/main/java/seng302/Model/Event.java | 66 +++++++++++++++---- mock/src/main/java/seng302/Model/Race.java | 26 ++++++-- 4 files changed, 88 insertions(+), 23 deletions(-) diff --git a/mock/src/main/java/seng302/App.java b/mock/src/main/java/seng302/App.java index cc2122cb..16890a4d 100644 --- a/mock/src/main/java/seng302/App.java +++ b/mock/src/main/java/seng302/App.java @@ -8,6 +8,7 @@ import seng302.Model.Event; import javax.xml.parsers.ParserConfigurationException; import java.io.IOException; +import java.io.OutputStream; public class App extends Application { @@ -23,8 +24,9 @@ public class App extends Application { @Override public void start(Stage primaryStage) { try { + OutputStream outputStream = System.out;//TEMP currently using System.out, but should replace this with tcp socket we are sending over. RaceDataSource raceData = new RaceXMLReader("raceXML/bermuda_AC35.xml"); - Event raceEvent = new Event(raceData); + Event raceEvent = new Event(raceData, outputStream); raceEvent.start(); } catch (IOException e) { e.printStackTrace(); diff --git a/mock/src/main/java/seng302/Data/RaceData.java b/mock/src/main/java/seng302/Data/RaceData.java index d16177da..fdc941b6 100644 --- a/mock/src/main/java/seng302/Data/RaceData.java +++ b/mock/src/main/java/seng302/Data/RaceData.java @@ -18,6 +18,7 @@ import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; +import java.io.StringWriter; import java.time.OffsetDateTime; import java.util.List; @@ -47,7 +48,7 @@ public class RaceData { } - public void createXML() { + public String createXML() { try { DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); @@ -148,14 +149,13 @@ public class RaceData { TransformerFactory transformerFactory = TransformerFactory.newInstance(); Transformer transformer = transformerFactory.newTransformer(); DOMSource source = new DOMSource(doc); - StreamResult result = new StreamResult(System.out); - // Output to console for testing - // StreamResult result = new StreamResult(System.out); + //Serialize document. + StringWriter stringWriter = new StringWriter(); + StreamResult result = new StreamResult(stringWriter); + transformer.transform(source,result); - transformer.transform(source, result); - - System.out.println("File saved!"); + return stringWriter.toString(); } catch (ParserConfigurationException pce) { @@ -164,6 +164,7 @@ public class RaceData { tfe.printStackTrace(); } + return "";//TEMP this is probably bad. This shouldn't really be reached, but seems necessary due to the use of catches above. } diff --git a/mock/src/main/java/seng302/Model/Event.java b/mock/src/main/java/seng302/Model/Event.java index 2b55a0bf..27df9e7f 100644 --- a/mock/src/main/java/seng302/Model/Event.java +++ b/mock/src/main/java/seng302/Model/Event.java @@ -13,6 +13,9 @@ import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; +import java.io.IOException; +import java.io.OutputStream; +import java.io.StringWriter; import java.util.List; /** @@ -22,16 +25,33 @@ public class Event { RaceDataSource raceDataSource; - public Event(RaceDataSource raceData) { + ///The stream to which we send all data. + private OutputStream outputStream; + + + + /** + * Ctor. + * @param raceData + * @param outputStream OutputStream to write data to. + */ + public Event(RaceDataSource raceData, OutputStream outputStream) { this.raceDataSource = raceData; + this.outputStream = outputStream; } - public void start() { + public void start() throws IOException + { + System.out.println("\nREGATTA DATA\n");//TEMP REMOVE debug sendRegattaData(); + System.out.println("\nRACE DATA\n");//TEMP REMOVE debug sendRaceData(); + System.out.println("\nBOAT DATA\n");//TEMP REMOVE debug sendBoatData(); - Race newRace = new Race(raceDataSource, 15); + System.out.println("RACE STARTING!!\n\n");//TEMP REMOVE debug + + Race newRace = new Race(raceDataSource, 15, this.outputStream); new Thread((newRace)).start(); } @@ -87,13 +107,21 @@ public class Event { magneticVariation.appendChild(doc.createTextNode(Double.toString(14.76))); rootElement.appendChild(magneticVariation); - TransformerFactory trasformerFactory = TransformerFactory.newInstance(); - Transformer transformer = trasformerFactory.newTransformer(); + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + Transformer transformer = transformerFactory.newTransformer(); DOMSource source = new DOMSource(doc); - //print XML object to check for correctness - StreamResult result = new StreamResult(System.out); + + + //Serialize document. + StringWriter stringWriter = new StringWriter(); + StreamResult result = new StreamResult(stringWriter); transformer.transform(source,result); + //TODO now we should place in XML message object. + //TODO now we should serialize xml message object. + //TODO now we should write serialized xml message over this.outputStream. + + this.outputStream.write(stringWriter.toString().getBytes());//TEMP currently we output the XML doc, not the serialized message. } catch (Exception e){ e.printStackTrace(); @@ -101,9 +129,17 @@ public class Event { } - public void sendRaceData() { + public void sendRaceData() throws IOException + { RaceData raceData = new RaceData(raceDataSource); - raceData.createXML(); + //Serialize race data to an XML as a string. + String xmlString = raceData.createXML(); + + //TODO now we should place in XML message object. + //TODO now we should serialize xml message object. + //TODO now we should write serialized xml message over this.outputStream. + + this.outputStream.write(xmlString.getBytes());//TEMP currently we output the XML doc, not the serialized message. } public void sendBoatData() { @@ -194,9 +230,17 @@ public class Event { Transformer transformer = trasformerFactory.newTransformer(); DOMSource source = new DOMSource(doc); - //print XML object to check for correctness - StreamResult result = new StreamResult(System.out); + + //Serialize document. + StringWriter stringWriter = new StringWriter(); + StreamResult result = new StreamResult(stringWriter); transformer.transform(source,result); + //TODO now we should place in XML message object. + //TODO now we should serialize xml message object. + //TODO now we should write serialized xml message over this.outputStream. + + this.outputStream.write(stringWriter.toString().getBytes());//TEMP currently we output the XML doc, not the serialized message. + } catch (Exception e) { e.printStackTrace(); diff --git a/mock/src/main/java/seng302/Model/Race.java b/mock/src/main/java/seng302/Model/Race.java index 3e7de7bc..a1e727f6 100644 --- a/mock/src/main/java/seng302/Model/Race.java +++ b/mock/src/main/java/seng302/Model/Race.java @@ -15,6 +15,8 @@ import seng302.RaceEventMessages.BoatLocationMessage; import java.awt.geom.Point2D; +import java.io.IOException; +import java.io.OutputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -39,26 +41,33 @@ public class Race implements Runnable { protected int PRERACE_TIME = 120000; //time in milliseconds to pause during pre-race + //Outputstream to write messages to. + private OutputStream outputStream; + /** * Initailiser for Race * * @param boats Takes in an array of boats that are participating in the race. * @param legs Number of marks in order that the boats pass in order to complete the race. * @param scaleFactor for race + * @param outputStream Outputstream to write messages to. */ - public Race(List boats, List legs, int scaleFactor) { + public Race(List boats, List legs, int scaleFactor, OutputStream outputStream) { this.startingBoats = FXCollections.observableArrayList(boats); this.legs = legs; this.legs.add(new Leg("Finish", this.legs.size())); this.scaleFactor = scaleFactor; + this.outputStream = outputStream; + if (startingBoats != null && startingBoats.size() > 0) { initialiseBoats(); } + } - public Race(RaceDataSource raceData, int scaleFactor) { - this(raceData.getBoats(), raceData.getLegs(), scaleFactor); + public Race(RaceDataSource raceData, int scaleFactor, OutputStream outputStream) { + this(raceData.getBoats(), raceData.getLegs(), scaleFactor, outputStream); } /** @@ -209,7 +218,16 @@ public class Race implements Runnable { //We have finished creating the message. //TODO at this point, we need to send the event to the visualiser. - System.out.println(boatLocationMessage);//TEMP debug print + //System.out.println(boatLocationMessage);//TEMP debug print + try + { + //TODO we should actually serialize the boat message before writing to output. + outputStream.write(boatLocationMessage.toString().getBytes()); + } + catch (IOException e) + { + e.printStackTrace(); + } } else { From 2876eec1e44b18e967243645a759454b49c747bd Mon Sep 17 00:00:00 2001 From: fjc40 Date: Tue, 25 Apr 2017 11:24:33 +1200 Subject: [PATCH 4/4] Added some exception classes to encapsulate the internal exceptions that can occur when sending Boat/race/regatta data. #story[778] --- .../Exceptions/InvalidBoatDataException.java | 21 ++ .../Exceptions/InvalidRaceDataException.java | 20 + .../InvalidRegattaDataException.java | 20 + mock/src/main/java/seng302/Model/Event.java | 342 +++++++++++------- 4 files changed, 266 insertions(+), 137 deletions(-) create mode 100644 mock/src/main/java/seng302/Exceptions/InvalidBoatDataException.java create mode 100644 mock/src/main/java/seng302/Exceptions/InvalidRaceDataException.java create mode 100644 mock/src/main/java/seng302/Exceptions/InvalidRegattaDataException.java diff --git a/mock/src/main/java/seng302/Exceptions/InvalidBoatDataException.java b/mock/src/main/java/seng302/Exceptions/InvalidBoatDataException.java new file mode 100644 index 00000000..7bf7a360 --- /dev/null +++ b/mock/src/main/java/seng302/Exceptions/InvalidBoatDataException.java @@ -0,0 +1,21 @@ +package seng302.Exceptions; + +/** + * Created by f123 on 25-Apr-17. + */ + +/** + * An exception thrown when we cannot generate Boats.xml and send an XML message. + */ +public class InvalidBoatDataException extends RuntimeException +{ + + public InvalidBoatDataException() + { + } + + public InvalidBoatDataException(String message) + { + super(message); + } +} diff --git a/mock/src/main/java/seng302/Exceptions/InvalidRaceDataException.java b/mock/src/main/java/seng302/Exceptions/InvalidRaceDataException.java new file mode 100644 index 00000000..424fb0d5 --- /dev/null +++ b/mock/src/main/java/seng302/Exceptions/InvalidRaceDataException.java @@ -0,0 +1,20 @@ +package seng302.Exceptions; + +/** + * Created by f123 on 25-Apr-17. + */ + +/** + * Exception thrown when we cannot generate Race.xml data, and send an XML message. + */ +public class InvalidRaceDataException extends RuntimeException +{ + public InvalidRaceDataException() + { + } + + public InvalidRaceDataException(String message) + { + super(message); + } +} diff --git a/mock/src/main/java/seng302/Exceptions/InvalidRegattaDataException.java b/mock/src/main/java/seng302/Exceptions/InvalidRegattaDataException.java new file mode 100644 index 00000000..bff8ce03 --- /dev/null +++ b/mock/src/main/java/seng302/Exceptions/InvalidRegattaDataException.java @@ -0,0 +1,20 @@ +package seng302.Exceptions; + +/** + * Created by f123 on 25-Apr-17. + */ + +/** + * An exception thrown when a Regatta.xml message cannot be generated and sent. + */ +public class InvalidRegattaDataException extends RuntimeException +{ + public InvalidRegattaDataException() + { + } + + public InvalidRegattaDataException(String message) + { + super(message); + } +} diff --git a/mock/src/main/java/seng302/Model/Event.java b/mock/src/main/java/seng302/Model/Event.java index 27df9e7f..614d05bf 100644 --- a/mock/src/main/java/seng302/Model/Event.java +++ b/mock/src/main/java/seng302/Model/Event.java @@ -4,12 +4,18 @@ import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; import seng302.Data.RaceData; +import seng302.Exceptions.InvalidBoatDataException; +import seng302.Exceptions.InvalidRaceDataException; +import seng302.Exceptions.InvalidRegattaDataException; import seng302.Model.Race; import seng302.RaceDataSource; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; @@ -40,7 +46,7 @@ public class Event { this.outputStream = outputStream; } - public void start() throws IOException + public void start() { System.out.println("\nREGATTA DATA\n");//TEMP REMOVE debug sendRegattaData(); @@ -56,80 +62,107 @@ public class Event { } - public void sendRegattaData() { - try { + public void sendRegattaData() throws InvalidRegattaDataException { - DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); - DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); - //root element - Document doc = docBuilder.newDocument(); - Element rootElement = doc.createElement("RegattaConfig"); - doc.appendChild(rootElement); - - //regattaID element - Element regattaID = doc.createElement("RegattaID"); - regattaID.appendChild(doc.createTextNode("3")); - rootElement.appendChild(regattaID); - - //regattaName element - Element regattaName = doc.createElement("RegattaName"); - regattaName.appendChild(doc.createTextNode("New Zealand Test")); - rootElement.appendChild(regattaName); - - //courseName element - Element courseName = doc.createElement("CourseName"); - courseName.appendChild(doc.createTextNode("North Head")); - rootElement.appendChild(courseName); - - //centralLatitude element - Element centralLat = doc.createElement("CentralLatitude"); - centralLat.appendChild(doc.createTextNode(Double.toString(32.293039))); - rootElement.appendChild(centralLat); - - //centralLongitude element - Element centralLong = doc.createElement("CentralLongitude"); - centralLong.appendChild(doc.createTextNode(Double.toString(-64.843983))); - rootElement.appendChild(centralLong); - - //centralAltitude element - Element centralAlt = doc.createElement("CentralAltitude"); - centralAlt.appendChild(doc.createTextNode(Double.toString(0))); - rootElement.appendChild(centralAlt); - - //utcOffset element - Element utcOffset = doc.createElement("UtcOffset"); - utcOffset.appendChild(doc.createTextNode(Double.toString(-3))); - rootElement.appendChild(utcOffset); - - //magneticVariation element - Element magneticVariation = doc.createElement("MagneticVariation"); - magneticVariation.appendChild(doc.createTextNode(Double.toString(14.76))); - rootElement.appendChild(magneticVariation); + DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder docBuilder = null; + try + { + docBuilder = docFactory.newDocumentBuilder(); + } + catch (ParserConfigurationException e) + { + throw new InvalidRegattaDataException(); + } - TransformerFactory transformerFactory = TransformerFactory.newInstance(); - Transformer transformer = transformerFactory.newTransformer(); - DOMSource source = new DOMSource(doc); + //root element + Document doc = docBuilder.newDocument(); + Element rootElement = doc.createElement("RegattaConfig"); + doc.appendChild(rootElement); + + //regattaID element + Element regattaID = doc.createElement("RegattaID"); + regattaID.appendChild(doc.createTextNode("3")); + rootElement.appendChild(regattaID); + + //regattaName element + Element regattaName = doc.createElement("RegattaName"); + regattaName.appendChild(doc.createTextNode("New Zealand Test")); + rootElement.appendChild(regattaName); + + //courseName element + Element courseName = doc.createElement("CourseName"); + courseName.appendChild(doc.createTextNode("North Head")); + rootElement.appendChild(courseName); + + //centralLatitude element + Element centralLat = doc.createElement("CentralLatitude"); + centralLat.appendChild(doc.createTextNode(Double.toString(32.293039))); + rootElement.appendChild(centralLat); + + //centralLongitude element + Element centralLong = doc.createElement("CentralLongitude"); + centralLong.appendChild(doc.createTextNode(Double.toString(-64.843983))); + rootElement.appendChild(centralLong); + + //centralAltitude element + Element centralAlt = doc.createElement("CentralAltitude"); + centralAlt.appendChild(doc.createTextNode(Double.toString(0))); + rootElement.appendChild(centralAlt); + + //utcOffset element + Element utcOffset = doc.createElement("UtcOffset"); + utcOffset.appendChild(doc.createTextNode(Double.toString(-3))); + rootElement.appendChild(utcOffset); + + //magneticVariation element + Element magneticVariation = doc.createElement("MagneticVariation"); + magneticVariation.appendChild(doc.createTextNode(Double.toString(14.76))); + rootElement.appendChild(magneticVariation); + + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + Transformer transformer = null; + try + { + transformer = transformerFactory.newTransformer(); + } + catch (TransformerConfigurationException e) + { + throw new InvalidRegattaDataException(); + } + DOMSource source = new DOMSource(doc); - //Serialize document. - StringWriter stringWriter = new StringWriter(); - StreamResult result = new StreamResult(stringWriter); + //Serialize document. + StringWriter stringWriter = new StringWriter(); + StreamResult result = new StreamResult(stringWriter); + try + { transformer.transform(source,result); - //TODO now we should place in XML message object. - //TODO now we should serialize xml message object. - //TODO now we should write serialized xml message over this.outputStream. + } + catch (TransformerException e) + { + throw new InvalidRegattaDataException(); + } + //TODO now we should place in XML message object. + //TODO now we should serialize xml message object. + //TODO now we should write serialized xml message over this.outputStream. + try + { this.outputStream.write(stringWriter.toString().getBytes());//TEMP currently we output the XML doc, not the serialized message. - - } catch (Exception e){ - e.printStackTrace(); } + catch (IOException e) + { + throw new InvalidRegattaDataException(); + } + } - public void sendRaceData() throws IOException + public void sendRaceData() throws InvalidRaceDataException { RaceData raceData = new RaceData(raceDataSource); //Serialize race data to an XML as a string. @@ -139,112 +172,147 @@ public class Event { //TODO now we should serialize xml message object. //TODO now we should write serialized xml message over this.outputStream. - this.outputStream.write(xmlString.getBytes());//TEMP currently we output the XML doc, not the serialized message. + try + { + this.outputStream.write(xmlString.getBytes());//TEMP currently we output the XML doc, not the serialized message. + } + catch (IOException e) + { + throw new InvalidRaceDataException(); + } } - public void sendBoatData() { + public void sendBoatData() throws InvalidBoatDataException + { List boatData = raceDataSource.getBoats(); - try { - DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); - DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); - //root element - Document doc = docBuilder.newDocument(); - Element rootElement = doc.createElement("BoatConfig"); - doc.appendChild(rootElement); + DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder docBuilder = null; - //Boats element - Element boats = doc.createElement("Boats"); - rootElement.appendChild(boats); + try + { + docBuilder = docFactory.newDocumentBuilder(); + } + catch (ParserConfigurationException e) + { + throw new InvalidBoatDataException(); + } - for (int i=0; i < boatData.size(); i++) { + //root element + Document doc = docBuilder.newDocument(); + Element rootElement = doc.createElement("BoatConfig"); + doc.appendChild(rootElement); - //Boat element - Element boat = doc.createElement("Boat"); + //Boats element + Element boats = doc.createElement("Boats"); + rootElement.appendChild(boats); - //Type attribute - Attr attrType = doc.createAttribute("Type"); - attrType.setValue("Mark"); - boat.setAttributeNode(attrType); + for (int i=0; i < boatData.size(); i++) { - //SourceID attribute - Attr attrSourceID = doc.createAttribute("SourceID"); - attrSourceID.setValue(Integer.toString(boatData.get(i).getSourceID())); - boat.setAttributeNode(attrSourceID); + //Boat element + Element boat = doc.createElement("Boat"); - //ShapeID attribute - Attr attrShapeID = doc.createAttribute("ShapeID"); - attrShapeID.setValue("0"); - boat.setAttributeNode(attrShapeID); + //Type attribute + Attr attrType = doc.createAttribute("Type"); + attrType.setValue("Mark"); + boat.setAttributeNode(attrType); - //HullNum attribute - Attr attrHullNum = doc.createAttribute("HullNum"); - attrHullNum.setValue("RG01"); - boat.setAttributeNode(attrHullNum); + //SourceID attribute + Attr attrSourceID = doc.createAttribute("SourceID"); + attrSourceID.setValue(Integer.toString(boatData.get(i).getSourceID())); + boat.setAttributeNode(attrSourceID); - //StoweName attribute - Attr attrStoweName = doc.createAttribute("StoweName"); - attrStoweName.setValue(boatData.get(i).getAbbrev()); - boat.setAttributeNode(attrStoweName); + //ShapeID attribute + Attr attrShapeID = doc.createAttribute("ShapeID"); + attrShapeID.setValue("0"); + boat.setAttributeNode(attrShapeID); - //ShortName attribute - Attr attrShortName = doc.createAttribute("ShortName"); - attrShortName.setValue(boatData.get(i).getAbbrev()); - boat.setAttributeNode(attrShortName); + //HullNum attribute + Attr attrHullNum = doc.createAttribute("HullNum"); + attrHullNum.setValue("RG01"); + boat.setAttributeNode(attrHullNum); - //BoatName attribute - Attr attrBoatName = doc.createAttribute("BoatName"); - attrBoatName.setValue(boatData.get(i).toString()); - boat.setAttributeNode(attrBoatName); + //StoweName attribute + Attr attrStoweName = doc.createAttribute("StoweName"); + attrStoweName.setValue(boatData.get(i).getAbbrev()); + boat.setAttributeNode(attrStoweName); - //GPSCoord for element - Element GPSCoord = doc.createElement("GPSposition"); + //ShortName attribute + Attr attrShortName = doc.createAttribute("ShortName"); + attrShortName.setValue(boatData.get(i).getAbbrev()); + boat.setAttributeNode(attrShortName); - //Z axis attribute - Attr attrZCoord = doc.createAttribute("Z"); - attrZCoord.setValue("0"); - GPSCoord.setAttributeNode(attrZCoord); + //BoatName attribute + Attr attrBoatName = doc.createAttribute("BoatName"); + attrBoatName.setValue(boatData.get(i).toString()); + boat.setAttributeNode(attrBoatName); - //Y axis attribute - Attr attrYCoord = doc.createAttribute("Y"); - attrYCoord.setValue(Double.toString(boatData.get(i).getCurrentPosition().getLatitude())); - GPSCoord.setAttributeNode(attrYCoord); + //GPSCoord for element + Element GPSCoord = doc.createElement("GPSposition"); - //X axis attribute - Attr attrXCoord = doc.createAttribute("X"); - attrXCoord.setValue(Double.toString(boatData.get(i).getCurrentPosition().getLongitude())); - GPSCoord.setAttributeNode(attrXCoord); + //Z axis attribute + Attr attrZCoord = doc.createAttribute("Z"); + attrZCoord.setValue("0"); + GPSCoord.setAttributeNode(attrZCoord); - //Write GPSCoord to boat - boat.appendChild(GPSCoord); + //Y axis attribute + Attr attrYCoord = doc.createAttribute("Y"); + attrYCoord.setValue(Double.toString(boatData.get(i).getCurrentPosition().getLatitude())); + GPSCoord.setAttributeNode(attrYCoord); - //Write boat to boats - boats.appendChild(boat); + //X axis attribute + Attr attrXCoord = doc.createAttribute("X"); + attrXCoord.setValue(Double.toString(boatData.get(i).getCurrentPosition().getLongitude())); + GPSCoord.setAttributeNode(attrXCoord); - } + //Write GPSCoord to boat + boat.appendChild(GPSCoord); - TransformerFactory trasformerFactory = TransformerFactory.newInstance(); - Transformer transformer = trasformerFactory.newTransformer(); - DOMSource source = new DOMSource(doc); + //Write boat to boats + boats.appendChild(boat); + } - //Serialize document. - StringWriter stringWriter = new StringWriter(); - StreamResult result = new StreamResult(stringWriter); - transformer.transform(source,result); - //TODO now we should place in XML message object. - //TODO now we should serialize xml message object. - //TODO now we should write serialized xml message over this.outputStream. + TransformerFactory trasformerFactory = TransformerFactory.newInstance(); + Transformer transformer = null; + try + { + transformer = trasformerFactory.newTransformer(); + } + catch (TransformerConfigurationException e) + { + throw new InvalidBoatDataException(); + } + DOMSource source = new DOMSource(doc); - this.outputStream.write(stringWriter.toString().getBytes());//TEMP currently we output the XML doc, not the serialized message. + //Serialize document. + StringWriter stringWriter = new StringWriter(); + StreamResult result = new StreamResult(stringWriter); + try + { + transformer.transform(source,result); + } + catch (TransformerException e) + { + throw new InvalidBoatDataException(); + } + //TODO now we should place in XML message object. + //TODO now we should serialize xml message object. + //TODO now we should write serialized xml message over this.outputStream. - } catch (Exception e) { - e.printStackTrace(); + try + { + this.outputStream.write(stringWriter.toString().getBytes());//TEMP currently we output the XML doc, not the serialized message. } + catch (IOException e) + { + throw new InvalidBoatDataException(); + } + }