- add sources.
[platform/framework/web/crosswalk.git] / src / third_party / protobuf / java / src / main / java / com / google / protobuf / AbstractMessage.java
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.FieldDescriptor;
35 import com.google.protobuf.GeneratedMessage.ExtendableBuilder;
36 import com.google.protobuf.Internal.EnumLite;
37
38 import java.io.IOException;
39 import java.io.InputStream;
40 import java.util.ArrayList;
41 import java.util.List;
42 import java.util.Map;
43
44 /**
45  * A partial implementation of the {@link Message} interface which implements
46  * as many methods of that interface as possible in terms of other methods.
47  *
48  * @author kenton@google.com Kenton Varda
49  */
50 public abstract class AbstractMessage extends AbstractMessageLite
51                                       implements Message {
52   @SuppressWarnings("unchecked")
53   public boolean isInitialized() {
54     // Check that all required fields are present.
55     for (final FieldDescriptor field : getDescriptorForType().getFields()) {
56       if (field.isRequired()) {
57         if (!hasField(field)) {
58           return false;
59         }
60       }
61     }
62
63     // Check that embedded messages are initialized.
64     for (final Map.Entry<FieldDescriptor, Object> entry :
65         getAllFields().entrySet()) {
66       final FieldDescriptor field = entry.getKey();
67       if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
68         if (field.isRepeated()) {
69           for (final Message element : (List<Message>) entry.getValue()) {
70             if (!element.isInitialized()) {
71               return false;
72             }
73           }
74         } else {
75           if (!((Message) entry.getValue()).isInitialized()) {
76             return false;
77           }
78         }
79       }
80     }
81
82     return true;
83   }
84
85   public List<String> findInitializationErrors() {
86     return Builder.findMissingFields(this);
87   }
88
89   public String getInitializationErrorString() {
90     return delimitWithCommas(findInitializationErrors());
91   }
92
93   private static String delimitWithCommas(List<String> parts) {
94     StringBuilder result = new StringBuilder();
95     for (String part : parts) {
96       if (result.length() > 0) {
97         result.append(", ");
98       }
99       result.append(part);
100     }
101     return result.toString();
102   }
103
104   @Override
105   public final String toString() {
106     return TextFormat.printToString(this);
107   }
108
109   public void writeTo(final CodedOutputStream output) throws IOException {
110     final boolean isMessageSet =
111         getDescriptorForType().getOptions().getMessageSetWireFormat();
112
113     for (final Map.Entry<FieldDescriptor, Object> entry :
114         getAllFields().entrySet()) {
115       final FieldDescriptor field = entry.getKey();
116       final Object value = entry.getValue();
117       if (isMessageSet && field.isExtension() &&
118           field.getType() == FieldDescriptor.Type.MESSAGE &&
119           !field.isRepeated()) {
120         output.writeMessageSetExtension(field.getNumber(), (Message) value);
121       } else {
122         FieldSet.writeField(field, value, output);
123       }
124     }
125
126     final UnknownFieldSet unknownFields = getUnknownFields();
127     if (isMessageSet) {
128       unknownFields.writeAsMessageSetTo(output);
129     } else {
130       unknownFields.writeTo(output);
131     }
132   }
133
134   private int memoizedSize = -1;
135
136   public int getSerializedSize() {
137     int size = memoizedSize;
138     if (size != -1) {
139       return size;
140     }
141
142     size = 0;
143     final boolean isMessageSet =
144         getDescriptorForType().getOptions().getMessageSetWireFormat();
145
146     for (final Map.Entry<FieldDescriptor, Object> entry :
147         getAllFields().entrySet()) {
148       final FieldDescriptor field = entry.getKey();
149       final Object value = entry.getValue();
150       if (isMessageSet && field.isExtension() &&
151           field.getType() == FieldDescriptor.Type.MESSAGE &&
152           !field.isRepeated()) {
153         size += CodedOutputStream.computeMessageSetExtensionSize(
154             field.getNumber(), (Message) value);
155       } else {
156         size += FieldSet.computeFieldSize(field, value);
157       }
158     }
159
160     final UnknownFieldSet unknownFields = getUnknownFields();
161     if (isMessageSet) {
162       size += unknownFields.getSerializedSizeAsMessageSet();
163     } else {
164       size += unknownFields.getSerializedSize();
165     }
166
167     memoizedSize = size;
168     return size;
169   }
170
171   @Override
172   public boolean equals(final Object other) {
173     if (other == this) {
174       return true;
175     }
176     if (!(other instanceof Message)) {
177       return false;
178     }
179     final Message otherMessage = (Message) other;
180     if (getDescriptorForType() != otherMessage.getDescriptorForType()) {
181       return false;
182     }
183     return getAllFields().equals(otherMessage.getAllFields()) &&
184         getUnknownFields().equals(otherMessage.getUnknownFields());
185   }
186
187   @Override
188   public int hashCode() {
189     int hash = 41;
190     hash = (19 * hash) + getDescriptorForType().hashCode();
191     hash = hashFields(hash, getAllFields());
192     hash = (29 * hash) + getUnknownFields().hashCode();
193     return hash;
194   }
195
196   /** Get a hash code for given fields and values, using the given seed. */
197   @SuppressWarnings("unchecked")
198   protected int hashFields(int hash, Map<FieldDescriptor, Object> map) {
199     for (Map.Entry<FieldDescriptor, Object> entry : map.entrySet()) {
200       FieldDescriptor field = entry.getKey();
201       Object value = entry.getValue();
202       hash = (37 * hash) + field.getNumber();
203       if (field.getType() != FieldDescriptor.Type.ENUM){
204         hash = (53 * hash) + value.hashCode();
205       } else if (field.isRepeated()) {
206         List<? extends EnumLite> list = (List<? extends EnumLite>) value;
207         hash = (53 * hash) + hashEnumList(list);
208       } else {
209         hash = (53 * hash) + hashEnum((EnumLite) value);
210       }
211     }
212     return hash;
213   }
214
215   /**
216    * Helper method for implementing {@link Message#hashCode()}.
217    * @see Boolean#hashCode()
218    */
219   protected static int hashLong(long n) {
220     return (int) (n ^ (n >>> 32));
221   }
222
223   /**
224    * Helper method for implementing {@link Message#hashCode()}.
225    * @see Boolean#hashCode()
226    */
227   protected static int hashBoolean(boolean b) {
228     return b ? 1231 : 1237;
229   }
230
231   /**
232    * Package private helper method for AbstractParser to create
233    * UninitializedMessageException with missing field information.
234    */
235   @Override
236   UninitializedMessageException newUninitializedMessageException() {
237     return Builder.newUninitializedMessageException(this);
238   }
239
240   /**
241    * Helper method for implementing {@link Message#hashCode()}.
242    * <p>
243    * This is needed because {@link java.lang.Enum#hashCode()} is final, but we
244    * need to use the field number as the hash code to ensure compatibility
245    * between statically and dynamically generated enum objects.
246    */
247   protected static int hashEnum(EnumLite e) {
248     return e.getNumber();
249   }
250
251   /** Helper method for implementing {@link Message#hashCode()}. */
252   protected static int hashEnumList(List<? extends EnumLite> list) {
253     int hash = 1;
254     for (EnumLite e : list) {
255       hash = 31 * hash + hashEnum(e);
256     }
257     return hash;
258   }
259
260   // =================================================================
261
262   /**
263    * A partial implementation of the {@link Message.Builder} interface which
264    * implements as many methods of that interface as possible in terms of
265    * other methods.
266    */
267   @SuppressWarnings("unchecked")
268   public static abstract class Builder<BuilderType extends Builder>
269       extends AbstractMessageLite.Builder<BuilderType>
270       implements Message.Builder {
271     // The compiler produces an error if this is not declared explicitly.
272     @Override
273     public abstract BuilderType clone();
274
275     public BuilderType clear() {
276       for (final Map.Entry<FieldDescriptor, Object> entry :
277            getAllFields().entrySet()) {
278         clearField(entry.getKey());
279       }
280       return (BuilderType) this;
281     }
282
283     public List<String> findInitializationErrors() {
284       return findMissingFields(this);
285     }
286
287     public String getInitializationErrorString() {
288       return delimitWithCommas(findInitializationErrors());
289     }
290
291     public BuilderType mergeFrom(final Message other) {
292       if (other.getDescriptorForType() != getDescriptorForType()) {
293         throw new IllegalArgumentException(
294           "mergeFrom(Message) can only merge messages of the same type.");
295       }
296
297       // Note:  We don't attempt to verify that other's fields have valid
298       //   types.  Doing so would be a losing battle.  We'd have to verify
299       //   all sub-messages as well, and we'd have to make copies of all of
300       //   them to insure that they don't change after verification (since
301       //   the Message interface itself cannot enforce immutability of
302       //   implementations).
303       // TODO(kenton):  Provide a function somewhere called makeDeepCopy()
304       //   which allows people to make secure deep copies of messages.
305
306       for (final Map.Entry<FieldDescriptor, Object> entry :
307            other.getAllFields().entrySet()) {
308         final FieldDescriptor field = entry.getKey();
309         if (field.isRepeated()) {
310           for (final Object element : (List)entry.getValue()) {
311             addRepeatedField(field, element);
312           }
313         } else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
314           final Message existingValue = (Message)getField(field);
315           if (existingValue == existingValue.getDefaultInstanceForType()) {
316             setField(field, entry.getValue());
317           } else {
318             setField(field,
319               existingValue.newBuilderForType()
320                 .mergeFrom(existingValue)
321                 .mergeFrom((Message)entry.getValue())
322                 .build());
323           }
324         } else {
325           setField(field, entry.getValue());
326         }
327       }
328
329       mergeUnknownFields(other.getUnknownFields());
330
331       return (BuilderType) this;
332     }
333
334     @Override
335     public BuilderType mergeFrom(final CodedInputStream input)
336                                  throws IOException {
337       return mergeFrom(input, ExtensionRegistry.getEmptyRegistry());
338     }
339
340     @Override
341     public BuilderType mergeFrom(
342         final CodedInputStream input,
343         final ExtensionRegistryLite extensionRegistry)
344         throws IOException {
345       final UnknownFieldSet.Builder unknownFields =
346         UnknownFieldSet.newBuilder(getUnknownFields());
347       while (true) {
348         final int tag = input.readTag();
349         if (tag == 0) {
350           break;
351         }
352
353         if (!mergeFieldFrom(input, unknownFields, extensionRegistry,
354                             getDescriptorForType(), this, null, tag)) {
355           // end group tag
356           break;
357         }
358       }
359       setUnknownFields(unknownFields.build());
360       return (BuilderType) this;
361     }
362
363     /** helper method to handle {@code builder} and {@code extensions}. */
364     private static void addRepeatedField(
365         Message.Builder builder,
366         FieldSet<FieldDescriptor> extensions,
367         FieldDescriptor field,
368         Object value) {
369       if (builder != null) {
370         builder.addRepeatedField(field, value);
371       } else {
372         extensions.addRepeatedField(field, value);
373       }
374     }
375
376     /** helper method to handle {@code builder} and {@code extensions}. */
377     private static void setField(
378         Message.Builder builder,
379         FieldSet<FieldDescriptor> extensions,
380         FieldDescriptor field,
381         Object value) {
382       if (builder != null) {
383         builder.setField(field, value);
384       } else {
385         extensions.setField(field, value);
386       }
387     }
388
389     /** helper method to handle {@code builder} and {@code extensions}. */
390     private static boolean hasOriginalMessage(
391         Message.Builder builder,
392         FieldSet<FieldDescriptor> extensions,
393         FieldDescriptor field) {
394       if (builder != null) {
395         return builder.hasField(field);
396       } else {
397         return extensions.hasField(field);
398       }
399     }
400
401     /** helper method to handle {@code builder} and {@code extensions}. */
402     private static Message getOriginalMessage(
403         Message.Builder builder,
404         FieldSet<FieldDescriptor> extensions,
405         FieldDescriptor field) {
406       if (builder != null) {
407         return (Message) builder.getField(field);
408       } else {
409         return (Message) extensions.getField(field);
410       }
411     }
412
413     /** helper method to handle {@code builder} and {@code extensions}. */
414     private static void mergeOriginalMessage(
415         Message.Builder builder,
416         FieldSet<FieldDescriptor> extensions,
417         FieldDescriptor field,
418         Message.Builder subBuilder) {
419       Message originalMessage = getOriginalMessage(builder, extensions, field);
420       if (originalMessage != null) {
421         subBuilder.mergeFrom(originalMessage);
422       }
423     }
424
425     /**
426      * Like {@link #mergeFrom(CodedInputStream, ExtensionRegistryLite)}, but
427      * parses a single field.
428      *
429      * When {@code builder} is not null, the method will parse and merge the
430      * field into {@code builder}. Otherwise, it will try to parse the field
431      * into {@code extensions}, when it's called by the parsing constructor in
432      * generated classes.
433      *
434      * Package-private because it is used by GeneratedMessage.ExtendableMessage.
435      * @param tag The tag, which should have already been read.
436      * @return {@code true} unless the tag is an end-group tag.
437      */
438     static boolean mergeFieldFrom(
439         CodedInputStream input,
440         UnknownFieldSet.Builder unknownFields,
441         ExtensionRegistryLite extensionRegistry,
442         Descriptor type,
443         Message.Builder builder,
444         FieldSet<FieldDescriptor> extensions,
445         int tag) throws IOException {
446       if (type.getOptions().getMessageSetWireFormat() &&
447           tag == WireFormat.MESSAGE_SET_ITEM_TAG) {
448         mergeMessageSetExtensionFromCodedStream(
449             input, unknownFields, extensionRegistry, type, builder, extensions);
450         return true;
451       }
452
453       final int wireType = WireFormat.getTagWireType(tag);
454       final int fieldNumber = WireFormat.getTagFieldNumber(tag);
455
456       final FieldDescriptor field;
457       Message defaultInstance = null;
458
459       if (type.isExtensionNumber(fieldNumber)) {
460         // extensionRegistry may be either ExtensionRegistry or
461         // ExtensionRegistryLite.  Since the type we are parsing is a full
462         // message, only a full ExtensionRegistry could possibly contain
463         // extensions of it.  Otherwise we will treat the registry as if it
464         // were empty.
465         if (extensionRegistry instanceof ExtensionRegistry) {
466           final ExtensionRegistry.ExtensionInfo extension =
467             ((ExtensionRegistry) extensionRegistry)
468               .findExtensionByNumber(type, fieldNumber);
469           if (extension == null) {
470             field = null;
471           } else {
472             field = extension.descriptor;
473             defaultInstance = extension.defaultInstance;
474             if (defaultInstance == null &&
475                 field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
476               throw new IllegalStateException(
477                   "Message-typed extension lacked default instance: " +
478                   field.getFullName());
479             }
480           }
481         } else {
482           field = null;
483         }
484       } else if (builder != null) {
485         field = type.findFieldByNumber(fieldNumber);
486       } else {
487         field = null;
488       }
489
490       boolean unknown = false;
491       boolean packed = false;
492       if (field == null) {
493         unknown = true;  // Unknown field.
494       } else if (wireType == FieldSet.getWireFormatForFieldType(
495                    field.getLiteType(),
496                    false  /* isPacked */)) {
497         packed = false;
498       } else if (field.isPackable() &&
499                  wireType == FieldSet.getWireFormatForFieldType(
500                    field.getLiteType(),
501                    true  /* isPacked */)) {
502         packed = true;
503       } else {
504         unknown = true;  // Unknown wire type.
505       }
506
507       if (unknown) {  // Unknown field or wrong wire type.  Skip.
508         return unknownFields.mergeFieldFrom(tag, input);
509       }
510
511       if (packed) {
512         final int length = input.readRawVarint32();
513         final int limit = input.pushLimit(length);
514         if (field.getLiteType() == WireFormat.FieldType.ENUM) {
515           while (input.getBytesUntilLimit() > 0) {
516             final int rawValue = input.readEnum();
517             final Object value = field.getEnumType().findValueByNumber(rawValue);
518             if (value == null) {
519               // If the number isn't recognized as a valid value for this
520               // enum, drop it (don't even add it to unknownFields).
521               return true;
522             }
523             addRepeatedField(builder, extensions, field, value);
524           }
525         } else {
526           while (input.getBytesUntilLimit() > 0) {
527             final Object value =
528               FieldSet.readPrimitiveField(input, field.getLiteType());
529             addRepeatedField(builder, extensions, field, value);
530           }
531         }
532         input.popLimit(limit);
533       } else {
534         final Object value;
535         switch (field.getType()) {
536           case GROUP: {
537             final Message.Builder subBuilder;
538             if (defaultInstance != null) {
539               subBuilder = defaultInstance.newBuilderForType();
540             } else {
541               subBuilder = builder.newBuilderForField(field);
542             }
543             if (!field.isRepeated()) {
544               mergeOriginalMessage(builder, extensions, field, subBuilder);
545             }
546             input.readGroup(field.getNumber(), subBuilder, extensionRegistry);
547             value = subBuilder.buildPartial();
548             break;
549           }
550           case MESSAGE: {
551             final Message.Builder subBuilder;
552             if (defaultInstance != null) {
553               subBuilder = defaultInstance.newBuilderForType();
554             } else {
555               subBuilder = builder.newBuilderForField(field);
556             }
557             if (!field.isRepeated()) {
558               mergeOriginalMessage(builder, extensions, field, subBuilder);
559             }
560             input.readMessage(subBuilder, extensionRegistry);
561             value = subBuilder.buildPartial();
562             break;
563           }
564           case ENUM:
565             final int rawValue = input.readEnum();
566             value = field.getEnumType().findValueByNumber(rawValue);
567             // If the number isn't recognized as a valid value for this enum,
568             // drop it.
569             if (value == null) {
570               unknownFields.mergeVarintField(fieldNumber, rawValue);
571               return true;
572             }
573             break;
574           default:
575             value = FieldSet.readPrimitiveField(input, field.getLiteType());
576             break;
577         }
578
579         if (field.isRepeated()) {
580           addRepeatedField(builder, extensions, field, value);
581         } else {
582           setField(builder, extensions, field, value);
583         }
584       }
585
586       return true;
587     }
588
589     /**
590      * Called by {@code #mergeFieldFrom()} to parse a MessageSet extension.
591      * If {@code builder} is not null, this method will merge MessageSet into
592      * the builder.  Otherwise, it will merge the MessageSet into {@code
593      * extensions}.
594      */
595     private static void mergeMessageSetExtensionFromCodedStream(
596         CodedInputStream input,
597         UnknownFieldSet.Builder unknownFields,
598         ExtensionRegistryLite extensionRegistry,
599         Descriptor type,
600         Message.Builder builder,
601         FieldSet<FieldDescriptor> extensions) throws IOException {
602
603       // The wire format for MessageSet is:
604       //   message MessageSet {
605       //     repeated group Item = 1 {
606       //       required int32 typeId = 2;
607       //       required bytes message = 3;
608       //     }
609       //   }
610       // "typeId" is the extension's field number.  The extension can only be
611       // a message type, where "message" contains the encoded bytes of that
612       // message.
613       //
614       // In practice, we will probably never see a MessageSet item in which
615       // the message appears before the type ID, or where either field does not
616       // appear exactly once.  However, in theory such cases are valid, so we
617       // should be prepared to accept them.
618
619       int typeId = 0;
620       ByteString rawBytes = null; // If we encounter "message" before "typeId"
621       ExtensionRegistry.ExtensionInfo extension = null;
622
623       // Read bytes from input, if we get it's type first then parse it eagerly,
624       // otherwise we store the raw bytes in a local variable.
625       while (true) {
626         final int tag = input.readTag();
627         if (tag == 0) {
628           break;
629         }
630
631         if (tag == WireFormat.MESSAGE_SET_TYPE_ID_TAG) {
632           typeId = input.readUInt32();
633           if (typeId != 0) {
634             // extensionRegistry may be either ExtensionRegistry or
635             // ExtensionRegistryLite. Since the type we are parsing is a full
636             // message, only a full ExtensionRegistry could possibly contain
637             // extensions of it. Otherwise we will treat the registry as if it
638             // were empty.
639             if (extensionRegistry instanceof ExtensionRegistry) {
640               extension = ((ExtensionRegistry) extensionRegistry)
641                   .findExtensionByNumber(type, typeId);
642             }
643           }
644
645         } else if (tag == WireFormat.MESSAGE_SET_MESSAGE_TAG) {
646           if (typeId != 0) {
647             if (extension != null && ExtensionRegistryLite.isEagerlyParseMessageSets()) {
648               // We already know the type, so we can parse directly from the
649               // input with no copying.  Hooray!
650               eagerlyMergeMessageSetExtension(
651                   input, extension, extensionRegistry, builder, extensions);
652               rawBytes = null;
653               continue;
654             }
655           }
656           // We haven't seen a type ID yet or we want parse message lazily.
657           rawBytes = input.readBytes();
658
659         } else { // Unknown tag. Skip it.
660           if (!input.skipField(tag)) {
661             break; // End of group
662           }
663         }
664       }
665       input.checkLastTagWas(WireFormat.MESSAGE_SET_ITEM_END_TAG);
666
667       // Process the raw bytes.
668       if (rawBytes != null && typeId != 0) { // Zero is not a valid type ID.
669         if (extension != null) { // We known the type
670           mergeMessageSetExtensionFromBytes(
671               rawBytes, extension, extensionRegistry, builder, extensions);
672         } else { // We don't know how to parse this. Ignore it.
673           if (rawBytes != null) {
674             unknownFields.mergeField(typeId, UnknownFieldSet.Field.newBuilder()
675                 .addLengthDelimited(rawBytes).build());
676           }
677         }
678       }
679     }
680
681     private static void eagerlyMergeMessageSetExtension(
682         CodedInputStream input,
683         ExtensionRegistry.ExtensionInfo extension,
684         ExtensionRegistryLite extensionRegistry,
685         Message.Builder builder,
686         FieldSet<FieldDescriptor> extensions) throws IOException {
687
688       FieldDescriptor field = extension.descriptor;
689       Message value = null;
690       if (hasOriginalMessage(builder, extensions, field)) {
691         Message originalMessage =
692             getOriginalMessage(builder, extensions, field);
693         Message.Builder subBuilder = originalMessage.toBuilder();
694         input.readMessage(subBuilder, extensionRegistry);
695         value = subBuilder.buildPartial();
696       } else {
697         value = input.readMessage(extension.defaultInstance.getParserForType(),
698           extensionRegistry);
699       }
700
701       if (builder != null) {
702         builder.setField(field, value);
703       } else {
704         extensions.setField(field, value);
705       }
706     }
707
708     private static void mergeMessageSetExtensionFromBytes(
709         ByteString rawBytes,
710         ExtensionRegistry.ExtensionInfo extension,
711         ExtensionRegistryLite extensionRegistry,
712         Message.Builder builder,
713         FieldSet<FieldDescriptor> extensions) throws IOException {
714
715       FieldDescriptor field = extension.descriptor;
716       boolean hasOriginalValue = hasOriginalMessage(builder, extensions, field);
717
718       if (hasOriginalValue || ExtensionRegistryLite.isEagerlyParseMessageSets()) {
719         // If the field already exists, we just parse the field.
720         Message value = null;
721         if (hasOriginalValue) {
722           Message originalMessage =
723               getOriginalMessage(builder, extensions, field);
724           Message.Builder subBuilder= originalMessage.toBuilder();
725           subBuilder.mergeFrom(rawBytes, extensionRegistry);
726           value = subBuilder.buildPartial();
727         } else {
728           value = extension.defaultInstance.getParserForType()
729               .parsePartialFrom(rawBytes, extensionRegistry);
730         }
731         setField(builder, extensions, field, value);
732       } else {
733         // Use LazyField to load MessageSet lazily.
734         LazyField lazyField = new LazyField(
735             extension.defaultInstance, extensionRegistry, rawBytes);
736         if (builder != null) {
737           // TODO(xiangl): it looks like this method can only be invoked by
738           // ExtendableBuilder, but I'm not sure. So I double check the type of
739           // builder here. It may be useless and need more investigation.
740           if (builder instanceof ExtendableBuilder) {
741             builder.setField(field, lazyField);
742           } else {
743             builder.setField(field, lazyField.getValue());
744           }
745         } else {
746           extensions.setField(field, lazyField);
747         }
748       }
749     }
750
751     public BuilderType mergeUnknownFields(final UnknownFieldSet unknownFields) {
752       setUnknownFields(
753         UnknownFieldSet.newBuilder(getUnknownFields())
754                        .mergeFrom(unknownFields)
755                        .build());
756       return (BuilderType) this;
757     }
758
759     public Message.Builder getFieldBuilder(final FieldDescriptor field) {
760       throw new UnsupportedOperationException(
761           "getFieldBuilder() called on an unsupported message type.");
762     }
763
764     /**
765      * Construct an UninitializedMessageException reporting missing fields in
766      * the given message.
767      */
768     protected static UninitializedMessageException
769         newUninitializedMessageException(Message message) {
770       return new UninitializedMessageException(findMissingFields(message));
771     }
772
773     /**
774      * Populates {@code this.missingFields} with the full "path" of each
775      * missing required field in the given message.
776      */
777     private static List<String> findMissingFields(
778         final MessageOrBuilder message) {
779       final List<String> results = new ArrayList<String>();
780       findMissingFields(message, "", results);
781       return results;
782     }
783
784     /** Recursive helper implementing {@link #findMissingFields(Message)}. */
785     private static void findMissingFields(final MessageOrBuilder message,
786                                           final String prefix,
787                                           final List<String> results) {
788       for (final FieldDescriptor field :
789           message.getDescriptorForType().getFields()) {
790         if (field.isRequired() && !message.hasField(field)) {
791           results.add(prefix + field.getName());
792         }
793       }
794
795       for (final Map.Entry<FieldDescriptor, Object> entry :
796            message.getAllFields().entrySet()) {
797         final FieldDescriptor field = entry.getKey();
798         final Object value = entry.getValue();
799
800         if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
801           if (field.isRepeated()) {
802             int i = 0;
803             for (final Object element : (List) value) {
804               findMissingFields((MessageOrBuilder) element,
805                                 subMessagePrefix(prefix, field, i++),
806                                 results);
807             }
808           } else {
809             if (message.hasField(field)) {
810               findMissingFields((MessageOrBuilder) value,
811                                 subMessagePrefix(prefix, field, -1),
812                                 results);
813             }
814           }
815         }
816       }
817     }
818
819     private static String subMessagePrefix(final String prefix,
820                                            final FieldDescriptor field,
821                                            final int index) {
822       final StringBuilder result = new StringBuilder(prefix);
823       if (field.isExtension()) {
824         result.append('(')
825               .append(field.getFullName())
826               .append(')');
827       } else {
828         result.append(field.getName());
829       }
830       if (index != -1) {
831         result.append('[')
832               .append(index)
833               .append(']');
834       }
835       result.append('.');
836       return result.toString();
837     }
838
839     // ===============================================================
840     // The following definitions seem to be required in order to make javac
841     // not produce weird errors like:
842     //
843     // java/com/google/protobuf/DynamicMessage.java:203: types
844     //   com.google.protobuf.AbstractMessage.Builder<
845     //     com.google.protobuf.DynamicMessage.Builder> and
846     //   com.google.protobuf.AbstractMessage.Builder<
847     //     com.google.protobuf.DynamicMessage.Builder> are incompatible; both
848     //   define mergeFrom(com.google.protobuf.ByteString), but with unrelated
849     //   return types.
850     //
851     // Strangely, these lines are only needed if javac is invoked separately
852     // on AbstractMessage.java and AbstractMessageLite.java.  If javac is
853     // invoked on both simultaneously, it works.  (Or maybe the important
854     // point is whether or not DynamicMessage.java is compiled together with
855     // AbstractMessageLite.java -- not sure.)  I suspect this is a compiler
856     // bug.
857
858     @Override
859     public BuilderType mergeFrom(final ByteString data)
860         throws InvalidProtocolBufferException {
861       return super.mergeFrom(data);
862     }
863
864     @Override
865     public BuilderType mergeFrom(
866         final ByteString data,
867         final ExtensionRegistryLite extensionRegistry)
868         throws InvalidProtocolBufferException {
869       return super.mergeFrom(data, extensionRegistry);
870     }
871
872     @Override
873     public BuilderType mergeFrom(final byte[] data)
874         throws InvalidProtocolBufferException {
875       return super.mergeFrom(data);
876     }
877
878     @Override
879     public BuilderType mergeFrom(
880         final byte[] data, final int off, final int len)
881         throws InvalidProtocolBufferException {
882       return super.mergeFrom(data, off, len);
883     }
884
885     @Override
886     public BuilderType mergeFrom(
887         final byte[] data,
888         final ExtensionRegistryLite extensionRegistry)
889         throws InvalidProtocolBufferException {
890       return super.mergeFrom(data, extensionRegistry);
891     }
892
893     @Override
894     public BuilderType mergeFrom(
895         final byte[] data, final int off, final int len,
896         final ExtensionRegistryLite extensionRegistry)
897         throws InvalidProtocolBufferException {
898       return super.mergeFrom(data, off, len, extensionRegistry);
899     }
900
901     @Override
902     public BuilderType mergeFrom(final InputStream input)
903         throws IOException {
904       return super.mergeFrom(input);
905     }
906
907     @Override
908     public BuilderType mergeFrom(
909         final InputStream input,
910         final ExtensionRegistryLite extensionRegistry)
911         throws IOException {
912       return super.mergeFrom(input, extensionRegistry);
913     }
914
915     @Override
916     public boolean mergeDelimitedFrom(final InputStream input)
917         throws IOException {
918       return super.mergeDelimitedFrom(input);
919     }
920
921     @Override
922     public boolean mergeDelimitedFrom(
923         final InputStream input,
924         final ExtensionRegistryLite extensionRegistry)
925         throws IOException {
926       return super.mergeDelimitedFrom(input, extensionRegistry);
927     }
928
929   }
930 }