diff --git a/src/main/java/seng302/Networking/RaceMessage.java b/src/main/java/seng302/Networking/RaceMessage.java index 23c3541c..60ed399f 100644 --- a/src/main/java/seng302/Networking/RaceMessage.java +++ b/src/main/java/seng302/Networking/RaceMessage.java @@ -1,4 +1,4 @@ -package seng302.Model; +package seng302.Networking; /** * Created by fwy13 on 19/04/17. diff --git a/src/main/java/seng302/Networking/RaceVisionByteEncoder.java b/src/main/java/seng302/Networking/RaceVisionByteEncoder.java index b30f878d..383edb79 100644 --- a/src/main/java/seng302/Networking/RaceVisionByteEncoder.java +++ b/src/main/java/seng302/Networking/RaceVisionByteEncoder.java @@ -1,10 +1,9 @@ -package seng302.Model; +package seng302.Networking; + +import seng302.Model.BoatInRace; -import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; -import java.nio.charset.Charset; import java.util.ArrayList; -import java.util.Arrays; /** * Created by fwy13 on 19/04/17. diff --git a/src/main/java/seng302/XMLMessageDecoder.java b/src/main/java/seng302/XMLMessageDecoder.java new file mode 100644 index 00000000..1ff42831 --- /dev/null +++ b/src/main/java/seng302/XMLMessageDecoder.java @@ -0,0 +1,102 @@ +package seng302; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.Arrays; + +/** + * Created by hba56 on 20/04/17. + */ +public class XMLMessageDecoder { + private byte messageVersionNumber; + private short ackNumber; + private long timeStamp; + private byte xmlMsgSubType; + private short sequenceNumber; + private short xmlMsgLength; + private String xmlMessage; + + private byte[] bytes; + + public XMLMessageDecoder(byte[] bytes) { + this.bytes = bytes; + } + + public void decode(){ + byte[] ackNumberBytes = Arrays.copyOfRange(bytes, 1, 3); + byte[] timeStampBytes = Arrays.copyOfRange(bytes, 3, 9); + byte[] sequenceNumberBytes = Arrays.copyOfRange(bytes, 10, 12); + byte[] xmlMsgLengthBytes = Arrays.copyOfRange(bytes, 12, 14); + byte[] xmlMessagebytes = Arrays.copyOfRange(bytes, 14, bytes.length); + + this.xmlMsgSubType = bytes[9]; + this.messageVersionNumber = bytes[0]; + this.ackNumber = bytesToShort(ackNumberBytes); + + this.timeStamp = bytesToLong(timeStampBytes); + + this.sequenceNumber = bytesToShort(sequenceNumberBytes); + this.xmlMsgLength = bytesToShort(xmlMsgLengthBytes); + this.xmlMessage = new String(xmlMessagebytes); + } + + private short bytesToShort(byte[] bytesShort){ + ByteBuffer byteBuffer = ByteBuffer.allocate(2); + byteBuffer.order(ByteOrder.LITTLE_ENDIAN); + byteBuffer.put(bytesShort[0]); + byteBuffer.put(bytesShort[1]); + short shortVal = byteBuffer.getShort(0); + return shortVal; + } + + private long bytesToLong(byte[] bytesLong){ + ByteBuffer byteBuffer = ByteBuffer.allocate(8); + byteBuffer.order(ByteOrder.BIG_ENDIAN); + byteBuffer.put((byte)0); + byteBuffer.put((byte)0); + byteBuffer.put(bytesLong[0]); + byteBuffer.put(bytesLong[1]); + byteBuffer.put(bytesLong[2]); + byteBuffer.put(bytesLong[3]); + byteBuffer.put(bytesLong[4]); + byteBuffer.put(bytesLong[5]); + +// System.out.println("====decode===="); +// for (byte i:byteBuffer.array() +// ) { +// System.out.println(i); +// } +// System.out.println("====decode===="); + + long longVal = byteBuffer.getLong(0); + return longVal; + } + + public byte getMessageVersionNumber() { + return messageVersionNumber; + } + + public short getAckNumber() { + return ackNumber; + } + + public long getTimeStamp() { + return timeStamp; + } + + public byte getXmlMsgSubType() { + return xmlMsgSubType; + } + + public short getSequenceNumber() { + return sequenceNumber; + } + + public short getXmlMsgLength() { + return xmlMsgLength; + } + + public String getXmlMessage() { + return xmlMessage; + } +} diff --git a/src/main/java/seng302/XMLMessageEncoder.java b/src/main/java/seng302/XMLMessageEncoder.java new file mode 100644 index 00000000..85cd5d2f --- /dev/null +++ b/src/main/java/seng302/XMLMessageEncoder.java @@ -0,0 +1,77 @@ +package seng302; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.Arrays; + +/** + * Encodes a XML file into a message of AC35 format + */ +public class XMLMessageEncoder { + private byte messageVersionNumber; + private short ackNumber; + private long timeStamp; + private byte xmlMsgSubType; + private short sequenceNumber; + private short xmlMsgLength; + private String xmlMessage; + + public XMLMessageEncoder(byte messageVersionNumber, short ackNumber, long timeStamp, byte xmlMsgSubType, short sequenceNumber, short xmlMsgLenght, String xmlMessage) { + this.messageVersionNumber = messageVersionNumber; + this.ackNumber = ackNumber; + this.timeStamp = timeStamp; + this.xmlMsgSubType = xmlMsgSubType; + this.sequenceNumber = sequenceNumber; + this.xmlMsgLength = xmlMsgLenght; + this.xmlMessage = xmlMessage; + } + + public byte[] encode() { + byte[] messageBytes = xmlMessage.getBytes(); + if (messageBytes.length > this.xmlMsgLength) { + //System.err.println("Xml message is to big"); + return null; + } + ByteBuffer tempOutputByteBuffer = ByteBuffer.allocate(14 + messageBytes.length); + + //ackNumber converted to bytes + byte[] ackNumberBytes = new byte[2]; + ackNumberBytes[0] = (byte) (ackNumber & 0xff); + ackNumberBytes[1] = (byte) ((ackNumber >> 8) & 0xff); + + //sequenceNumber converted to bytes + byte[] sequenceNumberBytes = new byte[2]; + sequenceNumberBytes[0] = (byte) (sequenceNumber & 0xff); + sequenceNumberBytes[1] = (byte) ((sequenceNumber >> 8) & 0xff); + + //xmlMsgLength converted to bytes + byte[] xmlMsgLengthBytes = new byte[2]; + xmlMsgLengthBytes[0] = (byte) (xmlMsgLength & 0xff); + xmlMsgLengthBytes[1] = (byte) ((xmlMsgLength >> 8) & 0xff); + + + tempOutputByteBuffer.put(messageVersionNumber); + tempOutputByteBuffer.put(ackNumberBytes); + tempOutputByteBuffer.put(longToSixBytes(timeStamp)); + tempOutputByteBuffer.put(xmlMsgSubType); + tempOutputByteBuffer.put(sequenceNumberBytes); + tempOutputByteBuffer.put(xmlMsgLengthBytes); + tempOutputByteBuffer.put(messageBytes); + + return tempOutputByteBuffer.array(); + } + + private byte[] longToSixBytes(long x) { + ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES); + buffer.putLong(x); + +// System.out.println("====encode===="); +// for (byte i:buffer.array() +// ) { +// System.out.println(i); +// } +// System.out.println("====encode===="); + + return Arrays.copyOfRange(buffer.array(), 2, 8); + } +} diff --git a/src/test/java/XMLMessageDecoderTest.java b/src/test/java/XMLMessageDecoderTest.java new file mode 100644 index 00000000..a373db5a --- /dev/null +++ b/src/test/java/XMLMessageDecoderTest.java @@ -0,0 +1,47 @@ +import org.junit.Assert; +import org.junit.Test; +import seng302.XMLMessageDecoder; +import seng302.XMLMessageEncoder; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +/** + * Created by hba56 on 20/04/17. + */ +public class XMLMessageDecoderTest { + @Test + public void getByteArrayTest(){ + try{ + StringBuilder xmlString; + BufferedReader br = new BufferedReader(new InputStreamReader( + this.getClass().getResourceAsStream(("raceXML/Regatta.xml")))); + String line; + xmlString = new StringBuilder(); + while((line=br.readLine())!= null){ + xmlString.append(line.trim()); + } + long time = System.currentTimeMillis(); + XMLMessageEncoder testEncoder = new XMLMessageEncoder((byte)1, (short)1, time, (byte)7, (short)1, (short)xmlString.length(), xmlString.toString()); + + byte[] encodedXML = testEncoder.encode(); + + XMLMessageDecoder decoderXML = new XMLMessageDecoder(encodedXML); + decoderXML.decode(); + + + Assert.assertEquals((byte)1, decoderXML.getMessageVersionNumber()); + Assert.assertEquals((short)1, decoderXML.getAckNumber()); + Assert.assertEquals(time, decoderXML.getTimeStamp()); + Assert.assertEquals((byte)7, decoderXML.getXmlMsgSubType()); + Assert.assertEquals((short)1, decoderXML.getSequenceNumber()); + Assert.assertEquals((short)xmlString.length(), decoderXML.getXmlMsgLength()); + Assert.assertEquals(xmlString.toString(), decoderXML.getXmlMessage()); + + + }catch (IOException e){ + System.out.println(e); + } + } +} diff --git a/src/test/java/XMLMessageEncoderTest.java b/src/test/java/XMLMessageEncoderTest.java new file mode 100644 index 00000000..b00c6565 --- /dev/null +++ b/src/test/java/XMLMessageEncoderTest.java @@ -0,0 +1,53 @@ +import org.junit.Assert; +import org.junit.Test; +import seng302.XMLMessageEncoder; + +import java.io.*; + +/** + * Created by hba56 on 19/04/17. + */ +public class XMLMessageEncoderTest { + @Test + public void getByteArrayTest(){ + StringBuilder xmlString; + try{ + BufferedReader br = new BufferedReader(new InputStreamReader( + this.getClass().getResourceAsStream(("raceXML/Regatta.xml")))); + String line; + xmlString = new StringBuilder(); + while((line=br.readLine())!= null){ + xmlString.append(line.trim()); + } + XMLMessageEncoder testEncoder = new XMLMessageEncoder((byte)1, (short)1, System.currentTimeMillis(), (byte)7, (short)1, (short)xmlString.length(), xmlString.toString()); + + byte[] encodedXML = testEncoder.encode(); + + //1 + 2 + 6 + 1 + 2 + 2 + 374 + Assert.assertEquals(388, encodedXML.length); + }catch (IOException e){ + System.out.println(e); + } + } + + @Test + public void getByteArrayNullTest(){ + StringBuilder xmlString; + try{ + BufferedReader br = new BufferedReader(new InputStreamReader( + this.getClass().getResourceAsStream(("raceXML/Regatta.xml")))); + String line; + xmlString = new StringBuilder(); + while((line=br.readLine())!= null){ + xmlString.append(line.trim()); + } + XMLMessageEncoder testEncoder = new XMLMessageEncoder((byte)1, (short)1, System.currentTimeMillis(), (byte)7, (short)1, (short)1, xmlString.toString()); + + byte[] encodedXML = testEncoder.encode(); + + Assert.assertEquals(null, encodedXML); + }catch (IOException e){ + System.out.println(e); + } + } +} diff --git a/src/test/resources/raceXML/Regatta.xml b/src/test/resources/raceXML/Regatta.xml new file mode 100644 index 00000000..23fde025 --- /dev/null +++ b/src/test/resources/raceXML/Regatta.xml @@ -0,0 +1,12 @@ + + + + 1 + Seng302 Mock Test + Bermuda AC35 + -32.296577 + 64.854304 + 0.00 + -4 + -14.78 + \ No newline at end of file