Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(223)

Side by Side Diff: third_party/protobuf/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java

Issue 2600753002: Reverts third_party/protobuf: Update to HEAD (f52e188fe4) (Closed)
Patch Set: Created 3 years, 12 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Protocol Buffers - Google's data interchange format 1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved. 2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/ 3 // https://developers.google.com/protocol-buffers/
4 // 4 //
5 // Redistribution and use in source and binary forms, with or without 5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are 6 // modification, are permitted provided that the following conditions are
7 // met: 7 // met:
8 // 8 //
9 // * Redistributions of source code must retain the above copyright 9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer. 10 // notice, this list of conditions and the following disclaimer.
(...skipping 20 matching lines...) Expand all
31 package com.google.protobuf.util; 31 package com.google.protobuf.util;
32 32
33 import com.google.protobuf.Descriptors.Descriptor; 33 import com.google.protobuf.Descriptors.Descriptor;
34 import com.google.protobuf.Descriptors.FieldDescriptor; 34 import com.google.protobuf.Descriptors.FieldDescriptor;
35 import com.google.protobuf.FieldMask; 35 import com.google.protobuf.FieldMask;
36 import com.google.protobuf.Message; 36 import com.google.protobuf.Message;
37 37
38 import java.util.ArrayList; 38 import java.util.ArrayList;
39 import java.util.List; 39 import java.util.List;
40 import java.util.Map.Entry; 40 import java.util.Map.Entry;
41 import java.util.SortedMap;
42 import java.util.TreeMap; 41 import java.util.TreeMap;
43 import java.util.logging.Logger; 42 import java.util.logging.Logger;
44 43
45 /** 44 /**
46 * A tree representation of a FieldMask. Each leaf node in this tree represent 45 * A tree representation of a FieldMask. Each leaf node in this tree represent
47 * a field path in the FieldMask. 46 * a field path in the FieldMask.
48 * 47 *
49 * <p>For example, FieldMask "foo.bar,foo.baz,bar.baz" as a tree will be: 48 * <p>For example, FieldMask "foo.bar,foo.baz,bar.baz" as a tree will be:
50 * <pre> 49 * <pre>
51 * [root] -+- foo -+- bar 50 * [root] -+- foo -+- bar
52 * | | 51 * | |
53 * | +- baz 52 * | +- baz
54 * | 53 * |
55 * +- bar --- baz 54 * +- bar --- baz
56 * </pre> 55 * </pre>
57 * 56 *
58 * <p>By representing FieldMasks with this tree structure we can easily convert 57 * <p>By representing FieldMasks with this tree structure we can easily convert
59 * a FieldMask to a canonical form, merge two FieldMasks, calculate the 58 * a FieldMask to a canonical form, merge two FieldMasks, calculate the
60 * intersection to two FieldMasks and traverse all fields specified by the 59 * intersection to two FieldMasks and traverse all fields specified by the
61 * FieldMask in a message tree. 60 * FieldMask in a message tree.
62 */ 61 */
63 final class FieldMaskTree { 62 class FieldMaskTree {
64 private static final Logger logger = Logger.getLogger(FieldMaskTree.class.getN ame()); 63 private static final Logger logger = Logger.getLogger(FieldMaskTree.class.getN ame());
65 64
66 private static final String FIELD_PATH_SEPARATOR_REGEX = "\\."; 65 private static final String FIELD_PATH_SEPARATOR_REGEX = "\\.";
67 66
68 private static final class Node { 67 private static class Node {
69 final SortedMap<String, Node> children = new TreeMap<String, Node>(); 68 public TreeMap<String, Node> children = new TreeMap<String, Node>();
70 } 69 }
71 70
72 private final Node root = new Node(); 71 private final Node root = new Node();
73 72
74 /** 73 /** Creates an empty FieldMaskTree. */
75 * Creates an empty FieldMaskTree. 74 public FieldMaskTree() {}
76 */
77 FieldMaskTree() {}
78 75
79 /** 76 /** Creates a FieldMaskTree for a given FieldMask. */
80 * Creates a FieldMaskTree for a given FieldMask. 77 public FieldMaskTree(FieldMask mask) {
81 */
82 FieldMaskTree(FieldMask mask) {
83 mergeFromFieldMask(mask); 78 mergeFromFieldMask(mask);
84 } 79 }
85 80
86 @Override 81 @Override
87 public String toString() { 82 public String toString() {
88 return FieldMaskUtil.toString(toFieldMask()); 83 return FieldMaskUtil.toString(toFieldMask());
89 } 84 }
90 85
91 /** 86 /**
92 * Adds a field path to the tree. In a FieldMask, every field path matches the 87 * Adds a field path to the tree. In a FieldMask, every field path matches the
93 * specified field as well as all its sub-fields. For example, a field path 88 * specified field as well as all its sub-fields. For example, a field path
94 * "foo.bar" matches field "foo.bar" and also "foo.bar.baz", etc. When adding 89 * "foo.bar" matches field "foo.bar" and also "foo.bar.baz", etc. When adding
95 * a field path to the tree, redundant sub-paths will be removed. That is, 90 * a field path to the tree, redundant sub-paths will be removed. That is,
96 * after adding "foo.bar" to the tree, "foo.bar.baz" will be removed if it 91 * after adding "foo.bar" to the tree, "foo.bar.baz" will be removed if it
97 * exists, which will turn the tree node for "foo.bar" to a leaf node. 92 * exists, which will turn the tree node for "foo.bar" to a leaf node.
98 * Likewise, if the field path to add is a sub-path of an existing leaf node, 93 * Likewise, if the field path to add is a sub-path of an existing leaf node,
99 * nothing will be changed in the tree. 94 * nothing will be changed in the tree.
100 */ 95 */
101 FieldMaskTree addFieldPath(String path) { 96 public FieldMaskTree addFieldPath(String path) {
102 String[] parts = path.split(FIELD_PATH_SEPARATOR_REGEX); 97 String[] parts = path.split(FIELD_PATH_SEPARATOR_REGEX);
103 if (parts.length == 0) { 98 if (parts.length == 0) {
104 return this; 99 return this;
105 } 100 }
106 Node node = root; 101 Node node = root;
107 boolean createNewBranch = false; 102 boolean createNewBranch = false;
108 // Find the matching node in the tree. 103 // Find the matching node in the tree.
109 for (String part : parts) { 104 for (String part : parts) {
110 // Check whether the path matches an existing leaf node. 105 // Check whether the path matches an existing leaf node.
111 if (!createNewBranch && node != root && node.children.isEmpty()) { 106 if (!createNewBranch && node != root && node.children.isEmpty()) {
(...skipping 10 matching lines...) Expand all
122 } 117 }
123 } 118 }
124 // Turn the matching node into a leaf node (i.e., remove sub-paths). 119 // Turn the matching node into a leaf node (i.e., remove sub-paths).
125 node.children.clear(); 120 node.children.clear();
126 return this; 121 return this;
127 } 122 }
128 123
129 /** 124 /**
130 * Merges all field paths in a FieldMask into this tree. 125 * Merges all field paths in a FieldMask into this tree.
131 */ 126 */
132 FieldMaskTree mergeFromFieldMask(FieldMask mask) { 127 public FieldMaskTree mergeFromFieldMask(FieldMask mask) {
133 for (String path : mask.getPathsList()) { 128 for (String path : mask.getPathsList()) {
134 addFieldPath(path); 129 addFieldPath(path);
135 } 130 }
136 return this; 131 return this;
137 } 132 }
138 133
139 /** 134 /** Converts this tree to a FieldMask. */
140 * Converts this tree to a FieldMask. 135 public FieldMask toFieldMask() {
141 */
142 FieldMask toFieldMask() {
143 if (root.children.isEmpty()) { 136 if (root.children.isEmpty()) {
144 return FieldMask.getDefaultInstance(); 137 return FieldMask.getDefaultInstance();
145 } 138 }
146 List<String> paths = new ArrayList<String>(); 139 List<String> paths = new ArrayList<String>();
147 getFieldPaths(root, "", paths); 140 getFieldPaths(root, "", paths);
148 return FieldMask.newBuilder().addAllPaths(paths).build(); 141 return FieldMask.newBuilder().addAllPaths(paths).build();
149 } 142 }
150 143
151 /** 144 /** Gathers all field paths in a sub-tree. */
152 * Gathers all field paths in a sub-tree.
153 */
154 private void getFieldPaths(Node node, String path, List<String> paths) { 145 private void getFieldPaths(Node node, String path, List<String> paths) {
155 if (node.children.isEmpty()) { 146 if (node.children.isEmpty()) {
156 paths.add(path); 147 paths.add(path);
157 return; 148 return;
158 } 149 }
159 for (Entry<String, Node> entry : node.children.entrySet()) { 150 for (Entry<String, Node> entry : node.children.entrySet()) {
160 String childPath = path.isEmpty() ? entry.getKey() : path + "." + entry.ge tKey(); 151 String childPath = path.isEmpty() ? entry.getKey() : path + "." + entry.ge tKey();
161 getFieldPaths(entry.getValue(), childPath, paths); 152 getFieldPaths(entry.getValue(), childPath, paths);
162 } 153 }
163 } 154 }
164 155
165 /** 156 /**
166 * Adds the intersection of this tree with the given {@code path} to {@code ou tput}. 157 * Adds the intersection of this tree with the given {@code path} to
158 * {@code output}.
167 */ 159 */
168 void intersectFieldPath(String path, FieldMaskTree output) { 160 public void intersectFieldPath(String path, FieldMaskTree output) {
169 if (root.children.isEmpty()) { 161 if (root.children.isEmpty()) {
170 return; 162 return;
171 } 163 }
172 String[] parts = path.split(FIELD_PATH_SEPARATOR_REGEX); 164 String[] parts = path.split(FIELD_PATH_SEPARATOR_REGEX);
173 if (parts.length == 0) { 165 if (parts.length == 0) {
174 return; 166 return;
175 } 167 }
176 Node node = root; 168 Node node = root;
177 for (String part : parts) { 169 for (String part : parts) {
178 if (node != root && node.children.isEmpty()) { 170 if (node != root && node.children.isEmpty()) {
(...skipping 10 matching lines...) Expand all
189 // We found a matching node for the path. All leaf children of this matching 181 // We found a matching node for the path. All leaf children of this matching
190 // node is in the intersection. 182 // node is in the intersection.
191 List<String> paths = new ArrayList<String>(); 183 List<String> paths = new ArrayList<String>();
192 getFieldPaths(node, path, paths); 184 getFieldPaths(node, path, paths);
193 for (String value : paths) { 185 for (String value : paths) {
194 output.addFieldPath(value); 186 output.addFieldPath(value);
195 } 187 }
196 } 188 }
197 189
198 /** 190 /**
199 * Merges all fields specified by this FieldMaskTree from {@code source} to {@ code destination}. 191 * Merges all fields specified by this FieldMaskTree from {@code source} to
192 * {@code destination}.
200 */ 193 */
201 void merge(Message source, Message.Builder destination, FieldMaskUtil.MergeOpt ions options) { 194 public void merge(
195 Message source, Message.Builder destination, FieldMaskUtil.MergeOptions op tions) {
202 if (source.getDescriptorForType() != destination.getDescriptorForType()) { 196 if (source.getDescriptorForType() != destination.getDescriptorForType()) {
203 throw new IllegalArgumentException("Cannot merge messages of different typ es."); 197 throw new IllegalArgumentException("Cannot merge messages of different typ es.");
204 } 198 }
205 if (root.children.isEmpty()) { 199 if (root.children.isEmpty()) {
206 return; 200 return;
207 } 201 }
208 merge(root, "", source, destination, options); 202 merge(root, "", source, destination, options);
209 } 203 }
210 204
211 /** 205 /** Merges all fields specified by a sub-tree from {@code source} to
212 * Merges all fields specified by a sub-tree from {@code source} to {@code des tination}. 206 * {@code destination}.
213 */ 207 */
214 private void merge( 208 private void merge(
215 Node node, 209 Node node,
216 String path, 210 String path,
217 Message source, 211 Message source,
218 Message.Builder destination, 212 Message.Builder destination,
219 FieldMaskUtil.MergeOptions options) { 213 FieldMaskUtil.MergeOptions options) {
220 if (source.getDescriptorForType() != destination.getDescriptorForType()) { 214 assert source.getDescriptorForType() == destination.getDescriptorForType();
221 throw new IllegalArgumentException(
222 String.format(
223 "source (%s) and destination (%s) descriptor must be equal",
224 source.getDescriptorForType(), destination.getDescriptorForType()) );
225 }
226 215
227 Descriptor descriptor = source.getDescriptorForType(); 216 Descriptor descriptor = source.getDescriptorForType();
228 for (Entry<String, Node> entry : node.children.entrySet()) { 217 for (Entry<String, Node> entry : node.children.entrySet()) {
229 FieldDescriptor field = descriptor.findFieldByName(entry.getKey()); 218 FieldDescriptor field = descriptor.findFieldByName(entry.getKey());
230 if (field == null) { 219 if (field == null) {
231 logger.warning( 220 logger.warning(
232 "Cannot find field \"" 221 "Cannot find field \""
233 + entry.getKey() 222 + entry.getKey()
234 + "\" in message type " 223 + "\" in message type "
235 + descriptor.getFullName()); 224 + descriptor.getFullName());
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
278 if (source.hasField(field) || !options.replacePrimitiveFields()) { 267 if (source.hasField(field) || !options.replacePrimitiveFields()) {
279 destination.setField(field, source.getField(field)); 268 destination.setField(field, source.getField(field));
280 } else { 269 } else {
281 destination.clearField(field); 270 destination.clearField(field);
282 } 271 }
283 } 272 }
284 } 273 }
285 } 274 }
286 } 275 }
287 } 276 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698