I'm a beginner in Java so I would appreciate a review of following simple class - in fact it's my first real usage of enums.
The background: I'm parsing MySQL internal client-server protocol. One of the fields in server greeting and client authorization packet is "Client capabilities" which is 32 bit integer encoding 18 boolean flags ( if anyone is interested: http://forge.mysql.com/wiki/MySQL_Internals_ClientServer_Protocol#Handshake_Initialization_Packet)
I've read that the most 'java way' to implement such thing will be using EnumSet class.
I'll welcome any suggestions and other solutions - my needs are:
- I must be able to parse flags from 4 bytes big endian buffer
- To encode flags back to 4 bytes big endian buffer
- To check if some arbitrary flag is set
here's the code:
public class ClientCapabilities
{
public enum Flag {
CLIENT_LONG_PASSWORD (1<<0),
CLIENT_FOUND_ROWS (1<<1),
CLIENT_LONG_FLAG (1<<2),
CLIENT_CONNECT_WITH_DB (1<<3),
CLIENT_NO_SCHEMA (1<<4),
CLIENT_COMPRESS (1<<5),
CLIENT_ODBC (1<<6),
CLIENT_LOCAL_FILES (1<<7),
CLIENT_IGNORE_SPACE (1<<8),
CLIENT_PROTOCOL_41 (1<<9),
CLIENT_INTERACTIVE (1<<10),
CLIENT_SSL (1<<11),
CLIENT_IGNORE_SIGPIPE (1<<12),
CLIENT_TRANSACTIONS (1<<13),
CLIENT_RESERVED (1<<14),
CLIENT_SECURE_CONNECTION (1<<15),
CLIENT_MULTI_STATEMENTS (1<<16),
CLIENT_MULTI_RESULTS (1<<17);
public final int weight;
Flag(Integer weight) {
this.weight = weight;
}
}
private final int originalInt;
private final EnumSet<Flag> flags = EnumSet.noneOf(Flag.class);
public ClientCapabilities(int capabilities)
{
originalInt = capabilities;
for (Flag f : Flag.values()) {
if ((capabilities & f.weight) > 0) {
flags.add(f);
}
}
}
public int getAsInt()
{
return originalInt;
}
public EnumSet<Flag> getFlags()
{
return flags;
}
@Override
public String toString() {
return flags.toString();
}
//only tests ahead - TestNG, not JUnit!
@Test
public static void testDecodingClientCapabilities()
{
byte[] exampleBuffer = new byte[] { (byte) 0x85, (byte) 0xa6, (byte) 0x03, (byte) 0x00 };
EnumSet<Flag> expectedEnumSet = EnumSet.of(
Flag.CLIENT_LONG_PASSWORD,
Flag.CLIENT_LONG_FLAG,
Flag.CLIENT_LOCAL_FILES,
Flag.CLIENT_PROTOCOL_41,
Flag.CLIENT_INTERACTIVE,
Flag.CLIENT_TRANSACTIONS,
Flag.CLIENT_SECURE_CONNECTION,
Flag.CLIENT_MULTI_STATEMENTS,
Flag.CLIENT_MULTI_RESULTS
);
ClientCapabilities capabilities = new ClientCapabilities(
PacketByteBuffer.readIntFromFourBytes(exampleBuffer,0));
Assert.assertEquals(capabilities.getFlags(), expectedEnumSet);
}
@Test
public static void testEncodingClientCapabilities()
{
byte[] exampleBuffer = new byte[] { (byte) 0x85, (byte) 0xa6, (byte) 0x03, (byte) 0x00 };
byte[] targetBuffer = new byte[] { 0, 0, 0, 0, 0};
ClientCapabilities capabilities = new ClientCapabilities(
PacketByteBuffer.readIntFromFourBytes(exampleBuffer,0));
PacketByteBuffer.writeIntToFourBytes(targetBuffer, 1, capabilities.originalInt);
Assert.assertEquals(targetBuffer[1], (byte) 0x85);
Assert.assertEquals(targetBuffer[2], (byte) 0xa6);
Assert.assertEquals(targetBuffer[3], (byte) 0x03);
Assert.assertEquals(targetBuffer[4], (byte) 0x00);
}
}