You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

231 lines
7.4 KiB

package seng302.Data;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import seng302.DataInput.RaceDataSource;
import seng302.Exceptions.InvalidRaceDataException;
import seng302.Model.Boat;
import seng302.Model.GPSCoordinate;
import seng302.Model.Marker;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
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;
/**
* Created by esa46 on 21/04/17.
*/
public class RaceData {
private RaceDataSource dataSource;
private Document doc;
private Element rootElement;
private OffsetDateTime creationTimeDate;
public RaceData(RaceDataSource dataSource) {
this.dataSource = dataSource;
creationTimeDate = OffsetDateTime.now();
}
/**
* Creates an AC35 officially formatted xml description of a race.
*
* @return String containing xml-formatted race description
*/
public String createXML() {
try {
//create base xml document
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
doc = docBuilder.newDocument();
//create root element (In this case, "Race")
rootElement = doc.createElement("Race");
doc.appendChild(rootElement);
appendChildElements();
// write the content into xml file
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
//Serialize document.
StringWriter stringWriter = new StringWriter();
StreamResult result = new StreamResult(stringWriter);
transformer.transform(source, result);
return stringWriter.toString();
} catch (ParserConfigurationException pce) {
throw new InvalidRaceDataException();
} catch (TransformerException tfe) {
throw new InvalidRaceDataException();
}
}
/**
* Creates all necessary child elements and appends them to the xml doc
*/
private void appendChildElements() {
appendRaceId();
appendRaceType();
appendCreationTimeDate();
appendRaceStartTime();
appendParticipants();
appendCourse();
appendCourseLimit();
}
/**
* Creates and appends race id element
*/
private void appendRaceId() {
Element raceIdElement = doc.createElement("RaceID");
raceIdElement.appendChild(doc.createTextNode(dataSource.getRaceId()));
rootElement.appendChild(raceIdElement);
}
/**
* Creates and appends race type element
*/
private void appendRaceType() {
Element raceTypeElement = doc.createElement("RaceType");
raceTypeElement.appendChild(doc.createTextNode(dataSource.getRaceType()));
rootElement.appendChild(raceTypeElement);
}
/**
* Creates and appends creation time date element
*/
private void appendCreationTimeDate() {
Element creationTimeElement = doc.createElement("CreationTimeDate");
creationTimeElement.appendChild(doc.createTextNode(creationTimeDate.toString()));
rootElement.appendChild(creationTimeElement);
}
/**
* Creates and appends race start time element, which is 3 minutes after the race was created by default
*/
private void appendRaceStartTime() {
Element startTimeElement = doc.createElement("RaceStartTime");
startTimeElement.setAttribute("Time", (creationTimeDate.plusMinutes(3)).toString());
startTimeElement.setAttribute("Postpone", "false");
rootElement.appendChild(startTimeElement);
}
/**
* Creates and appends participants element
*/
private void appendParticipants() {
Element participantsElement = doc.createElement("Participants");
for (Boat boat : dataSource.getBoats()) {
Element yachtElement = doc.createElement("Yacht");
yachtElement.setAttribute("SourceID", boat.getSourceID() + "");
participantsElement.appendChild(yachtElement);
}
rootElement.appendChild(participantsElement);
}
/**
* Creates and appends course elements
*/
private void appendCourse() {
Element courseElement = doc.createElement("Course");
Element compoundMarkSeqElement = doc.createElement("CompoundMarkSequence");
int i = 1;
for (Marker marker : dataSource.getMarkers()) {
courseElement.appendChild(createCompoundMarker(marker, i));
compoundMarkSeqElement.appendChild(createCornerElement(i));
i++;
}
rootElement.appendChild(compoundMarkSeqElement);
rootElement.appendChild(courseElement);
}
/**
* Creates a mark element for insertion in a coumpound mark element
*
* @param marker GPS coordinates of the mark
* @return Element mark element
*/
private Element createMark(GPSCoordinate marker) {
Element mark = doc.createElement("Mark");
mark.setAttribute("TargetLat", marker.getLatitude() + "");
mark.setAttribute("TargetLng", marker.getLongitude() + "");
return mark;
}
/**
* Creates a compound marker holding one or two marks,and a sequence number
*
* @param marker marker
* @param i sequence number
* @return Element compound mark element
*/
private Element createCompoundMarker(Marker marker, int i) {
Element compoundMarkElement = doc.createElement("CompoundMark");
compoundMarkElement.setAttribute("CompoundMarkId", i + "");
compoundMarkElement.setAttribute("Name", marker.getName());
compoundMarkElement.appendChild(createMark(marker.getMark1()));
if (!(marker.getMark1().equals(marker.getMark2()))) {
compoundMarkElement.appendChild(createMark(marker.getMark2()));
}
return compoundMarkElement;
}
/**
* Creates a corner element
*
* @param i sequence number
* @return Element corner element
*/
private Element createCornerElement(int i) {
Element cornerElement = doc.createElement("Corner");
cornerElement.setAttribute("SeqID", i + "");
cornerElement.setAttribute("CompoundMarkID", i + "");
return cornerElement;
}
/**
* Creates and appends course limits element (boundaries)
*/
private void appendCourseLimit() {
int j = 1;
Element courseLimitElement = doc.createElement("CourseLimit");
for (GPSCoordinate coordinate : dataSource.getBoundary()) {
Element limitElement = doc.createElement("Limit");
limitElement.setAttribute("SeqID", j + "");
limitElement.setAttribute("Lat", coordinate.getLatitude() + "");
limitElement.setAttribute("Lon", coordinate.getLongitude() + "");
courseLimitElement.appendChild(limitElement);
j++;
}
rootElement.appendChild(courseLimitElement);
}
}