/
DocumentTransform.java
119 lines (104 loc) · 4.14 KB
/
DocumentTransform.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/*
* Copyright 2017 Google LLC
*
* 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.google.cloud.firestore;
import com.google.firestore.v1.DocumentTransform.FieldTransform;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
/**
* A DocumentTransform contains pending server-side transforms and their corresponding field paths.
*/
final class DocumentTransform {
private final SortedMap<FieldPath, FieldTransform> transforms; // Sorted for testing.
private DocumentTransform(SortedMap<FieldPath, FieldTransform> transforms) {
this.transforms = transforms;
}
static DocumentTransform fromFieldPathMap(
DocumentReference documentReference, Map<FieldPath, Object> values) {
SortedMap<FieldPath, FieldTransform> transforms = new TreeMap<>();
for (Map.Entry<FieldPath, Object> entry : values.entrySet()) {
FieldPath path = entry.getKey();
Object value = entry.getValue();
if (value instanceof FieldValue) {
FieldValue fieldValue = (FieldValue) value;
if (fieldValue.includeInDocumentTransform()) {
transforms.put(path, fieldValue.toProto(path));
}
} else if (value instanceof Map) {
transforms.putAll(
extractFromMap((Map<String, Object>) value, path, /* allowTransforms= */ true));
} else if (entry.getValue() instanceof List) {
// DocumentTransforms cannot be contained in Lists. We still process the List for
// validation.
validateArray((List<Object>) entry.getValue(), path);
}
}
return new DocumentTransform(transforms);
}
private static SortedMap<FieldPath, FieldTransform> extractFromMap(
Map<String, Object> values, FieldPath path, boolean allowTransforms) {
SortedMap<FieldPath, FieldTransform> transforms = new TreeMap<>();
for (Map.Entry<String, Object> entry : values.entrySet()) {
Object value = entry.getValue();
path = path.append(FieldPath.of(entry.getKey()));
if (value instanceof FieldValue) {
FieldValue fieldValue = (FieldValue) value;
if (allowTransforms) {
if (fieldValue.includeInDocumentTransform()) {
transforms.put(path, fieldValue.toProto(path));
}
} else {
throw FirestoreException.invalidState(
fieldValue.getMethodName() + " is not supported inside of an array.");
}
} else if (value instanceof Map) {
transforms.putAll(extractFromMap((Map<String, Object>) value, path, allowTransforms));
} else if (entry.getValue() instanceof List) {
validateArray((List<Object>) entry.getValue(), path);
}
path = path.getParent();
}
return transforms;
}
private static void validateArray(List<Object> values, FieldPath path) {
for (int i = 0; i < values.size(); ++i) {
Object value = values.get(i);
path = path.append(FieldPath.of(Integer.toString(i)));
if (value instanceof FieldValue) {
throw FirestoreException.invalidState(
((FieldValue) value).getMethodName() + " is not supported inside of an array.");
} else if (value instanceof Map) {
extractFromMap((Map<String, Object>) value, path, false);
} else if (value instanceof List) {
validateArray((List<Object>) value, path);
}
path = path.getParent();
}
}
boolean isEmpty() {
return transforms.isEmpty();
}
Set<FieldPath> getFields() {
return Collections.unmodifiableSet(transforms.keySet());
}
Collection<FieldTransform> toPb() {
return transforms.values();
}
}