Skip to content

Commit dd2e9bd

Browse files
committed
add named options to CollectionSource and CollectionGroupSource
1 parent ea780f8 commit dd2e9bd

File tree

3 files changed

+94
-40
lines changed

3 files changed

+94
-40
lines changed

firebase-firestore/src/main/java/com/google/firebase/firestore/Pipeline.kt

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import com.google.common.collect.ImmutableList
2121
import com.google.firebase.Timestamp
2222
import com.google.firebase.firestore.model.DocumentKey
2323
import com.google.firebase.firestore.model.Values
24-
import com.google.firebase.firestore.pipeline.AbstractOptions
2524
import com.google.firebase.firestore.pipeline.AddFieldsStage
2625
import com.google.firebase.firestore.pipeline.AggregateFunction
2726
import com.google.firebase.firestore.pipeline.AggregateStage
@@ -39,7 +38,6 @@ import com.google.firebase.firestore.pipeline.FindNearestStage
3938
import com.google.firebase.firestore.pipeline.FunctionExpr
4039
import com.google.firebase.firestore.pipeline.GenericArg
4140
import com.google.firebase.firestore.pipeline.GenericStage
42-
import com.google.firebase.firestore.pipeline.InternalOptions
4341
import com.google.firebase.firestore.pipeline.LimitStage
4442
import com.google.firebase.firestore.pipeline.OffsetStage
4543
import com.google.firebase.firestore.pipeline.Ordering
@@ -54,7 +52,6 @@ import com.google.firebase.firestore.pipeline.Stage
5452
import com.google.firebase.firestore.pipeline.UnionStage
5553
import com.google.firebase.firestore.pipeline.UnnestStage
5654
import com.google.firebase.firestore.pipeline.WhereStage
57-
import com.google.firebase.firestore.util.Preconditions
5855
import com.google.firestore.v1.ExecutePipelineRequest
5956
import com.google.firestore.v1.StructuredPipeline
6057
import com.google.firestore.v1.Value
@@ -614,7 +611,7 @@ class PipelineSource internal constructor(private val firestore: FirebaseFiresto
614611
* Convert the given Query into an equivalent Pipeline.
615612
*
616613
* @param query A Query to be converted into a Pipeline.
617-
* @return Pipeline that is equivalent to [query]
614+
* @return A new [Pipeline] object that is equivalent to [query]
618615
* @throws [IllegalArgumentException] Thrown if the [query] provided targets a different project
619616
* or database than the pipeline.
620617
*/
@@ -629,7 +626,7 @@ class PipelineSource internal constructor(private val firestore: FirebaseFiresto
629626
* Convert the given Aggregate Query into an equivalent Pipeline.
630627
*
631628
* @param aggregateQuery An Aggregate Query to be converted into a Pipeline.
632-
* @return Pipeline that is equivalent to [aggregateQuery]
629+
* @return A new [Pipeline] object that is equivalent to [aggregateQuery]
633630
* @throws [IllegalArgumentException] Thrown if the [aggregateQuery] provided targets a different
634631
* project or database than the pipeline.
635632
*/
@@ -646,46 +643,50 @@ class PipelineSource internal constructor(private val firestore: FirebaseFiresto
646643
* Set the pipeline's source to the collection specified by the given path.
647644
*
648645
* @param path A path to a collection that will be the source of this pipeline.
649-
* @return Pipeline with documents from target collection.
646+
* @return A new [Pipeline] object with documents from target collection.
650647
*/
651-
fun collection(path: String): Pipeline =
652-
// Validate path by converting to CollectionReference
653-
collection(firestore.collection(path))
648+
fun collection(path: String): Pipeline = collection(CollectionSource.of(path))
654649

655650
/**
656-
* Set the pipeline's source to the collection specified by the given CollectionReference.
651+
* Set the pipeline's source to the collection specified by the given [CollectionReference].
657652
*
658-
* @param ref A CollectionReference for a collection that will be the source of this pipeline.
659-
* @return Pipeline with documents from target collection.
653+
* @param ref A [CollectionReference] for a collection that will be the source of this pipeline.
654+
* @return A new [Pipeline] object with documents from target collection.
660655
* @throws [IllegalArgumentException] Thrown if the [ref] provided targets a different project or
661656
* database than the pipeline.
662657
*/
663-
fun collection(ref: CollectionReference): Pipeline {
664-
if (ref.firestore.databaseId != firestore.databaseId) {
665-
throw IllegalArgumentException(
666-
"Provided collection reference is from a different Firestore instance."
667-
)
658+
fun collection(ref: CollectionReference): Pipeline = collection(CollectionSource.of(ref))
659+
660+
/**
661+
* Set the pipeline's source to the collection specified by CollectionSource.
662+
*
663+
* @param stage A [CollectionSource] that will be the source of this pipeline.
664+
* @return Pipeline with documents from target collection.
665+
* @throws [IllegalArgumentException] Thrown if the [stage] provided targets a different project
666+
* or database than the pipeline.
667+
*/
668+
fun collection(stage: CollectionSource): Pipeline {
669+
if (stage.firestore != null && stage.firestore.databaseId != firestore.databaseId) {
670+
throw IllegalArgumentException("Provided collection is from a different Firestore instance.")
668671
}
669-
return Pipeline(firestore, firestore.userDataReader, CollectionSource(ref.path))
672+
return Pipeline(firestore, firestore.userDataReader, stage)
670673
}
671674

672675
/**
673676
* Set the pipeline's source to the collection group with the given id.
674677
*
675-
* @param collectionid The id of a collection group that will be the source of this pipeline.
678+
* @param collectionId The id of a collection group that will be the source of this pipeline.
676679
*/
677-
fun collectionGroup(collectionId: String): Pipeline {
678-
Preconditions.checkNotNull(collectionId, "Provided collection ID must not be null.")
679-
require(!collectionId.contains("/")) {
680-
"Invalid collectionId '$collectionId'. Collection IDs must not contain '/'."
681-
}
682-
return Pipeline(firestore, firestore.userDataReader, CollectionGroupSource(collectionId))
683-
}
680+
fun collectionGroup(collectionId: String): Pipeline =
681+
pipeline(CollectionGroupSource.of((collectionId)))
682+
683+
fun pipeline(stage: CollectionGroupSource): Pipeline =
684+
Pipeline(firestore, firestore.userDataReader, stage)
684685

685686
/**
686687
* Set the pipeline's source to be all documents in this database.
687688
*
688-
* @return Pipeline with all documents in this database.
689+
* @return A new [Pipeline] object with all documents in this database.
689690
*/
690691
fun database(): Pipeline = Pipeline(firestore, firestore.userDataReader, DatabaseSource())
691692

@@ -694,7 +695,7 @@ class PipelineSource internal constructor(private val firestore: FirebaseFiresto
694695
*
695696
* @param documents Paths specifying the individual documents that will be the source of this
696697
* pipeline.
697-
* @return Pipeline with [documents].
698+
* @return A new [Pipeline] object with [documents].
698699
*/
699700
fun documents(vararg documents: String): Pipeline =
700701
// Validate document path by converting to DocumentReference

firebase-firestore/src/main/java/com/google/firebase/firestore/core/Query.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import com.google.firebase.firestore.pipeline.Expr;
3636
import com.google.firebase.firestore.pipeline.Field;
3737
import com.google.firebase.firestore.pipeline.FunctionExpr;
38+
import com.google.firebase.firestore.pipeline.InternalOptions;
3839
import com.google.firebase.firestore.pipeline.Ordering;
3940
import com.google.firebase.firestore.pipeline.Stage;
4041
import com.google.firestore.v1.Value;
@@ -521,7 +522,7 @@ private synchronized Target toTarget(List<OrderBy> orderBys) {
521522

522523
@NonNull
523524
public Pipeline toPipeline(FirebaseFirestore firestore, UserDataReader userDataReader) {
524-
Pipeline p = new Pipeline(firestore, userDataReader, pipelineSource());
525+
Pipeline p = new Pipeline(firestore, userDataReader, pipelineSource(firestore));
525526

526527
// Filters
527528
for (Filter filter : filters) {
@@ -598,13 +599,13 @@ private static BooleanExpr whereConditionsFromCursor(
598599
}
599600

600601
@NonNull
601-
private Stage pipelineSource() {
602+
private Stage<?> pipelineSource(FirebaseFirestore firestore) {
602603
if (isDocumentQuery()) {
603604
return new DocumentsSource(path.canonicalString());
604605
} else if (isCollectionGroupQuery()) {
605-
return new CollectionGroupSource(collectionGroup);
606+
return CollectionGroupSource.of(collectionGroup);
606607
} else {
607-
return new CollectionSource(path.canonicalString());
608+
return new CollectionSource(path.canonicalString(), firestore, InternalOptions.EMPTY);
608609
}
609610
}
610611

firebase-firestore/src/main/java/com/google/firebase/firestore/pipeline/stage.kt

Lines changed: 60 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,16 @@
1414

1515
package com.google.firebase.firestore.pipeline
1616

17+
import com.google.firebase.firestore.CollectionReference
18+
import com.google.firebase.firestore.FirebaseFirestore
1719
import com.google.firebase.firestore.UserDataReader
1820
import com.google.firebase.firestore.VectorValue
21+
import com.google.firebase.firestore.model.ResourcePath
1922
import com.google.firebase.firestore.model.Values
2023
import com.google.firebase.firestore.model.Values.encodeValue
2124
import com.google.firebase.firestore.pipeline.Expr.Companion.constant
2225
import com.google.firebase.firestore.pipeline.Expr.Companion.field
26+
import com.google.firebase.firestore.util.Preconditions
2327
import com.google.firestore.v1.Pipeline
2428
import com.google.firestore.v1.Value
2529

@@ -93,7 +97,7 @@ internal constructor(protected val name: String, internal val options: InternalO
9397
* not implemented in the SDK version being used.
9498
*/
9599
class GenericStage
96-
internal constructor(
100+
private constructor(
97101
name: String,
98102
private val arguments: List<GenericArg>,
99103
options: InternalOptions = InternalOptions.EMPTY
@@ -168,24 +172,72 @@ internal constructor(options: InternalOptions = InternalOptions.EMPTY) :
168172
override fun args(userDataReader: UserDataReader): Sequence<Value> = emptySequence()
169173
}
170174

171-
internal class CollectionSource
172-
@JvmOverloads
173-
internal constructor(val path: String, options: InternalOptions = InternalOptions.EMPTY) :
175+
class CollectionSource
176+
internal constructor(
177+
private val path: String,
178+
// We validate [firestore.databaseId] when adding to pipeline.
179+
internal val firestore: FirebaseFirestore?,
180+
options: InternalOptions) :
174181
Stage<CollectionSource>("collection", options) {
175-
override fun self(options: InternalOptions): CollectionSource = CollectionSource(path, options)
182+
override fun self(options: InternalOptions): CollectionSource = CollectionSource(path, firestore, options)
176183
override fun args(userDataReader: UserDataReader): Sequence<Value> =
177184
sequenceOf(
178185
Value.newBuilder().setReferenceValue(if (path.startsWith("/")) path else "/" + path).build()
179186
)
187+
companion object {
188+
/**
189+
* Set the pipeline's source to the collection specified by the given path.
190+
*
191+
* @param path A path to a collection that will be the source of this pipeline.
192+
* @return Pipeline with documents from target collection.
193+
*/
194+
@JvmStatic
195+
fun of(path: String): CollectionSource {
196+
// Validate path by converting to ResourcePath
197+
val resourcePath = ResourcePath.fromString(path)
198+
return CollectionSource(resourcePath.canonicalString(), null, InternalOptions.EMPTY)
199+
}
200+
201+
/**
202+
* Set the pipeline's source to the collection specified by the given CollectionReference.
203+
*
204+
* @param ref A CollectionReference for a collection that will be the source of this pipeline.
205+
* @return Pipeline with documents from target collection.
206+
*/
207+
@JvmStatic
208+
fun of(ref: CollectionReference): CollectionSource {
209+
return CollectionSource(ref.path, ref.firestore, InternalOptions.EMPTY)
210+
}
211+
}
212+
213+
fun withForceIndex(value: String) = with("force_index", value)
180214
}
181215

182-
internal class CollectionGroupSource
183-
@JvmOverloads
184-
internal constructor(val collectionId: String, options: InternalOptions = InternalOptions.EMPTY) :
216+
class CollectionGroupSource
217+
private constructor(private val collectionId: String, options: InternalOptions) :
185218
Stage<CollectionGroupSource>("collection_group", options) {
186219
override fun self(options: InternalOptions) = CollectionGroupSource(collectionId, options)
187220
override fun args(userDataReader: UserDataReader): Sequence<Value> =
188221
sequenceOf(Value.newBuilder().setReferenceValue("").build(), encodeValue(collectionId))
222+
223+
companion object {
224+
225+
/**
226+
* Set the pipeline's source to the collection group with the given id.
227+
*
228+
* @param collectionId The id of a collection group that will be the source of this pipeline.
229+
*/
230+
@JvmStatic
231+
fun of(collectionId: String): CollectionGroupSource {
232+
Preconditions.checkNotNull(collectionId, "Provided collection ID must not be null.")
233+
require(!collectionId.contains("/")) {
234+
"Invalid collectionId '$collectionId'. Collection IDs must not contain '/'."
235+
}
236+
return CollectionGroupSource(collectionId, InternalOptions.EMPTY)
237+
}
238+
}
239+
240+
fun withForceIndex(value: String) = with("force_index", value)
189241
}
190242

191243
internal class DocumentsSource

0 commit comments

Comments
 (0)