Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Task #7176/feat: added method to identify the data types from json and parse to … #34657

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,8 @@
import com.fasterxml.jackson.core.type.TypeReference;
import com.google.api.core.ApiFuture;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.cloud.firestore.CollectionReference;
import com.google.cloud.firestore.DocumentReference;
import com.google.cloud.firestore.DocumentSnapshot;
import com.google.cloud.firestore.FieldValue;
import com.google.cloud.firestore.Firestore;
import com.google.cloud.firestore.FirestoreException;
import com.google.cloud.firestore.Query;
import com.google.cloud.firestore.QuerySnapshot;
import com.google.cloud.firestore.WriteResult;
import com.google.cloud.Timestamp;
import com.google.cloud.firestore.*;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions;
import com.google.firebase.cloud.FirestoreClient;
Expand All @@ -59,6 +52,7 @@
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

Expand Down Expand Up @@ -96,6 +90,12 @@
public class FirestorePlugin extends BasePlugin {

private static final String FIELDVALUE_TIMESTAMP_METHOD_NAME = "serverTimestamp";
private static final Pattern REFERENCE_PATTERN = Pattern.compile("^/?[^/]+/[^/]+(/[^/]+/[^/]+)*$");
private static final String LATITUDE = "latitude";
private static final String LONGITUDE = "longitude";
private static final String STRING_SEPERATOR = "/";
private static final String SECONDS = "second";
private static final String NANO_SECONDS = "nanoseconds";

public FirestorePlugin(PluginWrapper wrapper) {
super(wrapper);
Expand Down Expand Up @@ -501,6 +501,7 @@ public Mono<ActionExecutionResult> handleDocumentLevelMethod(
Map<String, Object> mapBody,
String query,
List<RequestParamDTO> requestParams) {

return Mono.just(method)
// Get the actual Java method to be called.
.flatMap(method1 -> {
Expand Down Expand Up @@ -805,6 +806,9 @@ private boolean isWhereMethodUsed(Map<String, Object> formData) {

private Mono<ActionExecutionResult> methodAddToCollection(
CollectionReference collection, Map<String, Object> mapBody) {

mapBody.replaceAll((key, value) -> checkAndConvertDataType(value, collection));

return Mono.justOrEmpty(collection.add(mapBody))
.flatMap(future -> {
try {
Expand All @@ -829,6 +833,30 @@ private Mono<ActionExecutionResult> methodAddToCollection(
});
}

private Object checkAndConvertDataType(Object value, CollectionReference collection) {
if (value instanceof Map<?, ?> mapValue) {
if (mapValue.containsKey(SECONDS) && mapValue.containsKey(NANO_SECONDS)) {
long seconds = ((Number) mapValue.get(SECONDS)).longValue();
int nanos = ((Number) mapValue.get(NANO_SECONDS)).intValue();
return Timestamp.ofTimeSecondsAndNanos(seconds, nanos);
} else if (mapValue.containsKey(LATITUDE) && mapValue.containsKey(LONGITUDE)) {
double latitude = ((Number) mapValue.get(LATITUDE)).doubleValue();
double longitude = ((Number) mapValue.get(LONGITUDE)).doubleValue();
return new GeoPoint(latitude, longitude);
}
} else if (value instanceof String stringValue) {
// Validate the string as a Firestore document reference using regex
if (REFERENCE_PATTERN.matcher(stringValue).matches()) {
// Remove leading slash if present
if (stringValue.startsWith(STRING_SEPERATOR)) {
stringValue = stringValue.substring(1);
}
return collection.getFirestore().document(stringValue);
}
}
return value;
}

private Object resultToMap(Object objResult) throws AppsmithPluginException {
return resultToMap(objResult, true);
}
Expand Down Expand Up @@ -859,6 +887,7 @@ private Object resultToMap(Object objResult, boolean isRoot) throws AppsmithPlug

} else if (objResult instanceof DocumentReference) {
// A reference containing details of another document.

DocumentReference documentReference = (DocumentReference) objResult;
return Map.of(
"id", documentReference.getId(),
Expand All @@ -879,6 +908,16 @@ private Object resultToMap(Object objResult, boolean isRoot) throws AppsmithPlug
}
return converted;

} else if (objResult instanceof Timestamp) {
// Handle Firestore Timestamp directly
Timestamp timestamp = (Timestamp) objResult;
// Convert to ISO 8601 string or any preferred format
return timestamp.toSqlTimestamp().toInstant().toString();

} else if (objResult instanceof GeoPoint) {
GeoPoint geoPoint = (GeoPoint) objResult;
return String.format("POINT(%f %f)", geoPoint.getLatitude(), geoPoint.getLongitude());

} else if (isRoot) {
throw new AppsmithPluginException(
FirestorePluginError.QUERY_EXECUTION_FAILED,
Expand All @@ -893,7 +932,6 @@ private Object resultToMap(Object objResult, boolean isRoot) throws AppsmithPlug
@Override
public Mono<Firestore> datasourceCreate(DatasourceConfiguration datasourceConfiguration) {
final DBAuth authentication = (DBAuth) datasourceConfiguration.getAuthentication();

final Set<String> errors = validateDatasource(datasourceConfiguration);
if (!CollectionUtils.isEmpty(errors)) {
return Mono.error(new AppsmithPluginException(
Expand Down Expand Up @@ -984,7 +1022,6 @@ public Set<String> validateDatasource(DatasourceConfiguration datasourceConfigur
if (isBlank(datasourceConfiguration.getUrl())) {
invalids.add(FirestoreErrorMessages.DS_MISSING_FIRESTORE_URL_ERROR_MSG);
}

return invalids;
}

Expand Down