in firestore-incremental-capture-pipeline/src/main/java/com/pipeline/FirestoreReconstructor.java [47:149]
public static Map<String, Value> buildFirestoreMap(JsonElement dataJson, String projectId, String databaseId) {
JsonObject dataObject = dataJson.getAsJsonObject();
Map<String, Value> fieldsMap = new HashMap<>();
for (Map.Entry<String, JsonElement> entry : dataObject.entrySet()) {
JsonElement valueElem = entry.getValue();
if (valueElem.isJsonObject() && valueElem.getAsJsonObject().has("type")
&& valueElem.getAsJsonObject().has("value")) {
JsonObject entryValueObject = valueElem.getAsJsonObject();
String valueType = entryValueObject.get("type").getAsString().toUpperCase();
Value val;
switch (valueType) {
case "STRING":
val = Value.newBuilder().setStringValue(entryValueObject.get("value").getAsString()).build();
break;
case "NUMBER":
val = Value.newBuilder().setDoubleValue(entryValueObject.get("value").getAsDouble()).build();
break;
case "BOOLEAN":
String originalValue = entryValueObject.get("value").getAsString();
if (originalValue.equals("true")) {
val = Value.newBuilder().setBooleanValue(true).build();
} else {
val = Value.newBuilder().setBooleanValue(false).build();
}
break;
case "OBJECT":
val = Value.newBuilder().setMapValue(
MapValue.newBuilder().putAllFields(
buildFirestoreMap(entryValueObject.get("value"), projectId, databaseId)))
.build();
break;
case "MAP":
val = Value.newBuilder().setMapValue(
MapValue.newBuilder().putAllFields(
buildFirestoreMap(entryValueObject.get("value"), projectId, databaseId)))
.build();
break;
case "ARRAY":
val = Value.newBuilder().setArrayValue(
ArrayValue.newBuilder().addAllValues(
buildFirestoreList(entryValueObject.get("value").getAsJsonArray(), projectId,
databaseId)))
.build();
break;
case "GEOPOINT":
JsonObject geopointValue = entryValueObject.get("value").getAsJsonObject();
JsonObject latitude = geopointValue.get("latitude").getAsJsonObject();
JsonObject longitude = geopointValue.get("longitude").getAsJsonObject();
Double latitudeValue = latitude.get("value").getAsDouble();
Double longitudeValue = longitude.get("value").getAsDouble();
val = Value.newBuilder().setGeoPointValue(
com.google.type.LatLng.newBuilder().setLatitude(latitudeValue)
.setLongitude(longitudeValue)
.build())
.build();
break;
case "TIMESTAMP":
// parse the timestamp value as an Instant
Instant instant = Instant.parse(entryValueObject.get("value").getAsString());
long epochSecond = instant.getEpochSecond();
int nanoSecond = instant.getNano();
Timestamp timestamp = Timestamp.newBuilder().setSeconds(epochSecond).setNanos(nanoSecond)
.build();
// convert to seconds and nanoseconds
val = Value.newBuilder().setTimestampValue(timestamp).build();
break;
case "REFERENCE":
String pathString = entryValueObject.get("value").getAsString();
String fullReferenceString = String.format(
"projects/%s/databases/%s/documents/%s",
projectId,
databaseId,
pathString);
val = Value.newBuilder().setReferenceValue(fullReferenceString)
.build();
break;
default:
val = null;
continue;
}
fieldsMap.put(entry.getKey(), val);
}
}
// log it
return fieldsMap;
}