1 | // Protocol Buffers - Google's data interchange format |
---|
2 | // Copyright 2008 Google Inc. All rights reserved. |
---|
3 | // http://code.google.com/p/protobuf/ |
---|
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; |
---|
32 | |
---|
33 | import com.google.protobuf.Descriptors.Descriptor; |
---|
34 | import com.google.protobuf.Descriptors.EnumValueDescriptor; |
---|
35 | import com.google.protobuf.Descriptors.FieldDescriptor; |
---|
36 | |
---|
37 | import java.io.IOException; |
---|
38 | import java.io.ObjectStreamException; |
---|
39 | import java.io.Serializable; |
---|
40 | import java.lang.reflect.InvocationTargetException; |
---|
41 | import java.lang.reflect.Method; |
---|
42 | import java.util.ArrayList; |
---|
43 | import java.util.Collections; |
---|
44 | import java.util.Iterator; |
---|
45 | import java.util.List; |
---|
46 | import java.util.Map; |
---|
47 | import java.util.TreeMap; |
---|
48 | |
---|
49 | /** |
---|
50 | * All generated protocol message classes extend this class. This class |
---|
51 | * implements most of the Message and Builder interfaces using Java reflection. |
---|
52 | * Users can ignore this class and pretend that generated messages implement |
---|
53 | * the Message interface directly. |
---|
54 | * |
---|
55 | * @author kenton@google.com Kenton Varda |
---|
56 | */ |
---|
57 | public abstract class GeneratedMessage extends AbstractMessage |
---|
58 | implements Serializable { |
---|
59 | private static final long serialVersionUID = 1L; |
---|
60 | |
---|
61 | private final UnknownFieldSet unknownFields; |
---|
62 | |
---|
63 | /** |
---|
64 | * For testing. Allows a test to disable the optimization that avoids using |
---|
65 | * field builders for nested messages until they are requested. By disabling |
---|
66 | * this optimization, existing tests can be reused to test the field builders. |
---|
67 | */ |
---|
68 | protected static boolean alwaysUseFieldBuilders = false; |
---|
69 | |
---|
70 | protected GeneratedMessage() { |
---|
71 | this.unknownFields = UnknownFieldSet.getDefaultInstance(); |
---|
72 | } |
---|
73 | |
---|
74 | protected GeneratedMessage(Builder<?> builder) { |
---|
75 | this.unknownFields = builder.getUnknownFields(); |
---|
76 | } |
---|
77 | |
---|
78 | /** |
---|
79 | * For testing. Allows a test to disable the optimization that avoids using |
---|
80 | * field builders for nested messages until they are requested. By disabling |
---|
81 | * this optimization, existing tests can be reused to test the field builders. |
---|
82 | * See {@link RepeatedFieldBuilder} and {@link SingleFieldBuilder}. |
---|
83 | */ |
---|
84 | static void enableAlwaysUseFieldBuildersForTesting() { |
---|
85 | alwaysUseFieldBuilders = true; |
---|
86 | } |
---|
87 | |
---|
88 | /** |
---|
89 | * Get the FieldAccessorTable for this type. We can't have the message |
---|
90 | * class pass this in to the constructor because of bootstrapping trouble |
---|
91 | * with DescriptorProtos. |
---|
92 | */ |
---|
93 | protected abstract FieldAccessorTable internalGetFieldAccessorTable(); |
---|
94 | |
---|
95 | //@Override (Java 1.6 override semantics, but we must support 1.5) |
---|
96 | public Descriptor getDescriptorForType() { |
---|
97 | return internalGetFieldAccessorTable().descriptor; |
---|
98 | } |
---|
99 | |
---|
100 | /** Internal helper which returns a mutable map. */ |
---|
101 | private Map<FieldDescriptor, Object> getAllFieldsMutable() { |
---|
102 | final TreeMap<FieldDescriptor, Object> result = |
---|
103 | new TreeMap<FieldDescriptor, Object>(); |
---|
104 | final Descriptor descriptor = internalGetFieldAccessorTable().descriptor; |
---|
105 | for (final FieldDescriptor field : descriptor.getFields()) { |
---|
106 | if (field.isRepeated()) { |
---|
107 | final List<?> value = (List<?>) getField(field); |
---|
108 | if (!value.isEmpty()) { |
---|
109 | result.put(field, value); |
---|
110 | } |
---|
111 | } else { |
---|
112 | if (hasField(field)) { |
---|
113 | result.put(field, getField(field)); |
---|
114 | } |
---|
115 | } |
---|
116 | } |
---|
117 | return result; |
---|
118 | } |
---|
119 | |
---|
120 | @Override |
---|
121 | public boolean isInitialized() { |
---|
122 | for (final FieldDescriptor field : getDescriptorForType().getFields()) { |
---|
123 | // Check that all required fields are present. |
---|
124 | if (field.isRequired()) { |
---|
125 | if (!hasField(field)) { |
---|
126 | return false; |
---|
127 | } |
---|
128 | } |
---|
129 | // Check that embedded messages are initialized. |
---|
130 | if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { |
---|
131 | if (field.isRepeated()) { |
---|
132 | @SuppressWarnings("unchecked") final |
---|
133 | List<Message> messageList = (List<Message>) getField(field); |
---|
134 | for (final Message element : messageList) { |
---|
135 | if (!element.isInitialized()) { |
---|
136 | return false; |
---|
137 | } |
---|
138 | } |
---|
139 | } else { |
---|
140 | if (hasField(field) && !((Message) getField(field)).isInitialized()) { |
---|
141 | return false; |
---|
142 | } |
---|
143 | } |
---|
144 | } |
---|
145 | } |
---|
146 | |
---|
147 | return true; |
---|
148 | } |
---|
149 | |
---|
150 | //@Override (Java 1.6 override semantics, but we must support 1.5) |
---|
151 | public Map<FieldDescriptor, Object> getAllFields() { |
---|
152 | return Collections.unmodifiableMap(getAllFieldsMutable()); |
---|
153 | } |
---|
154 | |
---|
155 | //@Override (Java 1.6 override semantics, but we must support 1.5) |
---|
156 | public boolean hasField(final FieldDescriptor field) { |
---|
157 | return internalGetFieldAccessorTable().getField(field).has(this); |
---|
158 | } |
---|
159 | |
---|
160 | //@Override (Java 1.6 override semantics, but we must support 1.5) |
---|
161 | public Object getField(final FieldDescriptor field) { |
---|
162 | return internalGetFieldAccessorTable().getField(field).get(this); |
---|
163 | } |
---|
164 | |
---|
165 | //@Override (Java 1.6 override semantics, but we must support 1.5) |
---|
166 | public int getRepeatedFieldCount(final FieldDescriptor field) { |
---|
167 | return internalGetFieldAccessorTable().getField(field) |
---|
168 | .getRepeatedCount(this); |
---|
169 | } |
---|
170 | |
---|
171 | //@Override (Java 1.6 override semantics, but we must support 1.5) |
---|
172 | public Object getRepeatedField(final FieldDescriptor field, final int index) { |
---|
173 | return internalGetFieldAccessorTable().getField(field) |
---|
174 | .getRepeated(this, index); |
---|
175 | } |
---|
176 | |
---|
177 | //@Override (Java 1.6 override semantics, but we must support 1.5) |
---|
178 | public final UnknownFieldSet getUnknownFields() { |
---|
179 | return unknownFields; |
---|
180 | } |
---|
181 | |
---|
182 | protected abstract Message.Builder newBuilderForType(BuilderParent parent); |
---|
183 | |
---|
184 | /** |
---|
185 | * Interface for the parent of a Builder that allows the builder to |
---|
186 | * communicate invalidations back to the parent for use when using nested |
---|
187 | * builders. |
---|
188 | */ |
---|
189 | protected interface BuilderParent { |
---|
190 | |
---|
191 | /** |
---|
192 | * A builder becomes dirty whenever a field is modified -- including fields |
---|
193 | * in nested builders -- and becomes clean when build() is called. Thus, |
---|
194 | * when a builder becomes dirty, all its parents become dirty as well, and |
---|
195 | * when it becomes clean, all its children become clean. The dirtiness |
---|
196 | * state is used to invalidate certain cached values. |
---|
197 | * <br> |
---|
198 | * To this end, a builder calls markAsDirty() on its parent whenever it |
---|
199 | * transitions from clean to dirty. The parent must propagate this call to |
---|
200 | * its own parent, unless it was already dirty, in which case the |
---|
201 | * grandparent must necessarily already be dirty as well. The parent can |
---|
202 | * only transition back to "clean" after calling build() on all children. |
---|
203 | */ |
---|
204 | void markDirty(); |
---|
205 | } |
---|
206 | |
---|
207 | @SuppressWarnings("unchecked") |
---|
208 | public abstract static class Builder <BuilderType extends Builder> |
---|
209 | extends AbstractMessage.Builder<BuilderType> { |
---|
210 | |
---|
211 | private BuilderParent builderParent; |
---|
212 | |
---|
213 | private BuilderParentImpl meAsParent; |
---|
214 | |
---|
215 | // Indicates that we've built a message and so we are now obligated |
---|
216 | // to dispatch dirty invalidations. See GeneratedMessage.BuilderListener. |
---|
217 | private boolean isClean; |
---|
218 | |
---|
219 | private UnknownFieldSet unknownFields = |
---|
220 | UnknownFieldSet.getDefaultInstance(); |
---|
221 | |
---|
222 | protected Builder() { |
---|
223 | this(null); |
---|
224 | } |
---|
225 | |
---|
226 | protected Builder(BuilderParent builderParent) { |
---|
227 | this.builderParent = builderParent; |
---|
228 | } |
---|
229 | |
---|
230 | void dispose() { |
---|
231 | builderParent = null; |
---|
232 | } |
---|
233 | |
---|
234 | /** |
---|
235 | * Called by the subclass when a message is built. |
---|
236 | */ |
---|
237 | protected void onBuilt() { |
---|
238 | if (builderParent != null) { |
---|
239 | markClean(); |
---|
240 | } |
---|
241 | } |
---|
242 | |
---|
243 | /** |
---|
244 | * Called by the subclass or a builder to notify us that a message was |
---|
245 | * built and may be cached and therefore invalidations are needed. |
---|
246 | */ |
---|
247 | protected void markClean() { |
---|
248 | this.isClean = true; |
---|
249 | } |
---|
250 | |
---|
251 | /** |
---|
252 | * Gets whether invalidations are needed |
---|
253 | * |
---|
254 | * @return whether invalidations are needed |
---|
255 | */ |
---|
256 | protected boolean isClean() { |
---|
257 | return isClean; |
---|
258 | } |
---|
259 | |
---|
260 | // This is implemented here only to work around an apparent bug in the |
---|
261 | // Java compiler and/or build system. See bug #1898463. The mere presence |
---|
262 | // of this dummy clone() implementation makes it go away. |
---|
263 | @Override |
---|
264 | public BuilderType clone() { |
---|
265 | throw new UnsupportedOperationException( |
---|
266 | "This is supposed to be overridden by subclasses."); |
---|
267 | } |
---|
268 | |
---|
269 | /** |
---|
270 | * Called by the initialization and clear code paths to allow subclasses to |
---|
271 | * reset any of their builtin fields back to the initial values. |
---|
272 | */ |
---|
273 | public BuilderType clear() { |
---|
274 | unknownFields = UnknownFieldSet.getDefaultInstance(); |
---|
275 | onChanged(); |
---|
276 | return (BuilderType) this; |
---|
277 | } |
---|
278 | |
---|
279 | /** |
---|
280 | * Get the FieldAccessorTable for this type. We can't have the message |
---|
281 | * class pass this in to the constructor because of bootstrapping trouble |
---|
282 | * with DescriptorProtos. |
---|
283 | */ |
---|
284 | protected abstract FieldAccessorTable internalGetFieldAccessorTable(); |
---|
285 | |
---|
286 | //@Override (Java 1.6 override semantics, but we must support 1.5) |
---|
287 | public Descriptor getDescriptorForType() { |
---|
288 | return internalGetFieldAccessorTable().descriptor; |
---|
289 | } |
---|
290 | |
---|
291 | //@Override (Java 1.6 override semantics, but we must support 1.5) |
---|
292 | public Map<FieldDescriptor, Object> getAllFields() { |
---|
293 | return Collections.unmodifiableMap(getAllFieldsMutable()); |
---|
294 | } |
---|
295 | |
---|
296 | /** Internal helper which returns a mutable map. */ |
---|
297 | private Map<FieldDescriptor, Object> getAllFieldsMutable() { |
---|
298 | final TreeMap<FieldDescriptor, Object> result = |
---|
299 | new TreeMap<FieldDescriptor, Object>(); |
---|
300 | final Descriptor descriptor = internalGetFieldAccessorTable().descriptor; |
---|
301 | for (final FieldDescriptor field : descriptor.getFields()) { |
---|
302 | if (field.isRepeated()) { |
---|
303 | final List value = (List) getField(field); |
---|
304 | if (!value.isEmpty()) { |
---|
305 | result.put(field, value); |
---|
306 | } |
---|
307 | } else { |
---|
308 | if (hasField(field)) { |
---|
309 | result.put(field, getField(field)); |
---|
310 | } |
---|
311 | } |
---|
312 | } |
---|
313 | return result; |
---|
314 | } |
---|
315 | |
---|
316 | public Message.Builder newBuilderForField( |
---|
317 | final FieldDescriptor field) { |
---|
318 | return internalGetFieldAccessorTable().getField(field).newBuilder(); |
---|
319 | } |
---|
320 | |
---|
321 | //@Override (Java 1.6 override semantics, but we must support 1.5) |
---|
322 | public boolean hasField(final FieldDescriptor field) { |
---|
323 | return internalGetFieldAccessorTable().getField(field).has(this); |
---|
324 | } |
---|
325 | |
---|
326 | //@Override (Java 1.6 override semantics, but we must support 1.5) |
---|
327 | public Object getField(final FieldDescriptor field) { |
---|
328 | Object object = internalGetFieldAccessorTable().getField(field).get(this); |
---|
329 | if (field.isRepeated()) { |
---|
330 | // The underlying list object is still modifiable at this point. |
---|
331 | // Make sure not to expose the modifiable list to the caller. |
---|
332 | return Collections.unmodifiableList((List) object); |
---|
333 | } else { |
---|
334 | return object; |
---|
335 | } |
---|
336 | } |
---|
337 | |
---|
338 | public BuilderType setField(final FieldDescriptor field, |
---|
339 | final Object value) { |
---|
340 | internalGetFieldAccessorTable().getField(field).set(this, value); |
---|
341 | return (BuilderType) this; |
---|
342 | } |
---|
343 | |
---|
344 | //@Override (Java 1.6 override semantics, but we must support 1.5) |
---|
345 | public BuilderType clearField(final FieldDescriptor field) { |
---|
346 | internalGetFieldAccessorTable().getField(field).clear(this); |
---|
347 | return (BuilderType) this; |
---|
348 | } |
---|
349 | |
---|
350 | //@Override (Java 1.6 override semantics, but we must support 1.5) |
---|
351 | public int getRepeatedFieldCount(final FieldDescriptor field) { |
---|
352 | return internalGetFieldAccessorTable().getField(field) |
---|
353 | .getRepeatedCount(this); |
---|
354 | } |
---|
355 | |
---|
356 | //@Override (Java 1.6 override semantics, but we must support 1.5) |
---|
357 | public Object getRepeatedField(final FieldDescriptor field, |
---|
358 | final int index) { |
---|
359 | return internalGetFieldAccessorTable().getField(field) |
---|
360 | .getRepeated(this, index); |
---|
361 | } |
---|
362 | |
---|
363 | public BuilderType setRepeatedField(final FieldDescriptor field, |
---|
364 | final int index, final Object value) { |
---|
365 | internalGetFieldAccessorTable().getField(field) |
---|
366 | .setRepeated(this, index, value); |
---|
367 | return (BuilderType) this; |
---|
368 | } |
---|
369 | |
---|
370 | public BuilderType addRepeatedField(final FieldDescriptor field, |
---|
371 | final Object value) { |
---|
372 | internalGetFieldAccessorTable().getField(field).addRepeated(this, value); |
---|
373 | return (BuilderType) this; |
---|
374 | } |
---|
375 | |
---|
376 | public final BuilderType setUnknownFields( |
---|
377 | final UnknownFieldSet unknownFields) { |
---|
378 | this.unknownFields = unknownFields; |
---|
379 | onChanged(); |
---|
380 | return (BuilderType) this; |
---|
381 | } |
---|
382 | |
---|
383 | @Override |
---|
384 | public final BuilderType mergeUnknownFields( |
---|
385 | final UnknownFieldSet unknownFields) { |
---|
386 | this.unknownFields = |
---|
387 | UnknownFieldSet.newBuilder(this.unknownFields) |
---|
388 | .mergeFrom(unknownFields) |
---|
389 | .build(); |
---|
390 | onChanged(); |
---|
391 | return (BuilderType) this; |
---|
392 | } |
---|
393 | |
---|
394 | //@Override (Java 1.6 override semantics, but we must support 1.5) |
---|
395 | public boolean isInitialized() { |
---|
396 | for (final FieldDescriptor field : getDescriptorForType().getFields()) { |
---|
397 | // Check that all required fields are present. |
---|
398 | if (field.isRequired()) { |
---|
399 | if (!hasField(field)) { |
---|
400 | return false; |
---|
401 | } |
---|
402 | } |
---|
403 | // Check that embedded messages are initialized. |
---|
404 | if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { |
---|
405 | if (field.isRepeated()) { |
---|
406 | @SuppressWarnings("unchecked") final |
---|
407 | List<Message> messageList = (List<Message>) getField(field); |
---|
408 | for (final Message element : messageList) { |
---|
409 | if (!element.isInitialized()) { |
---|
410 | return false; |
---|
411 | } |
---|
412 | } |
---|
413 | } else { |
---|
414 | if (hasField(field) && |
---|
415 | !((Message) getField(field)).isInitialized()) { |
---|
416 | return false; |
---|
417 | } |
---|
418 | } |
---|
419 | } |
---|
420 | } |
---|
421 | return true; |
---|
422 | } |
---|
423 | |
---|
424 | //@Override (Java 1.6 override semantics, but we must support 1.5) |
---|
425 | public final UnknownFieldSet getUnknownFields() { |
---|
426 | return unknownFields; |
---|
427 | } |
---|
428 | |
---|
429 | /** |
---|
430 | * Called by subclasses to parse an unknown field. |
---|
431 | * @return {@code true} unless the tag is an end-group tag. |
---|
432 | */ |
---|
433 | protected boolean parseUnknownField( |
---|
434 | final CodedInputStream input, |
---|
435 | final UnknownFieldSet.Builder unknownFields, |
---|
436 | final ExtensionRegistryLite extensionRegistry, |
---|
437 | final int tag) throws IOException { |
---|
438 | return unknownFields.mergeFieldFrom(tag, input); |
---|
439 | } |
---|
440 | |
---|
441 | /** |
---|
442 | * Implementation of {@link BuilderParent} for giving to our children. This |
---|
443 | * small inner class makes it so we don't publicly expose the BuilderParent |
---|
444 | * methods. |
---|
445 | */ |
---|
446 | private class BuilderParentImpl implements BuilderParent { |
---|
447 | |
---|
448 | //@Override (Java 1.6 override semantics, but we must support 1.5) |
---|
449 | public void markDirty() { |
---|
450 | onChanged(); |
---|
451 | } |
---|
452 | } |
---|
453 | |
---|
454 | /** |
---|
455 | * Gets the {@link BuilderParent} for giving to our children. |
---|
456 | * @return The builder parent for our children. |
---|
457 | */ |
---|
458 | protected BuilderParent getParentForChildren() { |
---|
459 | if (meAsParent == null) { |
---|
460 | meAsParent = new BuilderParentImpl(); |
---|
461 | } |
---|
462 | return meAsParent; |
---|
463 | } |
---|
464 | |
---|
465 | /** |
---|
466 | * Called when a the builder or one of its nested children has changed |
---|
467 | * and any parent should be notified of its invalidation. |
---|
468 | */ |
---|
469 | protected final void onChanged() { |
---|
470 | if (isClean && builderParent != null) { |
---|
471 | builderParent.markDirty(); |
---|
472 | |
---|
473 | // Don't keep dispatching invalidations until build is called again. |
---|
474 | isClean = false; |
---|
475 | } |
---|
476 | } |
---|
477 | } |
---|
478 | |
---|
479 | // ================================================================= |
---|
480 | // Extensions-related stuff |
---|
481 | |
---|
482 | public interface ExtendableMessageOrBuilder< |
---|
483 | MessageType extends ExtendableMessage> extends MessageOrBuilder { |
---|
484 | |
---|
485 | /** Check if a singular extension is present. */ |
---|
486 | <Type> boolean hasExtension( |
---|
487 | GeneratedExtension<MessageType, Type> extension); |
---|
488 | |
---|
489 | /** Get the number of elements in a repeated extension. */ |
---|
490 | <Type> int getExtensionCount( |
---|
491 | GeneratedExtension<MessageType, List<Type>> extension); |
---|
492 | |
---|
493 | /** Get the value of an extension. */ |
---|
494 | <Type> Type getExtension(GeneratedExtension<MessageType, Type> extension); |
---|
495 | |
---|
496 | /** Get one element of a repeated extension. */ |
---|
497 | <Type> Type getExtension( |
---|
498 | GeneratedExtension<MessageType, List<Type>> extension, |
---|
499 | int index); |
---|
500 | } |
---|
501 | |
---|
502 | /** |
---|
503 | * Generated message classes for message types that contain extension ranges |
---|
504 | * subclass this. |
---|
505 | * |
---|
506 | * <p>This class implements type-safe accessors for extensions. They |
---|
507 | * implement all the same operations that you can do with normal fields -- |
---|
508 | * e.g. "has", "get", and "getCount" -- but for extensions. The extensions |
---|
509 | * are identified using instances of the class {@link GeneratedExtension}; |
---|
510 | * the protocol compiler generates a static instance of this class for every |
---|
511 | * extension in its input. Through the magic of generics, all is made |
---|
512 | * type-safe. |
---|
513 | * |
---|
514 | * <p>For example, imagine you have the {@code .proto} file: |
---|
515 | * |
---|
516 | * <pre> |
---|
517 | * option java_class = "MyProto"; |
---|
518 | * |
---|
519 | * message Foo { |
---|
520 | * extensions 1000 to max; |
---|
521 | * } |
---|
522 | * |
---|
523 | * extend Foo { |
---|
524 | * optional int32 bar; |
---|
525 | * } |
---|
526 | * </pre> |
---|
527 | * |
---|
528 | * <p>Then you might write code like: |
---|
529 | * |
---|
530 | * <pre> |
---|
531 | * MyProto.Foo foo = getFoo(); |
---|
532 | * int i = foo.getExtension(MyProto.bar); |
---|
533 | * </pre> |
---|
534 | * |
---|
535 | * <p>See also {@link ExtendableBuilder}. |
---|
536 | */ |
---|
537 | public abstract static class ExtendableMessage< |
---|
538 | MessageType extends ExtendableMessage> |
---|
539 | extends GeneratedMessage |
---|
540 | implements ExtendableMessageOrBuilder<MessageType> { |
---|
541 | |
---|
542 | private final FieldSet<FieldDescriptor> extensions; |
---|
543 | |
---|
544 | protected ExtendableMessage() { |
---|
545 | this.extensions = FieldSet.newFieldSet(); |
---|
546 | } |
---|
547 | |
---|
548 | protected ExtendableMessage( |
---|
549 | ExtendableBuilder<MessageType, ?> builder) { |
---|
550 | super(builder); |
---|
551 | this.extensions = builder.buildExtensions(); |
---|
552 | } |
---|
553 | |
---|
554 | private void verifyExtensionContainingType( |
---|
555 | final GeneratedExtension<MessageType, ?> extension) { |
---|
556 | if (extension.getDescriptor().getContainingType() != |
---|
557 | getDescriptorForType()) { |
---|
558 | // This can only happen if someone uses unchecked operations. |
---|
559 | throw new IllegalArgumentException( |
---|
560 | "Extension is for type \"" + |
---|
561 | extension.getDescriptor().getContainingType().getFullName() + |
---|
562 | "\" which does not match message type \"" + |
---|
563 | getDescriptorForType().getFullName() + "\"."); |
---|
564 | } |
---|
565 | } |
---|
566 | |
---|
567 | /** Check if a singular extension is present. */ |
---|
568 | //@Override (Java 1.6 override semantics, but we must support 1.5) |
---|
569 | public final <Type> boolean hasExtension( |
---|
570 | final GeneratedExtension<MessageType, Type> extension) { |
---|
571 | verifyExtensionContainingType(extension); |
---|
572 | return extensions.hasField(extension.getDescriptor()); |
---|
573 | } |
---|
574 | |
---|
575 | /** Get the number of elements in a repeated extension. */ |
---|
576 | //@Override (Java 1.6 override semantics, but we must support 1.5) |
---|
577 | public final <Type> int getExtensionCount( |
---|
578 | final GeneratedExtension<MessageType, List<Type>> extension) { |
---|
579 | verifyExtensionContainingType(extension); |
---|
580 | final FieldDescriptor descriptor = extension.getDescriptor(); |
---|
581 | return extensions.getRepeatedFieldCount(descriptor); |
---|
582 | } |
---|
583 | |
---|
584 | /** Get the value of an extension. */ |
---|
585 | //@Override (Java 1.6 override semantics, but we must support 1.5) |
---|
586 | @SuppressWarnings("unchecked") |
---|
587 | public final <Type> Type getExtension( |
---|
588 | final GeneratedExtension<MessageType, Type> extension) { |
---|
589 | verifyExtensionContainingType(extension); |
---|
590 | FieldDescriptor descriptor = extension.getDescriptor(); |
---|
591 | final Object value = extensions.getField(descriptor); |
---|
592 | if (value == null) { |
---|
593 | if (descriptor.isRepeated()) { |
---|
594 | return (Type) Collections.emptyList(); |
---|
595 | } else if (descriptor.getJavaType() == |
---|
596 | FieldDescriptor.JavaType.MESSAGE) { |
---|
597 | return (Type) extension.getMessageDefaultInstance(); |
---|
598 | } else { |
---|
599 | return (Type) extension.fromReflectionType( |
---|
600 | descriptor.getDefaultValue()); |
---|
601 | } |
---|
602 | } else { |
---|
603 | return (Type) extension.fromReflectionType(value); |
---|
604 | } |
---|
605 | } |
---|
606 | |
---|
607 | /** Get one element of a repeated extension. */ |
---|
608 | //@Override (Java 1.6 override semantics, but we must support 1.5) |
---|
609 | @SuppressWarnings("unchecked") |
---|
610 | public final <Type> Type getExtension( |
---|
611 | final GeneratedExtension<MessageType, List<Type>> extension, |
---|
612 | final int index) { |
---|
613 | verifyExtensionContainingType(extension); |
---|
614 | FieldDescriptor descriptor = extension.getDescriptor(); |
---|
615 | return (Type) extension.singularFromReflectionType( |
---|
616 | extensions.getRepeatedField(descriptor, index)); |
---|
617 | } |
---|
618 | |
---|
619 | /** Called by subclasses to check if all extensions are initialized. */ |
---|
620 | protected boolean extensionsAreInitialized() { |
---|
621 | return extensions.isInitialized(); |
---|
622 | } |
---|
623 | |
---|
624 | @Override |
---|
625 | public boolean isInitialized() { |
---|
626 | return super.isInitialized() && extensionsAreInitialized(); |
---|
627 | } |
---|
628 | |
---|
629 | /** |
---|
630 | * Used by subclasses to serialize extensions. Extension ranges may be |
---|
631 | * interleaved with field numbers, but we must write them in canonical |
---|
632 | * (sorted by field number) order. ExtensionWriter helps us write |
---|
633 | * individual ranges of extensions at once. |
---|
634 | */ |
---|
635 | protected class ExtensionWriter { |
---|
636 | // Imagine how much simpler this code would be if Java iterators had |
---|
637 | // a way to get the next element without advancing the iterator. |
---|
638 | |
---|
639 | private final Iterator<Map.Entry<FieldDescriptor, Object>> iter = |
---|
640 | extensions.iterator(); |
---|
641 | private Map.Entry<FieldDescriptor, Object> next; |
---|
642 | private final boolean messageSetWireFormat; |
---|
643 | |
---|
644 | private ExtensionWriter(final boolean messageSetWireFormat) { |
---|
645 | if (iter.hasNext()) { |
---|
646 | next = iter.next(); |
---|
647 | } |
---|
648 | this.messageSetWireFormat = messageSetWireFormat; |
---|
649 | } |
---|
650 | |
---|
651 | public void writeUntil(final int end, final CodedOutputStream output) |
---|
652 | throws IOException { |
---|
653 | while (next != null && next.getKey().getNumber() < end) { |
---|
654 | FieldDescriptor descriptor = next.getKey(); |
---|
655 | if (messageSetWireFormat && descriptor.getLiteJavaType() == |
---|
656 | WireFormat.JavaType.MESSAGE && |
---|
657 | !descriptor.isRepeated()) { |
---|
658 | output.writeMessageSetExtension(descriptor.getNumber(), |
---|
659 | (Message) next.getValue()); |
---|
660 | } else { |
---|
661 | FieldSet.writeField(descriptor, next.getValue(), output); |
---|
662 | } |
---|
663 | if (iter.hasNext()) { |
---|
664 | next = iter.next(); |
---|
665 | } else { |
---|
666 | next = null; |
---|
667 | } |
---|
668 | } |
---|
669 | } |
---|
670 | } |
---|
671 | |
---|
672 | protected ExtensionWriter newExtensionWriter() { |
---|
673 | return new ExtensionWriter(false); |
---|
674 | } |
---|
675 | protected ExtensionWriter newMessageSetExtensionWriter() { |
---|
676 | return new ExtensionWriter(true); |
---|
677 | } |
---|
678 | |
---|
679 | /** Called by subclasses to compute the size of extensions. */ |
---|
680 | protected int extensionsSerializedSize() { |
---|
681 | return extensions.getSerializedSize(); |
---|
682 | } |
---|
683 | protected int extensionsSerializedSizeAsMessageSet() { |
---|
684 | return extensions.getMessageSetSerializedSize(); |
---|
685 | } |
---|
686 | |
---|
687 | // --------------------------------------------------------------- |
---|
688 | // Reflection |
---|
689 | |
---|
690 | protected Map<FieldDescriptor, Object> getExtensionFields() { |
---|
691 | return extensions.getAllFields(); |
---|
692 | } |
---|
693 | |
---|
694 | @Override |
---|
695 | public Map<FieldDescriptor, Object> getAllFields() { |
---|
696 | final Map<FieldDescriptor, Object> result = super.getAllFieldsMutable(); |
---|
697 | result.putAll(getExtensionFields()); |
---|
698 | return Collections.unmodifiableMap(result); |
---|
699 | } |
---|
700 | |
---|
701 | @Override |
---|
702 | public boolean hasField(final FieldDescriptor field) { |
---|
703 | if (field.isExtension()) { |
---|
704 | verifyContainingType(field); |
---|
705 | return extensions.hasField(field); |
---|
706 | } else { |
---|
707 | return super.hasField(field); |
---|
708 | } |
---|
709 | } |
---|
710 | |
---|
711 | @Override |
---|
712 | public Object getField(final FieldDescriptor field) { |
---|
713 | if (field.isExtension()) { |
---|
714 | verifyContainingType(field); |
---|
715 | final Object value = extensions.getField(field); |
---|
716 | if (value == null) { |
---|
717 | if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { |
---|
718 | // Lacking an ExtensionRegistry, we have no way to determine the |
---|
719 | // extension's real type, so we return a DynamicMessage. |
---|
720 | return DynamicMessage.getDefaultInstance(field.getMessageType()); |
---|
721 | } else { |
---|
722 | return field.getDefaultValue(); |
---|
723 | } |
---|
724 | } else { |
---|
725 | return value; |
---|
726 | } |
---|
727 | } else { |
---|
728 | return super.getField(field); |
---|
729 | } |
---|
730 | } |
---|
731 | |
---|
732 | @Override |
---|
733 | public int getRepeatedFieldCount(final FieldDescriptor field) { |
---|
734 | if (field.isExtension()) { |
---|
735 | verifyContainingType(field); |
---|
736 | return extensions.getRepeatedFieldCount(field); |
---|
737 | } else { |
---|
738 | return super.getRepeatedFieldCount(field); |
---|
739 | } |
---|
740 | } |
---|
741 | |
---|
742 | @Override |
---|
743 | public Object getRepeatedField(final FieldDescriptor field, |
---|
744 | final int index) { |
---|
745 | if (field.isExtension()) { |
---|
746 | verifyContainingType(field); |
---|
747 | return extensions.getRepeatedField(field, index); |
---|
748 | } else { |
---|
749 | return super.getRepeatedField(field, index); |
---|
750 | } |
---|
751 | } |
---|
752 | |
---|
753 | private void verifyContainingType(final FieldDescriptor field) { |
---|
754 | if (field.getContainingType() != getDescriptorForType()) { |
---|
755 | throw new IllegalArgumentException( |
---|
756 | "FieldDescriptor does not match message type."); |
---|
757 | } |
---|
758 | } |
---|
759 | } |
---|
760 | |
---|
761 | /** |
---|
762 | * Generated message builders for message types that contain extension ranges |
---|
763 | * subclass this. |
---|
764 | * |
---|
765 | * <p>This class implements type-safe accessors for extensions. They |
---|
766 | * implement all the same operations that you can do with normal fields -- |
---|
767 | * e.g. "get", "set", and "add" -- but for extensions. The extensions are |
---|
768 | * identified using instances of the class {@link GeneratedExtension}; the |
---|
769 | * protocol compiler generates a static instance of this class for every |
---|
770 | * extension in its input. Through the magic of generics, all is made |
---|
771 | * type-safe. |
---|
772 | * |
---|
773 | * <p>For example, imagine you have the {@code .proto} file: |
---|
774 | * |
---|
775 | * <pre> |
---|
776 | * option java_class = "MyProto"; |
---|
777 | * |
---|
778 | * message Foo { |
---|
779 | * extensions 1000 to max; |
---|
780 | * } |
---|
781 | * |
---|
782 | * extend Foo { |
---|
783 | * optional int32 bar; |
---|
784 | * } |
---|
785 | * </pre> |
---|
786 | * |
---|
787 | * <p>Then you might write code like: |
---|
788 | * |
---|
789 | * <pre> |
---|
790 | * MyProto.Foo foo = |
---|
791 | * MyProto.Foo.newBuilder() |
---|
792 | * .setExtension(MyProto.bar, 123) |
---|
793 | * .build(); |
---|
794 | * </pre> |
---|
795 | * |
---|
796 | * <p>See also {@link ExtendableMessage}. |
---|
797 | */ |
---|
798 | @SuppressWarnings("unchecked") |
---|
799 | public abstract static class ExtendableBuilder< |
---|
800 | MessageType extends ExtendableMessage, |
---|
801 | BuilderType extends ExtendableBuilder> |
---|
802 | extends Builder<BuilderType> |
---|
803 | implements ExtendableMessageOrBuilder<MessageType> { |
---|
804 | |
---|
805 | private FieldSet<FieldDescriptor> extensions = FieldSet.emptySet(); |
---|
806 | |
---|
807 | protected ExtendableBuilder() {} |
---|
808 | |
---|
809 | protected ExtendableBuilder( |
---|
810 | BuilderParent parent) { |
---|
811 | super(parent); |
---|
812 | } |
---|
813 | |
---|
814 | @Override |
---|
815 | public BuilderType clear() { |
---|
816 | extensions = FieldSet.emptySet(); |
---|
817 | return super.clear(); |
---|
818 | } |
---|
819 | |
---|
820 | // This is implemented here only to work around an apparent bug in the |
---|
821 | // Java compiler and/or build system. See bug #1898463. The mere presence |
---|
822 | // of this dummy clone() implementation makes it go away. |
---|
823 | @Override |
---|
824 | public BuilderType clone() { |
---|
825 | throw new UnsupportedOperationException( |
---|
826 | "This is supposed to be overridden by subclasses."); |
---|
827 | } |
---|
828 | |
---|
829 | private void ensureExtensionsIsMutable() { |
---|
830 | if (extensions.isImmutable()) { |
---|
831 | extensions = extensions.clone(); |
---|
832 | } |
---|
833 | } |
---|
834 | |
---|
835 | private void verifyExtensionContainingType( |
---|
836 | final GeneratedExtension<MessageType, ?> extension) { |
---|
837 | if (extension.getDescriptor().getContainingType() != |
---|
838 | getDescriptorForType()) { |
---|
839 | // This can only happen if someone uses unchecked operations. |
---|
840 | throw new IllegalArgumentException( |
---|
841 | "Extension is for type \"" + |
---|
842 | extension.getDescriptor().getContainingType().getFullName() + |
---|
843 | "\" which does not match message type \"" + |
---|
844 | getDescriptorForType().getFullName() + "\"."); |
---|
845 | } |
---|
846 | } |
---|
847 | |
---|
848 | /** Check if a singular extension is present. */ |
---|
849 | //@Override (Java 1.6 override semantics, but we must support 1.5) |
---|
850 | public final <Type> boolean hasExtension( |
---|
851 | final GeneratedExtension<MessageType, Type> extension) { |
---|
852 | verifyExtensionContainingType(extension); |
---|
853 | return extensions.hasField(extension.getDescriptor()); |
---|
854 | } |
---|
855 | |
---|
856 | /** Get the number of elements in a repeated extension. */ |
---|
857 | //@Override (Java 1.6 override semantics, but we must support 1.5) |
---|
858 | public final <Type> int getExtensionCount( |
---|
859 | final GeneratedExtension<MessageType, List<Type>> extension) { |
---|
860 | verifyExtensionContainingType(extension); |
---|
861 | final FieldDescriptor descriptor = extension.getDescriptor(); |
---|
862 | return extensions.getRepeatedFieldCount(descriptor); |
---|
863 | } |
---|
864 | |
---|
865 | /** Get the value of an extension. */ |
---|
866 | //@Override (Java 1.6 override semantics, but we must support 1.5) |
---|
867 | public final <Type> Type getExtension( |
---|
868 | final GeneratedExtension<MessageType, Type> extension) { |
---|
869 | verifyExtensionContainingType(extension); |
---|
870 | FieldDescriptor descriptor = extension.getDescriptor(); |
---|
871 | final Object value = extensions.getField(descriptor); |
---|
872 | if (value == null) { |
---|
873 | if (descriptor.isRepeated()) { |
---|
874 | return (Type) Collections.emptyList(); |
---|
875 | } else if (descriptor.getJavaType() == |
---|
876 | FieldDescriptor.JavaType.MESSAGE) { |
---|
877 | return (Type) extension.getMessageDefaultInstance(); |
---|
878 | } else { |
---|
879 | return (Type) extension.fromReflectionType( |
---|
880 | descriptor.getDefaultValue()); |
---|
881 | } |
---|
882 | } else { |
---|
883 | return (Type) extension.fromReflectionType(value); |
---|
884 | } |
---|
885 | } |
---|
886 | |
---|
887 | /** Get one element of a repeated extension. */ |
---|
888 | //@Override (Java 1.6 override semantics, but we must support 1.5) |
---|
889 | public final <Type> Type getExtension( |
---|
890 | final GeneratedExtension<MessageType, List<Type>> extension, |
---|
891 | final int index) { |
---|
892 | verifyExtensionContainingType(extension); |
---|
893 | FieldDescriptor descriptor = extension.getDescriptor(); |
---|
894 | return (Type) extension.singularFromReflectionType( |
---|
895 | extensions.getRepeatedField(descriptor, index)); |
---|
896 | } |
---|
897 | |
---|
898 | /** Set the value of an extension. */ |
---|
899 | public final <Type> BuilderType setExtension( |
---|
900 | final GeneratedExtension<MessageType, Type> extension, |
---|
901 | final Type value) { |
---|
902 | verifyExtensionContainingType(extension); |
---|
903 | ensureExtensionsIsMutable(); |
---|
904 | final FieldDescriptor descriptor = extension.getDescriptor(); |
---|
905 | extensions.setField(descriptor, extension.toReflectionType(value)); |
---|
906 | onChanged(); |
---|
907 | return (BuilderType) this; |
---|
908 | } |
---|
909 | |
---|
910 | /** Set the value of one element of a repeated extension. */ |
---|
911 | public final <Type> BuilderType setExtension( |
---|
912 | final GeneratedExtension<MessageType, List<Type>> extension, |
---|
913 | final int index, final Type value) { |
---|
914 | verifyExtensionContainingType(extension); |
---|
915 | ensureExtensionsIsMutable(); |
---|
916 | final FieldDescriptor descriptor = extension.getDescriptor(); |
---|
917 | extensions.setRepeatedField( |
---|
918 | descriptor, index, |
---|
919 | extension.singularToReflectionType(value)); |
---|
920 | onChanged(); |
---|
921 | return (BuilderType) this; |
---|
922 | } |
---|
923 | |
---|
924 | /** Append a value to a repeated extension. */ |
---|
925 | public final <Type> BuilderType addExtension( |
---|
926 | final GeneratedExtension<MessageType, List<Type>> extension, |
---|
927 | final Type value) { |
---|
928 | verifyExtensionContainingType(extension); |
---|
929 | ensureExtensionsIsMutable(); |
---|
930 | final FieldDescriptor descriptor = extension.getDescriptor(); |
---|
931 | extensions.addRepeatedField( |
---|
932 | descriptor, extension.singularToReflectionType(value)); |
---|
933 | onChanged(); |
---|
934 | return (BuilderType) this; |
---|
935 | } |
---|
936 | |
---|
937 | /** Clear an extension. */ |
---|
938 | public final <Type> BuilderType clearExtension( |
---|
939 | final GeneratedExtension<MessageType, ?> extension) { |
---|
940 | verifyExtensionContainingType(extension); |
---|
941 | ensureExtensionsIsMutable(); |
---|
942 | extensions.clearField(extension.getDescriptor()); |
---|
943 | onChanged(); |
---|
944 | return (BuilderType) this; |
---|
945 | } |
---|
946 | |
---|
947 | /** Called by subclasses to check if all extensions are initialized. */ |
---|
948 | protected boolean extensionsAreInitialized() { |
---|
949 | return extensions.isInitialized(); |
---|
950 | } |
---|
951 | |
---|
952 | /** |
---|
953 | * Called by the build code path to create a copy of the extensions for |
---|
954 | * building the message. |
---|
955 | */ |
---|
956 | private FieldSet<FieldDescriptor> buildExtensions() { |
---|
957 | extensions.makeImmutable(); |
---|
958 | return extensions; |
---|
959 | } |
---|
960 | |
---|
961 | @Override |
---|
962 | public boolean isInitialized() { |
---|
963 | return super.isInitialized() && extensionsAreInitialized(); |
---|
964 | } |
---|
965 | |
---|
966 | /** |
---|
967 | * Called by subclasses to parse an unknown field or an extension. |
---|
968 | * @return {@code true} unless the tag is an end-group tag. |
---|
969 | */ |
---|
970 | @Override |
---|
971 | protected boolean parseUnknownField( |
---|
972 | final CodedInputStream input, |
---|
973 | final UnknownFieldSet.Builder unknownFields, |
---|
974 | final ExtensionRegistryLite extensionRegistry, |
---|
975 | final int tag) throws IOException { |
---|
976 | return AbstractMessage.Builder.mergeFieldFrom( |
---|
977 | input, unknownFields, extensionRegistry, this, tag); |
---|
978 | } |
---|
979 | |
---|
980 | // --------------------------------------------------------------- |
---|
981 | // Reflection |
---|
982 | |
---|
983 | @Override |
---|
984 | public Map<FieldDescriptor, Object> getAllFields() { |
---|
985 | final Map<FieldDescriptor, Object> result = super.getAllFieldsMutable(); |
---|
986 | result.putAll(extensions.getAllFields()); |
---|
987 | return Collections.unmodifiableMap(result); |
---|
988 | } |
---|
989 | |
---|
990 | @Override |
---|
991 | public Object getField(final FieldDescriptor field) { |
---|
992 | if (field.isExtension()) { |
---|
993 | verifyContainingType(field); |
---|
994 | final Object value = extensions.getField(field); |
---|
995 | if (value == null) { |
---|
996 | if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { |
---|
997 | // Lacking an ExtensionRegistry, we have no way to determine the |
---|
998 | // extension's real type, so we return a DynamicMessage. |
---|
999 | return DynamicMessage.getDefaultInstance(field.getMessageType()); |
---|
1000 | } else { |
---|
1001 | return field.getDefaultValue(); |
---|
1002 | } |
---|
1003 | } else { |
---|
1004 | return value; |
---|
1005 | } |
---|
1006 | } else { |
---|
1007 | return super.getField(field); |
---|
1008 | } |
---|
1009 | } |
---|
1010 | |
---|
1011 | @Override |
---|
1012 | public int getRepeatedFieldCount(final FieldDescriptor field) { |
---|
1013 | if (field.isExtension()) { |
---|
1014 | verifyContainingType(field); |
---|
1015 | return extensions.getRepeatedFieldCount(field); |
---|
1016 | } else { |
---|
1017 | return super.getRepeatedFieldCount(field); |
---|
1018 | } |
---|
1019 | } |
---|
1020 | |
---|
1021 | @Override |
---|
1022 | public Object getRepeatedField(final FieldDescriptor field, |
---|
1023 | final int index) { |
---|
1024 | if (field.isExtension()) { |
---|
1025 | verifyContainingType(field); |
---|
1026 | return extensions.getRepeatedField(field, index); |
---|
1027 | } else { |
---|
1028 | return super.getRepeatedField(field, index); |
---|
1029 | } |
---|
1030 | } |
---|
1031 | |
---|
1032 | @Override |
---|
1033 | public boolean hasField(final FieldDescriptor field) { |
---|
1034 | if (field.isExtension()) { |
---|
1035 | verifyContainingType(field); |
---|
1036 | return extensions.hasField(field); |
---|
1037 | } else { |
---|
1038 | return super.hasField(field); |
---|
1039 | } |
---|
1040 | } |
---|
1041 | |
---|
1042 | @Override |
---|
1043 | public BuilderType setField(final FieldDescriptor field, |
---|
1044 | final Object value) { |
---|
1045 | if (field.isExtension()) { |
---|
1046 | verifyContainingType(field); |
---|
1047 | ensureExtensionsIsMutable(); |
---|
1048 | extensions.setField(field, value); |
---|
1049 | onChanged(); |
---|
1050 | return (BuilderType) this; |
---|
1051 | } else { |
---|
1052 | return super.setField(field, value); |
---|
1053 | } |
---|
1054 | } |
---|
1055 | |
---|
1056 | @Override |
---|
1057 | public BuilderType clearField(final FieldDescriptor field) { |
---|
1058 | if (field.isExtension()) { |
---|
1059 | verifyContainingType(field); |
---|
1060 | ensureExtensionsIsMutable(); |
---|
1061 | extensions.clearField(field); |
---|
1062 | onChanged(); |
---|
1063 | return (BuilderType) this; |
---|
1064 | } else { |
---|
1065 | return super.clearField(field); |
---|
1066 | } |
---|
1067 | } |
---|
1068 | |
---|
1069 | @Override |
---|
1070 | public BuilderType setRepeatedField(final FieldDescriptor field, |
---|
1071 | final int index, final Object value) { |
---|
1072 | if (field.isExtension()) { |
---|
1073 | verifyContainingType(field); |
---|
1074 | ensureExtensionsIsMutable(); |
---|
1075 | extensions.setRepeatedField(field, index, value); |
---|
1076 | onChanged(); |
---|
1077 | return (BuilderType) this; |
---|
1078 | } else { |
---|
1079 | return super.setRepeatedField(field, index, value); |
---|
1080 | } |
---|
1081 | } |
---|
1082 | |
---|
1083 | @Override |
---|
1084 | public BuilderType addRepeatedField(final FieldDescriptor field, |
---|
1085 | final Object value) { |
---|
1086 | if (field.isExtension()) { |
---|
1087 | verifyContainingType(field); |
---|
1088 | ensureExtensionsIsMutable(); |
---|
1089 | extensions.addRepeatedField(field, value); |
---|
1090 | onChanged(); |
---|
1091 | return (BuilderType) this; |
---|
1092 | } else { |
---|
1093 | return super.addRepeatedField(field, value); |
---|
1094 | } |
---|
1095 | } |
---|
1096 | |
---|
1097 | protected final void mergeExtensionFields(final ExtendableMessage other) { |
---|
1098 | ensureExtensionsIsMutable(); |
---|
1099 | extensions.mergeFrom(other.extensions); |
---|
1100 | onChanged(); |
---|
1101 | } |
---|
1102 | |
---|
1103 | private void verifyContainingType(final FieldDescriptor field) { |
---|
1104 | if (field.getContainingType() != getDescriptorForType()) { |
---|
1105 | throw new IllegalArgumentException( |
---|
1106 | "FieldDescriptor does not match message type."); |
---|
1107 | } |
---|
1108 | } |
---|
1109 | } |
---|
1110 | |
---|
1111 | // ----------------------------------------------------------------- |
---|
1112 | |
---|
1113 | /** |
---|
1114 | * Gets the descriptor for an extension. The implementation depends on whether |
---|
1115 | * the extension is scoped in the top level of a file or scoped in a Message. |
---|
1116 | */ |
---|
1117 | private static interface ExtensionDescriptorRetriever { |
---|
1118 | FieldDescriptor getDescriptor(); |
---|
1119 | } |
---|
1120 | |
---|
1121 | /** For use by generated code only. */ |
---|
1122 | public static <ContainingType extends Message, Type> |
---|
1123 | GeneratedExtension<ContainingType, Type> |
---|
1124 | newMessageScopedGeneratedExtension(final Message scope, |
---|
1125 | final int descriptorIndex, |
---|
1126 | final Class singularType, |
---|
1127 | final Message defaultInstance) { |
---|
1128 | // For extensions scoped within a Message, we use the Message to resolve |
---|
1129 | // the outer class's descriptor, from which the extension descriptor is |
---|
1130 | // obtained. |
---|
1131 | return new GeneratedExtension<ContainingType, Type>( |
---|
1132 | new ExtensionDescriptorRetriever() { |
---|
1133 | //@Override (Java 1.6 override semantics, but we must support 1.5) |
---|
1134 | public FieldDescriptor getDescriptor() { |
---|
1135 | return scope.getDescriptorForType().getExtensions() |
---|
1136 | .get(descriptorIndex); |
---|
1137 | } |
---|
1138 | }, |
---|
1139 | singularType, |
---|
1140 | defaultInstance); |
---|
1141 | } |
---|
1142 | |
---|
1143 | /** For use by generated code only. */ |
---|
1144 | public static <ContainingType extends Message, Type> |
---|
1145 | GeneratedExtension<ContainingType, Type> |
---|
1146 | newFileScopedGeneratedExtension(final Class singularType, |
---|
1147 | final Message defaultInstance) { |
---|
1148 | // For extensions scoped within a file, we rely on the outer class's |
---|
1149 | // static initializer to call internalInit() on the extension when the |
---|
1150 | // descriptor is available. |
---|
1151 | return new GeneratedExtension<ContainingType, Type>( |
---|
1152 | null, // ExtensionDescriptorRetriever is initialized in internalInit(); |
---|
1153 | singularType, |
---|
1154 | defaultInstance); |
---|
1155 | } |
---|
1156 | |
---|
1157 | /** |
---|
1158 | * Type used to represent generated extensions. The protocol compiler |
---|
1159 | * generates a static singleton instance of this class for each extension. |
---|
1160 | * |
---|
1161 | * <p>For example, imagine you have the {@code .proto} file: |
---|
1162 | * |
---|
1163 | * <pre> |
---|
1164 | * option java_class = "MyProto"; |
---|
1165 | * |
---|
1166 | * message Foo { |
---|
1167 | * extensions 1000 to max; |
---|
1168 | * } |
---|
1169 | * |
---|
1170 | * extend Foo { |
---|
1171 | * optional int32 bar; |
---|
1172 | * } |
---|
1173 | * </pre> |
---|
1174 | * |
---|
1175 | * <p>Then, {@code MyProto.Foo.bar} has type |
---|
1176 | * {@code GeneratedExtension<MyProto.Foo, Integer>}. |
---|
1177 | * |
---|
1178 | * <p>In general, users should ignore the details of this type, and simply use |
---|
1179 | * these static singletons as parameters to the extension accessors defined |
---|
1180 | * in {@link ExtendableMessage} and {@link ExtendableBuilder}. |
---|
1181 | */ |
---|
1182 | public static final class GeneratedExtension< |
---|
1183 | ContainingType extends Message, Type> { |
---|
1184 | // TODO(kenton): Find ways to avoid using Java reflection within this |
---|
1185 | // class. Also try to avoid suppressing unchecked warnings. |
---|
1186 | |
---|
1187 | // We can't always initialize the descriptor of a GeneratedExtension when |
---|
1188 | // we first construct it due to initialization order difficulties (namely, |
---|
1189 | // the descriptor may not have been constructed yet, since it is often |
---|
1190 | // constructed by the initializer of a separate module). |
---|
1191 | // |
---|
1192 | // In the case of nested extensions, we initialize the |
---|
1193 | // ExtensionDescriptorRetriever with an instance that uses the scoping |
---|
1194 | // Message's default instance to retrieve the extension's descriptor. |
---|
1195 | // |
---|
1196 | // In the case of non-nested extensions, we initialize the |
---|
1197 | // ExtensionDescriptorRetriever to null and rely on the outer class's static |
---|
1198 | // initializer to call internalInit() after the descriptor has been parsed. |
---|
1199 | private GeneratedExtension(ExtensionDescriptorRetriever descriptorRetriever, |
---|
1200 | Class singularType, |
---|
1201 | Message messageDefaultInstance) { |
---|
1202 | if (Message.class.isAssignableFrom(singularType) && |
---|
1203 | !singularType.isInstance(messageDefaultInstance)) { |
---|
1204 | throw new IllegalArgumentException( |
---|
1205 | "Bad messageDefaultInstance for " + singularType.getName()); |
---|
1206 | } |
---|
1207 | this.descriptorRetriever = descriptorRetriever; |
---|
1208 | this.singularType = singularType; |
---|
1209 | this.messageDefaultInstance = messageDefaultInstance; |
---|
1210 | |
---|
1211 | if (ProtocolMessageEnum.class.isAssignableFrom(singularType)) { |
---|
1212 | this.enumValueOf = getMethodOrDie(singularType, "valueOf", |
---|
1213 | EnumValueDescriptor.class); |
---|
1214 | this.enumGetValueDescriptor = |
---|
1215 | getMethodOrDie(singularType, "getValueDescriptor"); |
---|
1216 | } else { |
---|
1217 | this.enumValueOf = null; |
---|
1218 | this.enumGetValueDescriptor = null; |
---|
1219 | } |
---|
1220 | } |
---|
1221 | |
---|
1222 | /** For use by generated code only. */ |
---|
1223 | public void internalInit(final FieldDescriptor descriptor) { |
---|
1224 | if (descriptorRetriever != null) { |
---|
1225 | throw new IllegalStateException("Already initialized."); |
---|
1226 | } |
---|
1227 | descriptorRetriever = new ExtensionDescriptorRetriever() { |
---|
1228 | //@Override (Java 1.6 override semantics, but we must support 1.5) |
---|
1229 | public FieldDescriptor getDescriptor() { |
---|
1230 | return descriptor; |
---|
1231 | } |
---|
1232 | }; |
---|
1233 | } |
---|
1234 | |
---|
1235 | private ExtensionDescriptorRetriever descriptorRetriever; |
---|
1236 | private final Class singularType; |
---|
1237 | private final Message messageDefaultInstance; |
---|
1238 | private final Method enumValueOf; |
---|
1239 | private final Method enumGetValueDescriptor; |
---|
1240 | |
---|
1241 | public FieldDescriptor getDescriptor() { |
---|
1242 | if (descriptorRetriever == null) { |
---|
1243 | throw new IllegalStateException( |
---|
1244 | "getDescriptor() called before internalInit()"); |
---|
1245 | } |
---|
1246 | return descriptorRetriever.getDescriptor(); |
---|
1247 | } |
---|
1248 | |
---|
1249 | /** |
---|
1250 | * If the extension is an embedded message or group, returns the default |
---|
1251 | * instance of the message. |
---|
1252 | */ |
---|
1253 | public Message getMessageDefaultInstance() { |
---|
1254 | return messageDefaultInstance; |
---|
1255 | } |
---|
1256 | |
---|
1257 | /** |
---|
1258 | * Convert from the type used by the reflection accessors to the type used |
---|
1259 | * by native accessors. E.g., for enums, the reflection accessors use |
---|
1260 | * EnumValueDescriptors but the native accessors use the generated enum |
---|
1261 | * type. |
---|
1262 | */ |
---|
1263 | @SuppressWarnings("unchecked") |
---|
1264 | private Object fromReflectionType(final Object value) { |
---|
1265 | FieldDescriptor descriptor = getDescriptor(); |
---|
1266 | if (descriptor.isRepeated()) { |
---|
1267 | if (descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE || |
---|
1268 | descriptor.getJavaType() == FieldDescriptor.JavaType.ENUM) { |
---|
1269 | // Must convert the whole list. |
---|
1270 | final List result = new ArrayList(); |
---|
1271 | for (final Object element : (List) value) { |
---|
1272 | result.add(singularFromReflectionType(element)); |
---|
1273 | } |
---|
1274 | return result; |
---|
1275 | } else { |
---|
1276 | return value; |
---|
1277 | } |
---|
1278 | } else { |
---|
1279 | return singularFromReflectionType(value); |
---|
1280 | } |
---|
1281 | } |
---|
1282 | |
---|
1283 | /** |
---|
1284 | * Like {@link #fromReflectionType(Object)}, but if the type is a repeated |
---|
1285 | * type, this converts a single element. |
---|
1286 | */ |
---|
1287 | private Object singularFromReflectionType(final Object value) { |
---|
1288 | FieldDescriptor descriptor = getDescriptor(); |
---|
1289 | switch (descriptor.getJavaType()) { |
---|
1290 | case MESSAGE: |
---|
1291 | if (singularType.isInstance(value)) { |
---|
1292 | return value; |
---|
1293 | } else { |
---|
1294 | // It seems the copy of the embedded message stored inside the |
---|
1295 | // extended message is not of the exact type the user was |
---|
1296 | // expecting. This can happen if a user defines a |
---|
1297 | // GeneratedExtension manually and gives it a different type. |
---|
1298 | // This should not happen in normal use. But, to be nice, we'll |
---|
1299 | // copy the message to whatever type the caller was expecting. |
---|
1300 | return messageDefaultInstance.newBuilderForType() |
---|
1301 | .mergeFrom((Message) value).build(); |
---|
1302 | } |
---|
1303 | case ENUM: |
---|
1304 | return invokeOrDie(enumValueOf, null, (EnumValueDescriptor) value); |
---|
1305 | default: |
---|
1306 | return value; |
---|
1307 | } |
---|
1308 | } |
---|
1309 | |
---|
1310 | /** |
---|
1311 | * Convert from the type used by the native accessors to the type used |
---|
1312 | * by reflection accessors. E.g., for enums, the reflection accessors use |
---|
1313 | * EnumValueDescriptors but the native accessors use the generated enum |
---|
1314 | * type. |
---|
1315 | */ |
---|
1316 | @SuppressWarnings("unchecked") |
---|
1317 | private Object toReflectionType(final Object value) { |
---|
1318 | FieldDescriptor descriptor = getDescriptor(); |
---|
1319 | if (descriptor.isRepeated()) { |
---|
1320 | if (descriptor.getJavaType() == FieldDescriptor.JavaType.ENUM) { |
---|
1321 | // Must convert the whole list. |
---|
1322 | final List result = new ArrayList(); |
---|
1323 | for (final Object element : (List) value) { |
---|
1324 | result.add(singularToReflectionType(element)); |
---|
1325 | } |
---|
1326 | return result; |
---|
1327 | } else { |
---|
1328 | return value; |
---|
1329 | } |
---|
1330 | } else { |
---|
1331 | return singularToReflectionType(value); |
---|
1332 | } |
---|
1333 | } |
---|
1334 | |
---|
1335 | /** |
---|
1336 | * Like {@link #toReflectionType(Object)}, but if the type is a repeated |
---|
1337 | * type, this converts a single element. |
---|
1338 | */ |
---|
1339 | private Object singularToReflectionType(final Object value) { |
---|
1340 | FieldDescriptor descriptor = getDescriptor(); |
---|
1341 | switch (descriptor.getJavaType()) { |
---|
1342 | case ENUM: |
---|
1343 | return invokeOrDie(enumGetValueDescriptor, value); |
---|
1344 | default: |
---|
1345 | return value; |
---|
1346 | } |
---|
1347 | } |
---|
1348 | } |
---|
1349 | |
---|
1350 | // ================================================================= |
---|
1351 | |
---|
1352 | /** Calls Class.getMethod and throws a RuntimeException if it fails. */ |
---|
1353 | @SuppressWarnings("unchecked") |
---|
1354 | private static Method getMethodOrDie( |
---|
1355 | final Class clazz, final String name, final Class... params) { |
---|
1356 | try { |
---|
1357 | return clazz.getMethod(name, params); |
---|
1358 | } catch (NoSuchMethodException e) { |
---|
1359 | throw new RuntimeException( |
---|
1360 | "Generated message class \"" + clazz.getName() + |
---|
1361 | "\" missing method \"" + name + "\".", e); |
---|
1362 | } |
---|
1363 | } |
---|
1364 | |
---|
1365 | /** Calls invoke and throws a RuntimeException if it fails. */ |
---|
1366 | private static Object invokeOrDie( |
---|
1367 | final Method method, final Object object, final Object... params) { |
---|
1368 | try { |
---|
1369 | return method.invoke(object, params); |
---|
1370 | } catch (IllegalAccessException e) { |
---|
1371 | throw new RuntimeException( |
---|
1372 | "Couldn't use Java reflection to implement protocol message " + |
---|
1373 | "reflection.", e); |
---|
1374 | } catch (InvocationTargetException e) { |
---|
1375 | final Throwable cause = e.getCause(); |
---|
1376 | if (cause instanceof RuntimeException) { |
---|
1377 | throw (RuntimeException) cause; |
---|
1378 | } else if (cause instanceof Error) { |
---|
1379 | throw (Error) cause; |
---|
1380 | } else { |
---|
1381 | throw new RuntimeException( |
---|
1382 | "Unexpected exception thrown by generated accessor method.", cause); |
---|
1383 | } |
---|
1384 | } |
---|
1385 | } |
---|
1386 | |
---|
1387 | /** |
---|
1388 | * Users should ignore this class. This class provides the implementation |
---|
1389 | * with access to the fields of a message object using Java reflection. |
---|
1390 | */ |
---|
1391 | public static final class FieldAccessorTable { |
---|
1392 | |
---|
1393 | /** |
---|
1394 | * Construct a FieldAccessorTable for a particular message class. Only |
---|
1395 | * one FieldAccessorTable should ever be constructed per class. |
---|
1396 | * |
---|
1397 | * @param descriptor The type's descriptor. |
---|
1398 | * @param camelCaseNames The camelcase names of all fields in the message. |
---|
1399 | * These are used to derive the accessor method names. |
---|
1400 | * @param messageClass The message type. |
---|
1401 | * @param builderClass The builder type. |
---|
1402 | */ |
---|
1403 | public FieldAccessorTable( |
---|
1404 | final Descriptor descriptor, |
---|
1405 | final String[] camelCaseNames, |
---|
1406 | final Class<? extends GeneratedMessage> messageClass, |
---|
1407 | final Class<? extends Builder> builderClass) { |
---|
1408 | this.descriptor = descriptor; |
---|
1409 | fields = new FieldAccessor[descriptor.getFields().size()]; |
---|
1410 | |
---|
1411 | for (int i = 0; i < fields.length; i++) { |
---|
1412 | final FieldDescriptor field = descriptor.getFields().get(i); |
---|
1413 | if (field.isRepeated()) { |
---|
1414 | if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { |
---|
1415 | fields[i] = new RepeatedMessageFieldAccessor( |
---|
1416 | field, camelCaseNames[i], messageClass, builderClass); |
---|
1417 | } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) { |
---|
1418 | fields[i] = new RepeatedEnumFieldAccessor( |
---|
1419 | field, camelCaseNames[i], messageClass, builderClass); |
---|
1420 | } else { |
---|
1421 | fields[i] = new RepeatedFieldAccessor( |
---|
1422 | field, camelCaseNames[i], messageClass, builderClass); |
---|
1423 | } |
---|
1424 | } else { |
---|
1425 | if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { |
---|
1426 | fields[i] = new SingularMessageFieldAccessor( |
---|
1427 | field, camelCaseNames[i], messageClass, builderClass); |
---|
1428 | } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) { |
---|
1429 | fields[i] = new SingularEnumFieldAccessor( |
---|
1430 | field, camelCaseNames[i], messageClass, builderClass); |
---|
1431 | } else { |
---|
1432 | fields[i] = new SingularFieldAccessor( |
---|
1433 | field, camelCaseNames[i], messageClass, builderClass); |
---|
1434 | } |
---|
1435 | } |
---|
1436 | } |
---|
1437 | } |
---|
1438 | |
---|
1439 | private final Descriptor descriptor; |
---|
1440 | private final FieldAccessor[] fields; |
---|
1441 | |
---|
1442 | /** Get the FieldAccessor for a particular field. */ |
---|
1443 | private FieldAccessor getField(final FieldDescriptor field) { |
---|
1444 | if (field.getContainingType() != descriptor) { |
---|
1445 | throw new IllegalArgumentException( |
---|
1446 | "FieldDescriptor does not match message type."); |
---|
1447 | } else if (field.isExtension()) { |
---|
1448 | // If this type had extensions, it would subclass ExtendableMessage, |
---|
1449 | // which overrides the reflection interface to handle extensions. |
---|
1450 | throw new IllegalArgumentException( |
---|
1451 | "This type does not have extensions."); |
---|
1452 | } |
---|
1453 | return fields[field.getIndex()]; |
---|
1454 | } |
---|
1455 | |
---|
1456 | /** |
---|
1457 | * Abstract interface that provides access to a single field. This is |
---|
1458 | * implemented differently depending on the field type and cardinality. |
---|
1459 | */ |
---|
1460 | private interface FieldAccessor { |
---|
1461 | Object get(GeneratedMessage message); |
---|
1462 | Object get(GeneratedMessage.Builder builder); |
---|
1463 | void set(Builder builder, Object value); |
---|
1464 | Object getRepeated(GeneratedMessage message, int index); |
---|
1465 | Object getRepeated(GeneratedMessage.Builder builder, int index); |
---|
1466 | void setRepeated(Builder builder, |
---|
1467 | int index, Object value); |
---|
1468 | void addRepeated(Builder builder, Object value); |
---|
1469 | boolean has(GeneratedMessage message); |
---|
1470 | boolean has(GeneratedMessage.Builder builder); |
---|
1471 | int getRepeatedCount(GeneratedMessage message); |
---|
1472 | int getRepeatedCount(GeneratedMessage.Builder builder); |
---|
1473 | void clear(Builder builder); |
---|
1474 | Message.Builder newBuilder(); |
---|
1475 | } |
---|
1476 | |
---|
1477 | // --------------------------------------------------------------- |
---|
1478 | |
---|
1479 | private static class SingularFieldAccessor implements FieldAccessor { |
---|
1480 | SingularFieldAccessor( |
---|
1481 | final FieldDescriptor descriptor, final String camelCaseName, |
---|
1482 | final Class<? extends GeneratedMessage> messageClass, |
---|
1483 | final Class<? extends Builder> builderClass) { |
---|
1484 | getMethod = getMethodOrDie(messageClass, "get" + camelCaseName); |
---|
1485 | getMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName); |
---|
1486 | type = getMethod.getReturnType(); |
---|
1487 | setMethod = getMethodOrDie(builderClass, "set" + camelCaseName, type); |
---|
1488 | hasMethod = |
---|
1489 | getMethodOrDie(messageClass, "has" + camelCaseName); |
---|
1490 | hasMethodBuilder = |
---|
1491 | getMethodOrDie(builderClass, "has" + camelCaseName); |
---|
1492 | clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName); |
---|
1493 | } |
---|
1494 | |
---|
1495 | // Note: We use Java reflection to call public methods rather than |
---|
1496 | // access private fields directly as this avoids runtime security |
---|
1497 | // checks. |
---|
1498 | protected final Class<?> type; |
---|
1499 | protected final Method getMethod; |
---|
1500 | protected final Method getMethodBuilder; |
---|
1501 | protected final Method setMethod; |
---|
1502 | protected final Method hasMethod; |
---|
1503 | protected final Method hasMethodBuilder; |
---|
1504 | protected final Method clearMethod; |
---|
1505 | |
---|
1506 | public Object get(final GeneratedMessage message) { |
---|
1507 | return invokeOrDie(getMethod, message); |
---|
1508 | } |
---|
1509 | public Object get(GeneratedMessage.Builder builder) { |
---|
1510 | return invokeOrDie(getMethodBuilder, builder); |
---|
1511 | } |
---|
1512 | public void set(final Builder builder, final Object value) { |
---|
1513 | invokeOrDie(setMethod, builder, value); |
---|
1514 | } |
---|
1515 | public Object getRepeated(final GeneratedMessage message, |
---|
1516 | final int index) { |
---|
1517 | throw new UnsupportedOperationException( |
---|
1518 | "getRepeatedField() called on a singular field."); |
---|
1519 | } |
---|
1520 | public Object getRepeated(GeneratedMessage.Builder builder, int index) { |
---|
1521 | throw new UnsupportedOperationException( |
---|
1522 | "getRepeatedField() called on a singular field."); |
---|
1523 | } |
---|
1524 | public void setRepeated(final Builder builder, |
---|
1525 | final int index, final Object value) { |
---|
1526 | throw new UnsupportedOperationException( |
---|
1527 | "setRepeatedField() called on a singular field."); |
---|
1528 | } |
---|
1529 | public void addRepeated(final Builder builder, final Object value) { |
---|
1530 | throw new UnsupportedOperationException( |
---|
1531 | "addRepeatedField() called on a singular field."); |
---|
1532 | } |
---|
1533 | public boolean has(final GeneratedMessage message) { |
---|
1534 | return (Boolean) invokeOrDie(hasMethod, message); |
---|
1535 | } |
---|
1536 | public boolean has(GeneratedMessage.Builder builder) { |
---|
1537 | return (Boolean) invokeOrDie(hasMethodBuilder, builder); |
---|
1538 | } |
---|
1539 | public int getRepeatedCount(final GeneratedMessage message) { |
---|
1540 | throw new UnsupportedOperationException( |
---|
1541 | "getRepeatedFieldSize() called on a singular field."); |
---|
1542 | } |
---|
1543 | public int getRepeatedCount(GeneratedMessage.Builder builder) { |
---|
1544 | throw new UnsupportedOperationException( |
---|
1545 | "getRepeatedFieldSize() called on a singular field."); |
---|
1546 | } |
---|
1547 | public void clear(final Builder builder) { |
---|
1548 | invokeOrDie(clearMethod, builder); |
---|
1549 | } |
---|
1550 | public Message.Builder newBuilder() { |
---|
1551 | throw new UnsupportedOperationException( |
---|
1552 | "newBuilderForField() called on a non-Message type."); |
---|
1553 | } |
---|
1554 | } |
---|
1555 | |
---|
1556 | private static class RepeatedFieldAccessor implements FieldAccessor { |
---|
1557 | protected final Class type; |
---|
1558 | protected final Method getMethod; |
---|
1559 | protected final Method getMethodBuilder; |
---|
1560 | protected final Method getRepeatedMethod; |
---|
1561 | protected final Method getRepeatedMethodBuilder; |
---|
1562 | protected final Method setRepeatedMethod; |
---|
1563 | protected final Method addRepeatedMethod; |
---|
1564 | protected final Method getCountMethod; |
---|
1565 | protected final Method getCountMethodBuilder; |
---|
1566 | protected final Method clearMethod; |
---|
1567 | |
---|
1568 | RepeatedFieldAccessor( |
---|
1569 | final FieldDescriptor descriptor, final String camelCaseName, |
---|
1570 | final Class<? extends GeneratedMessage> messageClass, |
---|
1571 | final Class<? extends Builder> builderClass) { |
---|
1572 | getMethod = getMethodOrDie(messageClass, |
---|
1573 | "get" + camelCaseName + "List"); |
---|
1574 | getMethodBuilder = getMethodOrDie(builderClass, |
---|
1575 | "get" + camelCaseName + "List"); |
---|
1576 | |
---|
1577 | |
---|
1578 | getRepeatedMethod = |
---|
1579 | getMethodOrDie(messageClass, "get" + camelCaseName, Integer.TYPE); |
---|
1580 | getRepeatedMethodBuilder = |
---|
1581 | getMethodOrDie(builderClass, "get" + camelCaseName, Integer.TYPE); |
---|
1582 | type = getRepeatedMethod.getReturnType(); |
---|
1583 | setRepeatedMethod = |
---|
1584 | getMethodOrDie(builderClass, "set" + camelCaseName, |
---|
1585 | Integer.TYPE, type); |
---|
1586 | addRepeatedMethod = |
---|
1587 | getMethodOrDie(builderClass, "add" + camelCaseName, type); |
---|
1588 | getCountMethod = |
---|
1589 | getMethodOrDie(messageClass, "get" + camelCaseName + "Count"); |
---|
1590 | getCountMethodBuilder = |
---|
1591 | getMethodOrDie(builderClass, "get" + camelCaseName + "Count"); |
---|
1592 | |
---|
1593 | clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName); |
---|
1594 | } |
---|
1595 | |
---|
1596 | public Object get(final GeneratedMessage message) { |
---|
1597 | return invokeOrDie(getMethod, message); |
---|
1598 | } |
---|
1599 | public Object get(GeneratedMessage.Builder builder) { |
---|
1600 | return invokeOrDie(getMethodBuilder, builder); |
---|
1601 | } |
---|
1602 | public void set(final Builder builder, final Object value) { |
---|
1603 | // Add all the elements individually. This serves two purposes: |
---|
1604 | // 1) Verifies that each element has the correct type. |
---|
1605 | // 2) Insures that the caller cannot modify the list later on and |
---|
1606 | // have the modifications be reflected in the message. |
---|
1607 | clear(builder); |
---|
1608 | for (final Object element : (List<?>) value) { |
---|
1609 | addRepeated(builder, element); |
---|
1610 | } |
---|
1611 | } |
---|
1612 | public Object getRepeated(final GeneratedMessage message, |
---|
1613 | final int index) { |
---|
1614 | return invokeOrDie(getRepeatedMethod, message, index); |
---|
1615 | } |
---|
1616 | public Object getRepeated(GeneratedMessage.Builder builder, int index) { |
---|
1617 | return invokeOrDie(getRepeatedMethodBuilder, builder, index); |
---|
1618 | } |
---|
1619 | public void setRepeated(final Builder builder, |
---|
1620 | final int index, final Object value) { |
---|
1621 | invokeOrDie(setRepeatedMethod, builder, index, value); |
---|
1622 | } |
---|
1623 | public void addRepeated(final Builder builder, final Object value) { |
---|
1624 | invokeOrDie(addRepeatedMethod, builder, value); |
---|
1625 | } |
---|
1626 | public boolean has(final GeneratedMessage message) { |
---|
1627 | throw new UnsupportedOperationException( |
---|
1628 | "hasField() called on a singular field."); |
---|
1629 | } |
---|
1630 | public boolean has(GeneratedMessage.Builder builder) { |
---|
1631 | throw new UnsupportedOperationException( |
---|
1632 | "hasField() called on a singular field."); |
---|
1633 | } |
---|
1634 | public int getRepeatedCount(final GeneratedMessage message) { |
---|
1635 | return (Integer) invokeOrDie(getCountMethod, message); |
---|
1636 | } |
---|
1637 | public int getRepeatedCount(GeneratedMessage.Builder builder) { |
---|
1638 | return (Integer) invokeOrDie(getCountMethodBuilder, builder); |
---|
1639 | } |
---|
1640 | public void clear(final Builder builder) { |
---|
1641 | invokeOrDie(clearMethod, builder); |
---|
1642 | } |
---|
1643 | public Message.Builder newBuilder() { |
---|
1644 | throw new UnsupportedOperationException( |
---|
1645 | "newBuilderForField() called on a non-Message type."); |
---|
1646 | } |
---|
1647 | } |
---|
1648 | |
---|
1649 | // --------------------------------------------------------------- |
---|
1650 | |
---|
1651 | private static final class SingularEnumFieldAccessor |
---|
1652 | extends SingularFieldAccessor { |
---|
1653 | SingularEnumFieldAccessor( |
---|
1654 | final FieldDescriptor descriptor, final String camelCaseName, |
---|
1655 | final Class<? extends GeneratedMessage> messageClass, |
---|
1656 | final Class<? extends Builder> builderClass) { |
---|
1657 | super(descriptor, camelCaseName, messageClass, builderClass); |
---|
1658 | |
---|
1659 | valueOfMethod = getMethodOrDie(type, "valueOf", |
---|
1660 | EnumValueDescriptor.class); |
---|
1661 | getValueDescriptorMethod = |
---|
1662 | getMethodOrDie(type, "getValueDescriptor"); |
---|
1663 | } |
---|
1664 | |
---|
1665 | private Method valueOfMethod; |
---|
1666 | private Method getValueDescriptorMethod; |
---|
1667 | |
---|
1668 | @Override |
---|
1669 | public Object get(final GeneratedMessage message) { |
---|
1670 | return invokeOrDie(getValueDescriptorMethod, super.get(message)); |
---|
1671 | } |
---|
1672 | |
---|
1673 | @Override |
---|
1674 | public Object get(final GeneratedMessage.Builder builder) { |
---|
1675 | return invokeOrDie(getValueDescriptorMethod, super.get(builder)); |
---|
1676 | } |
---|
1677 | |
---|
1678 | @Override |
---|
1679 | public void set(final Builder builder, final Object value) { |
---|
1680 | super.set(builder, invokeOrDie(valueOfMethod, null, value)); |
---|
1681 | } |
---|
1682 | } |
---|
1683 | |
---|
1684 | private static final class RepeatedEnumFieldAccessor |
---|
1685 | extends RepeatedFieldAccessor { |
---|
1686 | RepeatedEnumFieldAccessor( |
---|
1687 | final FieldDescriptor descriptor, final String camelCaseName, |
---|
1688 | final Class<? extends GeneratedMessage> messageClass, |
---|
1689 | final Class<? extends Builder> builderClass) { |
---|
1690 | super(descriptor, camelCaseName, messageClass, builderClass); |
---|
1691 | |
---|
1692 | valueOfMethod = getMethodOrDie(type, "valueOf", |
---|
1693 | EnumValueDescriptor.class); |
---|
1694 | getValueDescriptorMethod = |
---|
1695 | getMethodOrDie(type, "getValueDescriptor"); |
---|
1696 | } |
---|
1697 | |
---|
1698 | private final Method valueOfMethod; |
---|
1699 | private final Method getValueDescriptorMethod; |
---|
1700 | |
---|
1701 | @Override |
---|
1702 | @SuppressWarnings("unchecked") |
---|
1703 | public Object get(final GeneratedMessage message) { |
---|
1704 | final List newList = new ArrayList(); |
---|
1705 | for (final Object element : (List) super.get(message)) { |
---|
1706 | newList.add(invokeOrDie(getValueDescriptorMethod, element)); |
---|
1707 | } |
---|
1708 | return Collections.unmodifiableList(newList); |
---|
1709 | } |
---|
1710 | |
---|
1711 | @Override |
---|
1712 | @SuppressWarnings("unchecked") |
---|
1713 | public Object get(final GeneratedMessage.Builder builder) { |
---|
1714 | final List newList = new ArrayList(); |
---|
1715 | for (final Object element : (List) super.get(builder)) { |
---|
1716 | newList.add(invokeOrDie(getValueDescriptorMethod, element)); |
---|
1717 | } |
---|
1718 | return Collections.unmodifiableList(newList); |
---|
1719 | } |
---|
1720 | |
---|
1721 | @Override |
---|
1722 | public Object getRepeated(final GeneratedMessage message, |
---|
1723 | final int index) { |
---|
1724 | return invokeOrDie(getValueDescriptorMethod, |
---|
1725 | super.getRepeated(message, index)); |
---|
1726 | } |
---|
1727 | @Override |
---|
1728 | public Object getRepeated(final GeneratedMessage.Builder builder, |
---|
1729 | final int index) { |
---|
1730 | return invokeOrDie(getValueDescriptorMethod, |
---|
1731 | super.getRepeated(builder, index)); |
---|
1732 | } |
---|
1733 | @Override |
---|
1734 | public void setRepeated(final Builder builder, |
---|
1735 | final int index, final Object value) { |
---|
1736 | super.setRepeated(builder, index, invokeOrDie(valueOfMethod, null, |
---|
1737 | value)); |
---|
1738 | } |
---|
1739 | @Override |
---|
1740 | public void addRepeated(final Builder builder, final Object value) { |
---|
1741 | super.addRepeated(builder, invokeOrDie(valueOfMethod, null, value)); |
---|
1742 | } |
---|
1743 | } |
---|
1744 | |
---|
1745 | // --------------------------------------------------------------- |
---|
1746 | |
---|
1747 | private static final class SingularMessageFieldAccessor |
---|
1748 | extends SingularFieldAccessor { |
---|
1749 | SingularMessageFieldAccessor( |
---|
1750 | final FieldDescriptor descriptor, final String camelCaseName, |
---|
1751 | final Class<? extends GeneratedMessage> messageClass, |
---|
1752 | final Class<? extends Builder> builderClass) { |
---|
1753 | super(descriptor, camelCaseName, messageClass, builderClass); |
---|
1754 | |
---|
1755 | newBuilderMethod = getMethodOrDie(type, "newBuilder"); |
---|
1756 | } |
---|
1757 | |
---|
1758 | private final Method newBuilderMethod; |
---|
1759 | |
---|
1760 | private Object coerceType(final Object value) { |
---|
1761 | if (type.isInstance(value)) { |
---|
1762 | return value; |
---|
1763 | } else { |
---|
1764 | // The value is not the exact right message type. However, if it |
---|
1765 | // is an alternative implementation of the same type -- e.g. a |
---|
1766 | // DynamicMessage -- we should accept it. In this case we can make |
---|
1767 | // a copy of the message. |
---|
1768 | return ((Message.Builder) invokeOrDie(newBuilderMethod, null)) |
---|
1769 | .mergeFrom((Message) value).build(); |
---|
1770 | } |
---|
1771 | } |
---|
1772 | |
---|
1773 | @Override |
---|
1774 | public void set(final Builder builder, final Object value) { |
---|
1775 | super.set(builder, coerceType(value)); |
---|
1776 | } |
---|
1777 | @Override |
---|
1778 | public Message.Builder newBuilder() { |
---|
1779 | return (Message.Builder) invokeOrDie(newBuilderMethod, null); |
---|
1780 | } |
---|
1781 | } |
---|
1782 | |
---|
1783 | private static final class RepeatedMessageFieldAccessor |
---|
1784 | extends RepeatedFieldAccessor { |
---|
1785 | RepeatedMessageFieldAccessor( |
---|
1786 | final FieldDescriptor descriptor, final String camelCaseName, |
---|
1787 | final Class<? extends GeneratedMessage> messageClass, |
---|
1788 | final Class<? extends Builder> builderClass) { |
---|
1789 | super(descriptor, camelCaseName, messageClass, builderClass); |
---|
1790 | |
---|
1791 | newBuilderMethod = getMethodOrDie(type, "newBuilder"); |
---|
1792 | } |
---|
1793 | |
---|
1794 | private final Method newBuilderMethod; |
---|
1795 | |
---|
1796 | private Object coerceType(final Object value) { |
---|
1797 | if (type.isInstance(value)) { |
---|
1798 | return value; |
---|
1799 | } else { |
---|
1800 | // The value is not the exact right message type. However, if it |
---|
1801 | // is an alternative implementation of the same type -- e.g. a |
---|
1802 | // DynamicMessage -- we should accept it. In this case we can make |
---|
1803 | // a copy of the message. |
---|
1804 | return ((Message.Builder) invokeOrDie(newBuilderMethod, null)) |
---|
1805 | .mergeFrom((Message) value).build(); |
---|
1806 | } |
---|
1807 | } |
---|
1808 | |
---|
1809 | @Override |
---|
1810 | public void setRepeated(final Builder builder, |
---|
1811 | final int index, final Object value) { |
---|
1812 | super.setRepeated(builder, index, coerceType(value)); |
---|
1813 | } |
---|
1814 | @Override |
---|
1815 | public void addRepeated(final Builder builder, final Object value) { |
---|
1816 | super.addRepeated(builder, coerceType(value)); |
---|
1817 | } |
---|
1818 | @Override |
---|
1819 | public Message.Builder newBuilder() { |
---|
1820 | return (Message.Builder) invokeOrDie(newBuilderMethod, null); |
---|
1821 | } |
---|
1822 | } |
---|
1823 | } |
---|
1824 | |
---|
1825 | /** |
---|
1826 | * Replaces this object in the output stream with a serialized form. |
---|
1827 | * Part of Java's serialization magic. Generated sub-classes must override |
---|
1828 | * this method by calling <code>return super.writeReplace();</code> |
---|
1829 | * @return a SerializedForm of this message |
---|
1830 | */ |
---|
1831 | protected Object writeReplace() throws ObjectStreamException { |
---|
1832 | return new GeneratedMessageLite.SerializedForm(this); |
---|
1833 | } |
---|
1834 | } |
---|