Home | History | Annotate | Download | only in protobuf
      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 (at) google.com Kenton Varda
     43  */
     44 public abstract class GeneratedMessageLite extends AbstractMessageLite {
     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> {
     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
     57     public BuilderType clone() {
     58       throw new UnsupportedOperationException(
     59           "This is supposed to be overridden by subclasses.");
     60     }
     61 
     62     /** All subclasses implement this. */
     63     public abstract BuilderType mergeFrom(MessageType message);
     64 
     65     // Defined here for return type covariance.
     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      */
     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      */
     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 {
     95     protected ExtendableMessage() {}
     96     private final FieldSet<ExtensionDescriptor> extensions =
     97         FieldSet.newFieldSet();
     98 
     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. */
    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. */
    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")
    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")
    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. */
    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 
    166       private ExtensionWriter(boolean messageSetWireFormat) {
    167         if (iter.hasNext()) {
    168           next = iter.next();
    169         }
    170         this.messageSetWireFormat = messageSetWireFormat;
    171       }
    172 
    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 
    194     protected ExtensionWriter newExtensionWriter() {
    195       return new ExtensionWriter(false);
    196     }
    197     protected ExtensionWriter newMessageSetExtensionWriter() {
    198       return new ExtensionWriter(true);
    199     }
    200 
    201     /** Called by subclasses to compute the size of extensions. */
    202     protected int extensionsSerializedSize() {
    203       return extensions.getSerializedSize();
    204     }
    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> {
    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
    224     public BuilderType clone() {
    225       throw new UnsupportedOperationException(
    226           "This is supposed to be overridden by subclasses.");
    227     }
    228 
    229     @Override
    230     protected abstract MessageType internalGetResult();
    231 
    232     /** Check if a singular extension is present. */
    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. */
    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. */
    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. */
    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. */
    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. */
    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. */
    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. */
    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
    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 
    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>
    423       newGeneratedExtension() {
    424     return new GeneratedExtension<ContainingType, Type>();
    425   }
    426 
    427   private static final class ExtensionDescriptor
    428       implements FieldSet.FieldDescriptorLite<
    429         ExtensionDescriptor> {
    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 
    449     public int getNumber() {
    450       return number;
    451     }
    452 
    453     public WireFormat.FieldType getLiteType() {
    454       return type;
    455     }
    456 
    457     public WireFormat.JavaType getLiteJavaType() {
    458       return type.getJavaType();
    459     }
    460 
    461     public boolean isRepeated() {
    462       return isRepeated;
    463     }
    464 
    465     public boolean isPacked() {
    466       return isPacked;
    467     }
    468 
    469     public Internal.EnumLiteMap<?> getEnumType() {
    470       return enumTypeMap;
    471     }
    472 
    473     @SuppressWarnings("unchecked")
    474     public MessageLite.Builder internalMergeFrom(
    475         MessageLite.Builder to, MessageLite from) {
    476       return ((Builder) to).mergeFrom((GeneratedMessageLite) from);
    477     }
    478 
    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.
    499     private GeneratedExtension() {}
    500 
    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. */
    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. */
    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      */
    549     public ContainingType getContainingTypeDefaultInstance() {
    550       return containingTypeDefaultInstance;
    551     }
    552 
    553     /** Get the field number. */
    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      */
    562     public MessageLite getMessageDefaultInstance() {
    563       return messageDefaultInstance;
    564     }
    565   }
    566 }
    567