• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 java.io.IOException;
34 import java.util.Collections;
35 import java.util.Iterator;
36 import java.util.List;
37 import java.util.Map;
38 
39 /**
40  * Lite version of {@link GeneratedMessage}.
41  *
42  * @author kenton@google.com Kenton Varda
43  */
44 public abstract class GeneratedMessageLite extends AbstractMessageLite {
GeneratedMessageLite()45   protected GeneratedMessageLite() {}
46 
47   @SuppressWarnings("unchecked")
48   public abstract static class Builder<MessageType extends GeneratedMessageLite,
49                                        BuilderType extends Builder>
50       extends AbstractMessageLite.Builder<BuilderType> {
Builder()51     protected Builder() {}
52 
53     // This is implemented here only to work around an apparent bug in the
54     // Java compiler and/or build system.  See bug #1898463.  The mere presence
55     // of this dummy clone() implementation makes it go away.
56     @Override
clone()57     public BuilderType clone() {
58       throw new UnsupportedOperationException(
59           "This is supposed to be overridden by subclasses.");
60     }
61 
62     /** All subclasses implement this. */
mergeFrom(MessageType message)63     public abstract BuilderType mergeFrom(MessageType message);
64 
65     // Defined here for return type covariance.
getDefaultInstanceForType()66     public abstract MessageType getDefaultInstanceForType();
67 
68     /**
69      * Get the message being built.  We don't just pass this to the
70      * constructor because it becomes null when build() is called.
71      */
internalGetResult()72     protected abstract MessageType internalGetResult();
73 
74     /**
75      * Called by subclasses to parse an unknown field.
76      * @return {@code true} unless the tag is an end-group tag.
77      */
parseUnknownField( final CodedInputStream input, final ExtensionRegistryLite extensionRegistry, final int tag)78     protected boolean parseUnknownField(
79         final CodedInputStream input,
80         final ExtensionRegistryLite extensionRegistry,
81         final int tag) throws IOException {
82       return input.skipField(tag);
83     }
84   }
85 
86   // =================================================================
87   // Extensions-related stuff
88 
89   /**
90    * Lite equivalent of {@link GeneratedMessage.ExtendableMessage}.
91    */
92   public abstract static class ExtendableMessage<
93         MessageType extends ExtendableMessage<MessageType>>
94       extends GeneratedMessageLite {
ExtendableMessage()95     protected ExtendableMessage() {}
96     private final FieldSet<ExtensionDescriptor> extensions =
97         FieldSet.newFieldSet();
98 
verifyExtensionContainingType( final GeneratedExtension<MessageType, ?> extension)99     private void verifyExtensionContainingType(
100         final GeneratedExtension<MessageType, ?> extension) {
101       if (extension.getContainingTypeDefaultInstance() !=
102           getDefaultInstanceForType()) {
103         // This can only happen if someone uses unchecked operations.
104         throw new IllegalArgumentException(
105           "This extension is for a different message type.  Please make " +
106           "sure that you are not suppressing any generics type warnings.");
107       }
108     }
109 
110     /** Check if a singular extension is present. */
hasExtension( final GeneratedExtension<MessageType, ?> extension)111     public final boolean hasExtension(
112         final GeneratedExtension<MessageType, ?> extension) {
113       verifyExtensionContainingType(extension);
114       return extensions.hasField(extension.descriptor);
115     }
116 
117     /** Get the number of elements in a repeated extension. */
getExtensionCount( final GeneratedExtension<MessageType, List<Type>> extension)118     public final <Type> int getExtensionCount(
119         final GeneratedExtension<MessageType, List<Type>> extension) {
120       verifyExtensionContainingType(extension);
121       return extensions.getRepeatedFieldCount(extension.descriptor);
122     }
123 
124     /** Get the value of an extension. */
125     @SuppressWarnings("unchecked")
getExtension( final GeneratedExtension<MessageType, Type> extension)126     public final <Type> Type getExtension(
127         final GeneratedExtension<MessageType, Type> extension) {
128       verifyExtensionContainingType(extension);
129       final Object value = extensions.getField(extension.descriptor);
130       if (value == null) {
131         return extension.defaultValue;
132       } else {
133         return (Type) value;
134       }
135     }
136 
137     /** Get one element of a repeated extension. */
138     @SuppressWarnings("unchecked")
getExtension( final GeneratedExtension<MessageType, List<Type>> extension, final int index)139     public final <Type> Type getExtension(
140         final GeneratedExtension<MessageType, List<Type>> extension,
141         final int index) {
142       verifyExtensionContainingType(extension);
143       return (Type) extensions.getRepeatedField(extension.descriptor, index);
144     }
145 
146     /** Called by subclasses to check if all extensions are initialized. */
extensionsAreInitialized()147     protected boolean extensionsAreInitialized() {
148       return extensions.isInitialized();
149     }
150 
151     /**
152      * Used by subclasses to serialize extensions.  Extension ranges may be
153      * interleaved with field numbers, but we must write them in canonical
154      * (sorted by field number) order.  ExtensionWriter helps us write
155      * individual ranges of extensions at once.
156      */
157     protected class ExtensionWriter {
158       // Imagine how much simpler this code would be if Java iterators had
159       // a way to get the next element without advancing the iterator.
160 
161       private final Iterator<Map.Entry<ExtensionDescriptor, Object>> iter =
162             extensions.iterator();
163       private Map.Entry<ExtensionDescriptor, Object> next;
164       private final boolean messageSetWireFormat;
165 
ExtensionWriter(boolean messageSetWireFormat)166       private ExtensionWriter(boolean messageSetWireFormat) {
167         if (iter.hasNext()) {
168           next = iter.next();
169         }
170         this.messageSetWireFormat = messageSetWireFormat;
171       }
172 
writeUntil(final int end, final CodedOutputStream output)173       public void writeUntil(final int end, final CodedOutputStream output)
174                              throws IOException {
175         while (next != null && next.getKey().getNumber() < end) {
176           ExtensionDescriptor extension = next.getKey();
177           if (messageSetWireFormat && extension.getLiteJavaType() ==
178                   WireFormat.JavaType.MESSAGE &&
179               !extension.isRepeated()) {
180             output.writeMessageSetExtension(extension.getNumber(),
181                                             (MessageLite) next.getValue());
182           } else {
183             FieldSet.writeField(extension, next.getValue(), output);
184           }
185           if (iter.hasNext()) {
186             next = iter.next();
187           } else {
188             next = null;
189           }
190         }
191       }
192     }
193 
newExtensionWriter()194     protected ExtensionWriter newExtensionWriter() {
195       return new ExtensionWriter(false);
196     }
newMessageSetExtensionWriter()197     protected ExtensionWriter newMessageSetExtensionWriter() {
198       return new ExtensionWriter(true);
199     }
200 
201     /** Called by subclasses to compute the size of extensions. */
extensionsSerializedSize()202     protected int extensionsSerializedSize() {
203       return extensions.getSerializedSize();
204     }
extensionsSerializedSizeAsMessageSet()205     protected int extensionsSerializedSizeAsMessageSet() {
206       return extensions.getMessageSetSerializedSize();
207     }
208   }
209 
210   /**
211    * Lite equivalent of {@link GeneratedMessage.ExtendableBuilder}.
212    */
213   @SuppressWarnings("unchecked")
214   public abstract static class ExtendableBuilder<
215         MessageType extends ExtendableMessage<MessageType>,
216         BuilderType extends ExtendableBuilder<MessageType, BuilderType>>
217       extends Builder<MessageType, BuilderType> {
ExtendableBuilder()218     protected ExtendableBuilder() {}
219 
220     // This is implemented here only to work around an apparent bug in the
221     // Java compiler and/or build system.  See bug #1898463.  The mere presence
222     // of this dummy clone() implementation makes it go away.
223     @Override
clone()224     public BuilderType clone() {
225       throw new UnsupportedOperationException(
226           "This is supposed to be overridden by subclasses.");
227     }
228 
229     @Override
internalGetResult()230     protected abstract MessageType internalGetResult();
231 
232     /** Check if a singular extension is present. */
hasExtension( final GeneratedExtension<MessageType, ?> extension)233     public final boolean hasExtension(
234         final GeneratedExtension<MessageType, ?> extension) {
235       return internalGetResult().hasExtension(extension);
236     }
237 
238     /** Get the number of elements in a repeated extension. */
getExtensionCount( final GeneratedExtension<MessageType, List<Type>> extension)239     public final <Type> int getExtensionCount(
240         final GeneratedExtension<MessageType, List<Type>> extension) {
241       return internalGetResult().getExtensionCount(extension);
242     }
243 
244     /** Get the value of an extension. */
getExtension( final GeneratedExtension<MessageType, Type> extension)245     public final <Type> Type getExtension(
246         final GeneratedExtension<MessageType, Type> extension) {
247       return internalGetResult().getExtension(extension);
248     }
249 
250     /** Get one element of a repeated extension. */
getExtension( final GeneratedExtension<MessageType, List<Type>> extension, final int index)251     public final <Type> Type getExtension(
252         final GeneratedExtension<MessageType, List<Type>> extension,
253         final int index) {
254       return internalGetResult().getExtension(extension, index);
255     }
256 
257     /** Set the value of an extension. */
setExtension( final GeneratedExtension<MessageType, Type> extension, final Type value)258     public final <Type> BuilderType setExtension(
259         final GeneratedExtension<MessageType, Type> extension,
260         final Type value) {
261       final ExtendableMessage<MessageType> message = internalGetResult();
262       message.verifyExtensionContainingType(extension);
263       message.extensions.setField(extension.descriptor, value);
264       return (BuilderType) this;
265     }
266 
267     /** Set the value of one element of a repeated extension. */
setExtension( final GeneratedExtension<MessageType, List<Type>> extension, final int index, final Type value)268     public final <Type> BuilderType setExtension(
269         final GeneratedExtension<MessageType, List<Type>> extension,
270         final int index, final Type value) {
271       final ExtendableMessage<MessageType> message = internalGetResult();
272       message.verifyExtensionContainingType(extension);
273       message.extensions.setRepeatedField(extension.descriptor, index, value);
274       return (BuilderType) this;
275     }
276 
277     /** Append a value to a repeated extension. */
addExtension( final GeneratedExtension<MessageType, List<Type>> extension, final Type value)278     public final <Type> BuilderType addExtension(
279         final GeneratedExtension<MessageType, List<Type>> extension,
280         final Type value) {
281       final ExtendableMessage<MessageType> message = internalGetResult();
282       message.verifyExtensionContainingType(extension);
283       message.extensions.addRepeatedField(extension.descriptor, value);
284       return (BuilderType) this;
285     }
286 
287     /** Clear an extension. */
clearExtension( final GeneratedExtension<MessageType, ?> extension)288     public final <Type> BuilderType clearExtension(
289         final GeneratedExtension<MessageType, ?> extension) {
290       final ExtendableMessage<MessageType> message = internalGetResult();
291       message.verifyExtensionContainingType(extension);
292       message.extensions.clearField(extension.descriptor);
293       return (BuilderType) this;
294     }
295 
296     /**
297      * Called by subclasses to parse an unknown field or an extension.
298      * @return {@code true} unless the tag is an end-group tag.
299      */
300     @Override
parseUnknownField( final CodedInputStream input, final ExtensionRegistryLite extensionRegistry, final int tag)301     protected boolean parseUnknownField(
302         final CodedInputStream input,
303         final ExtensionRegistryLite extensionRegistry,
304         final int tag) throws IOException {
305       final FieldSet<ExtensionDescriptor> extensions =
306           ((ExtendableMessage) internalGetResult()).extensions;
307 
308       final int wireType = WireFormat.getTagWireType(tag);
309       final int fieldNumber = WireFormat.getTagFieldNumber(tag);
310 
311       final GeneratedExtension<MessageType, ?> extension =
312         extensionRegistry.findLiteExtensionByNumber(
313             getDefaultInstanceForType(), fieldNumber);
314 
315       boolean unknown = false;
316       boolean packed = false;
317       if (extension == null) {
318         unknown = true;  // Unknown field.
319       } else if (wireType == FieldSet.getWireFormatForFieldType(
320                    extension.descriptor.getLiteType(),
321                    false  /* isPacked */)) {
322         packed = false;  // Normal, unpacked value.
323       } else if (extension.descriptor.isRepeated &&
324                  extension.descriptor.type.isPackable() &&
325                  wireType == FieldSet.getWireFormatForFieldType(
326                    extension.descriptor.getLiteType(),
327                    true  /* isPacked */)) {
328         packed = true;  // Packed value.
329       } else {
330         unknown = true;  // Wrong wire type.
331       }
332 
333       if (unknown) {  // Unknown field or wrong wire type.  Skip.
334         return input.skipField(tag);
335       }
336 
337       if (packed) {
338         final int length = input.readRawVarint32();
339         final int limit = input.pushLimit(length);
340         if (extension.descriptor.getLiteType() == WireFormat.FieldType.ENUM) {
341           while (input.getBytesUntilLimit() > 0) {
342             final int rawValue = input.readEnum();
343             final Object value =
344                 extension.descriptor.getEnumType().findValueByNumber(rawValue);
345             if (value == null) {
346               // If the number isn't recognized as a valid value for this
347               // enum, drop it (don't even add it to unknownFields).
348               return true;
349             }
350             extensions.addRepeatedField(extension.descriptor, value);
351           }
352         } else {
353           while (input.getBytesUntilLimit() > 0) {
354             final Object value =
355               FieldSet.readPrimitiveField(input,
356                                           extension.descriptor.getLiteType());
357             extensions.addRepeatedField(extension.descriptor, value);
358           }
359         }
360         input.popLimit(limit);
361       } else {
362         final Object value;
363         switch (extension.descriptor.getLiteJavaType()) {
364           case MESSAGE: {
365             MessageLite.Builder subBuilder = null;
366             if (!extension.descriptor.isRepeated()) {
367               MessageLite existingValue =
368                   (MessageLite) extensions.getField(extension.descriptor);
369               if (existingValue != null) {
370                 subBuilder = existingValue.toBuilder();
371               }
372             }
373             if (subBuilder == null) {
374               subBuilder = extension.messageDefaultInstance.newBuilderForType();
375             }
376             if (extension.descriptor.getLiteType() ==
377                 WireFormat.FieldType.GROUP) {
378               input.readGroup(extension.getNumber(),
379                               subBuilder, extensionRegistry);
380             } else {
381               input.readMessage(subBuilder, extensionRegistry);
382             }
383             value = subBuilder.build();
384             break;
385           }
386           case ENUM:
387             final int rawValue = input.readEnum();
388             value = extension.descriptor.getEnumType()
389                              .findValueByNumber(rawValue);
390             // If the number isn't recognized as a valid value for this enum,
391             // drop it.
392             if (value == null) {
393               return true;
394             }
395             break;
396           default:
397             value = FieldSet.readPrimitiveField(input,
398                 extension.descriptor.getLiteType());
399             break;
400         }
401 
402         if (extension.descriptor.isRepeated()) {
403           extensions.addRepeatedField(extension.descriptor, value);
404         } else {
405           extensions.setField(extension.descriptor, value);
406         }
407       }
408 
409       return true;
410     }
411 
mergeExtensionFields(final MessageType other)412     protected final void mergeExtensionFields(final MessageType other) {
413       ((ExtendableMessage) internalGetResult()).extensions.mergeFrom(
414           ((ExtendableMessage) other).extensions);
415     }
416   }
417 
418   // -----------------------------------------------------------------
419 
420   /** For use by generated code only. */
421   public static <ContainingType extends MessageLite, Type>
422       GeneratedExtension<ContainingType, Type>
newGeneratedExtension()423       newGeneratedExtension() {
424     return new GeneratedExtension<ContainingType, Type>();
425   }
426 
427   private static final class ExtensionDescriptor
428       implements FieldSet.FieldDescriptorLite<
429         ExtensionDescriptor> {
ExtensionDescriptor( final Internal.EnumLiteMap<?> enumTypeMap, final int number, final WireFormat.FieldType type, final boolean isRepeated, final boolean isPacked)430     private ExtensionDescriptor(
431         final Internal.EnumLiteMap<?> enumTypeMap,
432         final int number,
433         final WireFormat.FieldType type,
434         final boolean isRepeated,
435         final boolean isPacked) {
436       this.enumTypeMap = enumTypeMap;
437       this.number = number;
438       this.type = type;
439       this.isRepeated = isRepeated;
440       this.isPacked = isPacked;
441     }
442 
443     private final Internal.EnumLiteMap<?> enumTypeMap;
444     private final int number;
445     private final WireFormat.FieldType type;
446     private final boolean isRepeated;
447     private final boolean isPacked;
448 
getNumber()449     public int getNumber() {
450       return number;
451     }
452 
getLiteType()453     public WireFormat.FieldType getLiteType() {
454       return type;
455     }
456 
getLiteJavaType()457     public WireFormat.JavaType getLiteJavaType() {
458       return type.getJavaType();
459     }
460 
isRepeated()461     public boolean isRepeated() {
462       return isRepeated;
463     }
464 
isPacked()465     public boolean isPacked() {
466       return isPacked;
467     }
468 
getEnumType()469     public Internal.EnumLiteMap<?> getEnumType() {
470       return enumTypeMap;
471     }
472 
473     @SuppressWarnings("unchecked")
internalMergeFrom( MessageLite.Builder to, MessageLite from)474     public MessageLite.Builder internalMergeFrom(
475         MessageLite.Builder to, MessageLite from) {
476       return ((Builder) to).mergeFrom((GeneratedMessageLite) from);
477     }
478 
compareTo(ExtensionDescriptor other)479     public int compareTo(ExtensionDescriptor other) {
480       return number - other.number;
481     }
482   }
483 
484   /**
485    * Lite equivalent to {@link GeneratedMessage.GeneratedExtension}.
486    *
487    * Users should ignore the contents of this class and only use objects of
488    * this type as parameters to extension accessors and ExtensionRegistry.add().
489    */
490   public static final class GeneratedExtension<
491       ContainingType extends MessageLite, Type> {
492     // We can't always initialize a GeneratedExtension when we first construct
493     // it due to initialization order difficulties (namely, the default
494     // instances may not have been constructed yet).  So, we construct an
495     // uninitialized GeneratedExtension once, then call internalInit() on it
496     // later.  Generated code will always call internalInit() on all extensions
497     // as part of the static initialization code, and internalInit() throws an
498     // exception if called more than once, so this method is useless to users.
GeneratedExtension()499     private GeneratedExtension() {}
500 
internalInit( final ContainingType containingTypeDefaultInstance, final Type defaultValue, final MessageLite messageDefaultInstance, final ExtensionDescriptor descriptor)501     private void internalInit(
502         final ContainingType containingTypeDefaultInstance,
503         final Type defaultValue,
504         final MessageLite messageDefaultInstance,
505         final ExtensionDescriptor descriptor) {
506       this.containingTypeDefaultInstance = containingTypeDefaultInstance;
507       this.defaultValue = defaultValue;
508       this.messageDefaultInstance = messageDefaultInstance;
509       this.descriptor = descriptor;
510     }
511 
512     /** For use by generated code only. */
internalInitSingular( final ContainingType containingTypeDefaultInstance, final Type defaultValue, final MessageLite messageDefaultInstance, final Internal.EnumLiteMap<?> enumTypeMap, final int number, final WireFormat.FieldType type)513     public void internalInitSingular(
514         final ContainingType containingTypeDefaultInstance,
515         final Type defaultValue,
516         final MessageLite messageDefaultInstance,
517         final Internal.EnumLiteMap<?> enumTypeMap,
518         final int number,
519         final WireFormat.FieldType type) {
520       internalInit(
521         containingTypeDefaultInstance, defaultValue, messageDefaultInstance,
522         new ExtensionDescriptor(enumTypeMap, number, type,
523           false /* isRepeated */, false /* isPacked */));
524     }
525 
526     /** For use by generated code only. */
internalInitRepeated( final ContainingType containingTypeDefaultInstance, final MessageLite messageDefaultInstance, final Internal.EnumLiteMap<?> enumTypeMap, final int number, final WireFormat.FieldType type, final boolean isPacked)527     public void internalInitRepeated(
528         final ContainingType containingTypeDefaultInstance,
529         final MessageLite messageDefaultInstance,
530         final Internal.EnumLiteMap<?> enumTypeMap,
531         final int number,
532         final WireFormat.FieldType type,
533         final boolean isPacked) {
534       internalInit(
535         containingTypeDefaultInstance, (Type) Collections.emptyList(),
536         messageDefaultInstance,
537         new ExtensionDescriptor(
538           enumTypeMap, number, type, true /* isRepeated */, isPacked));
539     }
540 
541     private ContainingType containingTypeDefaultInstance;
542     private Type defaultValue;
543     private MessageLite messageDefaultInstance;
544     private ExtensionDescriptor descriptor;
545 
546     /**
547      * Default instance of the type being extended, used to identify that type.
548      */
getContainingTypeDefaultInstance()549     public ContainingType getContainingTypeDefaultInstance() {
550       return containingTypeDefaultInstance;
551     }
552 
553     /** Get the field number. */
getNumber()554     public int getNumber() {
555       return descriptor.getNumber();
556     }
557 
558     /**
559      * If the extension is an embedded message, this is the default instance of
560      * that type.
561      */
getMessageDefaultInstance()562     public MessageLite getMessageDefaultInstance() {
563       return messageDefaultInstance;
564     }
565   }
566 }
567