24
24
import java .util .Map .Entry ;
25
25
import java .util .Optional ;
26
26
import java .util .function .Function ;
27
- import java .util .stream .StreamSupport ;
28
27
29
28
import org .bson .BsonBinary ;
30
29
import org .bson .BsonBinarySubType ;
31
30
import org .bson .BsonNull ;
32
31
import org .bson .Document ;
33
32
import org .jspecify .annotations .Nullable ;
33
+
34
34
import org .springframework .data .mongodb .core .mapping .Field ;
35
35
import org .springframework .data .mongodb .core .query .Collation ;
36
36
import org .springframework .data .mongodb .core .schema .IdentifiableJsonSchemaProperty ;
@@ -391,6 +391,7 @@ public CollectionOptions changeStream(CollectionChangeStreamOptions changeStream
391
391
*
392
392
* @param encryptedFieldsOptions must not be {@literal null}.
393
393
* @return new instance of {@link CollectionOptions}.
394
+ * @since 4.5
394
395
*/
395
396
@ Contract ("_ -> new" )
396
397
@ CheckReturnValue
@@ -711,7 +712,7 @@ public static EncryptedFieldsOptions fromSchema(MongoJsonSchema schema) {
711
712
/**
712
713
* @return new instance of {@link EncryptedFieldsOptions}.
713
714
*/
714
- public static EncryptedFieldsOptions fromProperties (List <JsonSchemaProperty > properties ) {
715
+ public static EncryptedFieldsOptions fromProperties (List <? extends JsonSchemaProperty > properties ) {
715
716
return new EncryptedFieldsOptions (null , List .copyOf (properties ));
716
717
}
717
718
@@ -743,6 +744,7 @@ public EncryptedFieldsOptions queryable(JsonSchemaProperty property, QueryCharac
743
744
*
744
745
* @param property must not be {@literal null}.
745
746
* @return new instance of {@link EncryptedFieldsOptions}.
747
+ * @since 4.5.1
746
748
*/
747
749
@ Contract ("_ -> new" )
748
750
@ CheckReturnValue
@@ -751,24 +753,26 @@ public EncryptedFieldsOptions with(EncryptedJsonSchemaProperty property) {
751
753
}
752
754
753
755
/**
754
- * Add a {@link JsonSchemaProperty property} that should not be encrypted but not queryable.
756
+ * Add a {@link JsonSchemaProperty property} that should be encrypted but not queryable.
755
757
*
756
758
* @param property must not be {@literal null}.
757
- * @param key can be {@literal null}.
759
+ * @param keyId the key identifier to be used, can be {@literal null}.
758
760
* @return new instance of {@link EncryptedFieldsOptions}.
761
+ * @since 4.5.1
759
762
*/
760
763
@ Contract ("_, _ -> new" )
761
764
@ CheckReturnValue
762
- public EncryptedFieldsOptions encrypted (JsonSchemaProperty property , @ Nullable Object key ) {
765
+ public EncryptedFieldsOptions encrypted (JsonSchemaProperty property , @ Nullable Object keyId ) {
763
766
764
767
List <JsonSchemaProperty > targetPropertyList = new ArrayList <>(properties .size () + 1 );
765
768
targetPropertyList .addAll (properties );
769
+
766
770
if (property instanceof IdentifiableJsonSchemaProperty .EncryptedJsonSchemaProperty ) {
767
771
targetPropertyList .add (property );
768
772
} else {
769
773
EncryptedJsonSchemaProperty encryptedJsonSchemaProperty = new EncryptedJsonSchemaProperty (property );
770
- if (key != null ) {
771
- targetPropertyList .add (encryptedJsonSchemaProperty .keyId (key ));
774
+ if (keyId != null ) {
775
+ targetPropertyList .add (encryptedJsonSchemaProperty .keyId (keyId ));
772
776
}
773
777
}
774
778
@@ -799,45 +803,48 @@ private List<Document> fromProperties() {
799
803
800
804
List <Document > converted = new ArrayList <>(properties .size ());
801
805
for (JsonSchemaProperty property : properties ) {
806
+ converted .add (getEncryptedField (property ));
807
+ }
808
+ return converted ;
809
+ }
802
810
803
- Document field = new Document ( "path" , property . getIdentifier ());
811
+ private Document getEncryptedField ( JsonSchemaProperty property ) {
804
812
805
- if (!property .getTypes ().isEmpty ()) {
806
- field .append ("bsonType" , property .getTypes ().iterator ().next ().toBsonType ().value ());
807
- }
813
+ Document field = new Document ("path" , property .getIdentifier ());
808
814
809
- if (property instanceof QueryableJsonSchemaProperty qproperty && qproperty
810
- .getTargetProperty () instanceof IdentifiableJsonSchemaProperty .EncryptedJsonSchemaProperty encrypted ) {
811
- if (encrypted .getKeyId () != null ) {
812
- if (encrypted .getKeyId () instanceof String stringKey ) {
813
- field .append ("keyId" ,
814
- new BsonBinary (BsonBinarySubType .UUID_STANDARD , stringKey .getBytes (StandardCharsets .UTF_8 )));
815
- } else {
816
- field .append ("keyId" , encrypted .getKeyId ());
817
- }
818
- }
819
- } else if (property instanceof IdentifiableJsonSchemaProperty .EncryptedJsonSchemaProperty encrypted ) {
820
- if (encrypted .getKeyId () != null ) {
821
- if (encrypted .getKeyId () instanceof String stringKey ) {
822
- field .append ("keyId" ,
823
- new BsonBinary (BsonBinarySubType .UUID_STANDARD , stringKey .getBytes (StandardCharsets .UTF_8 )));
824
- } else {
825
- field .append ("keyId" , encrypted .getKeyId ());
826
- }
827
- }
828
- }
815
+ if (!property .getTypes ().isEmpty ()) {
816
+ field .append ("bsonType" , property .getTypes ().iterator ().next ().toBsonType ().value ());
817
+ }
818
+
819
+ if (property instanceof QueryableJsonSchemaProperty qp
820
+ && qp .getTargetProperty () instanceof IdentifiableJsonSchemaProperty .EncryptedJsonSchemaProperty encrypted
821
+ && encrypted .getKeyId () != null ) {
829
822
830
- if (property instanceof QueryableJsonSchemaProperty qproperty ) {
831
- field .append ("queries" , StreamSupport .stream (qproperty .getCharacteristics ().spliterator (), false )
832
- .map (QueryCharacteristic ::toDocument ).toList ());
823
+ if (encrypted .getKeyId () instanceof String stringKey ) {
824
+ field .append ("keyId" ,
825
+ new BsonBinary (BsonBinarySubType .UUID_STANDARD , stringKey .getBytes (StandardCharsets .UTF_8 )));
826
+ } else {
827
+ field .append ("keyId" , encrypted .getKeyId ());
833
828
}
834
- if (!field .containsKey ("keyId" )) {
835
- field .append ("keyId" , BsonNull .VALUE );
829
+ } else if (property instanceof IdentifiableJsonSchemaProperty .EncryptedJsonSchemaProperty encrypted
830
+ && encrypted .getKeyId () != null ) {
831
+ if (encrypted .getKeyId () instanceof String stringKey ) {
832
+ field .append ("keyId" ,
833
+ new BsonBinary (BsonBinarySubType .UUID_STANDARD , stringKey .getBytes (StandardCharsets .UTF_8 )));
834
+ } else {
835
+ field .append ("keyId" , encrypted .getKeyId ());
836
836
}
837
+ }
837
838
838
- converted .add (field );
839
+ if (property instanceof QueryableJsonSchemaProperty qp ) {
840
+ field .append ("queries" , qp .getCharacteristics ().map (QueryCharacteristic ::toDocument ).toList ());
839
841
}
840
- return converted ;
842
+
843
+ if (!field .containsKey ("keyId" )) {
844
+ field .append ("keyId" , BsonNull .VALUE );
845
+ }
846
+
847
+ return field ;
841
848
}
842
849
843
850
private List <Document > fromSchema () {
@@ -851,19 +858,25 @@ private List<Document> fromSchema() {
851
858
collectPaths (root , null , paths );
852
859
853
860
List <Document > fields = new ArrayList <>();
854
- if (!paths .isEmpty ()) {
861
+ if (paths .isEmpty ()) {
862
+ return fields ;
863
+ }
855
864
856
- for (Entry <String , Document > entry : paths .entrySet ()) {
857
- Document field = new Document ("path" , entry .getKey ());
858
- field .append ("keyId" , entry .getValue ().getOrDefault ("keyId" , BsonNull .VALUE ));
859
- if (entry .getValue ().containsKey ("bsonType" )) {
860
- field .append ("bsonType" , entry .getValue ().get ("bsonType" ));
861
- }
862
- if (entry .getValue ().containsKey ("queries" )) {
863
- field .put ("queries" , entry .getValue ().get ("queries" ));
864
- }
865
- fields .add (field );
865
+ for (Entry <String , Document > entry : paths .entrySet ()) {
866
+
867
+ Document field = new Document ("path" , entry .getKey ());
868
+
869
+ field .append ("keyId" , entry .getValue ().getOrDefault ("keyId" , BsonNull .VALUE ));
870
+
871
+ if (entry .getValue ().containsKey ("bsonType" )) {
872
+ field .append ("bsonType" , entry .getValue ().get ("bsonType" ));
873
+ }
874
+
875
+ if (entry .getValue ().containsKey ("queries" )) {
876
+ field .put ("queries" , entry .getValue ().get ("queries" ));
866
877
}
878
+
879
+ fields .add (field );
867
880
}
868
881
869
882
return fields ;
@@ -873,28 +886,29 @@ private List<Document> fromSchema() {
873
886
private static void collectPaths (Document document , @ Nullable String currentPath , Map <String , Document > paths ) {
874
887
875
888
if (document .containsKey ("type" ) && document .get ("type" ).equals ("object" )) {
889
+
876
890
Object o = document .get ("properties" );
877
- if (o == null ) {
891
+
892
+ if (!(o instanceof Document properties )) {
878
893
return ;
879
894
}
880
895
881
- if (o instanceof Document properties ) {
882
- for (Entry <String , Object > entry : properties .entrySet ()) {
883
- if (entry .getValue () instanceof Document nested ) {
884
-
885
- String path = currentPath == null ? entry .getKey () : (currentPath + "." + entry .getKey ());
886
- if (nested .containsKey ("encrypt" )) {
887
- Document target = new Document (nested .get ("encrypt" , Document .class ));
888
- if (nested .containsKey ("queries" )) {
889
- List <?> queries = nested .get ("queries" , List .class );
890
- if (!queries .isEmpty () && queries .iterator ().next () instanceof Document qd ) {
891
- target .putAll (qd );
892
- }
896
+ for (Entry <String , Object > entry : properties .entrySet ()) {
897
+
898
+ if (entry .getValue () instanceof Document nested ) {
899
+
900
+ String path = currentPath == null ? entry .getKey () : (currentPath + "." + entry .getKey ());
901
+ if (nested .containsKey ("encrypt" )) {
902
+ Document target = new Document (nested .get ("encrypt" , Document .class ));
903
+ if (nested .containsKey ("queries" )) {
904
+ List <?> queries = nested .get ("queries" , List .class );
905
+ if (!queries .isEmpty () && queries .iterator ().next () instanceof Document qd ) {
906
+ target .putAll (qd );
893
907
}
894
- paths .put (path , target );
895
- } else {
896
- collectPaths (nested , path , paths );
897
908
}
909
+ paths .put (path , target );
910
+ } else {
911
+ collectPaths (nested , path , paths );
898
912
}
899
913
}
900
914
}
0 commit comments