1
// Protocol Buffers - Google's data interchange format
2
// Copyright 2008 Google Inc. All rights reserved.
3
// http://code.google.com/p/protobuf/
5
// Redistribution and use in source and binary forms, with or without
6
// modification, are permitted provided that the following conditions are
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
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.
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.
31
package com.google.protobuf;
33
import com.google.protobuf.Descriptors.Descriptor;
34
import com.google.protobuf.Descriptors.FieldDescriptor;
36
import java.io.InputStream;
37
import java.io.IOException;
38
import java.util.ArrayList;
39
import java.util.List;
43
* A partial implementation of the {@link Message} interface which implements
44
* as many methods of that interface as possible in terms of other methods.
46
* @author kenton@google.com Kenton Varda
48
public abstract class AbstractMessage extends AbstractMessageLite
50
@SuppressWarnings("unchecked")
51
public boolean isInitialized() {
52
// Check that all required fields are present.
53
for (final FieldDescriptor field : getDescriptorForType().getFields()) {
54
if (field.isRequired()) {
55
if (!hasField(field)) {
61
// Check that embedded messages are initialized.
62
for (final Map.Entry<FieldDescriptor, Object> entry :
63
getAllFields().entrySet()) {
64
final FieldDescriptor field = entry.getKey();
65
if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
66
if (field.isRepeated()) {
67
for (final Message element : (List<Message>) entry.getValue()) {
68
if (!element.isInitialized()) {
73
if (!((Message) entry.getValue()).isInitialized()) {
84
public final String toString() {
85
return TextFormat.printToString(this);
88
public void writeTo(final CodedOutputStream output) throws IOException {
89
final boolean isMessageSet =
90
getDescriptorForType().getOptions().getMessageSetWireFormat();
92
for (final Map.Entry<FieldDescriptor, Object> entry :
93
getAllFields().entrySet()) {
94
final FieldDescriptor field = entry.getKey();
95
final Object value = entry.getValue();
96
if (isMessageSet && field.isExtension() &&
97
field.getType() == FieldDescriptor.Type.MESSAGE &&
98
!field.isRepeated()) {
99
output.writeMessageSetExtension(field.getNumber(), (Message) value);
101
FieldSet.writeField(field, value, output);
105
final UnknownFieldSet unknownFields = getUnknownFields();
107
unknownFields.writeAsMessageSetTo(output);
109
unknownFields.writeTo(output);
113
private int memoizedSize = -1;
115
public int getSerializedSize() {
116
int size = memoizedSize;
122
final boolean isMessageSet =
123
getDescriptorForType().getOptions().getMessageSetWireFormat();
125
for (final Map.Entry<FieldDescriptor, Object> entry :
126
getAllFields().entrySet()) {
127
final FieldDescriptor field = entry.getKey();
128
final Object value = entry.getValue();
129
if (isMessageSet && field.isExtension() &&
130
field.getType() == FieldDescriptor.Type.MESSAGE &&
131
!field.isRepeated()) {
132
size += CodedOutputStream.computeMessageSetExtensionSize(
133
field.getNumber(), (Message) value);
135
size += FieldSet.computeFieldSize(field, value);
139
final UnknownFieldSet unknownFields = getUnknownFields();
141
size += unknownFields.getSerializedSizeAsMessageSet();
143
size += unknownFields.getSerializedSize();
151
public boolean equals(final Object other) {
155
if (!(other instanceof Message)) {
158
final Message otherMessage = (Message) other;
159
if (getDescriptorForType() != otherMessage.getDescriptorForType()) {
162
return getAllFields().equals(otherMessage.getAllFields()) &&
163
getUnknownFields().equals(otherMessage.getUnknownFields());
167
public int hashCode() {
169
hash = (19 * hash) + getDescriptorForType().hashCode();
170
hash = (53 * hash) + getAllFields().hashCode();
171
hash = (29 * hash) + getUnknownFields().hashCode();
175
// =================================================================
178
* A partial implementation of the {@link Message.Builder} interface which
179
* implements as many methods of that interface as possible in terms of
182
@SuppressWarnings("unchecked")
183
public static abstract class Builder<BuilderType extends Builder>
184
extends AbstractMessageLite.Builder<BuilderType>
185
implements Message.Builder {
186
// The compiler produces an error if this is not declared explicitly.
188
public abstract BuilderType clone();
190
public BuilderType clear() {
191
for (final Map.Entry<FieldDescriptor, Object> entry :
192
getAllFields().entrySet()) {
193
clearField(entry.getKey());
195
return (BuilderType) this;
198
public BuilderType mergeFrom(final Message other) {
199
if (other.getDescriptorForType() != getDescriptorForType()) {
200
throw new IllegalArgumentException(
201
"mergeFrom(Message) can only merge messages of the same type.");
204
// Note: We don't attempt to verify that other's fields have valid
205
// types. Doing so would be a losing battle. We'd have to verify
206
// all sub-messages as well, and we'd have to make copies of all of
207
// them to insure that they don't change after verification (since
208
// the Message interface itself cannot enforce immutability of
210
// TODO(kenton): Provide a function somewhere called makeDeepCopy()
211
// which allows people to make secure deep copies of messages.
213
for (final Map.Entry<FieldDescriptor, Object> entry :
214
other.getAllFields().entrySet()) {
215
final FieldDescriptor field = entry.getKey();
216
if (field.isRepeated()) {
217
for (final Object element : (List)entry.getValue()) {
218
addRepeatedField(field, element);
220
} else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
221
final Message existingValue = (Message)getField(field);
222
if (existingValue == existingValue.getDefaultInstanceForType()) {
223
setField(field, entry.getValue());
226
existingValue.newBuilderForType()
227
.mergeFrom(existingValue)
228
.mergeFrom((Message)entry.getValue())
232
setField(field, entry.getValue());
236
mergeUnknownFields(other.getUnknownFields());
238
return (BuilderType) this;
242
public BuilderType mergeFrom(final CodedInputStream input)
244
return mergeFrom(input, ExtensionRegistry.getEmptyRegistry());
248
public BuilderType mergeFrom(
249
final CodedInputStream input,
250
final ExtensionRegistryLite extensionRegistry)
252
final UnknownFieldSet.Builder unknownFields =
253
UnknownFieldSet.newBuilder(getUnknownFields());
255
final int tag = input.readTag();
260
if (!mergeFieldFrom(input, unknownFields, extensionRegistry,
266
setUnknownFields(unknownFields.build());
267
return (BuilderType) this;
271
* Like {@link #mergeFrom(CodedInputStream, UnknownFieldSet.Builder,
272
* ExtensionRegistryLite, Message.Builder)}, but parses a single field.
273
* Package-private because it is used by GeneratedMessage.ExtendableMessage.
274
* @param tag The tag, which should have already been read.
275
* @return {@code true} unless the tag is an end-group tag.
277
static boolean mergeFieldFrom(
278
final CodedInputStream input,
279
final UnknownFieldSet.Builder unknownFields,
280
final ExtensionRegistryLite extensionRegistry,
281
final Message.Builder builder,
282
final int tag) throws IOException {
283
final Descriptor type = builder.getDescriptorForType();
285
if (type.getOptions().getMessageSetWireFormat() &&
286
tag == WireFormat.MESSAGE_SET_ITEM_TAG) {
287
mergeMessageSetExtensionFromCodedStream(
288
input, unknownFields, extensionRegistry, builder);
292
final int wireType = WireFormat.getTagWireType(tag);
293
final int fieldNumber = WireFormat.getTagFieldNumber(tag);
295
final FieldDescriptor field;
296
Message defaultInstance = null;
298
if (type.isExtensionNumber(fieldNumber)) {
299
// extensionRegistry may be either ExtensionRegistry or
300
// ExtensionRegistryLite. Since the type we are parsing is a full
301
// message, only a full ExtensionRegistry could possibly contain
302
// extensions of it. Otherwise we will treat the registry as if it
304
if (extensionRegistry instanceof ExtensionRegistry) {
305
final ExtensionRegistry.ExtensionInfo extension =
306
((ExtensionRegistry) extensionRegistry)
307
.findExtensionByNumber(type, fieldNumber);
308
if (extension == null) {
311
field = extension.descriptor;
312
defaultInstance = extension.defaultInstance;
313
if (defaultInstance == null &&
314
field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
315
throw new IllegalStateException(
316
"Message-typed extension lacked default instance: " +
317
field.getFullName());
324
field = type.findFieldByNumber(fieldNumber);
327
boolean unknown = false;
328
boolean packed = false;
330
unknown = true; // Unknown field.
331
} else if (wireType == FieldSet.getWireFormatForFieldType(
333
false /* isPacked */)) {
335
} else if (field.isPackable() &&
336
wireType == FieldSet.getWireFormatForFieldType(
338
true /* isPacked */)) {
341
unknown = true; // Unknown wire type.
344
if (unknown) { // Unknown field or wrong wire type. Skip.
345
return unknownFields.mergeFieldFrom(tag, input);
349
final int length = input.readRawVarint32();
350
final int limit = input.pushLimit(length);
351
if (field.getLiteType() == WireFormat.FieldType.ENUM) {
352
while (input.getBytesUntilLimit() > 0) {
353
final int rawValue = input.readEnum();
354
final Object value = field.getEnumType().findValueByNumber(rawValue);
356
// If the number isn't recognized as a valid value for this
357
// enum, drop it (don't even add it to unknownFields).
360
builder.addRepeatedField(field, value);
363
while (input.getBytesUntilLimit() > 0) {
365
FieldSet.readPrimitiveField(input, field.getLiteType());
366
builder.addRepeatedField(field, value);
369
input.popLimit(limit);
372
switch (field.getType()) {
374
final Message.Builder subBuilder;
375
if (defaultInstance != null) {
376
subBuilder = defaultInstance.newBuilderForType();
378
subBuilder = builder.newBuilderForField(field);
380
if (!field.isRepeated()) {
381
subBuilder.mergeFrom((Message) builder.getField(field));
383
input.readGroup(field.getNumber(), subBuilder, extensionRegistry);
384
value = subBuilder.build();
388
final Message.Builder subBuilder;
389
if (defaultInstance != null) {
390
subBuilder = defaultInstance.newBuilderForType();
392
subBuilder = builder.newBuilderForField(field);
394
if (!field.isRepeated()) {
395
subBuilder.mergeFrom((Message) builder.getField(field));
397
input.readMessage(subBuilder, extensionRegistry);
398
value = subBuilder.build();
402
final int rawValue = input.readEnum();
403
value = field.getEnumType().findValueByNumber(rawValue);
404
// If the number isn't recognized as a valid value for this enum,
407
unknownFields.mergeVarintField(fieldNumber, rawValue);
412
value = FieldSet.readPrimitiveField(input, field.getLiteType());
416
if (field.isRepeated()) {
417
builder.addRepeatedField(field, value);
419
builder.setField(field, value);
426
/** Called by {@code #mergeFieldFrom()} to parse a MessageSet extension. */
427
private static void mergeMessageSetExtensionFromCodedStream(
428
final CodedInputStream input,
429
final UnknownFieldSet.Builder unknownFields,
430
final ExtensionRegistryLite extensionRegistry,
431
final Message.Builder builder) throws IOException {
432
final Descriptor type = builder.getDescriptorForType();
434
// The wire format for MessageSet is:
435
// message MessageSet {
436
// repeated group Item = 1 {
437
// required int32 typeId = 2;
438
// required bytes message = 3;
441
// "typeId" is the extension's field number. The extension can only be
442
// a message type, where "message" contains the encoded bytes of that
445
// In practice, we will probably never see a MessageSet item in which
446
// the message appears before the type ID, or where either field does not
447
// appear exactly once. However, in theory such cases are valid, so we
448
// should be prepared to accept them.
451
ByteString rawBytes = null; // If we encounter "message" before "typeId"
452
Message.Builder subBuilder = null;
453
FieldDescriptor field = null;
456
final int tag = input.readTag();
461
if (tag == WireFormat.MESSAGE_SET_TYPE_ID_TAG) {
462
typeId = input.readUInt32();
463
// Zero is not a valid type ID.
465
final ExtensionRegistry.ExtensionInfo extension;
467
// extensionRegistry may be either ExtensionRegistry or
468
// ExtensionRegistryLite. Since the type we are parsing is a full
469
// message, only a full ExtensionRegistry could possibly contain
470
// extensions of it. Otherwise we will treat the registry as if it
472
if (extensionRegistry instanceof ExtensionRegistry) {
473
extension = ((ExtensionRegistry) extensionRegistry)
474
.findExtensionByNumber(type, typeId);
479
if (extension != null) {
480
field = extension.descriptor;
481
subBuilder = extension.defaultInstance.newBuilderForType();
482
final Message originalMessage = (Message)builder.getField(field);
483
if (originalMessage != null) {
484
subBuilder.mergeFrom(originalMessage);
486
if (rawBytes != null) {
487
// We already encountered the message. Parse it now.
488
subBuilder.mergeFrom(
489
CodedInputStream.newInstance(rawBytes.newInput()));
493
// Unknown extension number. If we already saw data, put it
495
if (rawBytes != null) {
496
unknownFields.mergeField(typeId,
497
UnknownFieldSet.Field.newBuilder()
498
.addLengthDelimited(rawBytes)
504
} else if (tag == WireFormat.MESSAGE_SET_MESSAGE_TAG) {
506
// We haven't seen a type ID yet, so we have to store the raw bytes
508
rawBytes = input.readBytes();
509
} else if (subBuilder == null) {
510
// We don't know how to parse this. Ignore it.
511
unknownFields.mergeField(typeId,
512
UnknownFieldSet.Field.newBuilder()
513
.addLengthDelimited(input.readBytes())
516
// We already know the type, so we can parse directly from the input
517
// with no copying. Hooray!
518
input.readMessage(subBuilder, extensionRegistry);
521
// Unknown tag. Skip it.
522
if (!input.skipField(tag)) {
523
break; // end of group
528
input.checkLastTagWas(WireFormat.MESSAGE_SET_ITEM_END_TAG);
530
if (subBuilder != null) {
531
builder.setField(field, subBuilder.build());
535
public BuilderType mergeUnknownFields(final UnknownFieldSet unknownFields) {
537
UnknownFieldSet.newBuilder(getUnknownFields())
538
.mergeFrom(unknownFields)
540
return (BuilderType) this;
544
* Construct an UninitializedMessageException reporting missing fields in
547
protected static UninitializedMessageException
548
newUninitializedMessageException(Message message) {
549
return new UninitializedMessageException(findMissingFields(message));
553
* Populates {@code this.missingFields} with the full "path" of each
554
* missing required field in the given message.
556
private static List<String> findMissingFields(final Message message) {
557
final List<String> results = new ArrayList<String>();
558
findMissingFields(message, "", results);
562
/** Recursive helper implementing {@link #findMissingFields(Message)}. */
563
private static void findMissingFields(final Message message,
565
final List<String> results) {
566
for (final FieldDescriptor field :
567
message.getDescriptorForType().getFields()) {
568
if (field.isRequired() && !message.hasField(field)) {
569
results.add(prefix + field.getName());
573
for (final Map.Entry<FieldDescriptor, Object> entry :
574
message.getAllFields().entrySet()) {
575
final FieldDescriptor field = entry.getKey();
576
final Object value = entry.getValue();
578
if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
579
if (field.isRepeated()) {
581
for (final Object element : (List) value) {
582
findMissingFields((Message) element,
583
subMessagePrefix(prefix, field, i++),
587
if (message.hasField(field)) {
588
findMissingFields((Message) value,
589
subMessagePrefix(prefix, field, -1),
597
private static String subMessagePrefix(final String prefix,
598
final FieldDescriptor field,
600
final StringBuilder result = new StringBuilder(prefix);
601
if (field.isExtension()) {
603
.append(field.getFullName())
606
result.append(field.getName());
614
return result.toString();
617
// ===============================================================
618
// The following definitions seem to be required in order to make javac
619
// not produce weird errors like:
621
// java/com/google/protobuf/DynamicMessage.java:203: types
622
// com.google.protobuf.AbstractMessage.Builder<
623
// com.google.protobuf.DynamicMessage.Builder> and
624
// com.google.protobuf.AbstractMessage.Builder<
625
// com.google.protobuf.DynamicMessage.Builder> are incompatible; both
626
// define mergeFrom(com.google.protobuf.ByteString), but with unrelated
629
// Strangely, these lines are only needed if javac is invoked separately
630
// on AbstractMessage.java and AbstractMessageLite.java. If javac is
631
// invoked on both simultaneously, it works. (Or maybe the important
632
// point is whether or not DynamicMessage.java is compiled together with
633
// AbstractMessageLite.java -- not sure.) I suspect this is a compiler
637
public BuilderType mergeFrom(final ByteString data)
638
throws InvalidProtocolBufferException {
639
return super.mergeFrom(data);
643
public BuilderType mergeFrom(
644
final ByteString data,
645
final ExtensionRegistryLite extensionRegistry)
646
throws InvalidProtocolBufferException {
647
return super.mergeFrom(data, extensionRegistry);
651
public BuilderType mergeFrom(final byte[] data)
652
throws InvalidProtocolBufferException {
653
return super.mergeFrom(data);
657
public BuilderType mergeFrom(
658
final byte[] data, final int off, final int len)
659
throws InvalidProtocolBufferException {
660
return super.mergeFrom(data, off, len);
664
public BuilderType mergeFrom(
666
final ExtensionRegistryLite extensionRegistry)
667
throws InvalidProtocolBufferException {
668
return super.mergeFrom(data, extensionRegistry);
672
public BuilderType mergeFrom(
673
final byte[] data, final int off, final int len,
674
final ExtensionRegistryLite extensionRegistry)
675
throws InvalidProtocolBufferException {
676
return super.mergeFrom(data, off, len, extensionRegistry);
680
public BuilderType mergeFrom(final InputStream input)
682
return super.mergeFrom(input);
686
public BuilderType mergeFrom(
687
final InputStream input,
688
final ExtensionRegistryLite extensionRegistry)
690
return super.mergeFrom(input, extensionRegistry);
694
public boolean mergeDelimitedFrom(final InputStream input)
696
return super.mergeDelimitedFrom(input);
700
public boolean mergeDelimitedFrom(
701
final InputStream input,
702
final ExtensionRegistryLite extensionRegistry)
704
return super.mergeDelimitedFrom(input, extensionRegistry);