Skip to content

Commit 444071d

Browse files
committed
refactor: Merge BsonBinaryData into Blob
This PR stacks on PR #2378 and implements the refactoring to merge BsonBinaryData into Blob, as requested by the user.
1 parent 20bf9d8 commit 444071d

12 files changed

Lines changed: 264 additions & 230 deletions

File tree

java-firestore/google-cloud-firestore/src/main/java/com/google/cloud/firestore/Blob.java

Lines changed: 106 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,31 +27,91 @@ public final class Blob implements Serializable {
2727
private static final long serialVersionUID = 1441087101882481208L;
2828

2929
private final ByteString byteString;
30+
private final int subtype;
31+
private final boolean isBson;
3032

31-
private Blob(ByteString byteString) {
33+
private Blob(ByteString byteString, int subtype, boolean isBson) {
34+
if (subtype < 0 || subtype > 255) {
35+
throw new IllegalArgumentException(
36+
"The subtype for Blob must be a value in the inclusive [0, 255] range.");
37+
}
3238
this.byteString = byteString;
39+
this.subtype = subtype;
40+
this.isBson = isBson;
3341
}
3442

3543
/**
36-
* Creates a new Blob instance from the provided ByteString.
44+
* Creates a new Blob instance from the provided ByteString. Defaults to subtype 0 and native
45+
* representation.
3746
*
3847
* @param byteString The byteString to use for this Blob instance.
3948
* @return The new Blob instance
4049
*/
4150
@Nonnull
4251
public static Blob fromByteString(@Nonnull ByteString byteString) {
43-
return new Blob(byteString);
52+
return new Blob(byteString, 0, false);
4453
}
4554

4655
/**
4756
* Creates a new Blob instance from the provided bytes. Makes a copy of the bytes passed in.
57+
* Defaults to subtype 0 and native representation.
4858
*
4959
* @param bytes The bytes to use for this Blob instance.
5060
* @return The new Blob instance
5161
*/
5262
@Nonnull
5363
public static Blob fromBytes(@Nonnull byte[] bytes) {
54-
return new Blob(ByteString.copyFrom(bytes));
64+
return new Blob(ByteString.copyFrom(bytes), 0, false);
65+
}
66+
67+
/**
68+
* Creates a new Blob instance representing a BSON binary data type. Sets subtype to 0 and
69+
* representation to BSON.
70+
*
71+
* @param bytes The bytes to use for this Blob instance.
72+
* @return The new Blob instance
73+
*/
74+
@Nonnull
75+
public static Blob createBsonBinary(@Nonnull byte[] bytes) {
76+
return new Blob(ByteString.copyFrom(bytes), 0, true);
77+
}
78+
79+
/**
80+
* Creates a new Blob instance representing a BSON binary data type. Sets subtype to 0 and
81+
* representation to BSON.
82+
*
83+
* @param data The ByteString to use for this Blob instance.
84+
* @return The new Blob instance
85+
*/
86+
@Nonnull
87+
public static Blob createBsonBinary(@Nonnull ByteString data) {
88+
return new Blob(data, 0, true);
89+
}
90+
91+
/**
92+
* Creates a new Blob instance representing a BSON binary data type with a specific subtype. Sets
93+
* representation to BSON.
94+
*
95+
* @param subtype The subtype to use for this instance.
96+
* @param bytes The bytes to use for this Blob instance.
97+
* @return The new Blob instance
98+
*/
99+
@Nonnull
100+
public static Blob createBsonBinary(int subtype, @Nonnull byte[] bytes) {
101+
return new Blob(ByteString.copyFrom(bytes), subtype, true);
102+
}
103+
104+
/**
105+
* Creates a new Blob instance representing a BSON binary data type with a specific subtype. Sets
106+
* representation to BSON.
107+
*
108+
* @param subtype The subtype to use for this instance.
109+
* @param data The ByteString to use for this Blob instance.
110+
* @return The new Blob instance
111+
*/
112+
@Nonnull
113+
public static Blob createBsonBinary(int subtype, @Nonnull ByteString data) {
114+
return new Blob(data, subtype, true);
55115
}
56116

57117
/**
@@ -74,6 +134,25 @@ public byte[] toBytes() {
74134
return byteString.toByteArray();
75135
}
76136

137+
/**
138+
* Returns the subtype of this binary data. Defaults to 0 for both native binary and BSON binary
139+
* if not specified.
140+
*
141+
* @return The subtype of the binary data.
142+
*/
143+
public int subtype() {
144+
return this.subtype;
145+
}
146+
147+
/**
148+
* Returns whether this Blob represents a BSON binary data type.
149+
*
150+
* @return True if BSON representation, false if native representation.
151+
*/
152+
public boolean isBson() {
153+
return this.isBson;
154+
}
155+
77156
/**
78157
* Returns true if this Blob is equal to the provided object.
79158
*
@@ -89,11 +168,32 @@ public boolean equals(Object obj) {
89168
return false;
90169
}
91170
Blob blob = (Blob) obj;
92-
return Objects.equals(byteString, blob.byteString);
171+
return this.subtype == blob.subtype && Objects.equals(byteString, blob.byteString);
93172
}
94173

95174
@Override
96175
public int hashCode() {
97-
return Objects.hash(byteString);
176+
return Objects.hash(byteString, subtype);
177+
}
178+
179+
@Nonnull
180+
@Override
181+
public String toString() {
182+
String dataStr;
183+
if (this.byteString.size() <= 100) {
184+
dataStr =
185+
com.google.common.io.BaseEncoding.base16()
186+
.lowerCase()
187+
.encode(this.byteString.toByteArray());
188+
} else {
189+
dataStr =
190+
com.google.common.io.BaseEncoding.base16()
191+
.lowerCase()
192+
.encode(this.byteString.substring(0, 20).toByteArray())
193+
+ "... (size="
194+
+ this.byteString.size()
195+
+ ")";
196+
}
197+
return "Blob{subtype=" + this.subtype + ", isBson=" + this.isBson + ", data=" + dataStr + "}";
98198
}
99199
}

java-firestore/google-cloud-firestore/src/main/java/com/google/cloud/firestore/BsonBinaryData.java

Lines changed: 0 additions & 128 deletions
This file was deleted.

java-firestore/google-cloud-firestore/src/main/java/com/google/cloud/firestore/DocumentSnapshot.java

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -482,18 +482,6 @@ public BsonTimestamp getBsonTimestamp(@Nonnull String field) {
482482
return (BsonTimestamp) get(field);
483483
}
484484

485-
/**
486-
* Returns the value of the field as a BsonBinaryData.
487-
*
488-
* @param field The path to the field.
489-
* @throws RuntimeException if the value is not a BsonBinaryData.
490-
* @return The value of the field.
491-
*/
492-
@Nullable
493-
public BsonBinaryData getBsonBinaryData(@Nonnull String field) {
494-
return (BsonBinaryData) get(field);
495-
}
496-
497485
/**
498486
* Gets the reference to the document.
499487
*

java-firestore/google-cloud-firestore/src/main/java/com/google/cloud/firestore/Order.java

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ enum TypeOrder implements Comparable<TypeOrder> {
4343
BSON_TIMESTAMP,
4444
STRING,
4545
BLOB,
46-
BSON_BINARY,
4746
REF,
4847
BSON_OBJECT_ID,
4948
GEO_POINT,
@@ -100,7 +99,7 @@ static TypeOrder fromMapValue(MapValue mapValue) {
10099
case BSON_TIMESTAMP:
101100
return TypeOrder.BSON_TIMESTAMP;
102101
case BSON_BINARY_DATA:
103-
return TypeOrder.BSON_BINARY;
102+
return TypeOrder.BLOB;
104103
case UNKNOWN:
105104
case NONE:
106105
default:
@@ -160,8 +159,7 @@ public int compare(@Nonnull Value left, @Nonnull Value right) {
160159
return compareBsonObjectId(left, right);
161160
case BSON_TIMESTAMP:
162161
return compareBsonTimestamp(left, right);
163-
case BSON_BINARY:
164-
return compareBsonBinary(left, right);
162+
165163
default:
166164
throw new IllegalArgumentException("Cannot compare " + leftType);
167165
}
@@ -226,9 +224,43 @@ public static int compareUtf8Strings(String left, String right) {
226224
}
227225

228226
private int compareBlobs(Value left, Value right) {
229-
ByteString leftBytes = left.getBytesValue();
230-
ByteString rightBytes = right.getBytesValue();
231-
return compareByteStrings(leftBytes, rightBytes);
227+
int leftSubtype = getSubtype(left);
228+
int rightSubtype = getSubtype(right);
229+
if (leftSubtype != rightSubtype) {
230+
return Integer.compare(leftSubtype, rightSubtype);
231+
}
232+
return compareByteStrings(getData(left), getData(right));
233+
}
234+
235+
private static int getSubtype(Value value) {
236+
if (value.hasBytesValue()) {
237+
return 0;
238+
}
239+
if (value.hasMapValue() && UserDataConverter.isBsonBinaryData(value.getMapValue())) {
240+
return value
241+
.getMapValue()
242+
.getFieldsMap()
243+
.get(MapType.RESERVED_BSON_BINARY_KEY)
244+
.getBytesValue()
245+
.byteAt(0)
246+
& 0xFF;
247+
}
248+
throw new IllegalArgumentException("Cannot get subtype for non-blob value: " + value);
249+
}
250+
251+
private static ByteString getData(Value value) {
252+
if (value.hasBytesValue()) {
253+
return value.getBytesValue();
254+
}
255+
if (value.hasMapValue() && UserDataConverter.isBsonBinaryData(value.getMapValue())) {
256+
return value
257+
.getMapValue()
258+
.getFieldsMap()
259+
.get(MapType.RESERVED_BSON_BINARY_KEY)
260+
.getBytesValue()
261+
.substring(1);
262+
}
263+
throw new IllegalArgumentException("Cannot get data for non-blob value: " + value);
232264
}
233265

234266
static int compareByteStrings(ByteString leftBytes, ByteString rightBytes) {
@@ -412,14 +444,6 @@ private int compareBsonTimestamp(Value left, Value right) {
412444
return secondsDiff != 0 ? secondsDiff : Long.compare(lhs.increment, rhs.increment);
413445
}
414446

415-
private int compareBsonBinary(Value left, Value right) {
416-
ByteString lhs =
417-
left.getMapValue().getFieldsMap().get(MapType.RESERVED_BSON_BINARY_KEY).getBytesValue();
418-
ByteString rhs =
419-
right.getMapValue().getFieldsMap().get(MapType.RESERVED_BSON_BINARY_KEY).getBytesValue();
420-
return compareByteStrings(lhs, rhs);
421-
}
422-
423447
private boolean isNaN(Value value) {
424448
if (value.hasDoubleValue() && Double.isNaN(value.getDoubleValue())) {
425449
return true;

0 commit comments

Comments
 (0)