diff --git a/.gitignore b/.gitignore index 02e9bdf0e21..5581f51dc17 100644 --- a/.gitignore +++ b/.gitignore @@ -68,3 +68,4 @@ driver-benchmarks/.factorypath # bin build directories **/bin +docs/superpowers/ diff --git a/driver-core/src/main/com/mongodb/client/model/vault/EncryptOptions.java b/driver-core/src/main/com/mongodb/client/model/vault/EncryptOptions.java index f509f8b3ea3..bdd2eeb5be6 100644 --- a/driver-core/src/main/com/mongodb/client/model/vault/EncryptOptions.java +++ b/driver-core/src/main/com/mongodb/client/model/vault/EncryptOptions.java @@ -34,6 +34,7 @@ public class EncryptOptions { private String queryType; private RangeOptions rangeOptions; private TextOptions textOptions; + private StringOptions stringOptions; /** * Construct an instance with the given algorithm. @@ -54,12 +55,12 @@ public EncryptOptions(final String algorithm) { *
The "TextPreview" algorithm is in preview and should be used for experimental workloads only. - * These features are unstable and their security is not guaranteed until released as Generally Available (GA). - * The GA version of these features may not be backwards compatible with the preview version.
+ *The "String" algorithm supports Queryable Encryption prefix, suffix, and substring string queries. + * Use the "String" algorithm with query types "prefix"/"suffix"/"substring" (server 9.0+) or the deprecated + * aliases "prefixPreview"/"suffixPreview"/"substringPreview" (server 8.2 to pre-9.0).
* * @return the encryption algorithm */ @@ -149,8 +150,12 @@ public Long getContentionFactor() { /** * The QueryType. * - *Currently, we support only "equality", "range", "prefixPreview", "suffixPreview" or "substringPreview" queryType.
- *It is an error to set queryType when the algorithm is not "Indexed", "Range" or "TextPreview".
+ *Currently, we support only "equality", "range", "prefix", "suffix", "substring", "prefixPreview", + * "suffixPreview" or "substringPreview" queryType.
+ *The "prefix", "suffix", "substring", "prefixPreview", "suffixPreview" and "substringPreview" query types are + * only valid with the "String" algorithm. "prefixPreview"/"suffixPreview"/"substringPreview" are deprecated + * aliases supported for servers 8.2 to pre-9.0; use "prefix"/"suffix"/"substring" on server 9.0+.
+ *It is an error to set queryType when the algorithm is not "Indexed", "Range" or "String".
* @param queryType the query type * @return this * @since 4.7 @@ -164,7 +169,7 @@ public EncryptOptions queryType(@Nullable final String queryType) { /** * Gets the QueryType. * - *Currently, we support only "equality" or "range" queryType.
+ *See {@link #queryType(String)} for the supported query types.
* @see #queryType(String) * @return the queryType or null * @since 4.7 @@ -205,13 +210,15 @@ public RangeOptions getRangeOptions() { /** * The TextOptions * - *It is an error to set TextOptions when the algorithm is not "TextPreview". + *
It is an error to set TextOptions when the algorithm is not "String". * @param textOptions the text options * @return this * @since 5.6 * @mongodb.server.release 8.2 * @mongodb.driver.manual /core/queryable-encryption/ queryable encryption + * @deprecated Use {@link #stringOptions(StringOptions)} instead. */ + @Deprecated @Alpha(Reason.SERVER) public EncryptOptions textOptions(@Nullable final TextOptions textOptions) { this.textOptions = textOptions; @@ -225,13 +232,43 @@ public EncryptOptions textOptions(@Nullable final TextOptions textOptions) { * @since 5.6 * @mongodb.server.release 8.2 * @mongodb.driver.manual /core/queryable-encryption/ queryable encryption + * @deprecated Use {@link #getStringOptions()} instead. */ + @Deprecated @Alpha(Reason.SERVER) @Nullable public TextOptions getTextOptions() { return textOptions; } + /** + * The StringOptions + * + *
It is an error to set StringOptions when the algorithm is not "String". + * @param stringOptions the string options + * @return this + * @since 5.9 + * @mongodb.server.release 8.2 + * @mongodb.driver.manual /core/queryable-encryption/ queryable encryption + */ + public EncryptOptions stringOptions(@Nullable final StringOptions stringOptions) { + this.stringOptions = stringOptions; + return this; + } + + /** + * Gets the StringOptions + * @see #stringOptions(StringOptions) + * @return the string options or null if not set + * @since 5.9 + * @mongodb.server.release 8.2 + * @mongodb.driver.manual /core/queryable-encryption/ queryable encryption + */ + @Nullable + public StringOptions getStringOptions() { + return stringOptions; + } + @Override public String toString() { return "EncryptOptions{" @@ -241,6 +278,8 @@ public String toString() { + ", contentionFactor=" + contentionFactor + ", queryType='" + queryType + '\'' + ", rangeOptions=" + rangeOptions + + ", textOptions=" + textOptions + + ", stringOptions=" + stringOptions + '}'; } } diff --git a/driver-core/src/main/com/mongodb/client/model/vault/StringOptions.java b/driver-core/src/main/com/mongodb/client/model/vault/StringOptions.java new file mode 100644 index 00000000000..5563f84fcce --- /dev/null +++ b/driver-core/src/main/com/mongodb/client/model/vault/StringOptions.java @@ -0,0 +1,192 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.mongodb.client.model.vault; + +import com.mongodb.lang.Nullable; +import org.bson.BsonDocument; + +/** + * String options for a Queryable Encryption field that supports string queries (prefix, suffix, and substring). + * + * @since 5.9 + * @mongodb.server.release 8.2 + * @mongodb.driver.manual /core/queryable-encryption/ queryable encryption + */ +public class StringOptions { + private boolean caseSensitive; + private boolean diacriticSensitive; + @Nullable + private BsonDocument prefixOptions; + @Nullable + private BsonDocument suffixOptions; + @Nullable + private BsonDocument substringOptions; + + /** + * Construct a new instance + */ + public StringOptions() { + } + + /** + * @return true if string indexes for this field are case sensitive. + */ + public boolean getCaseSensitive() { + return caseSensitive; + } + + /** + * Set case sensitivity + * + * @param caseSensitive true if string indexes are case sensitive + * @return this + */ + public StringOptions caseSensitive(final boolean caseSensitive) { + this.caseSensitive = caseSensitive; + return this; + } + + /** + * @return true if string indexes are diacritic sensitive + */ + public boolean getDiacriticSensitive() { + return diacriticSensitive; + } + + /** + * Set diacritic sensitivity + * + * @param diacriticSensitive true if string indexes are diacritic sensitive + * @return this + */ + public StringOptions diacriticSensitive(final boolean diacriticSensitive) { + this.diacriticSensitive = diacriticSensitive; + return this; + } + + /** + * Set the prefix options. + * + *
Expected to be a {@link BsonDocument} in the format of:
+ * + *
+ * {@code
+ * {
+ * // strMinQueryLength is the minimum allowed query length. Querying with a shorter string will error.
+ * strMinQueryLength: BsonInt32,
+ * // strMaxQueryLength is the maximum allowed query length. Querying with a longer string will error.
+ * strMaxQueryLength: BsonInt32
+ * }
+ * }
+ *
+ *
+ * @param prefixOptions the prefix options or null
+ * @return this
+ */
+ public StringOptions prefixOptions(@Nullable final BsonDocument prefixOptions) {
+ this.prefixOptions = prefixOptions;
+ return this;
+ }
+
+ /**
+ * @see #prefixOptions(BsonDocument)
+ * @return the prefix options document or null
+ */
+ @Nullable
+ public BsonDocument getPrefixOptions() {
+ return prefixOptions;
+ }
+
+ /**
+ * Set the suffix options.
+ *
+ * Expected to be a {@link BsonDocument} in the format of:
+ * + *
+ * {@code
+ * {
+ * // strMinQueryLength is the minimum allowed query length. Querying with a shorter string will error.
+ * strMinQueryLength: BsonInt32,
+ * // strMaxQueryLength is the maximum allowed query length. Querying with a longer string will error.
+ * strMaxQueryLength: BsonInt32
+ * }
+ * }
+ *
+ *
+ * @param suffixOptions the suffix options or null
+ * @return this
+ */
+ public StringOptions suffixOptions(@Nullable final BsonDocument suffixOptions) {
+ this.suffixOptions = suffixOptions;
+ return this;
+ }
+
+ /**
+ * @see #suffixOptions(BsonDocument)
+ * @return the suffix options document or null
+ */
+ @Nullable
+ public BsonDocument getSuffixOptions() {
+ return suffixOptions;
+ }
+
+ /**
+ * Set the substring options.
+ *
+ * Expected to be a {@link BsonDocument} in the format of:
+ * + *
+ * {@code
+ * {
+ * // strMaxLength is the maximum allowed length to insert. Inserting longer strings will error.
+ * strMaxLength: BsonInt32,
+ * // strMinQueryLength is the minimum allowed query length. Querying with a shorter string will error.
+ * strMinQueryLength: BsonInt32,
+ * // strMaxQueryLength is the maximum allowed query length. Querying with a longer string will error.
+ * strMaxQueryLength: BsonInt32
+ * }
+ * }
+ *
+ *
+ * @param substringOptions the substring options or null
+ * @return this
+ */
+ public StringOptions substringOptions(@Nullable final BsonDocument substringOptions) {
+ this.substringOptions = substringOptions;
+ return this;
+ }
+
+ /**
+ * @see #substringOptions(BsonDocument)
+ * @return the substring options document or null
+ */
+ @Nullable
+ public BsonDocument getSubstringOptions() {
+ return substringOptions;
+ }
+
+ @Override
+ public String toString() {
+ return "StringOptions{"
+ + "caseSensitive=" + caseSensitive
+ + ", diacriticSensitive=" + diacriticSensitive
+ + ", prefixOptions=" + prefixOptions
+ + ", suffixOptions=" + suffixOptions
+ + ", substringOptions=" + substringOptions
+ + '}';
+ }
+}
diff --git a/driver-core/src/main/com/mongodb/client/model/vault/TextOptions.java b/driver-core/src/main/com/mongodb/client/model/vault/TextOptions.java
index 34dcd0d806d..2520cbc9bf4 100644
--- a/driver-core/src/main/com/mongodb/client/model/vault/TextOptions.java
+++ b/driver-core/src/main/com/mongodb/client/model/vault/TextOptions.java
@@ -29,11 +29,13 @@
* @since 5.6
* @mongodb.server.release 8.2
* @mongodb.driver.manual /core/queryable-encryption/ queryable encryption
+ * @deprecated Use {@link StringOptions} instead.
*/
+@Deprecated
@Alpha(Reason.SERVER)
public class TextOptions {
- private Boolean caseSensitive;
- private Boolean diacriticSensitive;
+ private boolean caseSensitive;
+ private boolean diacriticSensitive;
@Nullable
private BsonDocument prefixOptions;
@Nullable
@@ -184,4 +186,14 @@ public BsonDocument getSubstringOptions() {
return substringOptions;
}
+ @Override
+ public String toString() {
+ return "TextOptions{"
+ + "caseSensitive=" + caseSensitive
+ + ", diacriticSensitive=" + diacriticSensitive
+ + ", prefixOptions=" + prefixOptions
+ + ", suffixOptions=" + suffixOptions
+ + ", substringOptions=" + substringOptions
+ + '}';
+ }
}
diff --git a/driver-core/src/main/com/mongodb/internal/client/vault/EncryptOptionsHelper.java b/driver-core/src/main/com/mongodb/internal/client/vault/EncryptOptionsHelper.java
index 2b472668d98..7a8dab950f4 100644
--- a/driver-core/src/main/com/mongodb/internal/client/vault/EncryptOptionsHelper.java
+++ b/driver-core/src/main/com/mongodb/internal/client/vault/EncryptOptionsHelper.java
@@ -17,8 +17,10 @@
import com.mongodb.client.model.vault.EncryptOptions;
import com.mongodb.client.model.vault.RangeOptions;
+import com.mongodb.client.model.vault.StringOptions;
import com.mongodb.client.model.vault.TextOptions;
import com.mongodb.internal.crypt.capi.MongoExplicitEncryptOptions;
+import com.mongodb.lang.Nullable;
import org.bson.BsonBoolean;
import org.bson.BsonDocument;
import org.bson.BsonInt32;
@@ -73,31 +75,51 @@ public static MongoExplicitEncryptOptions asMongoExplicitEncryptOptions(final En
encryptOptionsBuilder.rangeOptions(rangeOptionsBsonDocument);
}
- TextOptions textOptions = options.getTextOptions();
- if (textOptions != null) {
- BsonDocument textOptionsDocument = new BsonDocument();
- textOptionsDocument.put("caseSensitive", BsonBoolean.valueOf(textOptions.getCaseSensitive()));
- textOptionsDocument.put("diacriticSensitive", BsonBoolean.valueOf(textOptions.getDiacriticSensitive()));
+ StringOptions stringOptions = resolveStringOptions(options);
+ if (stringOptions != null) {
+ BsonDocument stringOptionsDocument = new BsonDocument();
+ stringOptionsDocument.put("caseSensitive", BsonBoolean.valueOf(stringOptions.getCaseSensitive()));
+ stringOptionsDocument.put("diacriticSensitive", BsonBoolean.valueOf(stringOptions.getDiacriticSensitive()));
- BsonDocument substringOptions = textOptions.getSubstringOptions();
+ BsonDocument substringOptions = stringOptions.getSubstringOptions();
if (substringOptions != null) {
- textOptionsDocument.put("substring", substringOptions);
+ stringOptionsDocument.put("substring", substringOptions);
}
- BsonDocument prefixOptions = textOptions.getPrefixOptions();
+ BsonDocument prefixOptions = stringOptions.getPrefixOptions();
if (prefixOptions != null) {
- textOptionsDocument.put("prefix", prefixOptions);
+ stringOptionsDocument.put("prefix", prefixOptions);
}
- BsonDocument suffixOptions = textOptions.getSuffixOptions();
+ BsonDocument suffixOptions = stringOptions.getSuffixOptions();
if (suffixOptions != null) {
- textOptionsDocument.put("suffix", suffixOptions);
+ stringOptionsDocument.put("suffix", suffixOptions);
}
- encryptOptionsBuilder.textOptions(textOptionsDocument);
+ encryptOptionsBuilder.textOptions(stringOptionsDocument);
}
return encryptOptionsBuilder.build();
}
+
+ @SuppressWarnings("deprecation")
+ @Nullable
+ private static StringOptions resolveStringOptions(final EncryptOptions options) {
+ StringOptions stringOptions = options.getStringOptions();
+ if (stringOptions != null) {
+ return stringOptions;
+ }
+ TextOptions textOptions = options.getTextOptions();
+ if (textOptions == null) {
+ return null;
+ }
+ return new StringOptions()
+ .caseSensitive(textOptions.getCaseSensitive())
+ .diacriticSensitive(textOptions.getDiacriticSensitive())
+ .prefixOptions(textOptions.getPrefixOptions())
+ .suffixOptions(textOptions.getSuffixOptions())
+ .substringOptions(textOptions.getSubstringOptions());
+ }
+
private EncryptOptionsHelper() {
}
}
diff --git a/driver-core/src/test/unit/com/mongodb/client/model/vault/EncryptOptionsTest.java b/driver-core/src/test/unit/com/mongodb/client/model/vault/EncryptOptionsTest.java
new file mode 100644
index 00000000000..2859d728e99
--- /dev/null
+++ b/driver-core/src/test/unit/com/mongodb/client/model/vault/EncryptOptionsTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2008-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.mongodb.client.model.vault;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class EncryptOptionsTest {
+
+ @Test
+ void shouldStoreStringOptions() {
+ StringOptions stringOptions = new StringOptions().caseSensitive(true);
+ EncryptOptions options = new EncryptOptions("String").stringOptions(stringOptions);
+ assertSame(stringOptions, options.getStringOptions());
+ assertNull(options.getTextOptions());
+ }
+
+ @Test
+ @SuppressWarnings("deprecation")
+ void shouldStoreDeprecatedTextOptionsIndependently() {
+ TextOptions textOptions = new TextOptions().caseSensitive(true);
+ EncryptOptions options = new EncryptOptions("String").textOptions(textOptions);
+ assertSame(textOptions, options.getTextOptions());
+ assertNull(options.getStringOptions());
+ }
+
+ @Test
+ void toStringShouldIncludeStringOptions() {
+ EncryptOptions options = new EncryptOptions("String").stringOptions(new StringOptions());
+ assertTrue(options.toString().contains("stringOptions="));
+ }
+}
diff --git a/driver-core/src/test/unit/com/mongodb/client/model/vault/StringOptionsTest.java b/driver-core/src/test/unit/com/mongodb/client/model/vault/StringOptionsTest.java
new file mode 100644
index 00000000000..4568f1b53eb
--- /dev/null
+++ b/driver-core/src/test/unit/com/mongodb/client/model/vault/StringOptionsTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2008-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.mongodb.client.model.vault;
+
+import org.bson.BsonDocument;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class StringOptionsTest {
+
+ @Test
+ void shouldRoundTripAllProperties() {
+ BsonDocument prefix = BsonDocument.parse("{strMaxQueryLength: 10, strMinQueryLength: 2}");
+ BsonDocument suffix = BsonDocument.parse("{strMaxQueryLength: 10, strMinQueryLength: 2}");
+ BsonDocument substring = BsonDocument.parse("{strMaxLength: 10, strMaxQueryLength: 10, strMinQueryLength: 2}");
+
+ StringOptions options = new StringOptions()
+ .caseSensitive(true)
+ .diacriticSensitive(true)
+ .prefixOptions(prefix)
+ .suffixOptions(suffix)
+ .substringOptions(substring);
+
+ assertTrue(options.getCaseSensitive());
+ assertTrue(options.getDiacriticSensitive());
+ assertEquals(prefix, options.getPrefixOptions());
+ assertEquals(suffix, options.getSuffixOptions());
+ assertEquals(substring, options.getSubstringOptions());
+ }
+
+ @Test
+ void shouldDefaultOptionDocumentsToNull() {
+ StringOptions options = new StringOptions();
+ assertNull(options.getPrefixOptions());
+ assertNull(options.getSuffixOptions());
+ assertNull(options.getSubstringOptions());
+ }
+
+ @Test
+ void shouldDefaultBooleanFlagsToFalse() {
+ StringOptions options = new StringOptions();
+ assertFalse(options.getCaseSensitive());
+ assertFalse(options.getDiacriticSensitive());
+ }
+
+ @Test
+ void shouldIncludeAllFieldsInToString() {
+ String result = new StringOptions()
+ .caseSensitive(true)
+ .diacriticSensitive(false)
+ .prefixOptions(BsonDocument.parse("{strMaxQueryLength: 10, strMinQueryLength: 2}"))
+ .toString();
+
+ assertEquals("StringOptions{caseSensitive=true, diacriticSensitive=false, "
+ + "prefixOptions={\"strMaxQueryLength\": 10, \"strMinQueryLength\": 2}, "
+ + "suffixOptions=null, substringOptions=null}", result);
+ }
+}
diff --git a/driver-core/src/test/unit/com/mongodb/internal/client/vault/EncryptOptionsHelperTest.java b/driver-core/src/test/unit/com/mongodb/internal/client/vault/EncryptOptionsHelperTest.java
new file mode 100644
index 00000000000..3835b715ce4
--- /dev/null
+++ b/driver-core/src/test/unit/com/mongodb/internal/client/vault/EncryptOptionsHelperTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2008-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.mongodb.internal.client.vault;
+
+import com.mongodb.client.model.vault.EncryptOptions;
+import com.mongodb.client.model.vault.StringOptions;
+import com.mongodb.client.model.vault.TextOptions;
+import com.mongodb.internal.crypt.capi.MongoExplicitEncryptOptions;
+import org.bson.BsonDocument;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+class EncryptOptionsHelperTest {
+
+ @Test
+ void shouldMapStringOptionsToTextOptionsDocument() {
+ EncryptOptions options = new EncryptOptions("String").stringOptions(new StringOptions()
+ .caseSensitive(true)
+ .diacriticSensitive(false)
+ .prefixOptions(BsonDocument.parse("{strMaxQueryLength: 10, strMinQueryLength: 2}")));
+
+ MongoExplicitEncryptOptions result = EncryptOptionsHelper.asMongoExplicitEncryptOptions(options);
+
+ assertEquals(BsonDocument.parse("{caseSensitive: true, diacriticSensitive: false, "
+ + "prefix: {strMaxQueryLength: 10, strMinQueryLength: 2}}"),
+ result.getTextOptions());
+ }
+
+ @Test
+ @SuppressWarnings("deprecation")
+ void shouldFallBackToDeprecatedTextOptions() {
+ EncryptOptions options = new EncryptOptions("String").textOptions(new TextOptions()
+ .caseSensitive(true)
+ .diacriticSensitive(true)
+ .suffixOptions(BsonDocument.parse("{strMaxQueryLength: 10, strMinQueryLength: 2}")));
+
+ MongoExplicitEncryptOptions result = EncryptOptionsHelper.asMongoExplicitEncryptOptions(options);
+
+ assertEquals(BsonDocument.parse("{caseSensitive: true, diacriticSensitive: true, "
+ + "suffix: {strMaxQueryLength: 10, strMinQueryLength: 2}}"),
+ result.getTextOptions());
+ }
+
+ @Test
+ void shouldLeaveTextOptionsNullWhenNeitherSet() {
+ MongoExplicitEncryptOptions result = EncryptOptionsHelper.asMongoExplicitEncryptOptions(
+ new EncryptOptions("Indexed"));
+ assertNull(result.getTextOptions());
+ }
+
+ @Test
+ @SuppressWarnings("deprecation")
+ void shouldPreferStringOptionsOverDeprecatedTextOptionsWhenBothSet() {
+ EncryptOptions options = new EncryptOptions("String")
+ .stringOptions(new StringOptions()
+ .caseSensitive(true)
+ .diacriticSensitive(true)
+ .prefixOptions(BsonDocument.parse("{strMaxQueryLength: 10, strMinQueryLength: 2}")))
+ .textOptions(new TextOptions()
+ .caseSensitive(false)
+ .diacriticSensitive(false)
+ .suffixOptions(BsonDocument.parse("{strMaxQueryLength: 5, strMinQueryLength: 1}")));
+
+ MongoExplicitEncryptOptions result = EncryptOptionsHelper.asMongoExplicitEncryptOptions(options);
+
+ assertEquals(BsonDocument.parse("{caseSensitive: true, diacriticSensitive: true, "
+ + "prefix: {strMaxQueryLength: 10, strMinQueryLength: 2}}"),
+ result.getTextOptions());
+ }
+}
diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ClientEncryptionTextExplicitEncryptionTest.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ClientEncryptionStringExplicitEncryptionTest.java
similarity index 87%
rename from driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ClientEncryptionTextExplicitEncryptionTest.java
rename to driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ClientEncryptionStringExplicitEncryptionTest.java
index 2c7eda55aae..d53f4b2c331 100644
--- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ClientEncryptionTextExplicitEncryptionTest.java
+++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ClientEncryptionStringExplicitEncryptionTest.java
@@ -18,14 +18,14 @@
import com.mongodb.ClientEncryptionSettings;
import com.mongodb.MongoClientSettings;
-import com.mongodb.client.AbstractClientEncryptionTextExplicitEncryptionTest;
+import com.mongodb.client.AbstractClientEncryptionStringExplicitEncryptionTest;
import com.mongodb.client.MongoClient;
import com.mongodb.client.vault.ClientEncryption;
import com.mongodb.reactivestreams.client.syncadapter.SyncClientEncryption;
import com.mongodb.reactivestreams.client.syncadapter.SyncMongoClient;
import com.mongodb.reactivestreams.client.vault.ClientEncryptions;
-public class ClientEncryptionTextExplicitEncryptionTest extends AbstractClientEncryptionTextExplicitEncryptionTest {
+public class ClientEncryptionStringExplicitEncryptionTest extends AbstractClientEncryptionStringExplicitEncryptionTest {
@Override
protected MongoClient createMongoClient(final MongoClientSettings settings) {
return new SyncMongoClient(settings);
diff --git a/driver-sync/src/test/functional/com/mongodb/client/AbstractClientEncryptionStringExplicitEncryptionTest.java b/driver-sync/src/test/functional/com/mongodb/client/AbstractClientEncryptionStringExplicitEncryptionTest.java
new file mode 100644
index 00000000000..89ed6b61e55
--- /dev/null
+++ b/driver-sync/src/test/functional/com/mongodb/client/AbstractClientEncryptionStringExplicitEncryptionTest.java
@@ -0,0 +1,394 @@
+/*
+ * Copyright 2008-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.mongodb.client;
+
+import com.mongodb.AutoEncryptionSettings;
+import com.mongodb.ClientEncryptionSettings;
+import com.mongodb.MongoClientSettings;
+import com.mongodb.MongoException;
+import com.mongodb.MongoNamespace;
+import com.mongodb.WriteConcern;
+import com.mongodb.client.model.CreateCollectionOptions;
+import com.mongodb.client.model.DropCollectionOptions;
+import com.mongodb.client.model.vault.EncryptOptions;
+import com.mongodb.client.model.vault.StringOptions;
+import com.mongodb.client.vault.ClientEncryption;
+import com.mongodb.connection.ServerVersion;
+import com.mongodb.fixture.EncryptionFixture;
+import org.bson.BsonBinary;
+import org.bson.BsonDocument;
+import org.bson.BsonString;
+import org.bson.Document;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import java.util.Map;
+
+import static com.mongodb.ClusterFixture.getDefaultDatabaseName;
+import static com.mongodb.ClusterFixture.getMongoCryptVersion;
+import static com.mongodb.ClusterFixture.hasEncryptionTestsEnabled;
+import static com.mongodb.ClusterFixture.isStandalone;
+import static com.mongodb.ClusterFixture.serverVersionAtLeast;
+import static com.mongodb.client.Fixture.getDefaultDatabase;
+import static com.mongodb.client.Fixture.getMongoClient;
+import static com.mongodb.client.Fixture.getMongoClientSettings;
+import static com.mongodb.client.Fixture.getMongoClientSettingsBuilder;
+import static com.mongodb.fixture.EncryptionFixture.getKmsProviders;
+import static java.util.Arrays.asList;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assumptions.assumeFalse;
+import static org.junit.jupiter.api.Assumptions.assumeTrue;
+import static util.JsonPoweredTestHelper.getTestDocument;
+
+public abstract class AbstractClientEncryptionStringExplicitEncryptionTest {
+
+ private static final ServerVersion MIN_SUPPORTED_LIB_MONGOCRYPT_VERSION = new ServerVersion(asList(1, 20, 0));
+ private boolean gaSupported;
+ private MongoClient explicitEncryptedClient;
+ private MongoClient autoEncryptedClient;
+ private MongoDatabase explicitEncryptedDatabase;
+ private MongoDatabase autoEncryptedDatabase;
+ private ClientEncryption clientEncryption;
+ private BsonBinary key1Id;
+
+ protected abstract MongoClient createMongoClient(MongoClientSettings settings);
+ protected abstract ClientEncryption createClientEncryption(ClientEncryptionSettings settings);
+
+ @BeforeEach
+ public void setUp() {
+ assumeTrue(hasEncryptionTestsEnabled(), "String explicit encryption tests disabled");
+ assumeTrue(getMongoCryptVersion().compareTo(MIN_SUPPORTED_LIB_MONGOCRYPT_VERSION) >= 0, "Requires newer MongoCrypt version");
+ assumeTrue(serverVersionAtLeast(8, 2));
+ assumeFalse(isStandalone());
+
+ gaSupported = serverVersionAtLeast(9, 0);
+
+ MongoNamespace dataKeysNamespace = new MongoNamespace("keyvault.datakeys");
+ BsonDocument key1Document = bsonDocumentFromPath("keys/key1-document.json");
+
+ MapOnly applies when algorithm is "Indexed", "Range", or "TextPreview".
+ *Only applies when algorithm is "Indexed", "Range", or "String".
* @param contentionFactor the contention factor * @return this * @since 1.5 @@ -100,7 +100,7 @@ public Builder contentionFactor(final Long contentionFactor) { /** * The QueryType. * - *Only applies when algorithm is "Indexed", "Range", or "TextPreview".
+ *Only applies when algorithm is "Indexed", "Range", or "String".
* * @param queryType the query type * @return this @@ -126,11 +126,11 @@ public Builder rangeOptions(final BsonDocument rangeOptions) { } /** - * The Text Options. + * The String Options. * - *Only applies when algorithm is "TextPreview".
+ *Only applies when algorithm is "String".
* - * @param textOptions the text options + * @param textOptions the string options, as a BSON document * @return this * @since 5.6 */