Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Add MongoDB ObjectId and Timestamp types.

 - Create simple interfaces for ObjectId and Timestamp.
 - Provide simple implementations for both interface.
 - Register new reader, writer and predicate objects for them.
 - Add simple tests for the implementations.
  • Loading branch information...
commit a94c000c400d77ef0b97349dbe0f366b7c10ebd5 1 parent 5c65959
@kohanyirobert kohanyirobert authored
View
83 src/main/java/com/github/kohanyirobert/ebson/BasicObjectId.java
@@ -0,0 +1,83 @@
+package com.github.kohanyirobert.ebson;
+
+import com.google.common.base.Objects;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+import javax.xml.bind.DatatypeConverter;
+
+final class BasicObjectId implements ObjectId {
+
+ private static final int TIME_LENGTH = 4;
+ private static final int MACHINE_ID_LENGTH = 3;
+ private static final int PROCESS_ID_LENGTH = 2;
+ private static final int INCREMENT_LENGTH = 3;
+ private static final int OBJECT_ID_LENGTH =
+ TIME_LENGTH + MACHINE_ID_LENGTH + PROCESS_ID_LENGTH + INCREMENT_LENGTH;
+
+ private final ByteBuffer time;
+ private final ByteBuffer machineId;
+ private final ByteBuffer processId;
+ private final ByteBuffer increment;
+
+ private final ByteBuffer objectId = ByteBuffer.allocate(OBJECT_ID_LENGTH).order(ByteOrder.BIG_ENDIAN);
+
+ BasicObjectId(ByteBuffer buffer) {
+ int oldLimit = buffer.limit();
+
+ buffer.limit(buffer.position() + OBJECT_ID_LENGTH);
+ objectId.put(buffer).flip();
+
+ assert buffer.limit() == oldLimit;
+
+ time = ByteBuffer.wrap(objectId.array(), 0, TIME_LENGTH).order(ByteOrder.BIG_ENDIAN);
+ machineId = ByteBuffer.wrap(objectId.array(), TIME_LENGTH, MACHINE_ID_LENGTH).order(ByteOrder.LITTLE_ENDIAN);
+ processId = ByteBuffer.wrap(objectId.array(), MACHINE_ID_LENGTH, PROCESS_ID_LENGTH).order(ByteOrder.LITTLE_ENDIAN);
+ increment = ByteBuffer.wrap(objectId.array(), PROCESS_ID_LENGTH, INCREMENT_LENGTH).order(ByteOrder.BIG_ENDIAN);
+ }
+
+ @Override
+ public ByteBuffer getObjectId() {
+ return objectId.asReadOnlyBuffer();
+ }
+
+ @Override
+ public ByteBuffer getTime() {
+ return time.asReadOnlyBuffer();
+ }
+
+ @Override
+ public ByteBuffer getMachineId() {
+ return machineId.asReadOnlyBuffer();
+ }
+
+ @Override
+ public ByteBuffer getProcessId() {
+ return processId.asReadOnlyBuffer();
+ }
+
+ @Override
+ public ByteBuffer getIncrement() {
+ return increment.asReadOnlyBuffer();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(objectId);
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ if (object instanceof ObjectId) {
+ ObjectId other = (ObjectId) object;
+ return objectId.equals(other.getObjectId());
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return DatatypeConverter.printHexBinary(objectId.array()).toLowerCase();
+ }
+}
View
66 src/main/java/com/github/kohanyirobert/ebson/BasicTimestamp.java
@@ -0,0 +1,66 @@
+package com.github.kohanyirobert.ebson;
+
+import com.google.common.base.Objects;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+import javax.xml.bind.DatatypeConverter;
+
+final class BasicTimestamp implements Timestamp {
+
+ private static final int TIME_LENGTH = 4;
+ private static final int INCREMENT_LENGTH = 4;
+ private static final int TIMESTAMP_LENGTH = TIME_LENGTH + INCREMENT_LENGTH;
+
+ private final ByteBuffer time;
+ private final ByteBuffer increment;
+
+ private final ByteBuffer timestamp = ByteBuffer.allocate(TIMESTAMP_LENGTH).order(ByteOrder.LITTLE_ENDIAN);
+
+ BasicTimestamp(ByteBuffer buffer) {
+ int oldLimit = buffer.limit();
+
+ buffer.limit(buffer.position() + TIMESTAMP_LENGTH);
+ timestamp.put(buffer).flip();
+
+ assert buffer.limit() == oldLimit;
+
+ time = ByteBuffer.wrap(timestamp.array(), 0, TIME_LENGTH).order(ByteOrder.LITTLE_ENDIAN);
+ increment = ByteBuffer.wrap(timestamp.array(), INCREMENT_LENGTH, TIME_LENGTH).order(ByteOrder.LITTLE_ENDIAN);
+ }
+
+ @Override
+ public ByteBuffer getTimestamp() {
+ return timestamp.asReadOnlyBuffer();
+ }
+
+ @Override
+ public ByteBuffer getTime() {
+ return time.asReadOnlyBuffer();
+ }
+
+ @Override
+ public ByteBuffer getIncrement() {
+ return increment.asReadOnlyBuffer();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(timestamp);
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ if (object instanceof Timestamp) {
+ Timestamp other = (Timestamp) object;
+ return timestamp.equals(other.getTimestamp());
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return DatatypeConverter.printHexBinary(timestamp.array()).toLowerCase();
+ }
+}
View
6 src/main/java/com/github/kohanyirobert/ebson/BsonObject.java
@@ -63,7 +63,8 @@
* <b>Note:</b> special <a href="http://mongodb.org">MongoDB</a> related type.
* </p>
*/
- OBJECT_ID(BsonBytes.OBJECT_ID),
+ OBJECT_ID(BsonBytes.OBJECT_ID, DefaultPredicate.OBJECT_ID,
+ DefaultReader.OBJECT_ID, DefaultWriter.OBJECT_ID),
/**
* Boolean.
@@ -138,7 +139,8 @@
* sharding.
* </p>
*/
- TIMESTAMP(BsonBytes.TIMESTAMP),
+ TIMESTAMP(BsonBytes.TIMESTAMP, DefaultPredicate.TIMESTAMP,
+ DefaultReader.TIMESTAMP, DefaultWriter.TIMESTAMP),
/**
* 64-bit signed integer.
View
20 src/main/java/com/github/kohanyirobert/ebson/DefaultPredicate.java
@@ -69,6 +69,16 @@ public boolean apply(Class<?> input) {
}
},
+ OBJECT_ID {
+
+ @Override
+ public boolean apply(Class<?> input) {
+ return input == null
+ ? false
+ : ObjectId.class.isAssignableFrom(input);
+ }
+ },
+
BOOLEAN {
@Override
@@ -117,6 +127,16 @@ public boolean apply(Class<?> input) {
}
},
+ TIMESTAMP {
+
+ @Override
+ public boolean apply(Class<?> input) {
+ return input == null
+ ? false
+ : Timestamp.class.isAssignableFrom(input);
+ }
+ },
+
INT64 {
@Override
View
16 src/main/java/com/github/kohanyirobert/ebson/DefaultReader.java
@@ -108,6 +108,14 @@ public Object checkedReadFrom(ByteBuffer buffer) {
}
},
+ OBJECT_ID {
+
+ @Override
+ Object checkedReadFrom(ByteBuffer buffer) {
+ return new BasicObjectId(buffer);
+ }
+ },
+
BOOLEAN {
@Override
@@ -180,6 +188,14 @@ public Object checkedReadFrom(ByteBuffer buffer) {
}
},
+ TIMESTAMP {
+
+ @Override
+ Object checkedReadFrom(ByteBuffer buffer) {
+ return new BasicTimestamp(buffer);
+ }
+ },
+
INT64 {
@Override
View
16 src/main/java/com/github/kohanyirobert/ebson/DefaultWriter.java
@@ -104,6 +104,14 @@ public void writeTo(ByteBuffer buffer, Object reference) {
}
},
+ OBJECT_ID {
+
+ @Override
+ public void writeTo(ByteBuffer buffer, Object reference) {
+ buffer.put(((ObjectId) reference).getObjectId());
+ }
+ },
+
BOOLEAN {
@Override
@@ -169,6 +177,14 @@ public void writeTo(ByteBuffer buffer, Object reference) {
}
},
+ TIMESTAMP {
+
+ @Override
+ public void writeTo(ByteBuffer buffer, Object reference) {
+ buffer.put(((Timestamp) reference).getTimestamp());
+ }
+ },
+
INT64 {
@Override
View
17 src/main/java/com/github/kohanyirobert/ebson/ObjectId.java
@@ -0,0 +1,17 @@
+package com.github.kohanyirobert.ebson;
+
+import java.nio.ByteBuffer;
+
+// @checkstyle:off .
+public interface ObjectId {
+
+ ByteBuffer getObjectId();
+
+ ByteBuffer getTime();
+
+ ByteBuffer getMachineId();
+
+ ByteBuffer getProcessId();
+
+ ByteBuffer getIncrement();
+}
View
13 src/main/java/com/github/kohanyirobert/ebson/Timestamp.java
@@ -0,0 +1,13 @@
+package com.github.kohanyirobert.ebson;
+
+import java.nio.ByteBuffer;
+
+// @checkstyle:off .
+public interface Timestamp {
+
+ ByteBuffer getTimestamp();
+
+ ByteBuffer getTime();
+
+ ByteBuffer getIncrement();
+}
View
32 src/test/java/com/github/kohanyirobert/ebson/DefaultObjectIdReaderWriterTest.java
@@ -0,0 +1,32 @@
+package com.github.kohanyirobert.ebson;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Random;
+
+public final class DefaultObjectIdReaderWriterTest extends AbstractReaderWriterTest {
+
+ private static final ThreadLocal<ByteBuffer> RANDOM_OBJECT_ID = new ThreadLocal<ByteBuffer>() {
+
+ @Override
+ protected ByteBuffer initialValue() {
+ // @checkstyle:off MagicNumber
+ byte[] bytes = new byte[12];
+ new Random().nextBytes(bytes);
+ return ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN);
+ }
+ };
+
+ public DefaultObjectIdReaderWriterTest() {
+ super(DefaultReader.OBJECT_ID, DefaultWriter.OBJECT_ID);
+ }
+
+ @Test
+ public void randomObjectId() {
+ assertEquals(writeTo(new BasicObjectId(RANDOM_OBJECT_ID.get())), readFrom());
+ }
+}
View
32 src/test/java/com/github/kohanyirobert/ebson/DefaultTimestampReaderWriterTest.java
@@ -0,0 +1,32 @@
+package com.github.kohanyirobert.ebson;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Random;
+
+public final class DefaultTimestampReaderWriterTest extends AbstractReaderWriterTest {
+
+ private static final ThreadLocal<ByteBuffer> RANDOM_TIMESTAMP = new ThreadLocal<ByteBuffer>() {
+
+ @Override
+ protected ByteBuffer initialValue() {
+ // @checkstyle:off MagicNumber
+ byte[] bytes = new byte[8];
+ new Random().nextBytes(bytes);
+ return ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN);
+ }
+ };
+
+ public DefaultTimestampReaderWriterTest() {
+ super(DefaultReader.TIMESTAMP, DefaultWriter.TIMESTAMP);
+ }
+
+ @Test
+ public void randomTimestamp() {
+ assertEquals(writeTo(new BasicTimestamp(RANDOM_TIMESTAMP.get())), readFrom());
+ }
+}
Please sign in to comment.
Something went wrong with that request. Please try again.