@react-native-firebase/firestore 23.8.8 → 24.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/RNFBFirestore.podspec +2 -1
- package/android/src/reactnative/java/io/invertase/firebase/firestore/ReactNativeFirebaseFirestoreCollectionModule.java +17 -4
- package/android/src/reactnative/java/io/invertase/firebase/firestore/ReactNativeFirebaseFirestoreDocumentModule.java +2 -2
- package/android/src/reactnative/java/io/invertase/firebase/firestore/ReactNativeFirebaseFirestorePipelineExecutor.java +1243 -0
- package/android/src/reactnative/java/io/invertase/firebase/firestore/ReactNativeFirebaseFirestorePipelineNodeBuilder.java +3919 -0
- package/android/src/reactnative/java/io/invertase/firebase/firestore/ReactNativeFirebaseFirestorePipelineParser.java +1735 -0
- package/android/src/reactnative/java/io/invertase/firebase/firestore/ReactNativeFirebaseFirestoreSerialize.java +1 -1
- package/dist/module/FieldPath.js +59 -0
- package/dist/module/FieldPath.js.map +1 -0
- package/dist/module/FieldValue.js +82 -0
- package/dist/module/FieldValue.js.map +1 -0
- package/{lib → dist/module}/FirestoreAggregate.js +31 -43
- package/dist/module/FirestoreAggregate.js.map +1 -0
- package/dist/module/FirestoreBlob.js +56 -0
- package/dist/module/FirestoreBlob.js.map +1 -0
- package/dist/module/FirestoreCollectionReference.js +70 -0
- package/dist/module/FirestoreCollectionReference.js.map +1 -0
- package/{lib → dist/module}/FirestoreDocumentChange.js +12 -15
- package/dist/module/FirestoreDocumentChange.js.map +1 -0
- package/dist/module/FirestoreDocumentReference.js +170 -0
- package/dist/module/FirestoreDocumentReference.js.map +1 -0
- package/dist/module/FirestoreDocumentSnapshot.js +88 -0
- package/dist/module/FirestoreDocumentSnapshot.js.map +1 -0
- package/dist/module/FirestoreFilter.js +146 -0
- package/dist/module/FirestoreFilter.js.map +1 -0
- package/dist/module/FirestoreGeoPoint.js +80 -0
- package/dist/module/FirestoreGeoPoint.js.map +1 -0
- package/{lib → dist/module}/FirestorePath.js +5 -12
- package/dist/module/FirestorePath.js.map +1 -0
- package/{lib → dist/module}/FirestorePersistentCacheIndexManager.js +11 -4
- package/dist/module/FirestorePersistentCacheIndexManager.js.map +1 -0
- package/dist/module/FirestoreQuery.js +298 -0
- package/dist/module/FirestoreQuery.js.map +1 -0
- package/{lib → dist/module}/FirestoreQueryModifiers.js +25 -136
- package/dist/module/FirestoreQueryModifiers.js.map +1 -0
- package/dist/module/FirestoreQuerySnapshot.js +98 -0
- package/dist/module/FirestoreQuerySnapshot.js.map +1 -0
- package/dist/module/FirestoreSnapshotMetadata.js +38 -0
- package/dist/module/FirestoreSnapshotMetadata.js.map +1 -0
- package/dist/module/FirestoreStatics.js +50 -0
- package/dist/module/FirestoreStatics.js.map +1 -0
- package/{lib → dist/module}/FirestoreTimestamp.js +39 -39
- package/dist/module/FirestoreTimestamp.js.map +1 -0
- package/dist/module/FirestoreTransaction.js +113 -0
- package/dist/module/FirestoreTransaction.js.map +1 -0
- package/dist/module/FirestoreTransactionHandler.js +137 -0
- package/dist/module/FirestoreTransactionHandler.js.map +1 -0
- package/dist/module/FirestoreVectorValue.js +75 -0
- package/dist/module/FirestoreVectorValue.js.map +1 -0
- package/dist/module/FirestoreWriteBatch.js +113 -0
- package/dist/module/FirestoreWriteBatch.js.map +1 -0
- package/dist/module/LoadBundleTask.js +70 -0
- package/dist/module/LoadBundleTask.js.map +1 -0
- package/dist/module/index.js +31 -0
- package/dist/module/index.js.map +1 -0
- package/dist/module/modular/Bytes.js +67 -0
- package/dist/module/modular/Bytes.js.map +1 -0
- package/dist/module/modular/FieldPath.js +25 -0
- package/dist/module/modular/FieldPath.js.map +1 -0
- package/dist/module/modular/FieldValue.js +37 -0
- package/dist/module/modular/FieldValue.js.map +1 -0
- package/dist/module/modular/GeoPoint.js +22 -0
- package/dist/module/modular/GeoPoint.js.map +1 -0
- package/dist/module/modular/Timestamp.js +22 -0
- package/dist/module/modular/Timestamp.js.map +1 -0
- package/dist/module/modular/VectorValue.js +25 -0
- package/dist/module/modular/VectorValue.js.map +1 -0
- package/dist/module/modular/query.js +222 -0
- package/dist/module/modular/query.js.map +1 -0
- package/dist/module/modular/snapshot.js +32 -0
- package/dist/module/modular/snapshot.js.map +1 -0
- package/dist/module/modular.js +229 -0
- package/dist/module/modular.js.map +1 -0
- package/dist/module/namespaced.js +298 -0
- package/dist/module/namespaced.js.map +1 -0
- package/dist/module/package.json +1 -0
- package/dist/module/pipelines/expressions.js +1273 -0
- package/dist/module/pipelines/expressions.js.map +1 -0
- package/dist/module/pipelines/index.js +32 -0
- package/dist/module/pipelines/index.js.map +1 -0
- package/dist/module/pipelines/pipeline-result.js +58 -0
- package/dist/module/pipelines/pipeline-result.js.map +1 -0
- package/dist/module/pipelines/pipeline-source.js +4 -0
- package/dist/module/pipelines/pipeline-source.js.map +1 -0
- package/dist/module/pipelines/pipeline.js +4 -0
- package/dist/module/pipelines/pipeline.js.map +1 -0
- package/dist/module/pipelines/pipeline_impl.js +42 -0
- package/dist/module/pipelines/pipeline_impl.js.map +1 -0
- package/dist/module/pipelines/pipeline_options.js +4 -0
- package/dist/module/pipelines/pipeline_options.js.map +1 -0
- package/dist/module/pipelines/pipeline_runtime.js +526 -0
- package/dist/module/pipelines/pipeline_runtime.js.map +1 -0
- package/dist/module/pipelines/pipeline_support.js +71 -0
- package/dist/module/pipelines/pipeline_support.js.map +1 -0
- package/dist/module/pipelines/pipeline_validate.js +183 -0
- package/dist/module/pipelines/pipeline_validate.js.map +1 -0
- package/dist/module/pipelines/stage_options.js +4 -0
- package/dist/module/pipelines/stage_options.js.map +1 -0
- package/dist/module/pipelines/types.js +2 -0
- package/dist/module/pipelines/types.js.map +1 -0
- package/dist/module/types/firestore.js +4 -0
- package/dist/module/types/firestore.js.map +1 -0
- package/dist/module/types/internal.js +4 -0
- package/dist/module/types/internal.js.map +1 -0
- package/dist/module/types/namespaced.js +338 -0
- package/dist/module/types/namespaced.js.map +1 -0
- package/{lib → dist/module}/utils/index.js +59 -114
- package/dist/module/utils/index.js.map +1 -0
- package/{lib → dist/module}/utils/serialize.js +58 -116
- package/dist/module/utils/serialize.js.map +1 -0
- package/{lib → dist/module}/utils/typemap.js +6 -20
- package/dist/module/utils/typemap.js.map +1 -0
- package/dist/module/version.js +5 -0
- package/dist/module/version.js.map +1 -0
- package/dist/module/web/RNFBFirestoreModule.android.js +5 -0
- package/dist/module/web/RNFBFirestoreModule.android.js.map +1 -0
- package/dist/module/web/RNFBFirestoreModule.ios.js +5 -0
- package/dist/module/web/RNFBFirestoreModule.ios.js.map +1 -0
- package/dist/module/web/RNFBFirestoreModule.js +387 -0
- package/dist/module/web/RNFBFirestoreModule.js.map +1 -0
- package/{lib → dist/module}/web/convert.js +60 -94
- package/dist/module/web/convert.js.map +1 -0
- package/dist/module/web/pipelines/pipeline.js +34 -0
- package/dist/module/web/pipelines/pipeline.js.map +1 -0
- package/dist/module/web/pipelines/pipeline_bridge_factory.js +217 -0
- package/dist/module/web/pipelines/pipeline_bridge_factory.js.map +1 -0
- package/dist/module/web/pipelines/pipeline_node_builder.js +294 -0
- package/dist/module/web/pipelines/pipeline_node_builder.js.map +1 -0
- package/dist/module/web/pipelines/pipeline_parser.js +21 -0
- package/dist/module/web/pipelines/pipeline_parser.js.map +1 -0
- package/dist/module/web/pipelines/pipeline_snapshot_serializer.js +89 -0
- package/dist/module/web/pipelines/pipeline_snapshot_serializer.js.map +1 -0
- package/dist/module/web/query.js +95 -0
- package/dist/module/web/query.js.map +1 -0
- package/dist/typescript/lib/FieldPath.d.ts +10 -0
- package/dist/typescript/lib/FieldPath.d.ts.map +1 -0
- package/dist/typescript/lib/FieldValue.d.ts +17 -0
- package/dist/typescript/lib/FieldValue.d.ts.map +1 -0
- package/dist/typescript/lib/FirestoreAggregate.d.ts +40 -0
- package/dist/typescript/lib/FirestoreAggregate.d.ts.map +1 -0
- package/dist/typescript/lib/FirestoreBlob.d.ts +11 -0
- package/dist/typescript/lib/FirestoreBlob.d.ts.map +1 -0
- package/dist/typescript/lib/FirestoreCollectionReference.d.ts +15 -0
- package/dist/typescript/lib/FirestoreCollectionReference.d.ts.map +1 -0
- package/dist/typescript/lib/FirestoreDocumentChange.d.ts +27 -0
- package/dist/typescript/lib/FirestoreDocumentChange.d.ts.map +1 -0
- package/dist/typescript/lib/FirestoreDocumentReference.d.ts +30 -0
- package/dist/typescript/lib/FirestoreDocumentReference.d.ts.map +1 -0
- package/dist/typescript/lib/FirestoreDocumentSnapshot.d.ts +30 -0
- package/dist/typescript/lib/FirestoreDocumentSnapshot.d.ts.map +1 -0
- package/dist/typescript/lib/FirestoreFilter.d.ts +52 -0
- package/dist/typescript/lib/FirestoreFilter.d.ts.map +1 -0
- package/dist/typescript/lib/FirestoreGeoPoint.d.ts +22 -0
- package/dist/typescript/lib/FirestoreGeoPoint.d.ts.map +1 -0
- package/dist/typescript/lib/FirestorePath.d.ts +12 -0
- package/dist/typescript/lib/FirestorePath.d.ts.map +1 -0
- package/dist/typescript/lib/FirestorePersistentCacheIndexManager.d.ts +16 -0
- package/dist/typescript/lib/FirestorePersistentCacheIndexManager.d.ts.map +1 -0
- package/dist/typescript/lib/FirestoreQuery.d.ts +39 -0
- package/dist/typescript/lib/FirestoreQuery.d.ts.map +1 -0
- package/dist/typescript/lib/FirestoreQueryModifiers.d.ts +59 -0
- package/dist/typescript/lib/FirestoreQueryModifiers.d.ts.map +1 -0
- package/dist/typescript/lib/FirestoreQuerySnapshot.d.ts +49 -0
- package/dist/typescript/lib/FirestoreQuerySnapshot.d.ts.map +1 -0
- package/dist/typescript/lib/FirestoreSnapshotMetadata.d.ts +8 -0
- package/dist/typescript/lib/FirestoreSnapshotMetadata.d.ts.map +1 -0
- package/dist/typescript/lib/FirestoreStatics.d.ts +23 -0
- package/dist/typescript/lib/FirestoreStatics.d.ts.map +1 -0
- package/dist/typescript/lib/FirestoreTimestamp.d.ts +33 -0
- package/dist/typescript/lib/FirestoreTimestamp.d.ts.map +1 -0
- package/dist/typescript/lib/FirestoreTransaction.d.ts +42 -0
- package/dist/typescript/lib/FirestoreTransaction.d.ts.map +1 -0
- package/dist/typescript/lib/FirestoreTransactionHandler.d.ts +26 -0
- package/dist/typescript/lib/FirestoreTransactionHandler.d.ts.map +1 -0
- package/dist/typescript/lib/FirestoreVectorValue.d.ts +17 -0
- package/dist/typescript/lib/FirestoreVectorValue.d.ts.map +1 -0
- package/dist/typescript/lib/FirestoreWriteBatch.d.ts +21 -0
- package/dist/typescript/lib/FirestoreWriteBatch.d.ts.map +1 -0
- package/dist/typescript/lib/LoadBundleTask.d.ts +16 -0
- package/dist/typescript/lib/LoadBundleTask.d.ts.map +1 -0
- package/dist/typescript/lib/index.d.ts +6 -0
- package/dist/typescript/lib/index.d.ts.map +1 -0
- package/dist/typescript/lib/modular/Bytes.d.ts +22 -0
- package/dist/typescript/lib/modular/Bytes.d.ts.map +1 -0
- package/dist/typescript/lib/modular/FieldPath.d.ts +4 -0
- package/dist/typescript/lib/modular/FieldPath.d.ts.map +1 -0
- package/dist/typescript/lib/modular/FieldValue.d.ts +8 -0
- package/dist/typescript/lib/modular/FieldValue.d.ts.map +1 -0
- package/dist/typescript/lib/modular/GeoPoint.d.ts +3 -0
- package/dist/typescript/lib/modular/GeoPoint.d.ts.map +1 -0
- package/dist/typescript/lib/modular/Timestamp.d.ts +3 -0
- package/dist/typescript/lib/modular/Timestamp.d.ts.map +1 -0
- package/dist/typescript/lib/modular/VectorValue.d.ts +4 -0
- package/dist/typescript/lib/modular/VectorValue.d.ts.map +1 -0
- package/dist/typescript/lib/modular/query.d.ts +93 -0
- package/dist/typescript/lib/modular/query.d.ts.map +1 -0
- package/dist/typescript/lib/modular/snapshot.d.ts +30 -0
- package/dist/typescript/lib/modular/snapshot.d.ts.map +1 -0
- package/dist/typescript/lib/modular.d.ts +69 -0
- package/dist/typescript/lib/modular.d.ts.map +1 -0
- package/dist/typescript/lib/namespaced.d.ts +13 -0
- package/dist/typescript/lib/namespaced.d.ts.map +1 -0
- package/dist/typescript/lib/pipelines/expressions.d.ts +723 -0
- package/dist/typescript/lib/pipelines/expressions.d.ts.map +1 -0
- package/dist/typescript/lib/pipelines/index.d.ts +31 -0
- package/dist/typescript/lib/pipelines/index.d.ts.map +1 -0
- package/dist/typescript/lib/pipelines/pipeline-result.d.ts +30 -0
- package/dist/typescript/lib/pipelines/pipeline-result.d.ts.map +1 -0
- package/dist/typescript/lib/pipelines/pipeline-source.d.ts +64 -0
- package/dist/typescript/lib/pipelines/pipeline-source.d.ts.map +1 -0
- package/dist/typescript/lib/pipelines/pipeline.d.ts +61 -0
- package/dist/typescript/lib/pipelines/pipeline.d.ts.map +1 -0
- package/dist/typescript/lib/pipelines/pipeline_impl.d.ts +21 -0
- package/dist/typescript/lib/pipelines/pipeline_impl.d.ts.map +1 -0
- package/dist/typescript/lib/pipelines/pipeline_options.d.ts +17 -0
- package/dist/typescript/lib/pipelines/pipeline_options.d.ts.map +1 -0
- package/dist/typescript/lib/pipelines/pipeline_runtime.d.ts +10 -0
- package/dist/typescript/lib/pipelines/pipeline_runtime.d.ts.map +1 -0
- package/dist/typescript/lib/pipelines/pipeline_support.d.ts +7 -0
- package/dist/typescript/lib/pipelines/pipeline_support.d.ts.map +1 -0
- package/dist/typescript/lib/pipelines/pipeline_validate.d.ts +9 -0
- package/dist/typescript/lib/pipelines/pipeline_validate.d.ts.map +1 -0
- package/dist/typescript/lib/pipelines/stage_options.d.ts +326 -0
- package/dist/typescript/lib/pipelines/stage_options.d.ts.map +1 -0
- package/dist/typescript/lib/pipelines/types.d.ts +10 -0
- package/dist/typescript/lib/pipelines/types.d.ts.map +1 -0
- package/dist/typescript/lib/types/firestore.d.ts +263 -0
- package/dist/typescript/lib/types/firestore.d.ts.map +1 -0
- package/dist/typescript/lib/types/internal.d.ts +483 -0
- package/dist/typescript/lib/types/internal.d.ts.map +1 -0
- package/dist/typescript/lib/types/namespaced.d.ts +2285 -0
- package/dist/typescript/lib/types/namespaced.d.ts.map +1 -0
- package/dist/typescript/lib/utils/index.d.ts +15 -0
- package/dist/typescript/lib/utils/index.d.ts.map +1 -0
- package/dist/typescript/lib/utils/serialize.d.ts +17 -0
- package/dist/typescript/lib/utils/serialize.d.ts.map +1 -0
- package/dist/typescript/lib/utils/typemap.d.ts +3 -0
- package/dist/typescript/lib/utils/typemap.d.ts.map +1 -0
- package/dist/typescript/lib/version.d.ts +2 -0
- package/dist/typescript/lib/version.d.ts.map +1 -0
- package/dist/typescript/lib/web/RNFBFirestoreModule.android.d.ts +3 -0
- package/dist/typescript/lib/web/RNFBFirestoreModule.android.d.ts.map +1 -0
- package/dist/typescript/lib/web/RNFBFirestoreModule.d.ts +75 -0
- package/dist/typescript/lib/web/RNFBFirestoreModule.d.ts.map +1 -0
- package/dist/typescript/lib/web/RNFBFirestoreModule.ios.d.ts +3 -0
- package/dist/typescript/lib/web/RNFBFirestoreModule.ios.d.ts.map +1 -0
- package/dist/typescript/lib/web/convert.d.ts +14 -0
- package/dist/typescript/lib/web/convert.d.ts.map +1 -0
- package/dist/typescript/lib/web/pipelines/pipeline.d.ts +4 -0
- package/dist/typescript/lib/web/pipelines/pipeline.d.ts.map +1 -0
- package/dist/typescript/lib/web/pipelines/pipeline_bridge_factory.d.ts +5 -0
- package/dist/typescript/lib/web/pipelines/pipeline_bridge_factory.d.ts.map +1 -0
- package/dist/typescript/lib/web/pipelines/pipeline_node_builder.d.ts +5 -0
- package/dist/typescript/lib/web/pipelines/pipeline_node_builder.d.ts.map +1 -0
- package/dist/typescript/lib/web/pipelines/pipeline_parser.d.ts +3 -0
- package/dist/typescript/lib/web/pipelines/pipeline_parser.d.ts.map +1 -0
- package/dist/typescript/lib/web/pipelines/pipeline_snapshot_serializer.d.ts +4 -0
- package/dist/typescript/lib/web/pipelines/pipeline_snapshot_serializer.d.ts.map +1 -0
- package/dist/typescript/lib/web/query.d.ts +23 -0
- package/dist/typescript/lib/web/query.d.ts.map +1 -0
- package/dist/typescript/package.json +1 -0
- package/ios/RNFBFirestore/RNFBFirestoreCollectionModule.m +52 -2
- package/ios/RNFBFirestore/RNFBFirestorePipelineBridgeFactory.swift +384 -0
- package/ios/RNFBFirestore/RNFBFirestorePipelineCallHandler.swift +86 -0
- package/ios/RNFBFirestore/RNFBFirestorePipelineNodeBuilder.swift +1500 -0
- package/ios/RNFBFirestore/RNFBFirestorePipelineParser.swift +1352 -0
- package/ios/RNFBFirestore/RNFBFirestorePipelineSnapshotSerializer.swift +98 -0
- package/lib/{FirestoreFieldPath.js → FieldPath.ts} +10 -12
- package/lib/{FirestoreFieldValue.js → FieldValue.ts} +22 -19
- package/lib/FirestoreAggregate.ts +124 -0
- package/lib/FirestoreBlob.ts +73 -0
- package/lib/FirestoreCollectionReference.ts +99 -0
- package/lib/FirestoreDocumentChange.ts +71 -0
- package/lib/FirestoreDocumentReference.ts +310 -0
- package/lib/FirestoreDocumentSnapshot.ts +149 -0
- package/lib/FirestoreFilter.ts +232 -0
- package/lib/{FirestoreGeoPoint.js → FirestoreGeoPoint.ts} +48 -8
- package/lib/FirestorePath.ts +54 -0
- package/lib/FirestorePersistentCacheIndexManager.ts +46 -0
- package/lib/{FirestoreQuery.js → FirestoreQuery.ts} +208 -100
- package/lib/FirestoreQueryModifiers.ts +411 -0
- package/lib/{FirestoreQuerySnapshot.js → FirestoreQuerySnapshot.ts} +61 -32
- package/lib/{FirestoreSnapshotMetadata.js → FirestoreSnapshotMetadata.ts} +8 -6
- package/lib/{FirestoreStatics.js → FirestoreStatics.ts} +18 -11
- package/lib/FirestoreTimestamp.ts +161 -0
- package/lib/{FirestoreTransaction.js → FirestoreTransaction.ts} +64 -27
- package/lib/{FirestoreTransactionHandler.js → FirestoreTransactionHandler.ts} +54 -75
- package/lib/{FirestoreVectorValue.js → FirestoreVectorValue.ts} +36 -15
- package/lib/{FirestoreWriteBatch.js → FirestoreWriteBatch.ts} +45 -21
- package/lib/LoadBundleTask.ts +85 -0
- package/lib/index.ts +71 -0
- package/lib/modular/Bytes.ts +81 -0
- package/lib/modular/FieldPath.ts +24 -0
- package/lib/modular/FieldValue.ts +40 -0
- package/lib/modular/GeoPoint.ts +20 -0
- package/lib/modular/Timestamp.ts +20 -0
- package/lib/modular/VectorValue.ts +24 -0
- package/lib/modular/query.ts +368 -0
- package/lib/modular/snapshot.ts +137 -0
- package/lib/modular.ts +552 -0
- package/lib/{index.js → namespaced.ts} +170 -80
- package/lib/pipelines/expressions.ts +2321 -0
- package/lib/pipelines/index.ts +203 -0
- package/lib/pipelines/pipeline-result.ts +78 -0
- package/lib/pipelines/pipeline-source.ts +83 -0
- package/lib/pipelines/pipeline.ts +99 -0
- package/lib/pipelines/pipeline_impl.ts +46 -0
- package/lib/pipelines/pipeline_options.ts +32 -0
- package/lib/pipelines/pipeline_runtime.ts +863 -0
- package/lib/pipelines/pipeline_support.ts +134 -0
- package/lib/pipelines/pipeline_validate.ts +242 -0
- package/lib/pipelines/stage_options.ts +376 -0
- package/lib/pipelines/types.ts +26 -0
- package/lib/types/firestore.ts +477 -0
- package/lib/types/internal.ts +747 -0
- package/lib/{index.d.ts → types/namespaced.ts} +280 -79
- package/lib/utils/index.ts +244 -0
- package/lib/utils/serialize.ts +314 -0
- package/lib/utils/typemap.ts +65 -0
- package/lib/version.ts +2 -0
- package/lib/web/{RNFBFirestoreModule.js → RNFBFirestoreModule.ts} +222 -234
- package/lib/web/convert.ts +287 -0
- package/lib/web/pipelines/pipeline.ts +47 -0
- package/lib/web/pipelines/pipeline_bridge_factory.ts +377 -0
- package/lib/web/pipelines/pipeline_node_builder.ts +413 -0
- package/lib/web/pipelines/pipeline_parser.ts +23 -0
- package/lib/web/pipelines/pipeline_snapshot_serializer.ts +133 -0
- package/lib/web/query.ts +150 -0
- package/package.json +46 -7
- package/tsconfig.json +35 -0
- package/lib/FirestoreBlob.js +0 -107
- package/lib/FirestoreCollectionReference.js +0 -70
- package/lib/FirestoreDocumentReference.js +0 -222
- package/lib/FirestoreDocumentSnapshot.js +0 -132
- package/lib/FirestoreFilter.js +0 -156
- package/lib/modular/Bytes.d.ts +0 -11
- package/lib/modular/Bytes.js +0 -62
- package/lib/modular/FieldPath.d.ts +0 -20
- package/lib/modular/FieldPath.js +0 -7
- package/lib/modular/FieldValue.d.ts +0 -67
- package/lib/modular/FieldValue.js +0 -41
- package/lib/modular/GeoPoint.d.ts +0 -17
- package/lib/modular/GeoPoint.js +0 -3
- package/lib/modular/Timestamp.d.ts +0 -85
- package/lib/modular/Timestamp.js +0 -3
- package/lib/modular/VectorValue.d.ts +0 -30
- package/lib/modular/VectorValue.js +0 -11
- package/lib/modular/index.d.ts +0 -788
- package/lib/modular/index.js +0 -410
- package/lib/modular/query.d.ts +0 -370
- package/lib/modular/query.js +0 -233
- package/lib/modular/snapshot.d.ts +0 -256
- package/lib/modular/snapshot.js +0 -33
- package/lib/modular/utils/observer.js +0 -16
- package/lib/version.js +0 -2
- package/lib/web/query.js +0 -112
- /package/lib/web/{RNFBFirestoreModule.android.js → RNFBFirestoreModule.android.ts} +0 -0
- /package/lib/web/{RNFBFirestoreModule.ios.js → RNFBFirestoreModule.ios.ts} +0 -0
|
@@ -0,0 +1,1735 @@
|
|
|
1
|
+
package io.invertase.firebase.firestore;
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.ReadableArray;
|
|
4
|
+
import com.facebook.react.bridge.ReadableMap;
|
|
5
|
+
import com.facebook.react.bridge.ReadableMapKeySetIterator;
|
|
6
|
+
import com.facebook.react.bridge.ReadableType;
|
|
7
|
+
import java.util.ArrayDeque;
|
|
8
|
+
import java.util.Arrays;
|
|
9
|
+
import java.util.HashMap;
|
|
10
|
+
import java.util.HashSet;
|
|
11
|
+
import java.util.List;
|
|
12
|
+
import java.util.Map;
|
|
13
|
+
import java.util.Set;
|
|
14
|
+
|
|
15
|
+
final class ReactNativeFirebaseFirestorePipelineParser {
|
|
16
|
+
private static final Set<String> SOURCE_TYPES =
|
|
17
|
+
new HashSet<>(
|
|
18
|
+
Arrays.asList("collection", "collectionGroup", "database", "documents", "query"));
|
|
19
|
+
|
|
20
|
+
private static final Set<String> KNOWN_STAGES =
|
|
21
|
+
new HashSet<>(
|
|
22
|
+
Arrays.asList(
|
|
23
|
+
"where",
|
|
24
|
+
"select",
|
|
25
|
+
"addFields",
|
|
26
|
+
"removeFields",
|
|
27
|
+
"sort",
|
|
28
|
+
"limit",
|
|
29
|
+
"offset",
|
|
30
|
+
"aggregate",
|
|
31
|
+
"distinct",
|
|
32
|
+
"findNearest",
|
|
33
|
+
"replaceWith",
|
|
34
|
+
"sample",
|
|
35
|
+
"union",
|
|
36
|
+
"unnest",
|
|
37
|
+
"rawStage"));
|
|
38
|
+
|
|
39
|
+
private static final class ParsedPipelineRequestBox {
|
|
40
|
+
ParsedPipelineRequest value;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
private static final class ParsedExpressionNodeBox {
|
|
44
|
+
ParsedExpressionNode value;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
private static final class ParsedValueNodeBox {
|
|
48
|
+
ParsedValueNode value;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
private interface PendingParsedStage {}
|
|
52
|
+
|
|
53
|
+
private static final class ReadyParsedStage implements PendingParsedStage {
|
|
54
|
+
final ParsedPipelineStage stage;
|
|
55
|
+
|
|
56
|
+
ReadyParsedStage(ParsedPipelineStage stage) {
|
|
57
|
+
this.stage = stage;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private static final class PendingUnionStage implements PendingParsedStage {
|
|
62
|
+
final ParsedPipelineRequestBox childBox;
|
|
63
|
+
|
|
64
|
+
PendingUnionStage(ParsedPipelineRequestBox childBox) {
|
|
65
|
+
this.childBox = childBox;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
private abstract static class PipelineParseFrame {}
|
|
70
|
+
|
|
71
|
+
private abstract static class ExpressionValueParseFrame {}
|
|
72
|
+
|
|
73
|
+
private static final class PendingValueEntry {
|
|
74
|
+
final String key;
|
|
75
|
+
final Object value;
|
|
76
|
+
final ParsedValueNodeBox box;
|
|
77
|
+
|
|
78
|
+
PendingValueEntry(String key, Object value, ParsedValueNodeBox box) {
|
|
79
|
+
this.key = key;
|
|
80
|
+
this.value = value;
|
|
81
|
+
this.box = box;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
private static final class EnterPipelineParseFrame extends PipelineParseFrame {
|
|
86
|
+
final Map<String, Object> pipeline;
|
|
87
|
+
final Map<String, Object> options;
|
|
88
|
+
final ParsedPipelineRequestBox box;
|
|
89
|
+
|
|
90
|
+
EnterPipelineParseFrame(
|
|
91
|
+
Map<String, Object> pipeline, Map<String, Object> options, ParsedPipelineRequestBox box) {
|
|
92
|
+
this.pipeline = pipeline;
|
|
93
|
+
this.options = options;
|
|
94
|
+
this.box = box;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
private static final class ExitPipelineParseFrame extends PipelineParseFrame {
|
|
99
|
+
final ParsedPipelineSource source;
|
|
100
|
+
final List<PendingParsedStage> stages;
|
|
101
|
+
final ParsedPipelineExecuteOptions options;
|
|
102
|
+
final ParsedPipelineRequestBox box;
|
|
103
|
+
|
|
104
|
+
ExitPipelineParseFrame(
|
|
105
|
+
ParsedPipelineSource source,
|
|
106
|
+
List<PendingParsedStage> stages,
|
|
107
|
+
ParsedPipelineExecuteOptions options,
|
|
108
|
+
ParsedPipelineRequestBox box) {
|
|
109
|
+
this.source = source;
|
|
110
|
+
this.stages = stages;
|
|
111
|
+
this.options = options;
|
|
112
|
+
this.box = box;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
private static final class ExpressionEnterFrame extends ExpressionValueParseFrame {
|
|
117
|
+
final Object value;
|
|
118
|
+
final ParsedExpressionNodeBox box;
|
|
119
|
+
final String fieldName;
|
|
120
|
+
|
|
121
|
+
ExpressionEnterFrame(Object value, ParsedExpressionNodeBox box, String fieldName) {
|
|
122
|
+
this.value = value;
|
|
123
|
+
this.box = box;
|
|
124
|
+
this.fieldName = fieldName;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
private static final class ExpressionValueExitFrame extends ExpressionValueParseFrame {
|
|
129
|
+
final ParsedValueNodeBox valueBox;
|
|
130
|
+
final ParsedExpressionNodeBox expressionBox;
|
|
131
|
+
final String fieldName;
|
|
132
|
+
|
|
133
|
+
ExpressionValueExitFrame(
|
|
134
|
+
ParsedValueNodeBox valueBox, ParsedExpressionNodeBox expressionBox, String fieldName) {
|
|
135
|
+
this.valueBox = valueBox;
|
|
136
|
+
this.expressionBox = expressionBox;
|
|
137
|
+
this.fieldName = fieldName;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
private static final class ExpressionConstantExitFrame extends ExpressionValueParseFrame {
|
|
142
|
+
final ParsedExpressionNodeBox expressionBox;
|
|
143
|
+
final ParsedValueNodeBox valueBox;
|
|
144
|
+
final String fieldName;
|
|
145
|
+
|
|
146
|
+
ExpressionConstantExitFrame(
|
|
147
|
+
ParsedExpressionNodeBox expressionBox, ParsedValueNodeBox valueBox, String fieldName) {
|
|
148
|
+
this.expressionBox = expressionBox;
|
|
149
|
+
this.valueBox = valueBox;
|
|
150
|
+
this.fieldName = fieldName;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
private static final class ExpressionFunctionExitFrame extends ExpressionValueParseFrame {
|
|
155
|
+
final ParsedExpressionNodeBox box;
|
|
156
|
+
final String name;
|
|
157
|
+
final List<ParsedValueNodeBox> argBoxes;
|
|
158
|
+
final String fieldName;
|
|
159
|
+
|
|
160
|
+
ExpressionFunctionExitFrame(
|
|
161
|
+
ParsedExpressionNodeBox box,
|
|
162
|
+
String name,
|
|
163
|
+
List<ParsedValueNodeBox> argBoxes,
|
|
164
|
+
String fieldName) {
|
|
165
|
+
this.box = box;
|
|
166
|
+
this.name = name;
|
|
167
|
+
this.argBoxes = argBoxes;
|
|
168
|
+
this.fieldName = fieldName;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
private static final class ExpressionOperatorLogicalExitFrame extends ExpressionValueParseFrame {
|
|
173
|
+
final ParsedExpressionNodeBox box;
|
|
174
|
+
final String normalizedOperator;
|
|
175
|
+
final List<ParsedExpressionNodeBox> queryBoxes;
|
|
176
|
+
final String fieldName;
|
|
177
|
+
|
|
178
|
+
ExpressionOperatorLogicalExitFrame(
|
|
179
|
+
ParsedExpressionNodeBox box,
|
|
180
|
+
String normalizedOperator,
|
|
181
|
+
List<ParsedExpressionNodeBox> queryBoxes,
|
|
182
|
+
String fieldName) {
|
|
183
|
+
this.box = box;
|
|
184
|
+
this.normalizedOperator = normalizedOperator;
|
|
185
|
+
this.queryBoxes = queryBoxes;
|
|
186
|
+
this.fieldName = fieldName;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
private static final class ExpressionOperatorBinaryExitFrame extends ExpressionValueParseFrame {
|
|
191
|
+
final ParsedExpressionNodeBox box;
|
|
192
|
+
final String normalizedOperator;
|
|
193
|
+
final ParsedExpressionNodeBox fieldBox;
|
|
194
|
+
final ParsedValueNodeBox valueBox;
|
|
195
|
+
final String fieldName;
|
|
196
|
+
|
|
197
|
+
ExpressionOperatorBinaryExitFrame(
|
|
198
|
+
ParsedExpressionNodeBox box,
|
|
199
|
+
String normalizedOperator,
|
|
200
|
+
ParsedExpressionNodeBox fieldBox,
|
|
201
|
+
ParsedValueNodeBox valueBox,
|
|
202
|
+
String fieldName) {
|
|
203
|
+
this.box = box;
|
|
204
|
+
this.normalizedOperator = normalizedOperator;
|
|
205
|
+
this.fieldBox = fieldBox;
|
|
206
|
+
this.valueBox = valueBox;
|
|
207
|
+
this.fieldName = fieldName;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
private static final class ValueEnterFrame extends ExpressionValueParseFrame {
|
|
212
|
+
final Object value;
|
|
213
|
+
final ParsedValueNodeBox box;
|
|
214
|
+
final String fieldName;
|
|
215
|
+
|
|
216
|
+
ValueEnterFrame(Object value, ParsedValueNodeBox box, String fieldName) {
|
|
217
|
+
this.value = value;
|
|
218
|
+
this.box = box;
|
|
219
|
+
this.fieldName = fieldName;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
private static final class ValueListExitFrame extends ExpressionValueParseFrame {
|
|
224
|
+
final ParsedValueNodeBox box;
|
|
225
|
+
final List<ParsedValueNodeBox> childBoxes;
|
|
226
|
+
final String fieldName;
|
|
227
|
+
|
|
228
|
+
ValueListExitFrame(
|
|
229
|
+
ParsedValueNodeBox box, List<ParsedValueNodeBox> childBoxes, String fieldName) {
|
|
230
|
+
this.box = box;
|
|
231
|
+
this.childBoxes = childBoxes;
|
|
232
|
+
this.fieldName = fieldName;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
private static final class ValueMapExitFrame extends ExpressionValueParseFrame {
|
|
237
|
+
final ParsedValueNodeBox box;
|
|
238
|
+
final List<Map.Entry<String, ParsedValueNodeBox>> entries;
|
|
239
|
+
final String fieldName;
|
|
240
|
+
|
|
241
|
+
ValueMapExitFrame(
|
|
242
|
+
ParsedValueNodeBox box,
|
|
243
|
+
List<Map.Entry<String, ParsedValueNodeBox>> entries,
|
|
244
|
+
String fieldName) {
|
|
245
|
+
this.box = box;
|
|
246
|
+
this.entries = entries;
|
|
247
|
+
this.fieldName = fieldName;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
private static final class StageDescriptor {
|
|
252
|
+
final String stageName;
|
|
253
|
+
final Map<String, Object> stageOptions;
|
|
254
|
+
|
|
255
|
+
StageDescriptor(String stageName, Map<String, Object> stageOptions) {
|
|
256
|
+
this.stageName = stageName;
|
|
257
|
+
this.stageOptions = stageOptions;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
private ReactNativeFirebaseFirestorePipelineParser() {}
|
|
262
|
+
|
|
263
|
+
static ParsedPipelineRequest parse(ReadableMap pipeline, ReadableMap options)
|
|
264
|
+
throws ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException {
|
|
265
|
+
if (pipeline == null) {
|
|
266
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
267
|
+
"pipelineExecute() expected a pipeline object.");
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
return parsePipelineMap(
|
|
271
|
+
readableMapToJava(pipeline), options == null ? null : readableMapToJava(options));
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
private static ParsedPipelineRequest parsePipelineMap(
|
|
275
|
+
Map<String, Object> pipeline, Map<String, Object> options)
|
|
276
|
+
throws ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException {
|
|
277
|
+
ParsedPipelineRequestBox rootBox = new ParsedPipelineRequestBox();
|
|
278
|
+
ArrayDeque<PipelineParseFrame> stack = new ArrayDeque<>();
|
|
279
|
+
stack.push(new EnterPipelineParseFrame(pipeline, options, rootBox));
|
|
280
|
+
|
|
281
|
+
while (!stack.isEmpty()) {
|
|
282
|
+
PipelineParseFrame frame = stack.pop();
|
|
283
|
+
if (frame instanceof EnterPipelineParseFrame) {
|
|
284
|
+
EnterPipelineParseFrame enterFrame = (EnterPipelineParseFrame) frame;
|
|
285
|
+
ParsedPipelineSource source =
|
|
286
|
+
parseSource(requireMap(enterFrame.pipeline, "source", "pipeline.source"));
|
|
287
|
+
List<Object> stagesArray = requireArray(enterFrame.pipeline, "stages", "pipeline.stages");
|
|
288
|
+
ParsedPipelineExecuteOptions parsedOptions = parseOptions(enterFrame.options);
|
|
289
|
+
List<PendingParsedStage> pendingStages = new java.util.ArrayList<>(stagesArray.size());
|
|
290
|
+
List<Map.Entry<Map<String, Object>, ParsedPipelineRequestBox>> nestedPipelines =
|
|
291
|
+
new java.util.ArrayList<>();
|
|
292
|
+
|
|
293
|
+
for (int i = 0; i < stagesArray.size(); i++) {
|
|
294
|
+
Object stageValue = stagesArray.get(i);
|
|
295
|
+
if (!(stageValue instanceof Map)) {
|
|
296
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
297
|
+
"pipelineExecute() expected each pipeline stage to be an object.");
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
@SuppressWarnings("unchecked")
|
|
301
|
+
Map<String, Object> stageMap = (Map<String, Object>) stageValue;
|
|
302
|
+
String fieldName = "pipeline.stages[" + i + "]";
|
|
303
|
+
StageDescriptor descriptor = parseStageDescriptor(stageMap, fieldName);
|
|
304
|
+
if ("union".equals(descriptor.stageName)) {
|
|
305
|
+
ParsedPipelineRequestBox childBox = new ParsedPipelineRequestBox();
|
|
306
|
+
pendingStages.add(new PendingUnionStage(childBox));
|
|
307
|
+
nestedPipelines.add(
|
|
308
|
+
new java.util.AbstractMap.SimpleEntry<>(
|
|
309
|
+
requireMap(descriptor.stageOptions, "other", fieldName + ".options.other"),
|
|
310
|
+
childBox));
|
|
311
|
+
} else {
|
|
312
|
+
pendingStages.add(
|
|
313
|
+
new ReadyParsedStage(parseStage(descriptor.stageName, descriptor.stageOptions)));
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
stack.push(
|
|
318
|
+
new ExitPipelineParseFrame(source, pendingStages, parsedOptions, enterFrame.box));
|
|
319
|
+
for (int i = nestedPipelines.size() - 1; i >= 0; i--) {
|
|
320
|
+
Map.Entry<Map<String, Object>, ParsedPipelineRequestBox> nestedEntry =
|
|
321
|
+
nestedPipelines.get(i);
|
|
322
|
+
stack.push(
|
|
323
|
+
new EnterPipelineParseFrame(nestedEntry.getKey(), null, nestedEntry.getValue()));
|
|
324
|
+
}
|
|
325
|
+
continue;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
ExitPipelineParseFrame exitFrame = (ExitPipelineParseFrame) frame;
|
|
329
|
+
List<ParsedPipelineStage> stages = new java.util.ArrayList<>(exitFrame.stages.size());
|
|
330
|
+
for (PendingParsedStage pendingStage : exitFrame.stages) {
|
|
331
|
+
if (pendingStage instanceof ReadyParsedStage) {
|
|
332
|
+
stages.add(((ReadyParsedStage) pendingStage).stage);
|
|
333
|
+
continue;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
ParsedPipelineRequestBox childBox = ((PendingUnionStage) pendingStage).childBox;
|
|
337
|
+
if (childBox.value == null) {
|
|
338
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
339
|
+
"pipelineExecute() failed to parse nested union pipeline.");
|
|
340
|
+
}
|
|
341
|
+
stages.add(new ParsedUnionStage(childBox.value));
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
exitFrame.box.value = new ParsedPipelineRequest(exitFrame.source, stages, exitFrame.options);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
if (rootBox.value == null) {
|
|
348
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
349
|
+
"pipelineExecute() expected a pipeline object.");
|
|
350
|
+
}
|
|
351
|
+
return rootBox.value;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
private static ParsedPipelineSource parseSource(Map<String, Object> source)
|
|
355
|
+
throws ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException {
|
|
356
|
+
String sourceType = requireNonEmptyString(source, "source", "pipeline.source.source");
|
|
357
|
+
if (!SOURCE_TYPES.contains(sourceType)) {
|
|
358
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
359
|
+
"pipelineExecute() received an unknown source type.");
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
switch (sourceType) {
|
|
363
|
+
case "collection":
|
|
364
|
+
return ParsedPipelineSource.collection(
|
|
365
|
+
requireNonEmptyString(source, "path", "pipeline.source.path"),
|
|
366
|
+
optionalMap(source, "rawOptions", "pipeline.source.rawOptions"));
|
|
367
|
+
case "collectionGroup":
|
|
368
|
+
return ParsedPipelineSource.collectionGroup(
|
|
369
|
+
requireNonEmptyString(source, "collectionId", "pipeline.source.collectionId"),
|
|
370
|
+
optionalMap(source, "rawOptions", "pipeline.source.rawOptions"));
|
|
371
|
+
case "database":
|
|
372
|
+
return ParsedPipelineSource.database(
|
|
373
|
+
optionalMap(source, "rawOptions", "pipeline.source.rawOptions"));
|
|
374
|
+
case "documents":
|
|
375
|
+
return ParsedPipelineSource.documents(
|
|
376
|
+
parseDocuments(requireArray(source, "documents", "pipeline.source.documents")));
|
|
377
|
+
case "query":
|
|
378
|
+
return ParsedPipelineSource.query(
|
|
379
|
+
requireNonEmptyString(source, "path", "pipeline.source.path"),
|
|
380
|
+
requireNonEmptyString(source, "queryType", "pipeline.source.queryType"),
|
|
381
|
+
requireArray(source, "filters", "pipeline.source.filters"),
|
|
382
|
+
requireArray(source, "orders", "pipeline.source.orders"),
|
|
383
|
+
requireMap(source, "options", "pipeline.source.options"));
|
|
384
|
+
default:
|
|
385
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
386
|
+
"pipelineExecute() received an unknown source type.");
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
private static StageDescriptor parseStageDescriptor(
|
|
391
|
+
Map<String, Object> stageMap, String fieldName)
|
|
392
|
+
throws ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException {
|
|
393
|
+
Object stageNameValue = stageMap.get("stage");
|
|
394
|
+
if (!(stageNameValue instanceof String) || ((String) stageNameValue).isEmpty()) {
|
|
395
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
396
|
+
"pipelineExecute() expected " + fieldName + ".stage to be a non-empty string.");
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
String stageName = (String) stageNameValue;
|
|
400
|
+
if (!KNOWN_STAGES.contains(stageName)) {
|
|
401
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
402
|
+
"pipelineExecute() received an unknown stage: " + stageName + ".");
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
Object optionsValue = stageMap.get("options");
|
|
406
|
+
if (!(optionsValue instanceof Map)) {
|
|
407
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
408
|
+
"pipelineExecute() expected " + fieldName + ".options to be an object.");
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
@SuppressWarnings("unchecked")
|
|
412
|
+
Map<String, Object> stageOptions = (Map<String, Object>) optionsValue;
|
|
413
|
+
return new StageDescriptor(stageName, stageOptions);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
private static ParsedPipelineStage parseStage(String stageName, Map<String, Object> stageOptions)
|
|
417
|
+
throws ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException {
|
|
418
|
+
switch (stageName) {
|
|
419
|
+
case "where":
|
|
420
|
+
return new ParsedWhereStage(
|
|
421
|
+
parseExpressionNode(
|
|
422
|
+
requireValue(stageOptions, "condition", "stage.options.condition"),
|
|
423
|
+
"stage.options.condition"));
|
|
424
|
+
case "select":
|
|
425
|
+
return new ParsedSelectStage(
|
|
426
|
+
parseSelectableNodes(
|
|
427
|
+
requireArray(stageOptions, "selections", "stage.options.selections"),
|
|
428
|
+
"stage.options.selections"));
|
|
429
|
+
case "addFields":
|
|
430
|
+
return new ParsedAddFieldsStage(
|
|
431
|
+
parseSelectableNodes(
|
|
432
|
+
requireArray(stageOptions, "fields", "stage.options.fields"),
|
|
433
|
+
"stage.options.fields"));
|
|
434
|
+
case "removeFields":
|
|
435
|
+
return new ParsedRemoveFieldsStage(
|
|
436
|
+
requireArray(stageOptions, "fields", "stage.options.fields"));
|
|
437
|
+
case "sort":
|
|
438
|
+
return new ParsedSortStage(
|
|
439
|
+
parseOrderingNodes(
|
|
440
|
+
requireArray(stageOptions, "orderings", "stage.options.orderings"),
|
|
441
|
+
"stage.options.orderings"));
|
|
442
|
+
case "limit":
|
|
443
|
+
return new ParsedLimitStage(requireValue(stageOptions, "limit", "stage.options.limit"));
|
|
444
|
+
case "offset":
|
|
445
|
+
return new ParsedOffsetStage(requireValue(stageOptions, "offset", "stage.options.offset"));
|
|
446
|
+
case "aggregate":
|
|
447
|
+
return new ParsedAggregateStage(
|
|
448
|
+
parseAggregateNodes(
|
|
449
|
+
requireArray(stageOptions, "accumulators", "stage.options.accumulators"),
|
|
450
|
+
"stage.options.accumulators"),
|
|
451
|
+
optionalSelectableNodes(stageOptions, "groups", "stage.options.groups"));
|
|
452
|
+
case "distinct":
|
|
453
|
+
return new ParsedDistinctStage(
|
|
454
|
+
parseSelectableNodes(
|
|
455
|
+
requireArray(stageOptions, "groups", "stage.options.groups"),
|
|
456
|
+
"stage.options.groups"));
|
|
457
|
+
case "findNearest":
|
|
458
|
+
return new ParsedFindNearestStage(
|
|
459
|
+
requireValue(stageOptions, "field", "stage.options.field"),
|
|
460
|
+
requireValue(stageOptions, "vectorValue", "stage.options.vectorValue"),
|
|
461
|
+
requireString(stageOptions, "distanceMeasure", "stage.options.distanceMeasure"),
|
|
462
|
+
stageOptions.get("limit"),
|
|
463
|
+
optionalString(stageOptions, "distanceField"));
|
|
464
|
+
case "replaceWith":
|
|
465
|
+
return new ParsedReplaceWithStage(
|
|
466
|
+
parseExpressionNode(
|
|
467
|
+
requireValue(stageOptions, "map", "stage.options.map"), "stage.options.map"));
|
|
468
|
+
case "sample":
|
|
469
|
+
return new ParsedSampleStage(stageOptions.get("documents"), stageOptions.get("percentage"));
|
|
470
|
+
case "union":
|
|
471
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
472
|
+
"pipelineExecute() failed to parse nested union pipeline.");
|
|
473
|
+
case "unnest":
|
|
474
|
+
return new ParsedUnnestStage(
|
|
475
|
+
parseSelectableNode(
|
|
476
|
+
requireValue(stageOptions, "selectable", "stage.options.selectable"),
|
|
477
|
+
"stage.options.selectable"),
|
|
478
|
+
optionalString(stageOptions, "indexField"));
|
|
479
|
+
case "rawStage":
|
|
480
|
+
return new ParsedRawStage(
|
|
481
|
+
requireNonEmptyString(stageOptions, "name", "stage.options.name"),
|
|
482
|
+
stageOptions.get("params"),
|
|
483
|
+
optionalMap(stageOptions, "options", "stage.options.options"));
|
|
484
|
+
default:
|
|
485
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
486
|
+
"pipelineExecute() received an unknown stage: " + stageName + ".");
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
private static ParsedPipelineExecuteOptions parseOptions(Map<String, Object> options)
|
|
491
|
+
throws ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException {
|
|
492
|
+
if (options == null) {
|
|
493
|
+
return new ParsedPipelineExecuteOptions(null, null);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
String indexMode = null;
|
|
497
|
+
if (options.containsKey("indexMode")) {
|
|
498
|
+
if (!(options.get("indexMode") instanceof String)) {
|
|
499
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
500
|
+
"pipelineExecute() expected options.indexMode to be a string.");
|
|
501
|
+
}
|
|
502
|
+
indexMode = (String) options.get("indexMode");
|
|
503
|
+
if (indexMode != null && !"recommended".equals(indexMode)) {
|
|
504
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
505
|
+
"pipelineExecute() only supports options.indexMode=\"recommended\".");
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
Map<String, Object> rawOptions = optionalMap(options, "rawOptions", "options.rawOptions");
|
|
510
|
+
return new ParsedPipelineExecuteOptions(indexMode, rawOptions);
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
private static String[] parseDocuments(List<Object> values)
|
|
514
|
+
throws ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException {
|
|
515
|
+
if (values.isEmpty()) {
|
|
516
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
517
|
+
"pipelineExecute() expected pipeline.source.documents to contain at least one document"
|
|
518
|
+
+ " path.");
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
String[] parsedDocuments = new String[values.size()];
|
|
522
|
+
for (int i = 0; i < values.size(); i++) {
|
|
523
|
+
Object value = values.get(i);
|
|
524
|
+
if (!(value instanceof String)) {
|
|
525
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
526
|
+
"pipelineExecute() expected pipeline.source.documents entries to be strings.");
|
|
527
|
+
}
|
|
528
|
+
parsedDocuments[i] = (String) value;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
return parsedDocuments;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
private static Map<String, Object> requireMap(
|
|
535
|
+
Map<String, Object> map, String key, String fieldName)
|
|
536
|
+
throws ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException {
|
|
537
|
+
Object value = map.get(key);
|
|
538
|
+
if (!(value instanceof Map)) {
|
|
539
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
540
|
+
"pipelineExecute() expected " + fieldName + " to be an object.");
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
@SuppressWarnings("unchecked")
|
|
544
|
+
Map<String, Object> nested = (Map<String, Object>) value;
|
|
545
|
+
return nested;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
private static List<Object> requireArray(Map<String, Object> map, String key, String fieldName)
|
|
549
|
+
throws ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException {
|
|
550
|
+
Object value = map.get(key);
|
|
551
|
+
if (!(value instanceof List)) {
|
|
552
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
553
|
+
"pipelineExecute() expected " + fieldName + " to be an array.");
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
@SuppressWarnings("unchecked")
|
|
557
|
+
List<Object> nested = (List<Object>) value;
|
|
558
|
+
return nested;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
private static List<Object> optionalArray(Map<String, Object> map, String key, String fieldName)
|
|
562
|
+
throws ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException {
|
|
563
|
+
if (!map.containsKey(key) || map.get(key) == null) {
|
|
564
|
+
return null;
|
|
565
|
+
}
|
|
566
|
+
return requireArray(map, key, fieldName);
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
private static Map<String, Object> optionalMap(
|
|
570
|
+
Map<String, Object> map, String key, String fieldName)
|
|
571
|
+
throws ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException {
|
|
572
|
+
if (!map.containsKey(key) || map.get(key) == null) {
|
|
573
|
+
return null;
|
|
574
|
+
}
|
|
575
|
+
return requireMap(map, key, fieldName);
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
private static Object requireValue(Map<String, Object> map, String key, String fieldName)
|
|
579
|
+
throws ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException {
|
|
580
|
+
if (!map.containsKey(key)) {
|
|
581
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
582
|
+
"pipelineExecute() expected " + fieldName + " to be provided.");
|
|
583
|
+
}
|
|
584
|
+
return map.get(key);
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
private static String requireString(Map<String, Object> map, String key, String fieldName)
|
|
588
|
+
throws ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException {
|
|
589
|
+
Object value = requireValue(map, key, fieldName);
|
|
590
|
+
if (!(value instanceof String)) {
|
|
591
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
592
|
+
"pipelineExecute() expected " + fieldName + " to be a string.");
|
|
593
|
+
}
|
|
594
|
+
return (String) value;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
private static String optionalString(Map<String, Object> map, String key) {
|
|
598
|
+
if (map == null || !map.containsKey(key) || map.get(key) == null) {
|
|
599
|
+
return null;
|
|
600
|
+
}
|
|
601
|
+
Object value = map.get(key);
|
|
602
|
+
return value instanceof String ? (String) value : null;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
private static List<ParsedSelectableNode> parseSelectableNodes(
|
|
606
|
+
List<Object> values, String fieldName)
|
|
607
|
+
throws ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException {
|
|
608
|
+
List<ParsedSelectableNode> output = new java.util.ArrayList<>(values.size());
|
|
609
|
+
for (int i = 0; i < values.size(); i++) {
|
|
610
|
+
output.add(parseSelectableNode(values.get(i), fieldName + "[" + i + "]"));
|
|
611
|
+
}
|
|
612
|
+
return output;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
private static List<ParsedSelectableNode> optionalSelectableNodes(
|
|
616
|
+
Map<String, Object> map, String key, String fieldName)
|
|
617
|
+
throws ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException {
|
|
618
|
+
List<Object> values = optionalArray(map, key, fieldName);
|
|
619
|
+
return values == null ? null : parseSelectableNodes(values, fieldName);
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
private static List<ParsedOrderingNode> parseOrderingNodes(List<Object> values, String fieldName)
|
|
623
|
+
throws ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException {
|
|
624
|
+
List<ParsedOrderingNode> output = new java.util.ArrayList<>(values.size());
|
|
625
|
+
for (int i = 0; i < values.size(); i++) {
|
|
626
|
+
output.add(parseOrderingNode(values.get(i), fieldName + "[" + i + "]"));
|
|
627
|
+
}
|
|
628
|
+
return output;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
private static List<ParsedAggregateNode> parseAggregateNodes(
|
|
632
|
+
List<Object> values, String fieldName)
|
|
633
|
+
throws ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException {
|
|
634
|
+
List<ParsedAggregateNode> output = new java.util.ArrayList<>(values.size());
|
|
635
|
+
for (int i = 0; i < values.size(); i++) {
|
|
636
|
+
output.add(parseAggregateNode(values.get(i), fieldName + "[" + i + "]"));
|
|
637
|
+
}
|
|
638
|
+
return output;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
private static ParsedSelectableNode parseSelectableNode(Object value, String fieldName)
|
|
642
|
+
throws ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException {
|
|
643
|
+
if (value instanceof String) {
|
|
644
|
+
return new ParsedSelectableNode(parseExpressionNode(value, fieldName), null, false);
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
if (!(value instanceof Map)) {
|
|
648
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
649
|
+
"pipelineExecute() expected " + fieldName + " to be a selectable expression.");
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
Map<?, ?> map = (Map<?, ?>) value;
|
|
653
|
+
String alias = firstString(map.get("alias"), map.get("as"), map.get("name"));
|
|
654
|
+
if (alias != null && !alias.isEmpty()) {
|
|
655
|
+
if (map.containsKey("path") || map.containsKey("fieldPath") || map.containsKey("segments")) {
|
|
656
|
+
return new ParsedSelectableNode(
|
|
657
|
+
new ParsedFieldExpressionNode(coerceFieldPath(value, fieldName + ".path")),
|
|
658
|
+
alias,
|
|
659
|
+
true);
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
Object exprValue = firstNonNull(map.get("expr"), map.get("expression"), map.get("field"));
|
|
663
|
+
if (exprValue == null) {
|
|
664
|
+
exprValue = value;
|
|
665
|
+
}
|
|
666
|
+
return new ParsedSelectableNode(
|
|
667
|
+
parseExpressionNode(exprValue, fieldName + ".expr"), alias, false);
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
return new ParsedSelectableNode(parseExpressionNode(value, fieldName), null, false);
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
private static ParsedOrderingNode parseOrderingNode(Object value, String fieldName)
|
|
674
|
+
throws ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException {
|
|
675
|
+
if (value instanceof String) {
|
|
676
|
+
return new ParsedOrderingNode(parseExpressionNode(value, fieldName), false, true);
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
if (!(value instanceof Map)) {
|
|
680
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
681
|
+
"pipelineExecute() expected " + fieldName + " to be a string or object.");
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
Map<?, ?> map = (Map<?, ?>) value;
|
|
685
|
+
String direction =
|
|
686
|
+
map.get("direction") instanceof String ? (String) map.get("direction") : "asc";
|
|
687
|
+
boolean descending = isDescendingDirection(direction);
|
|
688
|
+
Object expressionValue =
|
|
689
|
+
firstNonNull(
|
|
690
|
+
map.get("expression"),
|
|
691
|
+
map.get("expr"),
|
|
692
|
+
map.get("field"),
|
|
693
|
+
map.get("fieldPath"),
|
|
694
|
+
map.get("path"),
|
|
695
|
+
value);
|
|
696
|
+
return new ParsedOrderingNode(
|
|
697
|
+
parseExpressionNode(expressionValue, fieldName), descending, false);
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
private static ParsedAggregateNode parseAggregateNode(Object value, String fieldName)
|
|
701
|
+
throws ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException {
|
|
702
|
+
if (!(value instanceof Map)) {
|
|
703
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
704
|
+
"pipelineExecute() expected " + fieldName + " to be an object.");
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
Map<?, ?> map = (Map<?, ?>) value;
|
|
708
|
+
Object aggregateValue = map.containsKey("aggregate") ? map.get("aggregate") : map;
|
|
709
|
+
if (!(aggregateValue instanceof Map)) {
|
|
710
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
711
|
+
"pipelineExecute() expected " + fieldName + ".aggregate to be an object.");
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
Map<?, ?> aggregateMap = (Map<?, ?>) aggregateValue;
|
|
715
|
+
String kind =
|
|
716
|
+
firstString(
|
|
717
|
+
aggregateMap.get("kind"),
|
|
718
|
+
aggregateMap.get("name"),
|
|
719
|
+
aggregateMap.get("function"),
|
|
720
|
+
aggregateMap.get("op"));
|
|
721
|
+
if (kind == null || kind.isEmpty()) {
|
|
722
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
723
|
+
"pipelineExecute() expected " + fieldName + " to include an aggregate kind.");
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
String alias = firstString(map.get("alias"), map.get("as"), map.get("name"));
|
|
727
|
+
if (alias == null || alias.isEmpty()) {
|
|
728
|
+
alias = kind.toLowerCase(java.util.Locale.ROOT);
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
Object expressionValue = firstNonNull(aggregateMap.get("expr"), aggregateMap.get("field"));
|
|
732
|
+
if (expressionValue == null) {
|
|
733
|
+
expressionValue = aggregateMap.get("value");
|
|
734
|
+
}
|
|
735
|
+
ParsedValueNode primaryValue =
|
|
736
|
+
expressionValue == null ? null : parseValueNode(expressionValue, fieldName + ".expr");
|
|
737
|
+
|
|
738
|
+
java.util.List<ParsedValueNode> args = new java.util.ArrayList<>();
|
|
739
|
+
Object argsValue = aggregateMap.get("args");
|
|
740
|
+
if (argsValue instanceof List) {
|
|
741
|
+
List<?> rawArgs = (List<?>) argsValue;
|
|
742
|
+
for (int i = 0; i < rawArgs.size(); i++) {
|
|
743
|
+
args.add(parseValueNode(rawArgs.get(i), fieldName + ".args[" + i + "]"));
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
return new ParsedAggregateNode(kind, alias, primaryValue, args);
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
private static ParsedExpressionNode parseExpressionNode(Object value, String fieldName)
|
|
751
|
+
throws ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException {
|
|
752
|
+
ParsedExpressionNodeBox rootBox = new ParsedExpressionNodeBox();
|
|
753
|
+
parseExpressionValueTree(new ExpressionEnterFrame(value, rootBox, fieldName));
|
|
754
|
+
if (rootBox.value == null) {
|
|
755
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
756
|
+
"pipelineExecute() expected " + fieldName + " to be provided.");
|
|
757
|
+
}
|
|
758
|
+
return rootBox.value;
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
private static java.util.List<ParsedValueNode> parseArgumentValueNodes(
|
|
762
|
+
Object argsValue, String fieldName)
|
|
763
|
+
throws ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException {
|
|
764
|
+
java.util.List<ParsedValueNode> args = new java.util.ArrayList<>();
|
|
765
|
+
if (argsValue == null) {
|
|
766
|
+
return args;
|
|
767
|
+
}
|
|
768
|
+
if (argsValue instanceof List) {
|
|
769
|
+
List<?> rawArgs = (List<?>) argsValue;
|
|
770
|
+
for (int i = 0; i < rawArgs.size(); i++) {
|
|
771
|
+
args.add(parseValueNode(rawArgs.get(i), fieldName + "[" + i + "]"));
|
|
772
|
+
}
|
|
773
|
+
return args;
|
|
774
|
+
}
|
|
775
|
+
args.add(parseValueNode(argsValue, fieldName + "[0]"));
|
|
776
|
+
return args;
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
private static ParsedValueNode parseValueNode(Object value, String fieldName)
|
|
780
|
+
throws ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException {
|
|
781
|
+
ParsedValueNodeBox rootBox = new ParsedValueNodeBox();
|
|
782
|
+
parseExpressionValueTree(new ValueEnterFrame(value, rootBox, fieldName));
|
|
783
|
+
if (rootBox.value == null) {
|
|
784
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
785
|
+
"pipelineExecute() expected " + fieldName + " to be provided.");
|
|
786
|
+
}
|
|
787
|
+
return rootBox.value;
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
private static boolean isExpressionLike(Map<?, ?> map) {
|
|
791
|
+
Object exprType = map.get("exprType");
|
|
792
|
+
return exprType instanceof String
|
|
793
|
+
|| map.containsKey("operator")
|
|
794
|
+
|| map.containsKey("name")
|
|
795
|
+
|| map.containsKey("expr")
|
|
796
|
+
|| map.containsKey("expression")
|
|
797
|
+
|| map.containsKey("fieldPath")
|
|
798
|
+
|| map.containsKey("path")
|
|
799
|
+
|| map.containsKey("segments")
|
|
800
|
+
|| map.containsKey("_segments");
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
private static String coerceFieldPath(Object value, String fieldName)
|
|
804
|
+
throws ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException {
|
|
805
|
+
Object currentValue = value;
|
|
806
|
+
|
|
807
|
+
while (true) {
|
|
808
|
+
if (currentValue instanceof String) {
|
|
809
|
+
String fieldPath = (String) currentValue;
|
|
810
|
+
if (!fieldPath.isEmpty()) {
|
|
811
|
+
return fieldPath;
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
if (currentValue instanceof Map) {
|
|
816
|
+
Map<?, ?> map = (Map<?, ?>) currentValue;
|
|
817
|
+
Object path = firstNonNull(map.get("path"), map.get("fieldPath"));
|
|
818
|
+
if (path != null && !(path instanceof Map)) {
|
|
819
|
+
currentValue = path;
|
|
820
|
+
continue;
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
Object segments = map.get("segments");
|
|
824
|
+
if (!(segments instanceof List)) {
|
|
825
|
+
segments = map.get("_segments");
|
|
826
|
+
}
|
|
827
|
+
if (segments instanceof List) {
|
|
828
|
+
List<?> list = (List<?>) segments;
|
|
829
|
+
StringBuilder builder = new StringBuilder();
|
|
830
|
+
for (int i = 0; i < list.size(); i++) {
|
|
831
|
+
Object segment = list.get(i);
|
|
832
|
+
if (!(segment instanceof String)) {
|
|
833
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
834
|
+
"pipelineExecute() expected " + fieldName + " segment values to be strings.");
|
|
835
|
+
}
|
|
836
|
+
if (i > 0) {
|
|
837
|
+
builder.append('.');
|
|
838
|
+
}
|
|
839
|
+
builder.append((String) segment);
|
|
840
|
+
}
|
|
841
|
+
String pathValue = builder.toString();
|
|
842
|
+
if (!pathValue.isEmpty()) {
|
|
843
|
+
return pathValue;
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
849
|
+
"pipelineExecute() expected " + fieldName + " to resolve to a field path string.");
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
private static void parseExpressionValueTree(ExpressionValueParseFrame initialFrame)
|
|
854
|
+
throws ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException {
|
|
855
|
+
ArrayDeque<ExpressionValueParseFrame> stack = new ArrayDeque<>();
|
|
856
|
+
stack.push(initialFrame);
|
|
857
|
+
|
|
858
|
+
while (!stack.isEmpty()) {
|
|
859
|
+
ExpressionValueParseFrame frame = stack.pop();
|
|
860
|
+
if (frame instanceof ExpressionEnterFrame) {
|
|
861
|
+
ExpressionEnterFrame enterFrame = (ExpressionEnterFrame) frame;
|
|
862
|
+
Object value = enterFrame.value;
|
|
863
|
+
String fieldName = enterFrame.fieldName;
|
|
864
|
+
|
|
865
|
+
if (value instanceof String) {
|
|
866
|
+
enterFrame.box.value = new ParsedFieldExpressionNode((String) value);
|
|
867
|
+
continue;
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
if (value instanceof Map) {
|
|
871
|
+
Map<?, ?> map = (Map<?, ?>) value;
|
|
872
|
+
if (map.containsKey("expr")) {
|
|
873
|
+
stack.push(
|
|
874
|
+
new ExpressionEnterFrame(map.get("expr"), enterFrame.box, fieldName + ".expr"));
|
|
875
|
+
continue;
|
|
876
|
+
}
|
|
877
|
+
if (map.containsKey("expression")) {
|
|
878
|
+
stack.push(
|
|
879
|
+
new ExpressionEnterFrame(
|
|
880
|
+
map.get("expression"), enterFrame.box, fieldName + ".expression"));
|
|
881
|
+
continue;
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
Object operatorValue = map.get("operator");
|
|
885
|
+
if (operatorValue instanceof String) {
|
|
886
|
+
String normalizedOperator = ((String) operatorValue).toUpperCase(java.util.Locale.ROOT);
|
|
887
|
+
if ("AND".equals(normalizedOperator) || "OR".equals(normalizedOperator)) {
|
|
888
|
+
Object queriesValue = map.get("queries");
|
|
889
|
+
if (!(queriesValue instanceof List) || ((List<?>) queriesValue).isEmpty()) {
|
|
890
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
891
|
+
"pipelineExecute() expected "
|
|
892
|
+
+ fieldName
|
|
893
|
+
+ ".queries to contain boolean expressions.");
|
|
894
|
+
}
|
|
895
|
+
List<?> queries = (List<?>) queriesValue;
|
|
896
|
+
List<ParsedExpressionNodeBox> queryBoxes = new java.util.ArrayList<>(queries.size());
|
|
897
|
+
for (int i = 0; i < queries.size(); i++) {
|
|
898
|
+
queryBoxes.add(new ParsedExpressionNodeBox());
|
|
899
|
+
}
|
|
900
|
+
stack.push(
|
|
901
|
+
new ExpressionOperatorLogicalExitFrame(
|
|
902
|
+
enterFrame.box, normalizedOperator, queryBoxes, fieldName));
|
|
903
|
+
for (int i = queries.size() - 1; i >= 0; i--) {
|
|
904
|
+
stack.push(
|
|
905
|
+
new ExpressionEnterFrame(
|
|
906
|
+
queries.get(i), queryBoxes.get(i), fieldName + ".queries[" + i + "]"));
|
|
907
|
+
}
|
|
908
|
+
continue;
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
Object fieldValue =
|
|
912
|
+
map.get("fieldPath") != null ? map.get("fieldPath") : map.get("field");
|
|
913
|
+
if (fieldValue == null) {
|
|
914
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
915
|
+
"pipelineExecute() expected " + fieldName + ".fieldPath to be provided.");
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
Object rightValue =
|
|
919
|
+
map.containsKey("value")
|
|
920
|
+
? map.get("value")
|
|
921
|
+
: map.containsKey("right") ? map.get("right") : map.get("operand");
|
|
922
|
+
ParsedExpressionNodeBox fieldBox = new ParsedExpressionNodeBox();
|
|
923
|
+
ParsedValueNodeBox valueBox = new ParsedValueNodeBox();
|
|
924
|
+
stack.push(
|
|
925
|
+
new ExpressionOperatorBinaryExitFrame(
|
|
926
|
+
enterFrame.box, normalizedOperator, fieldBox, valueBox, fieldName));
|
|
927
|
+
stack.push(new ValueEnterFrame(rightValue, valueBox, fieldName + ".value"));
|
|
928
|
+
stack.push(new ExpressionEnterFrame(fieldValue, fieldBox, fieldName + ".fieldPath"));
|
|
929
|
+
continue;
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
Object exprType = map.get("exprType");
|
|
933
|
+
if (exprType instanceof String) {
|
|
934
|
+
String normalizedType = ((String) exprType).toLowerCase(java.util.Locale.ROOT);
|
|
935
|
+
if ("field".equals(normalizedType)) {
|
|
936
|
+
enterFrame.box.value =
|
|
937
|
+
new ParsedFieldExpressionNode(coerceFieldPath(value, fieldName));
|
|
938
|
+
continue;
|
|
939
|
+
}
|
|
940
|
+
if ("constant".equals(normalizedType)) {
|
|
941
|
+
ParsedValueNodeBox valueBox = new ParsedValueNodeBox();
|
|
942
|
+
stack.push(new ExpressionConstantExitFrame(enterFrame.box, valueBox, fieldName));
|
|
943
|
+
stack.push(new ValueEnterFrame(map.get("value"), valueBox, fieldName + ".value"));
|
|
944
|
+
continue;
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
if (map.containsKey("name")) {
|
|
949
|
+
Object nameValue = map.get("name");
|
|
950
|
+
if (!(nameValue instanceof String) || ((String) nameValue).isEmpty()) {
|
|
951
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
952
|
+
"pipelineExecute() expected " + fieldName + ".name to be a non-empty string.");
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
List<Object> rawArgs = new java.util.ArrayList<>();
|
|
956
|
+
Object argsValue = map.get("args");
|
|
957
|
+
if (argsValue instanceof List) {
|
|
958
|
+
for (Object rawArg : (List<?>) argsValue) {
|
|
959
|
+
rawArgs.add(rawArg);
|
|
960
|
+
}
|
|
961
|
+
} else if (argsValue != null) {
|
|
962
|
+
rawArgs.add(argsValue);
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
List<ParsedValueNodeBox> argBoxes = new java.util.ArrayList<>(rawArgs.size());
|
|
966
|
+
for (int i = 0; i < rawArgs.size(); i++) {
|
|
967
|
+
argBoxes.add(new ParsedValueNodeBox());
|
|
968
|
+
}
|
|
969
|
+
stack.push(
|
|
970
|
+
new ExpressionFunctionExitFrame(
|
|
971
|
+
enterFrame.box, (String) nameValue, argBoxes, fieldName));
|
|
972
|
+
for (int i = rawArgs.size() - 1; i >= 0; i--) {
|
|
973
|
+
stack.push(
|
|
974
|
+
new ValueEnterFrame(
|
|
975
|
+
rawArgs.get(i), argBoxes.get(i), fieldName + ".args[" + i + "]"));
|
|
976
|
+
}
|
|
977
|
+
continue;
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
if (map.containsKey("fieldPath")
|
|
981
|
+
|| map.containsKey("path")
|
|
982
|
+
|| map.containsKey("segments")
|
|
983
|
+
|| map.containsKey("_segments")) {
|
|
984
|
+
enterFrame.box.value = new ParsedFieldExpressionNode(coerceFieldPath(value, fieldName));
|
|
985
|
+
continue;
|
|
986
|
+
}
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
ParsedValueNodeBox valueBox = new ParsedValueNodeBox();
|
|
990
|
+
stack.push(new ExpressionConstantExitFrame(enterFrame.box, valueBox, fieldName));
|
|
991
|
+
stack.push(new ValueEnterFrame(value, valueBox, fieldName));
|
|
992
|
+
continue;
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
if (frame instanceof ExpressionValueExitFrame) {
|
|
996
|
+
ExpressionValueExitFrame exitFrame = (ExpressionValueExitFrame) frame;
|
|
997
|
+
if (exitFrame.expressionBox.value == null) {
|
|
998
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
999
|
+
"pipelineExecute() expected " + exitFrame.fieldName + " to be provided.");
|
|
1000
|
+
}
|
|
1001
|
+
exitFrame.valueBox.value = new ParsedExpressionValueNode(exitFrame.expressionBox.value);
|
|
1002
|
+
continue;
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
if (frame instanceof ExpressionConstantExitFrame) {
|
|
1006
|
+
ExpressionConstantExitFrame exitFrame = (ExpressionConstantExitFrame) frame;
|
|
1007
|
+
if (exitFrame.valueBox.value == null) {
|
|
1008
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
1009
|
+
"pipelineExecute() expected " + exitFrame.fieldName + " to be provided.");
|
|
1010
|
+
}
|
|
1011
|
+
exitFrame.expressionBox.value = new ParsedConstantExpressionNode(exitFrame.valueBox.value);
|
|
1012
|
+
continue;
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
if (frame instanceof ExpressionFunctionExitFrame) {
|
|
1016
|
+
ExpressionFunctionExitFrame exitFrame = (ExpressionFunctionExitFrame) frame;
|
|
1017
|
+
List<ParsedValueNode> args = new java.util.ArrayList<>(exitFrame.argBoxes.size());
|
|
1018
|
+
for (int i = 0; i < exitFrame.argBoxes.size(); i++) {
|
|
1019
|
+
ParsedValueNode value = exitFrame.argBoxes.get(i).value;
|
|
1020
|
+
if (value == null) {
|
|
1021
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
1022
|
+
"pipelineExecute() expected "
|
|
1023
|
+
+ exitFrame.fieldName
|
|
1024
|
+
+ ".args["
|
|
1025
|
+
+ i
|
|
1026
|
+
+ "] to be provided.");
|
|
1027
|
+
}
|
|
1028
|
+
args.add(value);
|
|
1029
|
+
}
|
|
1030
|
+
exitFrame.box.value = new ParsedFunctionExpressionNode(exitFrame.name, args);
|
|
1031
|
+
continue;
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
if (frame instanceof ExpressionOperatorLogicalExitFrame) {
|
|
1035
|
+
ExpressionOperatorLogicalExitFrame exitFrame = (ExpressionOperatorLogicalExitFrame) frame;
|
|
1036
|
+
List<ParsedValueNode> args = new java.util.ArrayList<>(exitFrame.queryBoxes.size());
|
|
1037
|
+
for (int i = 0; i < exitFrame.queryBoxes.size(); i++) {
|
|
1038
|
+
ParsedExpressionNode expression = exitFrame.queryBoxes.get(i).value;
|
|
1039
|
+
if (expression == null) {
|
|
1040
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
1041
|
+
"pipelineExecute() expected "
|
|
1042
|
+
+ exitFrame.fieldName
|
|
1043
|
+
+ ".queries["
|
|
1044
|
+
+ i
|
|
1045
|
+
+ "] to be provided.");
|
|
1046
|
+
}
|
|
1047
|
+
args.add(new ParsedExpressionValueNode(expression));
|
|
1048
|
+
}
|
|
1049
|
+
exitFrame.box.value =
|
|
1050
|
+
new ParsedFunctionExpressionNode(
|
|
1051
|
+
"AND".equals(exitFrame.normalizedOperator) ? "and" : "or", args);
|
|
1052
|
+
continue;
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
if (frame instanceof ExpressionOperatorBinaryExitFrame) {
|
|
1056
|
+
ExpressionOperatorBinaryExitFrame exitFrame = (ExpressionOperatorBinaryExitFrame) frame;
|
|
1057
|
+
if (exitFrame.fieldBox.value == null) {
|
|
1058
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
1059
|
+
"pipelineExecute() expected " + exitFrame.fieldName + ".fieldPath to be provided.");
|
|
1060
|
+
}
|
|
1061
|
+
if (exitFrame.valueBox.value == null) {
|
|
1062
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
1063
|
+
"pipelineExecute() expected " + exitFrame.fieldName + ".value to be provided.");
|
|
1064
|
+
}
|
|
1065
|
+
List<ParsedValueNode> args = new java.util.ArrayList<>(2);
|
|
1066
|
+
args.add(new ParsedExpressionValueNode(exitFrame.fieldBox.value));
|
|
1067
|
+
args.add(exitFrame.valueBox.value);
|
|
1068
|
+
exitFrame.box.value =
|
|
1069
|
+
new ParsedFunctionExpressionNode(
|
|
1070
|
+
mapOperatorToFunction(exitFrame.normalizedOperator), args);
|
|
1071
|
+
continue;
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
if (frame instanceof ValueEnterFrame) {
|
|
1075
|
+
ValueEnterFrame enterFrame = (ValueEnterFrame) frame;
|
|
1076
|
+
Object value = enterFrame.value;
|
|
1077
|
+
String fieldName = enterFrame.fieldName;
|
|
1078
|
+
|
|
1079
|
+
if (value instanceof Map) {
|
|
1080
|
+
Map<?, ?> map = (Map<?, ?>) value;
|
|
1081
|
+
if (isExpressionLike(map)) {
|
|
1082
|
+
ParsedExpressionNodeBox expressionBox = new ParsedExpressionNodeBox();
|
|
1083
|
+
stack.push(new ExpressionValueExitFrame(enterFrame.box, expressionBox, fieldName));
|
|
1084
|
+
stack.push(new ExpressionEnterFrame(value, expressionBox, fieldName));
|
|
1085
|
+
continue;
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
List<PendingValueEntry> pendingEntries = new java.util.ArrayList<>();
|
|
1089
|
+
List<Map.Entry<String, ParsedValueNodeBox>> exitEntries = new java.util.ArrayList<>();
|
|
1090
|
+
for (Map.Entry<?, ?> entry : map.entrySet()) {
|
|
1091
|
+
if (entry.getKey() instanceof String) {
|
|
1092
|
+
ParsedValueNodeBox childBox = new ParsedValueNodeBox();
|
|
1093
|
+
String key = (String) entry.getKey();
|
|
1094
|
+
pendingEntries.add(new PendingValueEntry(key, entry.getValue(), childBox));
|
|
1095
|
+
exitEntries.add(new java.util.AbstractMap.SimpleEntry<>(key, childBox));
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
stack.push(new ValueMapExitFrame(enterFrame.box, exitEntries, fieldName));
|
|
1099
|
+
for (int i = pendingEntries.size() - 1; i >= 0; i--) {
|
|
1100
|
+
PendingValueEntry entry = pendingEntries.get(i);
|
|
1101
|
+
stack.push(new ValueEnterFrame(entry.value, entry.box, fieldName + "." + entry.key));
|
|
1102
|
+
}
|
|
1103
|
+
continue;
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
if (value instanceof List) {
|
|
1107
|
+
List<?> list = (List<?>) value;
|
|
1108
|
+
List<ParsedValueNodeBox> childBoxes = new java.util.ArrayList<>(list.size());
|
|
1109
|
+
for (int i = 0; i < list.size(); i++) {
|
|
1110
|
+
childBoxes.add(new ParsedValueNodeBox());
|
|
1111
|
+
}
|
|
1112
|
+
stack.push(new ValueListExitFrame(enterFrame.box, childBoxes, fieldName));
|
|
1113
|
+
for (int i = list.size() - 1; i >= 0; i--) {
|
|
1114
|
+
stack.push(
|
|
1115
|
+
new ValueEnterFrame(list.get(i), childBoxes.get(i), fieldName + "[" + i + "]"));
|
|
1116
|
+
}
|
|
1117
|
+
continue;
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
enterFrame.box.value = new ParsedPrimitiveValueNode(value);
|
|
1121
|
+
continue;
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
if (frame instanceof ValueListExitFrame) {
|
|
1125
|
+
ValueListExitFrame exitFrame = (ValueListExitFrame) frame;
|
|
1126
|
+
List<ParsedValueNode> values = new java.util.ArrayList<>(exitFrame.childBoxes.size());
|
|
1127
|
+
for (int i = 0; i < exitFrame.childBoxes.size(); i++) {
|
|
1128
|
+
ParsedValueNode value = exitFrame.childBoxes.get(i).value;
|
|
1129
|
+
if (value == null) {
|
|
1130
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
1131
|
+
"pipelineExecute() expected "
|
|
1132
|
+
+ exitFrame.fieldName
|
|
1133
|
+
+ "["
|
|
1134
|
+
+ i
|
|
1135
|
+
+ "] to be provided.");
|
|
1136
|
+
}
|
|
1137
|
+
values.add(value);
|
|
1138
|
+
}
|
|
1139
|
+
exitFrame.box.value = new ParsedListValueNode(values);
|
|
1140
|
+
continue;
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
ValueMapExitFrame exitFrame = (ValueMapExitFrame) frame;
|
|
1144
|
+
Map<String, ParsedValueNode> values = new java.util.LinkedHashMap<>();
|
|
1145
|
+
for (Map.Entry<String, ParsedValueNodeBox> entry : exitFrame.entries) {
|
|
1146
|
+
if (entry.getValue().value == null) {
|
|
1147
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
1148
|
+
"pipelineExecute() expected "
|
|
1149
|
+
+ exitFrame.fieldName
|
|
1150
|
+
+ "."
|
|
1151
|
+
+ entry.getKey()
|
|
1152
|
+
+ " to be provided.");
|
|
1153
|
+
}
|
|
1154
|
+
values.put(entry.getKey(), entry.getValue().value);
|
|
1155
|
+
}
|
|
1156
|
+
exitFrame.box.value = new ParsedMapValueNode(values);
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
private static String firstString(Object... values) {
|
|
1161
|
+
for (Object value : values) {
|
|
1162
|
+
if (value instanceof String && !((String) value).isEmpty()) {
|
|
1163
|
+
return (String) value;
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
return null;
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
private static Object firstNonNull(Object... values) {
|
|
1170
|
+
for (Object value : values) {
|
|
1171
|
+
if (value != null) {
|
|
1172
|
+
return value;
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
return null;
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
private static boolean isDescendingDirection(String direction) {
|
|
1179
|
+
if (direction == null) {
|
|
1180
|
+
return false;
|
|
1181
|
+
}
|
|
1182
|
+
String normalized = direction.toLowerCase(java.util.Locale.ROOT);
|
|
1183
|
+
return "desc".equals(normalized) || "descending".equals(normalized);
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
private static String mapOperatorToFunction(String operatorName) {
|
|
1187
|
+
switch (operatorName) {
|
|
1188
|
+
case "==":
|
|
1189
|
+
case "=":
|
|
1190
|
+
case "EQUAL":
|
|
1191
|
+
return "equal";
|
|
1192
|
+
case "!=":
|
|
1193
|
+
case "<>":
|
|
1194
|
+
case "NOT_EQUAL":
|
|
1195
|
+
return "not_equal";
|
|
1196
|
+
case ">":
|
|
1197
|
+
case "GREATER_THAN":
|
|
1198
|
+
return "greater_than";
|
|
1199
|
+
case ">=":
|
|
1200
|
+
case "GREATER_THAN_OR_EQUAL":
|
|
1201
|
+
return "greater_than_or_equal";
|
|
1202
|
+
case "<":
|
|
1203
|
+
case "LESS_THAN":
|
|
1204
|
+
return "less_than";
|
|
1205
|
+
case "<=":
|
|
1206
|
+
case "LESS_THAN_OR_EQUAL":
|
|
1207
|
+
return "less_than_or_equal";
|
|
1208
|
+
case "ARRAY_CONTAINS":
|
|
1209
|
+
case "ARRAY-CONTAINS":
|
|
1210
|
+
return "array_contains";
|
|
1211
|
+
case "ARRAY_CONTAINS_ANY":
|
|
1212
|
+
case "ARRAY-CONTAINS-ANY":
|
|
1213
|
+
return "array_contains_any";
|
|
1214
|
+
case "ARRAY_CONTAINS_ALL":
|
|
1215
|
+
case "ARRAY-CONTAINS-ALL":
|
|
1216
|
+
return "array_contains_all";
|
|
1217
|
+
case "IN":
|
|
1218
|
+
return "equal_any";
|
|
1219
|
+
case "NOT_IN":
|
|
1220
|
+
return "not_equal_any";
|
|
1221
|
+
default:
|
|
1222
|
+
return operatorName.toLowerCase(java.util.Locale.ROOT);
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
private static ReadableMap requireMap(ReadableMap map, String key, String fieldName)
|
|
1227
|
+
throws ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException {
|
|
1228
|
+
if (!map.hasKey(key) || map.getType(key) != ReadableType.Map) {
|
|
1229
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
1230
|
+
"pipelineExecute() expected " + fieldName + " to be an object.");
|
|
1231
|
+
}
|
|
1232
|
+
|
|
1233
|
+
ReadableMap nested = map.getMap(key);
|
|
1234
|
+
if (nested == null) {
|
|
1235
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
1236
|
+
"pipelineExecute() expected " + fieldName + " to be an object.");
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
return nested;
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
private static ReadableArray requireArray(ReadableMap map, String key, String fieldName)
|
|
1243
|
+
throws ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException {
|
|
1244
|
+
if (!map.hasKey(key) || map.getType(key) != ReadableType.Array) {
|
|
1245
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
1246
|
+
"pipelineExecute() expected " + fieldName + " to be an array.");
|
|
1247
|
+
}
|
|
1248
|
+
|
|
1249
|
+
ReadableArray nested = map.getArray(key);
|
|
1250
|
+
if (nested == null) {
|
|
1251
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
1252
|
+
"pipelineExecute() expected " + fieldName + " to be an array.");
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1255
|
+
return nested;
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1258
|
+
private static String requireNonEmptyString(ReadableMap map, String key, String fieldName)
|
|
1259
|
+
throws ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException {
|
|
1260
|
+
if (!map.hasKey(key) || map.getType(key) != ReadableType.String) {
|
|
1261
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
1262
|
+
"pipelineExecute() expected " + fieldName + " to be a string.");
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1265
|
+
String value = map.getString(key);
|
|
1266
|
+
if (value == null || value.isEmpty()) {
|
|
1267
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
1268
|
+
"pipelineExecute() expected " + fieldName + " to be a non-empty string.");
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
return value;
|
|
1272
|
+
}
|
|
1273
|
+
|
|
1274
|
+
private static String requireNonEmptyString(Map<String, Object> map, String key, String fieldName)
|
|
1275
|
+
throws ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException {
|
|
1276
|
+
Object value = map.get(key);
|
|
1277
|
+
if (!(value instanceof String)) {
|
|
1278
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
1279
|
+
"pipelineExecute() expected " + fieldName + " to be a string.");
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
String stringValue = (String) value;
|
|
1283
|
+
if (stringValue.isEmpty()) {
|
|
1284
|
+
throw new ReactNativeFirebaseFirestorePipelineExecutor.PipelineValidationException(
|
|
1285
|
+
"pipelineExecute() expected " + fieldName + " to be a non-empty string.");
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1288
|
+
return stringValue;
|
|
1289
|
+
}
|
|
1290
|
+
|
|
1291
|
+
private static Number coerceNumber(double value) {
|
|
1292
|
+
if (Math.floor(value) == value && value <= Long.MAX_VALUE && value >= Long.MIN_VALUE) {
|
|
1293
|
+
return (long) value;
|
|
1294
|
+
}
|
|
1295
|
+
return value;
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1298
|
+
private static Map<String, Object> readableMapToJava(ReadableMap readableMap) {
|
|
1299
|
+
Map<String, Object> output = new HashMap<>();
|
|
1300
|
+
ReadableMapKeySetIterator iterator = readableMap.keySetIterator();
|
|
1301
|
+
|
|
1302
|
+
while (iterator.hasNextKey()) {
|
|
1303
|
+
String key = iterator.nextKey();
|
|
1304
|
+
ReadableType type = readableMap.getType(key);
|
|
1305
|
+
if (type == ReadableType.Null) {
|
|
1306
|
+
output.put(key, null);
|
|
1307
|
+
continue;
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
switch (type) {
|
|
1311
|
+
case Boolean:
|
|
1312
|
+
output.put(key, readableMap.getBoolean(key));
|
|
1313
|
+
break;
|
|
1314
|
+
case Number:
|
|
1315
|
+
output.put(key, coerceNumber(readableMap.getDouble(key)));
|
|
1316
|
+
break;
|
|
1317
|
+
case String:
|
|
1318
|
+
output.put(key, readableMap.getString(key));
|
|
1319
|
+
break;
|
|
1320
|
+
case Map:
|
|
1321
|
+
ReadableMap nestedMap = readableMap.getMap(key);
|
|
1322
|
+
output.put(key, nestedMap == null ? null : readableMapToJava(nestedMap));
|
|
1323
|
+
break;
|
|
1324
|
+
case Array:
|
|
1325
|
+
ReadableArray nestedArray = readableMap.getArray(key);
|
|
1326
|
+
output.put(key, nestedArray == null ? null : readableArrayToJava(nestedArray));
|
|
1327
|
+
break;
|
|
1328
|
+
case Null:
|
|
1329
|
+
default:
|
|
1330
|
+
output.put(key, null);
|
|
1331
|
+
break;
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1335
|
+
return output;
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1338
|
+
private static List<Object> readableArrayToJava(ReadableArray readableArray) {
|
|
1339
|
+
List<Object> output = new java.util.ArrayList<>();
|
|
1340
|
+
for (int i = 0; i < readableArray.size(); i++) {
|
|
1341
|
+
ReadableType type = readableArray.getType(i);
|
|
1342
|
+
if (type == ReadableType.Null) {
|
|
1343
|
+
output.add(null);
|
|
1344
|
+
continue;
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1347
|
+
switch (type) {
|
|
1348
|
+
case Boolean:
|
|
1349
|
+
output.add(readableArray.getBoolean(i));
|
|
1350
|
+
break;
|
|
1351
|
+
case Number:
|
|
1352
|
+
output.add(coerceNumber(readableArray.getDouble(i)));
|
|
1353
|
+
break;
|
|
1354
|
+
case String:
|
|
1355
|
+
output.add(readableArray.getString(i));
|
|
1356
|
+
break;
|
|
1357
|
+
case Map:
|
|
1358
|
+
ReadableMap nestedMap = readableArray.getMap(i);
|
|
1359
|
+
output.add(nestedMap == null ? null : readableMapToJava(nestedMap));
|
|
1360
|
+
break;
|
|
1361
|
+
case Array:
|
|
1362
|
+
ReadableArray nestedArray = readableArray.getArray(i);
|
|
1363
|
+
output.add(nestedArray == null ? null : readableArrayToJava(nestedArray));
|
|
1364
|
+
break;
|
|
1365
|
+
case Null:
|
|
1366
|
+
default:
|
|
1367
|
+
output.add(null);
|
|
1368
|
+
break;
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1372
|
+
return output;
|
|
1373
|
+
}
|
|
1374
|
+
|
|
1375
|
+
static final class ParsedPipelineRequest {
|
|
1376
|
+
final ParsedPipelineSource source;
|
|
1377
|
+
final List<ParsedPipelineStage> stages;
|
|
1378
|
+
final ParsedPipelineExecuteOptions options;
|
|
1379
|
+
|
|
1380
|
+
ParsedPipelineRequest(
|
|
1381
|
+
ParsedPipelineSource source,
|
|
1382
|
+
List<ParsedPipelineStage> stages,
|
|
1383
|
+
ParsedPipelineExecuteOptions options) {
|
|
1384
|
+
this.source = source;
|
|
1385
|
+
this.stages = stages;
|
|
1386
|
+
this.options = options;
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
|
|
1390
|
+
static final class ParsedPipelineSource {
|
|
1391
|
+
final String sourceType;
|
|
1392
|
+
final String path;
|
|
1393
|
+
final String collectionId;
|
|
1394
|
+
final String[] documents;
|
|
1395
|
+
final String queryType;
|
|
1396
|
+
final List<Object> filters;
|
|
1397
|
+
final List<Object> orders;
|
|
1398
|
+
final Map<String, Object> options;
|
|
1399
|
+
final Map<String, Object> rawOptions;
|
|
1400
|
+
|
|
1401
|
+
private ParsedPipelineSource(
|
|
1402
|
+
String sourceType,
|
|
1403
|
+
String path,
|
|
1404
|
+
String collectionId,
|
|
1405
|
+
String[] documents,
|
|
1406
|
+
String queryType,
|
|
1407
|
+
List<Object> filters,
|
|
1408
|
+
List<Object> orders,
|
|
1409
|
+
Map<String, Object> options,
|
|
1410
|
+
Map<String, Object> rawOptions) {
|
|
1411
|
+
this.sourceType = sourceType;
|
|
1412
|
+
this.path = path;
|
|
1413
|
+
this.collectionId = collectionId;
|
|
1414
|
+
this.documents = documents;
|
|
1415
|
+
this.queryType = queryType;
|
|
1416
|
+
this.filters = filters;
|
|
1417
|
+
this.orders = orders;
|
|
1418
|
+
this.options = options;
|
|
1419
|
+
this.rawOptions = rawOptions;
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
static ParsedPipelineSource collection(String path, Map<String, Object> rawOptions) {
|
|
1423
|
+
return new ParsedPipelineSource(
|
|
1424
|
+
"collection", path, null, null, null, null, null, null, rawOptions);
|
|
1425
|
+
}
|
|
1426
|
+
|
|
1427
|
+
static ParsedPipelineSource collectionGroup(
|
|
1428
|
+
String collectionId, Map<String, Object> rawOptions) {
|
|
1429
|
+
return new ParsedPipelineSource(
|
|
1430
|
+
"collectionGroup", null, collectionId, null, null, null, null, null, rawOptions);
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
static ParsedPipelineSource database(Map<String, Object> rawOptions) {
|
|
1434
|
+
return new ParsedPipelineSource(
|
|
1435
|
+
"database", null, null, null, null, null, null, null, rawOptions);
|
|
1436
|
+
}
|
|
1437
|
+
|
|
1438
|
+
static ParsedPipelineSource documents(String[] documents) {
|
|
1439
|
+
return new ParsedPipelineSource(
|
|
1440
|
+
"documents", null, null, documents, null, null, null, null, null);
|
|
1441
|
+
}
|
|
1442
|
+
|
|
1443
|
+
static ParsedPipelineSource query(
|
|
1444
|
+
String path,
|
|
1445
|
+
String queryType,
|
|
1446
|
+
List<Object> filters,
|
|
1447
|
+
List<Object> orders,
|
|
1448
|
+
Map<String, Object> options) {
|
|
1449
|
+
return new ParsedPipelineSource(
|
|
1450
|
+
"query", path, null, null, queryType, filters, orders, options, null);
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1454
|
+
static class ParsedPipelineStage {
|
|
1455
|
+
final String stageName;
|
|
1456
|
+
|
|
1457
|
+
ParsedPipelineStage(String stageName) {
|
|
1458
|
+
this.stageName = stageName;
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1462
|
+
static final class ParsedWhereStage extends ParsedPipelineStage {
|
|
1463
|
+
final ParsedExpressionNode condition;
|
|
1464
|
+
|
|
1465
|
+
ParsedWhereStage(ParsedExpressionNode condition) {
|
|
1466
|
+
super("where");
|
|
1467
|
+
this.condition = condition;
|
|
1468
|
+
}
|
|
1469
|
+
}
|
|
1470
|
+
|
|
1471
|
+
static final class ParsedSelectStage extends ParsedPipelineStage {
|
|
1472
|
+
final List<ParsedSelectableNode> selections;
|
|
1473
|
+
|
|
1474
|
+
ParsedSelectStage(List<ParsedSelectableNode> selections) {
|
|
1475
|
+
super("select");
|
|
1476
|
+
this.selections = selections;
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
|
|
1480
|
+
static final class ParsedAddFieldsStage extends ParsedPipelineStage {
|
|
1481
|
+
final List<ParsedSelectableNode> fields;
|
|
1482
|
+
|
|
1483
|
+
ParsedAddFieldsStage(List<ParsedSelectableNode> fields) {
|
|
1484
|
+
super("addFields");
|
|
1485
|
+
this.fields = fields;
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
static final class ParsedRemoveFieldsStage extends ParsedPipelineStage {
|
|
1490
|
+
final List<Object> fields;
|
|
1491
|
+
|
|
1492
|
+
ParsedRemoveFieldsStage(List<Object> fields) {
|
|
1493
|
+
super("removeFields");
|
|
1494
|
+
this.fields = fields;
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
|
|
1498
|
+
static final class ParsedSortStage extends ParsedPipelineStage {
|
|
1499
|
+
final List<ParsedOrderingNode> orderings;
|
|
1500
|
+
|
|
1501
|
+
ParsedSortStage(List<ParsedOrderingNode> orderings) {
|
|
1502
|
+
super("sort");
|
|
1503
|
+
this.orderings = orderings;
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1507
|
+
static final class ParsedLimitStage extends ParsedPipelineStage {
|
|
1508
|
+
final Object limit;
|
|
1509
|
+
|
|
1510
|
+
ParsedLimitStage(Object limit) {
|
|
1511
|
+
super("limit");
|
|
1512
|
+
this.limit = limit;
|
|
1513
|
+
}
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1516
|
+
static final class ParsedOffsetStage extends ParsedPipelineStage {
|
|
1517
|
+
final Object offset;
|
|
1518
|
+
|
|
1519
|
+
ParsedOffsetStage(Object offset) {
|
|
1520
|
+
super("offset");
|
|
1521
|
+
this.offset = offset;
|
|
1522
|
+
}
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1525
|
+
static final class ParsedAggregateStage extends ParsedPipelineStage {
|
|
1526
|
+
final List<ParsedAggregateNode> accumulators;
|
|
1527
|
+
final List<ParsedSelectableNode> groups;
|
|
1528
|
+
|
|
1529
|
+
ParsedAggregateStage(
|
|
1530
|
+
List<ParsedAggregateNode> accumulators, List<ParsedSelectableNode> groups) {
|
|
1531
|
+
super("aggregate");
|
|
1532
|
+
this.accumulators = accumulators;
|
|
1533
|
+
this.groups = groups;
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1536
|
+
|
|
1537
|
+
static final class ParsedDistinctStage extends ParsedPipelineStage {
|
|
1538
|
+
final List<ParsedSelectableNode> groups;
|
|
1539
|
+
|
|
1540
|
+
ParsedDistinctStage(List<ParsedSelectableNode> groups) {
|
|
1541
|
+
super("distinct");
|
|
1542
|
+
this.groups = groups;
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
|
|
1546
|
+
static final class ParsedFindNearestStage extends ParsedPipelineStage {
|
|
1547
|
+
final Object field;
|
|
1548
|
+
final Object vectorValue;
|
|
1549
|
+
final String distanceMeasure;
|
|
1550
|
+
final Object limit;
|
|
1551
|
+
final String distanceField;
|
|
1552
|
+
|
|
1553
|
+
ParsedFindNearestStage(
|
|
1554
|
+
Object field,
|
|
1555
|
+
Object vectorValue,
|
|
1556
|
+
String distanceMeasure,
|
|
1557
|
+
Object limit,
|
|
1558
|
+
String distanceField) {
|
|
1559
|
+
super("findNearest");
|
|
1560
|
+
this.field = field;
|
|
1561
|
+
this.vectorValue = vectorValue;
|
|
1562
|
+
this.distanceMeasure = distanceMeasure;
|
|
1563
|
+
this.limit = limit;
|
|
1564
|
+
this.distanceField = distanceField;
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1567
|
+
|
|
1568
|
+
static final class ParsedReplaceWithStage extends ParsedPipelineStage {
|
|
1569
|
+
final ParsedExpressionNode map;
|
|
1570
|
+
|
|
1571
|
+
ParsedReplaceWithStage(ParsedExpressionNode map) {
|
|
1572
|
+
super("replaceWith");
|
|
1573
|
+
this.map = map;
|
|
1574
|
+
}
|
|
1575
|
+
}
|
|
1576
|
+
|
|
1577
|
+
static final class ParsedSampleStage extends ParsedPipelineStage {
|
|
1578
|
+
final Object documents;
|
|
1579
|
+
final Object percentage;
|
|
1580
|
+
|
|
1581
|
+
ParsedSampleStage(Object documents, Object percentage) {
|
|
1582
|
+
super("sample");
|
|
1583
|
+
this.documents = documents;
|
|
1584
|
+
this.percentage = percentage;
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1587
|
+
|
|
1588
|
+
static final class ParsedUnionStage extends ParsedPipelineStage {
|
|
1589
|
+
final ParsedPipelineRequest other;
|
|
1590
|
+
|
|
1591
|
+
ParsedUnionStage(ParsedPipelineRequest other) {
|
|
1592
|
+
super("union");
|
|
1593
|
+
this.other = other;
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1597
|
+
static final class ParsedUnnestStage extends ParsedPipelineStage {
|
|
1598
|
+
final ParsedSelectableNode selectable;
|
|
1599
|
+
final String indexField;
|
|
1600
|
+
|
|
1601
|
+
ParsedUnnestStage(ParsedSelectableNode selectable, String indexField) {
|
|
1602
|
+
super("unnest");
|
|
1603
|
+
this.selectable = selectable;
|
|
1604
|
+
this.indexField = indexField;
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1607
|
+
|
|
1608
|
+
static final class ParsedRawStage extends ParsedPipelineStage {
|
|
1609
|
+
final String name;
|
|
1610
|
+
final Object params;
|
|
1611
|
+
final Map<String, Object> options;
|
|
1612
|
+
|
|
1613
|
+
ParsedRawStage(String name, Object params, Map<String, Object> options) {
|
|
1614
|
+
super("rawStage");
|
|
1615
|
+
this.name = name;
|
|
1616
|
+
this.params = params;
|
|
1617
|
+
this.options = options;
|
|
1618
|
+
}
|
|
1619
|
+
}
|
|
1620
|
+
|
|
1621
|
+
abstract static class ParsedExpressionNode {}
|
|
1622
|
+
|
|
1623
|
+
static final class ParsedFieldExpressionNode extends ParsedExpressionNode {
|
|
1624
|
+
final String path;
|
|
1625
|
+
|
|
1626
|
+
ParsedFieldExpressionNode(String path) {
|
|
1627
|
+
this.path = path;
|
|
1628
|
+
}
|
|
1629
|
+
}
|
|
1630
|
+
|
|
1631
|
+
static final class ParsedConstantExpressionNode extends ParsedExpressionNode {
|
|
1632
|
+
final ParsedValueNode value;
|
|
1633
|
+
|
|
1634
|
+
ParsedConstantExpressionNode(ParsedValueNode value) {
|
|
1635
|
+
this.value = value;
|
|
1636
|
+
}
|
|
1637
|
+
}
|
|
1638
|
+
|
|
1639
|
+
static final class ParsedFunctionExpressionNode extends ParsedExpressionNode {
|
|
1640
|
+
final String name;
|
|
1641
|
+
final List<ParsedValueNode> args;
|
|
1642
|
+
|
|
1643
|
+
ParsedFunctionExpressionNode(String name, List<ParsedValueNode> args) {
|
|
1644
|
+
this.name = name;
|
|
1645
|
+
this.args = args;
|
|
1646
|
+
}
|
|
1647
|
+
}
|
|
1648
|
+
|
|
1649
|
+
abstract static class ParsedValueNode {}
|
|
1650
|
+
|
|
1651
|
+
static final class ParsedPrimitiveValueNode extends ParsedValueNode {
|
|
1652
|
+
final Object value;
|
|
1653
|
+
|
|
1654
|
+
ParsedPrimitiveValueNode(Object value) {
|
|
1655
|
+
this.value = value;
|
|
1656
|
+
}
|
|
1657
|
+
}
|
|
1658
|
+
|
|
1659
|
+
static final class ParsedListValueNode extends ParsedValueNode {
|
|
1660
|
+
final List<ParsedValueNode> values;
|
|
1661
|
+
|
|
1662
|
+
ParsedListValueNode(List<ParsedValueNode> values) {
|
|
1663
|
+
this.values = values;
|
|
1664
|
+
}
|
|
1665
|
+
}
|
|
1666
|
+
|
|
1667
|
+
static final class ParsedMapValueNode extends ParsedValueNode {
|
|
1668
|
+
final Map<String, ParsedValueNode> values;
|
|
1669
|
+
|
|
1670
|
+
ParsedMapValueNode(Map<String, ParsedValueNode> values) {
|
|
1671
|
+
this.values = values;
|
|
1672
|
+
}
|
|
1673
|
+
}
|
|
1674
|
+
|
|
1675
|
+
static final class ParsedExpressionValueNode extends ParsedValueNode {
|
|
1676
|
+
final ParsedExpressionNode expression;
|
|
1677
|
+
|
|
1678
|
+
ParsedExpressionValueNode(ParsedExpressionNode expression) {
|
|
1679
|
+
this.expression = expression;
|
|
1680
|
+
}
|
|
1681
|
+
}
|
|
1682
|
+
|
|
1683
|
+
static final class ParsedSelectableNode {
|
|
1684
|
+
final ParsedExpressionNode expression;
|
|
1685
|
+
final String alias;
|
|
1686
|
+
final boolean isFlatFieldAlias;
|
|
1687
|
+
|
|
1688
|
+
ParsedSelectableNode(ParsedExpressionNode expression, String alias, boolean isFlatFieldAlias) {
|
|
1689
|
+
this.expression = expression;
|
|
1690
|
+
this.alias = alias;
|
|
1691
|
+
this.isFlatFieldAlias = isFlatFieldAlias;
|
|
1692
|
+
}
|
|
1693
|
+
}
|
|
1694
|
+
|
|
1695
|
+
static final class ParsedOrderingNode {
|
|
1696
|
+
final ParsedExpressionNode expression;
|
|
1697
|
+
final boolean descending;
|
|
1698
|
+
final boolean fieldShortcut;
|
|
1699
|
+
|
|
1700
|
+
ParsedOrderingNode(ParsedExpressionNode expression, boolean descending, boolean fieldShortcut) {
|
|
1701
|
+
this.expression = expression;
|
|
1702
|
+
this.descending = descending;
|
|
1703
|
+
this.fieldShortcut = fieldShortcut;
|
|
1704
|
+
}
|
|
1705
|
+
}
|
|
1706
|
+
|
|
1707
|
+
static final class ParsedAggregateNode {
|
|
1708
|
+
final String kind;
|
|
1709
|
+
final String alias;
|
|
1710
|
+
final ParsedValueNode primaryValue;
|
|
1711
|
+
final List<ParsedValueNode> args;
|
|
1712
|
+
|
|
1713
|
+
ParsedAggregateNode(
|
|
1714
|
+
String kind, String alias, ParsedValueNode primaryValue, List<ParsedValueNode> args) {
|
|
1715
|
+
this.kind = kind;
|
|
1716
|
+
this.alias = alias;
|
|
1717
|
+
this.primaryValue = primaryValue;
|
|
1718
|
+
this.args = args;
|
|
1719
|
+
}
|
|
1720
|
+
}
|
|
1721
|
+
|
|
1722
|
+
static final class ParsedPipelineExecuteOptions {
|
|
1723
|
+
final String indexMode;
|
|
1724
|
+
final Map<String, Object> rawOptions;
|
|
1725
|
+
|
|
1726
|
+
ParsedPipelineExecuteOptions(String indexMode, Map<String, Object> rawOptions) {
|
|
1727
|
+
this.indexMode = indexMode;
|
|
1728
|
+
this.rawOptions = rawOptions;
|
|
1729
|
+
}
|
|
1730
|
+
|
|
1731
|
+
boolean isEmpty() {
|
|
1732
|
+
return indexMode == null && rawOptions == null;
|
|
1733
|
+
}
|
|
1734
|
+
}
|
|
1735
|
+
}
|