FieldMaskUtil.java
Go to the documentation of this file.
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 package com.google.protobuf.util;
32 
33 import static com.google.common.base.Preconditions.checkArgument;
34 
35 import com.google.common.base.CaseFormat;
36 import com.google.common.base.Joiner;
37 import com.google.common.base.Splitter;
38 import com.google.common.primitives.Ints;
39 import com.google.errorprone.annotations.CanIgnoreReturnValue;
42 import com.google.protobuf.FieldMask;
44 import com.google.protobuf.Message;
45 import java.util.ArrayList;
46 import java.util.Arrays;
47 import java.util.List;
48 
52 public class FieldMaskUtil {
53  private static final String FIELD_PATH_SEPARATOR = ",";
54  private static final String FIELD_PATH_SEPARATOR_REGEX = ",";
55  private static final String FIELD_SEPARATOR_REGEX = "\\.";
56 
57  private FieldMaskUtil() {}
58 
62  public static String toString(FieldMask fieldMask) {
63  // TODO(xiaofeng): Consider using com.google.common.base.Joiner here instead.
64  StringBuilder result = new StringBuilder();
65  boolean first = true;
66  for (String value : fieldMask.getPathsList()) {
67  if (value.isEmpty()) {
68  // Ignore empty paths.
69  continue;
70  }
71  if (first) {
72  first = false;
73  } else {
74  result.append(FIELD_PATH_SEPARATOR);
75  }
76  result.append(value);
77  }
78  return result.toString();
79  }
80 
84  public static FieldMask fromString(String value) {
85  // TODO(xiaofeng): Consider using com.google.common.base.Splitter here instead.
86  return fromStringList(null, Arrays.asList(value.split(FIELD_PATH_SEPARATOR_REGEX)));
87  }
88 
94  public static FieldMask fromString(Class<? extends Message> type, String value) {
95  // TODO(xiaofeng): Consider using com.google.common.base.Splitter here instead.
96  return fromStringList(type, Arrays.asList(value.split(FIELD_PATH_SEPARATOR_REGEX)));
97  }
98 
104  // TODO(xiaofeng): Consider renaming fromStrings()
105  public static FieldMask fromStringList(Class<? extends Message> type, Iterable<String> paths) {
106  FieldMask.Builder builder = FieldMask.newBuilder();
107  for (String path : paths) {
108  if (path.isEmpty()) {
109  // Ignore empty field paths.
110  continue;
111  }
112  if (type != null && !isValid(type, path)) {
113  throw new IllegalArgumentException(path + " is not a valid path for " + type);
114  }
115  builder.addPaths(path);
116  }
117  return builder.build();
118  }
119 
125  public static FieldMask fromFieldNumbers(Class<? extends Message> type, int... fieldNumbers) {
126  return fromFieldNumbers(type, Ints.asList(fieldNumbers));
127  }
128 
135  Class<? extends Message> type, Iterable<Integer> fieldNumbers) {
136  Descriptor descriptor = Internal.getDefaultInstance(type).getDescriptorForType();
137 
138  FieldMask.Builder builder = FieldMask.newBuilder();
139  for (Integer fieldNumber : fieldNumbers) {
140  FieldDescriptor field = descriptor.findFieldByNumber(fieldNumber);
141  checkArgument(
142  field != null,
143  String.format("%s is not a valid field number for %s.", fieldNumber, type));
144  builder.addPaths(field.getName());
145  }
146  return builder.build();
147  }
148 
153  public static String toJsonString(FieldMask fieldMask) {
154  List<String> paths = new ArrayList<String>(fieldMask.getPathsCount());
155  for (String path : fieldMask.getPathsList()) {
156  if (path.isEmpty()) {
157  continue;
158  }
159  paths.add(CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, path));
160  }
161  return Joiner.on(FIELD_PATH_SEPARATOR).join(paths);
162  }
163 
168  public static FieldMask fromJsonString(String value) {
169  Iterable<String> paths = Splitter.on(FIELD_PATH_SEPARATOR).split(value);
170  FieldMask.Builder builder = FieldMask.newBuilder();
171  for (String path : paths) {
172  if (path.isEmpty()) {
173  continue;
174  }
175  builder.addPaths(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, path));
176  }
177  return builder.build();
178  }
179 
183  public static boolean isValid(Class<? extends Message> type, FieldMask fieldMask) {
184  Descriptor descriptor = Internal.getDefaultInstance(type).getDescriptorForType();
185 
186  return isValid(descriptor, fieldMask);
187  }
188 
192  public static boolean isValid(Descriptor descriptor, FieldMask fieldMask) {
193  for (String path : fieldMask.getPathsList()) {
194  if (!isValid(descriptor, path)) {
195  return false;
196  }
197  }
198  return true;
199  }
200 
204  public static boolean isValid(Class<? extends Message> type, String path) {
205  Descriptor descriptor = Internal.getDefaultInstance(type).getDescriptorForType();
206 
207  return isValid(descriptor, path);
208  }
209 
213  public static boolean isValid(Descriptor descriptor, String path) {
214  String[] parts = path.split(FIELD_SEPARATOR_REGEX);
215  if (parts.length == 0) {
216  return false;
217  }
218  for (String name : parts) {
219  if (descriptor == null) {
220  return false;
221  }
222  FieldDescriptor field = descriptor.findFieldByName(name);
223  if (field == null) {
224  return false;
225  }
226  if (!field.isRepeated() && field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
227  descriptor = field.getMessageType();
228  } else {
229  descriptor = null;
230  }
231  }
232  return true;
233  }
234 
241  return new FieldMaskTree(mask).toFieldMask();
242  }
243 
247  public static FieldMask union(
248  FieldMask firstMask, FieldMask secondMask, FieldMask... otherMasks) {
249  FieldMaskTree maskTree = new FieldMaskTree(firstMask).mergeFromFieldMask(secondMask);
250  for (FieldMask mask : otherMasks) {
251  maskTree.mergeFromFieldMask(mask);
252  }
253  return maskTree.toFieldMask();
254  }
255 
259  public static FieldMask intersection(FieldMask mask1, FieldMask mask2) {
260  FieldMaskTree tree = new FieldMaskTree(mask1);
261  FieldMaskTree result = new FieldMaskTree();
262  for (String path : mask2.getPathsList()) {
263  tree.intersectFieldPath(path, result);
264  }
265  return result.toFieldMask();
266  }
267 
271  public static final class MergeOptions {
272  private boolean replaceMessageFields = false;
273  private boolean replaceRepeatedFields = false;
274  // TODO(b/28277137): change the default behavior to always replace primitive fields after
275  // fixing all failing TAP tests.
276  private boolean replacePrimitiveFields = false;
277 
282  public boolean replaceMessageFields() {
283  return replaceMessageFields;
284  }
285 
290  public boolean replaceRepeatedFields() {
291  return replaceRepeatedFields;
292  }
293 
299  public boolean replacePrimitiveFields() {
300  return replacePrimitiveFields;
301  }
302 
310  @CanIgnoreReturnValue
313  return this;
314  }
315 
323  @CanIgnoreReturnValue
326  return this;
327  }
328 
340  @CanIgnoreReturnValue
343  return this;
344  }
345  }
346 
351  public static void merge(
353  new FieldMaskTree(mask).merge(source, destination, options);
354  }
355 
359  public static void merge(FieldMask mask, Message source, Message.Builder destination) {
360  merge(mask, source, destination, new MergeOptions());
361  }
362 }
com.google.protobuf.Descriptors
Definition: Descriptors.java:80
com.google.protobuf.util.FieldMaskUtil.isValid
static boolean isValid(Class<? extends Message > type, String path)
Definition: FieldMaskUtil.java:204
name
GLuint const GLchar * name
Definition: glcorearb.h:3055
com.google.protobuf.util.FieldMaskUtil.isValid
static boolean isValid(Descriptor descriptor, FieldMask fieldMask)
Definition: FieldMaskUtil.java:192
options
Message * options
Definition: src/google/protobuf/descriptor.cc:3119
com.google.protobuf.util.FieldMaskUtil.MergeOptions.replaceMessageFields
boolean replaceMessageFields()
Definition: FieldMaskUtil.java:282
com.google.protobuf.util.FieldMaskUtil.FIELD_SEPARATOR_REGEX
static final String FIELD_SEPARATOR_REGEX
Definition: FieldMaskUtil.java:55
com.google.protobuf.util.FieldMaskUtil.normalize
static FieldMask normalize(FieldMask mask)
Definition: FieldMaskUtil.java:240
com.google.protobuf.util.FieldMaskUtil.MergeOptions.setReplaceMessageFields
MergeOptions setReplaceMessageFields(boolean value)
Definition: FieldMaskUtil.java:311
FieldMask
struct FieldMask FieldMask
Definition: php/ext/google/protobuf/protobuf.h:640
com.google.protobuf
Definition: ProtoCaliperBenchmark.java:2
com.google.protobuf.util.FieldMaskUtil.fromFieldNumbers
static FieldMask fromFieldNumbers(Class<? extends Message > type, Iterable< Integer > fieldNumbers)
Definition: FieldMaskUtil.java:134
descriptor
Descriptor * descriptor
Definition: php/ext/google/protobuf/protobuf.h:936
com.google.protobuf.util.FieldMaskUtil.toString
static String toString(FieldMask fieldMask)
Definition: FieldMaskUtil.java:62
com.google.protobuf.util.FieldMaskUtil.MergeOptions.setReplaceRepeatedFields
MergeOptions setReplaceRepeatedFields(boolean value)
Definition: FieldMaskUtil.java:324
com.google.protobuf.util.FieldMaskUtil.MergeOptions
Definition: FieldMaskUtil.java:271
com.google.protobuf.util.FieldMaskUtil.fromFieldNumbers
static FieldMask fromFieldNumbers(Class<? extends Message > type, int... fieldNumbers)
Definition: FieldMaskUtil.java:125
com.google.protobuf.util.FieldMaskUtil.MergeOptions.replacePrimitiveFields
boolean replacePrimitiveFields()
Definition: FieldMaskUtil.java:299
com.google.protobuf.util.FieldMaskUtil.fromString
static FieldMask fromString(String value)
Definition: FieldMaskUtil.java:84
com.google.protobuf.util.FieldMaskUtil.MergeOptions.setReplacePrimitiveFields
MergeOptions setReplacePrimitiveFields(boolean value)
Definition: FieldMaskUtil.java:341
com.google.protobuf.Message.Builder
Definition: Message.java:104
path
GLsizei const GLchar ** path
Definition: glcorearb.h:3658
com.google.protobuf.util.FieldMaskUtil.FIELD_PATH_SEPARATOR_REGEX
static final String FIELD_PATH_SEPARATOR_REGEX
Definition: FieldMaskUtil.java:54
mask
GLint GLuint mask
Definition: glcorearb.h:2789
com.google.protobuf.util.FieldMaskUtil.toJsonString
static String toJsonString(FieldMask fieldMask)
Definition: FieldMaskUtil.java:153
com.google.protobuf.Descriptors.FieldDescriptor.JavaType
Definition: Descriptors.java:1262
com.google.protobuf.util.FieldMaskUtil.merge
static void merge(FieldMask mask, Message source, Message.Builder destination, MergeOptions options)
Definition: FieldMaskUtil.java:351
source
GLsizei GLsizei GLchar * source
Definition: glcorearb.h:3072
field
const FieldDescriptor * field
Definition: parser_unittest.cc:2694
com.google.protobuf.util.FieldMaskUtil.fromStringList
static FieldMask fromStringList(Class<? extends Message > type, Iterable< String > paths)
Definition: FieldMaskUtil.java:105
com.google.protobuf.util.FieldMaskUtil.intersection
static FieldMask intersection(FieldMask mask1, FieldMask mask2)
Definition: FieldMaskUtil.java:259
com.google.protobuf.util.FieldMaskUtil
Definition: FieldMaskUtil.java:52
java
com.google.protobuf.Descriptors.Descriptor
Definition: Descriptors.java:629
com.google.protobuf.util.FieldMaskUtil.fromString
static FieldMask fromString(Class<? extends Message > type, String value)
Definition: FieldMaskUtil.java:94
type
GLenum type
Definition: glcorearb.h:2695
com.google.protobuf.Internal.getDefaultInstance
static< T extends MessageLite > T getDefaultInstance(Class< T > clazz)
Definition: Internal.java:364
com.google.protobuf.util.FieldMaskUtil.MergeOptions.replacePrimitiveFields
boolean replacePrimitiveFields
Definition: FieldMaskUtil.java:276
com.google.protobuf.util.FieldMaskUtil.FieldMaskUtil
FieldMaskUtil()
Definition: FieldMaskUtil.java:57
com.google.protobuf.util.FieldMaskUtil.MergeOptions.replaceMessageFields
boolean replaceMessageFields
Definition: FieldMaskUtil.java:272
com.google.protobuf.util.FieldMaskUtil.isValid
static boolean isValid(Descriptor descriptor, String path)
Definition: FieldMaskUtil.java:213
com.google
com
first
GLint first
Definition: glcorearb.h:2830
com.google.protobuf.util.FieldMaskUtil.fromJsonString
static FieldMask fromJsonString(String value)
Definition: FieldMaskUtil.java:168
tree
Definition: wepoll.c:502
com.google.protobuf.Internal
Definition: Internal.java:54
com.google.protobuf.util.FieldMaskUtil.merge
static void merge(FieldMask mask, Message source, Message.Builder destination)
Definition: FieldMaskUtil.java:359
com.google.protobuf.util.FieldMaskUtil.MergeOptions.replaceRepeatedFields
boolean replaceRepeatedFields()
Definition: FieldMaskUtil.java:290
com.google.protobuf.util.FieldMaskUtil.FIELD_PATH_SEPARATOR
static final String FIELD_PATH_SEPARATOR
Definition: FieldMaskUtil.java:53
value
GLsizei const GLfloat * value
Definition: glcorearb.h:3093
com.google.protobuf.util.FieldMaskUtil.isValid
static boolean isValid(Class<? extends Message > type, FieldMask fieldMask)
Definition: FieldMaskUtil.java:183
com.google.protobuf.util.FieldMaskUtil.MergeOptions.replaceRepeatedFields
boolean replaceRepeatedFields
Definition: FieldMaskUtil.java:273
com.google.protobuf.Message
Definition: Message.java:50
com.google.protobuf.Descriptors.FieldDescriptor
Definition: Descriptors.java:949
com.google.protobuf.Descriptors.FieldDescriptor.JavaType.MESSAGE
MESSAGE
Definition: Descriptors.java:1271


libaditof
Author(s):
autogenerated on Wed May 21 2025 02:06:51