diff --git a/.gitignore b/.gitignore
index edb9f61..3dfdefe 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,4 +7,5 @@
 vendor
 build
 go.mod
-go.sum
\ No newline at end of file
+go.sum
+proto
\ No newline at end of file
diff --git a/menu-feed/README.md b/menu-feed/README.md
new file mode 100644
index 0000000..05e37fe
--- /dev/null
+++ b/menu-feed/README.md
@@ -0,0 +1,5 @@
+#Creating Google Ordering Redirect Menu Feed Examples
+
+- Download the lastest version of protoc from https://github.com/protocolbuffers/protobuf/releases
+- Create a proto directory for source protos inside project directory. For Java use java/src/main/proto.
+- Download the protos from https://developers.google.com/actions-center/verticals/ordering/redirect/reference/menu-feeds/menus-feed-proto-bundle
diff --git a/menu-feed/go/feed.go b/menu-feed/go/feed.go
index 2f5e0f7..4fa2a27 100644
--- a/menu-feed/go/feed.go
+++ b/menu-feed/go/feed.go
@@ -13,6 +13,7 @@
 	money "google.golang.org/genproto/googleapis/type/money"
 	"google.golang.org/protobuf/encoding/protojson"
 	timestamppb "google.golang.org/protobuf/types/known/timestamppb"
+	proto "google.golang.org/protobuf/proto"
 )
 
 func main() {
@@ -126,6 +127,15 @@
 			}},
 	}
 
+	// Example testing for menu feed size
+    // Protocol buffer message must be less than 2 GiB
+    // https://protobuf.dev/programming-guides/proto-limits/
+    // It is recommended to not exceed 200 MB, as there is an Actions
+    // Center limit of 200 MB per file after compression.
+	if proto.Size(feed) > 200 * 1024 * 1024 {
+		// create new file
+	}
+
 	marshalOptions := protojson.MarshalOptions{
 		UseProtoNames: true,
 	}
diff --git a/menu-feed/java/pom.xml b/menu-feed/java/pom.xml
index f056542..44b281e 100644
--- a/menu-feed/java/pom.xml
+++ b/menu-feed/java/pom.xml
@@ -8,13 +8,13 @@
     <artifactId>feed</artifactId>
     <version>1.0.0</version>
 
-    <properties>
+   <properties>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
-        <java.version>11.0</java.version>
-        <maven.compiler.source>11</maven.compiler.source>
-        <maven.compiler.target>11</maven.compiler.target>
-        <protobuf.version>3.22.0</protobuf.version>
+        <java.version>23.0</java.version>
+        <maven.compiler.source>23</maven.compiler.source>
+        <maven.compiler.target>23</maven.compiler.target>
+        <protobuf.version>4.29.3</protobuf.version>
     </properties>
 
     <dependencies>
@@ -73,6 +73,22 @@
                     </execution>
                 </executions>
             </plugin>
+            <plugin>
+                <groupId>org.xolstice.maven.plugins</groupId>
+                <artifactId>protobuf-maven-plugin</artifactId>
+                <version>0.6.1</version>
+                <configuration>
+                    <protocExecutable>protoc</protocExecutable>
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>compile</goal>
+                            <goal>test-compile</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
         </plugins>
     </build>
 
diff --git a/menu-feed/java/src/main/java/com/example/Feed.java b/menu-feed/java/src/main/java/com/example/Feed.java
index a689d81..51e3348 100644
--- a/menu-feed/java/src/main/java/com/example/Feed.java
+++ b/menu-feed/java/src/main/java/com/example/Feed.java
@@ -23,6 +23,9 @@
  */
 public class Feed {
 
+  // 200 MB
+  public static final int MAX_BYTES_DATA_FILE = 200 * 1024 * 1024;
+
   public static void main(String[] args) throws InvalidProtocolBufferException {
     Feed feed = new Feed();
     feed.createMenuFeed();
@@ -95,6 +98,16 @@
             .addData(MenuComponent.newBuilder().setItem(item))
             .addData(MenuComponent.newBuilder().setOption(option));
 
+    // Example testing for menu feed size
+    // Protocol buffer message must be less than 2 GiB
+    // https://protobuf.dev/programming-guides/proto-limits/
+    // It is recommended to not exceed 200 MB, as there is an Actions
+    // Center limit of 200 MB per file after compression.
+    int size = foodMenuFeed.build().getSerializedSize();
+    if (size > MAX_BYTES_DATA_FILE) {
+        // create new file
+    }
+
     String feedJSON =
         JsonFormat.printer()
             .omittingInsignificantWhitespace()
diff --git a/menu-feed/java/src/main/java/com/google/type/LocalizedText.java b/menu-feed/java/src/main/java/com/google/type/LocalizedText.java
deleted file mode 100644
index 716ed77..0000000
--- a/menu-feed/java/src/main/java/com/google/type/LocalizedText.java
+++ /dev/null
@@ -1,728 +0,0 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: localized_text.proto
-
-package com.google.type;
-
-/**
- * <pre>
- * Localized variant of a text in a particular language.
- * </pre>
- *
- * Protobuf type {@code google.type.LocalizedText}
- */
-public final class LocalizedText extends
-    com.google.protobuf.GeneratedMessageV3 implements
-    // @@protoc_insertion_point(message_implements:google.type.LocalizedText)
-    LocalizedTextOrBuilder {
-private static final long serialVersionUID = 0L;
-  // Use LocalizedText.newBuilder() to construct.
-  private LocalizedText(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
-    super(builder);
-  }
-  private LocalizedText() {
-    text_ = "";
-    languageCode_ = "";
-  }
-
-  @java.lang.Override
-  @SuppressWarnings({"unused"})
-  protected java.lang.Object newInstance(
-      UnusedPrivateParameter unused) {
-    return new LocalizedText();
-  }
-
-  public static final com.google.protobuf.Descriptors.Descriptor
-      getDescriptor() {
-    return com.google.type.LocalizedTextProto.internal_static_google_type_LocalizedText_descriptor;
-  }
-
-  @java.lang.Override
-  protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-      internalGetFieldAccessorTable() {
-    return com.google.type.LocalizedTextProto.internal_static_google_type_LocalizedText_fieldAccessorTable
-        .ensureFieldAccessorsInitialized(
-            com.google.type.LocalizedText.class, com.google.type.LocalizedText.Builder.class);
-  }
-
-  public static final int TEXT_FIELD_NUMBER = 1;
-  @SuppressWarnings("serial")
-  private volatile java.lang.Object text_ = "";
-  /**
-   * <pre>
-   * Localized string in the language corresponding to `language_code' below.
-   * </pre>
-   *
-   * <code>string text = 1;</code>
-   * @return The text.
-   */
-  @java.lang.Override
-  public java.lang.String getText() {
-    java.lang.Object ref = text_;
-    if (ref instanceof java.lang.String) {
-      return (java.lang.String) ref;
-    } else {
-      com.google.protobuf.ByteString bs = 
-          (com.google.protobuf.ByteString) ref;
-      java.lang.String s = bs.toStringUtf8();
-      text_ = s;
-      return s;
-    }
-  }
-  /**
-   * <pre>
-   * Localized string in the language corresponding to `language_code' below.
-   * </pre>
-   *
-   * <code>string text = 1;</code>
-   * @return The bytes for text.
-   */
-  @java.lang.Override
-  public com.google.protobuf.ByteString
-      getTextBytes() {
-    java.lang.Object ref = text_;
-    if (ref instanceof java.lang.String) {
-      com.google.protobuf.ByteString b = 
-          com.google.protobuf.ByteString.copyFromUtf8(
-              (java.lang.String) ref);
-      text_ = b;
-      return b;
-    } else {
-      return (com.google.protobuf.ByteString) ref;
-    }
-  }
-
-  public static final int LANGUAGE_CODE_FIELD_NUMBER = 2;
-  @SuppressWarnings("serial")
-  private volatile java.lang.Object languageCode_ = "";
-  /**
-   * <pre>
-   * The text's BCP-47 language code, such as "en-US" or "sr-Latn".
-   *
-   * For more information, see
-   * http://www.unicode.org/reports/tr35/#Unicode_locale_identifier.
-   * </pre>
-   *
-   * <code>string language_code = 2;</code>
-   * @return The languageCode.
-   */
-  @java.lang.Override
-  public java.lang.String getLanguageCode() {
-    java.lang.Object ref = languageCode_;
-    if (ref instanceof java.lang.String) {
-      return (java.lang.String) ref;
-    } else {
-      com.google.protobuf.ByteString bs = 
-          (com.google.protobuf.ByteString) ref;
-      java.lang.String s = bs.toStringUtf8();
-      languageCode_ = s;
-      return s;
-    }
-  }
-  /**
-   * <pre>
-   * The text's BCP-47 language code, such as "en-US" or "sr-Latn".
-   *
-   * For more information, see
-   * http://www.unicode.org/reports/tr35/#Unicode_locale_identifier.
-   * </pre>
-   *
-   * <code>string language_code = 2;</code>
-   * @return The bytes for languageCode.
-   */
-  @java.lang.Override
-  public com.google.protobuf.ByteString
-      getLanguageCodeBytes() {
-    java.lang.Object ref = languageCode_;
-    if (ref instanceof java.lang.String) {
-      com.google.protobuf.ByteString b = 
-          com.google.protobuf.ByteString.copyFromUtf8(
-              (java.lang.String) ref);
-      languageCode_ = b;
-      return b;
-    } else {
-      return (com.google.protobuf.ByteString) ref;
-    }
-  }
-
-  private byte memoizedIsInitialized = -1;
-  @java.lang.Override
-  public final boolean isInitialized() {
-    byte isInitialized = memoizedIsInitialized;
-    if (isInitialized == 1) return true;
-    if (isInitialized == 0) return false;
-
-    memoizedIsInitialized = 1;
-    return true;
-  }
-
-  @java.lang.Override
-  public void writeTo(com.google.protobuf.CodedOutputStream output)
-                      throws java.io.IOException {
-    if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(text_)) {
-      com.google.protobuf.GeneratedMessageV3.writeString(output, 1, text_);
-    }
-    if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(languageCode_)) {
-      com.google.protobuf.GeneratedMessageV3.writeString(output, 2, languageCode_);
-    }
-    getUnknownFields().writeTo(output);
-  }
-
-  @java.lang.Override
-  public int getSerializedSize() {
-    int size = memoizedSize;
-    if (size != -1) return size;
-
-    size = 0;
-    if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(text_)) {
-      size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, text_);
-    }
-    if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(languageCode_)) {
-      size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, languageCode_);
-    }
-    size += getUnknownFields().getSerializedSize();
-    memoizedSize = size;
-    return size;
-  }
-
-  @java.lang.Override
-  public boolean equals(final java.lang.Object obj) {
-    if (obj == this) {
-     return true;
-    }
-    if (!(obj instanceof com.google.type.LocalizedText)) {
-      return super.equals(obj);
-    }
-    com.google.type.LocalizedText other = (com.google.type.LocalizedText) obj;
-
-    if (!getText()
-        .equals(other.getText())) return false;
-    if (!getLanguageCode()
-        .equals(other.getLanguageCode())) return false;
-    if (!getUnknownFields().equals(other.getUnknownFields())) return false;
-    return true;
-  }
-
-  @java.lang.Override
-  public int hashCode() {
-    if (memoizedHashCode != 0) {
-      return memoizedHashCode;
-    }
-    int hash = 41;
-    hash = (19 * hash) + getDescriptor().hashCode();
-    hash = (37 * hash) + TEXT_FIELD_NUMBER;
-    hash = (53 * hash) + getText().hashCode();
-    hash = (37 * hash) + LANGUAGE_CODE_FIELD_NUMBER;
-    hash = (53 * hash) + getLanguageCode().hashCode();
-    hash = (29 * hash) + getUnknownFields().hashCode();
-    memoizedHashCode = hash;
-    return hash;
-  }
-
-  public static com.google.type.LocalizedText parseFrom(
-      java.nio.ByteBuffer data)
-      throws com.google.protobuf.InvalidProtocolBufferException {
-    return PARSER.parseFrom(data);
-  }
-  public static com.google.type.LocalizedText parseFrom(
-      java.nio.ByteBuffer data,
-      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-      throws com.google.protobuf.InvalidProtocolBufferException {
-    return PARSER.parseFrom(data, extensionRegistry);
-  }
-  public static com.google.type.LocalizedText parseFrom(
-      com.google.protobuf.ByteString data)
-      throws com.google.protobuf.InvalidProtocolBufferException {
-    return PARSER.parseFrom(data);
-  }
-  public static com.google.type.LocalizedText parseFrom(
-      com.google.protobuf.ByteString data,
-      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-      throws com.google.protobuf.InvalidProtocolBufferException {
-    return PARSER.parseFrom(data, extensionRegistry);
-  }
-  public static com.google.type.LocalizedText parseFrom(byte[] data)
-      throws com.google.protobuf.InvalidProtocolBufferException {
-    return PARSER.parseFrom(data);
-  }
-  public static com.google.type.LocalizedText parseFrom(
-      byte[] data,
-      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-      throws com.google.protobuf.InvalidProtocolBufferException {
-    return PARSER.parseFrom(data, extensionRegistry);
-  }
-  public static com.google.type.LocalizedText parseFrom(java.io.InputStream input)
-      throws java.io.IOException {
-    return com.google.protobuf.GeneratedMessageV3
-        .parseWithIOException(PARSER, input);
-  }
-  public static com.google.type.LocalizedText parseFrom(
-      java.io.InputStream input,
-      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-      throws java.io.IOException {
-    return com.google.protobuf.GeneratedMessageV3
-        .parseWithIOException(PARSER, input, extensionRegistry);
-  }
-  public static com.google.type.LocalizedText parseDelimitedFrom(java.io.InputStream input)
-      throws java.io.IOException {
-    return com.google.protobuf.GeneratedMessageV3
-        .parseDelimitedWithIOException(PARSER, input);
-  }
-  public static com.google.type.LocalizedText parseDelimitedFrom(
-      java.io.InputStream input,
-      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-      throws java.io.IOException {
-    return com.google.protobuf.GeneratedMessageV3
-        .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
-  }
-  public static com.google.type.LocalizedText parseFrom(
-      com.google.protobuf.CodedInputStream input)
-      throws java.io.IOException {
-    return com.google.protobuf.GeneratedMessageV3
-        .parseWithIOException(PARSER, input);
-  }
-  public static com.google.type.LocalizedText parseFrom(
-      com.google.protobuf.CodedInputStream input,
-      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-      throws java.io.IOException {
-    return com.google.protobuf.GeneratedMessageV3
-        .parseWithIOException(PARSER, input, extensionRegistry);
-  }
-
-  @java.lang.Override
-  public Builder newBuilderForType() { return newBuilder(); }
-  public static Builder newBuilder() {
-    return DEFAULT_INSTANCE.toBuilder();
-  }
-  public static Builder newBuilder(com.google.type.LocalizedText prototype) {
-    return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
-  }
-  @java.lang.Override
-  public Builder toBuilder() {
-    return this == DEFAULT_INSTANCE
-        ? new Builder() : new Builder().mergeFrom(this);
-  }
-
-  @java.lang.Override
-  protected Builder newBuilderForType(
-      com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-    Builder builder = new Builder(parent);
-    return builder;
-  }
-  /**
-   * <pre>
-   * Localized variant of a text in a particular language.
-   * </pre>
-   *
-   * Protobuf type {@code google.type.LocalizedText}
-   */
-  public static final class Builder extends
-      com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
-      // @@protoc_insertion_point(builder_implements:google.type.LocalizedText)
-      com.google.type.LocalizedTextOrBuilder {
-    public static final com.google.protobuf.Descriptors.Descriptor
-        getDescriptor() {
-      return com.google.type.LocalizedTextProto.internal_static_google_type_LocalizedText_descriptor;
-    }
-
-    @java.lang.Override
-    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-        internalGetFieldAccessorTable() {
-      return com.google.type.LocalizedTextProto.internal_static_google_type_LocalizedText_fieldAccessorTable
-          .ensureFieldAccessorsInitialized(
-              com.google.type.LocalizedText.class, com.google.type.LocalizedText.Builder.class);
-    }
-
-    // Construct using com.google.type.LocalizedText.newBuilder()
-    private Builder() {
-
-    }
-
-    private Builder(
-        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-      super(parent);
-
-    }
-    @java.lang.Override
-    public Builder clear() {
-      super.clear();
-      bitField0_ = 0;
-      text_ = "";
-      languageCode_ = "";
-      return this;
-    }
-
-    @java.lang.Override
-    public com.google.protobuf.Descriptors.Descriptor
-        getDescriptorForType() {
-      return com.google.type.LocalizedTextProto.internal_static_google_type_LocalizedText_descriptor;
-    }
-
-    @java.lang.Override
-    public com.google.type.LocalizedText getDefaultInstanceForType() {
-      return com.google.type.LocalizedText.getDefaultInstance();
-    }
-
-    @java.lang.Override
-    public com.google.type.LocalizedText build() {
-      com.google.type.LocalizedText result = buildPartial();
-      if (!result.isInitialized()) {
-        throw newUninitializedMessageException(result);
-      }
-      return result;
-    }
-
-    @java.lang.Override
-    public com.google.type.LocalizedText buildPartial() {
-      com.google.type.LocalizedText result = new com.google.type.LocalizedText(this);
-      if (bitField0_ != 0) { buildPartial0(result); }
-      onBuilt();
-      return result;
-    }
-
-    private void buildPartial0(com.google.type.LocalizedText result) {
-      int from_bitField0_ = bitField0_;
-      if (((from_bitField0_ & 0x00000001) != 0)) {
-        result.text_ = text_;
-      }
-      if (((from_bitField0_ & 0x00000002) != 0)) {
-        result.languageCode_ = languageCode_;
-      }
-    }
-
-    @java.lang.Override
-    public Builder mergeFrom(com.google.protobuf.Message other) {
-      if (other instanceof com.google.type.LocalizedText) {
-        return mergeFrom((com.google.type.LocalizedText)other);
-      } else {
-        super.mergeFrom(other);
-        return this;
-      }
-    }
-
-    public Builder mergeFrom(com.google.type.LocalizedText other) {
-      if (other == com.google.type.LocalizedText.getDefaultInstance()) return this;
-      if (!other.getText().isEmpty()) {
-        text_ = other.text_;
-        bitField0_ |= 0x00000001;
-        onChanged();
-      }
-      if (!other.getLanguageCode().isEmpty()) {
-        languageCode_ = other.languageCode_;
-        bitField0_ |= 0x00000002;
-        onChanged();
-      }
-      this.mergeUnknownFields(other.getUnknownFields());
-      onChanged();
-      return this;
-    }
-
-    @java.lang.Override
-    public final boolean isInitialized() {
-      return true;
-    }
-
-    @java.lang.Override
-    public Builder mergeFrom(
-        com.google.protobuf.CodedInputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      if (extensionRegistry == null) {
-        throw new java.lang.NullPointerException();
-      }
-      try {
-        boolean done = false;
-        while (!done) {
-          int tag = input.readTag();
-          switch (tag) {
-            case 0:
-              done = true;
-              break;
-            case 10: {
-              text_ = input.readStringRequireUtf8();
-              bitField0_ |= 0x00000001;
-              break;
-            } // case 10
-            case 18: {
-              languageCode_ = input.readStringRequireUtf8();
-              bitField0_ |= 0x00000002;
-              break;
-            } // case 18
-            default: {
-              if (!super.parseUnknownField(input, extensionRegistry, tag)) {
-                done = true; // was an endgroup tag
-              }
-              break;
-            } // default:
-          } // switch (tag)
-        } // while (!done)
-      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-        throw e.unwrapIOException();
-      } finally {
-        onChanged();
-      } // finally
-      return this;
-    }
-    private int bitField0_;
-
-    private java.lang.Object text_ = "";
-    /**
-     * <pre>
-     * Localized string in the language corresponding to `language_code' below.
-     * </pre>
-     *
-     * <code>string text = 1;</code>
-     * @return The text.
-     */
-    public java.lang.String getText() {
-      java.lang.Object ref = text_;
-      if (!(ref instanceof java.lang.String)) {
-        com.google.protobuf.ByteString bs =
-            (com.google.protobuf.ByteString) ref;
-        java.lang.String s = bs.toStringUtf8();
-        text_ = s;
-        return s;
-      } else {
-        return (java.lang.String) ref;
-      }
-    }
-    /**
-     * <pre>
-     * Localized string in the language corresponding to `language_code' below.
-     * </pre>
-     *
-     * <code>string text = 1;</code>
-     * @return The bytes for text.
-     */
-    public com.google.protobuf.ByteString
-        getTextBytes() {
-      java.lang.Object ref = text_;
-      if (ref instanceof String) {
-        com.google.protobuf.ByteString b = 
-            com.google.protobuf.ByteString.copyFromUtf8(
-                (java.lang.String) ref);
-        text_ = b;
-        return b;
-      } else {
-        return (com.google.protobuf.ByteString) ref;
-      }
-    }
-    /**
-     * <pre>
-     * Localized string in the language corresponding to `language_code' below.
-     * </pre>
-     *
-     * <code>string text = 1;</code>
-     * @param value The text to set.
-     * @return This builder for chaining.
-     */
-    public Builder setText(
-        java.lang.String value) {
-      if (value == null) { throw new NullPointerException(); }
-      text_ = value;
-      bitField0_ |= 0x00000001;
-      onChanged();
-      return this;
-    }
-    /**
-     * <pre>
-     * Localized string in the language corresponding to `language_code' below.
-     * </pre>
-     *
-     * <code>string text = 1;</code>
-     * @return This builder for chaining.
-     */
-    public Builder clearText() {
-      text_ = getDefaultInstance().getText();
-      bitField0_ = (bitField0_ & ~0x00000001);
-      onChanged();
-      return this;
-    }
-    /**
-     * <pre>
-     * Localized string in the language corresponding to `language_code' below.
-     * </pre>
-     *
-     * <code>string text = 1;</code>
-     * @param value The bytes for text to set.
-     * @return This builder for chaining.
-     */
-    public Builder setTextBytes(
-        com.google.protobuf.ByteString value) {
-      if (value == null) { throw new NullPointerException(); }
-      checkByteStringIsUtf8(value);
-      text_ = value;
-      bitField0_ |= 0x00000001;
-      onChanged();
-      return this;
-    }
-
-    private java.lang.Object languageCode_ = "";
-    /**
-     * <pre>
-     * The text's BCP-47 language code, such as "en-US" or "sr-Latn".
-     *
-     * For more information, see
-     * http://www.unicode.org/reports/tr35/#Unicode_locale_identifier.
-     * </pre>
-     *
-     * <code>string language_code = 2;</code>
-     * @return The languageCode.
-     */
-    public java.lang.String getLanguageCode() {
-      java.lang.Object ref = languageCode_;
-      if (!(ref instanceof java.lang.String)) {
-        com.google.protobuf.ByteString bs =
-            (com.google.protobuf.ByteString) ref;
-        java.lang.String s = bs.toStringUtf8();
-        languageCode_ = s;
-        return s;
-      } else {
-        return (java.lang.String) ref;
-      }
-    }
-    /**
-     * <pre>
-     * The text's BCP-47 language code, such as "en-US" or "sr-Latn".
-     *
-     * For more information, see
-     * http://www.unicode.org/reports/tr35/#Unicode_locale_identifier.
-     * </pre>
-     *
-     * <code>string language_code = 2;</code>
-     * @return The bytes for languageCode.
-     */
-    public com.google.protobuf.ByteString
-        getLanguageCodeBytes() {
-      java.lang.Object ref = languageCode_;
-      if (ref instanceof String) {
-        com.google.protobuf.ByteString b = 
-            com.google.protobuf.ByteString.copyFromUtf8(
-                (java.lang.String) ref);
-        languageCode_ = b;
-        return b;
-      } else {
-        return (com.google.protobuf.ByteString) ref;
-      }
-    }
-    /**
-     * <pre>
-     * The text's BCP-47 language code, such as "en-US" or "sr-Latn".
-     *
-     * For more information, see
-     * http://www.unicode.org/reports/tr35/#Unicode_locale_identifier.
-     * </pre>
-     *
-     * <code>string language_code = 2;</code>
-     * @param value The languageCode to set.
-     * @return This builder for chaining.
-     */
-    public Builder setLanguageCode(
-        java.lang.String value) {
-      if (value == null) { throw new NullPointerException(); }
-      languageCode_ = value;
-      bitField0_ |= 0x00000002;
-      onChanged();
-      return this;
-    }
-    /**
-     * <pre>
-     * The text's BCP-47 language code, such as "en-US" or "sr-Latn".
-     *
-     * For more information, see
-     * http://www.unicode.org/reports/tr35/#Unicode_locale_identifier.
-     * </pre>
-     *
-     * <code>string language_code = 2;</code>
-     * @return This builder for chaining.
-     */
-    public Builder clearLanguageCode() {
-      languageCode_ = getDefaultInstance().getLanguageCode();
-      bitField0_ = (bitField0_ & ~0x00000002);
-      onChanged();
-      return this;
-    }
-    /**
-     * <pre>
-     * The text's BCP-47 language code, such as "en-US" or "sr-Latn".
-     *
-     * For more information, see
-     * http://www.unicode.org/reports/tr35/#Unicode_locale_identifier.
-     * </pre>
-     *
-     * <code>string language_code = 2;</code>
-     * @param value The bytes for languageCode to set.
-     * @return This builder for chaining.
-     */
-    public Builder setLanguageCodeBytes(
-        com.google.protobuf.ByteString value) {
-      if (value == null) { throw new NullPointerException(); }
-      checkByteStringIsUtf8(value);
-      languageCode_ = value;
-      bitField0_ |= 0x00000002;
-      onChanged();
-      return this;
-    }
-    @java.lang.Override
-    public final Builder setUnknownFields(
-        final com.google.protobuf.UnknownFieldSet unknownFields) {
-      return super.setUnknownFields(unknownFields);
-    }
-
-    @java.lang.Override
-    public final Builder mergeUnknownFields(
-        final com.google.protobuf.UnknownFieldSet unknownFields) {
-      return super.mergeUnknownFields(unknownFields);
-    }
-
-
-    // @@protoc_insertion_point(builder_scope:google.type.LocalizedText)
-  }
-
-  // @@protoc_insertion_point(class_scope:google.type.LocalizedText)
-  private static final com.google.type.LocalizedText DEFAULT_INSTANCE;
-  static {
-    DEFAULT_INSTANCE = new com.google.type.LocalizedText();
-  }
-
-  public static com.google.type.LocalizedText getDefaultInstance() {
-    return DEFAULT_INSTANCE;
-  }
-
-  private static final com.google.protobuf.Parser<LocalizedText>
-      PARSER = new com.google.protobuf.AbstractParser<LocalizedText>() {
-    @java.lang.Override
-    public LocalizedText parsePartialFrom(
-        com.google.protobuf.CodedInputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      Builder builder = newBuilder();
-      try {
-        builder.mergeFrom(input, extensionRegistry);
-      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-        throw e.setUnfinishedMessage(builder.buildPartial());
-      } catch (com.google.protobuf.UninitializedMessageException e) {
-        throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
-      } catch (java.io.IOException e) {
-        throw new com.google.protobuf.InvalidProtocolBufferException(e)
-            .setUnfinishedMessage(builder.buildPartial());
-      }
-      return builder.buildPartial();
-    }
-  };
-
-  public static com.google.protobuf.Parser<LocalizedText> parser() {
-    return PARSER;
-  }
-
-  @java.lang.Override
-  public com.google.protobuf.Parser<LocalizedText> getParserForType() {
-    return PARSER;
-  }
-
-  @java.lang.Override
-  public com.google.type.LocalizedText getDefaultInstanceForType() {
-    return DEFAULT_INSTANCE;
-  }
-
-}
-
diff --git a/menu-feed/java/src/main/java/com/google/type/LocalizedTextOrBuilder.java b/menu-feed/java/src/main/java/com/google/type/LocalizedTextOrBuilder.java
deleted file mode 100644
index 4d4a2c0..0000000
--- a/menu-feed/java/src/main/java/com/google/type/LocalizedTextOrBuilder.java
+++ /dev/null
@@ -1,55 +0,0 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: localized_text.proto
-
-package com.google.type;
-
-public interface LocalizedTextOrBuilder extends
-    // @@protoc_insertion_point(interface_extends:google.type.LocalizedText)
-    com.google.protobuf.MessageOrBuilder {
-
-  /**
-   * <pre>
-   * Localized string in the language corresponding to `language_code' below.
-   * </pre>
-   *
-   * <code>string text = 1;</code>
-   * @return The text.
-   */
-  java.lang.String getText();
-  /**
-   * <pre>
-   * Localized string in the language corresponding to `language_code' below.
-   * </pre>
-   *
-   * <code>string text = 1;</code>
-   * @return The bytes for text.
-   */
-  com.google.protobuf.ByteString
-      getTextBytes();
-
-  /**
-   * <pre>
-   * The text's BCP-47 language code, such as "en-US" or "sr-Latn".
-   *
-   * For more information, see
-   * http://www.unicode.org/reports/tr35/#Unicode_locale_identifier.
-   * </pre>
-   *
-   * <code>string language_code = 2;</code>
-   * @return The languageCode.
-   */
-  java.lang.String getLanguageCode();
-  /**
-   * <pre>
-   * The text's BCP-47 language code, such as "en-US" or "sr-Latn".
-   *
-   * For more information, see
-   * http://www.unicode.org/reports/tr35/#Unicode_locale_identifier.
-   * </pre>
-   *
-   * <code>string language_code = 2;</code>
-   * @return The bytes for languageCode.
-   */
-  com.google.protobuf.ByteString
-      getLanguageCodeBytes();
-}
diff --git a/menu-feed/java/src/main/java/com/google/type/LocalizedTextProto.java b/menu-feed/java/src/main/java/com/google/type/LocalizedTextProto.java
deleted file mode 100644
index 6d8137f..0000000
--- a/menu-feed/java/src/main/java/com/google/type/LocalizedTextProto.java
+++ /dev/null
@@ -1,51 +0,0 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: localized_text.proto
-
-package com.google.type;
-
-public final class LocalizedTextProto {
-  private LocalizedTextProto() {}
-  public static void registerAllExtensions(
-      com.google.protobuf.ExtensionRegistryLite registry) {
-  }
-
-  public static void registerAllExtensions(
-      com.google.protobuf.ExtensionRegistry registry) {
-    registerAllExtensions(
-        (com.google.protobuf.ExtensionRegistryLite) registry);
-  }
-  static final com.google.protobuf.Descriptors.Descriptor
-    internal_static_google_type_LocalizedText_descriptor;
-  static final 
-    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-      internal_static_google_type_LocalizedText_fieldAccessorTable;
-
-  public static com.google.protobuf.Descriptors.FileDescriptor
-      getDescriptor() {
-    return descriptor;
-  }
-  private static  com.google.protobuf.Descriptors.FileDescriptor
-      descriptor;
-  static {
-    java.lang.String[] descriptorData = {
-      "\n\024localized_text.proto\022\013google.type\"4\n\rL" +
-      "ocalizedText\022\014\n\004text\030\001 \001(\t\022\025\n\rlanguage_c" +
-      "ode\030\002 \001(\tBz\n\017com.google.typeB\022LocalizedT" +
-      "extProtoP\001ZHgoogle.golang.org/genproto/g" +
-      "oogleapis/type/localized_text;localized_" +
-      "text\370\001\001\242\002\003GTPb\006proto3"
-    };
-    descriptor = com.google.protobuf.Descriptors.FileDescriptor
-      .internalBuildGeneratedFileFrom(descriptorData,
-        new com.google.protobuf.Descriptors.FileDescriptor[] {
-        });
-    internal_static_google_type_LocalizedText_descriptor =
-      getDescriptor().getMessageTypes().get(0);
-    internal_static_google_type_LocalizedText_fieldAccessorTable = new
-      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
-        internal_static_google_type_LocalizedText_descriptor,
-        new java.lang.String[] { "Text", "LanguageCode", });
-  }
-
-  // @@protoc_insertion_point(outer_class_scope)
-}
diff --git a/menu-feed/java/src/main/java/com/google/type/Money.java b/menu-feed/java/src/main/java/com/google/type/Money.java
deleted file mode 100644
index c921feb..0000000
--- a/menu-feed/java/src/main/java/com/google/type/Money.java
+++ /dev/null
@@ -1,732 +0,0 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: money.proto
-
-package com.google.type;
-
-/**
- * <pre>
- * Represents an amount of money with its currency type.
- * </pre>
- *
- * Protobuf type {@code google.type.Money}
- */
-public final class Money extends
-    com.google.protobuf.GeneratedMessageV3 implements
-    // @@protoc_insertion_point(message_implements:google.type.Money)
-    MoneyOrBuilder {
-private static final long serialVersionUID = 0L;
-  // Use Money.newBuilder() to construct.
-  private Money(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
-    super(builder);
-  }
-  private Money() {
-    currencyCode_ = "";
-  }
-
-  @java.lang.Override
-  @SuppressWarnings({"unused"})
-  protected java.lang.Object newInstance(
-      UnusedPrivateParameter unused) {
-    return new Money();
-  }
-
-  public static final com.google.protobuf.Descriptors.Descriptor
-      getDescriptor() {
-    return com.google.type.MoneyProto.internal_static_google_type_Money_descriptor;
-  }
-
-  @java.lang.Override
-  protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-      internalGetFieldAccessorTable() {
-    return com.google.type.MoneyProto.internal_static_google_type_Money_fieldAccessorTable
-        .ensureFieldAccessorsInitialized(
-            com.google.type.Money.class, com.google.type.Money.Builder.class);
-  }
-
-  public static final int CURRENCY_CODE_FIELD_NUMBER = 1;
-  @SuppressWarnings("serial")
-  private volatile java.lang.Object currencyCode_ = "";
-  /**
-   * <pre>
-   * The three-letter currency code defined in ISO 4217.
-   * </pre>
-   *
-   * <code>string currency_code = 1;</code>
-   * @return The currencyCode.
-   */
-  @java.lang.Override
-  public java.lang.String getCurrencyCode() {
-    java.lang.Object ref = currencyCode_;
-    if (ref instanceof java.lang.String) {
-      return (java.lang.String) ref;
-    } else {
-      com.google.protobuf.ByteString bs = 
-          (com.google.protobuf.ByteString) ref;
-      java.lang.String s = bs.toStringUtf8();
-      currencyCode_ = s;
-      return s;
-    }
-  }
-  /**
-   * <pre>
-   * The three-letter currency code defined in ISO 4217.
-   * </pre>
-   *
-   * <code>string currency_code = 1;</code>
-   * @return The bytes for currencyCode.
-   */
-  @java.lang.Override
-  public com.google.protobuf.ByteString
-      getCurrencyCodeBytes() {
-    java.lang.Object ref = currencyCode_;
-    if (ref instanceof java.lang.String) {
-      com.google.protobuf.ByteString b = 
-          com.google.protobuf.ByteString.copyFromUtf8(
-              (java.lang.String) ref);
-      currencyCode_ = b;
-      return b;
-    } else {
-      return (com.google.protobuf.ByteString) ref;
-    }
-  }
-
-  public static final int UNITS_FIELD_NUMBER = 2;
-  private long units_ = 0L;
-  /**
-   * <pre>
-   * The whole units of the amount.
-   * For example if `currencyCode` is `"USD"`, then 1 unit is one US dollar.
-   * </pre>
-   *
-   * <code>int64 units = 2;</code>
-   * @return The units.
-   */
-  @java.lang.Override
-  public long getUnits() {
-    return units_;
-  }
-
-  public static final int NANOS_FIELD_NUMBER = 3;
-  private int nanos_ = 0;
-  /**
-   * <pre>
-   * Number of nano (10^-9) units of the amount.
-   * The value must be between -999,999,999 and +999,999,999 inclusive.
-   * If `units` is positive, `nanos` must be positive or zero.
-   * If `units` is zero, `nanos` can be positive, zero, or negative.
-   * If `units` is negative, `nanos` must be negative or zero.
-   * For example $-1.75 is represented as `units`=-1 and `nanos`=-750,000,000.
-   * </pre>
-   *
-   * <code>int32 nanos = 3;</code>
-   * @return The nanos.
-   */
-  @java.lang.Override
-  public int getNanos() {
-    return nanos_;
-  }
-
-  private byte memoizedIsInitialized = -1;
-  @java.lang.Override
-  public final boolean isInitialized() {
-    byte isInitialized = memoizedIsInitialized;
-    if (isInitialized == 1) return true;
-    if (isInitialized == 0) return false;
-
-    memoizedIsInitialized = 1;
-    return true;
-  }
-
-  @java.lang.Override
-  public void writeTo(com.google.protobuf.CodedOutputStream output)
-                      throws java.io.IOException {
-    if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(currencyCode_)) {
-      com.google.protobuf.GeneratedMessageV3.writeString(output, 1, currencyCode_);
-    }
-    if (units_ != 0L) {
-      output.writeInt64(2, units_);
-    }
-    if (nanos_ != 0) {
-      output.writeInt32(3, nanos_);
-    }
-    getUnknownFields().writeTo(output);
-  }
-
-  @java.lang.Override
-  public int getSerializedSize() {
-    int size = memoizedSize;
-    if (size != -1) return size;
-
-    size = 0;
-    if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(currencyCode_)) {
-      size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, currencyCode_);
-    }
-    if (units_ != 0L) {
-      size += com.google.protobuf.CodedOutputStream
-        .computeInt64Size(2, units_);
-    }
-    if (nanos_ != 0) {
-      size += com.google.protobuf.CodedOutputStream
-        .computeInt32Size(3, nanos_);
-    }
-    size += getUnknownFields().getSerializedSize();
-    memoizedSize = size;
-    return size;
-  }
-
-  @java.lang.Override
-  public boolean equals(final java.lang.Object obj) {
-    if (obj == this) {
-     return true;
-    }
-    if (!(obj instanceof com.google.type.Money)) {
-      return super.equals(obj);
-    }
-    com.google.type.Money other = (com.google.type.Money) obj;
-
-    if (!getCurrencyCode()
-        .equals(other.getCurrencyCode())) return false;
-    if (getUnits()
-        != other.getUnits()) return false;
-    if (getNanos()
-        != other.getNanos()) return false;
-    if (!getUnknownFields().equals(other.getUnknownFields())) return false;
-    return true;
-  }
-
-  @java.lang.Override
-  public int hashCode() {
-    if (memoizedHashCode != 0) {
-      return memoizedHashCode;
-    }
-    int hash = 41;
-    hash = (19 * hash) + getDescriptor().hashCode();
-    hash = (37 * hash) + CURRENCY_CODE_FIELD_NUMBER;
-    hash = (53 * hash) + getCurrencyCode().hashCode();
-    hash = (37 * hash) + UNITS_FIELD_NUMBER;
-    hash = (53 * hash) + com.google.protobuf.Internal.hashLong(
-        getUnits());
-    hash = (37 * hash) + NANOS_FIELD_NUMBER;
-    hash = (53 * hash) + getNanos();
-    hash = (29 * hash) + getUnknownFields().hashCode();
-    memoizedHashCode = hash;
-    return hash;
-  }
-
-  public static com.google.type.Money parseFrom(
-      java.nio.ByteBuffer data)
-      throws com.google.protobuf.InvalidProtocolBufferException {
-    return PARSER.parseFrom(data);
-  }
-  public static com.google.type.Money parseFrom(
-      java.nio.ByteBuffer data,
-      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-      throws com.google.protobuf.InvalidProtocolBufferException {
-    return PARSER.parseFrom(data, extensionRegistry);
-  }
-  public static com.google.type.Money parseFrom(
-      com.google.protobuf.ByteString data)
-      throws com.google.protobuf.InvalidProtocolBufferException {
-    return PARSER.parseFrom(data);
-  }
-  public static com.google.type.Money parseFrom(
-      com.google.protobuf.ByteString data,
-      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-      throws com.google.protobuf.InvalidProtocolBufferException {
-    return PARSER.parseFrom(data, extensionRegistry);
-  }
-  public static com.google.type.Money parseFrom(byte[] data)
-      throws com.google.protobuf.InvalidProtocolBufferException {
-    return PARSER.parseFrom(data);
-  }
-  public static com.google.type.Money parseFrom(
-      byte[] data,
-      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-      throws com.google.protobuf.InvalidProtocolBufferException {
-    return PARSER.parseFrom(data, extensionRegistry);
-  }
-  public static com.google.type.Money parseFrom(java.io.InputStream input)
-      throws java.io.IOException {
-    return com.google.protobuf.GeneratedMessageV3
-        .parseWithIOException(PARSER, input);
-  }
-  public static com.google.type.Money parseFrom(
-      java.io.InputStream input,
-      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-      throws java.io.IOException {
-    return com.google.protobuf.GeneratedMessageV3
-        .parseWithIOException(PARSER, input, extensionRegistry);
-  }
-  public static com.google.type.Money parseDelimitedFrom(java.io.InputStream input)
-      throws java.io.IOException {
-    return com.google.protobuf.GeneratedMessageV3
-        .parseDelimitedWithIOException(PARSER, input);
-  }
-  public static com.google.type.Money parseDelimitedFrom(
-      java.io.InputStream input,
-      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-      throws java.io.IOException {
-    return com.google.protobuf.GeneratedMessageV3
-        .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
-  }
-  public static com.google.type.Money parseFrom(
-      com.google.protobuf.CodedInputStream input)
-      throws java.io.IOException {
-    return com.google.protobuf.GeneratedMessageV3
-        .parseWithIOException(PARSER, input);
-  }
-  public static com.google.type.Money parseFrom(
-      com.google.protobuf.CodedInputStream input,
-      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-      throws java.io.IOException {
-    return com.google.protobuf.GeneratedMessageV3
-        .parseWithIOException(PARSER, input, extensionRegistry);
-  }
-
-  @java.lang.Override
-  public Builder newBuilderForType() { return newBuilder(); }
-  public static Builder newBuilder() {
-    return DEFAULT_INSTANCE.toBuilder();
-  }
-  public static Builder newBuilder(com.google.type.Money prototype) {
-    return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
-  }
-  @java.lang.Override
-  public Builder toBuilder() {
-    return this == DEFAULT_INSTANCE
-        ? new Builder() : new Builder().mergeFrom(this);
-  }
-
-  @java.lang.Override
-  protected Builder newBuilderForType(
-      com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-    Builder builder = new Builder(parent);
-    return builder;
-  }
-  /**
-   * <pre>
-   * Represents an amount of money with its currency type.
-   * </pre>
-   *
-   * Protobuf type {@code google.type.Money}
-   */
-  public static final class Builder extends
-      com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
-      // @@protoc_insertion_point(builder_implements:google.type.Money)
-      com.google.type.MoneyOrBuilder {
-    public static final com.google.protobuf.Descriptors.Descriptor
-        getDescriptor() {
-      return com.google.type.MoneyProto.internal_static_google_type_Money_descriptor;
-    }
-
-    @java.lang.Override
-    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-        internalGetFieldAccessorTable() {
-      return com.google.type.MoneyProto.internal_static_google_type_Money_fieldAccessorTable
-          .ensureFieldAccessorsInitialized(
-              com.google.type.Money.class, com.google.type.Money.Builder.class);
-    }
-
-    // Construct using com.google.type.Money.newBuilder()
-    private Builder() {
-
-    }
-
-    private Builder(
-        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-      super(parent);
-
-    }
-    @java.lang.Override
-    public Builder clear() {
-      super.clear();
-      bitField0_ = 0;
-      currencyCode_ = "";
-      units_ = 0L;
-      nanos_ = 0;
-      return this;
-    }
-
-    @java.lang.Override
-    public com.google.protobuf.Descriptors.Descriptor
-        getDescriptorForType() {
-      return com.google.type.MoneyProto.internal_static_google_type_Money_descriptor;
-    }
-
-    @java.lang.Override
-    public com.google.type.Money getDefaultInstanceForType() {
-      return com.google.type.Money.getDefaultInstance();
-    }
-
-    @java.lang.Override
-    public com.google.type.Money build() {
-      com.google.type.Money result = buildPartial();
-      if (!result.isInitialized()) {
-        throw newUninitializedMessageException(result);
-      }
-      return result;
-    }
-
-    @java.lang.Override
-    public com.google.type.Money buildPartial() {
-      com.google.type.Money result = new com.google.type.Money(this);
-      if (bitField0_ != 0) { buildPartial0(result); }
-      onBuilt();
-      return result;
-    }
-
-    private void buildPartial0(com.google.type.Money result) {
-      int from_bitField0_ = bitField0_;
-      if (((from_bitField0_ & 0x00000001) != 0)) {
-        result.currencyCode_ = currencyCode_;
-      }
-      if (((from_bitField0_ & 0x00000002) != 0)) {
-        result.units_ = units_;
-      }
-      if (((from_bitField0_ & 0x00000004) != 0)) {
-        result.nanos_ = nanos_;
-      }
-    }
-
-    @java.lang.Override
-    public Builder mergeFrom(com.google.protobuf.Message other) {
-      if (other instanceof com.google.type.Money) {
-        return mergeFrom((com.google.type.Money)other);
-      } else {
-        super.mergeFrom(other);
-        return this;
-      }
-    }
-
-    public Builder mergeFrom(com.google.type.Money other) {
-      if (other == com.google.type.Money.getDefaultInstance()) return this;
-      if (!other.getCurrencyCode().isEmpty()) {
-        currencyCode_ = other.currencyCode_;
-        bitField0_ |= 0x00000001;
-        onChanged();
-      }
-      if (other.getUnits() != 0L) {
-        setUnits(other.getUnits());
-      }
-      if (other.getNanos() != 0) {
-        setNanos(other.getNanos());
-      }
-      this.mergeUnknownFields(other.getUnknownFields());
-      onChanged();
-      return this;
-    }
-
-    @java.lang.Override
-    public final boolean isInitialized() {
-      return true;
-    }
-
-    @java.lang.Override
-    public Builder mergeFrom(
-        com.google.protobuf.CodedInputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      if (extensionRegistry == null) {
-        throw new java.lang.NullPointerException();
-      }
-      try {
-        boolean done = false;
-        while (!done) {
-          int tag = input.readTag();
-          switch (tag) {
-            case 0:
-              done = true;
-              break;
-            case 10: {
-              currencyCode_ = input.readStringRequireUtf8();
-              bitField0_ |= 0x00000001;
-              break;
-            } // case 10
-            case 16: {
-              units_ = input.readInt64();
-              bitField0_ |= 0x00000002;
-              break;
-            } // case 16
-            case 24: {
-              nanos_ = input.readInt32();
-              bitField0_ |= 0x00000004;
-              break;
-            } // case 24
-            default: {
-              if (!super.parseUnknownField(input, extensionRegistry, tag)) {
-                done = true; // was an endgroup tag
-              }
-              break;
-            } // default:
-          } // switch (tag)
-        } // while (!done)
-      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-        throw e.unwrapIOException();
-      } finally {
-        onChanged();
-      } // finally
-      return this;
-    }
-    private int bitField0_;
-
-    private java.lang.Object currencyCode_ = "";
-    /**
-     * <pre>
-     * The three-letter currency code defined in ISO 4217.
-     * </pre>
-     *
-     * <code>string currency_code = 1;</code>
-     * @return The currencyCode.
-     */
-    public java.lang.String getCurrencyCode() {
-      java.lang.Object ref = currencyCode_;
-      if (!(ref instanceof java.lang.String)) {
-        com.google.protobuf.ByteString bs =
-            (com.google.protobuf.ByteString) ref;
-        java.lang.String s = bs.toStringUtf8();
-        currencyCode_ = s;
-        return s;
-      } else {
-        return (java.lang.String) ref;
-      }
-    }
-    /**
-     * <pre>
-     * The three-letter currency code defined in ISO 4217.
-     * </pre>
-     *
-     * <code>string currency_code = 1;</code>
-     * @return The bytes for currencyCode.
-     */
-    public com.google.protobuf.ByteString
-        getCurrencyCodeBytes() {
-      java.lang.Object ref = currencyCode_;
-      if (ref instanceof String) {
-        com.google.protobuf.ByteString b = 
-            com.google.protobuf.ByteString.copyFromUtf8(
-                (java.lang.String) ref);
-        currencyCode_ = b;
-        return b;
-      } else {
-        return (com.google.protobuf.ByteString) ref;
-      }
-    }
-    /**
-     * <pre>
-     * The three-letter currency code defined in ISO 4217.
-     * </pre>
-     *
-     * <code>string currency_code = 1;</code>
-     * @param value The currencyCode to set.
-     * @return This builder for chaining.
-     */
-    public Builder setCurrencyCode(
-        java.lang.String value) {
-      if (value == null) { throw new NullPointerException(); }
-      currencyCode_ = value;
-      bitField0_ |= 0x00000001;
-      onChanged();
-      return this;
-    }
-    /**
-     * <pre>
-     * The three-letter currency code defined in ISO 4217.
-     * </pre>
-     *
-     * <code>string currency_code = 1;</code>
-     * @return This builder for chaining.
-     */
-    public Builder clearCurrencyCode() {
-      currencyCode_ = getDefaultInstance().getCurrencyCode();
-      bitField0_ = (bitField0_ & ~0x00000001);
-      onChanged();
-      return this;
-    }
-    /**
-     * <pre>
-     * The three-letter currency code defined in ISO 4217.
-     * </pre>
-     *
-     * <code>string currency_code = 1;</code>
-     * @param value The bytes for currencyCode to set.
-     * @return This builder for chaining.
-     */
-    public Builder setCurrencyCodeBytes(
-        com.google.protobuf.ByteString value) {
-      if (value == null) { throw new NullPointerException(); }
-      checkByteStringIsUtf8(value);
-      currencyCode_ = value;
-      bitField0_ |= 0x00000001;
-      onChanged();
-      return this;
-    }
-
-    private long units_ ;
-    /**
-     * <pre>
-     * The whole units of the amount.
-     * For example if `currencyCode` is `"USD"`, then 1 unit is one US dollar.
-     * </pre>
-     *
-     * <code>int64 units = 2;</code>
-     * @return The units.
-     */
-    @java.lang.Override
-    public long getUnits() {
-      return units_;
-    }
-    /**
-     * <pre>
-     * The whole units of the amount.
-     * For example if `currencyCode` is `"USD"`, then 1 unit is one US dollar.
-     * </pre>
-     *
-     * <code>int64 units = 2;</code>
-     * @param value The units to set.
-     * @return This builder for chaining.
-     */
-    public Builder setUnits(long value) {
-
-      units_ = value;
-      bitField0_ |= 0x00000002;
-      onChanged();
-      return this;
-    }
-    /**
-     * <pre>
-     * The whole units of the amount.
-     * For example if `currencyCode` is `"USD"`, then 1 unit is one US dollar.
-     * </pre>
-     *
-     * <code>int64 units = 2;</code>
-     * @return This builder for chaining.
-     */
-    public Builder clearUnits() {
-      bitField0_ = (bitField0_ & ~0x00000002);
-      units_ = 0L;
-      onChanged();
-      return this;
-    }
-
-    private int nanos_ ;
-    /**
-     * <pre>
-     * Number of nano (10^-9) units of the amount.
-     * The value must be between -999,999,999 and +999,999,999 inclusive.
-     * If `units` is positive, `nanos` must be positive or zero.
-     * If `units` is zero, `nanos` can be positive, zero, or negative.
-     * If `units` is negative, `nanos` must be negative or zero.
-     * For example $-1.75 is represented as `units`=-1 and `nanos`=-750,000,000.
-     * </pre>
-     *
-     * <code>int32 nanos = 3;</code>
-     * @return The nanos.
-     */
-    @java.lang.Override
-    public int getNanos() {
-      return nanos_;
-    }
-    /**
-     * <pre>
-     * Number of nano (10^-9) units of the amount.
-     * The value must be between -999,999,999 and +999,999,999 inclusive.
-     * If `units` is positive, `nanos` must be positive or zero.
-     * If `units` is zero, `nanos` can be positive, zero, or negative.
-     * If `units` is negative, `nanos` must be negative or zero.
-     * For example $-1.75 is represented as `units`=-1 and `nanos`=-750,000,000.
-     * </pre>
-     *
-     * <code>int32 nanos = 3;</code>
-     * @param value The nanos to set.
-     * @return This builder for chaining.
-     */
-    public Builder setNanos(int value) {
-
-      nanos_ = value;
-      bitField0_ |= 0x00000004;
-      onChanged();
-      return this;
-    }
-    /**
-     * <pre>
-     * Number of nano (10^-9) units of the amount.
-     * The value must be between -999,999,999 and +999,999,999 inclusive.
-     * If `units` is positive, `nanos` must be positive or zero.
-     * If `units` is zero, `nanos` can be positive, zero, or negative.
-     * If `units` is negative, `nanos` must be negative or zero.
-     * For example $-1.75 is represented as `units`=-1 and `nanos`=-750,000,000.
-     * </pre>
-     *
-     * <code>int32 nanos = 3;</code>
-     * @return This builder for chaining.
-     */
-    public Builder clearNanos() {
-      bitField0_ = (bitField0_ & ~0x00000004);
-      nanos_ = 0;
-      onChanged();
-      return this;
-    }
-    @java.lang.Override
-    public final Builder setUnknownFields(
-        final com.google.protobuf.UnknownFieldSet unknownFields) {
-      return super.setUnknownFields(unknownFields);
-    }
-
-    @java.lang.Override
-    public final Builder mergeUnknownFields(
-        final com.google.protobuf.UnknownFieldSet unknownFields) {
-      return super.mergeUnknownFields(unknownFields);
-    }
-
-
-    // @@protoc_insertion_point(builder_scope:google.type.Money)
-  }
-
-  // @@protoc_insertion_point(class_scope:google.type.Money)
-  private static final com.google.type.Money DEFAULT_INSTANCE;
-  static {
-    DEFAULT_INSTANCE = new com.google.type.Money();
-  }
-
-  public static com.google.type.Money getDefaultInstance() {
-    return DEFAULT_INSTANCE;
-  }
-
-  private static final com.google.protobuf.Parser<Money>
-      PARSER = new com.google.protobuf.AbstractParser<Money>() {
-    @java.lang.Override
-    public Money parsePartialFrom(
-        com.google.protobuf.CodedInputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      Builder builder = newBuilder();
-      try {
-        builder.mergeFrom(input, extensionRegistry);
-      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-        throw e.setUnfinishedMessage(builder.buildPartial());
-      } catch (com.google.protobuf.UninitializedMessageException e) {
-        throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
-      } catch (java.io.IOException e) {
-        throw new com.google.protobuf.InvalidProtocolBufferException(e)
-            .setUnfinishedMessage(builder.buildPartial());
-      }
-      return builder.buildPartial();
-    }
-  };
-
-  public static com.google.protobuf.Parser<Money> parser() {
-    return PARSER;
-  }
-
-  @java.lang.Override
-  public com.google.protobuf.Parser<Money> getParserForType() {
-    return PARSER;
-  }
-
-  @java.lang.Override
-  public com.google.type.Money getDefaultInstanceForType() {
-    return DEFAULT_INSTANCE;
-  }
-
-}
-
diff --git a/menu-feed/java/src/main/java/com/google/type/MoneyOrBuilder.java b/menu-feed/java/src/main/java/com/google/type/MoneyOrBuilder.java
deleted file mode 100644
index ed05c1e..0000000
--- a/menu-feed/java/src/main/java/com/google/type/MoneyOrBuilder.java
+++ /dev/null
@@ -1,55 +0,0 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: money.proto
-
-package com.google.type;
-
-public interface MoneyOrBuilder extends
-    // @@protoc_insertion_point(interface_extends:google.type.Money)
-    com.google.protobuf.MessageOrBuilder {
-
-  /**
-   * <pre>
-   * The three-letter currency code defined in ISO 4217.
-   * </pre>
-   *
-   * <code>string currency_code = 1;</code>
-   * @return The currencyCode.
-   */
-  java.lang.String getCurrencyCode();
-  /**
-   * <pre>
-   * The three-letter currency code defined in ISO 4217.
-   * </pre>
-   *
-   * <code>string currency_code = 1;</code>
-   * @return The bytes for currencyCode.
-   */
-  com.google.protobuf.ByteString
-      getCurrencyCodeBytes();
-
-  /**
-   * <pre>
-   * The whole units of the amount.
-   * For example if `currencyCode` is `"USD"`, then 1 unit is one US dollar.
-   * </pre>
-   *
-   * <code>int64 units = 2;</code>
-   * @return The units.
-   */
-  long getUnits();
-
-  /**
-   * <pre>
-   * Number of nano (10^-9) units of the amount.
-   * The value must be between -999,999,999 and +999,999,999 inclusive.
-   * If `units` is positive, `nanos` must be positive or zero.
-   * If `units` is zero, `nanos` can be positive, zero, or negative.
-   * If `units` is negative, `nanos` must be negative or zero.
-   * For example $-1.75 is represented as `units`=-1 and `nanos`=-750,000,000.
-   * </pre>
-   *
-   * <code>int32 nanos = 3;</code>
-   * @return The nanos.
-   */
-  int getNanos();
-}
diff --git a/menu-feed/java/src/main/java/com/google/type/MoneyProto.java b/menu-feed/java/src/main/java/com/google/type/MoneyProto.java
deleted file mode 100644
index 24fe444..0000000
--- a/menu-feed/java/src/main/java/com/google/type/MoneyProto.java
+++ /dev/null
@@ -1,50 +0,0 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: money.proto
-
-package com.google.type;
-
-public final class MoneyProto {
-  private MoneyProto() {}
-  public static void registerAllExtensions(
-      com.google.protobuf.ExtensionRegistryLite registry) {
-  }
-
-  public static void registerAllExtensions(
-      com.google.protobuf.ExtensionRegistry registry) {
-    registerAllExtensions(
-        (com.google.protobuf.ExtensionRegistryLite) registry);
-  }
-  static final com.google.protobuf.Descriptors.Descriptor
-    internal_static_google_type_Money_descriptor;
-  static final 
-    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-      internal_static_google_type_Money_fieldAccessorTable;
-
-  public static com.google.protobuf.Descriptors.FileDescriptor
-      getDescriptor() {
-    return descriptor;
-  }
-  private static  com.google.protobuf.Descriptors.FileDescriptor
-      descriptor;
-  static {
-    java.lang.String[] descriptorData = {
-      "\n\013money.proto\022\013google.type\"<\n\005Money\022\025\n\rc" +
-      "urrency_code\030\001 \001(\t\022\r\n\005units\030\002 \001(\003\022\r\n\005nan" +
-      "os\030\003 \001(\005B`\n\017com.google.typeB\nMoneyProtoP" +
-      "\001Z6google.golang.org/genproto/googleapis" +
-      "/type/money;money\370\001\001\242\002\003GTPb\006proto3"
-    };
-    descriptor = com.google.protobuf.Descriptors.FileDescriptor
-      .internalBuildGeneratedFileFrom(descriptorData,
-        new com.google.protobuf.Descriptors.FileDescriptor[] {
-        });
-    internal_static_google_type_Money_descriptor =
-      getDescriptor().getMessageTypes().get(0);
-    internal_static_google_type_Money_fieldAccessorTable = new
-      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
-        internal_static_google_type_Money_descriptor,
-        new java.lang.String[] { "CurrencyCode", "Units", "Nanos", });
-  }
-
-  // @@protoc_insertion_point(outer_class_scope)
-}
diff --git a/menu-feed/java/src/main/java/food/menu/v1/FoodMenu.java b/menu-feed/java/src/main/java/food/menu/v1/FoodMenu.java
deleted file mode 100644
index 4a0936d..0000000
--- a/menu-feed/java/src/main/java/food/menu/v1/FoodMenu.java
+++ /dev/null
@@ -1,26852 +0,0 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: food_menu.proto
-
-package food.menu.v1;
-
-public final class FoodMenu {
-  private FoodMenu() {}
-  public static void registerAllExtensions(
-      com.google.protobuf.ExtensionRegistryLite registry) {
-  }
-
-  public static void registerAllExtensions(
-      com.google.protobuf.ExtensionRegistry registry) {
-    registerAllExtensions(
-        (com.google.protobuf.ExtensionRegistryLite) registry);
-  }
-  /**
-   * <pre>
-   * Indicates a dietary restriction or guideline adhered to during
-   * food preparation.
-   * </pre>
-   *
-   * Protobuf enum {@code food.menu.v1.DietaryRestriction}
-   */
-  public enum DietaryRestriction
-      implements com.google.protobuf.ProtocolMessageEnum {
-    /**
-     * <pre>
-     * Do not use. The dietary restriction is not explicitly specified.
-     * </pre>
-     *
-     * <code>DIET_UNSPECIFIED = 0;</code>
-     */
-    DIET_UNSPECIFIED(0),
-    /**
-     * <code>DIET_DIABETIC = 1;</code>
-     */
-    DIET_DIABETIC(1),
-    /**
-     * <code>DIET_GLUTEN_FREE = 2;</code>
-     */
-    DIET_GLUTEN_FREE(2),
-    /**
-     * <code>DIET_HALAL = 3;</code>
-     */
-    DIET_HALAL(3),
-    /**
-     * <code>DIET_HINDU = 4;</code>
-     */
-    DIET_HINDU(4),
-    /**
-     * <code>DIET_KOSHER = 5;</code>
-     */
-    DIET_KOSHER(5),
-    /**
-     * <code>DIET_LOW_CALORIE = 6;</code>
-     */
-    DIET_LOW_CALORIE(6),
-    /**
-     * <code>DIET_LOW_FAT = 7;</code>
-     */
-    DIET_LOW_FAT(7),
-    /**
-     * <code>DIET_LOW_LACTOSE = 8;</code>
-     */
-    DIET_LOW_LACTOSE(8),
-    /**
-     * <code>DIET_LOW_SALT = 9;</code>
-     */
-    DIET_LOW_SALT(9),
-    /**
-     * <code>DIET_VEGAN = 10;</code>
-     */
-    DIET_VEGAN(10),
-    /**
-     * <code>DIET_VEGETARIAN = 11;</code>
-     */
-    DIET_VEGETARIAN(11),
-    UNRECOGNIZED(-1),
-    ;
-
-    /**
-     * <pre>
-     * Do not use. The dietary restriction is not explicitly specified.
-     * </pre>
-     *
-     * <code>DIET_UNSPECIFIED = 0;</code>
-     */
-    public static final int DIET_UNSPECIFIED_VALUE = 0;
-    /**
-     * <code>DIET_DIABETIC = 1;</code>
-     */
-    public static final int DIET_DIABETIC_VALUE = 1;
-    /**
-     * <code>DIET_GLUTEN_FREE = 2;</code>
-     */
-    public static final int DIET_GLUTEN_FREE_VALUE = 2;
-    /**
-     * <code>DIET_HALAL = 3;</code>
-     */
-    public static final int DIET_HALAL_VALUE = 3;
-    /**
-     * <code>DIET_HINDU = 4;</code>
-     */
-    public static final int DIET_HINDU_VALUE = 4;
-    /**
-     * <code>DIET_KOSHER = 5;</code>
-     */
-    public static final int DIET_KOSHER_VALUE = 5;
-    /**
-     * <code>DIET_LOW_CALORIE = 6;</code>
-     */
-    public static final int DIET_LOW_CALORIE_VALUE = 6;
-    /**
-     * <code>DIET_LOW_FAT = 7;</code>
-     */
-    public static final int DIET_LOW_FAT_VALUE = 7;
-    /**
-     * <code>DIET_LOW_LACTOSE = 8;</code>
-     */
-    public static final int DIET_LOW_LACTOSE_VALUE = 8;
-    /**
-     * <code>DIET_LOW_SALT = 9;</code>
-     */
-    public static final int DIET_LOW_SALT_VALUE = 9;
-    /**
-     * <code>DIET_VEGAN = 10;</code>
-     */
-    public static final int DIET_VEGAN_VALUE = 10;
-    /**
-     * <code>DIET_VEGETARIAN = 11;</code>
-     */
-    public static final int DIET_VEGETARIAN_VALUE = 11;
-
-
-    public final int getNumber() {
-      if (this == UNRECOGNIZED) {
-        throw new java.lang.IllegalArgumentException(
-            "Can't get the number of an unknown enum value.");
-      }
-      return value;
-    }
-
-    /**
-     * @param value The numeric wire value of the corresponding enum entry.
-     * @return The enum associated with the given numeric wire value.
-     * @deprecated Use {@link #forNumber(int)} instead.
-     */
-    @java.lang.Deprecated
-    public static DietaryRestriction valueOf(int value) {
-      return forNumber(value);
-    }
-
-    /**
-     * @param value The numeric wire value of the corresponding enum entry.
-     * @return The enum associated with the given numeric wire value.
-     */
-    public static DietaryRestriction forNumber(int value) {
-      switch (value) {
-        case 0: return DIET_UNSPECIFIED;
-        case 1: return DIET_DIABETIC;
-        case 2: return DIET_GLUTEN_FREE;
-        case 3: return DIET_HALAL;
-        case 4: return DIET_HINDU;
-        case 5: return DIET_KOSHER;
-        case 6: return DIET_LOW_CALORIE;
-        case 7: return DIET_LOW_FAT;
-        case 8: return DIET_LOW_LACTOSE;
-        case 9: return DIET_LOW_SALT;
-        case 10: return DIET_VEGAN;
-        case 11: return DIET_VEGETARIAN;
-        default: return null;
-      }
-    }
-
-    public static com.google.protobuf.Internal.EnumLiteMap<DietaryRestriction>
-        internalGetValueMap() {
-      return internalValueMap;
-    }
-    private static final com.google.protobuf.Internal.EnumLiteMap<
-        DietaryRestriction> internalValueMap =
-          new com.google.protobuf.Internal.EnumLiteMap<DietaryRestriction>() {
-            public DietaryRestriction findValueByNumber(int number) {
-              return DietaryRestriction.forNumber(number);
-            }
-          };
-
-    public final com.google.protobuf.Descriptors.EnumValueDescriptor
-        getValueDescriptor() {
-      if (this == UNRECOGNIZED) {
-        throw new java.lang.IllegalStateException(
-            "Can't get the descriptor of an unrecognized enum value.");
-      }
-      return getDescriptor().getValues().get(ordinal());
-    }
-    public final com.google.protobuf.Descriptors.EnumDescriptor
-        getDescriptorForType() {
-      return getDescriptor();
-    }
-    public static final com.google.protobuf.Descriptors.EnumDescriptor
-        getDescriptor() {
-      return food.menu.v1.FoodMenu.getDescriptor().getEnumTypes().get(0);
-    }
-
-    private static final DietaryRestriction[] VALUES = values();
-
-    public static DietaryRestriction valueOf(
-        com.google.protobuf.Descriptors.EnumValueDescriptor desc) {
-      if (desc.getType() != getDescriptor()) {
-        throw new java.lang.IllegalArgumentException(
-          "EnumValueDescriptor is not for this type.");
-      }
-      if (desc.getIndex() == -1) {
-        return UNRECOGNIZED;
-      }
-      return VALUES[desc.getIndex()];
-    }
-
-    private final int value;
-
-    private DietaryRestriction(int value) {
-      this.value = value;
-    }
-
-    // @@protoc_insertion_point(enum_scope:food.menu.v1.DietaryRestriction)
-  }
-
-  /**
-   * <pre>
-   * Allergen type derived from GS1: http://gs1.org/voc/AllergenTypeCode
-   * </pre>
-   *
-   * Protobuf enum {@code food.menu.v1.AllergenTypeCode}
-   */
-  public enum AllergenTypeCode
-      implements com.google.protobuf.ProtocolMessageEnum {
-    /**
-     * <pre>
-     * Do not use. The allergen type code is not explicitly specified.
-     * </pre>
-     *
-     * <code>ALLERGEN_TYPE_CODE_UNSPECIFIED = 0;</code>
-     */
-    ALLERGEN_TYPE_CODE_UNSPECIFIED(0),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_ALMONDS = 1;</code>
-     */
-    ALLERGEN_TYPE_CODE_ALMONDS(1),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_ALPHA_ISOMETHYL_IONONE = 2;</code>
-     */
-    ALLERGEN_TYPE_CODE_ALPHA_ISOMETHYL_IONONE(2),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_ALCOHOL = 3;</code>
-     */
-    ALLERGEN_TYPE_CODE_ALCOHOL(3),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_AMYL_CINNAMAL = 4;</code>
-     */
-    ALLERGEN_TYPE_CODE_AMYL_CINNAMAL(4),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_ANISE_ALCOHOL = 5;</code>
-     */
-    ALLERGEN_TYPE_CODE_ANISE_ALCOHOL(5),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_BARLEY = 6;</code>
-     */
-    ALLERGEN_TYPE_CODE_BARLEY(6),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_BENZYL_ALCOHOL = 7;</code>
-     */
-    ALLERGEN_TYPE_CODE_BENZYL_ALCOHOL(7),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_BENZYL_BENZOATE = 8;</code>
-     */
-    ALLERGEN_TYPE_CODE_BENZYL_BENZOATE(8),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_BENZYL_CINNAMATE = 9;</code>
-     */
-    ALLERGEN_TYPE_CODE_BENZYL_CINNAMATE(9),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_BENZYL_SALICYLATE = 10;</code>
-     */
-    ALLERGEN_TYPE_CODE_BENZYL_SALICYLATE(10),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_BRAZIL_NUTS = 11;</code>
-     */
-    ALLERGEN_TYPE_CODE_BRAZIL_NUTS(11),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_BUTYLPHENYL_METHYLPROPIONATE = 12;</code>
-     */
-    ALLERGEN_TYPE_CODE_BUTYLPHENYL_METHYLPROPIONATE(12),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_CARROTS = 13;</code>
-     */
-    ALLERGEN_TYPE_CODE_CARROTS(13),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_CASHEW_NUTS = 14;</code>
-     */
-    ALLERGEN_TYPE_CODE_CASHEW_NUTS(14),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_CELERY = 15;</code>
-     */
-    ALLERGEN_TYPE_CODE_CELERY(15),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_CEREALS_CONTAINING_GLUTEN = 16;</code>
-     */
-    ALLERGEN_TYPE_CODE_CEREALS_CONTAINING_GLUTEN(16),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_CINNAMAL = 17;</code>
-     */
-    ALLERGEN_TYPE_CODE_CINNAMAL(17),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_CINNAMYL_ALCOHOL = 18;</code>
-     */
-    ALLERGEN_TYPE_CODE_CINNAMYL_ALCOHOL(18),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_CITRAL = 19;</code>
-     */
-    ALLERGEN_TYPE_CODE_CITRAL(19),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_CITRONELLOL = 20;</code>
-     */
-    ALLERGEN_TYPE_CODE_CITRONELLOL(20),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_COCOA = 21;</code>
-     */
-    ALLERGEN_TYPE_CODE_COCOA(21),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_CORIANDER = 22;</code>
-     */
-    ALLERGEN_TYPE_CODE_CORIANDER(22),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_CORN = 23;</code>
-     */
-    ALLERGEN_TYPE_CODE_CORN(23),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_COUMARIN = 24;</code>
-     */
-    ALLERGEN_TYPE_CODE_COUMARIN(24),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_CRUSTACEANS = 25;</code>
-     */
-    ALLERGEN_TYPE_CODE_CRUSTACEANS(25),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_EGGS = 26;</code>
-     */
-    ALLERGEN_TYPE_CODE_EGGS(26),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_EUGENOL = 27;</code>
-     */
-    ALLERGEN_TYPE_CODE_EUGENOL(27),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_EVERNIA_FURFURACEA = 28;</code>
-     */
-    ALLERGEN_TYPE_CODE_EVERNIA_FURFURACEA(28),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_EVERNIA_PRUNASTRI = 29;</code>
-     */
-    ALLERGEN_TYPE_CODE_EVERNIA_PRUNASTRI(29),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_FARNESOL = 30;</code>
-     */
-    ALLERGEN_TYPE_CODE_FARNESOL(30),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_FISH = 31;</code>
-     */
-    ALLERGEN_TYPE_CODE_FISH(31),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_GERANIOL = 32;</code>
-     */
-    ALLERGEN_TYPE_CODE_GERANIOL(32),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_GLUTEN = 33;</code>
-     */
-    ALLERGEN_TYPE_CODE_GLUTEN(33),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_HAZELNUTS = 34;</code>
-     */
-    ALLERGEN_TYPE_CODE_HAZELNUTS(34),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_HEXYL_CINNAMAL = 35;</code>
-     */
-    ALLERGEN_TYPE_CODE_HEXYL_CINNAMAL(35),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_HYDROXYCITRONELLAL = 36;</code>
-     */
-    ALLERGEN_TYPE_CODE_HYDROXYCITRONELLAL(36),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_HYDROXYISOHEXYL_3_CYCLOHEXENE_CARBOXALDEHYDE_ISOEUGENOL_LIMONENE_LINAL = 37;</code>
-     */
-    ALLERGEN_TYPE_CODE_HYDROXYISOHEXYL_3_CYCLOHEXENE_CARBOXALDEHYDE_ISOEUGENOL_LIMONENE_LINAL(37),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_KAMUT = 38;</code>
-     */
-    ALLERGEN_TYPE_CODE_KAMUT(38),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_LACTOSE = 39;</code>
-     */
-    ALLERGEN_TYPE_CODE_LACTOSE(39),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_LUPINE = 40;</code>
-     */
-    ALLERGEN_TYPE_CODE_LUPINE(40),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_MACADAMIA_NUTS = 41;</code>
-     */
-    ALLERGEN_TYPE_CODE_MACADAMIA_NUTS(41),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_METHYL_2_OCTYNOATE = 42;</code>
-     */
-    ALLERGEN_TYPE_CODE_METHYL_2_OCTYNOATE(42),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_MILK = 43;</code>
-     */
-    ALLERGEN_TYPE_CODE_MILK(43),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_MOLLUSCS = 44;</code>
-     */
-    ALLERGEN_TYPE_CODE_MOLLUSCS(44),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_MUSTARD = 45;</code>
-     */
-    ALLERGEN_TYPE_CODE_MUSTARD(45),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_NO_DECLARED_ALLERGENS = 46;</code>
-     */
-    ALLERGEN_TYPE_CODE_NO_DECLARED_ALLERGENS(46),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_OAT = 47;</code>
-     */
-    ALLERGEN_TYPE_CODE_OAT(47),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_PEANUTS = 48;</code>
-     */
-    ALLERGEN_TYPE_CODE_PEANUTS(48),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_PEAS = 49;</code>
-     */
-    ALLERGEN_TYPE_CODE_PEAS(49),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_PECAN_NUTS = 50;</code>
-     */
-    ALLERGEN_TYPE_CODE_PECAN_NUTS(50),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_PISTACHIOS = 51;</code>
-     */
-    ALLERGEN_TYPE_CODE_PISTACHIOS(51),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_POD_FRUITS = 52;</code>
-     */
-    ALLERGEN_TYPE_CODE_POD_FRUITS(52),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_QUEENSLAND_NUTS = 53;</code>
-     */
-    ALLERGEN_TYPE_CODE_QUEENSLAND_NUTS(53),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_RYE = 54;</code>
-     */
-    ALLERGEN_TYPE_CODE_RYE(54),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_SESAME_SEEDS = 55;</code>
-     */
-    ALLERGEN_TYPE_CODE_SESAME_SEEDS(55),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_SOYBEANS = 56;</code>
-     */
-    ALLERGEN_TYPE_CODE_SOYBEANS(56),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_SPELT = 57;</code>
-     */
-    ALLERGEN_TYPE_CODE_SPELT(57),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_SULPHUR_DIOXIDE = 58;</code>
-     */
-    ALLERGEN_TYPE_CODE_SULPHUR_DIOXIDE(58),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_TREE_NUTS = 59;</code>
-     */
-    ALLERGEN_TYPE_CODE_TREE_NUTS(59),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_TREE_NUT_TRACES = 60;</code>
-     */
-    ALLERGEN_TYPE_CODE_TREE_NUT_TRACES(60),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_WALNUTS = 61;</code>
-     */
-    ALLERGEN_TYPE_CODE_WALNUTS(61),
-    /**
-     * <code>ALLERGEN_TYPE_CODE_WHEAT = 62;</code>
-     */
-    ALLERGEN_TYPE_CODE_WHEAT(62),
-    UNRECOGNIZED(-1),
-    ;
-
-    /**
-     * <pre>
-     * Do not use. The allergen type code is not explicitly specified.
-     * </pre>
-     *
-     * <code>ALLERGEN_TYPE_CODE_UNSPECIFIED = 0;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_UNSPECIFIED_VALUE = 0;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_ALMONDS = 1;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_ALMONDS_VALUE = 1;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_ALPHA_ISOMETHYL_IONONE = 2;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_ALPHA_ISOMETHYL_IONONE_VALUE = 2;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_ALCOHOL = 3;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_ALCOHOL_VALUE = 3;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_AMYL_CINNAMAL = 4;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_AMYL_CINNAMAL_VALUE = 4;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_ANISE_ALCOHOL = 5;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_ANISE_ALCOHOL_VALUE = 5;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_BARLEY = 6;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_BARLEY_VALUE = 6;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_BENZYL_ALCOHOL = 7;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_BENZYL_ALCOHOL_VALUE = 7;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_BENZYL_BENZOATE = 8;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_BENZYL_BENZOATE_VALUE = 8;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_BENZYL_CINNAMATE = 9;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_BENZYL_CINNAMATE_VALUE = 9;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_BENZYL_SALICYLATE = 10;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_BENZYL_SALICYLATE_VALUE = 10;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_BRAZIL_NUTS = 11;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_BRAZIL_NUTS_VALUE = 11;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_BUTYLPHENYL_METHYLPROPIONATE = 12;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_BUTYLPHENYL_METHYLPROPIONATE_VALUE = 12;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_CARROTS = 13;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_CARROTS_VALUE = 13;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_CASHEW_NUTS = 14;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_CASHEW_NUTS_VALUE = 14;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_CELERY = 15;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_CELERY_VALUE = 15;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_CEREALS_CONTAINING_GLUTEN = 16;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_CEREALS_CONTAINING_GLUTEN_VALUE = 16;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_CINNAMAL = 17;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_CINNAMAL_VALUE = 17;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_CINNAMYL_ALCOHOL = 18;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_CINNAMYL_ALCOHOL_VALUE = 18;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_CITRAL = 19;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_CITRAL_VALUE = 19;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_CITRONELLOL = 20;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_CITRONELLOL_VALUE = 20;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_COCOA = 21;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_COCOA_VALUE = 21;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_CORIANDER = 22;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_CORIANDER_VALUE = 22;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_CORN = 23;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_CORN_VALUE = 23;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_COUMARIN = 24;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_COUMARIN_VALUE = 24;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_CRUSTACEANS = 25;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_CRUSTACEANS_VALUE = 25;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_EGGS = 26;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_EGGS_VALUE = 26;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_EUGENOL = 27;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_EUGENOL_VALUE = 27;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_EVERNIA_FURFURACEA = 28;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_EVERNIA_FURFURACEA_VALUE = 28;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_EVERNIA_PRUNASTRI = 29;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_EVERNIA_PRUNASTRI_VALUE = 29;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_FARNESOL = 30;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_FARNESOL_VALUE = 30;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_FISH = 31;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_FISH_VALUE = 31;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_GERANIOL = 32;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_GERANIOL_VALUE = 32;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_GLUTEN = 33;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_GLUTEN_VALUE = 33;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_HAZELNUTS = 34;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_HAZELNUTS_VALUE = 34;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_HEXYL_CINNAMAL = 35;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_HEXYL_CINNAMAL_VALUE = 35;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_HYDROXYCITRONELLAL = 36;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_HYDROXYCITRONELLAL_VALUE = 36;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_HYDROXYISOHEXYL_3_CYCLOHEXENE_CARBOXALDEHYDE_ISOEUGENOL_LIMONENE_LINAL = 37;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_HYDROXYISOHEXYL_3_CYCLOHEXENE_CARBOXALDEHYDE_ISOEUGENOL_LIMONENE_LINAL_VALUE = 37;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_KAMUT = 38;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_KAMUT_VALUE = 38;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_LACTOSE = 39;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_LACTOSE_VALUE = 39;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_LUPINE = 40;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_LUPINE_VALUE = 40;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_MACADAMIA_NUTS = 41;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_MACADAMIA_NUTS_VALUE = 41;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_METHYL_2_OCTYNOATE = 42;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_METHYL_2_OCTYNOATE_VALUE = 42;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_MILK = 43;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_MILK_VALUE = 43;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_MOLLUSCS = 44;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_MOLLUSCS_VALUE = 44;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_MUSTARD = 45;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_MUSTARD_VALUE = 45;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_NO_DECLARED_ALLERGENS = 46;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_NO_DECLARED_ALLERGENS_VALUE = 46;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_OAT = 47;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_OAT_VALUE = 47;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_PEANUTS = 48;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_PEANUTS_VALUE = 48;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_PEAS = 49;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_PEAS_VALUE = 49;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_PECAN_NUTS = 50;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_PECAN_NUTS_VALUE = 50;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_PISTACHIOS = 51;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_PISTACHIOS_VALUE = 51;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_POD_FRUITS = 52;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_POD_FRUITS_VALUE = 52;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_QUEENSLAND_NUTS = 53;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_QUEENSLAND_NUTS_VALUE = 53;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_RYE = 54;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_RYE_VALUE = 54;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_SESAME_SEEDS = 55;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_SESAME_SEEDS_VALUE = 55;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_SOYBEANS = 56;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_SOYBEANS_VALUE = 56;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_SPELT = 57;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_SPELT_VALUE = 57;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_SULPHUR_DIOXIDE = 58;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_SULPHUR_DIOXIDE_VALUE = 58;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_TREE_NUTS = 59;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_TREE_NUTS_VALUE = 59;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_TREE_NUT_TRACES = 60;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_TREE_NUT_TRACES_VALUE = 60;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_WALNUTS = 61;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_WALNUTS_VALUE = 61;
-    /**
-     * <code>ALLERGEN_TYPE_CODE_WHEAT = 62;</code>
-     */
-    public static final int ALLERGEN_TYPE_CODE_WHEAT_VALUE = 62;
-
-
-    public final int getNumber() {
-      if (this == UNRECOGNIZED) {
-        throw new java.lang.IllegalArgumentException(
-            "Can't get the number of an unknown enum value.");
-      }
-      return value;
-    }
-
-    /**
-     * @param value The numeric wire value of the corresponding enum entry.
-     * @return The enum associated with the given numeric wire value.
-     * @deprecated Use {@link #forNumber(int)} instead.
-     */
-    @java.lang.Deprecated
-    public static AllergenTypeCode valueOf(int value) {
-      return forNumber(value);
-    }
-
-    /**
-     * @param value The numeric wire value of the corresponding enum entry.
-     * @return The enum associated with the given numeric wire value.
-     */
-    public static AllergenTypeCode forNumber(int value) {
-      switch (value) {
-        case 0: return ALLERGEN_TYPE_CODE_UNSPECIFIED;
-        case 1: return ALLERGEN_TYPE_CODE_ALMONDS;
-        case 2: return ALLERGEN_TYPE_CODE_ALPHA_ISOMETHYL_IONONE;
-        case 3: return ALLERGEN_TYPE_CODE_ALCOHOL;
-        case 4: return ALLERGEN_TYPE_CODE_AMYL_CINNAMAL;
-        case 5: return ALLERGEN_TYPE_CODE_ANISE_ALCOHOL;
-        case 6: return ALLERGEN_TYPE_CODE_BARLEY;
-        case 7: return ALLERGEN_TYPE_CODE_BENZYL_ALCOHOL;
-        case 8: return ALLERGEN_TYPE_CODE_BENZYL_BENZOATE;
-        case 9: return ALLERGEN_TYPE_CODE_BENZYL_CINNAMATE;
-        case 10: return ALLERGEN_TYPE_CODE_BENZYL_SALICYLATE;
-        case 11: return ALLERGEN_TYPE_CODE_BRAZIL_NUTS;
-        case 12: return ALLERGEN_TYPE_CODE_BUTYLPHENYL_METHYLPROPIONATE;
-        case 13: return ALLERGEN_TYPE_CODE_CARROTS;
-        case 14: return ALLERGEN_TYPE_CODE_CASHEW_NUTS;
-        case 15: return ALLERGEN_TYPE_CODE_CELERY;
-        case 16: return ALLERGEN_TYPE_CODE_CEREALS_CONTAINING_GLUTEN;
-        case 17: return ALLERGEN_TYPE_CODE_CINNAMAL;
-        case 18: return ALLERGEN_TYPE_CODE_CINNAMYL_ALCOHOL;
-        case 19: return ALLERGEN_TYPE_CODE_CITRAL;
-        case 20: return ALLERGEN_TYPE_CODE_CITRONELLOL;
-        case 21: return ALLERGEN_TYPE_CODE_COCOA;
-        case 22: return ALLERGEN_TYPE_CODE_CORIANDER;
-        case 23: return ALLERGEN_TYPE_CODE_CORN;
-        case 24: return ALLERGEN_TYPE_CODE_COUMARIN;
-        case 25: return ALLERGEN_TYPE_CODE_CRUSTACEANS;
-        case 26: return ALLERGEN_TYPE_CODE_EGGS;
-        case 27: return ALLERGEN_TYPE_CODE_EUGENOL;
-        case 28: return ALLERGEN_TYPE_CODE_EVERNIA_FURFURACEA;
-        case 29: return ALLERGEN_TYPE_CODE_EVERNIA_PRUNASTRI;
-        case 30: return ALLERGEN_TYPE_CODE_FARNESOL;
-        case 31: return ALLERGEN_TYPE_CODE_FISH;
-        case 32: return ALLERGEN_TYPE_CODE_GERANIOL;
-        case 33: return ALLERGEN_TYPE_CODE_GLUTEN;
-        case 34: return ALLERGEN_TYPE_CODE_HAZELNUTS;
-        case 35: return ALLERGEN_TYPE_CODE_HEXYL_CINNAMAL;
-        case 36: return ALLERGEN_TYPE_CODE_HYDROXYCITRONELLAL;
-        case 37: return ALLERGEN_TYPE_CODE_HYDROXYISOHEXYL_3_CYCLOHEXENE_CARBOXALDEHYDE_ISOEUGENOL_LIMONENE_LINAL;
-        case 38: return ALLERGEN_TYPE_CODE_KAMUT;
-        case 39: return ALLERGEN_TYPE_CODE_LACTOSE;
-        case 40: return ALLERGEN_TYPE_CODE_LUPINE;
-        case 41: return ALLERGEN_TYPE_CODE_MACADAMIA_NUTS;
-        case 42: return ALLERGEN_TYPE_CODE_METHYL_2_OCTYNOATE;
-        case 43: return ALLERGEN_TYPE_CODE_MILK;
-        case 44: return ALLERGEN_TYPE_CODE_MOLLUSCS;
-        case 45: return ALLERGEN_TYPE_CODE_MUSTARD;
-        case 46: return ALLERGEN_TYPE_CODE_NO_DECLARED_ALLERGENS;
-        case 47: return ALLERGEN_TYPE_CODE_OAT;
-        case 48: return ALLERGEN_TYPE_CODE_PEANUTS;
-        case 49: return ALLERGEN_TYPE_CODE_PEAS;
-        case 50: return ALLERGEN_TYPE_CODE_PECAN_NUTS;
-        case 51: return ALLERGEN_TYPE_CODE_PISTACHIOS;
-        case 52: return ALLERGEN_TYPE_CODE_POD_FRUITS;
-        case 53: return ALLERGEN_TYPE_CODE_QUEENSLAND_NUTS;
-        case 54: return ALLERGEN_TYPE_CODE_RYE;
-        case 55: return ALLERGEN_TYPE_CODE_SESAME_SEEDS;
-        case 56: return ALLERGEN_TYPE_CODE_SOYBEANS;
-        case 57: return ALLERGEN_TYPE_CODE_SPELT;
-        case 58: return ALLERGEN_TYPE_CODE_SULPHUR_DIOXIDE;
-        case 59: return ALLERGEN_TYPE_CODE_TREE_NUTS;
-        case 60: return ALLERGEN_TYPE_CODE_TREE_NUT_TRACES;
-        case 61: return ALLERGEN_TYPE_CODE_WALNUTS;
-        case 62: return ALLERGEN_TYPE_CODE_WHEAT;
-        default: return null;
-      }
-    }
-
-    public static com.google.protobuf.Internal.EnumLiteMap<AllergenTypeCode>
-        internalGetValueMap() {
-      return internalValueMap;
-    }
-    private static final com.google.protobuf.Internal.EnumLiteMap<
-        AllergenTypeCode> internalValueMap =
-          new com.google.protobuf.Internal.EnumLiteMap<AllergenTypeCode>() {
-            public AllergenTypeCode findValueByNumber(int number) {
-              return AllergenTypeCode.forNumber(number);
-            }
-          };
-
-    public final com.google.protobuf.Descriptors.EnumValueDescriptor
-        getValueDescriptor() {
-      if (this == UNRECOGNIZED) {
-        throw new java.lang.IllegalStateException(
-            "Can't get the descriptor of an unrecognized enum value.");
-      }
-      return getDescriptor().getValues().get(ordinal());
-    }
-    public final com.google.protobuf.Descriptors.EnumDescriptor
-        getDescriptorForType() {
-      return getDescriptor();
-    }
-    public static final com.google.protobuf.Descriptors.EnumDescriptor
-        getDescriptor() {
-      return food.menu.v1.FoodMenu.getDescriptor().getEnumTypes().get(1);
-    }
-
-    private static final AllergenTypeCode[] VALUES = values();
-
-    public static AllergenTypeCode valueOf(
-        com.google.protobuf.Descriptors.EnumValueDescriptor desc) {
-      if (desc.getType() != getDescriptor()) {
-        throw new java.lang.IllegalArgumentException(
-          "EnumValueDescriptor is not for this type.");
-      }
-      if (desc.getIndex() == -1) {
-        return UNRECOGNIZED;
-      }
-      return VALUES[desc.getIndex()];
-    }
-
-    private final int value;
-
-    private AllergenTypeCode(int value) {
-      this.value = value;
-    }
-
-    // @@protoc_insertion_point(enum_scope:food.menu.v1.AllergenTypeCode)
-  }
-
-  /**
-   * Protobuf enum {@code food.menu.v1.NutritionValueUnit}
-   */
-  public enum NutritionValueUnit
-      implements com.google.protobuf.ProtocolMessageEnum {
-    /**
-     * <pre>
-     * Do not use. The nutrition value unit is not explicitly set.
-     * </pre>
-     *
-     * <code>NUTRITION_VALUE_UNIT_UNSPECIFIED = 0;</code>
-     */
-    NUTRITION_VALUE_UNIT_UNSPECIFIED(0),
-    /**
-     * <pre>
-     * Units used to express the amount of energy in a menu item.
-     * </pre>
-     *
-     * <code>ENERGY_CALORIES = 1;</code>
-     */
-    ENERGY_CALORIES(1),
-    /**
-     * <code>ENERGY_KILOJOULES = 2;</code>
-     */
-    ENERGY_KILOJOULES(2),
-    /**
-     * <pre>
-     * Units used to express the amount in weight a substance is present in the
-     * menu item.
-     * </pre>
-     *
-     * <code>WEIGHT_MILLIGRAMS = 3;</code>
-     */
-    WEIGHT_MILLIGRAMS(3),
-    /**
-     * <code>WEIGHT_GRAMS = 4;</code>
-     */
-    WEIGHT_GRAMS(4),
-    UNRECOGNIZED(-1),
-    ;
-
-    /**
-     * <pre>
-     * Do not use. The nutrition value unit is not explicitly set.
-     * </pre>
-     *
-     * <code>NUTRITION_VALUE_UNIT_UNSPECIFIED = 0;</code>
-     */
-    public static final int NUTRITION_VALUE_UNIT_UNSPECIFIED_VALUE = 0;
-    /**
-     * <pre>
-     * Units used to express the amount of energy in a menu item.
-     * </pre>
-     *
-     * <code>ENERGY_CALORIES = 1;</code>
-     */
-    public static final int ENERGY_CALORIES_VALUE = 1;
-    /**
-     * <code>ENERGY_KILOJOULES = 2;</code>
-     */
-    public static final int ENERGY_KILOJOULES_VALUE = 2;
-    /**
-     * <pre>
-     * Units used to express the amount in weight a substance is present in the
-     * menu item.
-     * </pre>
-     *
-     * <code>WEIGHT_MILLIGRAMS = 3;</code>
-     */
-    public static final int WEIGHT_MILLIGRAMS_VALUE = 3;
-    /**
-     * <code>WEIGHT_GRAMS = 4;</code>
-     */
-    public static final int WEIGHT_GRAMS_VALUE = 4;
-
-
-    public final int getNumber() {
-      if (this == UNRECOGNIZED) {
-        throw new java.lang.IllegalArgumentException(
-            "Can't get the number of an unknown enum value.");
-      }
-      return value;
-    }
-
-    /**
-     * @param value The numeric wire value of the corresponding enum entry.
-     * @return The enum associated with the given numeric wire value.
-     * @deprecated Use {@link #forNumber(int)} instead.
-     */
-    @java.lang.Deprecated
-    public static NutritionValueUnit valueOf(int value) {
-      return forNumber(value);
-    }
-
-    /**
-     * @param value The numeric wire value of the corresponding enum entry.
-     * @return The enum associated with the given numeric wire value.
-     */
-    public static NutritionValueUnit forNumber(int value) {
-      switch (value) {
-        case 0: return NUTRITION_VALUE_UNIT_UNSPECIFIED;
-        case 1: return ENERGY_CALORIES;
-        case 2: return ENERGY_KILOJOULES;
-        case 3: return WEIGHT_MILLIGRAMS;
-        case 4: return WEIGHT_GRAMS;
-        default: return null;
-      }
-    }
-
-    public static com.google.protobuf.Internal.EnumLiteMap<NutritionValueUnit>
-        internalGetValueMap() {
-      return internalValueMap;
-    }
-    private static final com.google.protobuf.Internal.EnumLiteMap<
-        NutritionValueUnit> internalValueMap =
-          new com.google.protobuf.Internal.EnumLiteMap<NutritionValueUnit>() {
-            public NutritionValueUnit findValueByNumber(int number) {
-              return NutritionValueUnit.forNumber(number);
-            }
-          };
-
-    public final com.google.protobuf.Descriptors.EnumValueDescriptor
-        getValueDescriptor() {
-      if (this == UNRECOGNIZED) {
-        throw new java.lang.IllegalStateException(
-            "Can't get the descriptor of an unrecognized enum value.");
-      }
-      return getDescriptor().getValues().get(ordinal());
-    }
-    public final com.google.protobuf.Descriptors.EnumDescriptor
-        getDescriptorForType() {
-      return getDescriptor();
-    }
-    public static final com.google.protobuf.Descriptors.EnumDescriptor
-        getDescriptor() {
-      return food.menu.v1.FoodMenu.getDescriptor().getEnumTypes().get(2);
-    }
-
-    private static final NutritionValueUnit[] VALUES = values();
-
-    public static NutritionValueUnit valueOf(
-        com.google.protobuf.Descriptors.EnumValueDescriptor desc) {
-      if (desc.getType() != getDescriptor()) {
-        throw new java.lang.IllegalArgumentException(
-          "EnumValueDescriptor is not for this type.");
-      }
-      if (desc.getIndex() == -1) {
-        return UNRECOGNIZED;
-      }
-      return VALUES[desc.getIndex()];
-    }
-
-    private final int value;
-
-    private NutritionValueUnit(int value) {
-      this.value = value;
-    }
-
-    // @@protoc_insertion_point(enum_scope:food.menu.v1.NutritionValueUnit)
-  }
-
-  /**
-   * <pre>
-   * Indicates the level of containment a food item has of a certain attribute,
-   * such as allergens or additives.
-   * </pre>
-   *
-   * Protobuf enum {@code food.menu.v1.ContainmentLevelCode}
-   */
-  public enum ContainmentLevelCode
-      implements com.google.protobuf.ProtocolMessageEnum {
-    /**
-     * <pre>
-     * Do not use. The containment level code is not explicitly specified.
-     * </pre>
-     *
-     * <code>CONTAINMENT_LEVEL_CODE_UNSPECIFIED = 0;</code>
-     */
-    CONTAINMENT_LEVEL_CODE_UNSPECIFIED(0),
-    /**
-     * <code>CONTAINMENT_LEVEL_CODE_CONTAINS = 1;</code>
-     */
-    CONTAINMENT_LEVEL_CODE_CONTAINS(1),
-    /**
-     * <code>CONTAINMENT_LEVEL_CODE_DOES_NOT_CONTAIN = 2;</code>
-     */
-    CONTAINMENT_LEVEL_CODE_DOES_NOT_CONTAIN(2),
-    /**
-     * <code>CONTAINMENT_LEVEL_CODE_MAY_CONTAIN = 3;</code>
-     */
-    CONTAINMENT_LEVEL_CODE_MAY_CONTAIN(3),
-    UNRECOGNIZED(-1),
-    ;
-
-    /**
-     * <pre>
-     * Do not use. The containment level code is not explicitly specified.
-     * </pre>
-     *
-     * <code>CONTAINMENT_LEVEL_CODE_UNSPECIFIED = 0;</code>
-     */
-    public static final int CONTAINMENT_LEVEL_CODE_UNSPECIFIED_VALUE = 0;
-    /**
-     * <code>CONTAINMENT_LEVEL_CODE_CONTAINS = 1;</code>
-     */
-    public static final int CONTAINMENT_LEVEL_CODE_CONTAINS_VALUE = 1;
-    /**
-     * <code>CONTAINMENT_LEVEL_CODE_DOES_NOT_CONTAIN = 2;</code>
-     */
-    public static final int CONTAINMENT_LEVEL_CODE_DOES_NOT_CONTAIN_VALUE = 2;
-    /**
-     * <code>CONTAINMENT_LEVEL_CODE_MAY_CONTAIN = 3;</code>
-     */
-    public static final int CONTAINMENT_LEVEL_CODE_MAY_CONTAIN_VALUE = 3;
-
-
-    public final int getNumber() {
-      if (this == UNRECOGNIZED) {
-        throw new java.lang.IllegalArgumentException(
-            "Can't get the number of an unknown enum value.");
-      }
-      return value;
-    }
-
-    /**
-     * @param value The numeric wire value of the corresponding enum entry.
-     * @return The enum associated with the given numeric wire value.
-     * @deprecated Use {@link #forNumber(int)} instead.
-     */
-    @java.lang.Deprecated
-    public static ContainmentLevelCode valueOf(int value) {
-      return forNumber(value);
-    }
-
-    /**
-     * @param value The numeric wire value of the corresponding enum entry.
-     * @return The enum associated with the given numeric wire value.
-     */
-    public static ContainmentLevelCode forNumber(int value) {
-      switch (value) {
-        case 0: return CONTAINMENT_LEVEL_CODE_UNSPECIFIED;
-        case 1: return CONTAINMENT_LEVEL_CODE_CONTAINS;
-        case 2: return CONTAINMENT_LEVEL_CODE_DOES_NOT_CONTAIN;
-        case 3: return CONTAINMENT_LEVEL_CODE_MAY_CONTAIN;
-        default: return null;
-      }
-    }
-
-    public static com.google.protobuf.Internal.EnumLiteMap<ContainmentLevelCode>
-        internalGetValueMap() {
-      return internalValueMap;
-    }
-    private static final com.google.protobuf.Internal.EnumLiteMap<
-        ContainmentLevelCode> internalValueMap =
-          new com.google.protobuf.Internal.EnumLiteMap<ContainmentLevelCode>() {
-            public ContainmentLevelCode findValueByNumber(int number) {
-              return ContainmentLevelCode.forNumber(number);
-            }
-          };
-
-    public final com.google.protobuf.Descriptors.EnumValueDescriptor
-        getValueDescriptor() {
-      if (this == UNRECOGNIZED) {
-        throw new java.lang.IllegalStateException(
-            "Can't get the descriptor of an unrecognized enum value.");
-      }
-      return getDescriptor().getValues().get(ordinal());
-    }
-    public final com.google.protobuf.Descriptors.EnumDescriptor
-        getDescriptorForType() {
-      return getDescriptor();
-    }
-    public static final com.google.protobuf.Descriptors.EnumDescriptor
-        getDescriptor() {
-      return food.menu.v1.FoodMenu.getDescriptor().getEnumTypes().get(3);
-    }
-
-    private static final ContainmentLevelCode[] VALUES = values();
-
-    public static ContainmentLevelCode valueOf(
-        com.google.protobuf.Descriptors.EnumValueDescriptor desc) {
-      if (desc.getType() != getDescriptor()) {
-        throw new java.lang.IllegalArgumentException(
-          "EnumValueDescriptor is not for this type.");
-      }
-      if (desc.getIndex() == -1) {
-        return UNRECOGNIZED;
-      }
-      return VALUES[desc.getIndex()];
-    }
-
-    private final int value;
-
-    private ContainmentLevelCode(int value) {
-      this.value = value;
-    }
-
-    // @@protoc_insertion_point(enum_scope:food.menu.v1.ContainmentLevelCode)
-  }
-
-  /**
-   * <pre>
-   * Indicates how to properly deposit a food item or bottle.
-   * </pre>
-   *
-   * Protobuf enum {@code food.menu.v1.DepositCode}
-   */
-  public enum DepositCode
-      implements com.google.protobuf.ProtocolMessageEnum {
-    /**
-     * <pre>
-     * Do not use. The deposite code is not explicitly specified.
-     * </pre>
-     *
-     * <code>DEPOSIT_CODE_UNSPECIFIED = 0;</code>
-     */
-    DEPOSIT_CODE_UNSPECIFIED(0),
-    /**
-     * <code>DEPOSIT_CODE_REUSABLE = 1;</code>
-     */
-    DEPOSIT_CODE_REUSABLE(1),
-    /**
-     * <code>DEPOSIT_CODE_RECYCLABLE = 2;</code>
-     */
-    DEPOSIT_CODE_RECYCLABLE(2),
-    UNRECOGNIZED(-1),
-    ;
-
-    /**
-     * <pre>
-     * Do not use. The deposite code is not explicitly specified.
-     * </pre>
-     *
-     * <code>DEPOSIT_CODE_UNSPECIFIED = 0;</code>
-     */
-    public static final int DEPOSIT_CODE_UNSPECIFIED_VALUE = 0;
-    /**
-     * <code>DEPOSIT_CODE_REUSABLE = 1;</code>
-     */
-    public static final int DEPOSIT_CODE_REUSABLE_VALUE = 1;
-    /**
-     * <code>DEPOSIT_CODE_RECYCLABLE = 2;</code>
-     */
-    public static final int DEPOSIT_CODE_RECYCLABLE_VALUE = 2;
-
-
-    public final int getNumber() {
-      if (this == UNRECOGNIZED) {
-        throw new java.lang.IllegalArgumentException(
-            "Can't get the number of an unknown enum value.");
-      }
-      return value;
-    }
-
-    /**
-     * @param value The numeric wire value of the corresponding enum entry.
-     * @return The enum associated with the given numeric wire value.
-     * @deprecated Use {@link #forNumber(int)} instead.
-     */
-    @java.lang.Deprecated
-    public static DepositCode valueOf(int value) {
-      return forNumber(value);
-    }
-
-    /**
-     * @param value The numeric wire value of the corresponding enum entry.
-     * @return The enum associated with the given numeric wire value.
-     */
-    public static DepositCode forNumber(int value) {
-      switch (value) {
-        case 0: return DEPOSIT_CODE_UNSPECIFIED;
-        case 1: return DEPOSIT_CODE_REUSABLE;
-        case 2: return DEPOSIT_CODE_RECYCLABLE;
-        default: return null;
-      }
-    }
-
-    public static com.google.protobuf.Internal.EnumLiteMap<DepositCode>
-        internalGetValueMap() {
-      return internalValueMap;
-    }
-    private static final com.google.protobuf.Internal.EnumLiteMap<
-        DepositCode> internalValueMap =
-          new com.google.protobuf.Internal.EnumLiteMap<DepositCode>() {
-            public DepositCode findValueByNumber(int number) {
-              return DepositCode.forNumber(number);
-            }
-          };
-
-    public final com.google.protobuf.Descriptors.EnumValueDescriptor
-        getValueDescriptor() {
-      if (this == UNRECOGNIZED) {
-        throw new java.lang.IllegalStateException(
-            "Can't get the descriptor of an unrecognized enum value.");
-      }
-      return getDescriptor().getValues().get(ordinal());
-    }
-    public final com.google.protobuf.Descriptors.EnumDescriptor
-        getDescriptorForType() {
-      return getDescriptor();
-    }
-    public static final com.google.protobuf.Descriptors.EnumDescriptor
-        getDescriptor() {
-      return food.menu.v1.FoodMenu.getDescriptor().getEnumTypes().get(4);
-    }
-
-    private static final DepositCode[] VALUES = values();
-
-    public static DepositCode valueOf(
-        com.google.protobuf.Descriptors.EnumValueDescriptor desc) {
-      if (desc.getType() != getDescriptor()) {
-        throw new java.lang.IllegalArgumentException(
-          "EnumValueDescriptor is not for this type.");
-      }
-      if (desc.getIndex() == -1) {
-        return UNRECOGNIZED;
-      }
-      return VALUES[desc.getIndex()];
-    }
-
-    private final int value;
-
-    private DepositCode(int value) {
-      this.value = value;
-    }
-
-    // @@protoc_insertion_point(enum_scope:food.menu.v1.DepositCode)
-  }
-
-  public interface FoodMenuFeedOrBuilder extends
-      // @@protoc_insertion_point(interface_extends:food.menu.v1.FoodMenuFeed)
-      com.google.protobuf.MessageOrBuilder {
-
-    /**
-     * <code>repeated .food.menu.v1.MenuComponent data = 1;</code>
-     */
-    java.util.List<food.menu.v1.FoodMenu.MenuComponent> 
-        getDataList();
-    /**
-     * <code>repeated .food.menu.v1.MenuComponent data = 1;</code>
-     */
-    food.menu.v1.FoodMenu.MenuComponent getData(int index);
-    /**
-     * <code>repeated .food.menu.v1.MenuComponent data = 1;</code>
-     */
-    int getDataCount();
-    /**
-     * <code>repeated .food.menu.v1.MenuComponent data = 1;</code>
-     */
-    java.util.List<? extends food.menu.v1.FoodMenu.MenuComponentOrBuilder> 
-        getDataOrBuilderList();
-    /**
-     * <code>repeated .food.menu.v1.MenuComponent data = 1;</code>
-     */
-    food.menu.v1.FoodMenu.MenuComponentOrBuilder getDataOrBuilder(
-        int index);
-  }
-  /**
-   * Protobuf type {@code food.menu.v1.FoodMenuFeed}
-   */
-  public static final class FoodMenuFeed extends
-      com.google.protobuf.GeneratedMessageV3 implements
-      // @@protoc_insertion_point(message_implements:food.menu.v1.FoodMenuFeed)
-      FoodMenuFeedOrBuilder {
-  private static final long serialVersionUID = 0L;
-    // Use FoodMenuFeed.newBuilder() to construct.
-    private FoodMenuFeed(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
-      super(builder);
-    }
-    private FoodMenuFeed() {
-      data_ = java.util.Collections.emptyList();
-    }
-
-    @java.lang.Override
-    @SuppressWarnings({"unused"})
-    protected java.lang.Object newInstance(
-        UnusedPrivateParameter unused) {
-      return new FoodMenuFeed();
-    }
-
-    public static final com.google.protobuf.Descriptors.Descriptor
-        getDescriptor() {
-      return food.menu.v1.FoodMenu.internal_static_food_menu_v1_FoodMenuFeed_descriptor;
-    }
-
-    @java.lang.Override
-    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-        internalGetFieldAccessorTable() {
-      return food.menu.v1.FoodMenu.internal_static_food_menu_v1_FoodMenuFeed_fieldAccessorTable
-          .ensureFieldAccessorsInitialized(
-              food.menu.v1.FoodMenu.FoodMenuFeed.class, food.menu.v1.FoodMenu.FoodMenuFeed.Builder.class);
-    }
-
-    public static final int DATA_FIELD_NUMBER = 1;
-    @SuppressWarnings("serial")
-    private java.util.List<food.menu.v1.FoodMenu.MenuComponent> data_;
-    /**
-     * <code>repeated .food.menu.v1.MenuComponent data = 1;</code>
-     */
-    @java.lang.Override
-    public java.util.List<food.menu.v1.FoodMenu.MenuComponent> getDataList() {
-      return data_;
-    }
-    /**
-     * <code>repeated .food.menu.v1.MenuComponent data = 1;</code>
-     */
-    @java.lang.Override
-    public java.util.List<? extends food.menu.v1.FoodMenu.MenuComponentOrBuilder> 
-        getDataOrBuilderList() {
-      return data_;
-    }
-    /**
-     * <code>repeated .food.menu.v1.MenuComponent data = 1;</code>
-     */
-    @java.lang.Override
-    public int getDataCount() {
-      return data_.size();
-    }
-    /**
-     * <code>repeated .food.menu.v1.MenuComponent data = 1;</code>
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.MenuComponent getData(int index) {
-      return data_.get(index);
-    }
-    /**
-     * <code>repeated .food.menu.v1.MenuComponent data = 1;</code>
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.MenuComponentOrBuilder getDataOrBuilder(
-        int index) {
-      return data_.get(index);
-    }
-
-    private byte memoizedIsInitialized = -1;
-    @java.lang.Override
-    public final boolean isInitialized() {
-      byte isInitialized = memoizedIsInitialized;
-      if (isInitialized == 1) return true;
-      if (isInitialized == 0) return false;
-
-      memoizedIsInitialized = 1;
-      return true;
-    }
-
-    @java.lang.Override
-    public void writeTo(com.google.protobuf.CodedOutputStream output)
-                        throws java.io.IOException {
-      for (int i = 0; i < data_.size(); i++) {
-        output.writeMessage(1, data_.get(i));
-      }
-      getUnknownFields().writeTo(output);
-    }
-
-    @java.lang.Override
-    public int getSerializedSize() {
-      int size = memoizedSize;
-      if (size != -1) return size;
-
-      size = 0;
-      for (int i = 0; i < data_.size(); i++) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(1, data_.get(i));
-      }
-      size += getUnknownFields().getSerializedSize();
-      memoizedSize = size;
-      return size;
-    }
-
-    @java.lang.Override
-    public boolean equals(final java.lang.Object obj) {
-      if (obj == this) {
-       return true;
-      }
-      if (!(obj instanceof food.menu.v1.FoodMenu.FoodMenuFeed)) {
-        return super.equals(obj);
-      }
-      food.menu.v1.FoodMenu.FoodMenuFeed other = (food.menu.v1.FoodMenu.FoodMenuFeed) obj;
-
-      if (!getDataList()
-          .equals(other.getDataList())) return false;
-      if (!getUnknownFields().equals(other.getUnknownFields())) return false;
-      return true;
-    }
-
-    @java.lang.Override
-    public int hashCode() {
-      if (memoizedHashCode != 0) {
-        return memoizedHashCode;
-      }
-      int hash = 41;
-      hash = (19 * hash) + getDescriptor().hashCode();
-      if (getDataCount() > 0) {
-        hash = (37 * hash) + DATA_FIELD_NUMBER;
-        hash = (53 * hash) + getDataList().hashCode();
-      }
-      hash = (29 * hash) + getUnknownFields().hashCode();
-      memoizedHashCode = hash;
-      return hash;
-    }
-
-    public static food.menu.v1.FoodMenu.FoodMenuFeed parseFrom(
-        java.nio.ByteBuffer data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.FoodMenuFeed parseFrom(
-        java.nio.ByteBuffer data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.FoodMenuFeed parseFrom(
-        com.google.protobuf.ByteString data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.FoodMenuFeed parseFrom(
-        com.google.protobuf.ByteString data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.FoodMenuFeed parseFrom(byte[] data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.FoodMenuFeed parseFrom(
-        byte[] data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.FoodMenuFeed parseFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.FoodMenuFeed parseFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.FoodMenuFeed parseDelimitedFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseDelimitedWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.FoodMenuFeed parseDelimitedFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.FoodMenuFeed parseFrom(
-        com.google.protobuf.CodedInputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.FoodMenuFeed parseFrom(
-        com.google.protobuf.CodedInputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input, extensionRegistry);
-    }
-
-    @java.lang.Override
-    public Builder newBuilderForType() { return newBuilder(); }
-    public static Builder newBuilder() {
-      return DEFAULT_INSTANCE.toBuilder();
-    }
-    public static Builder newBuilder(food.menu.v1.FoodMenu.FoodMenuFeed prototype) {
-      return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
-    }
-    @java.lang.Override
-    public Builder toBuilder() {
-      return this == DEFAULT_INSTANCE
-          ? new Builder() : new Builder().mergeFrom(this);
-    }
-
-    @java.lang.Override
-    protected Builder newBuilderForType(
-        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-      Builder builder = new Builder(parent);
-      return builder;
-    }
-    /**
-     * Protobuf type {@code food.menu.v1.FoodMenuFeed}
-     */
-    public static final class Builder extends
-        com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
-        // @@protoc_insertion_point(builder_implements:food.menu.v1.FoodMenuFeed)
-        food.menu.v1.FoodMenu.FoodMenuFeedOrBuilder {
-      public static final com.google.protobuf.Descriptors.Descriptor
-          getDescriptor() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_FoodMenuFeed_descriptor;
-      }
-
-      @java.lang.Override
-      protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-          internalGetFieldAccessorTable() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_FoodMenuFeed_fieldAccessorTable
-            .ensureFieldAccessorsInitialized(
-                food.menu.v1.FoodMenu.FoodMenuFeed.class, food.menu.v1.FoodMenu.FoodMenuFeed.Builder.class);
-      }
-
-      // Construct using food.menu.v1.FoodMenu.FoodMenuFeed.newBuilder()
-      private Builder() {
-
-      }
-
-      private Builder(
-          com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-        super(parent);
-
-      }
-      @java.lang.Override
-      public Builder clear() {
-        super.clear();
-        bitField0_ = 0;
-        if (dataBuilder_ == null) {
-          data_ = java.util.Collections.emptyList();
-        } else {
-          data_ = null;
-          dataBuilder_.clear();
-        }
-        bitField0_ = (bitField0_ & ~0x00000001);
-        return this;
-      }
-
-      @java.lang.Override
-      public com.google.protobuf.Descriptors.Descriptor
-          getDescriptorForType() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_FoodMenuFeed_descriptor;
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.FoodMenuFeed getDefaultInstanceForType() {
-        return food.menu.v1.FoodMenu.FoodMenuFeed.getDefaultInstance();
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.FoodMenuFeed build() {
-        food.menu.v1.FoodMenu.FoodMenuFeed result = buildPartial();
-        if (!result.isInitialized()) {
-          throw newUninitializedMessageException(result);
-        }
-        return result;
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.FoodMenuFeed buildPartial() {
-        food.menu.v1.FoodMenu.FoodMenuFeed result = new food.menu.v1.FoodMenu.FoodMenuFeed(this);
-        buildPartialRepeatedFields(result);
-        if (bitField0_ != 0) { buildPartial0(result); }
-        onBuilt();
-        return result;
-      }
-
-      private void buildPartialRepeatedFields(food.menu.v1.FoodMenu.FoodMenuFeed result) {
-        if (dataBuilder_ == null) {
-          if (((bitField0_ & 0x00000001) != 0)) {
-            data_ = java.util.Collections.unmodifiableList(data_);
-            bitField0_ = (bitField0_ & ~0x00000001);
-          }
-          result.data_ = data_;
-        } else {
-          result.data_ = dataBuilder_.build();
-        }
-      }
-
-      private void buildPartial0(food.menu.v1.FoodMenu.FoodMenuFeed result) {
-        int from_bitField0_ = bitField0_;
-      }
-
-      @java.lang.Override
-      public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof food.menu.v1.FoodMenu.FoodMenuFeed) {
-          return mergeFrom((food.menu.v1.FoodMenu.FoodMenuFeed)other);
-        } else {
-          super.mergeFrom(other);
-          return this;
-        }
-      }
-
-      public Builder mergeFrom(food.menu.v1.FoodMenu.FoodMenuFeed other) {
-        if (other == food.menu.v1.FoodMenu.FoodMenuFeed.getDefaultInstance()) return this;
-        if (dataBuilder_ == null) {
-          if (!other.data_.isEmpty()) {
-            if (data_.isEmpty()) {
-              data_ = other.data_;
-              bitField0_ = (bitField0_ & ~0x00000001);
-            } else {
-              ensureDataIsMutable();
-              data_.addAll(other.data_);
-            }
-            onChanged();
-          }
-        } else {
-          if (!other.data_.isEmpty()) {
-            if (dataBuilder_.isEmpty()) {
-              dataBuilder_.dispose();
-              dataBuilder_ = null;
-              data_ = other.data_;
-              bitField0_ = (bitField0_ & ~0x00000001);
-              dataBuilder_ = 
-                com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ?
-                   getDataFieldBuilder() : null;
-            } else {
-              dataBuilder_.addAllMessages(other.data_);
-            }
-          }
-        }
-        this.mergeUnknownFields(other.getUnknownFields());
-        onChanged();
-        return this;
-      }
-
-      @java.lang.Override
-      public final boolean isInitialized() {
-        return true;
-      }
-
-      @java.lang.Override
-      public Builder mergeFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws java.io.IOException {
-        if (extensionRegistry == null) {
-          throw new java.lang.NullPointerException();
-        }
-        try {
-          boolean done = false;
-          while (!done) {
-            int tag = input.readTag();
-            switch (tag) {
-              case 0:
-                done = true;
-                break;
-              case 10: {
-                food.menu.v1.FoodMenu.MenuComponent m =
-                    input.readMessage(
-                        food.menu.v1.FoodMenu.MenuComponent.parser(),
-                        extensionRegistry);
-                if (dataBuilder_ == null) {
-                  ensureDataIsMutable();
-                  data_.add(m);
-                } else {
-                  dataBuilder_.addMessage(m);
-                }
-                break;
-              } // case 10
-              default: {
-                if (!super.parseUnknownField(input, extensionRegistry, tag)) {
-                  done = true; // was an endgroup tag
-                }
-                break;
-              } // default:
-            } // switch (tag)
-          } // while (!done)
-        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          throw e.unwrapIOException();
-        } finally {
-          onChanged();
-        } // finally
-        return this;
-      }
-      private int bitField0_;
-
-      private java.util.List<food.menu.v1.FoodMenu.MenuComponent> data_ =
-        java.util.Collections.emptyList();
-      private void ensureDataIsMutable() {
-        if (!((bitField0_ & 0x00000001) != 0)) {
-          data_ = new java.util.ArrayList<food.menu.v1.FoodMenu.MenuComponent>(data_);
-          bitField0_ |= 0x00000001;
-         }
-      }
-
-      private com.google.protobuf.RepeatedFieldBuilderV3<
-          food.menu.v1.FoodMenu.MenuComponent, food.menu.v1.FoodMenu.MenuComponent.Builder, food.menu.v1.FoodMenu.MenuComponentOrBuilder> dataBuilder_;
-
-      /**
-       * <code>repeated .food.menu.v1.MenuComponent data = 1;</code>
-       */
-      public java.util.List<food.menu.v1.FoodMenu.MenuComponent> getDataList() {
-        if (dataBuilder_ == null) {
-          return java.util.Collections.unmodifiableList(data_);
-        } else {
-          return dataBuilder_.getMessageList();
-        }
-      }
-      /**
-       * <code>repeated .food.menu.v1.MenuComponent data = 1;</code>
-       */
-      public int getDataCount() {
-        if (dataBuilder_ == null) {
-          return data_.size();
-        } else {
-          return dataBuilder_.getCount();
-        }
-      }
-      /**
-       * <code>repeated .food.menu.v1.MenuComponent data = 1;</code>
-       */
-      public food.menu.v1.FoodMenu.MenuComponent getData(int index) {
-        if (dataBuilder_ == null) {
-          return data_.get(index);
-        } else {
-          return dataBuilder_.getMessage(index);
-        }
-      }
-      /**
-       * <code>repeated .food.menu.v1.MenuComponent data = 1;</code>
-       */
-      public Builder setData(
-          int index, food.menu.v1.FoodMenu.MenuComponent value) {
-        if (dataBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          ensureDataIsMutable();
-          data_.set(index, value);
-          onChanged();
-        } else {
-          dataBuilder_.setMessage(index, value);
-        }
-        return this;
-      }
-      /**
-       * <code>repeated .food.menu.v1.MenuComponent data = 1;</code>
-       */
-      public Builder setData(
-          int index, food.menu.v1.FoodMenu.MenuComponent.Builder builderForValue) {
-        if (dataBuilder_ == null) {
-          ensureDataIsMutable();
-          data_.set(index, builderForValue.build());
-          onChanged();
-        } else {
-          dataBuilder_.setMessage(index, builderForValue.build());
-        }
-        return this;
-      }
-      /**
-       * <code>repeated .food.menu.v1.MenuComponent data = 1;</code>
-       */
-      public Builder addData(food.menu.v1.FoodMenu.MenuComponent value) {
-        if (dataBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          ensureDataIsMutable();
-          data_.add(value);
-          onChanged();
-        } else {
-          dataBuilder_.addMessage(value);
-        }
-        return this;
-      }
-      /**
-       * <code>repeated .food.menu.v1.MenuComponent data = 1;</code>
-       */
-      public Builder addData(
-          int index, food.menu.v1.FoodMenu.MenuComponent value) {
-        if (dataBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          ensureDataIsMutable();
-          data_.add(index, value);
-          onChanged();
-        } else {
-          dataBuilder_.addMessage(index, value);
-        }
-        return this;
-      }
-      /**
-       * <code>repeated .food.menu.v1.MenuComponent data = 1;</code>
-       */
-      public Builder addData(
-          food.menu.v1.FoodMenu.MenuComponent.Builder builderForValue) {
-        if (dataBuilder_ == null) {
-          ensureDataIsMutable();
-          data_.add(builderForValue.build());
-          onChanged();
-        } else {
-          dataBuilder_.addMessage(builderForValue.build());
-        }
-        return this;
-      }
-      /**
-       * <code>repeated .food.menu.v1.MenuComponent data = 1;</code>
-       */
-      public Builder addData(
-          int index, food.menu.v1.FoodMenu.MenuComponent.Builder builderForValue) {
-        if (dataBuilder_ == null) {
-          ensureDataIsMutable();
-          data_.add(index, builderForValue.build());
-          onChanged();
-        } else {
-          dataBuilder_.addMessage(index, builderForValue.build());
-        }
-        return this;
-      }
-      /**
-       * <code>repeated .food.menu.v1.MenuComponent data = 1;</code>
-       */
-      public Builder addAllData(
-          java.lang.Iterable<? extends food.menu.v1.FoodMenu.MenuComponent> values) {
-        if (dataBuilder_ == null) {
-          ensureDataIsMutable();
-          com.google.protobuf.AbstractMessageLite.Builder.addAll(
-              values, data_);
-          onChanged();
-        } else {
-          dataBuilder_.addAllMessages(values);
-        }
-        return this;
-      }
-      /**
-       * <code>repeated .food.menu.v1.MenuComponent data = 1;</code>
-       */
-      public Builder clearData() {
-        if (dataBuilder_ == null) {
-          data_ = java.util.Collections.emptyList();
-          bitField0_ = (bitField0_ & ~0x00000001);
-          onChanged();
-        } else {
-          dataBuilder_.clear();
-        }
-        return this;
-      }
-      /**
-       * <code>repeated .food.menu.v1.MenuComponent data = 1;</code>
-       */
-      public Builder removeData(int index) {
-        if (dataBuilder_ == null) {
-          ensureDataIsMutable();
-          data_.remove(index);
-          onChanged();
-        } else {
-          dataBuilder_.remove(index);
-        }
-        return this;
-      }
-      /**
-       * <code>repeated .food.menu.v1.MenuComponent data = 1;</code>
-       */
-      public food.menu.v1.FoodMenu.MenuComponent.Builder getDataBuilder(
-          int index) {
-        return getDataFieldBuilder().getBuilder(index);
-      }
-      /**
-       * <code>repeated .food.menu.v1.MenuComponent data = 1;</code>
-       */
-      public food.menu.v1.FoodMenu.MenuComponentOrBuilder getDataOrBuilder(
-          int index) {
-        if (dataBuilder_ == null) {
-          return data_.get(index);  } else {
-          return dataBuilder_.getMessageOrBuilder(index);
-        }
-      }
-      /**
-       * <code>repeated .food.menu.v1.MenuComponent data = 1;</code>
-       */
-      public java.util.List<? extends food.menu.v1.FoodMenu.MenuComponentOrBuilder> 
-           getDataOrBuilderList() {
-        if (dataBuilder_ != null) {
-          return dataBuilder_.getMessageOrBuilderList();
-        } else {
-          return java.util.Collections.unmodifiableList(data_);
-        }
-      }
-      /**
-       * <code>repeated .food.menu.v1.MenuComponent data = 1;</code>
-       */
-      public food.menu.v1.FoodMenu.MenuComponent.Builder addDataBuilder() {
-        return getDataFieldBuilder().addBuilder(
-            food.menu.v1.FoodMenu.MenuComponent.getDefaultInstance());
-      }
-      /**
-       * <code>repeated .food.menu.v1.MenuComponent data = 1;</code>
-       */
-      public food.menu.v1.FoodMenu.MenuComponent.Builder addDataBuilder(
-          int index) {
-        return getDataFieldBuilder().addBuilder(
-            index, food.menu.v1.FoodMenu.MenuComponent.getDefaultInstance());
-      }
-      /**
-       * <code>repeated .food.menu.v1.MenuComponent data = 1;</code>
-       */
-      public java.util.List<food.menu.v1.FoodMenu.MenuComponent.Builder> 
-           getDataBuilderList() {
-        return getDataFieldBuilder().getBuilderList();
-      }
-      private com.google.protobuf.RepeatedFieldBuilderV3<
-          food.menu.v1.FoodMenu.MenuComponent, food.menu.v1.FoodMenu.MenuComponent.Builder, food.menu.v1.FoodMenu.MenuComponentOrBuilder> 
-          getDataFieldBuilder() {
-        if (dataBuilder_ == null) {
-          dataBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3<
-              food.menu.v1.FoodMenu.MenuComponent, food.menu.v1.FoodMenu.MenuComponent.Builder, food.menu.v1.FoodMenu.MenuComponentOrBuilder>(
-                  data_,
-                  ((bitField0_ & 0x00000001) != 0),
-                  getParentForChildren(),
-                  isClean());
-          data_ = null;
-        }
-        return dataBuilder_;
-      }
-      @java.lang.Override
-      public final Builder setUnknownFields(
-          final com.google.protobuf.UnknownFieldSet unknownFields) {
-        return super.setUnknownFields(unknownFields);
-      }
-
-      @java.lang.Override
-      public final Builder mergeUnknownFields(
-          final com.google.protobuf.UnknownFieldSet unknownFields) {
-        return super.mergeUnknownFields(unknownFields);
-      }
-
-
-      // @@protoc_insertion_point(builder_scope:food.menu.v1.FoodMenuFeed)
-    }
-
-    // @@protoc_insertion_point(class_scope:food.menu.v1.FoodMenuFeed)
-    private static final food.menu.v1.FoodMenu.FoodMenuFeed DEFAULT_INSTANCE;
-    static {
-      DEFAULT_INSTANCE = new food.menu.v1.FoodMenu.FoodMenuFeed();
-    }
-
-    public static food.menu.v1.FoodMenu.FoodMenuFeed getDefaultInstance() {
-      return DEFAULT_INSTANCE;
-    }
-
-    private static final com.google.protobuf.Parser<FoodMenuFeed>
-        PARSER = new com.google.protobuf.AbstractParser<FoodMenuFeed>() {
-      @java.lang.Override
-      public FoodMenuFeed parsePartialFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws com.google.protobuf.InvalidProtocolBufferException {
-        Builder builder = newBuilder();
-        try {
-          builder.mergeFrom(input, extensionRegistry);
-        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          throw e.setUnfinishedMessage(builder.buildPartial());
-        } catch (com.google.protobuf.UninitializedMessageException e) {
-          throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
-        } catch (java.io.IOException e) {
-          throw new com.google.protobuf.InvalidProtocolBufferException(e)
-              .setUnfinishedMessage(builder.buildPartial());
-        }
-        return builder.buildPartial();
-      }
-    };
-
-    public static com.google.protobuf.Parser<FoodMenuFeed> parser() {
-      return PARSER;
-    }
-
-    @java.lang.Override
-    public com.google.protobuf.Parser<FoodMenuFeed> getParserForType() {
-      return PARSER;
-    }
-
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.FoodMenuFeed getDefaultInstanceForType() {
-      return DEFAULT_INSTANCE;
-    }
-
-  }
-
-  public interface MenuComponentOrBuilder extends
-      // @@protoc_insertion_point(interface_extends:food.menu.v1.MenuComponent)
-      com.google.protobuf.MessageOrBuilder {
-
-    /**
-     * <code>.food.menu.v1.Menu menu = 1;</code>
-     * @return Whether the menu field is set.
-     */
-    boolean hasMenu();
-    /**
-     * <code>.food.menu.v1.Menu menu = 1;</code>
-     * @return The menu.
-     */
-    food.menu.v1.FoodMenu.Menu getMenu();
-    /**
-     * <code>.food.menu.v1.Menu menu = 1;</code>
-     */
-    food.menu.v1.FoodMenu.MenuOrBuilder getMenuOrBuilder();
-
-    /**
-     * <code>.food.menu.v1.MenuSection section = 2;</code>
-     * @return Whether the section field is set.
-     */
-    boolean hasSection();
-    /**
-     * <code>.food.menu.v1.MenuSection section = 2;</code>
-     * @return The section.
-     */
-    food.menu.v1.FoodMenu.MenuSection getSection();
-    /**
-     * <code>.food.menu.v1.MenuSection section = 2;</code>
-     */
-    food.menu.v1.FoodMenu.MenuSectionOrBuilder getSectionOrBuilder();
-
-    /**
-     * <code>.food.menu.v1.MenuItem item = 3;</code>
-     * @return Whether the item field is set.
-     */
-    boolean hasItem();
-    /**
-     * <code>.food.menu.v1.MenuItem item = 3;</code>
-     * @return The item.
-     */
-    food.menu.v1.FoodMenu.MenuItem getItem();
-    /**
-     * <code>.food.menu.v1.MenuItem item = 3;</code>
-     */
-    food.menu.v1.FoodMenu.MenuItemOrBuilder getItemOrBuilder();
-
-    /**
-     * <code>.food.menu.v1.MenuItemOption option = 4;</code>
-     * @return Whether the option field is set.
-     */
-    boolean hasOption();
-    /**
-     * <code>.food.menu.v1.MenuItemOption option = 4;</code>
-     * @return The option.
-     */
-    food.menu.v1.FoodMenu.MenuItemOption getOption();
-    /**
-     * <code>.food.menu.v1.MenuItemOption option = 4;</code>
-     */
-    food.menu.v1.FoodMenu.MenuItemOptionOrBuilder getOptionOrBuilder();
-
-    food.menu.v1.FoodMenu.MenuComponent.TypeCase getTypeCase();
-  }
-  /**
-   * Protobuf type {@code food.menu.v1.MenuComponent}
-   */
-  public static final class MenuComponent extends
-      com.google.protobuf.GeneratedMessageV3 implements
-      // @@protoc_insertion_point(message_implements:food.menu.v1.MenuComponent)
-      MenuComponentOrBuilder {
-  private static final long serialVersionUID = 0L;
-    // Use MenuComponent.newBuilder() to construct.
-    private MenuComponent(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
-      super(builder);
-    }
-    private MenuComponent() {
-    }
-
-    @java.lang.Override
-    @SuppressWarnings({"unused"})
-    protected java.lang.Object newInstance(
-        UnusedPrivateParameter unused) {
-      return new MenuComponent();
-    }
-
-    public static final com.google.protobuf.Descriptors.Descriptor
-        getDescriptor() {
-      return food.menu.v1.FoodMenu.internal_static_food_menu_v1_MenuComponent_descriptor;
-    }
-
-    @java.lang.Override
-    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-        internalGetFieldAccessorTable() {
-      return food.menu.v1.FoodMenu.internal_static_food_menu_v1_MenuComponent_fieldAccessorTable
-          .ensureFieldAccessorsInitialized(
-              food.menu.v1.FoodMenu.MenuComponent.class, food.menu.v1.FoodMenu.MenuComponent.Builder.class);
-    }
-
-    private int typeCase_ = 0;
-    @SuppressWarnings("serial")
-    private java.lang.Object type_;
-    public enum TypeCase
-        implements com.google.protobuf.Internal.EnumLite,
-            com.google.protobuf.AbstractMessage.InternalOneOfEnum {
-      MENU(1),
-      SECTION(2),
-      ITEM(3),
-      OPTION(4),
-      TYPE_NOT_SET(0);
-      private final int value;
-      private TypeCase(int value) {
-        this.value = value;
-      }
-      /**
-       * @param value The number of the enum to look for.
-       * @return The enum associated with the given number.
-       * @deprecated Use {@link #forNumber(int)} instead.
-       */
-      @java.lang.Deprecated
-      public static TypeCase valueOf(int value) {
-        return forNumber(value);
-      }
-
-      public static TypeCase forNumber(int value) {
-        switch (value) {
-          case 1: return MENU;
-          case 2: return SECTION;
-          case 3: return ITEM;
-          case 4: return OPTION;
-          case 0: return TYPE_NOT_SET;
-          default: return null;
-        }
-      }
-      public int getNumber() {
-        return this.value;
-      }
-    };
-
-    public TypeCase
-    getTypeCase() {
-      return TypeCase.forNumber(
-          typeCase_);
-    }
-
-    public static final int MENU_FIELD_NUMBER = 1;
-    /**
-     * <code>.food.menu.v1.Menu menu = 1;</code>
-     * @return Whether the menu field is set.
-     */
-    @java.lang.Override
-    public boolean hasMenu() {
-      return typeCase_ == 1;
-    }
-    /**
-     * <code>.food.menu.v1.Menu menu = 1;</code>
-     * @return The menu.
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.Menu getMenu() {
-      if (typeCase_ == 1) {
-         return (food.menu.v1.FoodMenu.Menu) type_;
-      }
-      return food.menu.v1.FoodMenu.Menu.getDefaultInstance();
-    }
-    /**
-     * <code>.food.menu.v1.Menu menu = 1;</code>
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.MenuOrBuilder getMenuOrBuilder() {
-      if (typeCase_ == 1) {
-         return (food.menu.v1.FoodMenu.Menu) type_;
-      }
-      return food.menu.v1.FoodMenu.Menu.getDefaultInstance();
-    }
-
-    public static final int SECTION_FIELD_NUMBER = 2;
-    /**
-     * <code>.food.menu.v1.MenuSection section = 2;</code>
-     * @return Whether the section field is set.
-     */
-    @java.lang.Override
-    public boolean hasSection() {
-      return typeCase_ == 2;
-    }
-    /**
-     * <code>.food.menu.v1.MenuSection section = 2;</code>
-     * @return The section.
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.MenuSection getSection() {
-      if (typeCase_ == 2) {
-         return (food.menu.v1.FoodMenu.MenuSection) type_;
-      }
-      return food.menu.v1.FoodMenu.MenuSection.getDefaultInstance();
-    }
-    /**
-     * <code>.food.menu.v1.MenuSection section = 2;</code>
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.MenuSectionOrBuilder getSectionOrBuilder() {
-      if (typeCase_ == 2) {
-         return (food.menu.v1.FoodMenu.MenuSection) type_;
-      }
-      return food.menu.v1.FoodMenu.MenuSection.getDefaultInstance();
-    }
-
-    public static final int ITEM_FIELD_NUMBER = 3;
-    /**
-     * <code>.food.menu.v1.MenuItem item = 3;</code>
-     * @return Whether the item field is set.
-     */
-    @java.lang.Override
-    public boolean hasItem() {
-      return typeCase_ == 3;
-    }
-    /**
-     * <code>.food.menu.v1.MenuItem item = 3;</code>
-     * @return The item.
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.MenuItem getItem() {
-      if (typeCase_ == 3) {
-         return (food.menu.v1.FoodMenu.MenuItem) type_;
-      }
-      return food.menu.v1.FoodMenu.MenuItem.getDefaultInstance();
-    }
-    /**
-     * <code>.food.menu.v1.MenuItem item = 3;</code>
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.MenuItemOrBuilder getItemOrBuilder() {
-      if (typeCase_ == 3) {
-         return (food.menu.v1.FoodMenu.MenuItem) type_;
-      }
-      return food.menu.v1.FoodMenu.MenuItem.getDefaultInstance();
-    }
-
-    public static final int OPTION_FIELD_NUMBER = 4;
-    /**
-     * <code>.food.menu.v1.MenuItemOption option = 4;</code>
-     * @return Whether the option field is set.
-     */
-    @java.lang.Override
-    public boolean hasOption() {
-      return typeCase_ == 4;
-    }
-    /**
-     * <code>.food.menu.v1.MenuItemOption option = 4;</code>
-     * @return The option.
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.MenuItemOption getOption() {
-      if (typeCase_ == 4) {
-         return (food.menu.v1.FoodMenu.MenuItemOption) type_;
-      }
-      return food.menu.v1.FoodMenu.MenuItemOption.getDefaultInstance();
-    }
-    /**
-     * <code>.food.menu.v1.MenuItemOption option = 4;</code>
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.MenuItemOptionOrBuilder getOptionOrBuilder() {
-      if (typeCase_ == 4) {
-         return (food.menu.v1.FoodMenu.MenuItemOption) type_;
-      }
-      return food.menu.v1.FoodMenu.MenuItemOption.getDefaultInstance();
-    }
-
-    private byte memoizedIsInitialized = -1;
-    @java.lang.Override
-    public final boolean isInitialized() {
-      byte isInitialized = memoizedIsInitialized;
-      if (isInitialized == 1) return true;
-      if (isInitialized == 0) return false;
-
-      memoizedIsInitialized = 1;
-      return true;
-    }
-
-    @java.lang.Override
-    public void writeTo(com.google.protobuf.CodedOutputStream output)
-                        throws java.io.IOException {
-      if (typeCase_ == 1) {
-        output.writeMessage(1, (food.menu.v1.FoodMenu.Menu) type_);
-      }
-      if (typeCase_ == 2) {
-        output.writeMessage(2, (food.menu.v1.FoodMenu.MenuSection) type_);
-      }
-      if (typeCase_ == 3) {
-        output.writeMessage(3, (food.menu.v1.FoodMenu.MenuItem) type_);
-      }
-      if (typeCase_ == 4) {
-        output.writeMessage(4, (food.menu.v1.FoodMenu.MenuItemOption) type_);
-      }
-      getUnknownFields().writeTo(output);
-    }
-
-    @java.lang.Override
-    public int getSerializedSize() {
-      int size = memoizedSize;
-      if (size != -1) return size;
-
-      size = 0;
-      if (typeCase_ == 1) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(1, (food.menu.v1.FoodMenu.Menu) type_);
-      }
-      if (typeCase_ == 2) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(2, (food.menu.v1.FoodMenu.MenuSection) type_);
-      }
-      if (typeCase_ == 3) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(3, (food.menu.v1.FoodMenu.MenuItem) type_);
-      }
-      if (typeCase_ == 4) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(4, (food.menu.v1.FoodMenu.MenuItemOption) type_);
-      }
-      size += getUnknownFields().getSerializedSize();
-      memoizedSize = size;
-      return size;
-    }
-
-    @java.lang.Override
-    public boolean equals(final java.lang.Object obj) {
-      if (obj == this) {
-       return true;
-      }
-      if (!(obj instanceof food.menu.v1.FoodMenu.MenuComponent)) {
-        return super.equals(obj);
-      }
-      food.menu.v1.FoodMenu.MenuComponent other = (food.menu.v1.FoodMenu.MenuComponent) obj;
-
-      if (!getTypeCase().equals(other.getTypeCase())) return false;
-      switch (typeCase_) {
-        case 1:
-          if (!getMenu()
-              .equals(other.getMenu())) return false;
-          break;
-        case 2:
-          if (!getSection()
-              .equals(other.getSection())) return false;
-          break;
-        case 3:
-          if (!getItem()
-              .equals(other.getItem())) return false;
-          break;
-        case 4:
-          if (!getOption()
-              .equals(other.getOption())) return false;
-          break;
-        case 0:
-        default:
-      }
-      if (!getUnknownFields().equals(other.getUnknownFields())) return false;
-      return true;
-    }
-
-    @java.lang.Override
-    public int hashCode() {
-      if (memoizedHashCode != 0) {
-        return memoizedHashCode;
-      }
-      int hash = 41;
-      hash = (19 * hash) + getDescriptor().hashCode();
-      switch (typeCase_) {
-        case 1:
-          hash = (37 * hash) + MENU_FIELD_NUMBER;
-          hash = (53 * hash) + getMenu().hashCode();
-          break;
-        case 2:
-          hash = (37 * hash) + SECTION_FIELD_NUMBER;
-          hash = (53 * hash) + getSection().hashCode();
-          break;
-        case 3:
-          hash = (37 * hash) + ITEM_FIELD_NUMBER;
-          hash = (53 * hash) + getItem().hashCode();
-          break;
-        case 4:
-          hash = (37 * hash) + OPTION_FIELD_NUMBER;
-          hash = (53 * hash) + getOption().hashCode();
-          break;
-        case 0:
-        default:
-      }
-      hash = (29 * hash) + getUnknownFields().hashCode();
-      memoizedHashCode = hash;
-      return hash;
-    }
-
-    public static food.menu.v1.FoodMenu.MenuComponent parseFrom(
-        java.nio.ByteBuffer data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.MenuComponent parseFrom(
-        java.nio.ByteBuffer data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.MenuComponent parseFrom(
-        com.google.protobuf.ByteString data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.MenuComponent parseFrom(
-        com.google.protobuf.ByteString data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.MenuComponent parseFrom(byte[] data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.MenuComponent parseFrom(
-        byte[] data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.MenuComponent parseFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.MenuComponent parseFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.MenuComponent parseDelimitedFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseDelimitedWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.MenuComponent parseDelimitedFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.MenuComponent parseFrom(
-        com.google.protobuf.CodedInputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.MenuComponent parseFrom(
-        com.google.protobuf.CodedInputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input, extensionRegistry);
-    }
-
-    @java.lang.Override
-    public Builder newBuilderForType() { return newBuilder(); }
-    public static Builder newBuilder() {
-      return DEFAULT_INSTANCE.toBuilder();
-    }
-    public static Builder newBuilder(food.menu.v1.FoodMenu.MenuComponent prototype) {
-      return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
-    }
-    @java.lang.Override
-    public Builder toBuilder() {
-      return this == DEFAULT_INSTANCE
-          ? new Builder() : new Builder().mergeFrom(this);
-    }
-
-    @java.lang.Override
-    protected Builder newBuilderForType(
-        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-      Builder builder = new Builder(parent);
-      return builder;
-    }
-    /**
-     * Protobuf type {@code food.menu.v1.MenuComponent}
-     */
-    public static final class Builder extends
-        com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
-        // @@protoc_insertion_point(builder_implements:food.menu.v1.MenuComponent)
-        food.menu.v1.FoodMenu.MenuComponentOrBuilder {
-      public static final com.google.protobuf.Descriptors.Descriptor
-          getDescriptor() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_MenuComponent_descriptor;
-      }
-
-      @java.lang.Override
-      protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-          internalGetFieldAccessorTable() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_MenuComponent_fieldAccessorTable
-            .ensureFieldAccessorsInitialized(
-                food.menu.v1.FoodMenu.MenuComponent.class, food.menu.v1.FoodMenu.MenuComponent.Builder.class);
-      }
-
-      // Construct using food.menu.v1.FoodMenu.MenuComponent.newBuilder()
-      private Builder() {
-
-      }
-
-      private Builder(
-          com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-        super(parent);
-
-      }
-      @java.lang.Override
-      public Builder clear() {
-        super.clear();
-        bitField0_ = 0;
-        if (menuBuilder_ != null) {
-          menuBuilder_.clear();
-        }
-        if (sectionBuilder_ != null) {
-          sectionBuilder_.clear();
-        }
-        if (itemBuilder_ != null) {
-          itemBuilder_.clear();
-        }
-        if (optionBuilder_ != null) {
-          optionBuilder_.clear();
-        }
-        typeCase_ = 0;
-        type_ = null;
-        return this;
-      }
-
-      @java.lang.Override
-      public com.google.protobuf.Descriptors.Descriptor
-          getDescriptorForType() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_MenuComponent_descriptor;
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.MenuComponent getDefaultInstanceForType() {
-        return food.menu.v1.FoodMenu.MenuComponent.getDefaultInstance();
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.MenuComponent build() {
-        food.menu.v1.FoodMenu.MenuComponent result = buildPartial();
-        if (!result.isInitialized()) {
-          throw newUninitializedMessageException(result);
-        }
-        return result;
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.MenuComponent buildPartial() {
-        food.menu.v1.FoodMenu.MenuComponent result = new food.menu.v1.FoodMenu.MenuComponent(this);
-        if (bitField0_ != 0) { buildPartial0(result); }
-        buildPartialOneofs(result);
-        onBuilt();
-        return result;
-      }
-
-      private void buildPartial0(food.menu.v1.FoodMenu.MenuComponent result) {
-        int from_bitField0_ = bitField0_;
-      }
-
-      private void buildPartialOneofs(food.menu.v1.FoodMenu.MenuComponent result) {
-        result.typeCase_ = typeCase_;
-        result.type_ = this.type_;
-        if (typeCase_ == 1 &&
-            menuBuilder_ != null) {
-          result.type_ = menuBuilder_.build();
-        }
-        if (typeCase_ == 2 &&
-            sectionBuilder_ != null) {
-          result.type_ = sectionBuilder_.build();
-        }
-        if (typeCase_ == 3 &&
-            itemBuilder_ != null) {
-          result.type_ = itemBuilder_.build();
-        }
-        if (typeCase_ == 4 &&
-            optionBuilder_ != null) {
-          result.type_ = optionBuilder_.build();
-        }
-      }
-
-      @java.lang.Override
-      public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof food.menu.v1.FoodMenu.MenuComponent) {
-          return mergeFrom((food.menu.v1.FoodMenu.MenuComponent)other);
-        } else {
-          super.mergeFrom(other);
-          return this;
-        }
-      }
-
-      public Builder mergeFrom(food.menu.v1.FoodMenu.MenuComponent other) {
-        if (other == food.menu.v1.FoodMenu.MenuComponent.getDefaultInstance()) return this;
-        switch (other.getTypeCase()) {
-          case MENU: {
-            mergeMenu(other.getMenu());
-            break;
-          }
-          case SECTION: {
-            mergeSection(other.getSection());
-            break;
-          }
-          case ITEM: {
-            mergeItem(other.getItem());
-            break;
-          }
-          case OPTION: {
-            mergeOption(other.getOption());
-            break;
-          }
-          case TYPE_NOT_SET: {
-            break;
-          }
-        }
-        this.mergeUnknownFields(other.getUnknownFields());
-        onChanged();
-        return this;
-      }
-
-      @java.lang.Override
-      public final boolean isInitialized() {
-        return true;
-      }
-
-      @java.lang.Override
-      public Builder mergeFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws java.io.IOException {
-        if (extensionRegistry == null) {
-          throw new java.lang.NullPointerException();
-        }
-        try {
-          boolean done = false;
-          while (!done) {
-            int tag = input.readTag();
-            switch (tag) {
-              case 0:
-                done = true;
-                break;
-              case 10: {
-                input.readMessage(
-                    getMenuFieldBuilder().getBuilder(),
-                    extensionRegistry);
-                typeCase_ = 1;
-                break;
-              } // case 10
-              case 18: {
-                input.readMessage(
-                    getSectionFieldBuilder().getBuilder(),
-                    extensionRegistry);
-                typeCase_ = 2;
-                break;
-              } // case 18
-              case 26: {
-                input.readMessage(
-                    getItemFieldBuilder().getBuilder(),
-                    extensionRegistry);
-                typeCase_ = 3;
-                break;
-              } // case 26
-              case 34: {
-                input.readMessage(
-                    getOptionFieldBuilder().getBuilder(),
-                    extensionRegistry);
-                typeCase_ = 4;
-                break;
-              } // case 34
-              default: {
-                if (!super.parseUnknownField(input, extensionRegistry, tag)) {
-                  done = true; // was an endgroup tag
-                }
-                break;
-              } // default:
-            } // switch (tag)
-          } // while (!done)
-        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          throw e.unwrapIOException();
-        } finally {
-          onChanged();
-        } // finally
-        return this;
-      }
-      private int typeCase_ = 0;
-      private java.lang.Object type_;
-      public TypeCase
-          getTypeCase() {
-        return TypeCase.forNumber(
-            typeCase_);
-      }
-
-      public Builder clearType() {
-        typeCase_ = 0;
-        type_ = null;
-        onChanged();
-        return this;
-      }
-
-      private int bitField0_;
-
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.Menu, food.menu.v1.FoodMenu.Menu.Builder, food.menu.v1.FoodMenu.MenuOrBuilder> menuBuilder_;
-      /**
-       * <code>.food.menu.v1.Menu menu = 1;</code>
-       * @return Whether the menu field is set.
-       */
-      @java.lang.Override
-      public boolean hasMenu() {
-        return typeCase_ == 1;
-      }
-      /**
-       * <code>.food.menu.v1.Menu menu = 1;</code>
-       * @return The menu.
-       */
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.Menu getMenu() {
-        if (menuBuilder_ == null) {
-          if (typeCase_ == 1) {
-            return (food.menu.v1.FoodMenu.Menu) type_;
-          }
-          return food.menu.v1.FoodMenu.Menu.getDefaultInstance();
-        } else {
-          if (typeCase_ == 1) {
-            return menuBuilder_.getMessage();
-          }
-          return food.menu.v1.FoodMenu.Menu.getDefaultInstance();
-        }
-      }
-      /**
-       * <code>.food.menu.v1.Menu menu = 1;</code>
-       */
-      public Builder setMenu(food.menu.v1.FoodMenu.Menu value) {
-        if (menuBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          type_ = value;
-          onChanged();
-        } else {
-          menuBuilder_.setMessage(value);
-        }
-        typeCase_ = 1;
-        return this;
-      }
-      /**
-       * <code>.food.menu.v1.Menu menu = 1;</code>
-       */
-      public Builder setMenu(
-          food.menu.v1.FoodMenu.Menu.Builder builderForValue) {
-        if (menuBuilder_ == null) {
-          type_ = builderForValue.build();
-          onChanged();
-        } else {
-          menuBuilder_.setMessage(builderForValue.build());
-        }
-        typeCase_ = 1;
-        return this;
-      }
-      /**
-       * <code>.food.menu.v1.Menu menu = 1;</code>
-       */
-      public Builder mergeMenu(food.menu.v1.FoodMenu.Menu value) {
-        if (menuBuilder_ == null) {
-          if (typeCase_ == 1 &&
-              type_ != food.menu.v1.FoodMenu.Menu.getDefaultInstance()) {
-            type_ = food.menu.v1.FoodMenu.Menu.newBuilder((food.menu.v1.FoodMenu.Menu) type_)
-                .mergeFrom(value).buildPartial();
-          } else {
-            type_ = value;
-          }
-          onChanged();
-        } else {
-          if (typeCase_ == 1) {
-            menuBuilder_.mergeFrom(value);
-          } else {
-            menuBuilder_.setMessage(value);
-          }
-        }
-        typeCase_ = 1;
-        return this;
-      }
-      /**
-       * <code>.food.menu.v1.Menu menu = 1;</code>
-       */
-      public Builder clearMenu() {
-        if (menuBuilder_ == null) {
-          if (typeCase_ == 1) {
-            typeCase_ = 0;
-            type_ = null;
-            onChanged();
-          }
-        } else {
-          if (typeCase_ == 1) {
-            typeCase_ = 0;
-            type_ = null;
-          }
-          menuBuilder_.clear();
-        }
-        return this;
-      }
-      /**
-       * <code>.food.menu.v1.Menu menu = 1;</code>
-       */
-      public food.menu.v1.FoodMenu.Menu.Builder getMenuBuilder() {
-        return getMenuFieldBuilder().getBuilder();
-      }
-      /**
-       * <code>.food.menu.v1.Menu menu = 1;</code>
-       */
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.MenuOrBuilder getMenuOrBuilder() {
-        if ((typeCase_ == 1) && (menuBuilder_ != null)) {
-          return menuBuilder_.getMessageOrBuilder();
-        } else {
-          if (typeCase_ == 1) {
-            return (food.menu.v1.FoodMenu.Menu) type_;
-          }
-          return food.menu.v1.FoodMenu.Menu.getDefaultInstance();
-        }
-      }
-      /**
-       * <code>.food.menu.v1.Menu menu = 1;</code>
-       */
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.Menu, food.menu.v1.FoodMenu.Menu.Builder, food.menu.v1.FoodMenu.MenuOrBuilder> 
-          getMenuFieldBuilder() {
-        if (menuBuilder_ == null) {
-          if (!(typeCase_ == 1)) {
-            type_ = food.menu.v1.FoodMenu.Menu.getDefaultInstance();
-          }
-          menuBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
-              food.menu.v1.FoodMenu.Menu, food.menu.v1.FoodMenu.Menu.Builder, food.menu.v1.FoodMenu.MenuOrBuilder>(
-                  (food.menu.v1.FoodMenu.Menu) type_,
-                  getParentForChildren(),
-                  isClean());
-          type_ = null;
-        }
-        typeCase_ = 1;
-        onChanged();
-        return menuBuilder_;
-      }
-
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.MenuSection, food.menu.v1.FoodMenu.MenuSection.Builder, food.menu.v1.FoodMenu.MenuSectionOrBuilder> sectionBuilder_;
-      /**
-       * <code>.food.menu.v1.MenuSection section = 2;</code>
-       * @return Whether the section field is set.
-       */
-      @java.lang.Override
-      public boolean hasSection() {
-        return typeCase_ == 2;
-      }
-      /**
-       * <code>.food.menu.v1.MenuSection section = 2;</code>
-       * @return The section.
-       */
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.MenuSection getSection() {
-        if (sectionBuilder_ == null) {
-          if (typeCase_ == 2) {
-            return (food.menu.v1.FoodMenu.MenuSection) type_;
-          }
-          return food.menu.v1.FoodMenu.MenuSection.getDefaultInstance();
-        } else {
-          if (typeCase_ == 2) {
-            return sectionBuilder_.getMessage();
-          }
-          return food.menu.v1.FoodMenu.MenuSection.getDefaultInstance();
-        }
-      }
-      /**
-       * <code>.food.menu.v1.MenuSection section = 2;</code>
-       */
-      public Builder setSection(food.menu.v1.FoodMenu.MenuSection value) {
-        if (sectionBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          type_ = value;
-          onChanged();
-        } else {
-          sectionBuilder_.setMessage(value);
-        }
-        typeCase_ = 2;
-        return this;
-      }
-      /**
-       * <code>.food.menu.v1.MenuSection section = 2;</code>
-       */
-      public Builder setSection(
-          food.menu.v1.FoodMenu.MenuSection.Builder builderForValue) {
-        if (sectionBuilder_ == null) {
-          type_ = builderForValue.build();
-          onChanged();
-        } else {
-          sectionBuilder_.setMessage(builderForValue.build());
-        }
-        typeCase_ = 2;
-        return this;
-      }
-      /**
-       * <code>.food.menu.v1.MenuSection section = 2;</code>
-       */
-      public Builder mergeSection(food.menu.v1.FoodMenu.MenuSection value) {
-        if (sectionBuilder_ == null) {
-          if (typeCase_ == 2 &&
-              type_ != food.menu.v1.FoodMenu.MenuSection.getDefaultInstance()) {
-            type_ = food.menu.v1.FoodMenu.MenuSection.newBuilder((food.menu.v1.FoodMenu.MenuSection) type_)
-                .mergeFrom(value).buildPartial();
-          } else {
-            type_ = value;
-          }
-          onChanged();
-        } else {
-          if (typeCase_ == 2) {
-            sectionBuilder_.mergeFrom(value);
-          } else {
-            sectionBuilder_.setMessage(value);
-          }
-        }
-        typeCase_ = 2;
-        return this;
-      }
-      /**
-       * <code>.food.menu.v1.MenuSection section = 2;</code>
-       */
-      public Builder clearSection() {
-        if (sectionBuilder_ == null) {
-          if (typeCase_ == 2) {
-            typeCase_ = 0;
-            type_ = null;
-            onChanged();
-          }
-        } else {
-          if (typeCase_ == 2) {
-            typeCase_ = 0;
-            type_ = null;
-          }
-          sectionBuilder_.clear();
-        }
-        return this;
-      }
-      /**
-       * <code>.food.menu.v1.MenuSection section = 2;</code>
-       */
-      public food.menu.v1.FoodMenu.MenuSection.Builder getSectionBuilder() {
-        return getSectionFieldBuilder().getBuilder();
-      }
-      /**
-       * <code>.food.menu.v1.MenuSection section = 2;</code>
-       */
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.MenuSectionOrBuilder getSectionOrBuilder() {
-        if ((typeCase_ == 2) && (sectionBuilder_ != null)) {
-          return sectionBuilder_.getMessageOrBuilder();
-        } else {
-          if (typeCase_ == 2) {
-            return (food.menu.v1.FoodMenu.MenuSection) type_;
-          }
-          return food.menu.v1.FoodMenu.MenuSection.getDefaultInstance();
-        }
-      }
-      /**
-       * <code>.food.menu.v1.MenuSection section = 2;</code>
-       */
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.MenuSection, food.menu.v1.FoodMenu.MenuSection.Builder, food.menu.v1.FoodMenu.MenuSectionOrBuilder> 
-          getSectionFieldBuilder() {
-        if (sectionBuilder_ == null) {
-          if (!(typeCase_ == 2)) {
-            type_ = food.menu.v1.FoodMenu.MenuSection.getDefaultInstance();
-          }
-          sectionBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
-              food.menu.v1.FoodMenu.MenuSection, food.menu.v1.FoodMenu.MenuSection.Builder, food.menu.v1.FoodMenu.MenuSectionOrBuilder>(
-                  (food.menu.v1.FoodMenu.MenuSection) type_,
-                  getParentForChildren(),
-                  isClean());
-          type_ = null;
-        }
-        typeCase_ = 2;
-        onChanged();
-        return sectionBuilder_;
-      }
-
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.MenuItem, food.menu.v1.FoodMenu.MenuItem.Builder, food.menu.v1.FoodMenu.MenuItemOrBuilder> itemBuilder_;
-      /**
-       * <code>.food.menu.v1.MenuItem item = 3;</code>
-       * @return Whether the item field is set.
-       */
-      @java.lang.Override
-      public boolean hasItem() {
-        return typeCase_ == 3;
-      }
-      /**
-       * <code>.food.menu.v1.MenuItem item = 3;</code>
-       * @return The item.
-       */
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.MenuItem getItem() {
-        if (itemBuilder_ == null) {
-          if (typeCase_ == 3) {
-            return (food.menu.v1.FoodMenu.MenuItem) type_;
-          }
-          return food.menu.v1.FoodMenu.MenuItem.getDefaultInstance();
-        } else {
-          if (typeCase_ == 3) {
-            return itemBuilder_.getMessage();
-          }
-          return food.menu.v1.FoodMenu.MenuItem.getDefaultInstance();
-        }
-      }
-      /**
-       * <code>.food.menu.v1.MenuItem item = 3;</code>
-       */
-      public Builder setItem(food.menu.v1.FoodMenu.MenuItem value) {
-        if (itemBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          type_ = value;
-          onChanged();
-        } else {
-          itemBuilder_.setMessage(value);
-        }
-        typeCase_ = 3;
-        return this;
-      }
-      /**
-       * <code>.food.menu.v1.MenuItem item = 3;</code>
-       */
-      public Builder setItem(
-          food.menu.v1.FoodMenu.MenuItem.Builder builderForValue) {
-        if (itemBuilder_ == null) {
-          type_ = builderForValue.build();
-          onChanged();
-        } else {
-          itemBuilder_.setMessage(builderForValue.build());
-        }
-        typeCase_ = 3;
-        return this;
-      }
-      /**
-       * <code>.food.menu.v1.MenuItem item = 3;</code>
-       */
-      public Builder mergeItem(food.menu.v1.FoodMenu.MenuItem value) {
-        if (itemBuilder_ == null) {
-          if (typeCase_ == 3 &&
-              type_ != food.menu.v1.FoodMenu.MenuItem.getDefaultInstance()) {
-            type_ = food.menu.v1.FoodMenu.MenuItem.newBuilder((food.menu.v1.FoodMenu.MenuItem) type_)
-                .mergeFrom(value).buildPartial();
-          } else {
-            type_ = value;
-          }
-          onChanged();
-        } else {
-          if (typeCase_ == 3) {
-            itemBuilder_.mergeFrom(value);
-          } else {
-            itemBuilder_.setMessage(value);
-          }
-        }
-        typeCase_ = 3;
-        return this;
-      }
-      /**
-       * <code>.food.menu.v1.MenuItem item = 3;</code>
-       */
-      public Builder clearItem() {
-        if (itemBuilder_ == null) {
-          if (typeCase_ == 3) {
-            typeCase_ = 0;
-            type_ = null;
-            onChanged();
-          }
-        } else {
-          if (typeCase_ == 3) {
-            typeCase_ = 0;
-            type_ = null;
-          }
-          itemBuilder_.clear();
-        }
-        return this;
-      }
-      /**
-       * <code>.food.menu.v1.MenuItem item = 3;</code>
-       */
-      public food.menu.v1.FoodMenu.MenuItem.Builder getItemBuilder() {
-        return getItemFieldBuilder().getBuilder();
-      }
-      /**
-       * <code>.food.menu.v1.MenuItem item = 3;</code>
-       */
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.MenuItemOrBuilder getItemOrBuilder() {
-        if ((typeCase_ == 3) && (itemBuilder_ != null)) {
-          return itemBuilder_.getMessageOrBuilder();
-        } else {
-          if (typeCase_ == 3) {
-            return (food.menu.v1.FoodMenu.MenuItem) type_;
-          }
-          return food.menu.v1.FoodMenu.MenuItem.getDefaultInstance();
-        }
-      }
-      /**
-       * <code>.food.menu.v1.MenuItem item = 3;</code>
-       */
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.MenuItem, food.menu.v1.FoodMenu.MenuItem.Builder, food.menu.v1.FoodMenu.MenuItemOrBuilder> 
-          getItemFieldBuilder() {
-        if (itemBuilder_ == null) {
-          if (!(typeCase_ == 3)) {
-            type_ = food.menu.v1.FoodMenu.MenuItem.getDefaultInstance();
-          }
-          itemBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
-              food.menu.v1.FoodMenu.MenuItem, food.menu.v1.FoodMenu.MenuItem.Builder, food.menu.v1.FoodMenu.MenuItemOrBuilder>(
-                  (food.menu.v1.FoodMenu.MenuItem) type_,
-                  getParentForChildren(),
-                  isClean());
-          type_ = null;
-        }
-        typeCase_ = 3;
-        onChanged();
-        return itemBuilder_;
-      }
-
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.MenuItemOption, food.menu.v1.FoodMenu.MenuItemOption.Builder, food.menu.v1.FoodMenu.MenuItemOptionOrBuilder> optionBuilder_;
-      /**
-       * <code>.food.menu.v1.MenuItemOption option = 4;</code>
-       * @return Whether the option field is set.
-       */
-      @java.lang.Override
-      public boolean hasOption() {
-        return typeCase_ == 4;
-      }
-      /**
-       * <code>.food.menu.v1.MenuItemOption option = 4;</code>
-       * @return The option.
-       */
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.MenuItemOption getOption() {
-        if (optionBuilder_ == null) {
-          if (typeCase_ == 4) {
-            return (food.menu.v1.FoodMenu.MenuItemOption) type_;
-          }
-          return food.menu.v1.FoodMenu.MenuItemOption.getDefaultInstance();
-        } else {
-          if (typeCase_ == 4) {
-            return optionBuilder_.getMessage();
-          }
-          return food.menu.v1.FoodMenu.MenuItemOption.getDefaultInstance();
-        }
-      }
-      /**
-       * <code>.food.menu.v1.MenuItemOption option = 4;</code>
-       */
-      public Builder setOption(food.menu.v1.FoodMenu.MenuItemOption value) {
-        if (optionBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          type_ = value;
-          onChanged();
-        } else {
-          optionBuilder_.setMessage(value);
-        }
-        typeCase_ = 4;
-        return this;
-      }
-      /**
-       * <code>.food.menu.v1.MenuItemOption option = 4;</code>
-       */
-      public Builder setOption(
-          food.menu.v1.FoodMenu.MenuItemOption.Builder builderForValue) {
-        if (optionBuilder_ == null) {
-          type_ = builderForValue.build();
-          onChanged();
-        } else {
-          optionBuilder_.setMessage(builderForValue.build());
-        }
-        typeCase_ = 4;
-        return this;
-      }
-      /**
-       * <code>.food.menu.v1.MenuItemOption option = 4;</code>
-       */
-      public Builder mergeOption(food.menu.v1.FoodMenu.MenuItemOption value) {
-        if (optionBuilder_ == null) {
-          if (typeCase_ == 4 &&
-              type_ != food.menu.v1.FoodMenu.MenuItemOption.getDefaultInstance()) {
-            type_ = food.menu.v1.FoodMenu.MenuItemOption.newBuilder((food.menu.v1.FoodMenu.MenuItemOption) type_)
-                .mergeFrom(value).buildPartial();
-          } else {
-            type_ = value;
-          }
-          onChanged();
-        } else {
-          if (typeCase_ == 4) {
-            optionBuilder_.mergeFrom(value);
-          } else {
-            optionBuilder_.setMessage(value);
-          }
-        }
-        typeCase_ = 4;
-        return this;
-      }
-      /**
-       * <code>.food.menu.v1.MenuItemOption option = 4;</code>
-       */
-      public Builder clearOption() {
-        if (optionBuilder_ == null) {
-          if (typeCase_ == 4) {
-            typeCase_ = 0;
-            type_ = null;
-            onChanged();
-          }
-        } else {
-          if (typeCase_ == 4) {
-            typeCase_ = 0;
-            type_ = null;
-          }
-          optionBuilder_.clear();
-        }
-        return this;
-      }
-      /**
-       * <code>.food.menu.v1.MenuItemOption option = 4;</code>
-       */
-      public food.menu.v1.FoodMenu.MenuItemOption.Builder getOptionBuilder() {
-        return getOptionFieldBuilder().getBuilder();
-      }
-      /**
-       * <code>.food.menu.v1.MenuItemOption option = 4;</code>
-       */
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.MenuItemOptionOrBuilder getOptionOrBuilder() {
-        if ((typeCase_ == 4) && (optionBuilder_ != null)) {
-          return optionBuilder_.getMessageOrBuilder();
-        } else {
-          if (typeCase_ == 4) {
-            return (food.menu.v1.FoodMenu.MenuItemOption) type_;
-          }
-          return food.menu.v1.FoodMenu.MenuItemOption.getDefaultInstance();
-        }
-      }
-      /**
-       * <code>.food.menu.v1.MenuItemOption option = 4;</code>
-       */
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.MenuItemOption, food.menu.v1.FoodMenu.MenuItemOption.Builder, food.menu.v1.FoodMenu.MenuItemOptionOrBuilder> 
-          getOptionFieldBuilder() {
-        if (optionBuilder_ == null) {
-          if (!(typeCase_ == 4)) {
-            type_ = food.menu.v1.FoodMenu.MenuItemOption.getDefaultInstance();
-          }
-          optionBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
-              food.menu.v1.FoodMenu.MenuItemOption, food.menu.v1.FoodMenu.MenuItemOption.Builder, food.menu.v1.FoodMenu.MenuItemOptionOrBuilder>(
-                  (food.menu.v1.FoodMenu.MenuItemOption) type_,
-                  getParentForChildren(),
-                  isClean());
-          type_ = null;
-        }
-        typeCase_ = 4;
-        onChanged();
-        return optionBuilder_;
-      }
-      @java.lang.Override
-      public final Builder setUnknownFields(
-          final com.google.protobuf.UnknownFieldSet unknownFields) {
-        return super.setUnknownFields(unknownFields);
-      }
-
-      @java.lang.Override
-      public final Builder mergeUnknownFields(
-          final com.google.protobuf.UnknownFieldSet unknownFields) {
-        return super.mergeUnknownFields(unknownFields);
-      }
-
-
-      // @@protoc_insertion_point(builder_scope:food.menu.v1.MenuComponent)
-    }
-
-    // @@protoc_insertion_point(class_scope:food.menu.v1.MenuComponent)
-    private static final food.menu.v1.FoodMenu.MenuComponent DEFAULT_INSTANCE;
-    static {
-      DEFAULT_INSTANCE = new food.menu.v1.FoodMenu.MenuComponent();
-    }
-
-    public static food.menu.v1.FoodMenu.MenuComponent getDefaultInstance() {
-      return DEFAULT_INSTANCE;
-    }
-
-    private static final com.google.protobuf.Parser<MenuComponent>
-        PARSER = new com.google.protobuf.AbstractParser<MenuComponent>() {
-      @java.lang.Override
-      public MenuComponent parsePartialFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws com.google.protobuf.InvalidProtocolBufferException {
-        Builder builder = newBuilder();
-        try {
-          builder.mergeFrom(input, extensionRegistry);
-        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          throw e.setUnfinishedMessage(builder.buildPartial());
-        } catch (com.google.protobuf.UninitializedMessageException e) {
-          throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
-        } catch (java.io.IOException e) {
-          throw new com.google.protobuf.InvalidProtocolBufferException(e)
-              .setUnfinishedMessage(builder.buildPartial());
-        }
-        return builder.buildPartial();
-      }
-    };
-
-    public static com.google.protobuf.Parser<MenuComponent> parser() {
-      return PARSER;
-    }
-
-    @java.lang.Override
-    public com.google.protobuf.Parser<MenuComponent> getParserForType() {
-      return PARSER;
-    }
-
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.MenuComponent getDefaultInstanceForType() {
-      return DEFAULT_INSTANCE;
-    }
-
-  }
-
-  public interface MenuOrBuilder extends
-      // @@protoc_insertion_point(interface_extends:food.menu.v1.Menu)
-      com.google.protobuf.MessageOrBuilder {
-
-    /**
-     * <pre>
-     * An opaque string from a partner which uniquely identifies the Menu within
-     * the partner feed.
-     * Required.
-     * </pre>
-     *
-     * <code>string menu_id = 1;</code>
-     * @return The menuId.
-     */
-    java.lang.String getMenuId();
-    /**
-     * <pre>
-     * An opaque string from a partner which uniquely identifies the Menu within
-     * the partner feed.
-     * Required.
-     * </pre>
-     *
-     * <code>string menu_id = 1;</code>
-     * @return The bytes for menuId.
-     */
-    com.google.protobuf.ByteString
-        getMenuIdBytes();
-
-    /**
-     * <pre>
-     * The merchants to whom the menu apply.
-     * Note: This field is repeated so chain restaurants can share the same menu
-     * across multiple locations, each of which is a separate merchant.
-     * Required.
-     * </pre>
-     *
-     * <code>repeated string merchant_ids = 2;</code>
-     * @return A list containing the merchantIds.
-     */
-    java.util.List<java.lang.String>
-        getMerchantIdsList();
-    /**
-     * <pre>
-     * The merchants to whom the menu apply.
-     * Note: This field is repeated so chain restaurants can share the same menu
-     * across multiple locations, each of which is a separate merchant.
-     * Required.
-     * </pre>
-     *
-     * <code>repeated string merchant_ids = 2;</code>
-     * @return The count of merchantIds.
-     */
-    int getMerchantIdsCount();
-    /**
-     * <pre>
-     * The merchants to whom the menu apply.
-     * Note: This field is repeated so chain restaurants can share the same menu
-     * across multiple locations, each of which is a separate merchant.
-     * Required.
-     * </pre>
-     *
-     * <code>repeated string merchant_ids = 2;</code>
-     * @param index The index of the element to return.
-     * @return The merchantIds at the given index.
-     */
-    java.lang.String getMerchantIds(int index);
-    /**
-     * <pre>
-     * The merchants to whom the menu apply.
-     * Note: This field is repeated so chain restaurants can share the same menu
-     * across multiple locations, each of which is a separate merchant.
-     * Required.
-     * </pre>
-     *
-     * <code>repeated string merchant_ids = 2;</code>
-     * @param index The index of the value to return.
-     * @return The bytes of the merchantIds at the given index.
-     */
-    com.google.protobuf.ByteString
-        getMerchantIdsBytes(int index);
-
-    /**
-     * <pre>
-     * The name that can identify the Menu when a user is browsing the menu.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField display_name = 3;</code>
-     * @return Whether the displayName field is set.
-     */
-    boolean hasDisplayName();
-    /**
-     * <pre>
-     * The name that can identify the Menu when a user is browsing the menu.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField display_name = 3;</code>
-     * @return The displayName.
-     */
-    food.menu.v1.FoodMenu.TextField getDisplayName();
-    /**
-     * <pre>
-     * The name that can identify the Menu when a user is browsing the menu.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField display_name = 3;</code>
-     */
-    food.menu.v1.FoodMenu.TextFieldOrBuilder getDisplayNameOrBuilder();
-
-    /**
-     * <pre>
-     * The default language code associated with the text labels contained in the
-     * menu. Expects BCP-47 language code, such as "en-US" or "sr-Latn".
-     *
-     * For more information, see
-     * http://www.unicode.org/reports/tr35/#Unicode_locale_identifier.
-     * Optional.
-     * </pre>
-     *
-     * <code>string language = 4;</code>
-     * @return The language.
-     */
-    java.lang.String getLanguage();
-    /**
-     * <pre>
-     * The default language code associated with the text labels contained in the
-     * menu. Expects BCP-47 language code, such as "en-US" or "sr-Latn".
-     *
-     * For more information, see
-     * http://www.unicode.org/reports/tr35/#Unicode_locale_identifier.
-     * Optional.
-     * </pre>
-     *
-     * <code>string language = 4;</code>
-     * @return The bytes for language.
-     */
-    com.google.protobuf.ByteString
-        getLanguageBytes();
-
-    /**
-     * <pre>
-     * Disclaimer to be shown to the user for the menu. For example, nutritional
-     * information disclosure and allergen disclosure.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.Disclaimer disclaimer = 5;</code>
-     * @return Whether the disclaimer field is set.
-     */
-    boolean hasDisclaimer();
-    /**
-     * <pre>
-     * Disclaimer to be shown to the user for the menu. For example, nutritional
-     * information disclosure and allergen disclosure.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.Disclaimer disclaimer = 5;</code>
-     * @return The disclaimer.
-     */
-    food.menu.v1.FoodMenu.Disclaimer getDisclaimer();
-    /**
-     * <pre>
-     * Disclaimer to be shown to the user for the menu. For example, nutritional
-     * information disclosure and allergen disclosure.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.Disclaimer disclaimer = 5;</code>
-     */
-    food.menu.v1.FoodMenu.DisclaimerOrBuilder getDisclaimerOrBuilder();
-
-    /**
-     * <pre>
-     * IDs of items contained within this menu. Expects first-level menu items
-     * only.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated string menu_item_ids = 6;</code>
-     * @return A list containing the menuItemIds.
-     */
-    java.util.List<java.lang.String>
-        getMenuItemIdsList();
-    /**
-     * <pre>
-     * IDs of items contained within this menu. Expects first-level menu items
-     * only.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated string menu_item_ids = 6;</code>
-     * @return The count of menuItemIds.
-     */
-    int getMenuItemIdsCount();
-    /**
-     * <pre>
-     * IDs of items contained within this menu. Expects first-level menu items
-     * only.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated string menu_item_ids = 6;</code>
-     * @param index The index of the element to return.
-     * @return The menuItemIds at the given index.
-     */
-    java.lang.String getMenuItemIds(int index);
-    /**
-     * <pre>
-     * IDs of items contained within this menu. Expects first-level menu items
-     * only.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated string menu_item_ids = 6;</code>
-     * @param index The index of the value to return.
-     * @return The bytes of the menuItemIds at the given index.
-     */
-    com.google.protobuf.ByteString
-        getMenuItemIdsBytes(int index);
-
-    /**
-     * <pre>
-     * IDs of sections contained within this menu. Expects first-level menu
-     * sections only.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated string menu_section_ids = 7;</code>
-     * @return A list containing the menuSectionIds.
-     */
-    java.util.List<java.lang.String>
-        getMenuSectionIdsList();
-    /**
-     * <pre>
-     * IDs of sections contained within this menu. Expects first-level menu
-     * sections only.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated string menu_section_ids = 7;</code>
-     * @return The count of menuSectionIds.
-     */
-    int getMenuSectionIdsCount();
-    /**
-     * <pre>
-     * IDs of sections contained within this menu. Expects first-level menu
-     * sections only.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated string menu_section_ids = 7;</code>
-     * @param index The index of the element to return.
-     * @return The menuSectionIds at the given index.
-     */
-    java.lang.String getMenuSectionIds(int index);
-    /**
-     * <pre>
-     * IDs of sections contained within this menu. Expects first-level menu
-     * sections only.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated string menu_section_ids = 7;</code>
-     * @param index The index of the value to return.
-     * @return The bytes of the menuSectionIds at the given index.
-     */
-    com.google.protobuf.ByteString
-        getMenuSectionIdsBytes(int index);
-
-    /**
-     * <pre>
-     * Timestamp when this Menu or any of its contents was last updated by the
-     * restaurant; i.e. a date to be associated with the phrase “accurate as of
-     * date”.
-     * Optional.
-     * </pre>
-     *
-     * <code>.google.protobuf.Timestamp last_merchant_update_time = 8;</code>
-     * @return Whether the lastMerchantUpdateTime field is set.
-     */
-    boolean hasLastMerchantUpdateTime();
-    /**
-     * <pre>
-     * Timestamp when this Menu or any of its contents was last updated by the
-     * restaurant; i.e. a date to be associated with the phrase “accurate as of
-     * date”.
-     * Optional.
-     * </pre>
-     *
-     * <code>.google.protobuf.Timestamp last_merchant_update_time = 8;</code>
-     * @return The lastMerchantUpdateTime.
-     */
-    com.google.protobuf.Timestamp getLastMerchantUpdateTime();
-    /**
-     * <pre>
-     * Timestamp when this Menu or any of its contents was last updated by the
-     * restaurant; i.e. a date to be associated with the phrase “accurate as of
-     * date”.
-     * Optional.
-     * </pre>
-     *
-     * <code>.google.protobuf.Timestamp last_merchant_update_time = 8;</code>
-     */
-    com.google.protobuf.TimestampOrBuilder getLastMerchantUpdateTimeOrBuilder();
-  }
-  /**
-   * <pre>
-   * Top-level catalog of food items offered by a Food establishment. Menu
-   * contains a list of merchant ids and the menu that apply to those merchants.
-   * A Menu can be used to represent single merchant with the menu, or multiple
-   * merchants (typically chain restaurants) with the menus.
-   * </pre>
-   *
-   * Protobuf type {@code food.menu.v1.Menu}
-   */
-  public static final class Menu extends
-      com.google.protobuf.GeneratedMessageV3 implements
-      // @@protoc_insertion_point(message_implements:food.menu.v1.Menu)
-      MenuOrBuilder {
-  private static final long serialVersionUID = 0L;
-    // Use Menu.newBuilder() to construct.
-    private Menu(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
-      super(builder);
-    }
-    private Menu() {
-      menuId_ = "";
-      merchantIds_ =
-          com.google.protobuf.LazyStringArrayList.emptyList();
-      language_ = "";
-      menuItemIds_ =
-          com.google.protobuf.LazyStringArrayList.emptyList();
-      menuSectionIds_ =
-          com.google.protobuf.LazyStringArrayList.emptyList();
-    }
-
-    @java.lang.Override
-    @SuppressWarnings({"unused"})
-    protected java.lang.Object newInstance(
-        UnusedPrivateParameter unused) {
-      return new Menu();
-    }
-
-    public static final com.google.protobuf.Descriptors.Descriptor
-        getDescriptor() {
-      return food.menu.v1.FoodMenu.internal_static_food_menu_v1_Menu_descriptor;
-    }
-
-    @java.lang.Override
-    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-        internalGetFieldAccessorTable() {
-      return food.menu.v1.FoodMenu.internal_static_food_menu_v1_Menu_fieldAccessorTable
-          .ensureFieldAccessorsInitialized(
-              food.menu.v1.FoodMenu.Menu.class, food.menu.v1.FoodMenu.Menu.Builder.class);
-    }
-
-    public static final int MENU_ID_FIELD_NUMBER = 1;
-    @SuppressWarnings("serial")
-    private volatile java.lang.Object menuId_ = "";
-    /**
-     * <pre>
-     * An opaque string from a partner which uniquely identifies the Menu within
-     * the partner feed.
-     * Required.
-     * </pre>
-     *
-     * <code>string menu_id = 1;</code>
-     * @return The menuId.
-     */
-    @java.lang.Override
-    public java.lang.String getMenuId() {
-      java.lang.Object ref = menuId_;
-      if (ref instanceof java.lang.String) {
-        return (java.lang.String) ref;
-      } else {
-        com.google.protobuf.ByteString bs = 
-            (com.google.protobuf.ByteString) ref;
-        java.lang.String s = bs.toStringUtf8();
-        menuId_ = s;
-        return s;
-      }
-    }
-    /**
-     * <pre>
-     * An opaque string from a partner which uniquely identifies the Menu within
-     * the partner feed.
-     * Required.
-     * </pre>
-     *
-     * <code>string menu_id = 1;</code>
-     * @return The bytes for menuId.
-     */
-    @java.lang.Override
-    public com.google.protobuf.ByteString
-        getMenuIdBytes() {
-      java.lang.Object ref = menuId_;
-      if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
-            com.google.protobuf.ByteString.copyFromUtf8(
-                (java.lang.String) ref);
-        menuId_ = b;
-        return b;
-      } else {
-        return (com.google.protobuf.ByteString) ref;
-      }
-    }
-
-    public static final int MERCHANT_IDS_FIELD_NUMBER = 2;
-    @SuppressWarnings("serial")
-    private com.google.protobuf.LazyStringArrayList merchantIds_ =
-        com.google.protobuf.LazyStringArrayList.emptyList();
-    /**
-     * <pre>
-     * The merchants to whom the menu apply.
-     * Note: This field is repeated so chain restaurants can share the same menu
-     * across multiple locations, each of which is a separate merchant.
-     * Required.
-     * </pre>
-     *
-     * <code>repeated string merchant_ids = 2;</code>
-     * @return A list containing the merchantIds.
-     */
-    public com.google.protobuf.ProtocolStringList
-        getMerchantIdsList() {
-      return merchantIds_;
-    }
-    /**
-     * <pre>
-     * The merchants to whom the menu apply.
-     * Note: This field is repeated so chain restaurants can share the same menu
-     * across multiple locations, each of which is a separate merchant.
-     * Required.
-     * </pre>
-     *
-     * <code>repeated string merchant_ids = 2;</code>
-     * @return The count of merchantIds.
-     */
-    public int getMerchantIdsCount() {
-      return merchantIds_.size();
-    }
-    /**
-     * <pre>
-     * The merchants to whom the menu apply.
-     * Note: This field is repeated so chain restaurants can share the same menu
-     * across multiple locations, each of which is a separate merchant.
-     * Required.
-     * </pre>
-     *
-     * <code>repeated string merchant_ids = 2;</code>
-     * @param index The index of the element to return.
-     * @return The merchantIds at the given index.
-     */
-    public java.lang.String getMerchantIds(int index) {
-      return merchantIds_.get(index);
-    }
-    /**
-     * <pre>
-     * The merchants to whom the menu apply.
-     * Note: This field is repeated so chain restaurants can share the same menu
-     * across multiple locations, each of which is a separate merchant.
-     * Required.
-     * </pre>
-     *
-     * <code>repeated string merchant_ids = 2;</code>
-     * @param index The index of the value to return.
-     * @return The bytes of the merchantIds at the given index.
-     */
-    public com.google.protobuf.ByteString
-        getMerchantIdsBytes(int index) {
-      return merchantIds_.getByteString(index);
-    }
-
-    public static final int DISPLAY_NAME_FIELD_NUMBER = 3;
-    private food.menu.v1.FoodMenu.TextField displayName_;
-    /**
-     * <pre>
-     * The name that can identify the Menu when a user is browsing the menu.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField display_name = 3;</code>
-     * @return Whether the displayName field is set.
-     */
-    @java.lang.Override
-    public boolean hasDisplayName() {
-      return displayName_ != null;
-    }
-    /**
-     * <pre>
-     * The name that can identify the Menu when a user is browsing the menu.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField display_name = 3;</code>
-     * @return The displayName.
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.TextField getDisplayName() {
-      return displayName_ == null ? food.menu.v1.FoodMenu.TextField.getDefaultInstance() : displayName_;
-    }
-    /**
-     * <pre>
-     * The name that can identify the Menu when a user is browsing the menu.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField display_name = 3;</code>
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.TextFieldOrBuilder getDisplayNameOrBuilder() {
-      return displayName_ == null ? food.menu.v1.FoodMenu.TextField.getDefaultInstance() : displayName_;
-    }
-
-    public static final int LANGUAGE_FIELD_NUMBER = 4;
-    @SuppressWarnings("serial")
-    private volatile java.lang.Object language_ = "";
-    /**
-     * <pre>
-     * The default language code associated with the text labels contained in the
-     * menu. Expects BCP-47 language code, such as "en-US" or "sr-Latn".
-     *
-     * For more information, see
-     * http://www.unicode.org/reports/tr35/#Unicode_locale_identifier.
-     * Optional.
-     * </pre>
-     *
-     * <code>string language = 4;</code>
-     * @return The language.
-     */
-    @java.lang.Override
-    public java.lang.String getLanguage() {
-      java.lang.Object ref = language_;
-      if (ref instanceof java.lang.String) {
-        return (java.lang.String) ref;
-      } else {
-        com.google.protobuf.ByteString bs = 
-            (com.google.protobuf.ByteString) ref;
-        java.lang.String s = bs.toStringUtf8();
-        language_ = s;
-        return s;
-      }
-    }
-    /**
-     * <pre>
-     * The default language code associated with the text labels contained in the
-     * menu. Expects BCP-47 language code, such as "en-US" or "sr-Latn".
-     *
-     * For more information, see
-     * http://www.unicode.org/reports/tr35/#Unicode_locale_identifier.
-     * Optional.
-     * </pre>
-     *
-     * <code>string language = 4;</code>
-     * @return The bytes for language.
-     */
-    @java.lang.Override
-    public com.google.protobuf.ByteString
-        getLanguageBytes() {
-      java.lang.Object ref = language_;
-      if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
-            com.google.protobuf.ByteString.copyFromUtf8(
-                (java.lang.String) ref);
-        language_ = b;
-        return b;
-      } else {
-        return (com.google.protobuf.ByteString) ref;
-      }
-    }
-
-    public static final int DISCLAIMER_FIELD_NUMBER = 5;
-    private food.menu.v1.FoodMenu.Disclaimer disclaimer_;
-    /**
-     * <pre>
-     * Disclaimer to be shown to the user for the menu. For example, nutritional
-     * information disclosure and allergen disclosure.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.Disclaimer disclaimer = 5;</code>
-     * @return Whether the disclaimer field is set.
-     */
-    @java.lang.Override
-    public boolean hasDisclaimer() {
-      return disclaimer_ != null;
-    }
-    /**
-     * <pre>
-     * Disclaimer to be shown to the user for the menu. For example, nutritional
-     * information disclosure and allergen disclosure.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.Disclaimer disclaimer = 5;</code>
-     * @return The disclaimer.
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.Disclaimer getDisclaimer() {
-      return disclaimer_ == null ? food.menu.v1.FoodMenu.Disclaimer.getDefaultInstance() : disclaimer_;
-    }
-    /**
-     * <pre>
-     * Disclaimer to be shown to the user for the menu. For example, nutritional
-     * information disclosure and allergen disclosure.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.Disclaimer disclaimer = 5;</code>
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.DisclaimerOrBuilder getDisclaimerOrBuilder() {
-      return disclaimer_ == null ? food.menu.v1.FoodMenu.Disclaimer.getDefaultInstance() : disclaimer_;
-    }
-
-    public static final int MENU_ITEM_IDS_FIELD_NUMBER = 6;
-    @SuppressWarnings("serial")
-    private com.google.protobuf.LazyStringArrayList menuItemIds_ =
-        com.google.protobuf.LazyStringArrayList.emptyList();
-    /**
-     * <pre>
-     * IDs of items contained within this menu. Expects first-level menu items
-     * only.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated string menu_item_ids = 6;</code>
-     * @return A list containing the menuItemIds.
-     */
-    public com.google.protobuf.ProtocolStringList
-        getMenuItemIdsList() {
-      return menuItemIds_;
-    }
-    /**
-     * <pre>
-     * IDs of items contained within this menu. Expects first-level menu items
-     * only.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated string menu_item_ids = 6;</code>
-     * @return The count of menuItemIds.
-     */
-    public int getMenuItemIdsCount() {
-      return menuItemIds_.size();
-    }
-    /**
-     * <pre>
-     * IDs of items contained within this menu. Expects first-level menu items
-     * only.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated string menu_item_ids = 6;</code>
-     * @param index The index of the element to return.
-     * @return The menuItemIds at the given index.
-     */
-    public java.lang.String getMenuItemIds(int index) {
-      return menuItemIds_.get(index);
-    }
-    /**
-     * <pre>
-     * IDs of items contained within this menu. Expects first-level menu items
-     * only.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated string menu_item_ids = 6;</code>
-     * @param index The index of the value to return.
-     * @return The bytes of the menuItemIds at the given index.
-     */
-    public com.google.protobuf.ByteString
-        getMenuItemIdsBytes(int index) {
-      return menuItemIds_.getByteString(index);
-    }
-
-    public static final int MENU_SECTION_IDS_FIELD_NUMBER = 7;
-    @SuppressWarnings("serial")
-    private com.google.protobuf.LazyStringArrayList menuSectionIds_ =
-        com.google.protobuf.LazyStringArrayList.emptyList();
-    /**
-     * <pre>
-     * IDs of sections contained within this menu. Expects first-level menu
-     * sections only.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated string menu_section_ids = 7;</code>
-     * @return A list containing the menuSectionIds.
-     */
-    public com.google.protobuf.ProtocolStringList
-        getMenuSectionIdsList() {
-      return menuSectionIds_;
-    }
-    /**
-     * <pre>
-     * IDs of sections contained within this menu. Expects first-level menu
-     * sections only.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated string menu_section_ids = 7;</code>
-     * @return The count of menuSectionIds.
-     */
-    public int getMenuSectionIdsCount() {
-      return menuSectionIds_.size();
-    }
-    /**
-     * <pre>
-     * IDs of sections contained within this menu. Expects first-level menu
-     * sections only.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated string menu_section_ids = 7;</code>
-     * @param index The index of the element to return.
-     * @return The menuSectionIds at the given index.
-     */
-    public java.lang.String getMenuSectionIds(int index) {
-      return menuSectionIds_.get(index);
-    }
-    /**
-     * <pre>
-     * IDs of sections contained within this menu. Expects first-level menu
-     * sections only.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated string menu_section_ids = 7;</code>
-     * @param index The index of the value to return.
-     * @return The bytes of the menuSectionIds at the given index.
-     */
-    public com.google.protobuf.ByteString
-        getMenuSectionIdsBytes(int index) {
-      return menuSectionIds_.getByteString(index);
-    }
-
-    public static final int LAST_MERCHANT_UPDATE_TIME_FIELD_NUMBER = 8;
-    private com.google.protobuf.Timestamp lastMerchantUpdateTime_;
-    /**
-     * <pre>
-     * Timestamp when this Menu or any of its contents was last updated by the
-     * restaurant; i.e. a date to be associated with the phrase “accurate as of
-     * date”.
-     * Optional.
-     * </pre>
-     *
-     * <code>.google.protobuf.Timestamp last_merchant_update_time = 8;</code>
-     * @return Whether the lastMerchantUpdateTime field is set.
-     */
-    @java.lang.Override
-    public boolean hasLastMerchantUpdateTime() {
-      return lastMerchantUpdateTime_ != null;
-    }
-    /**
-     * <pre>
-     * Timestamp when this Menu or any of its contents was last updated by the
-     * restaurant; i.e. a date to be associated with the phrase “accurate as of
-     * date”.
-     * Optional.
-     * </pre>
-     *
-     * <code>.google.protobuf.Timestamp last_merchant_update_time = 8;</code>
-     * @return The lastMerchantUpdateTime.
-     */
-    @java.lang.Override
-    public com.google.protobuf.Timestamp getLastMerchantUpdateTime() {
-      return lastMerchantUpdateTime_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : lastMerchantUpdateTime_;
-    }
-    /**
-     * <pre>
-     * Timestamp when this Menu or any of its contents was last updated by the
-     * restaurant; i.e. a date to be associated with the phrase “accurate as of
-     * date”.
-     * Optional.
-     * </pre>
-     *
-     * <code>.google.protobuf.Timestamp last_merchant_update_time = 8;</code>
-     */
-    @java.lang.Override
-    public com.google.protobuf.TimestampOrBuilder getLastMerchantUpdateTimeOrBuilder() {
-      return lastMerchantUpdateTime_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : lastMerchantUpdateTime_;
-    }
-
-    private byte memoizedIsInitialized = -1;
-    @java.lang.Override
-    public final boolean isInitialized() {
-      byte isInitialized = memoizedIsInitialized;
-      if (isInitialized == 1) return true;
-      if (isInitialized == 0) return false;
-
-      memoizedIsInitialized = 1;
-      return true;
-    }
-
-    @java.lang.Override
-    public void writeTo(com.google.protobuf.CodedOutputStream output)
-                        throws java.io.IOException {
-      if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(menuId_)) {
-        com.google.protobuf.GeneratedMessageV3.writeString(output, 1, menuId_);
-      }
-      for (int i = 0; i < merchantIds_.size(); i++) {
-        com.google.protobuf.GeneratedMessageV3.writeString(output, 2, merchantIds_.getRaw(i));
-      }
-      if (displayName_ != null) {
-        output.writeMessage(3, getDisplayName());
-      }
-      if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(language_)) {
-        com.google.protobuf.GeneratedMessageV3.writeString(output, 4, language_);
-      }
-      if (disclaimer_ != null) {
-        output.writeMessage(5, getDisclaimer());
-      }
-      for (int i = 0; i < menuItemIds_.size(); i++) {
-        com.google.protobuf.GeneratedMessageV3.writeString(output, 6, menuItemIds_.getRaw(i));
-      }
-      for (int i = 0; i < menuSectionIds_.size(); i++) {
-        com.google.protobuf.GeneratedMessageV3.writeString(output, 7, menuSectionIds_.getRaw(i));
-      }
-      if (lastMerchantUpdateTime_ != null) {
-        output.writeMessage(8, getLastMerchantUpdateTime());
-      }
-      getUnknownFields().writeTo(output);
-    }
-
-    @java.lang.Override
-    public int getSerializedSize() {
-      int size = memoizedSize;
-      if (size != -1) return size;
-
-      size = 0;
-      if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(menuId_)) {
-        size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, menuId_);
-      }
-      {
-        int dataSize = 0;
-        for (int i = 0; i < merchantIds_.size(); i++) {
-          dataSize += computeStringSizeNoTag(merchantIds_.getRaw(i));
-        }
-        size += dataSize;
-        size += 1 * getMerchantIdsList().size();
-      }
-      if (displayName_ != null) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(3, getDisplayName());
-      }
-      if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(language_)) {
-        size += com.google.protobuf.GeneratedMessageV3.computeStringSize(4, language_);
-      }
-      if (disclaimer_ != null) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(5, getDisclaimer());
-      }
-      {
-        int dataSize = 0;
-        for (int i = 0; i < menuItemIds_.size(); i++) {
-          dataSize += computeStringSizeNoTag(menuItemIds_.getRaw(i));
-        }
-        size += dataSize;
-        size += 1 * getMenuItemIdsList().size();
-      }
-      {
-        int dataSize = 0;
-        for (int i = 0; i < menuSectionIds_.size(); i++) {
-          dataSize += computeStringSizeNoTag(menuSectionIds_.getRaw(i));
-        }
-        size += dataSize;
-        size += 1 * getMenuSectionIdsList().size();
-      }
-      if (lastMerchantUpdateTime_ != null) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(8, getLastMerchantUpdateTime());
-      }
-      size += getUnknownFields().getSerializedSize();
-      memoizedSize = size;
-      return size;
-    }
-
-    @java.lang.Override
-    public boolean equals(final java.lang.Object obj) {
-      if (obj == this) {
-       return true;
-      }
-      if (!(obj instanceof food.menu.v1.FoodMenu.Menu)) {
-        return super.equals(obj);
-      }
-      food.menu.v1.FoodMenu.Menu other = (food.menu.v1.FoodMenu.Menu) obj;
-
-      if (!getMenuId()
-          .equals(other.getMenuId())) return false;
-      if (!getMerchantIdsList()
-          .equals(other.getMerchantIdsList())) return false;
-      if (hasDisplayName() != other.hasDisplayName()) return false;
-      if (hasDisplayName()) {
-        if (!getDisplayName()
-            .equals(other.getDisplayName())) return false;
-      }
-      if (!getLanguage()
-          .equals(other.getLanguage())) return false;
-      if (hasDisclaimer() != other.hasDisclaimer()) return false;
-      if (hasDisclaimer()) {
-        if (!getDisclaimer()
-            .equals(other.getDisclaimer())) return false;
-      }
-      if (!getMenuItemIdsList()
-          .equals(other.getMenuItemIdsList())) return false;
-      if (!getMenuSectionIdsList()
-          .equals(other.getMenuSectionIdsList())) return false;
-      if (hasLastMerchantUpdateTime() != other.hasLastMerchantUpdateTime()) return false;
-      if (hasLastMerchantUpdateTime()) {
-        if (!getLastMerchantUpdateTime()
-            .equals(other.getLastMerchantUpdateTime())) return false;
-      }
-      if (!getUnknownFields().equals(other.getUnknownFields())) return false;
-      return true;
-    }
-
-    @java.lang.Override
-    public int hashCode() {
-      if (memoizedHashCode != 0) {
-        return memoizedHashCode;
-      }
-      int hash = 41;
-      hash = (19 * hash) + getDescriptor().hashCode();
-      hash = (37 * hash) + MENU_ID_FIELD_NUMBER;
-      hash = (53 * hash) + getMenuId().hashCode();
-      if (getMerchantIdsCount() > 0) {
-        hash = (37 * hash) + MERCHANT_IDS_FIELD_NUMBER;
-        hash = (53 * hash) + getMerchantIdsList().hashCode();
-      }
-      if (hasDisplayName()) {
-        hash = (37 * hash) + DISPLAY_NAME_FIELD_NUMBER;
-        hash = (53 * hash) + getDisplayName().hashCode();
-      }
-      hash = (37 * hash) + LANGUAGE_FIELD_NUMBER;
-      hash = (53 * hash) + getLanguage().hashCode();
-      if (hasDisclaimer()) {
-        hash = (37 * hash) + DISCLAIMER_FIELD_NUMBER;
-        hash = (53 * hash) + getDisclaimer().hashCode();
-      }
-      if (getMenuItemIdsCount() > 0) {
-        hash = (37 * hash) + MENU_ITEM_IDS_FIELD_NUMBER;
-        hash = (53 * hash) + getMenuItemIdsList().hashCode();
-      }
-      if (getMenuSectionIdsCount() > 0) {
-        hash = (37 * hash) + MENU_SECTION_IDS_FIELD_NUMBER;
-        hash = (53 * hash) + getMenuSectionIdsList().hashCode();
-      }
-      if (hasLastMerchantUpdateTime()) {
-        hash = (37 * hash) + LAST_MERCHANT_UPDATE_TIME_FIELD_NUMBER;
-        hash = (53 * hash) + getLastMerchantUpdateTime().hashCode();
-      }
-      hash = (29 * hash) + getUnknownFields().hashCode();
-      memoizedHashCode = hash;
-      return hash;
-    }
-
-    public static food.menu.v1.FoodMenu.Menu parseFrom(
-        java.nio.ByteBuffer data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.Menu parseFrom(
-        java.nio.ByteBuffer data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.Menu parseFrom(
-        com.google.protobuf.ByteString data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.Menu parseFrom(
-        com.google.protobuf.ByteString data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.Menu parseFrom(byte[] data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.Menu parseFrom(
-        byte[] data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.Menu parseFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.Menu parseFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.Menu parseDelimitedFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseDelimitedWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.Menu parseDelimitedFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.Menu parseFrom(
-        com.google.protobuf.CodedInputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.Menu parseFrom(
-        com.google.protobuf.CodedInputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input, extensionRegistry);
-    }
-
-    @java.lang.Override
-    public Builder newBuilderForType() { return newBuilder(); }
-    public static Builder newBuilder() {
-      return DEFAULT_INSTANCE.toBuilder();
-    }
-    public static Builder newBuilder(food.menu.v1.FoodMenu.Menu prototype) {
-      return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
-    }
-    @java.lang.Override
-    public Builder toBuilder() {
-      return this == DEFAULT_INSTANCE
-          ? new Builder() : new Builder().mergeFrom(this);
-    }
-
-    @java.lang.Override
-    protected Builder newBuilderForType(
-        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-      Builder builder = new Builder(parent);
-      return builder;
-    }
-    /**
-     * <pre>
-     * Top-level catalog of food items offered by a Food establishment. Menu
-     * contains a list of merchant ids and the menu that apply to those merchants.
-     * A Menu can be used to represent single merchant with the menu, or multiple
-     * merchants (typically chain restaurants) with the menus.
-     * </pre>
-     *
-     * Protobuf type {@code food.menu.v1.Menu}
-     */
-    public static final class Builder extends
-        com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
-        // @@protoc_insertion_point(builder_implements:food.menu.v1.Menu)
-        food.menu.v1.FoodMenu.MenuOrBuilder {
-      public static final com.google.protobuf.Descriptors.Descriptor
-          getDescriptor() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_Menu_descriptor;
-      }
-
-      @java.lang.Override
-      protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-          internalGetFieldAccessorTable() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_Menu_fieldAccessorTable
-            .ensureFieldAccessorsInitialized(
-                food.menu.v1.FoodMenu.Menu.class, food.menu.v1.FoodMenu.Menu.Builder.class);
-      }
-
-      // Construct using food.menu.v1.FoodMenu.Menu.newBuilder()
-      private Builder() {
-
-      }
-
-      private Builder(
-          com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-        super(parent);
-
-      }
-      @java.lang.Override
-      public Builder clear() {
-        super.clear();
-        bitField0_ = 0;
-        menuId_ = "";
-        merchantIds_ =
-            com.google.protobuf.LazyStringArrayList.emptyList();
-        displayName_ = null;
-        if (displayNameBuilder_ != null) {
-          displayNameBuilder_.dispose();
-          displayNameBuilder_ = null;
-        }
-        language_ = "";
-        disclaimer_ = null;
-        if (disclaimerBuilder_ != null) {
-          disclaimerBuilder_.dispose();
-          disclaimerBuilder_ = null;
-        }
-        menuItemIds_ =
-            com.google.protobuf.LazyStringArrayList.emptyList();
-        menuSectionIds_ =
-            com.google.protobuf.LazyStringArrayList.emptyList();
-        lastMerchantUpdateTime_ = null;
-        if (lastMerchantUpdateTimeBuilder_ != null) {
-          lastMerchantUpdateTimeBuilder_.dispose();
-          lastMerchantUpdateTimeBuilder_ = null;
-        }
-        return this;
-      }
-
-      @java.lang.Override
-      public com.google.protobuf.Descriptors.Descriptor
-          getDescriptorForType() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_Menu_descriptor;
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.Menu getDefaultInstanceForType() {
-        return food.menu.v1.FoodMenu.Menu.getDefaultInstance();
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.Menu build() {
-        food.menu.v1.FoodMenu.Menu result = buildPartial();
-        if (!result.isInitialized()) {
-          throw newUninitializedMessageException(result);
-        }
-        return result;
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.Menu buildPartial() {
-        food.menu.v1.FoodMenu.Menu result = new food.menu.v1.FoodMenu.Menu(this);
-        if (bitField0_ != 0) { buildPartial0(result); }
-        onBuilt();
-        return result;
-      }
-
-      private void buildPartial0(food.menu.v1.FoodMenu.Menu result) {
-        int from_bitField0_ = bitField0_;
-        if (((from_bitField0_ & 0x00000001) != 0)) {
-          result.menuId_ = menuId_;
-        }
-        if (((from_bitField0_ & 0x00000002) != 0)) {
-          merchantIds_.makeImmutable();
-          result.merchantIds_ = merchantIds_;
-        }
-        if (((from_bitField0_ & 0x00000004) != 0)) {
-          result.displayName_ = displayNameBuilder_ == null
-              ? displayName_
-              : displayNameBuilder_.build();
-        }
-        if (((from_bitField0_ & 0x00000008) != 0)) {
-          result.language_ = language_;
-        }
-        if (((from_bitField0_ & 0x00000010) != 0)) {
-          result.disclaimer_ = disclaimerBuilder_ == null
-              ? disclaimer_
-              : disclaimerBuilder_.build();
-        }
-        if (((from_bitField0_ & 0x00000020) != 0)) {
-          menuItemIds_.makeImmutable();
-          result.menuItemIds_ = menuItemIds_;
-        }
-        if (((from_bitField0_ & 0x00000040) != 0)) {
-          menuSectionIds_.makeImmutable();
-          result.menuSectionIds_ = menuSectionIds_;
-        }
-        if (((from_bitField0_ & 0x00000080) != 0)) {
-          result.lastMerchantUpdateTime_ = lastMerchantUpdateTimeBuilder_ == null
-              ? lastMerchantUpdateTime_
-              : lastMerchantUpdateTimeBuilder_.build();
-        }
-      }
-
-      @java.lang.Override
-      public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof food.menu.v1.FoodMenu.Menu) {
-          return mergeFrom((food.menu.v1.FoodMenu.Menu)other);
-        } else {
-          super.mergeFrom(other);
-          return this;
-        }
-      }
-
-      public Builder mergeFrom(food.menu.v1.FoodMenu.Menu other) {
-        if (other == food.menu.v1.FoodMenu.Menu.getDefaultInstance()) return this;
-        if (!other.getMenuId().isEmpty()) {
-          menuId_ = other.menuId_;
-          bitField0_ |= 0x00000001;
-          onChanged();
-        }
-        if (!other.merchantIds_.isEmpty()) {
-          if (merchantIds_.isEmpty()) {
-            merchantIds_ = other.merchantIds_;
-            bitField0_ |= 0x00000002;
-          } else {
-            ensureMerchantIdsIsMutable();
-            merchantIds_.addAll(other.merchantIds_);
-          }
-          onChanged();
-        }
-        if (other.hasDisplayName()) {
-          mergeDisplayName(other.getDisplayName());
-        }
-        if (!other.getLanguage().isEmpty()) {
-          language_ = other.language_;
-          bitField0_ |= 0x00000008;
-          onChanged();
-        }
-        if (other.hasDisclaimer()) {
-          mergeDisclaimer(other.getDisclaimer());
-        }
-        if (!other.menuItemIds_.isEmpty()) {
-          if (menuItemIds_.isEmpty()) {
-            menuItemIds_ = other.menuItemIds_;
-            bitField0_ |= 0x00000020;
-          } else {
-            ensureMenuItemIdsIsMutable();
-            menuItemIds_.addAll(other.menuItemIds_);
-          }
-          onChanged();
-        }
-        if (!other.menuSectionIds_.isEmpty()) {
-          if (menuSectionIds_.isEmpty()) {
-            menuSectionIds_ = other.menuSectionIds_;
-            bitField0_ |= 0x00000040;
-          } else {
-            ensureMenuSectionIdsIsMutable();
-            menuSectionIds_.addAll(other.menuSectionIds_);
-          }
-          onChanged();
-        }
-        if (other.hasLastMerchantUpdateTime()) {
-          mergeLastMerchantUpdateTime(other.getLastMerchantUpdateTime());
-        }
-        this.mergeUnknownFields(other.getUnknownFields());
-        onChanged();
-        return this;
-      }
-
-      @java.lang.Override
-      public final boolean isInitialized() {
-        return true;
-      }
-
-      @java.lang.Override
-      public Builder mergeFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws java.io.IOException {
-        if (extensionRegistry == null) {
-          throw new java.lang.NullPointerException();
-        }
-        try {
-          boolean done = false;
-          while (!done) {
-            int tag = input.readTag();
-            switch (tag) {
-              case 0:
-                done = true;
-                break;
-              case 10: {
-                menuId_ = input.readStringRequireUtf8();
-                bitField0_ |= 0x00000001;
-                break;
-              } // case 10
-              case 18: {
-                java.lang.String s = input.readStringRequireUtf8();
-                ensureMerchantIdsIsMutable();
-                merchantIds_.add(s);
-                break;
-              } // case 18
-              case 26: {
-                input.readMessage(
-                    getDisplayNameFieldBuilder().getBuilder(),
-                    extensionRegistry);
-                bitField0_ |= 0x00000004;
-                break;
-              } // case 26
-              case 34: {
-                language_ = input.readStringRequireUtf8();
-                bitField0_ |= 0x00000008;
-                break;
-              } // case 34
-              case 42: {
-                input.readMessage(
-                    getDisclaimerFieldBuilder().getBuilder(),
-                    extensionRegistry);
-                bitField0_ |= 0x00000010;
-                break;
-              } // case 42
-              case 50: {
-                java.lang.String s = input.readStringRequireUtf8();
-                ensureMenuItemIdsIsMutable();
-                menuItemIds_.add(s);
-                break;
-              } // case 50
-              case 58: {
-                java.lang.String s = input.readStringRequireUtf8();
-                ensureMenuSectionIdsIsMutable();
-                menuSectionIds_.add(s);
-                break;
-              } // case 58
-              case 66: {
-                input.readMessage(
-                    getLastMerchantUpdateTimeFieldBuilder().getBuilder(),
-                    extensionRegistry);
-                bitField0_ |= 0x00000080;
-                break;
-              } // case 66
-              default: {
-                if (!super.parseUnknownField(input, extensionRegistry, tag)) {
-                  done = true; // was an endgroup tag
-                }
-                break;
-              } // default:
-            } // switch (tag)
-          } // while (!done)
-        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          throw e.unwrapIOException();
-        } finally {
-          onChanged();
-        } // finally
-        return this;
-      }
-      private int bitField0_;
-
-      private java.lang.Object menuId_ = "";
-      /**
-       * <pre>
-       * An opaque string from a partner which uniquely identifies the Menu within
-       * the partner feed.
-       * Required.
-       * </pre>
-       *
-       * <code>string menu_id = 1;</code>
-       * @return The menuId.
-       */
-      public java.lang.String getMenuId() {
-        java.lang.Object ref = menuId_;
-        if (!(ref instanceof java.lang.String)) {
-          com.google.protobuf.ByteString bs =
-              (com.google.protobuf.ByteString) ref;
-          java.lang.String s = bs.toStringUtf8();
-          menuId_ = s;
-          return s;
-        } else {
-          return (java.lang.String) ref;
-        }
-      }
-      /**
-       * <pre>
-       * An opaque string from a partner which uniquely identifies the Menu within
-       * the partner feed.
-       * Required.
-       * </pre>
-       *
-       * <code>string menu_id = 1;</code>
-       * @return The bytes for menuId.
-       */
-      public com.google.protobuf.ByteString
-          getMenuIdBytes() {
-        java.lang.Object ref = menuId_;
-        if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
-              com.google.protobuf.ByteString.copyFromUtf8(
-                  (java.lang.String) ref);
-          menuId_ = b;
-          return b;
-        } else {
-          return (com.google.protobuf.ByteString) ref;
-        }
-      }
-      /**
-       * <pre>
-       * An opaque string from a partner which uniquely identifies the Menu within
-       * the partner feed.
-       * Required.
-       * </pre>
-       *
-       * <code>string menu_id = 1;</code>
-       * @param value The menuId to set.
-       * @return This builder for chaining.
-       */
-      public Builder setMenuId(
-          java.lang.String value) {
-        if (value == null) { throw new NullPointerException(); }
-        menuId_ = value;
-        bitField0_ |= 0x00000001;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * An opaque string from a partner which uniquely identifies the Menu within
-       * the partner feed.
-       * Required.
-       * </pre>
-       *
-       * <code>string menu_id = 1;</code>
-       * @return This builder for chaining.
-       */
-      public Builder clearMenuId() {
-        menuId_ = getDefaultInstance().getMenuId();
-        bitField0_ = (bitField0_ & ~0x00000001);
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * An opaque string from a partner which uniquely identifies the Menu within
-       * the partner feed.
-       * Required.
-       * </pre>
-       *
-       * <code>string menu_id = 1;</code>
-       * @param value The bytes for menuId to set.
-       * @return This builder for chaining.
-       */
-      public Builder setMenuIdBytes(
-          com.google.protobuf.ByteString value) {
-        if (value == null) { throw new NullPointerException(); }
-        checkByteStringIsUtf8(value);
-        menuId_ = value;
-        bitField0_ |= 0x00000001;
-        onChanged();
-        return this;
-      }
-
-      private com.google.protobuf.LazyStringArrayList merchantIds_ =
-          com.google.protobuf.LazyStringArrayList.emptyList();
-      private void ensureMerchantIdsIsMutable() {
-        if (!merchantIds_.isModifiable()) {
-          merchantIds_ = new com.google.protobuf.LazyStringArrayList(merchantIds_);
-        }
-        bitField0_ |= 0x00000002;
-      }
-      /**
-       * <pre>
-       * The merchants to whom the menu apply.
-       * Note: This field is repeated so chain restaurants can share the same menu
-       * across multiple locations, each of which is a separate merchant.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated string merchant_ids = 2;</code>
-       * @return A list containing the merchantIds.
-       */
-      public com.google.protobuf.ProtocolStringList
-          getMerchantIdsList() {
-        merchantIds_.makeImmutable();
-        return merchantIds_;
-      }
-      /**
-       * <pre>
-       * The merchants to whom the menu apply.
-       * Note: This field is repeated so chain restaurants can share the same menu
-       * across multiple locations, each of which is a separate merchant.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated string merchant_ids = 2;</code>
-       * @return The count of merchantIds.
-       */
-      public int getMerchantIdsCount() {
-        return merchantIds_.size();
-      }
-      /**
-       * <pre>
-       * The merchants to whom the menu apply.
-       * Note: This field is repeated so chain restaurants can share the same menu
-       * across multiple locations, each of which is a separate merchant.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated string merchant_ids = 2;</code>
-       * @param index The index of the element to return.
-       * @return The merchantIds at the given index.
-       */
-      public java.lang.String getMerchantIds(int index) {
-        return merchantIds_.get(index);
-      }
-      /**
-       * <pre>
-       * The merchants to whom the menu apply.
-       * Note: This field is repeated so chain restaurants can share the same menu
-       * across multiple locations, each of which is a separate merchant.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated string merchant_ids = 2;</code>
-       * @param index The index of the value to return.
-       * @return The bytes of the merchantIds at the given index.
-       */
-      public com.google.protobuf.ByteString
-          getMerchantIdsBytes(int index) {
-        return merchantIds_.getByteString(index);
-      }
-      /**
-       * <pre>
-       * The merchants to whom the menu apply.
-       * Note: This field is repeated so chain restaurants can share the same menu
-       * across multiple locations, each of which is a separate merchant.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated string merchant_ids = 2;</code>
-       * @param index The index to set the value at.
-       * @param value The merchantIds to set.
-       * @return This builder for chaining.
-       */
-      public Builder setMerchantIds(
-          int index, java.lang.String value) {
-        if (value == null) { throw new NullPointerException(); }
-        ensureMerchantIdsIsMutable();
-        merchantIds_.set(index, value);
-        bitField0_ |= 0x00000002;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * The merchants to whom the menu apply.
-       * Note: This field is repeated so chain restaurants can share the same menu
-       * across multiple locations, each of which is a separate merchant.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated string merchant_ids = 2;</code>
-       * @param value The merchantIds to add.
-       * @return This builder for chaining.
-       */
-      public Builder addMerchantIds(
-          java.lang.String value) {
-        if (value == null) { throw new NullPointerException(); }
-        ensureMerchantIdsIsMutable();
-        merchantIds_.add(value);
-        bitField0_ |= 0x00000002;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * The merchants to whom the menu apply.
-       * Note: This field is repeated so chain restaurants can share the same menu
-       * across multiple locations, each of which is a separate merchant.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated string merchant_ids = 2;</code>
-       * @param values The merchantIds to add.
-       * @return This builder for chaining.
-       */
-      public Builder addAllMerchantIds(
-          java.lang.Iterable<java.lang.String> values) {
-        ensureMerchantIdsIsMutable();
-        com.google.protobuf.AbstractMessageLite.Builder.addAll(
-            values, merchantIds_);
-        bitField0_ |= 0x00000002;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * The merchants to whom the menu apply.
-       * Note: This field is repeated so chain restaurants can share the same menu
-       * across multiple locations, each of which is a separate merchant.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated string merchant_ids = 2;</code>
-       * @return This builder for chaining.
-       */
-      public Builder clearMerchantIds() {
-        merchantIds_ =
-          com.google.protobuf.LazyStringArrayList.emptyList();
-        bitField0_ = (bitField0_ & ~0x00000002);;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * The merchants to whom the menu apply.
-       * Note: This field is repeated so chain restaurants can share the same menu
-       * across multiple locations, each of which is a separate merchant.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated string merchant_ids = 2;</code>
-       * @param value The bytes of the merchantIds to add.
-       * @return This builder for chaining.
-       */
-      public Builder addMerchantIdsBytes(
-          com.google.protobuf.ByteString value) {
-        if (value == null) { throw new NullPointerException(); }
-        checkByteStringIsUtf8(value);
-        ensureMerchantIdsIsMutable();
-        merchantIds_.add(value);
-        bitField0_ |= 0x00000002;
-        onChanged();
-        return this;
-      }
-
-      private food.menu.v1.FoodMenu.TextField displayName_;
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.TextField, food.menu.v1.FoodMenu.TextField.Builder, food.menu.v1.FoodMenu.TextFieldOrBuilder> displayNameBuilder_;
-      /**
-       * <pre>
-       * The name that can identify the Menu when a user is browsing the menu.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField display_name = 3;</code>
-       * @return Whether the displayName field is set.
-       */
-      public boolean hasDisplayName() {
-        return ((bitField0_ & 0x00000004) != 0);
-      }
-      /**
-       * <pre>
-       * The name that can identify the Menu when a user is browsing the menu.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField display_name = 3;</code>
-       * @return The displayName.
-       */
-      public food.menu.v1.FoodMenu.TextField getDisplayName() {
-        if (displayNameBuilder_ == null) {
-          return displayName_ == null ? food.menu.v1.FoodMenu.TextField.getDefaultInstance() : displayName_;
-        } else {
-          return displayNameBuilder_.getMessage();
-        }
-      }
-      /**
-       * <pre>
-       * The name that can identify the Menu when a user is browsing the menu.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField display_name = 3;</code>
-       */
-      public Builder setDisplayName(food.menu.v1.FoodMenu.TextField value) {
-        if (displayNameBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          displayName_ = value;
-        } else {
-          displayNameBuilder_.setMessage(value);
-        }
-        bitField0_ |= 0x00000004;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * The name that can identify the Menu when a user is browsing the menu.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField display_name = 3;</code>
-       */
-      public Builder setDisplayName(
-          food.menu.v1.FoodMenu.TextField.Builder builderForValue) {
-        if (displayNameBuilder_ == null) {
-          displayName_ = builderForValue.build();
-        } else {
-          displayNameBuilder_.setMessage(builderForValue.build());
-        }
-        bitField0_ |= 0x00000004;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * The name that can identify the Menu when a user is browsing the menu.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField display_name = 3;</code>
-       */
-      public Builder mergeDisplayName(food.menu.v1.FoodMenu.TextField value) {
-        if (displayNameBuilder_ == null) {
-          if (((bitField0_ & 0x00000004) != 0) &&
-            displayName_ != null &&
-            displayName_ != food.menu.v1.FoodMenu.TextField.getDefaultInstance()) {
-            getDisplayNameBuilder().mergeFrom(value);
-          } else {
-            displayName_ = value;
-          }
-        } else {
-          displayNameBuilder_.mergeFrom(value);
-        }
-        bitField0_ |= 0x00000004;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * The name that can identify the Menu when a user is browsing the menu.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField display_name = 3;</code>
-       */
-      public Builder clearDisplayName() {
-        bitField0_ = (bitField0_ & ~0x00000004);
-        displayName_ = null;
-        if (displayNameBuilder_ != null) {
-          displayNameBuilder_.dispose();
-          displayNameBuilder_ = null;
-        }
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * The name that can identify the Menu when a user is browsing the menu.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField display_name = 3;</code>
-       */
-      public food.menu.v1.FoodMenu.TextField.Builder getDisplayNameBuilder() {
-        bitField0_ |= 0x00000004;
-        onChanged();
-        return getDisplayNameFieldBuilder().getBuilder();
-      }
-      /**
-       * <pre>
-       * The name that can identify the Menu when a user is browsing the menu.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField display_name = 3;</code>
-       */
-      public food.menu.v1.FoodMenu.TextFieldOrBuilder getDisplayNameOrBuilder() {
-        if (displayNameBuilder_ != null) {
-          return displayNameBuilder_.getMessageOrBuilder();
-        } else {
-          return displayName_ == null ?
-              food.menu.v1.FoodMenu.TextField.getDefaultInstance() : displayName_;
-        }
-      }
-      /**
-       * <pre>
-       * The name that can identify the Menu when a user is browsing the menu.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField display_name = 3;</code>
-       */
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.TextField, food.menu.v1.FoodMenu.TextField.Builder, food.menu.v1.FoodMenu.TextFieldOrBuilder> 
-          getDisplayNameFieldBuilder() {
-        if (displayNameBuilder_ == null) {
-          displayNameBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
-              food.menu.v1.FoodMenu.TextField, food.menu.v1.FoodMenu.TextField.Builder, food.menu.v1.FoodMenu.TextFieldOrBuilder>(
-                  getDisplayName(),
-                  getParentForChildren(),
-                  isClean());
-          displayName_ = null;
-        }
-        return displayNameBuilder_;
-      }
-
-      private java.lang.Object language_ = "";
-      /**
-       * <pre>
-       * The default language code associated with the text labels contained in the
-       * menu. Expects BCP-47 language code, such as "en-US" or "sr-Latn".
-       *
-       * For more information, see
-       * http://www.unicode.org/reports/tr35/#Unicode_locale_identifier.
-       * Optional.
-       * </pre>
-       *
-       * <code>string language = 4;</code>
-       * @return The language.
-       */
-      public java.lang.String getLanguage() {
-        java.lang.Object ref = language_;
-        if (!(ref instanceof java.lang.String)) {
-          com.google.protobuf.ByteString bs =
-              (com.google.protobuf.ByteString) ref;
-          java.lang.String s = bs.toStringUtf8();
-          language_ = s;
-          return s;
-        } else {
-          return (java.lang.String) ref;
-        }
-      }
-      /**
-       * <pre>
-       * The default language code associated with the text labels contained in the
-       * menu. Expects BCP-47 language code, such as "en-US" or "sr-Latn".
-       *
-       * For more information, see
-       * http://www.unicode.org/reports/tr35/#Unicode_locale_identifier.
-       * Optional.
-       * </pre>
-       *
-       * <code>string language = 4;</code>
-       * @return The bytes for language.
-       */
-      public com.google.protobuf.ByteString
-          getLanguageBytes() {
-        java.lang.Object ref = language_;
-        if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
-              com.google.protobuf.ByteString.copyFromUtf8(
-                  (java.lang.String) ref);
-          language_ = b;
-          return b;
-        } else {
-          return (com.google.protobuf.ByteString) ref;
-        }
-      }
-      /**
-       * <pre>
-       * The default language code associated with the text labels contained in the
-       * menu. Expects BCP-47 language code, such as "en-US" or "sr-Latn".
-       *
-       * For more information, see
-       * http://www.unicode.org/reports/tr35/#Unicode_locale_identifier.
-       * Optional.
-       * </pre>
-       *
-       * <code>string language = 4;</code>
-       * @param value The language to set.
-       * @return This builder for chaining.
-       */
-      public Builder setLanguage(
-          java.lang.String value) {
-        if (value == null) { throw new NullPointerException(); }
-        language_ = value;
-        bitField0_ |= 0x00000008;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * The default language code associated with the text labels contained in the
-       * menu. Expects BCP-47 language code, such as "en-US" or "sr-Latn".
-       *
-       * For more information, see
-       * http://www.unicode.org/reports/tr35/#Unicode_locale_identifier.
-       * Optional.
-       * </pre>
-       *
-       * <code>string language = 4;</code>
-       * @return This builder for chaining.
-       */
-      public Builder clearLanguage() {
-        language_ = getDefaultInstance().getLanguage();
-        bitField0_ = (bitField0_ & ~0x00000008);
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * The default language code associated with the text labels contained in the
-       * menu. Expects BCP-47 language code, such as "en-US" or "sr-Latn".
-       *
-       * For more information, see
-       * http://www.unicode.org/reports/tr35/#Unicode_locale_identifier.
-       * Optional.
-       * </pre>
-       *
-       * <code>string language = 4;</code>
-       * @param value The bytes for language to set.
-       * @return This builder for chaining.
-       */
-      public Builder setLanguageBytes(
-          com.google.protobuf.ByteString value) {
-        if (value == null) { throw new NullPointerException(); }
-        checkByteStringIsUtf8(value);
-        language_ = value;
-        bitField0_ |= 0x00000008;
-        onChanged();
-        return this;
-      }
-
-      private food.menu.v1.FoodMenu.Disclaimer disclaimer_;
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.Disclaimer, food.menu.v1.FoodMenu.Disclaimer.Builder, food.menu.v1.FoodMenu.DisclaimerOrBuilder> disclaimerBuilder_;
-      /**
-       * <pre>
-       * Disclaimer to be shown to the user for the menu. For example, nutritional
-       * information disclosure and allergen disclosure.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.Disclaimer disclaimer = 5;</code>
-       * @return Whether the disclaimer field is set.
-       */
-      public boolean hasDisclaimer() {
-        return ((bitField0_ & 0x00000010) != 0);
-      }
-      /**
-       * <pre>
-       * Disclaimer to be shown to the user for the menu. For example, nutritional
-       * information disclosure and allergen disclosure.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.Disclaimer disclaimer = 5;</code>
-       * @return The disclaimer.
-       */
-      public food.menu.v1.FoodMenu.Disclaimer getDisclaimer() {
-        if (disclaimerBuilder_ == null) {
-          return disclaimer_ == null ? food.menu.v1.FoodMenu.Disclaimer.getDefaultInstance() : disclaimer_;
-        } else {
-          return disclaimerBuilder_.getMessage();
-        }
-      }
-      /**
-       * <pre>
-       * Disclaimer to be shown to the user for the menu. For example, nutritional
-       * information disclosure and allergen disclosure.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.Disclaimer disclaimer = 5;</code>
-       */
-      public Builder setDisclaimer(food.menu.v1.FoodMenu.Disclaimer value) {
-        if (disclaimerBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          disclaimer_ = value;
-        } else {
-          disclaimerBuilder_.setMessage(value);
-        }
-        bitField0_ |= 0x00000010;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Disclaimer to be shown to the user for the menu. For example, nutritional
-       * information disclosure and allergen disclosure.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.Disclaimer disclaimer = 5;</code>
-       */
-      public Builder setDisclaimer(
-          food.menu.v1.FoodMenu.Disclaimer.Builder builderForValue) {
-        if (disclaimerBuilder_ == null) {
-          disclaimer_ = builderForValue.build();
-        } else {
-          disclaimerBuilder_.setMessage(builderForValue.build());
-        }
-        bitField0_ |= 0x00000010;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Disclaimer to be shown to the user for the menu. For example, nutritional
-       * information disclosure and allergen disclosure.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.Disclaimer disclaimer = 5;</code>
-       */
-      public Builder mergeDisclaimer(food.menu.v1.FoodMenu.Disclaimer value) {
-        if (disclaimerBuilder_ == null) {
-          if (((bitField0_ & 0x00000010) != 0) &&
-            disclaimer_ != null &&
-            disclaimer_ != food.menu.v1.FoodMenu.Disclaimer.getDefaultInstance()) {
-            getDisclaimerBuilder().mergeFrom(value);
-          } else {
-            disclaimer_ = value;
-          }
-        } else {
-          disclaimerBuilder_.mergeFrom(value);
-        }
-        bitField0_ |= 0x00000010;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Disclaimer to be shown to the user for the menu. For example, nutritional
-       * information disclosure and allergen disclosure.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.Disclaimer disclaimer = 5;</code>
-       */
-      public Builder clearDisclaimer() {
-        bitField0_ = (bitField0_ & ~0x00000010);
-        disclaimer_ = null;
-        if (disclaimerBuilder_ != null) {
-          disclaimerBuilder_.dispose();
-          disclaimerBuilder_ = null;
-        }
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Disclaimer to be shown to the user for the menu. For example, nutritional
-       * information disclosure and allergen disclosure.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.Disclaimer disclaimer = 5;</code>
-       */
-      public food.menu.v1.FoodMenu.Disclaimer.Builder getDisclaimerBuilder() {
-        bitField0_ |= 0x00000010;
-        onChanged();
-        return getDisclaimerFieldBuilder().getBuilder();
-      }
-      /**
-       * <pre>
-       * Disclaimer to be shown to the user for the menu. For example, nutritional
-       * information disclosure and allergen disclosure.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.Disclaimer disclaimer = 5;</code>
-       */
-      public food.menu.v1.FoodMenu.DisclaimerOrBuilder getDisclaimerOrBuilder() {
-        if (disclaimerBuilder_ != null) {
-          return disclaimerBuilder_.getMessageOrBuilder();
-        } else {
-          return disclaimer_ == null ?
-              food.menu.v1.FoodMenu.Disclaimer.getDefaultInstance() : disclaimer_;
-        }
-      }
-      /**
-       * <pre>
-       * Disclaimer to be shown to the user for the menu. For example, nutritional
-       * information disclosure and allergen disclosure.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.Disclaimer disclaimer = 5;</code>
-       */
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.Disclaimer, food.menu.v1.FoodMenu.Disclaimer.Builder, food.menu.v1.FoodMenu.DisclaimerOrBuilder> 
-          getDisclaimerFieldBuilder() {
-        if (disclaimerBuilder_ == null) {
-          disclaimerBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
-              food.menu.v1.FoodMenu.Disclaimer, food.menu.v1.FoodMenu.Disclaimer.Builder, food.menu.v1.FoodMenu.DisclaimerOrBuilder>(
-                  getDisclaimer(),
-                  getParentForChildren(),
-                  isClean());
-          disclaimer_ = null;
-        }
-        return disclaimerBuilder_;
-      }
-
-      private com.google.protobuf.LazyStringArrayList menuItemIds_ =
-          com.google.protobuf.LazyStringArrayList.emptyList();
-      private void ensureMenuItemIdsIsMutable() {
-        if (!menuItemIds_.isModifiable()) {
-          menuItemIds_ = new com.google.protobuf.LazyStringArrayList(menuItemIds_);
-        }
-        bitField0_ |= 0x00000020;
-      }
-      /**
-       * <pre>
-       * IDs of items contained within this menu. Expects first-level menu items
-       * only.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated string menu_item_ids = 6;</code>
-       * @return A list containing the menuItemIds.
-       */
-      public com.google.protobuf.ProtocolStringList
-          getMenuItemIdsList() {
-        menuItemIds_.makeImmutable();
-        return menuItemIds_;
-      }
-      /**
-       * <pre>
-       * IDs of items contained within this menu. Expects first-level menu items
-       * only.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated string menu_item_ids = 6;</code>
-       * @return The count of menuItemIds.
-       */
-      public int getMenuItemIdsCount() {
-        return menuItemIds_.size();
-      }
-      /**
-       * <pre>
-       * IDs of items contained within this menu. Expects first-level menu items
-       * only.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated string menu_item_ids = 6;</code>
-       * @param index The index of the element to return.
-       * @return The menuItemIds at the given index.
-       */
-      public java.lang.String getMenuItemIds(int index) {
-        return menuItemIds_.get(index);
-      }
-      /**
-       * <pre>
-       * IDs of items contained within this menu. Expects first-level menu items
-       * only.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated string menu_item_ids = 6;</code>
-       * @param index The index of the value to return.
-       * @return The bytes of the menuItemIds at the given index.
-       */
-      public com.google.protobuf.ByteString
-          getMenuItemIdsBytes(int index) {
-        return menuItemIds_.getByteString(index);
-      }
-      /**
-       * <pre>
-       * IDs of items contained within this menu. Expects first-level menu items
-       * only.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated string menu_item_ids = 6;</code>
-       * @param index The index to set the value at.
-       * @param value The menuItemIds to set.
-       * @return This builder for chaining.
-       */
-      public Builder setMenuItemIds(
-          int index, java.lang.String value) {
-        if (value == null) { throw new NullPointerException(); }
-        ensureMenuItemIdsIsMutable();
-        menuItemIds_.set(index, value);
-        bitField0_ |= 0x00000020;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * IDs of items contained within this menu. Expects first-level menu items
-       * only.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated string menu_item_ids = 6;</code>
-       * @param value The menuItemIds to add.
-       * @return This builder for chaining.
-       */
-      public Builder addMenuItemIds(
-          java.lang.String value) {
-        if (value == null) { throw new NullPointerException(); }
-        ensureMenuItemIdsIsMutable();
-        menuItemIds_.add(value);
-        bitField0_ |= 0x00000020;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * IDs of items contained within this menu. Expects first-level menu items
-       * only.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated string menu_item_ids = 6;</code>
-       * @param values The menuItemIds to add.
-       * @return This builder for chaining.
-       */
-      public Builder addAllMenuItemIds(
-          java.lang.Iterable<java.lang.String> values) {
-        ensureMenuItemIdsIsMutable();
-        com.google.protobuf.AbstractMessageLite.Builder.addAll(
-            values, menuItemIds_);
-        bitField0_ |= 0x00000020;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * IDs of items contained within this menu. Expects first-level menu items
-       * only.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated string menu_item_ids = 6;</code>
-       * @return This builder for chaining.
-       */
-      public Builder clearMenuItemIds() {
-        menuItemIds_ =
-          com.google.protobuf.LazyStringArrayList.emptyList();
-        bitField0_ = (bitField0_ & ~0x00000020);;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * IDs of items contained within this menu. Expects first-level menu items
-       * only.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated string menu_item_ids = 6;</code>
-       * @param value The bytes of the menuItemIds to add.
-       * @return This builder for chaining.
-       */
-      public Builder addMenuItemIdsBytes(
-          com.google.protobuf.ByteString value) {
-        if (value == null) { throw new NullPointerException(); }
-        checkByteStringIsUtf8(value);
-        ensureMenuItemIdsIsMutable();
-        menuItemIds_.add(value);
-        bitField0_ |= 0x00000020;
-        onChanged();
-        return this;
-      }
-
-      private com.google.protobuf.LazyStringArrayList menuSectionIds_ =
-          com.google.protobuf.LazyStringArrayList.emptyList();
-      private void ensureMenuSectionIdsIsMutable() {
-        if (!menuSectionIds_.isModifiable()) {
-          menuSectionIds_ = new com.google.protobuf.LazyStringArrayList(menuSectionIds_);
-        }
-        bitField0_ |= 0x00000040;
-      }
-      /**
-       * <pre>
-       * IDs of sections contained within this menu. Expects first-level menu
-       * sections only.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated string menu_section_ids = 7;</code>
-       * @return A list containing the menuSectionIds.
-       */
-      public com.google.protobuf.ProtocolStringList
-          getMenuSectionIdsList() {
-        menuSectionIds_.makeImmutable();
-        return menuSectionIds_;
-      }
-      /**
-       * <pre>
-       * IDs of sections contained within this menu. Expects first-level menu
-       * sections only.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated string menu_section_ids = 7;</code>
-       * @return The count of menuSectionIds.
-       */
-      public int getMenuSectionIdsCount() {
-        return menuSectionIds_.size();
-      }
-      /**
-       * <pre>
-       * IDs of sections contained within this menu. Expects first-level menu
-       * sections only.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated string menu_section_ids = 7;</code>
-       * @param index The index of the element to return.
-       * @return The menuSectionIds at the given index.
-       */
-      public java.lang.String getMenuSectionIds(int index) {
-        return menuSectionIds_.get(index);
-      }
-      /**
-       * <pre>
-       * IDs of sections contained within this menu. Expects first-level menu
-       * sections only.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated string menu_section_ids = 7;</code>
-       * @param index The index of the value to return.
-       * @return The bytes of the menuSectionIds at the given index.
-       */
-      public com.google.protobuf.ByteString
-          getMenuSectionIdsBytes(int index) {
-        return menuSectionIds_.getByteString(index);
-      }
-      /**
-       * <pre>
-       * IDs of sections contained within this menu. Expects first-level menu
-       * sections only.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated string menu_section_ids = 7;</code>
-       * @param index The index to set the value at.
-       * @param value The menuSectionIds to set.
-       * @return This builder for chaining.
-       */
-      public Builder setMenuSectionIds(
-          int index, java.lang.String value) {
-        if (value == null) { throw new NullPointerException(); }
-        ensureMenuSectionIdsIsMutable();
-        menuSectionIds_.set(index, value);
-        bitField0_ |= 0x00000040;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * IDs of sections contained within this menu. Expects first-level menu
-       * sections only.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated string menu_section_ids = 7;</code>
-       * @param value The menuSectionIds to add.
-       * @return This builder for chaining.
-       */
-      public Builder addMenuSectionIds(
-          java.lang.String value) {
-        if (value == null) { throw new NullPointerException(); }
-        ensureMenuSectionIdsIsMutable();
-        menuSectionIds_.add(value);
-        bitField0_ |= 0x00000040;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * IDs of sections contained within this menu. Expects first-level menu
-       * sections only.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated string menu_section_ids = 7;</code>
-       * @param values The menuSectionIds to add.
-       * @return This builder for chaining.
-       */
-      public Builder addAllMenuSectionIds(
-          java.lang.Iterable<java.lang.String> values) {
-        ensureMenuSectionIdsIsMutable();
-        com.google.protobuf.AbstractMessageLite.Builder.addAll(
-            values, menuSectionIds_);
-        bitField0_ |= 0x00000040;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * IDs of sections contained within this menu. Expects first-level menu
-       * sections only.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated string menu_section_ids = 7;</code>
-       * @return This builder for chaining.
-       */
-      public Builder clearMenuSectionIds() {
-        menuSectionIds_ =
-          com.google.protobuf.LazyStringArrayList.emptyList();
-        bitField0_ = (bitField0_ & ~0x00000040);;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * IDs of sections contained within this menu. Expects first-level menu
-       * sections only.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated string menu_section_ids = 7;</code>
-       * @param value The bytes of the menuSectionIds to add.
-       * @return This builder for chaining.
-       */
-      public Builder addMenuSectionIdsBytes(
-          com.google.protobuf.ByteString value) {
-        if (value == null) { throw new NullPointerException(); }
-        checkByteStringIsUtf8(value);
-        ensureMenuSectionIdsIsMutable();
-        menuSectionIds_.add(value);
-        bitField0_ |= 0x00000040;
-        onChanged();
-        return this;
-      }
-
-      private com.google.protobuf.Timestamp lastMerchantUpdateTime_;
-      private com.google.protobuf.SingleFieldBuilderV3<
-          com.google.protobuf.Timestamp, com.google.protobuf.Timestamp.Builder, com.google.protobuf.TimestampOrBuilder> lastMerchantUpdateTimeBuilder_;
-      /**
-       * <pre>
-       * Timestamp when this Menu or any of its contents was last updated by the
-       * restaurant; i.e. a date to be associated with the phrase “accurate as of
-       * date”.
-       * Optional.
-       * </pre>
-       *
-       * <code>.google.protobuf.Timestamp last_merchant_update_time = 8;</code>
-       * @return Whether the lastMerchantUpdateTime field is set.
-       */
-      public boolean hasLastMerchantUpdateTime() {
-        return ((bitField0_ & 0x00000080) != 0);
-      }
-      /**
-       * <pre>
-       * Timestamp when this Menu or any of its contents was last updated by the
-       * restaurant; i.e. a date to be associated with the phrase “accurate as of
-       * date”.
-       * Optional.
-       * </pre>
-       *
-       * <code>.google.protobuf.Timestamp last_merchant_update_time = 8;</code>
-       * @return The lastMerchantUpdateTime.
-       */
-      public com.google.protobuf.Timestamp getLastMerchantUpdateTime() {
-        if (lastMerchantUpdateTimeBuilder_ == null) {
-          return lastMerchantUpdateTime_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : lastMerchantUpdateTime_;
-        } else {
-          return lastMerchantUpdateTimeBuilder_.getMessage();
-        }
-      }
-      /**
-       * <pre>
-       * Timestamp when this Menu or any of its contents was last updated by the
-       * restaurant; i.e. a date to be associated with the phrase “accurate as of
-       * date”.
-       * Optional.
-       * </pre>
-       *
-       * <code>.google.protobuf.Timestamp last_merchant_update_time = 8;</code>
-       */
-      public Builder setLastMerchantUpdateTime(com.google.protobuf.Timestamp value) {
-        if (lastMerchantUpdateTimeBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          lastMerchantUpdateTime_ = value;
-        } else {
-          lastMerchantUpdateTimeBuilder_.setMessage(value);
-        }
-        bitField0_ |= 0x00000080;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Timestamp when this Menu or any of its contents was last updated by the
-       * restaurant; i.e. a date to be associated with the phrase “accurate as of
-       * date”.
-       * Optional.
-       * </pre>
-       *
-       * <code>.google.protobuf.Timestamp last_merchant_update_time = 8;</code>
-       */
-      public Builder setLastMerchantUpdateTime(
-          com.google.protobuf.Timestamp.Builder builderForValue) {
-        if (lastMerchantUpdateTimeBuilder_ == null) {
-          lastMerchantUpdateTime_ = builderForValue.build();
-        } else {
-          lastMerchantUpdateTimeBuilder_.setMessage(builderForValue.build());
-        }
-        bitField0_ |= 0x00000080;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Timestamp when this Menu or any of its contents was last updated by the
-       * restaurant; i.e. a date to be associated with the phrase “accurate as of
-       * date”.
-       * Optional.
-       * </pre>
-       *
-       * <code>.google.protobuf.Timestamp last_merchant_update_time = 8;</code>
-       */
-      public Builder mergeLastMerchantUpdateTime(com.google.protobuf.Timestamp value) {
-        if (lastMerchantUpdateTimeBuilder_ == null) {
-          if (((bitField0_ & 0x00000080) != 0) &&
-            lastMerchantUpdateTime_ != null &&
-            lastMerchantUpdateTime_ != com.google.protobuf.Timestamp.getDefaultInstance()) {
-            getLastMerchantUpdateTimeBuilder().mergeFrom(value);
-          } else {
-            lastMerchantUpdateTime_ = value;
-          }
-        } else {
-          lastMerchantUpdateTimeBuilder_.mergeFrom(value);
-        }
-        bitField0_ |= 0x00000080;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Timestamp when this Menu or any of its contents was last updated by the
-       * restaurant; i.e. a date to be associated with the phrase “accurate as of
-       * date”.
-       * Optional.
-       * </pre>
-       *
-       * <code>.google.protobuf.Timestamp last_merchant_update_time = 8;</code>
-       */
-      public Builder clearLastMerchantUpdateTime() {
-        bitField0_ = (bitField0_ & ~0x00000080);
-        lastMerchantUpdateTime_ = null;
-        if (lastMerchantUpdateTimeBuilder_ != null) {
-          lastMerchantUpdateTimeBuilder_.dispose();
-          lastMerchantUpdateTimeBuilder_ = null;
-        }
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Timestamp when this Menu or any of its contents was last updated by the
-       * restaurant; i.e. a date to be associated with the phrase “accurate as of
-       * date”.
-       * Optional.
-       * </pre>
-       *
-       * <code>.google.protobuf.Timestamp last_merchant_update_time = 8;</code>
-       */
-      public com.google.protobuf.Timestamp.Builder getLastMerchantUpdateTimeBuilder() {
-        bitField0_ |= 0x00000080;
-        onChanged();
-        return getLastMerchantUpdateTimeFieldBuilder().getBuilder();
-      }
-      /**
-       * <pre>
-       * Timestamp when this Menu or any of its contents was last updated by the
-       * restaurant; i.e. a date to be associated with the phrase “accurate as of
-       * date”.
-       * Optional.
-       * </pre>
-       *
-       * <code>.google.protobuf.Timestamp last_merchant_update_time = 8;</code>
-       */
-      public com.google.protobuf.TimestampOrBuilder getLastMerchantUpdateTimeOrBuilder() {
-        if (lastMerchantUpdateTimeBuilder_ != null) {
-          return lastMerchantUpdateTimeBuilder_.getMessageOrBuilder();
-        } else {
-          return lastMerchantUpdateTime_ == null ?
-              com.google.protobuf.Timestamp.getDefaultInstance() : lastMerchantUpdateTime_;
-        }
-      }
-      /**
-       * <pre>
-       * Timestamp when this Menu or any of its contents was last updated by the
-       * restaurant; i.e. a date to be associated with the phrase “accurate as of
-       * date”.
-       * Optional.
-       * </pre>
-       *
-       * <code>.google.protobuf.Timestamp last_merchant_update_time = 8;</code>
-       */
-      private com.google.protobuf.SingleFieldBuilderV3<
-          com.google.protobuf.Timestamp, com.google.protobuf.Timestamp.Builder, com.google.protobuf.TimestampOrBuilder> 
-          getLastMerchantUpdateTimeFieldBuilder() {
-        if (lastMerchantUpdateTimeBuilder_ == null) {
-          lastMerchantUpdateTimeBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
-              com.google.protobuf.Timestamp, com.google.protobuf.Timestamp.Builder, com.google.protobuf.TimestampOrBuilder>(
-                  getLastMerchantUpdateTime(),
-                  getParentForChildren(),
-                  isClean());
-          lastMerchantUpdateTime_ = null;
-        }
-        return lastMerchantUpdateTimeBuilder_;
-      }
-      @java.lang.Override
-      public final Builder setUnknownFields(
-          final com.google.protobuf.UnknownFieldSet unknownFields) {
-        return super.setUnknownFields(unknownFields);
-      }
-
-      @java.lang.Override
-      public final Builder mergeUnknownFields(
-          final com.google.protobuf.UnknownFieldSet unknownFields) {
-        return super.mergeUnknownFields(unknownFields);
-      }
-
-
-      // @@protoc_insertion_point(builder_scope:food.menu.v1.Menu)
-    }
-
-    // @@protoc_insertion_point(class_scope:food.menu.v1.Menu)
-    private static final food.menu.v1.FoodMenu.Menu DEFAULT_INSTANCE;
-    static {
-      DEFAULT_INSTANCE = new food.menu.v1.FoodMenu.Menu();
-    }
-
-    public static food.menu.v1.FoodMenu.Menu getDefaultInstance() {
-      return DEFAULT_INSTANCE;
-    }
-
-    private static final com.google.protobuf.Parser<Menu>
-        PARSER = new com.google.protobuf.AbstractParser<Menu>() {
-      @java.lang.Override
-      public Menu parsePartialFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws com.google.protobuf.InvalidProtocolBufferException {
-        Builder builder = newBuilder();
-        try {
-          builder.mergeFrom(input, extensionRegistry);
-        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          throw e.setUnfinishedMessage(builder.buildPartial());
-        } catch (com.google.protobuf.UninitializedMessageException e) {
-          throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
-        } catch (java.io.IOException e) {
-          throw new com.google.protobuf.InvalidProtocolBufferException(e)
-              .setUnfinishedMessage(builder.buildPartial());
-        }
-        return builder.buildPartial();
-      }
-    };
-
-    public static com.google.protobuf.Parser<Menu> parser() {
-      return PARSER;
-    }
-
-    @java.lang.Override
-    public com.google.protobuf.Parser<Menu> getParserForType() {
-      return PARSER;
-    }
-
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.Menu getDefaultInstanceForType() {
-      return DEFAULT_INSTANCE;
-    }
-
-  }
-
-  public interface MenuSectionOrBuilder extends
-      // @@protoc_insertion_point(interface_extends:food.menu.v1.MenuSection)
-      com.google.protobuf.MessageOrBuilder {
-
-    /**
-     * <pre>
-     * An opaque string from an partner which uniquely identifies the MenuSection
-     * within the partner feed.
-     * Required.
-     * </pre>
-     *
-     * <code>string menu_section_id = 1;</code>
-     * @return The menuSectionId.
-     */
-    java.lang.String getMenuSectionId();
-    /**
-     * <pre>
-     * An opaque string from an partner which uniquely identifies the MenuSection
-     * within the partner feed.
-     * Required.
-     * </pre>
-     *
-     * <code>string menu_section_id = 1;</code>
-     * @return The bytes for menuSectionId.
-     */
-    com.google.protobuf.ByteString
-        getMenuSectionIdBytes();
-
-    /**
-     * <pre>
-     * The name that can identify the MenuSection when a user is browsing the
-     * menu.
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField display_name = 2;</code>
-     * @return Whether the displayName field is set.
-     */
-    boolean hasDisplayName();
-    /**
-     * <pre>
-     * The name that can identify the MenuSection when a user is browsing the
-     * menu.
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField display_name = 2;</code>
-     * @return The displayName.
-     */
-    food.menu.v1.FoodMenu.TextField getDisplayName();
-    /**
-     * <pre>
-     * The name that can identify the MenuSection when a user is browsing the
-     * menu.
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField display_name = 2;</code>
-     */
-    food.menu.v1.FoodMenu.TextFieldOrBuilder getDisplayNameOrBuilder();
-
-    /**
-     * <pre>
-     * A description of the menu section.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField description = 3;</code>
-     * @return Whether the description field is set.
-     */
-    boolean hasDescription();
-    /**
-     * <pre>
-     * A description of the menu section.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField description = 3;</code>
-     * @return The description.
-     */
-    food.menu.v1.FoodMenu.TextField getDescription();
-    /**
-     * <pre>
-     * A description of the menu section.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField description = 3;</code>
-     */
-    food.menu.v1.FoodMenu.TextFieldOrBuilder getDescriptionOrBuilder();
-
-    /**
-     * <pre>
-     * Image(s) of the menu section.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Image images = 4;</code>
-     */
-    java.util.List<food.menu.v1.FoodMenu.Image> 
-        getImagesList();
-    /**
-     * <pre>
-     * Image(s) of the menu section.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Image images = 4;</code>
-     */
-    food.menu.v1.FoodMenu.Image getImages(int index);
-    /**
-     * <pre>
-     * Image(s) of the menu section.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Image images = 4;</code>
-     */
-    int getImagesCount();
-    /**
-     * <pre>
-     * Image(s) of the menu section.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Image images = 4;</code>
-     */
-    java.util.List<? extends food.menu.v1.FoodMenu.ImageOrBuilder> 
-        getImagesOrBuilderList();
-    /**
-     * <pre>
-     * Image(s) of the menu section.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Image images = 4;</code>
-     */
-    food.menu.v1.FoodMenu.ImageOrBuilder getImagesOrBuilder(
-        int index);
-
-    /**
-     * <pre>
-     * IDs of MenuItem entities that correspond to this MenuSection entity. A
-     * section is expected to have at least 1 item if it does not contain any
-     * sub-sections.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated string menu_item_ids = 6;</code>
-     * @return A list containing the menuItemIds.
-     */
-    java.util.List<java.lang.String>
-        getMenuItemIdsList();
-    /**
-     * <pre>
-     * IDs of MenuItem entities that correspond to this MenuSection entity. A
-     * section is expected to have at least 1 item if it does not contain any
-     * sub-sections.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated string menu_item_ids = 6;</code>
-     * @return The count of menuItemIds.
-     */
-    int getMenuItemIdsCount();
-    /**
-     * <pre>
-     * IDs of MenuItem entities that correspond to this MenuSection entity. A
-     * section is expected to have at least 1 item if it does not contain any
-     * sub-sections.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated string menu_item_ids = 6;</code>
-     * @param index The index of the element to return.
-     * @return The menuItemIds at the given index.
-     */
-    java.lang.String getMenuItemIds(int index);
-    /**
-     * <pre>
-     * IDs of MenuItem entities that correspond to this MenuSection entity. A
-     * section is expected to have at least 1 item if it does not contain any
-     * sub-sections.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated string menu_item_ids = 6;</code>
-     * @param index The index of the value to return.
-     * @return The bytes of the menuItemIds at the given index.
-     */
-    com.google.protobuf.ByteString
-        getMenuItemIdsBytes(int index);
-
-    /**
-     * <pre>
-     * Child MenuSections (sub-sections) that correspond to this MenuSection
-     * entity.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated string menu_section_ids = 7;</code>
-     * @return A list containing the menuSectionIds.
-     */
-    java.util.List<java.lang.String>
-        getMenuSectionIdsList();
-    /**
-     * <pre>
-     * Child MenuSections (sub-sections) that correspond to this MenuSection
-     * entity.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated string menu_section_ids = 7;</code>
-     * @return The count of menuSectionIds.
-     */
-    int getMenuSectionIdsCount();
-    /**
-     * <pre>
-     * Child MenuSections (sub-sections) that correspond to this MenuSection
-     * entity.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated string menu_section_ids = 7;</code>
-     * @param index The index of the element to return.
-     * @return The menuSectionIds at the given index.
-     */
-    java.lang.String getMenuSectionIds(int index);
-    /**
-     * <pre>
-     * Child MenuSections (sub-sections) that correspond to this MenuSection
-     * entity.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated string menu_section_ids = 7;</code>
-     * @param index The index of the value to return.
-     * @return The bytes of the menuSectionIds at the given index.
-     */
-    com.google.protobuf.ByteString
-        getMenuSectionIdsBytes(int index);
-  }
-  /**
-   * <pre>
-   * A menu section is a grouping of items on a menu. Separate MenuSections are
-   * usually created for each logical grouping of items on a menu. For example,
-   * meal course type (Appetizer, Main, Dessert) and food categories (Burgers,
-   * Drinks) are typical sections.
-   * </pre>
-   *
-   * Protobuf type {@code food.menu.v1.MenuSection}
-   */
-  public static final class MenuSection extends
-      com.google.protobuf.GeneratedMessageV3 implements
-      // @@protoc_insertion_point(message_implements:food.menu.v1.MenuSection)
-      MenuSectionOrBuilder {
-  private static final long serialVersionUID = 0L;
-    // Use MenuSection.newBuilder() to construct.
-    private MenuSection(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
-      super(builder);
-    }
-    private MenuSection() {
-      menuSectionId_ = "";
-      images_ = java.util.Collections.emptyList();
-      menuItemIds_ =
-          com.google.protobuf.LazyStringArrayList.emptyList();
-      menuSectionIds_ =
-          com.google.protobuf.LazyStringArrayList.emptyList();
-    }
-
-    @java.lang.Override
-    @SuppressWarnings({"unused"})
-    protected java.lang.Object newInstance(
-        UnusedPrivateParameter unused) {
-      return new MenuSection();
-    }
-
-    public static final com.google.protobuf.Descriptors.Descriptor
-        getDescriptor() {
-      return food.menu.v1.FoodMenu.internal_static_food_menu_v1_MenuSection_descriptor;
-    }
-
-    @java.lang.Override
-    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-        internalGetFieldAccessorTable() {
-      return food.menu.v1.FoodMenu.internal_static_food_menu_v1_MenuSection_fieldAccessorTable
-          .ensureFieldAccessorsInitialized(
-              food.menu.v1.FoodMenu.MenuSection.class, food.menu.v1.FoodMenu.MenuSection.Builder.class);
-    }
-
-    public static final int MENU_SECTION_ID_FIELD_NUMBER = 1;
-    @SuppressWarnings("serial")
-    private volatile java.lang.Object menuSectionId_ = "";
-    /**
-     * <pre>
-     * An opaque string from an partner which uniquely identifies the MenuSection
-     * within the partner feed.
-     * Required.
-     * </pre>
-     *
-     * <code>string menu_section_id = 1;</code>
-     * @return The menuSectionId.
-     */
-    @java.lang.Override
-    public java.lang.String getMenuSectionId() {
-      java.lang.Object ref = menuSectionId_;
-      if (ref instanceof java.lang.String) {
-        return (java.lang.String) ref;
-      } else {
-        com.google.protobuf.ByteString bs = 
-            (com.google.protobuf.ByteString) ref;
-        java.lang.String s = bs.toStringUtf8();
-        menuSectionId_ = s;
-        return s;
-      }
-    }
-    /**
-     * <pre>
-     * An opaque string from an partner which uniquely identifies the MenuSection
-     * within the partner feed.
-     * Required.
-     * </pre>
-     *
-     * <code>string menu_section_id = 1;</code>
-     * @return The bytes for menuSectionId.
-     */
-    @java.lang.Override
-    public com.google.protobuf.ByteString
-        getMenuSectionIdBytes() {
-      java.lang.Object ref = menuSectionId_;
-      if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
-            com.google.protobuf.ByteString.copyFromUtf8(
-                (java.lang.String) ref);
-        menuSectionId_ = b;
-        return b;
-      } else {
-        return (com.google.protobuf.ByteString) ref;
-      }
-    }
-
-    public static final int DISPLAY_NAME_FIELD_NUMBER = 2;
-    private food.menu.v1.FoodMenu.TextField displayName_;
-    /**
-     * <pre>
-     * The name that can identify the MenuSection when a user is browsing the
-     * menu.
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField display_name = 2;</code>
-     * @return Whether the displayName field is set.
-     */
-    @java.lang.Override
-    public boolean hasDisplayName() {
-      return displayName_ != null;
-    }
-    /**
-     * <pre>
-     * The name that can identify the MenuSection when a user is browsing the
-     * menu.
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField display_name = 2;</code>
-     * @return The displayName.
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.TextField getDisplayName() {
-      return displayName_ == null ? food.menu.v1.FoodMenu.TextField.getDefaultInstance() : displayName_;
-    }
-    /**
-     * <pre>
-     * The name that can identify the MenuSection when a user is browsing the
-     * menu.
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField display_name = 2;</code>
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.TextFieldOrBuilder getDisplayNameOrBuilder() {
-      return displayName_ == null ? food.menu.v1.FoodMenu.TextField.getDefaultInstance() : displayName_;
-    }
-
-    public static final int DESCRIPTION_FIELD_NUMBER = 3;
-    private food.menu.v1.FoodMenu.TextField description_;
-    /**
-     * <pre>
-     * A description of the menu section.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField description = 3;</code>
-     * @return Whether the description field is set.
-     */
-    @java.lang.Override
-    public boolean hasDescription() {
-      return description_ != null;
-    }
-    /**
-     * <pre>
-     * A description of the menu section.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField description = 3;</code>
-     * @return The description.
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.TextField getDescription() {
-      return description_ == null ? food.menu.v1.FoodMenu.TextField.getDefaultInstance() : description_;
-    }
-    /**
-     * <pre>
-     * A description of the menu section.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField description = 3;</code>
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.TextFieldOrBuilder getDescriptionOrBuilder() {
-      return description_ == null ? food.menu.v1.FoodMenu.TextField.getDefaultInstance() : description_;
-    }
-
-    public static final int IMAGES_FIELD_NUMBER = 4;
-    @SuppressWarnings("serial")
-    private java.util.List<food.menu.v1.FoodMenu.Image> images_;
-    /**
-     * <pre>
-     * Image(s) of the menu section.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Image images = 4;</code>
-     */
-    @java.lang.Override
-    public java.util.List<food.menu.v1.FoodMenu.Image> getImagesList() {
-      return images_;
-    }
-    /**
-     * <pre>
-     * Image(s) of the menu section.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Image images = 4;</code>
-     */
-    @java.lang.Override
-    public java.util.List<? extends food.menu.v1.FoodMenu.ImageOrBuilder> 
-        getImagesOrBuilderList() {
-      return images_;
-    }
-    /**
-     * <pre>
-     * Image(s) of the menu section.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Image images = 4;</code>
-     */
-    @java.lang.Override
-    public int getImagesCount() {
-      return images_.size();
-    }
-    /**
-     * <pre>
-     * Image(s) of the menu section.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Image images = 4;</code>
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.Image getImages(int index) {
-      return images_.get(index);
-    }
-    /**
-     * <pre>
-     * Image(s) of the menu section.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Image images = 4;</code>
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.ImageOrBuilder getImagesOrBuilder(
-        int index) {
-      return images_.get(index);
-    }
-
-    public static final int MENU_ITEM_IDS_FIELD_NUMBER = 6;
-    @SuppressWarnings("serial")
-    private com.google.protobuf.LazyStringArrayList menuItemIds_ =
-        com.google.protobuf.LazyStringArrayList.emptyList();
-    /**
-     * <pre>
-     * IDs of MenuItem entities that correspond to this MenuSection entity. A
-     * section is expected to have at least 1 item if it does not contain any
-     * sub-sections.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated string menu_item_ids = 6;</code>
-     * @return A list containing the menuItemIds.
-     */
-    public com.google.protobuf.ProtocolStringList
-        getMenuItemIdsList() {
-      return menuItemIds_;
-    }
-    /**
-     * <pre>
-     * IDs of MenuItem entities that correspond to this MenuSection entity. A
-     * section is expected to have at least 1 item if it does not contain any
-     * sub-sections.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated string menu_item_ids = 6;</code>
-     * @return The count of menuItemIds.
-     */
-    public int getMenuItemIdsCount() {
-      return menuItemIds_.size();
-    }
-    /**
-     * <pre>
-     * IDs of MenuItem entities that correspond to this MenuSection entity. A
-     * section is expected to have at least 1 item if it does not contain any
-     * sub-sections.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated string menu_item_ids = 6;</code>
-     * @param index The index of the element to return.
-     * @return The menuItemIds at the given index.
-     */
-    public java.lang.String getMenuItemIds(int index) {
-      return menuItemIds_.get(index);
-    }
-    /**
-     * <pre>
-     * IDs of MenuItem entities that correspond to this MenuSection entity. A
-     * section is expected to have at least 1 item if it does not contain any
-     * sub-sections.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated string menu_item_ids = 6;</code>
-     * @param index The index of the value to return.
-     * @return The bytes of the menuItemIds at the given index.
-     */
-    public com.google.protobuf.ByteString
-        getMenuItemIdsBytes(int index) {
-      return menuItemIds_.getByteString(index);
-    }
-
-    public static final int MENU_SECTION_IDS_FIELD_NUMBER = 7;
-    @SuppressWarnings("serial")
-    private com.google.protobuf.LazyStringArrayList menuSectionIds_ =
-        com.google.protobuf.LazyStringArrayList.emptyList();
-    /**
-     * <pre>
-     * Child MenuSections (sub-sections) that correspond to this MenuSection
-     * entity.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated string menu_section_ids = 7;</code>
-     * @return A list containing the menuSectionIds.
-     */
-    public com.google.protobuf.ProtocolStringList
-        getMenuSectionIdsList() {
-      return menuSectionIds_;
-    }
-    /**
-     * <pre>
-     * Child MenuSections (sub-sections) that correspond to this MenuSection
-     * entity.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated string menu_section_ids = 7;</code>
-     * @return The count of menuSectionIds.
-     */
-    public int getMenuSectionIdsCount() {
-      return menuSectionIds_.size();
-    }
-    /**
-     * <pre>
-     * Child MenuSections (sub-sections) that correspond to this MenuSection
-     * entity.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated string menu_section_ids = 7;</code>
-     * @param index The index of the element to return.
-     * @return The menuSectionIds at the given index.
-     */
-    public java.lang.String getMenuSectionIds(int index) {
-      return menuSectionIds_.get(index);
-    }
-    /**
-     * <pre>
-     * Child MenuSections (sub-sections) that correspond to this MenuSection
-     * entity.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated string menu_section_ids = 7;</code>
-     * @param index The index of the value to return.
-     * @return The bytes of the menuSectionIds at the given index.
-     */
-    public com.google.protobuf.ByteString
-        getMenuSectionIdsBytes(int index) {
-      return menuSectionIds_.getByteString(index);
-    }
-
-    private byte memoizedIsInitialized = -1;
-    @java.lang.Override
-    public final boolean isInitialized() {
-      byte isInitialized = memoizedIsInitialized;
-      if (isInitialized == 1) return true;
-      if (isInitialized == 0) return false;
-
-      memoizedIsInitialized = 1;
-      return true;
-    }
-
-    @java.lang.Override
-    public void writeTo(com.google.protobuf.CodedOutputStream output)
-                        throws java.io.IOException {
-      if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(menuSectionId_)) {
-        com.google.protobuf.GeneratedMessageV3.writeString(output, 1, menuSectionId_);
-      }
-      if (displayName_ != null) {
-        output.writeMessage(2, getDisplayName());
-      }
-      if (description_ != null) {
-        output.writeMessage(3, getDescription());
-      }
-      for (int i = 0; i < images_.size(); i++) {
-        output.writeMessage(4, images_.get(i));
-      }
-      for (int i = 0; i < menuItemIds_.size(); i++) {
-        com.google.protobuf.GeneratedMessageV3.writeString(output, 6, menuItemIds_.getRaw(i));
-      }
-      for (int i = 0; i < menuSectionIds_.size(); i++) {
-        com.google.protobuf.GeneratedMessageV3.writeString(output, 7, menuSectionIds_.getRaw(i));
-      }
-      getUnknownFields().writeTo(output);
-    }
-
-    @java.lang.Override
-    public int getSerializedSize() {
-      int size = memoizedSize;
-      if (size != -1) return size;
-
-      size = 0;
-      if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(menuSectionId_)) {
-        size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, menuSectionId_);
-      }
-      if (displayName_ != null) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(2, getDisplayName());
-      }
-      if (description_ != null) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(3, getDescription());
-      }
-      for (int i = 0; i < images_.size(); i++) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(4, images_.get(i));
-      }
-      {
-        int dataSize = 0;
-        for (int i = 0; i < menuItemIds_.size(); i++) {
-          dataSize += computeStringSizeNoTag(menuItemIds_.getRaw(i));
-        }
-        size += dataSize;
-        size += 1 * getMenuItemIdsList().size();
-      }
-      {
-        int dataSize = 0;
-        for (int i = 0; i < menuSectionIds_.size(); i++) {
-          dataSize += computeStringSizeNoTag(menuSectionIds_.getRaw(i));
-        }
-        size += dataSize;
-        size += 1 * getMenuSectionIdsList().size();
-      }
-      size += getUnknownFields().getSerializedSize();
-      memoizedSize = size;
-      return size;
-    }
-
-    @java.lang.Override
-    public boolean equals(final java.lang.Object obj) {
-      if (obj == this) {
-       return true;
-      }
-      if (!(obj instanceof food.menu.v1.FoodMenu.MenuSection)) {
-        return super.equals(obj);
-      }
-      food.menu.v1.FoodMenu.MenuSection other = (food.menu.v1.FoodMenu.MenuSection) obj;
-
-      if (!getMenuSectionId()
-          .equals(other.getMenuSectionId())) return false;
-      if (hasDisplayName() != other.hasDisplayName()) return false;
-      if (hasDisplayName()) {
-        if (!getDisplayName()
-            .equals(other.getDisplayName())) return false;
-      }
-      if (hasDescription() != other.hasDescription()) return false;
-      if (hasDescription()) {
-        if (!getDescription()
-            .equals(other.getDescription())) return false;
-      }
-      if (!getImagesList()
-          .equals(other.getImagesList())) return false;
-      if (!getMenuItemIdsList()
-          .equals(other.getMenuItemIdsList())) return false;
-      if (!getMenuSectionIdsList()
-          .equals(other.getMenuSectionIdsList())) return false;
-      if (!getUnknownFields().equals(other.getUnknownFields())) return false;
-      return true;
-    }
-
-    @java.lang.Override
-    public int hashCode() {
-      if (memoizedHashCode != 0) {
-        return memoizedHashCode;
-      }
-      int hash = 41;
-      hash = (19 * hash) + getDescriptor().hashCode();
-      hash = (37 * hash) + MENU_SECTION_ID_FIELD_NUMBER;
-      hash = (53 * hash) + getMenuSectionId().hashCode();
-      if (hasDisplayName()) {
-        hash = (37 * hash) + DISPLAY_NAME_FIELD_NUMBER;
-        hash = (53 * hash) + getDisplayName().hashCode();
-      }
-      if (hasDescription()) {
-        hash = (37 * hash) + DESCRIPTION_FIELD_NUMBER;
-        hash = (53 * hash) + getDescription().hashCode();
-      }
-      if (getImagesCount() > 0) {
-        hash = (37 * hash) + IMAGES_FIELD_NUMBER;
-        hash = (53 * hash) + getImagesList().hashCode();
-      }
-      if (getMenuItemIdsCount() > 0) {
-        hash = (37 * hash) + MENU_ITEM_IDS_FIELD_NUMBER;
-        hash = (53 * hash) + getMenuItemIdsList().hashCode();
-      }
-      if (getMenuSectionIdsCount() > 0) {
-        hash = (37 * hash) + MENU_SECTION_IDS_FIELD_NUMBER;
-        hash = (53 * hash) + getMenuSectionIdsList().hashCode();
-      }
-      hash = (29 * hash) + getUnknownFields().hashCode();
-      memoizedHashCode = hash;
-      return hash;
-    }
-
-    public static food.menu.v1.FoodMenu.MenuSection parseFrom(
-        java.nio.ByteBuffer data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.MenuSection parseFrom(
-        java.nio.ByteBuffer data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.MenuSection parseFrom(
-        com.google.protobuf.ByteString data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.MenuSection parseFrom(
-        com.google.protobuf.ByteString data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.MenuSection parseFrom(byte[] data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.MenuSection parseFrom(
-        byte[] data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.MenuSection parseFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.MenuSection parseFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.MenuSection parseDelimitedFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseDelimitedWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.MenuSection parseDelimitedFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.MenuSection parseFrom(
-        com.google.protobuf.CodedInputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.MenuSection parseFrom(
-        com.google.protobuf.CodedInputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input, extensionRegistry);
-    }
-
-    @java.lang.Override
-    public Builder newBuilderForType() { return newBuilder(); }
-    public static Builder newBuilder() {
-      return DEFAULT_INSTANCE.toBuilder();
-    }
-    public static Builder newBuilder(food.menu.v1.FoodMenu.MenuSection prototype) {
-      return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
-    }
-    @java.lang.Override
-    public Builder toBuilder() {
-      return this == DEFAULT_INSTANCE
-          ? new Builder() : new Builder().mergeFrom(this);
-    }
-
-    @java.lang.Override
-    protected Builder newBuilderForType(
-        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-      Builder builder = new Builder(parent);
-      return builder;
-    }
-    /**
-     * <pre>
-     * A menu section is a grouping of items on a menu. Separate MenuSections are
-     * usually created for each logical grouping of items on a menu. For example,
-     * meal course type (Appetizer, Main, Dessert) and food categories (Burgers,
-     * Drinks) are typical sections.
-     * </pre>
-     *
-     * Protobuf type {@code food.menu.v1.MenuSection}
-     */
-    public static final class Builder extends
-        com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
-        // @@protoc_insertion_point(builder_implements:food.menu.v1.MenuSection)
-        food.menu.v1.FoodMenu.MenuSectionOrBuilder {
-      public static final com.google.protobuf.Descriptors.Descriptor
-          getDescriptor() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_MenuSection_descriptor;
-      }
-
-      @java.lang.Override
-      protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-          internalGetFieldAccessorTable() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_MenuSection_fieldAccessorTable
-            .ensureFieldAccessorsInitialized(
-                food.menu.v1.FoodMenu.MenuSection.class, food.menu.v1.FoodMenu.MenuSection.Builder.class);
-      }
-
-      // Construct using food.menu.v1.FoodMenu.MenuSection.newBuilder()
-      private Builder() {
-
-      }
-
-      private Builder(
-          com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-        super(parent);
-
-      }
-      @java.lang.Override
-      public Builder clear() {
-        super.clear();
-        bitField0_ = 0;
-        menuSectionId_ = "";
-        displayName_ = null;
-        if (displayNameBuilder_ != null) {
-          displayNameBuilder_.dispose();
-          displayNameBuilder_ = null;
-        }
-        description_ = null;
-        if (descriptionBuilder_ != null) {
-          descriptionBuilder_.dispose();
-          descriptionBuilder_ = null;
-        }
-        if (imagesBuilder_ == null) {
-          images_ = java.util.Collections.emptyList();
-        } else {
-          images_ = null;
-          imagesBuilder_.clear();
-        }
-        bitField0_ = (bitField0_ & ~0x00000008);
-        menuItemIds_ =
-            com.google.protobuf.LazyStringArrayList.emptyList();
-        menuSectionIds_ =
-            com.google.protobuf.LazyStringArrayList.emptyList();
-        return this;
-      }
-
-      @java.lang.Override
-      public com.google.protobuf.Descriptors.Descriptor
-          getDescriptorForType() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_MenuSection_descriptor;
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.MenuSection getDefaultInstanceForType() {
-        return food.menu.v1.FoodMenu.MenuSection.getDefaultInstance();
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.MenuSection build() {
-        food.menu.v1.FoodMenu.MenuSection result = buildPartial();
-        if (!result.isInitialized()) {
-          throw newUninitializedMessageException(result);
-        }
-        return result;
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.MenuSection buildPartial() {
-        food.menu.v1.FoodMenu.MenuSection result = new food.menu.v1.FoodMenu.MenuSection(this);
-        buildPartialRepeatedFields(result);
-        if (bitField0_ != 0) { buildPartial0(result); }
-        onBuilt();
-        return result;
-      }
-
-      private void buildPartialRepeatedFields(food.menu.v1.FoodMenu.MenuSection result) {
-        if (imagesBuilder_ == null) {
-          if (((bitField0_ & 0x00000008) != 0)) {
-            images_ = java.util.Collections.unmodifiableList(images_);
-            bitField0_ = (bitField0_ & ~0x00000008);
-          }
-          result.images_ = images_;
-        } else {
-          result.images_ = imagesBuilder_.build();
-        }
-      }
-
-      private void buildPartial0(food.menu.v1.FoodMenu.MenuSection result) {
-        int from_bitField0_ = bitField0_;
-        if (((from_bitField0_ & 0x00000001) != 0)) {
-          result.menuSectionId_ = menuSectionId_;
-        }
-        if (((from_bitField0_ & 0x00000002) != 0)) {
-          result.displayName_ = displayNameBuilder_ == null
-              ? displayName_
-              : displayNameBuilder_.build();
-        }
-        if (((from_bitField0_ & 0x00000004) != 0)) {
-          result.description_ = descriptionBuilder_ == null
-              ? description_
-              : descriptionBuilder_.build();
-        }
-        if (((from_bitField0_ & 0x00000010) != 0)) {
-          menuItemIds_.makeImmutable();
-          result.menuItemIds_ = menuItemIds_;
-        }
-        if (((from_bitField0_ & 0x00000020) != 0)) {
-          menuSectionIds_.makeImmutable();
-          result.menuSectionIds_ = menuSectionIds_;
-        }
-      }
-
-      @java.lang.Override
-      public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof food.menu.v1.FoodMenu.MenuSection) {
-          return mergeFrom((food.menu.v1.FoodMenu.MenuSection)other);
-        } else {
-          super.mergeFrom(other);
-          return this;
-        }
-      }
-
-      public Builder mergeFrom(food.menu.v1.FoodMenu.MenuSection other) {
-        if (other == food.menu.v1.FoodMenu.MenuSection.getDefaultInstance()) return this;
-        if (!other.getMenuSectionId().isEmpty()) {
-          menuSectionId_ = other.menuSectionId_;
-          bitField0_ |= 0x00000001;
-          onChanged();
-        }
-        if (other.hasDisplayName()) {
-          mergeDisplayName(other.getDisplayName());
-        }
-        if (other.hasDescription()) {
-          mergeDescription(other.getDescription());
-        }
-        if (imagesBuilder_ == null) {
-          if (!other.images_.isEmpty()) {
-            if (images_.isEmpty()) {
-              images_ = other.images_;
-              bitField0_ = (bitField0_ & ~0x00000008);
-            } else {
-              ensureImagesIsMutable();
-              images_.addAll(other.images_);
-            }
-            onChanged();
-          }
-        } else {
-          if (!other.images_.isEmpty()) {
-            if (imagesBuilder_.isEmpty()) {
-              imagesBuilder_.dispose();
-              imagesBuilder_ = null;
-              images_ = other.images_;
-              bitField0_ = (bitField0_ & ~0x00000008);
-              imagesBuilder_ = 
-                com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ?
-                   getImagesFieldBuilder() : null;
-            } else {
-              imagesBuilder_.addAllMessages(other.images_);
-            }
-          }
-        }
-        if (!other.menuItemIds_.isEmpty()) {
-          if (menuItemIds_.isEmpty()) {
-            menuItemIds_ = other.menuItemIds_;
-            bitField0_ |= 0x00000010;
-          } else {
-            ensureMenuItemIdsIsMutable();
-            menuItemIds_.addAll(other.menuItemIds_);
-          }
-          onChanged();
-        }
-        if (!other.menuSectionIds_.isEmpty()) {
-          if (menuSectionIds_.isEmpty()) {
-            menuSectionIds_ = other.menuSectionIds_;
-            bitField0_ |= 0x00000020;
-          } else {
-            ensureMenuSectionIdsIsMutable();
-            menuSectionIds_.addAll(other.menuSectionIds_);
-          }
-          onChanged();
-        }
-        this.mergeUnknownFields(other.getUnknownFields());
-        onChanged();
-        return this;
-      }
-
-      @java.lang.Override
-      public final boolean isInitialized() {
-        return true;
-      }
-
-      @java.lang.Override
-      public Builder mergeFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws java.io.IOException {
-        if (extensionRegistry == null) {
-          throw new java.lang.NullPointerException();
-        }
-        try {
-          boolean done = false;
-          while (!done) {
-            int tag = input.readTag();
-            switch (tag) {
-              case 0:
-                done = true;
-                break;
-              case 10: {
-                menuSectionId_ = input.readStringRequireUtf8();
-                bitField0_ |= 0x00000001;
-                break;
-              } // case 10
-              case 18: {
-                input.readMessage(
-                    getDisplayNameFieldBuilder().getBuilder(),
-                    extensionRegistry);
-                bitField0_ |= 0x00000002;
-                break;
-              } // case 18
-              case 26: {
-                input.readMessage(
-                    getDescriptionFieldBuilder().getBuilder(),
-                    extensionRegistry);
-                bitField0_ |= 0x00000004;
-                break;
-              } // case 26
-              case 34: {
-                food.menu.v1.FoodMenu.Image m =
-                    input.readMessage(
-                        food.menu.v1.FoodMenu.Image.parser(),
-                        extensionRegistry);
-                if (imagesBuilder_ == null) {
-                  ensureImagesIsMutable();
-                  images_.add(m);
-                } else {
-                  imagesBuilder_.addMessage(m);
-                }
-                break;
-              } // case 34
-              case 50: {
-                java.lang.String s = input.readStringRequireUtf8();
-                ensureMenuItemIdsIsMutable();
-                menuItemIds_.add(s);
-                break;
-              } // case 50
-              case 58: {
-                java.lang.String s = input.readStringRequireUtf8();
-                ensureMenuSectionIdsIsMutable();
-                menuSectionIds_.add(s);
-                break;
-              } // case 58
-              default: {
-                if (!super.parseUnknownField(input, extensionRegistry, tag)) {
-                  done = true; // was an endgroup tag
-                }
-                break;
-              } // default:
-            } // switch (tag)
-          } // while (!done)
-        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          throw e.unwrapIOException();
-        } finally {
-          onChanged();
-        } // finally
-        return this;
-      }
-      private int bitField0_;
-
-      private java.lang.Object menuSectionId_ = "";
-      /**
-       * <pre>
-       * An opaque string from an partner which uniquely identifies the MenuSection
-       * within the partner feed.
-       * Required.
-       * </pre>
-       *
-       * <code>string menu_section_id = 1;</code>
-       * @return The menuSectionId.
-       */
-      public java.lang.String getMenuSectionId() {
-        java.lang.Object ref = menuSectionId_;
-        if (!(ref instanceof java.lang.String)) {
-          com.google.protobuf.ByteString bs =
-              (com.google.protobuf.ByteString) ref;
-          java.lang.String s = bs.toStringUtf8();
-          menuSectionId_ = s;
-          return s;
-        } else {
-          return (java.lang.String) ref;
-        }
-      }
-      /**
-       * <pre>
-       * An opaque string from an partner which uniquely identifies the MenuSection
-       * within the partner feed.
-       * Required.
-       * </pre>
-       *
-       * <code>string menu_section_id = 1;</code>
-       * @return The bytes for menuSectionId.
-       */
-      public com.google.protobuf.ByteString
-          getMenuSectionIdBytes() {
-        java.lang.Object ref = menuSectionId_;
-        if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
-              com.google.protobuf.ByteString.copyFromUtf8(
-                  (java.lang.String) ref);
-          menuSectionId_ = b;
-          return b;
-        } else {
-          return (com.google.protobuf.ByteString) ref;
-        }
-      }
-      /**
-       * <pre>
-       * An opaque string from an partner which uniquely identifies the MenuSection
-       * within the partner feed.
-       * Required.
-       * </pre>
-       *
-       * <code>string menu_section_id = 1;</code>
-       * @param value The menuSectionId to set.
-       * @return This builder for chaining.
-       */
-      public Builder setMenuSectionId(
-          java.lang.String value) {
-        if (value == null) { throw new NullPointerException(); }
-        menuSectionId_ = value;
-        bitField0_ |= 0x00000001;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * An opaque string from an partner which uniquely identifies the MenuSection
-       * within the partner feed.
-       * Required.
-       * </pre>
-       *
-       * <code>string menu_section_id = 1;</code>
-       * @return This builder for chaining.
-       */
-      public Builder clearMenuSectionId() {
-        menuSectionId_ = getDefaultInstance().getMenuSectionId();
-        bitField0_ = (bitField0_ & ~0x00000001);
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * An opaque string from an partner which uniquely identifies the MenuSection
-       * within the partner feed.
-       * Required.
-       * </pre>
-       *
-       * <code>string menu_section_id = 1;</code>
-       * @param value The bytes for menuSectionId to set.
-       * @return This builder for chaining.
-       */
-      public Builder setMenuSectionIdBytes(
-          com.google.protobuf.ByteString value) {
-        if (value == null) { throw new NullPointerException(); }
-        checkByteStringIsUtf8(value);
-        menuSectionId_ = value;
-        bitField0_ |= 0x00000001;
-        onChanged();
-        return this;
-      }
-
-      private food.menu.v1.FoodMenu.TextField displayName_;
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.TextField, food.menu.v1.FoodMenu.TextField.Builder, food.menu.v1.FoodMenu.TextFieldOrBuilder> displayNameBuilder_;
-      /**
-       * <pre>
-       * The name that can identify the MenuSection when a user is browsing the
-       * menu.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField display_name = 2;</code>
-       * @return Whether the displayName field is set.
-       */
-      public boolean hasDisplayName() {
-        return ((bitField0_ & 0x00000002) != 0);
-      }
-      /**
-       * <pre>
-       * The name that can identify the MenuSection when a user is browsing the
-       * menu.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField display_name = 2;</code>
-       * @return The displayName.
-       */
-      public food.menu.v1.FoodMenu.TextField getDisplayName() {
-        if (displayNameBuilder_ == null) {
-          return displayName_ == null ? food.menu.v1.FoodMenu.TextField.getDefaultInstance() : displayName_;
-        } else {
-          return displayNameBuilder_.getMessage();
-        }
-      }
-      /**
-       * <pre>
-       * The name that can identify the MenuSection when a user is browsing the
-       * menu.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField display_name = 2;</code>
-       */
-      public Builder setDisplayName(food.menu.v1.FoodMenu.TextField value) {
-        if (displayNameBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          displayName_ = value;
-        } else {
-          displayNameBuilder_.setMessage(value);
-        }
-        bitField0_ |= 0x00000002;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * The name that can identify the MenuSection when a user is browsing the
-       * menu.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField display_name = 2;</code>
-       */
-      public Builder setDisplayName(
-          food.menu.v1.FoodMenu.TextField.Builder builderForValue) {
-        if (displayNameBuilder_ == null) {
-          displayName_ = builderForValue.build();
-        } else {
-          displayNameBuilder_.setMessage(builderForValue.build());
-        }
-        bitField0_ |= 0x00000002;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * The name that can identify the MenuSection when a user is browsing the
-       * menu.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField display_name = 2;</code>
-       */
-      public Builder mergeDisplayName(food.menu.v1.FoodMenu.TextField value) {
-        if (displayNameBuilder_ == null) {
-          if (((bitField0_ & 0x00000002) != 0) &&
-            displayName_ != null &&
-            displayName_ != food.menu.v1.FoodMenu.TextField.getDefaultInstance()) {
-            getDisplayNameBuilder().mergeFrom(value);
-          } else {
-            displayName_ = value;
-          }
-        } else {
-          displayNameBuilder_.mergeFrom(value);
-        }
-        bitField0_ |= 0x00000002;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * The name that can identify the MenuSection when a user is browsing the
-       * menu.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField display_name = 2;</code>
-       */
-      public Builder clearDisplayName() {
-        bitField0_ = (bitField0_ & ~0x00000002);
-        displayName_ = null;
-        if (displayNameBuilder_ != null) {
-          displayNameBuilder_.dispose();
-          displayNameBuilder_ = null;
-        }
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * The name that can identify the MenuSection when a user is browsing the
-       * menu.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField display_name = 2;</code>
-       */
-      public food.menu.v1.FoodMenu.TextField.Builder getDisplayNameBuilder() {
-        bitField0_ |= 0x00000002;
-        onChanged();
-        return getDisplayNameFieldBuilder().getBuilder();
-      }
-      /**
-       * <pre>
-       * The name that can identify the MenuSection when a user is browsing the
-       * menu.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField display_name = 2;</code>
-       */
-      public food.menu.v1.FoodMenu.TextFieldOrBuilder getDisplayNameOrBuilder() {
-        if (displayNameBuilder_ != null) {
-          return displayNameBuilder_.getMessageOrBuilder();
-        } else {
-          return displayName_ == null ?
-              food.menu.v1.FoodMenu.TextField.getDefaultInstance() : displayName_;
-        }
-      }
-      /**
-       * <pre>
-       * The name that can identify the MenuSection when a user is browsing the
-       * menu.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField display_name = 2;</code>
-       */
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.TextField, food.menu.v1.FoodMenu.TextField.Builder, food.menu.v1.FoodMenu.TextFieldOrBuilder> 
-          getDisplayNameFieldBuilder() {
-        if (displayNameBuilder_ == null) {
-          displayNameBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
-              food.menu.v1.FoodMenu.TextField, food.menu.v1.FoodMenu.TextField.Builder, food.menu.v1.FoodMenu.TextFieldOrBuilder>(
-                  getDisplayName(),
-                  getParentForChildren(),
-                  isClean());
-          displayName_ = null;
-        }
-        return displayNameBuilder_;
-      }
-
-      private food.menu.v1.FoodMenu.TextField description_;
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.TextField, food.menu.v1.FoodMenu.TextField.Builder, food.menu.v1.FoodMenu.TextFieldOrBuilder> descriptionBuilder_;
-      /**
-       * <pre>
-       * A description of the menu section.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField description = 3;</code>
-       * @return Whether the description field is set.
-       */
-      public boolean hasDescription() {
-        return ((bitField0_ & 0x00000004) != 0);
-      }
-      /**
-       * <pre>
-       * A description of the menu section.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField description = 3;</code>
-       * @return The description.
-       */
-      public food.menu.v1.FoodMenu.TextField getDescription() {
-        if (descriptionBuilder_ == null) {
-          return description_ == null ? food.menu.v1.FoodMenu.TextField.getDefaultInstance() : description_;
-        } else {
-          return descriptionBuilder_.getMessage();
-        }
-      }
-      /**
-       * <pre>
-       * A description of the menu section.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField description = 3;</code>
-       */
-      public Builder setDescription(food.menu.v1.FoodMenu.TextField value) {
-        if (descriptionBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          description_ = value;
-        } else {
-          descriptionBuilder_.setMessage(value);
-        }
-        bitField0_ |= 0x00000004;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * A description of the menu section.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField description = 3;</code>
-       */
-      public Builder setDescription(
-          food.menu.v1.FoodMenu.TextField.Builder builderForValue) {
-        if (descriptionBuilder_ == null) {
-          description_ = builderForValue.build();
-        } else {
-          descriptionBuilder_.setMessage(builderForValue.build());
-        }
-        bitField0_ |= 0x00000004;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * A description of the menu section.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField description = 3;</code>
-       */
-      public Builder mergeDescription(food.menu.v1.FoodMenu.TextField value) {
-        if (descriptionBuilder_ == null) {
-          if (((bitField0_ & 0x00000004) != 0) &&
-            description_ != null &&
-            description_ != food.menu.v1.FoodMenu.TextField.getDefaultInstance()) {
-            getDescriptionBuilder().mergeFrom(value);
-          } else {
-            description_ = value;
-          }
-        } else {
-          descriptionBuilder_.mergeFrom(value);
-        }
-        bitField0_ |= 0x00000004;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * A description of the menu section.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField description = 3;</code>
-       */
-      public Builder clearDescription() {
-        bitField0_ = (bitField0_ & ~0x00000004);
-        description_ = null;
-        if (descriptionBuilder_ != null) {
-          descriptionBuilder_.dispose();
-          descriptionBuilder_ = null;
-        }
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * A description of the menu section.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField description = 3;</code>
-       */
-      public food.menu.v1.FoodMenu.TextField.Builder getDescriptionBuilder() {
-        bitField0_ |= 0x00000004;
-        onChanged();
-        return getDescriptionFieldBuilder().getBuilder();
-      }
-      /**
-       * <pre>
-       * A description of the menu section.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField description = 3;</code>
-       */
-      public food.menu.v1.FoodMenu.TextFieldOrBuilder getDescriptionOrBuilder() {
-        if (descriptionBuilder_ != null) {
-          return descriptionBuilder_.getMessageOrBuilder();
-        } else {
-          return description_ == null ?
-              food.menu.v1.FoodMenu.TextField.getDefaultInstance() : description_;
-        }
-      }
-      /**
-       * <pre>
-       * A description of the menu section.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField description = 3;</code>
-       */
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.TextField, food.menu.v1.FoodMenu.TextField.Builder, food.menu.v1.FoodMenu.TextFieldOrBuilder> 
-          getDescriptionFieldBuilder() {
-        if (descriptionBuilder_ == null) {
-          descriptionBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
-              food.menu.v1.FoodMenu.TextField, food.menu.v1.FoodMenu.TextField.Builder, food.menu.v1.FoodMenu.TextFieldOrBuilder>(
-                  getDescription(),
-                  getParentForChildren(),
-                  isClean());
-          description_ = null;
-        }
-        return descriptionBuilder_;
-      }
-
-      private java.util.List<food.menu.v1.FoodMenu.Image> images_ =
-        java.util.Collections.emptyList();
-      private void ensureImagesIsMutable() {
-        if (!((bitField0_ & 0x00000008) != 0)) {
-          images_ = new java.util.ArrayList<food.menu.v1.FoodMenu.Image>(images_);
-          bitField0_ |= 0x00000008;
-         }
-      }
-
-      private com.google.protobuf.RepeatedFieldBuilderV3<
-          food.menu.v1.FoodMenu.Image, food.menu.v1.FoodMenu.Image.Builder, food.menu.v1.FoodMenu.ImageOrBuilder> imagesBuilder_;
-
-      /**
-       * <pre>
-       * Image(s) of the menu section.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Image images = 4;</code>
-       */
-      public java.util.List<food.menu.v1.FoodMenu.Image> getImagesList() {
-        if (imagesBuilder_ == null) {
-          return java.util.Collections.unmodifiableList(images_);
-        } else {
-          return imagesBuilder_.getMessageList();
-        }
-      }
-      /**
-       * <pre>
-       * Image(s) of the menu section.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Image images = 4;</code>
-       */
-      public int getImagesCount() {
-        if (imagesBuilder_ == null) {
-          return images_.size();
-        } else {
-          return imagesBuilder_.getCount();
-        }
-      }
-      /**
-       * <pre>
-       * Image(s) of the menu section.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Image images = 4;</code>
-       */
-      public food.menu.v1.FoodMenu.Image getImages(int index) {
-        if (imagesBuilder_ == null) {
-          return images_.get(index);
-        } else {
-          return imagesBuilder_.getMessage(index);
-        }
-      }
-      /**
-       * <pre>
-       * Image(s) of the menu section.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Image images = 4;</code>
-       */
-      public Builder setImages(
-          int index, food.menu.v1.FoodMenu.Image value) {
-        if (imagesBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          ensureImagesIsMutable();
-          images_.set(index, value);
-          onChanged();
-        } else {
-          imagesBuilder_.setMessage(index, value);
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Image(s) of the menu section.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Image images = 4;</code>
-       */
-      public Builder setImages(
-          int index, food.menu.v1.FoodMenu.Image.Builder builderForValue) {
-        if (imagesBuilder_ == null) {
-          ensureImagesIsMutable();
-          images_.set(index, builderForValue.build());
-          onChanged();
-        } else {
-          imagesBuilder_.setMessage(index, builderForValue.build());
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Image(s) of the menu section.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Image images = 4;</code>
-       */
-      public Builder addImages(food.menu.v1.FoodMenu.Image value) {
-        if (imagesBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          ensureImagesIsMutable();
-          images_.add(value);
-          onChanged();
-        } else {
-          imagesBuilder_.addMessage(value);
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Image(s) of the menu section.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Image images = 4;</code>
-       */
-      public Builder addImages(
-          int index, food.menu.v1.FoodMenu.Image value) {
-        if (imagesBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          ensureImagesIsMutable();
-          images_.add(index, value);
-          onChanged();
-        } else {
-          imagesBuilder_.addMessage(index, value);
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Image(s) of the menu section.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Image images = 4;</code>
-       */
-      public Builder addImages(
-          food.menu.v1.FoodMenu.Image.Builder builderForValue) {
-        if (imagesBuilder_ == null) {
-          ensureImagesIsMutable();
-          images_.add(builderForValue.build());
-          onChanged();
-        } else {
-          imagesBuilder_.addMessage(builderForValue.build());
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Image(s) of the menu section.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Image images = 4;</code>
-       */
-      public Builder addImages(
-          int index, food.menu.v1.FoodMenu.Image.Builder builderForValue) {
-        if (imagesBuilder_ == null) {
-          ensureImagesIsMutable();
-          images_.add(index, builderForValue.build());
-          onChanged();
-        } else {
-          imagesBuilder_.addMessage(index, builderForValue.build());
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Image(s) of the menu section.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Image images = 4;</code>
-       */
-      public Builder addAllImages(
-          java.lang.Iterable<? extends food.menu.v1.FoodMenu.Image> values) {
-        if (imagesBuilder_ == null) {
-          ensureImagesIsMutable();
-          com.google.protobuf.AbstractMessageLite.Builder.addAll(
-              values, images_);
-          onChanged();
-        } else {
-          imagesBuilder_.addAllMessages(values);
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Image(s) of the menu section.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Image images = 4;</code>
-       */
-      public Builder clearImages() {
-        if (imagesBuilder_ == null) {
-          images_ = java.util.Collections.emptyList();
-          bitField0_ = (bitField0_ & ~0x00000008);
-          onChanged();
-        } else {
-          imagesBuilder_.clear();
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Image(s) of the menu section.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Image images = 4;</code>
-       */
-      public Builder removeImages(int index) {
-        if (imagesBuilder_ == null) {
-          ensureImagesIsMutable();
-          images_.remove(index);
-          onChanged();
-        } else {
-          imagesBuilder_.remove(index);
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Image(s) of the menu section.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Image images = 4;</code>
-       */
-      public food.menu.v1.FoodMenu.Image.Builder getImagesBuilder(
-          int index) {
-        return getImagesFieldBuilder().getBuilder(index);
-      }
-      /**
-       * <pre>
-       * Image(s) of the menu section.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Image images = 4;</code>
-       */
-      public food.menu.v1.FoodMenu.ImageOrBuilder getImagesOrBuilder(
-          int index) {
-        if (imagesBuilder_ == null) {
-          return images_.get(index);  } else {
-          return imagesBuilder_.getMessageOrBuilder(index);
-        }
-      }
-      /**
-       * <pre>
-       * Image(s) of the menu section.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Image images = 4;</code>
-       */
-      public java.util.List<? extends food.menu.v1.FoodMenu.ImageOrBuilder> 
-           getImagesOrBuilderList() {
-        if (imagesBuilder_ != null) {
-          return imagesBuilder_.getMessageOrBuilderList();
-        } else {
-          return java.util.Collections.unmodifiableList(images_);
-        }
-      }
-      /**
-       * <pre>
-       * Image(s) of the menu section.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Image images = 4;</code>
-       */
-      public food.menu.v1.FoodMenu.Image.Builder addImagesBuilder() {
-        return getImagesFieldBuilder().addBuilder(
-            food.menu.v1.FoodMenu.Image.getDefaultInstance());
-      }
-      /**
-       * <pre>
-       * Image(s) of the menu section.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Image images = 4;</code>
-       */
-      public food.menu.v1.FoodMenu.Image.Builder addImagesBuilder(
-          int index) {
-        return getImagesFieldBuilder().addBuilder(
-            index, food.menu.v1.FoodMenu.Image.getDefaultInstance());
-      }
-      /**
-       * <pre>
-       * Image(s) of the menu section.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Image images = 4;</code>
-       */
-      public java.util.List<food.menu.v1.FoodMenu.Image.Builder> 
-           getImagesBuilderList() {
-        return getImagesFieldBuilder().getBuilderList();
-      }
-      private com.google.protobuf.RepeatedFieldBuilderV3<
-          food.menu.v1.FoodMenu.Image, food.menu.v1.FoodMenu.Image.Builder, food.menu.v1.FoodMenu.ImageOrBuilder> 
-          getImagesFieldBuilder() {
-        if (imagesBuilder_ == null) {
-          imagesBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3<
-              food.menu.v1.FoodMenu.Image, food.menu.v1.FoodMenu.Image.Builder, food.menu.v1.FoodMenu.ImageOrBuilder>(
-                  images_,
-                  ((bitField0_ & 0x00000008) != 0),
-                  getParentForChildren(),
-                  isClean());
-          images_ = null;
-        }
-        return imagesBuilder_;
-      }
-
-      private com.google.protobuf.LazyStringArrayList menuItemIds_ =
-          com.google.protobuf.LazyStringArrayList.emptyList();
-      private void ensureMenuItemIdsIsMutable() {
-        if (!menuItemIds_.isModifiable()) {
-          menuItemIds_ = new com.google.protobuf.LazyStringArrayList(menuItemIds_);
-        }
-        bitField0_ |= 0x00000010;
-      }
-      /**
-       * <pre>
-       * IDs of MenuItem entities that correspond to this MenuSection entity. A
-       * section is expected to have at least 1 item if it does not contain any
-       * sub-sections.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated string menu_item_ids = 6;</code>
-       * @return A list containing the menuItemIds.
-       */
-      public com.google.protobuf.ProtocolStringList
-          getMenuItemIdsList() {
-        menuItemIds_.makeImmutable();
-        return menuItemIds_;
-      }
-      /**
-       * <pre>
-       * IDs of MenuItem entities that correspond to this MenuSection entity. A
-       * section is expected to have at least 1 item if it does not contain any
-       * sub-sections.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated string menu_item_ids = 6;</code>
-       * @return The count of menuItemIds.
-       */
-      public int getMenuItemIdsCount() {
-        return menuItemIds_.size();
-      }
-      /**
-       * <pre>
-       * IDs of MenuItem entities that correspond to this MenuSection entity. A
-       * section is expected to have at least 1 item if it does not contain any
-       * sub-sections.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated string menu_item_ids = 6;</code>
-       * @param index The index of the element to return.
-       * @return The menuItemIds at the given index.
-       */
-      public java.lang.String getMenuItemIds(int index) {
-        return menuItemIds_.get(index);
-      }
-      /**
-       * <pre>
-       * IDs of MenuItem entities that correspond to this MenuSection entity. A
-       * section is expected to have at least 1 item if it does not contain any
-       * sub-sections.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated string menu_item_ids = 6;</code>
-       * @param index The index of the value to return.
-       * @return The bytes of the menuItemIds at the given index.
-       */
-      public com.google.protobuf.ByteString
-          getMenuItemIdsBytes(int index) {
-        return menuItemIds_.getByteString(index);
-      }
-      /**
-       * <pre>
-       * IDs of MenuItem entities that correspond to this MenuSection entity. A
-       * section is expected to have at least 1 item if it does not contain any
-       * sub-sections.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated string menu_item_ids = 6;</code>
-       * @param index The index to set the value at.
-       * @param value The menuItemIds to set.
-       * @return This builder for chaining.
-       */
-      public Builder setMenuItemIds(
-          int index, java.lang.String value) {
-        if (value == null) { throw new NullPointerException(); }
-        ensureMenuItemIdsIsMutable();
-        menuItemIds_.set(index, value);
-        bitField0_ |= 0x00000010;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * IDs of MenuItem entities that correspond to this MenuSection entity. A
-       * section is expected to have at least 1 item if it does not contain any
-       * sub-sections.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated string menu_item_ids = 6;</code>
-       * @param value The menuItemIds to add.
-       * @return This builder for chaining.
-       */
-      public Builder addMenuItemIds(
-          java.lang.String value) {
-        if (value == null) { throw new NullPointerException(); }
-        ensureMenuItemIdsIsMutable();
-        menuItemIds_.add(value);
-        bitField0_ |= 0x00000010;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * IDs of MenuItem entities that correspond to this MenuSection entity. A
-       * section is expected to have at least 1 item if it does not contain any
-       * sub-sections.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated string menu_item_ids = 6;</code>
-       * @param values The menuItemIds to add.
-       * @return This builder for chaining.
-       */
-      public Builder addAllMenuItemIds(
-          java.lang.Iterable<java.lang.String> values) {
-        ensureMenuItemIdsIsMutable();
-        com.google.protobuf.AbstractMessageLite.Builder.addAll(
-            values, menuItemIds_);
-        bitField0_ |= 0x00000010;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * IDs of MenuItem entities that correspond to this MenuSection entity. A
-       * section is expected to have at least 1 item if it does not contain any
-       * sub-sections.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated string menu_item_ids = 6;</code>
-       * @return This builder for chaining.
-       */
-      public Builder clearMenuItemIds() {
-        menuItemIds_ =
-          com.google.protobuf.LazyStringArrayList.emptyList();
-        bitField0_ = (bitField0_ & ~0x00000010);;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * IDs of MenuItem entities that correspond to this MenuSection entity. A
-       * section is expected to have at least 1 item if it does not contain any
-       * sub-sections.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated string menu_item_ids = 6;</code>
-       * @param value The bytes of the menuItemIds to add.
-       * @return This builder for chaining.
-       */
-      public Builder addMenuItemIdsBytes(
-          com.google.protobuf.ByteString value) {
-        if (value == null) { throw new NullPointerException(); }
-        checkByteStringIsUtf8(value);
-        ensureMenuItemIdsIsMutable();
-        menuItemIds_.add(value);
-        bitField0_ |= 0x00000010;
-        onChanged();
-        return this;
-      }
-
-      private com.google.protobuf.LazyStringArrayList menuSectionIds_ =
-          com.google.protobuf.LazyStringArrayList.emptyList();
-      private void ensureMenuSectionIdsIsMutable() {
-        if (!menuSectionIds_.isModifiable()) {
-          menuSectionIds_ = new com.google.protobuf.LazyStringArrayList(menuSectionIds_);
-        }
-        bitField0_ |= 0x00000020;
-      }
-      /**
-       * <pre>
-       * Child MenuSections (sub-sections) that correspond to this MenuSection
-       * entity.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated string menu_section_ids = 7;</code>
-       * @return A list containing the menuSectionIds.
-       */
-      public com.google.protobuf.ProtocolStringList
-          getMenuSectionIdsList() {
-        menuSectionIds_.makeImmutable();
-        return menuSectionIds_;
-      }
-      /**
-       * <pre>
-       * Child MenuSections (sub-sections) that correspond to this MenuSection
-       * entity.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated string menu_section_ids = 7;</code>
-       * @return The count of menuSectionIds.
-       */
-      public int getMenuSectionIdsCount() {
-        return menuSectionIds_.size();
-      }
-      /**
-       * <pre>
-       * Child MenuSections (sub-sections) that correspond to this MenuSection
-       * entity.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated string menu_section_ids = 7;</code>
-       * @param index The index of the element to return.
-       * @return The menuSectionIds at the given index.
-       */
-      public java.lang.String getMenuSectionIds(int index) {
-        return menuSectionIds_.get(index);
-      }
-      /**
-       * <pre>
-       * Child MenuSections (sub-sections) that correspond to this MenuSection
-       * entity.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated string menu_section_ids = 7;</code>
-       * @param index The index of the value to return.
-       * @return The bytes of the menuSectionIds at the given index.
-       */
-      public com.google.protobuf.ByteString
-          getMenuSectionIdsBytes(int index) {
-        return menuSectionIds_.getByteString(index);
-      }
-      /**
-       * <pre>
-       * Child MenuSections (sub-sections) that correspond to this MenuSection
-       * entity.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated string menu_section_ids = 7;</code>
-       * @param index The index to set the value at.
-       * @param value The menuSectionIds to set.
-       * @return This builder for chaining.
-       */
-      public Builder setMenuSectionIds(
-          int index, java.lang.String value) {
-        if (value == null) { throw new NullPointerException(); }
-        ensureMenuSectionIdsIsMutable();
-        menuSectionIds_.set(index, value);
-        bitField0_ |= 0x00000020;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Child MenuSections (sub-sections) that correspond to this MenuSection
-       * entity.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated string menu_section_ids = 7;</code>
-       * @param value The menuSectionIds to add.
-       * @return This builder for chaining.
-       */
-      public Builder addMenuSectionIds(
-          java.lang.String value) {
-        if (value == null) { throw new NullPointerException(); }
-        ensureMenuSectionIdsIsMutable();
-        menuSectionIds_.add(value);
-        bitField0_ |= 0x00000020;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Child MenuSections (sub-sections) that correspond to this MenuSection
-       * entity.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated string menu_section_ids = 7;</code>
-       * @param values The menuSectionIds to add.
-       * @return This builder for chaining.
-       */
-      public Builder addAllMenuSectionIds(
-          java.lang.Iterable<java.lang.String> values) {
-        ensureMenuSectionIdsIsMutable();
-        com.google.protobuf.AbstractMessageLite.Builder.addAll(
-            values, menuSectionIds_);
-        bitField0_ |= 0x00000020;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Child MenuSections (sub-sections) that correspond to this MenuSection
-       * entity.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated string menu_section_ids = 7;</code>
-       * @return This builder for chaining.
-       */
-      public Builder clearMenuSectionIds() {
-        menuSectionIds_ =
-          com.google.protobuf.LazyStringArrayList.emptyList();
-        bitField0_ = (bitField0_ & ~0x00000020);;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Child MenuSections (sub-sections) that correspond to this MenuSection
-       * entity.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated string menu_section_ids = 7;</code>
-       * @param value The bytes of the menuSectionIds to add.
-       * @return This builder for chaining.
-       */
-      public Builder addMenuSectionIdsBytes(
-          com.google.protobuf.ByteString value) {
-        if (value == null) { throw new NullPointerException(); }
-        checkByteStringIsUtf8(value);
-        ensureMenuSectionIdsIsMutable();
-        menuSectionIds_.add(value);
-        bitField0_ |= 0x00000020;
-        onChanged();
-        return this;
-      }
-      @java.lang.Override
-      public final Builder setUnknownFields(
-          final com.google.protobuf.UnknownFieldSet unknownFields) {
-        return super.setUnknownFields(unknownFields);
-      }
-
-      @java.lang.Override
-      public final Builder mergeUnknownFields(
-          final com.google.protobuf.UnknownFieldSet unknownFields) {
-        return super.mergeUnknownFields(unknownFields);
-      }
-
-
-      // @@protoc_insertion_point(builder_scope:food.menu.v1.MenuSection)
-    }
-
-    // @@protoc_insertion_point(class_scope:food.menu.v1.MenuSection)
-    private static final food.menu.v1.FoodMenu.MenuSection DEFAULT_INSTANCE;
-    static {
-      DEFAULT_INSTANCE = new food.menu.v1.FoodMenu.MenuSection();
-    }
-
-    public static food.menu.v1.FoodMenu.MenuSection getDefaultInstance() {
-      return DEFAULT_INSTANCE;
-    }
-
-    private static final com.google.protobuf.Parser<MenuSection>
-        PARSER = new com.google.protobuf.AbstractParser<MenuSection>() {
-      @java.lang.Override
-      public MenuSection parsePartialFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws com.google.protobuf.InvalidProtocolBufferException {
-        Builder builder = newBuilder();
-        try {
-          builder.mergeFrom(input, extensionRegistry);
-        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          throw e.setUnfinishedMessage(builder.buildPartial());
-        } catch (com.google.protobuf.UninitializedMessageException e) {
-          throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
-        } catch (java.io.IOException e) {
-          throw new com.google.protobuf.InvalidProtocolBufferException(e)
-              .setUnfinishedMessage(builder.buildPartial());
-        }
-        return builder.buildPartial();
-      }
-    };
-
-    public static com.google.protobuf.Parser<MenuSection> parser() {
-      return PARSER;
-    }
-
-    @java.lang.Override
-    public com.google.protobuf.Parser<MenuSection> getParserForType() {
-      return PARSER;
-    }
-
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.MenuSection getDefaultInstanceForType() {
-      return DEFAULT_INSTANCE;
-    }
-
-  }
-
-  public interface MenuItemOrBuilder extends
-      // @@protoc_insertion_point(interface_extends:food.menu.v1.MenuItem)
-      com.google.protobuf.MessageOrBuilder {
-
-    /**
-     * <pre>
-     * An opaque string from an partner which uniquely identifies the MenuItem
-     * within the partner feed.
-     * Required.
-     * </pre>
-     *
-     * <code>string menu_item_id = 1;</code>
-     * @return The menuItemId.
-     */
-    java.lang.String getMenuItemId();
-    /**
-     * <pre>
-     * An opaque string from an partner which uniquely identifies the MenuItem
-     * within the partner feed.
-     * Required.
-     * </pre>
-     *
-     * <code>string menu_item_id = 1;</code>
-     * @return The bytes for menuItemId.
-     */
-    com.google.protobuf.ByteString
-        getMenuItemIdBytes();
-
-    /**
-     * <pre>
-     * The name that can identify the MenuItem when a user is browsing the menu.
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField display_name = 2;</code>
-     * @return Whether the displayName field is set.
-     */
-    boolean hasDisplayName();
-    /**
-     * <pre>
-     * The name that can identify the MenuItem when a user is browsing the menu.
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField display_name = 2;</code>
-     * @return The displayName.
-     */
-    food.menu.v1.FoodMenu.TextField getDisplayName();
-    /**
-     * <pre>
-     * The name that can identify the MenuItem when a user is browsing the menu.
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField display_name = 2;</code>
-     */
-    food.menu.v1.FoodMenu.TextFieldOrBuilder getDisplayNameOrBuilder();
-
-    /**
-     * <pre>
-     * A description of the menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField description = 3;</code>
-     * @return Whether the description field is set.
-     */
-    boolean hasDescription();
-    /**
-     * <pre>
-     * A description of the menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField description = 3;</code>
-     * @return The description.
-     */
-    food.menu.v1.FoodMenu.TextField getDescription();
-    /**
-     * <pre>
-     * A description of the menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField description = 3;</code>
-     */
-    food.menu.v1.FoodMenu.TextFieldOrBuilder getDescriptionOrBuilder();
-
-    /**
-     * <pre>
-     * Image(s) of the menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Image images = 4;</code>
-     */
-    java.util.List<food.menu.v1.FoodMenu.Image> 
-        getImagesList();
-    /**
-     * <pre>
-     * Image(s) of the menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Image images = 4;</code>
-     */
-    food.menu.v1.FoodMenu.Image getImages(int index);
-    /**
-     * <pre>
-     * Image(s) of the menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Image images = 4;</code>
-     */
-    int getImagesCount();
-    /**
-     * <pre>
-     * Image(s) of the menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Image images = 4;</code>
-     */
-    java.util.List<? extends food.menu.v1.FoodMenu.ImageOrBuilder> 
-        getImagesOrBuilderList();
-    /**
-     * <pre>
-     * Image(s) of the menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Image images = 4;</code>
-     */
-    food.menu.v1.FoodMenu.ImageOrBuilder getImagesOrBuilder(
-        int index);
-
-    /**
-     * <pre>
-     * Available offers to purchase this food item.
-     * </pre>
-     *
-     * <code>.food.menu.v1.OfferSet offer_set = 6;</code>
-     * @return Whether the offerSet field is set.
-     */
-    boolean hasOfferSet();
-    /**
-     * <pre>
-     * Available offers to purchase this food item.
-     * </pre>
-     *
-     * <code>.food.menu.v1.OfferSet offer_set = 6;</code>
-     * @return The offerSet.
-     */
-    food.menu.v1.FoodMenu.OfferSet getOfferSet();
-    /**
-     * <pre>
-     * Available offers to purchase this food item.
-     * </pre>
-     *
-     * <code>.food.menu.v1.OfferSet offer_set = 6;</code>
-     */
-    food.menu.v1.FoodMenu.OfferSetOrBuilder getOfferSetOrBuilder();
-
-    /**
-     * <pre>
-     * Available options for this menu item.
-     * </pre>
-     *
-     * <code>.food.menu.v1.MenuItem.MenuItemOptionSet menu_item_option_set = 7;</code>
-     * @return Whether the menuItemOptionSet field is set.
-     */
-    boolean hasMenuItemOptionSet();
-    /**
-     * <pre>
-     * Available options for this menu item.
-     * </pre>
-     *
-     * <code>.food.menu.v1.MenuItem.MenuItemOptionSet menu_item_option_set = 7;</code>
-     * @return The menuItemOptionSet.
-     */
-    food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet getMenuItemOptionSet();
-    /**
-     * <pre>
-     * Available options for this menu item.
-     * </pre>
-     *
-     * <code>.food.menu.v1.MenuItem.MenuItemOptionSet menu_item_option_set = 7;</code>
-     */
-    food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSetOrBuilder getMenuItemOptionSetOrBuilder();
-
-    /**
-     * <pre>
-     * Attributes about this menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.MenuItemAttributes item_attributes = 8;</code>
-     * @return Whether the itemAttributes field is set.
-     */
-    boolean hasItemAttributes();
-    /**
-     * <pre>
-     * Attributes about this menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.MenuItemAttributes item_attributes = 8;</code>
-     * @return The itemAttributes.
-     */
-    food.menu.v1.FoodMenu.MenuItemAttributes getItemAttributes();
-    /**
-     * <pre>
-     * Attributes about this menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.MenuItemAttributes item_attributes = 8;</code>
-     */
-    food.menu.v1.FoodMenu.MenuItemAttributesOrBuilder getItemAttributesOrBuilder();
-
-    food.menu.v1.FoodMenu.MenuItem.PricingCase getPricingCase();
-  }
-  /**
-   * <pre>
-   * Represents a single food or drink item offered by a Food establishment.
-   * </pre>
-   *
-   * Protobuf type {@code food.menu.v1.MenuItem}
-   */
-  public static final class MenuItem extends
-      com.google.protobuf.GeneratedMessageV3 implements
-      // @@protoc_insertion_point(message_implements:food.menu.v1.MenuItem)
-      MenuItemOrBuilder {
-  private static final long serialVersionUID = 0L;
-    // Use MenuItem.newBuilder() to construct.
-    private MenuItem(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
-      super(builder);
-    }
-    private MenuItem() {
-      menuItemId_ = "";
-      images_ = java.util.Collections.emptyList();
-    }
-
-    @java.lang.Override
-    @SuppressWarnings({"unused"})
-    protected java.lang.Object newInstance(
-        UnusedPrivateParameter unused) {
-      return new MenuItem();
-    }
-
-    public static final com.google.protobuf.Descriptors.Descriptor
-        getDescriptor() {
-      return food.menu.v1.FoodMenu.internal_static_food_menu_v1_MenuItem_descriptor;
-    }
-
-    @java.lang.Override
-    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-        internalGetFieldAccessorTable() {
-      return food.menu.v1.FoodMenu.internal_static_food_menu_v1_MenuItem_fieldAccessorTable
-          .ensureFieldAccessorsInitialized(
-              food.menu.v1.FoodMenu.MenuItem.class, food.menu.v1.FoodMenu.MenuItem.Builder.class);
-    }
-
-    public interface MenuItemOptionSetOrBuilder extends
-        // @@protoc_insertion_point(interface_extends:food.menu.v1.MenuItem.MenuItemOptionSet)
-        com.google.protobuf.MessageOrBuilder {
-
-      /**
-       * <pre>
-       * IDs of menu item options that are applicable to this menu item.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated string menu_item_option_ids = 1;</code>
-       * @return A list containing the menuItemOptionIds.
-       */
-      java.util.List<java.lang.String>
-          getMenuItemOptionIdsList();
-      /**
-       * <pre>
-       * IDs of menu item options that are applicable to this menu item.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated string menu_item_option_ids = 1;</code>
-       * @return The count of menuItemOptionIds.
-       */
-      int getMenuItemOptionIdsCount();
-      /**
-       * <pre>
-       * IDs of menu item options that are applicable to this menu item.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated string menu_item_option_ids = 1;</code>
-       * @param index The index of the element to return.
-       * @return The menuItemOptionIds at the given index.
-       */
-      java.lang.String getMenuItemOptionIds(int index);
-      /**
-       * <pre>
-       * IDs of menu item options that are applicable to this menu item.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated string menu_item_option_ids = 1;</code>
-       * @param index The index of the value to return.
-       * @return The bytes of the menuItemOptionIds at the given index.
-       */
-      com.google.protobuf.ByteString
-          getMenuItemOptionIdsBytes(int index);
-    }
-    /**
-     * <pre>
-     * Container that specifies a list of options available on an item.
-     * </pre>
-     *
-     * Protobuf type {@code food.menu.v1.MenuItem.MenuItemOptionSet}
-     */
-    public static final class MenuItemOptionSet extends
-        com.google.protobuf.GeneratedMessageV3 implements
-        // @@protoc_insertion_point(message_implements:food.menu.v1.MenuItem.MenuItemOptionSet)
-        MenuItemOptionSetOrBuilder {
-    private static final long serialVersionUID = 0L;
-      // Use MenuItemOptionSet.newBuilder() to construct.
-      private MenuItemOptionSet(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
-        super(builder);
-      }
-      private MenuItemOptionSet() {
-        menuItemOptionIds_ =
-            com.google.protobuf.LazyStringArrayList.emptyList();
-      }
-
-      @java.lang.Override
-      @SuppressWarnings({"unused"})
-      protected java.lang.Object newInstance(
-          UnusedPrivateParameter unused) {
-        return new MenuItemOptionSet();
-      }
-
-      public static final com.google.protobuf.Descriptors.Descriptor
-          getDescriptor() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_MenuItem_MenuItemOptionSet_descriptor;
-      }
-
-      @java.lang.Override
-      protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-          internalGetFieldAccessorTable() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_MenuItem_MenuItemOptionSet_fieldAccessorTable
-            .ensureFieldAccessorsInitialized(
-                food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet.class, food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet.Builder.class);
-      }
-
-      public static final int MENU_ITEM_OPTION_IDS_FIELD_NUMBER = 1;
-      @SuppressWarnings("serial")
-      private com.google.protobuf.LazyStringArrayList menuItemOptionIds_ =
-          com.google.protobuf.LazyStringArrayList.emptyList();
-      /**
-       * <pre>
-       * IDs of menu item options that are applicable to this menu item.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated string menu_item_option_ids = 1;</code>
-       * @return A list containing the menuItemOptionIds.
-       */
-      public com.google.protobuf.ProtocolStringList
-          getMenuItemOptionIdsList() {
-        return menuItemOptionIds_;
-      }
-      /**
-       * <pre>
-       * IDs of menu item options that are applicable to this menu item.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated string menu_item_option_ids = 1;</code>
-       * @return The count of menuItemOptionIds.
-       */
-      public int getMenuItemOptionIdsCount() {
-        return menuItemOptionIds_.size();
-      }
-      /**
-       * <pre>
-       * IDs of menu item options that are applicable to this menu item.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated string menu_item_option_ids = 1;</code>
-       * @param index The index of the element to return.
-       * @return The menuItemOptionIds at the given index.
-       */
-      public java.lang.String getMenuItemOptionIds(int index) {
-        return menuItemOptionIds_.get(index);
-      }
-      /**
-       * <pre>
-       * IDs of menu item options that are applicable to this menu item.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated string menu_item_option_ids = 1;</code>
-       * @param index The index of the value to return.
-       * @return The bytes of the menuItemOptionIds at the given index.
-       */
-      public com.google.protobuf.ByteString
-          getMenuItemOptionIdsBytes(int index) {
-        return menuItemOptionIds_.getByteString(index);
-      }
-
-      private byte memoizedIsInitialized = -1;
-      @java.lang.Override
-      public final boolean isInitialized() {
-        byte isInitialized = memoizedIsInitialized;
-        if (isInitialized == 1) return true;
-        if (isInitialized == 0) return false;
-
-        memoizedIsInitialized = 1;
-        return true;
-      }
-
-      @java.lang.Override
-      public void writeTo(com.google.protobuf.CodedOutputStream output)
-                          throws java.io.IOException {
-        for (int i = 0; i < menuItemOptionIds_.size(); i++) {
-          com.google.protobuf.GeneratedMessageV3.writeString(output, 1, menuItemOptionIds_.getRaw(i));
-        }
-        getUnknownFields().writeTo(output);
-      }
-
-      @java.lang.Override
-      public int getSerializedSize() {
-        int size = memoizedSize;
-        if (size != -1) return size;
-
-        size = 0;
-        {
-          int dataSize = 0;
-          for (int i = 0; i < menuItemOptionIds_.size(); i++) {
-            dataSize += computeStringSizeNoTag(menuItemOptionIds_.getRaw(i));
-          }
-          size += dataSize;
-          size += 1 * getMenuItemOptionIdsList().size();
-        }
-        size += getUnknownFields().getSerializedSize();
-        memoizedSize = size;
-        return size;
-      }
-
-      @java.lang.Override
-      public boolean equals(final java.lang.Object obj) {
-        if (obj == this) {
-         return true;
-        }
-        if (!(obj instanceof food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet)) {
-          return super.equals(obj);
-        }
-        food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet other = (food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet) obj;
-
-        if (!getMenuItemOptionIdsList()
-            .equals(other.getMenuItemOptionIdsList())) return false;
-        if (!getUnknownFields().equals(other.getUnknownFields())) return false;
-        return true;
-      }
-
-      @java.lang.Override
-      public int hashCode() {
-        if (memoizedHashCode != 0) {
-          return memoizedHashCode;
-        }
-        int hash = 41;
-        hash = (19 * hash) + getDescriptor().hashCode();
-        if (getMenuItemOptionIdsCount() > 0) {
-          hash = (37 * hash) + MENU_ITEM_OPTION_IDS_FIELD_NUMBER;
-          hash = (53 * hash) + getMenuItemOptionIdsList().hashCode();
-        }
-        hash = (29 * hash) + getUnknownFields().hashCode();
-        memoizedHashCode = hash;
-        return hash;
-      }
-
-      public static food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet parseFrom(
-          java.nio.ByteBuffer data)
-          throws com.google.protobuf.InvalidProtocolBufferException {
-        return PARSER.parseFrom(data);
-      }
-      public static food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet parseFrom(
-          java.nio.ByteBuffer data,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws com.google.protobuf.InvalidProtocolBufferException {
-        return PARSER.parseFrom(data, extensionRegistry);
-      }
-      public static food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet parseFrom(
-          com.google.protobuf.ByteString data)
-          throws com.google.protobuf.InvalidProtocolBufferException {
-        return PARSER.parseFrom(data);
-      }
-      public static food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet parseFrom(
-          com.google.protobuf.ByteString data,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws com.google.protobuf.InvalidProtocolBufferException {
-        return PARSER.parseFrom(data, extensionRegistry);
-      }
-      public static food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet parseFrom(byte[] data)
-          throws com.google.protobuf.InvalidProtocolBufferException {
-        return PARSER.parseFrom(data);
-      }
-      public static food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet parseFrom(
-          byte[] data,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws com.google.protobuf.InvalidProtocolBufferException {
-        return PARSER.parseFrom(data, extensionRegistry);
-      }
-      public static food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet parseFrom(java.io.InputStream input)
-          throws java.io.IOException {
-        return com.google.protobuf.GeneratedMessageV3
-            .parseWithIOException(PARSER, input);
-      }
-      public static food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet parseFrom(
-          java.io.InputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws java.io.IOException {
-        return com.google.protobuf.GeneratedMessageV3
-            .parseWithIOException(PARSER, input, extensionRegistry);
-      }
-      public static food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet parseDelimitedFrom(java.io.InputStream input)
-          throws java.io.IOException {
-        return com.google.protobuf.GeneratedMessageV3
-            .parseDelimitedWithIOException(PARSER, input);
-      }
-      public static food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet parseDelimitedFrom(
-          java.io.InputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws java.io.IOException {
-        return com.google.protobuf.GeneratedMessageV3
-            .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
-      }
-      public static food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet parseFrom(
-          com.google.protobuf.CodedInputStream input)
-          throws java.io.IOException {
-        return com.google.protobuf.GeneratedMessageV3
-            .parseWithIOException(PARSER, input);
-      }
-      public static food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet parseFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws java.io.IOException {
-        return com.google.protobuf.GeneratedMessageV3
-            .parseWithIOException(PARSER, input, extensionRegistry);
-      }
-
-      @java.lang.Override
-      public Builder newBuilderForType() { return newBuilder(); }
-      public static Builder newBuilder() {
-        return DEFAULT_INSTANCE.toBuilder();
-      }
-      public static Builder newBuilder(food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet prototype) {
-        return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
-      }
-      @java.lang.Override
-      public Builder toBuilder() {
-        return this == DEFAULT_INSTANCE
-            ? new Builder() : new Builder().mergeFrom(this);
-      }
-
-      @java.lang.Override
-      protected Builder newBuilderForType(
-          com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-        Builder builder = new Builder(parent);
-        return builder;
-      }
-      /**
-       * <pre>
-       * Container that specifies a list of options available on an item.
-       * </pre>
-       *
-       * Protobuf type {@code food.menu.v1.MenuItem.MenuItemOptionSet}
-       */
-      public static final class Builder extends
-          com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
-          // @@protoc_insertion_point(builder_implements:food.menu.v1.MenuItem.MenuItemOptionSet)
-          food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSetOrBuilder {
-        public static final com.google.protobuf.Descriptors.Descriptor
-            getDescriptor() {
-          return food.menu.v1.FoodMenu.internal_static_food_menu_v1_MenuItem_MenuItemOptionSet_descriptor;
-        }
-
-        @java.lang.Override
-        protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-            internalGetFieldAccessorTable() {
-          return food.menu.v1.FoodMenu.internal_static_food_menu_v1_MenuItem_MenuItemOptionSet_fieldAccessorTable
-              .ensureFieldAccessorsInitialized(
-                  food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet.class, food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet.Builder.class);
-        }
-
-        // Construct using food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet.newBuilder()
-        private Builder() {
-
-        }
-
-        private Builder(
-            com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-          super(parent);
-
-        }
-        @java.lang.Override
-        public Builder clear() {
-          super.clear();
-          bitField0_ = 0;
-          menuItemOptionIds_ =
-              com.google.protobuf.LazyStringArrayList.emptyList();
-          return this;
-        }
-
-        @java.lang.Override
-        public com.google.protobuf.Descriptors.Descriptor
-            getDescriptorForType() {
-          return food.menu.v1.FoodMenu.internal_static_food_menu_v1_MenuItem_MenuItemOptionSet_descriptor;
-        }
-
-        @java.lang.Override
-        public food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet getDefaultInstanceForType() {
-          return food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet.getDefaultInstance();
-        }
-
-        @java.lang.Override
-        public food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet build() {
-          food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet result = buildPartial();
-          if (!result.isInitialized()) {
-            throw newUninitializedMessageException(result);
-          }
-          return result;
-        }
-
-        @java.lang.Override
-        public food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet buildPartial() {
-          food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet result = new food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet(this);
-          if (bitField0_ != 0) { buildPartial0(result); }
-          onBuilt();
-          return result;
-        }
-
-        private void buildPartial0(food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet result) {
-          int from_bitField0_ = bitField0_;
-          if (((from_bitField0_ & 0x00000001) != 0)) {
-            menuItemOptionIds_.makeImmutable();
-            result.menuItemOptionIds_ = menuItemOptionIds_;
-          }
-        }
-
-        @java.lang.Override
-        public Builder mergeFrom(com.google.protobuf.Message other) {
-          if (other instanceof food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet) {
-            return mergeFrom((food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet)other);
-          } else {
-            super.mergeFrom(other);
-            return this;
-          }
-        }
-
-        public Builder mergeFrom(food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet other) {
-          if (other == food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet.getDefaultInstance()) return this;
-          if (!other.menuItemOptionIds_.isEmpty()) {
-            if (menuItemOptionIds_.isEmpty()) {
-              menuItemOptionIds_ = other.menuItemOptionIds_;
-              bitField0_ |= 0x00000001;
-            } else {
-              ensureMenuItemOptionIdsIsMutable();
-              menuItemOptionIds_.addAll(other.menuItemOptionIds_);
-            }
-            onChanged();
-          }
-          this.mergeUnknownFields(other.getUnknownFields());
-          onChanged();
-          return this;
-        }
-
-        @java.lang.Override
-        public final boolean isInitialized() {
-          return true;
-        }
-
-        @java.lang.Override
-        public Builder mergeFrom(
-            com.google.protobuf.CodedInputStream input,
-            com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-            throws java.io.IOException {
-          if (extensionRegistry == null) {
-            throw new java.lang.NullPointerException();
-          }
-          try {
-            boolean done = false;
-            while (!done) {
-              int tag = input.readTag();
-              switch (tag) {
-                case 0:
-                  done = true;
-                  break;
-                case 10: {
-                  java.lang.String s = input.readStringRequireUtf8();
-                  ensureMenuItemOptionIdsIsMutable();
-                  menuItemOptionIds_.add(s);
-                  break;
-                } // case 10
-                default: {
-                  if (!super.parseUnknownField(input, extensionRegistry, tag)) {
-                    done = true; // was an endgroup tag
-                  }
-                  break;
-                } // default:
-              } // switch (tag)
-            } // while (!done)
-          } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-            throw e.unwrapIOException();
-          } finally {
-            onChanged();
-          } // finally
-          return this;
-        }
-        private int bitField0_;
-
-        private com.google.protobuf.LazyStringArrayList menuItemOptionIds_ =
-            com.google.protobuf.LazyStringArrayList.emptyList();
-        private void ensureMenuItemOptionIdsIsMutable() {
-          if (!menuItemOptionIds_.isModifiable()) {
-            menuItemOptionIds_ = new com.google.protobuf.LazyStringArrayList(menuItemOptionIds_);
-          }
-          bitField0_ |= 0x00000001;
-        }
-        /**
-         * <pre>
-         * IDs of menu item options that are applicable to this menu item.
-         * Required.
-         * </pre>
-         *
-         * <code>repeated string menu_item_option_ids = 1;</code>
-         * @return A list containing the menuItemOptionIds.
-         */
-        public com.google.protobuf.ProtocolStringList
-            getMenuItemOptionIdsList() {
-          menuItemOptionIds_.makeImmutable();
-          return menuItemOptionIds_;
-        }
-        /**
-         * <pre>
-         * IDs of menu item options that are applicable to this menu item.
-         * Required.
-         * </pre>
-         *
-         * <code>repeated string menu_item_option_ids = 1;</code>
-         * @return The count of menuItemOptionIds.
-         */
-        public int getMenuItemOptionIdsCount() {
-          return menuItemOptionIds_.size();
-        }
-        /**
-         * <pre>
-         * IDs of menu item options that are applicable to this menu item.
-         * Required.
-         * </pre>
-         *
-         * <code>repeated string menu_item_option_ids = 1;</code>
-         * @param index The index of the element to return.
-         * @return The menuItemOptionIds at the given index.
-         */
-        public java.lang.String getMenuItemOptionIds(int index) {
-          return menuItemOptionIds_.get(index);
-        }
-        /**
-         * <pre>
-         * IDs of menu item options that are applicable to this menu item.
-         * Required.
-         * </pre>
-         *
-         * <code>repeated string menu_item_option_ids = 1;</code>
-         * @param index The index of the value to return.
-         * @return The bytes of the menuItemOptionIds at the given index.
-         */
-        public com.google.protobuf.ByteString
-            getMenuItemOptionIdsBytes(int index) {
-          return menuItemOptionIds_.getByteString(index);
-        }
-        /**
-         * <pre>
-         * IDs of menu item options that are applicable to this menu item.
-         * Required.
-         * </pre>
-         *
-         * <code>repeated string menu_item_option_ids = 1;</code>
-         * @param index The index to set the value at.
-         * @param value The menuItemOptionIds to set.
-         * @return This builder for chaining.
-         */
-        public Builder setMenuItemOptionIds(
-            int index, java.lang.String value) {
-          if (value == null) { throw new NullPointerException(); }
-          ensureMenuItemOptionIdsIsMutable();
-          menuItemOptionIds_.set(index, value);
-          bitField0_ |= 0x00000001;
-          onChanged();
-          return this;
-        }
-        /**
-         * <pre>
-         * IDs of menu item options that are applicable to this menu item.
-         * Required.
-         * </pre>
-         *
-         * <code>repeated string menu_item_option_ids = 1;</code>
-         * @param value The menuItemOptionIds to add.
-         * @return This builder for chaining.
-         */
-        public Builder addMenuItemOptionIds(
-            java.lang.String value) {
-          if (value == null) { throw new NullPointerException(); }
-          ensureMenuItemOptionIdsIsMutable();
-          menuItemOptionIds_.add(value);
-          bitField0_ |= 0x00000001;
-          onChanged();
-          return this;
-        }
-        /**
-         * <pre>
-         * IDs of menu item options that are applicable to this menu item.
-         * Required.
-         * </pre>
-         *
-         * <code>repeated string menu_item_option_ids = 1;</code>
-         * @param values The menuItemOptionIds to add.
-         * @return This builder for chaining.
-         */
-        public Builder addAllMenuItemOptionIds(
-            java.lang.Iterable<java.lang.String> values) {
-          ensureMenuItemOptionIdsIsMutable();
-          com.google.protobuf.AbstractMessageLite.Builder.addAll(
-              values, menuItemOptionIds_);
-          bitField0_ |= 0x00000001;
-          onChanged();
-          return this;
-        }
-        /**
-         * <pre>
-         * IDs of menu item options that are applicable to this menu item.
-         * Required.
-         * </pre>
-         *
-         * <code>repeated string menu_item_option_ids = 1;</code>
-         * @return This builder for chaining.
-         */
-        public Builder clearMenuItemOptionIds() {
-          menuItemOptionIds_ =
-            com.google.protobuf.LazyStringArrayList.emptyList();
-          bitField0_ = (bitField0_ & ~0x00000001);;
-          onChanged();
-          return this;
-        }
-        /**
-         * <pre>
-         * IDs of menu item options that are applicable to this menu item.
-         * Required.
-         * </pre>
-         *
-         * <code>repeated string menu_item_option_ids = 1;</code>
-         * @param value The bytes of the menuItemOptionIds to add.
-         * @return This builder for chaining.
-         */
-        public Builder addMenuItemOptionIdsBytes(
-            com.google.protobuf.ByteString value) {
-          if (value == null) { throw new NullPointerException(); }
-          checkByteStringIsUtf8(value);
-          ensureMenuItemOptionIdsIsMutable();
-          menuItemOptionIds_.add(value);
-          bitField0_ |= 0x00000001;
-          onChanged();
-          return this;
-        }
-        @java.lang.Override
-        public final Builder setUnknownFields(
-            final com.google.protobuf.UnknownFieldSet unknownFields) {
-          return super.setUnknownFields(unknownFields);
-        }
-
-        @java.lang.Override
-        public final Builder mergeUnknownFields(
-            final com.google.protobuf.UnknownFieldSet unknownFields) {
-          return super.mergeUnknownFields(unknownFields);
-        }
-
-
-        // @@protoc_insertion_point(builder_scope:food.menu.v1.MenuItem.MenuItemOptionSet)
-      }
-
-      // @@protoc_insertion_point(class_scope:food.menu.v1.MenuItem.MenuItemOptionSet)
-      private static final food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet DEFAULT_INSTANCE;
-      static {
-        DEFAULT_INSTANCE = new food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet();
-      }
-
-      public static food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet getDefaultInstance() {
-        return DEFAULT_INSTANCE;
-      }
-
-      private static final com.google.protobuf.Parser<MenuItemOptionSet>
-          PARSER = new com.google.protobuf.AbstractParser<MenuItemOptionSet>() {
-        @java.lang.Override
-        public MenuItemOptionSet parsePartialFrom(
-            com.google.protobuf.CodedInputStream input,
-            com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-            throws com.google.protobuf.InvalidProtocolBufferException {
-          Builder builder = newBuilder();
-          try {
-            builder.mergeFrom(input, extensionRegistry);
-          } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-            throw e.setUnfinishedMessage(builder.buildPartial());
-          } catch (com.google.protobuf.UninitializedMessageException e) {
-            throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
-          } catch (java.io.IOException e) {
-            throw new com.google.protobuf.InvalidProtocolBufferException(e)
-                .setUnfinishedMessage(builder.buildPartial());
-          }
-          return builder.buildPartial();
-        }
-      };
-
-      public static com.google.protobuf.Parser<MenuItemOptionSet> parser() {
-        return PARSER;
-      }
-
-      @java.lang.Override
-      public com.google.protobuf.Parser<MenuItemOptionSet> getParserForType() {
-        return PARSER;
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet getDefaultInstanceForType() {
-        return DEFAULT_INSTANCE;
-      }
-
-    }
-
-    private int pricingCase_ = 0;
-    @SuppressWarnings("serial")
-    private java.lang.Object pricing_;
-    public enum PricingCase
-        implements com.google.protobuf.Internal.EnumLite,
-            com.google.protobuf.AbstractMessage.InternalOneOfEnum {
-      OFFER_SET(6),
-      MENU_ITEM_OPTION_SET(7),
-      PRICING_NOT_SET(0);
-      private final int value;
-      private PricingCase(int value) {
-        this.value = value;
-      }
-      /**
-       * @param value The number of the enum to look for.
-       * @return The enum associated with the given number.
-       * @deprecated Use {@link #forNumber(int)} instead.
-       */
-      @java.lang.Deprecated
-      public static PricingCase valueOf(int value) {
-        return forNumber(value);
-      }
-
-      public static PricingCase forNumber(int value) {
-        switch (value) {
-          case 6: return OFFER_SET;
-          case 7: return MENU_ITEM_OPTION_SET;
-          case 0: return PRICING_NOT_SET;
-          default: return null;
-        }
-      }
-      public int getNumber() {
-        return this.value;
-      }
-    };
-
-    public PricingCase
-    getPricingCase() {
-      return PricingCase.forNumber(
-          pricingCase_);
-    }
-
-    public static final int MENU_ITEM_ID_FIELD_NUMBER = 1;
-    @SuppressWarnings("serial")
-    private volatile java.lang.Object menuItemId_ = "";
-    /**
-     * <pre>
-     * An opaque string from an partner which uniquely identifies the MenuItem
-     * within the partner feed.
-     * Required.
-     * </pre>
-     *
-     * <code>string menu_item_id = 1;</code>
-     * @return The menuItemId.
-     */
-    @java.lang.Override
-    public java.lang.String getMenuItemId() {
-      java.lang.Object ref = menuItemId_;
-      if (ref instanceof java.lang.String) {
-        return (java.lang.String) ref;
-      } else {
-        com.google.protobuf.ByteString bs = 
-            (com.google.protobuf.ByteString) ref;
-        java.lang.String s = bs.toStringUtf8();
-        menuItemId_ = s;
-        return s;
-      }
-    }
-    /**
-     * <pre>
-     * An opaque string from an partner which uniquely identifies the MenuItem
-     * within the partner feed.
-     * Required.
-     * </pre>
-     *
-     * <code>string menu_item_id = 1;</code>
-     * @return The bytes for menuItemId.
-     */
-    @java.lang.Override
-    public com.google.protobuf.ByteString
-        getMenuItemIdBytes() {
-      java.lang.Object ref = menuItemId_;
-      if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
-            com.google.protobuf.ByteString.copyFromUtf8(
-                (java.lang.String) ref);
-        menuItemId_ = b;
-        return b;
-      } else {
-        return (com.google.protobuf.ByteString) ref;
-      }
-    }
-
-    public static final int DISPLAY_NAME_FIELD_NUMBER = 2;
-    private food.menu.v1.FoodMenu.TextField displayName_;
-    /**
-     * <pre>
-     * The name that can identify the MenuItem when a user is browsing the menu.
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField display_name = 2;</code>
-     * @return Whether the displayName field is set.
-     */
-    @java.lang.Override
-    public boolean hasDisplayName() {
-      return displayName_ != null;
-    }
-    /**
-     * <pre>
-     * The name that can identify the MenuItem when a user is browsing the menu.
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField display_name = 2;</code>
-     * @return The displayName.
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.TextField getDisplayName() {
-      return displayName_ == null ? food.menu.v1.FoodMenu.TextField.getDefaultInstance() : displayName_;
-    }
-    /**
-     * <pre>
-     * The name that can identify the MenuItem when a user is browsing the menu.
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField display_name = 2;</code>
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.TextFieldOrBuilder getDisplayNameOrBuilder() {
-      return displayName_ == null ? food.menu.v1.FoodMenu.TextField.getDefaultInstance() : displayName_;
-    }
-
-    public static final int DESCRIPTION_FIELD_NUMBER = 3;
-    private food.menu.v1.FoodMenu.TextField description_;
-    /**
-     * <pre>
-     * A description of the menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField description = 3;</code>
-     * @return Whether the description field is set.
-     */
-    @java.lang.Override
-    public boolean hasDescription() {
-      return description_ != null;
-    }
-    /**
-     * <pre>
-     * A description of the menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField description = 3;</code>
-     * @return The description.
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.TextField getDescription() {
-      return description_ == null ? food.menu.v1.FoodMenu.TextField.getDefaultInstance() : description_;
-    }
-    /**
-     * <pre>
-     * A description of the menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField description = 3;</code>
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.TextFieldOrBuilder getDescriptionOrBuilder() {
-      return description_ == null ? food.menu.v1.FoodMenu.TextField.getDefaultInstance() : description_;
-    }
-
-    public static final int IMAGES_FIELD_NUMBER = 4;
-    @SuppressWarnings("serial")
-    private java.util.List<food.menu.v1.FoodMenu.Image> images_;
-    /**
-     * <pre>
-     * Image(s) of the menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Image images = 4;</code>
-     */
-    @java.lang.Override
-    public java.util.List<food.menu.v1.FoodMenu.Image> getImagesList() {
-      return images_;
-    }
-    /**
-     * <pre>
-     * Image(s) of the menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Image images = 4;</code>
-     */
-    @java.lang.Override
-    public java.util.List<? extends food.menu.v1.FoodMenu.ImageOrBuilder> 
-        getImagesOrBuilderList() {
-      return images_;
-    }
-    /**
-     * <pre>
-     * Image(s) of the menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Image images = 4;</code>
-     */
-    @java.lang.Override
-    public int getImagesCount() {
-      return images_.size();
-    }
-    /**
-     * <pre>
-     * Image(s) of the menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Image images = 4;</code>
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.Image getImages(int index) {
-      return images_.get(index);
-    }
-    /**
-     * <pre>
-     * Image(s) of the menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Image images = 4;</code>
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.ImageOrBuilder getImagesOrBuilder(
-        int index) {
-      return images_.get(index);
-    }
-
-    public static final int OFFER_SET_FIELD_NUMBER = 6;
-    /**
-     * <pre>
-     * Available offers to purchase this food item.
-     * </pre>
-     *
-     * <code>.food.menu.v1.OfferSet offer_set = 6;</code>
-     * @return Whether the offerSet field is set.
-     */
-    @java.lang.Override
-    public boolean hasOfferSet() {
-      return pricingCase_ == 6;
-    }
-    /**
-     * <pre>
-     * Available offers to purchase this food item.
-     * </pre>
-     *
-     * <code>.food.menu.v1.OfferSet offer_set = 6;</code>
-     * @return The offerSet.
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.OfferSet getOfferSet() {
-      if (pricingCase_ == 6) {
-         return (food.menu.v1.FoodMenu.OfferSet) pricing_;
-      }
-      return food.menu.v1.FoodMenu.OfferSet.getDefaultInstance();
-    }
-    /**
-     * <pre>
-     * Available offers to purchase this food item.
-     * </pre>
-     *
-     * <code>.food.menu.v1.OfferSet offer_set = 6;</code>
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.OfferSetOrBuilder getOfferSetOrBuilder() {
-      if (pricingCase_ == 6) {
-         return (food.menu.v1.FoodMenu.OfferSet) pricing_;
-      }
-      return food.menu.v1.FoodMenu.OfferSet.getDefaultInstance();
-    }
-
-    public static final int MENU_ITEM_OPTION_SET_FIELD_NUMBER = 7;
-    /**
-     * <pre>
-     * Available options for this menu item.
-     * </pre>
-     *
-     * <code>.food.menu.v1.MenuItem.MenuItemOptionSet menu_item_option_set = 7;</code>
-     * @return Whether the menuItemOptionSet field is set.
-     */
-    @java.lang.Override
-    public boolean hasMenuItemOptionSet() {
-      return pricingCase_ == 7;
-    }
-    /**
-     * <pre>
-     * Available options for this menu item.
-     * </pre>
-     *
-     * <code>.food.menu.v1.MenuItem.MenuItemOptionSet menu_item_option_set = 7;</code>
-     * @return The menuItemOptionSet.
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet getMenuItemOptionSet() {
-      if (pricingCase_ == 7) {
-         return (food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet) pricing_;
-      }
-      return food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet.getDefaultInstance();
-    }
-    /**
-     * <pre>
-     * Available options for this menu item.
-     * </pre>
-     *
-     * <code>.food.menu.v1.MenuItem.MenuItemOptionSet menu_item_option_set = 7;</code>
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSetOrBuilder getMenuItemOptionSetOrBuilder() {
-      if (pricingCase_ == 7) {
-         return (food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet) pricing_;
-      }
-      return food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet.getDefaultInstance();
-    }
-
-    public static final int ITEM_ATTRIBUTES_FIELD_NUMBER = 8;
-    private food.menu.v1.FoodMenu.MenuItemAttributes itemAttributes_;
-    /**
-     * <pre>
-     * Attributes about this menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.MenuItemAttributes item_attributes = 8;</code>
-     * @return Whether the itemAttributes field is set.
-     */
-    @java.lang.Override
-    public boolean hasItemAttributes() {
-      return itemAttributes_ != null;
-    }
-    /**
-     * <pre>
-     * Attributes about this menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.MenuItemAttributes item_attributes = 8;</code>
-     * @return The itemAttributes.
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.MenuItemAttributes getItemAttributes() {
-      return itemAttributes_ == null ? food.menu.v1.FoodMenu.MenuItemAttributes.getDefaultInstance() : itemAttributes_;
-    }
-    /**
-     * <pre>
-     * Attributes about this menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.MenuItemAttributes item_attributes = 8;</code>
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.MenuItemAttributesOrBuilder getItemAttributesOrBuilder() {
-      return itemAttributes_ == null ? food.menu.v1.FoodMenu.MenuItemAttributes.getDefaultInstance() : itemAttributes_;
-    }
-
-    private byte memoizedIsInitialized = -1;
-    @java.lang.Override
-    public final boolean isInitialized() {
-      byte isInitialized = memoizedIsInitialized;
-      if (isInitialized == 1) return true;
-      if (isInitialized == 0) return false;
-
-      memoizedIsInitialized = 1;
-      return true;
-    }
-
-    @java.lang.Override
-    public void writeTo(com.google.protobuf.CodedOutputStream output)
-                        throws java.io.IOException {
-      if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(menuItemId_)) {
-        com.google.protobuf.GeneratedMessageV3.writeString(output, 1, menuItemId_);
-      }
-      if (displayName_ != null) {
-        output.writeMessage(2, getDisplayName());
-      }
-      if (description_ != null) {
-        output.writeMessage(3, getDescription());
-      }
-      for (int i = 0; i < images_.size(); i++) {
-        output.writeMessage(4, images_.get(i));
-      }
-      if (pricingCase_ == 6) {
-        output.writeMessage(6, (food.menu.v1.FoodMenu.OfferSet) pricing_);
-      }
-      if (pricingCase_ == 7) {
-        output.writeMessage(7, (food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet) pricing_);
-      }
-      if (itemAttributes_ != null) {
-        output.writeMessage(8, getItemAttributes());
-      }
-      getUnknownFields().writeTo(output);
-    }
-
-    @java.lang.Override
-    public int getSerializedSize() {
-      int size = memoizedSize;
-      if (size != -1) return size;
-
-      size = 0;
-      if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(menuItemId_)) {
-        size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, menuItemId_);
-      }
-      if (displayName_ != null) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(2, getDisplayName());
-      }
-      if (description_ != null) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(3, getDescription());
-      }
-      for (int i = 0; i < images_.size(); i++) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(4, images_.get(i));
-      }
-      if (pricingCase_ == 6) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(6, (food.menu.v1.FoodMenu.OfferSet) pricing_);
-      }
-      if (pricingCase_ == 7) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(7, (food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet) pricing_);
-      }
-      if (itemAttributes_ != null) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(8, getItemAttributes());
-      }
-      size += getUnknownFields().getSerializedSize();
-      memoizedSize = size;
-      return size;
-    }
-
-    @java.lang.Override
-    public boolean equals(final java.lang.Object obj) {
-      if (obj == this) {
-       return true;
-      }
-      if (!(obj instanceof food.menu.v1.FoodMenu.MenuItem)) {
-        return super.equals(obj);
-      }
-      food.menu.v1.FoodMenu.MenuItem other = (food.menu.v1.FoodMenu.MenuItem) obj;
-
-      if (!getMenuItemId()
-          .equals(other.getMenuItemId())) return false;
-      if (hasDisplayName() != other.hasDisplayName()) return false;
-      if (hasDisplayName()) {
-        if (!getDisplayName()
-            .equals(other.getDisplayName())) return false;
-      }
-      if (hasDescription() != other.hasDescription()) return false;
-      if (hasDescription()) {
-        if (!getDescription()
-            .equals(other.getDescription())) return false;
-      }
-      if (!getImagesList()
-          .equals(other.getImagesList())) return false;
-      if (hasItemAttributes() != other.hasItemAttributes()) return false;
-      if (hasItemAttributes()) {
-        if (!getItemAttributes()
-            .equals(other.getItemAttributes())) return false;
-      }
-      if (!getPricingCase().equals(other.getPricingCase())) return false;
-      switch (pricingCase_) {
-        case 6:
-          if (!getOfferSet()
-              .equals(other.getOfferSet())) return false;
-          break;
-        case 7:
-          if (!getMenuItemOptionSet()
-              .equals(other.getMenuItemOptionSet())) return false;
-          break;
-        case 0:
-        default:
-      }
-      if (!getUnknownFields().equals(other.getUnknownFields())) return false;
-      return true;
-    }
-
-    @java.lang.Override
-    public int hashCode() {
-      if (memoizedHashCode != 0) {
-        return memoizedHashCode;
-      }
-      int hash = 41;
-      hash = (19 * hash) + getDescriptor().hashCode();
-      hash = (37 * hash) + MENU_ITEM_ID_FIELD_NUMBER;
-      hash = (53 * hash) + getMenuItemId().hashCode();
-      if (hasDisplayName()) {
-        hash = (37 * hash) + DISPLAY_NAME_FIELD_NUMBER;
-        hash = (53 * hash) + getDisplayName().hashCode();
-      }
-      if (hasDescription()) {
-        hash = (37 * hash) + DESCRIPTION_FIELD_NUMBER;
-        hash = (53 * hash) + getDescription().hashCode();
-      }
-      if (getImagesCount() > 0) {
-        hash = (37 * hash) + IMAGES_FIELD_NUMBER;
-        hash = (53 * hash) + getImagesList().hashCode();
-      }
-      if (hasItemAttributes()) {
-        hash = (37 * hash) + ITEM_ATTRIBUTES_FIELD_NUMBER;
-        hash = (53 * hash) + getItemAttributes().hashCode();
-      }
-      switch (pricingCase_) {
-        case 6:
-          hash = (37 * hash) + OFFER_SET_FIELD_NUMBER;
-          hash = (53 * hash) + getOfferSet().hashCode();
-          break;
-        case 7:
-          hash = (37 * hash) + MENU_ITEM_OPTION_SET_FIELD_NUMBER;
-          hash = (53 * hash) + getMenuItemOptionSet().hashCode();
-          break;
-        case 0:
-        default:
-      }
-      hash = (29 * hash) + getUnknownFields().hashCode();
-      memoizedHashCode = hash;
-      return hash;
-    }
-
-    public static food.menu.v1.FoodMenu.MenuItem parseFrom(
-        java.nio.ByteBuffer data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.MenuItem parseFrom(
-        java.nio.ByteBuffer data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.MenuItem parseFrom(
-        com.google.protobuf.ByteString data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.MenuItem parseFrom(
-        com.google.protobuf.ByteString data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.MenuItem parseFrom(byte[] data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.MenuItem parseFrom(
-        byte[] data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.MenuItem parseFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.MenuItem parseFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.MenuItem parseDelimitedFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseDelimitedWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.MenuItem parseDelimitedFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.MenuItem parseFrom(
-        com.google.protobuf.CodedInputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.MenuItem parseFrom(
-        com.google.protobuf.CodedInputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input, extensionRegistry);
-    }
-
-    @java.lang.Override
-    public Builder newBuilderForType() { return newBuilder(); }
-    public static Builder newBuilder() {
-      return DEFAULT_INSTANCE.toBuilder();
-    }
-    public static Builder newBuilder(food.menu.v1.FoodMenu.MenuItem prototype) {
-      return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
-    }
-    @java.lang.Override
-    public Builder toBuilder() {
-      return this == DEFAULT_INSTANCE
-          ? new Builder() : new Builder().mergeFrom(this);
-    }
-
-    @java.lang.Override
-    protected Builder newBuilderForType(
-        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-      Builder builder = new Builder(parent);
-      return builder;
-    }
-    /**
-     * <pre>
-     * Represents a single food or drink item offered by a Food establishment.
-     * </pre>
-     *
-     * Protobuf type {@code food.menu.v1.MenuItem}
-     */
-    public static final class Builder extends
-        com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
-        // @@protoc_insertion_point(builder_implements:food.menu.v1.MenuItem)
-        food.menu.v1.FoodMenu.MenuItemOrBuilder {
-      public static final com.google.protobuf.Descriptors.Descriptor
-          getDescriptor() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_MenuItem_descriptor;
-      }
-
-      @java.lang.Override
-      protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-          internalGetFieldAccessorTable() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_MenuItem_fieldAccessorTable
-            .ensureFieldAccessorsInitialized(
-                food.menu.v1.FoodMenu.MenuItem.class, food.menu.v1.FoodMenu.MenuItem.Builder.class);
-      }
-
-      // Construct using food.menu.v1.FoodMenu.MenuItem.newBuilder()
-      private Builder() {
-
-      }
-
-      private Builder(
-          com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-        super(parent);
-
-      }
-      @java.lang.Override
-      public Builder clear() {
-        super.clear();
-        bitField0_ = 0;
-        menuItemId_ = "";
-        displayName_ = null;
-        if (displayNameBuilder_ != null) {
-          displayNameBuilder_.dispose();
-          displayNameBuilder_ = null;
-        }
-        description_ = null;
-        if (descriptionBuilder_ != null) {
-          descriptionBuilder_.dispose();
-          descriptionBuilder_ = null;
-        }
-        if (imagesBuilder_ == null) {
-          images_ = java.util.Collections.emptyList();
-        } else {
-          images_ = null;
-          imagesBuilder_.clear();
-        }
-        bitField0_ = (bitField0_ & ~0x00000008);
-        if (offerSetBuilder_ != null) {
-          offerSetBuilder_.clear();
-        }
-        if (menuItemOptionSetBuilder_ != null) {
-          menuItemOptionSetBuilder_.clear();
-        }
-        itemAttributes_ = null;
-        if (itemAttributesBuilder_ != null) {
-          itemAttributesBuilder_.dispose();
-          itemAttributesBuilder_ = null;
-        }
-        pricingCase_ = 0;
-        pricing_ = null;
-        return this;
-      }
-
-      @java.lang.Override
-      public com.google.protobuf.Descriptors.Descriptor
-          getDescriptorForType() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_MenuItem_descriptor;
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.MenuItem getDefaultInstanceForType() {
-        return food.menu.v1.FoodMenu.MenuItem.getDefaultInstance();
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.MenuItem build() {
-        food.menu.v1.FoodMenu.MenuItem result = buildPartial();
-        if (!result.isInitialized()) {
-          throw newUninitializedMessageException(result);
-        }
-        return result;
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.MenuItem buildPartial() {
-        food.menu.v1.FoodMenu.MenuItem result = new food.menu.v1.FoodMenu.MenuItem(this);
-        buildPartialRepeatedFields(result);
-        if (bitField0_ != 0) { buildPartial0(result); }
-        buildPartialOneofs(result);
-        onBuilt();
-        return result;
-      }
-
-      private void buildPartialRepeatedFields(food.menu.v1.FoodMenu.MenuItem result) {
-        if (imagesBuilder_ == null) {
-          if (((bitField0_ & 0x00000008) != 0)) {
-            images_ = java.util.Collections.unmodifiableList(images_);
-            bitField0_ = (bitField0_ & ~0x00000008);
-          }
-          result.images_ = images_;
-        } else {
-          result.images_ = imagesBuilder_.build();
-        }
-      }
-
-      private void buildPartial0(food.menu.v1.FoodMenu.MenuItem result) {
-        int from_bitField0_ = bitField0_;
-        if (((from_bitField0_ & 0x00000001) != 0)) {
-          result.menuItemId_ = menuItemId_;
-        }
-        if (((from_bitField0_ & 0x00000002) != 0)) {
-          result.displayName_ = displayNameBuilder_ == null
-              ? displayName_
-              : displayNameBuilder_.build();
-        }
-        if (((from_bitField0_ & 0x00000004) != 0)) {
-          result.description_ = descriptionBuilder_ == null
-              ? description_
-              : descriptionBuilder_.build();
-        }
-        if (((from_bitField0_ & 0x00000040) != 0)) {
-          result.itemAttributes_ = itemAttributesBuilder_ == null
-              ? itemAttributes_
-              : itemAttributesBuilder_.build();
-        }
-      }
-
-      private void buildPartialOneofs(food.menu.v1.FoodMenu.MenuItem result) {
-        result.pricingCase_ = pricingCase_;
-        result.pricing_ = this.pricing_;
-        if (pricingCase_ == 6 &&
-            offerSetBuilder_ != null) {
-          result.pricing_ = offerSetBuilder_.build();
-        }
-        if (pricingCase_ == 7 &&
-            menuItemOptionSetBuilder_ != null) {
-          result.pricing_ = menuItemOptionSetBuilder_.build();
-        }
-      }
-
-      @java.lang.Override
-      public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof food.menu.v1.FoodMenu.MenuItem) {
-          return mergeFrom((food.menu.v1.FoodMenu.MenuItem)other);
-        } else {
-          super.mergeFrom(other);
-          return this;
-        }
-      }
-
-      public Builder mergeFrom(food.menu.v1.FoodMenu.MenuItem other) {
-        if (other == food.menu.v1.FoodMenu.MenuItem.getDefaultInstance()) return this;
-        if (!other.getMenuItemId().isEmpty()) {
-          menuItemId_ = other.menuItemId_;
-          bitField0_ |= 0x00000001;
-          onChanged();
-        }
-        if (other.hasDisplayName()) {
-          mergeDisplayName(other.getDisplayName());
-        }
-        if (other.hasDescription()) {
-          mergeDescription(other.getDescription());
-        }
-        if (imagesBuilder_ == null) {
-          if (!other.images_.isEmpty()) {
-            if (images_.isEmpty()) {
-              images_ = other.images_;
-              bitField0_ = (bitField0_ & ~0x00000008);
-            } else {
-              ensureImagesIsMutable();
-              images_.addAll(other.images_);
-            }
-            onChanged();
-          }
-        } else {
-          if (!other.images_.isEmpty()) {
-            if (imagesBuilder_.isEmpty()) {
-              imagesBuilder_.dispose();
-              imagesBuilder_ = null;
-              images_ = other.images_;
-              bitField0_ = (bitField0_ & ~0x00000008);
-              imagesBuilder_ = 
-                com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ?
-                   getImagesFieldBuilder() : null;
-            } else {
-              imagesBuilder_.addAllMessages(other.images_);
-            }
-          }
-        }
-        if (other.hasItemAttributes()) {
-          mergeItemAttributes(other.getItemAttributes());
-        }
-        switch (other.getPricingCase()) {
-          case OFFER_SET: {
-            mergeOfferSet(other.getOfferSet());
-            break;
-          }
-          case MENU_ITEM_OPTION_SET: {
-            mergeMenuItemOptionSet(other.getMenuItemOptionSet());
-            break;
-          }
-          case PRICING_NOT_SET: {
-            break;
-          }
-        }
-        this.mergeUnknownFields(other.getUnknownFields());
-        onChanged();
-        return this;
-      }
-
-      @java.lang.Override
-      public final boolean isInitialized() {
-        return true;
-      }
-
-      @java.lang.Override
-      public Builder mergeFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws java.io.IOException {
-        if (extensionRegistry == null) {
-          throw new java.lang.NullPointerException();
-        }
-        try {
-          boolean done = false;
-          while (!done) {
-            int tag = input.readTag();
-            switch (tag) {
-              case 0:
-                done = true;
-                break;
-              case 10: {
-                menuItemId_ = input.readStringRequireUtf8();
-                bitField0_ |= 0x00000001;
-                break;
-              } // case 10
-              case 18: {
-                input.readMessage(
-                    getDisplayNameFieldBuilder().getBuilder(),
-                    extensionRegistry);
-                bitField0_ |= 0x00000002;
-                break;
-              } // case 18
-              case 26: {
-                input.readMessage(
-                    getDescriptionFieldBuilder().getBuilder(),
-                    extensionRegistry);
-                bitField0_ |= 0x00000004;
-                break;
-              } // case 26
-              case 34: {
-                food.menu.v1.FoodMenu.Image m =
-                    input.readMessage(
-                        food.menu.v1.FoodMenu.Image.parser(),
-                        extensionRegistry);
-                if (imagesBuilder_ == null) {
-                  ensureImagesIsMutable();
-                  images_.add(m);
-                } else {
-                  imagesBuilder_.addMessage(m);
-                }
-                break;
-              } // case 34
-              case 50: {
-                input.readMessage(
-                    getOfferSetFieldBuilder().getBuilder(),
-                    extensionRegistry);
-                pricingCase_ = 6;
-                break;
-              } // case 50
-              case 58: {
-                input.readMessage(
-                    getMenuItemOptionSetFieldBuilder().getBuilder(),
-                    extensionRegistry);
-                pricingCase_ = 7;
-                break;
-              } // case 58
-              case 66: {
-                input.readMessage(
-                    getItemAttributesFieldBuilder().getBuilder(),
-                    extensionRegistry);
-                bitField0_ |= 0x00000040;
-                break;
-              } // case 66
-              default: {
-                if (!super.parseUnknownField(input, extensionRegistry, tag)) {
-                  done = true; // was an endgroup tag
-                }
-                break;
-              } // default:
-            } // switch (tag)
-          } // while (!done)
-        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          throw e.unwrapIOException();
-        } finally {
-          onChanged();
-        } // finally
-        return this;
-      }
-      private int pricingCase_ = 0;
-      private java.lang.Object pricing_;
-      public PricingCase
-          getPricingCase() {
-        return PricingCase.forNumber(
-            pricingCase_);
-      }
-
-      public Builder clearPricing() {
-        pricingCase_ = 0;
-        pricing_ = null;
-        onChanged();
-        return this;
-      }
-
-      private int bitField0_;
-
-      private java.lang.Object menuItemId_ = "";
-      /**
-       * <pre>
-       * An opaque string from an partner which uniquely identifies the MenuItem
-       * within the partner feed.
-       * Required.
-       * </pre>
-       *
-       * <code>string menu_item_id = 1;</code>
-       * @return The menuItemId.
-       */
-      public java.lang.String getMenuItemId() {
-        java.lang.Object ref = menuItemId_;
-        if (!(ref instanceof java.lang.String)) {
-          com.google.protobuf.ByteString bs =
-              (com.google.protobuf.ByteString) ref;
-          java.lang.String s = bs.toStringUtf8();
-          menuItemId_ = s;
-          return s;
-        } else {
-          return (java.lang.String) ref;
-        }
-      }
-      /**
-       * <pre>
-       * An opaque string from an partner which uniquely identifies the MenuItem
-       * within the partner feed.
-       * Required.
-       * </pre>
-       *
-       * <code>string menu_item_id = 1;</code>
-       * @return The bytes for menuItemId.
-       */
-      public com.google.protobuf.ByteString
-          getMenuItemIdBytes() {
-        java.lang.Object ref = menuItemId_;
-        if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
-              com.google.protobuf.ByteString.copyFromUtf8(
-                  (java.lang.String) ref);
-          menuItemId_ = b;
-          return b;
-        } else {
-          return (com.google.protobuf.ByteString) ref;
-        }
-      }
-      /**
-       * <pre>
-       * An opaque string from an partner which uniquely identifies the MenuItem
-       * within the partner feed.
-       * Required.
-       * </pre>
-       *
-       * <code>string menu_item_id = 1;</code>
-       * @param value The menuItemId to set.
-       * @return This builder for chaining.
-       */
-      public Builder setMenuItemId(
-          java.lang.String value) {
-        if (value == null) { throw new NullPointerException(); }
-        menuItemId_ = value;
-        bitField0_ |= 0x00000001;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * An opaque string from an partner which uniquely identifies the MenuItem
-       * within the partner feed.
-       * Required.
-       * </pre>
-       *
-       * <code>string menu_item_id = 1;</code>
-       * @return This builder for chaining.
-       */
-      public Builder clearMenuItemId() {
-        menuItemId_ = getDefaultInstance().getMenuItemId();
-        bitField0_ = (bitField0_ & ~0x00000001);
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * An opaque string from an partner which uniquely identifies the MenuItem
-       * within the partner feed.
-       * Required.
-       * </pre>
-       *
-       * <code>string menu_item_id = 1;</code>
-       * @param value The bytes for menuItemId to set.
-       * @return This builder for chaining.
-       */
-      public Builder setMenuItemIdBytes(
-          com.google.protobuf.ByteString value) {
-        if (value == null) { throw new NullPointerException(); }
-        checkByteStringIsUtf8(value);
-        menuItemId_ = value;
-        bitField0_ |= 0x00000001;
-        onChanged();
-        return this;
-      }
-
-      private food.menu.v1.FoodMenu.TextField displayName_;
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.TextField, food.menu.v1.FoodMenu.TextField.Builder, food.menu.v1.FoodMenu.TextFieldOrBuilder> displayNameBuilder_;
-      /**
-       * <pre>
-       * The name that can identify the MenuItem when a user is browsing the menu.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField display_name = 2;</code>
-       * @return Whether the displayName field is set.
-       */
-      public boolean hasDisplayName() {
-        return ((bitField0_ & 0x00000002) != 0);
-      }
-      /**
-       * <pre>
-       * The name that can identify the MenuItem when a user is browsing the menu.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField display_name = 2;</code>
-       * @return The displayName.
-       */
-      public food.menu.v1.FoodMenu.TextField getDisplayName() {
-        if (displayNameBuilder_ == null) {
-          return displayName_ == null ? food.menu.v1.FoodMenu.TextField.getDefaultInstance() : displayName_;
-        } else {
-          return displayNameBuilder_.getMessage();
-        }
-      }
-      /**
-       * <pre>
-       * The name that can identify the MenuItem when a user is browsing the menu.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField display_name = 2;</code>
-       */
-      public Builder setDisplayName(food.menu.v1.FoodMenu.TextField value) {
-        if (displayNameBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          displayName_ = value;
-        } else {
-          displayNameBuilder_.setMessage(value);
-        }
-        bitField0_ |= 0x00000002;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * The name that can identify the MenuItem when a user is browsing the menu.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField display_name = 2;</code>
-       */
-      public Builder setDisplayName(
-          food.menu.v1.FoodMenu.TextField.Builder builderForValue) {
-        if (displayNameBuilder_ == null) {
-          displayName_ = builderForValue.build();
-        } else {
-          displayNameBuilder_.setMessage(builderForValue.build());
-        }
-        bitField0_ |= 0x00000002;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * The name that can identify the MenuItem when a user is browsing the menu.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField display_name = 2;</code>
-       */
-      public Builder mergeDisplayName(food.menu.v1.FoodMenu.TextField value) {
-        if (displayNameBuilder_ == null) {
-          if (((bitField0_ & 0x00000002) != 0) &&
-            displayName_ != null &&
-            displayName_ != food.menu.v1.FoodMenu.TextField.getDefaultInstance()) {
-            getDisplayNameBuilder().mergeFrom(value);
-          } else {
-            displayName_ = value;
-          }
-        } else {
-          displayNameBuilder_.mergeFrom(value);
-        }
-        bitField0_ |= 0x00000002;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * The name that can identify the MenuItem when a user is browsing the menu.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField display_name = 2;</code>
-       */
-      public Builder clearDisplayName() {
-        bitField0_ = (bitField0_ & ~0x00000002);
-        displayName_ = null;
-        if (displayNameBuilder_ != null) {
-          displayNameBuilder_.dispose();
-          displayNameBuilder_ = null;
-        }
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * The name that can identify the MenuItem when a user is browsing the menu.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField display_name = 2;</code>
-       */
-      public food.menu.v1.FoodMenu.TextField.Builder getDisplayNameBuilder() {
-        bitField0_ |= 0x00000002;
-        onChanged();
-        return getDisplayNameFieldBuilder().getBuilder();
-      }
-      /**
-       * <pre>
-       * The name that can identify the MenuItem when a user is browsing the menu.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField display_name = 2;</code>
-       */
-      public food.menu.v1.FoodMenu.TextFieldOrBuilder getDisplayNameOrBuilder() {
-        if (displayNameBuilder_ != null) {
-          return displayNameBuilder_.getMessageOrBuilder();
-        } else {
-          return displayName_ == null ?
-              food.menu.v1.FoodMenu.TextField.getDefaultInstance() : displayName_;
-        }
-      }
-      /**
-       * <pre>
-       * The name that can identify the MenuItem when a user is browsing the menu.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField display_name = 2;</code>
-       */
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.TextField, food.menu.v1.FoodMenu.TextField.Builder, food.menu.v1.FoodMenu.TextFieldOrBuilder> 
-          getDisplayNameFieldBuilder() {
-        if (displayNameBuilder_ == null) {
-          displayNameBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
-              food.menu.v1.FoodMenu.TextField, food.menu.v1.FoodMenu.TextField.Builder, food.menu.v1.FoodMenu.TextFieldOrBuilder>(
-                  getDisplayName(),
-                  getParentForChildren(),
-                  isClean());
-          displayName_ = null;
-        }
-        return displayNameBuilder_;
-      }
-
-      private food.menu.v1.FoodMenu.TextField description_;
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.TextField, food.menu.v1.FoodMenu.TextField.Builder, food.menu.v1.FoodMenu.TextFieldOrBuilder> descriptionBuilder_;
-      /**
-       * <pre>
-       * A description of the menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField description = 3;</code>
-       * @return Whether the description field is set.
-       */
-      public boolean hasDescription() {
-        return ((bitField0_ & 0x00000004) != 0);
-      }
-      /**
-       * <pre>
-       * A description of the menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField description = 3;</code>
-       * @return The description.
-       */
-      public food.menu.v1.FoodMenu.TextField getDescription() {
-        if (descriptionBuilder_ == null) {
-          return description_ == null ? food.menu.v1.FoodMenu.TextField.getDefaultInstance() : description_;
-        } else {
-          return descriptionBuilder_.getMessage();
-        }
-      }
-      /**
-       * <pre>
-       * A description of the menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField description = 3;</code>
-       */
-      public Builder setDescription(food.menu.v1.FoodMenu.TextField value) {
-        if (descriptionBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          description_ = value;
-        } else {
-          descriptionBuilder_.setMessage(value);
-        }
-        bitField0_ |= 0x00000004;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * A description of the menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField description = 3;</code>
-       */
-      public Builder setDescription(
-          food.menu.v1.FoodMenu.TextField.Builder builderForValue) {
-        if (descriptionBuilder_ == null) {
-          description_ = builderForValue.build();
-        } else {
-          descriptionBuilder_.setMessage(builderForValue.build());
-        }
-        bitField0_ |= 0x00000004;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * A description of the menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField description = 3;</code>
-       */
-      public Builder mergeDescription(food.menu.v1.FoodMenu.TextField value) {
-        if (descriptionBuilder_ == null) {
-          if (((bitField0_ & 0x00000004) != 0) &&
-            description_ != null &&
-            description_ != food.menu.v1.FoodMenu.TextField.getDefaultInstance()) {
-            getDescriptionBuilder().mergeFrom(value);
-          } else {
-            description_ = value;
-          }
-        } else {
-          descriptionBuilder_.mergeFrom(value);
-        }
-        bitField0_ |= 0x00000004;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * A description of the menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField description = 3;</code>
-       */
-      public Builder clearDescription() {
-        bitField0_ = (bitField0_ & ~0x00000004);
-        description_ = null;
-        if (descriptionBuilder_ != null) {
-          descriptionBuilder_.dispose();
-          descriptionBuilder_ = null;
-        }
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * A description of the menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField description = 3;</code>
-       */
-      public food.menu.v1.FoodMenu.TextField.Builder getDescriptionBuilder() {
-        bitField0_ |= 0x00000004;
-        onChanged();
-        return getDescriptionFieldBuilder().getBuilder();
-      }
-      /**
-       * <pre>
-       * A description of the menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField description = 3;</code>
-       */
-      public food.menu.v1.FoodMenu.TextFieldOrBuilder getDescriptionOrBuilder() {
-        if (descriptionBuilder_ != null) {
-          return descriptionBuilder_.getMessageOrBuilder();
-        } else {
-          return description_ == null ?
-              food.menu.v1.FoodMenu.TextField.getDefaultInstance() : description_;
-        }
-      }
-      /**
-       * <pre>
-       * A description of the menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField description = 3;</code>
-       */
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.TextField, food.menu.v1.FoodMenu.TextField.Builder, food.menu.v1.FoodMenu.TextFieldOrBuilder> 
-          getDescriptionFieldBuilder() {
-        if (descriptionBuilder_ == null) {
-          descriptionBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
-              food.menu.v1.FoodMenu.TextField, food.menu.v1.FoodMenu.TextField.Builder, food.menu.v1.FoodMenu.TextFieldOrBuilder>(
-                  getDescription(),
-                  getParentForChildren(),
-                  isClean());
-          description_ = null;
-        }
-        return descriptionBuilder_;
-      }
-
-      private java.util.List<food.menu.v1.FoodMenu.Image> images_ =
-        java.util.Collections.emptyList();
-      private void ensureImagesIsMutable() {
-        if (!((bitField0_ & 0x00000008) != 0)) {
-          images_ = new java.util.ArrayList<food.menu.v1.FoodMenu.Image>(images_);
-          bitField0_ |= 0x00000008;
-         }
-      }
-
-      private com.google.protobuf.RepeatedFieldBuilderV3<
-          food.menu.v1.FoodMenu.Image, food.menu.v1.FoodMenu.Image.Builder, food.menu.v1.FoodMenu.ImageOrBuilder> imagesBuilder_;
-
-      /**
-       * <pre>
-       * Image(s) of the menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Image images = 4;</code>
-       */
-      public java.util.List<food.menu.v1.FoodMenu.Image> getImagesList() {
-        if (imagesBuilder_ == null) {
-          return java.util.Collections.unmodifiableList(images_);
-        } else {
-          return imagesBuilder_.getMessageList();
-        }
-      }
-      /**
-       * <pre>
-       * Image(s) of the menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Image images = 4;</code>
-       */
-      public int getImagesCount() {
-        if (imagesBuilder_ == null) {
-          return images_.size();
-        } else {
-          return imagesBuilder_.getCount();
-        }
-      }
-      /**
-       * <pre>
-       * Image(s) of the menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Image images = 4;</code>
-       */
-      public food.menu.v1.FoodMenu.Image getImages(int index) {
-        if (imagesBuilder_ == null) {
-          return images_.get(index);
-        } else {
-          return imagesBuilder_.getMessage(index);
-        }
-      }
-      /**
-       * <pre>
-       * Image(s) of the menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Image images = 4;</code>
-       */
-      public Builder setImages(
-          int index, food.menu.v1.FoodMenu.Image value) {
-        if (imagesBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          ensureImagesIsMutable();
-          images_.set(index, value);
-          onChanged();
-        } else {
-          imagesBuilder_.setMessage(index, value);
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Image(s) of the menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Image images = 4;</code>
-       */
-      public Builder setImages(
-          int index, food.menu.v1.FoodMenu.Image.Builder builderForValue) {
-        if (imagesBuilder_ == null) {
-          ensureImagesIsMutable();
-          images_.set(index, builderForValue.build());
-          onChanged();
-        } else {
-          imagesBuilder_.setMessage(index, builderForValue.build());
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Image(s) of the menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Image images = 4;</code>
-       */
-      public Builder addImages(food.menu.v1.FoodMenu.Image value) {
-        if (imagesBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          ensureImagesIsMutable();
-          images_.add(value);
-          onChanged();
-        } else {
-          imagesBuilder_.addMessage(value);
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Image(s) of the menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Image images = 4;</code>
-       */
-      public Builder addImages(
-          int index, food.menu.v1.FoodMenu.Image value) {
-        if (imagesBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          ensureImagesIsMutable();
-          images_.add(index, value);
-          onChanged();
-        } else {
-          imagesBuilder_.addMessage(index, value);
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Image(s) of the menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Image images = 4;</code>
-       */
-      public Builder addImages(
-          food.menu.v1.FoodMenu.Image.Builder builderForValue) {
-        if (imagesBuilder_ == null) {
-          ensureImagesIsMutable();
-          images_.add(builderForValue.build());
-          onChanged();
-        } else {
-          imagesBuilder_.addMessage(builderForValue.build());
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Image(s) of the menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Image images = 4;</code>
-       */
-      public Builder addImages(
-          int index, food.menu.v1.FoodMenu.Image.Builder builderForValue) {
-        if (imagesBuilder_ == null) {
-          ensureImagesIsMutable();
-          images_.add(index, builderForValue.build());
-          onChanged();
-        } else {
-          imagesBuilder_.addMessage(index, builderForValue.build());
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Image(s) of the menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Image images = 4;</code>
-       */
-      public Builder addAllImages(
-          java.lang.Iterable<? extends food.menu.v1.FoodMenu.Image> values) {
-        if (imagesBuilder_ == null) {
-          ensureImagesIsMutable();
-          com.google.protobuf.AbstractMessageLite.Builder.addAll(
-              values, images_);
-          onChanged();
-        } else {
-          imagesBuilder_.addAllMessages(values);
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Image(s) of the menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Image images = 4;</code>
-       */
-      public Builder clearImages() {
-        if (imagesBuilder_ == null) {
-          images_ = java.util.Collections.emptyList();
-          bitField0_ = (bitField0_ & ~0x00000008);
-          onChanged();
-        } else {
-          imagesBuilder_.clear();
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Image(s) of the menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Image images = 4;</code>
-       */
-      public Builder removeImages(int index) {
-        if (imagesBuilder_ == null) {
-          ensureImagesIsMutable();
-          images_.remove(index);
-          onChanged();
-        } else {
-          imagesBuilder_.remove(index);
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Image(s) of the menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Image images = 4;</code>
-       */
-      public food.menu.v1.FoodMenu.Image.Builder getImagesBuilder(
-          int index) {
-        return getImagesFieldBuilder().getBuilder(index);
-      }
-      /**
-       * <pre>
-       * Image(s) of the menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Image images = 4;</code>
-       */
-      public food.menu.v1.FoodMenu.ImageOrBuilder getImagesOrBuilder(
-          int index) {
-        if (imagesBuilder_ == null) {
-          return images_.get(index);  } else {
-          return imagesBuilder_.getMessageOrBuilder(index);
-        }
-      }
-      /**
-       * <pre>
-       * Image(s) of the menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Image images = 4;</code>
-       */
-      public java.util.List<? extends food.menu.v1.FoodMenu.ImageOrBuilder> 
-           getImagesOrBuilderList() {
-        if (imagesBuilder_ != null) {
-          return imagesBuilder_.getMessageOrBuilderList();
-        } else {
-          return java.util.Collections.unmodifiableList(images_);
-        }
-      }
-      /**
-       * <pre>
-       * Image(s) of the menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Image images = 4;</code>
-       */
-      public food.menu.v1.FoodMenu.Image.Builder addImagesBuilder() {
-        return getImagesFieldBuilder().addBuilder(
-            food.menu.v1.FoodMenu.Image.getDefaultInstance());
-      }
-      /**
-       * <pre>
-       * Image(s) of the menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Image images = 4;</code>
-       */
-      public food.menu.v1.FoodMenu.Image.Builder addImagesBuilder(
-          int index) {
-        return getImagesFieldBuilder().addBuilder(
-            index, food.menu.v1.FoodMenu.Image.getDefaultInstance());
-      }
-      /**
-       * <pre>
-       * Image(s) of the menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Image images = 4;</code>
-       */
-      public java.util.List<food.menu.v1.FoodMenu.Image.Builder> 
-           getImagesBuilderList() {
-        return getImagesFieldBuilder().getBuilderList();
-      }
-      private com.google.protobuf.RepeatedFieldBuilderV3<
-          food.menu.v1.FoodMenu.Image, food.menu.v1.FoodMenu.Image.Builder, food.menu.v1.FoodMenu.ImageOrBuilder> 
-          getImagesFieldBuilder() {
-        if (imagesBuilder_ == null) {
-          imagesBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3<
-              food.menu.v1.FoodMenu.Image, food.menu.v1.FoodMenu.Image.Builder, food.menu.v1.FoodMenu.ImageOrBuilder>(
-                  images_,
-                  ((bitField0_ & 0x00000008) != 0),
-                  getParentForChildren(),
-                  isClean());
-          images_ = null;
-        }
-        return imagesBuilder_;
-      }
-
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.OfferSet, food.menu.v1.FoodMenu.OfferSet.Builder, food.menu.v1.FoodMenu.OfferSetOrBuilder> offerSetBuilder_;
-      /**
-       * <pre>
-       * Available offers to purchase this food item.
-       * </pre>
-       *
-       * <code>.food.menu.v1.OfferSet offer_set = 6;</code>
-       * @return Whether the offerSet field is set.
-       */
-      @java.lang.Override
-      public boolean hasOfferSet() {
-        return pricingCase_ == 6;
-      }
-      /**
-       * <pre>
-       * Available offers to purchase this food item.
-       * </pre>
-       *
-       * <code>.food.menu.v1.OfferSet offer_set = 6;</code>
-       * @return The offerSet.
-       */
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.OfferSet getOfferSet() {
-        if (offerSetBuilder_ == null) {
-          if (pricingCase_ == 6) {
-            return (food.menu.v1.FoodMenu.OfferSet) pricing_;
-          }
-          return food.menu.v1.FoodMenu.OfferSet.getDefaultInstance();
-        } else {
-          if (pricingCase_ == 6) {
-            return offerSetBuilder_.getMessage();
-          }
-          return food.menu.v1.FoodMenu.OfferSet.getDefaultInstance();
-        }
-      }
-      /**
-       * <pre>
-       * Available offers to purchase this food item.
-       * </pre>
-       *
-       * <code>.food.menu.v1.OfferSet offer_set = 6;</code>
-       */
-      public Builder setOfferSet(food.menu.v1.FoodMenu.OfferSet value) {
-        if (offerSetBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          pricing_ = value;
-          onChanged();
-        } else {
-          offerSetBuilder_.setMessage(value);
-        }
-        pricingCase_ = 6;
-        return this;
-      }
-      /**
-       * <pre>
-       * Available offers to purchase this food item.
-       * </pre>
-       *
-       * <code>.food.menu.v1.OfferSet offer_set = 6;</code>
-       */
-      public Builder setOfferSet(
-          food.menu.v1.FoodMenu.OfferSet.Builder builderForValue) {
-        if (offerSetBuilder_ == null) {
-          pricing_ = builderForValue.build();
-          onChanged();
-        } else {
-          offerSetBuilder_.setMessage(builderForValue.build());
-        }
-        pricingCase_ = 6;
-        return this;
-      }
-      /**
-       * <pre>
-       * Available offers to purchase this food item.
-       * </pre>
-       *
-       * <code>.food.menu.v1.OfferSet offer_set = 6;</code>
-       */
-      public Builder mergeOfferSet(food.menu.v1.FoodMenu.OfferSet value) {
-        if (offerSetBuilder_ == null) {
-          if (pricingCase_ == 6 &&
-              pricing_ != food.menu.v1.FoodMenu.OfferSet.getDefaultInstance()) {
-            pricing_ = food.menu.v1.FoodMenu.OfferSet.newBuilder((food.menu.v1.FoodMenu.OfferSet) pricing_)
-                .mergeFrom(value).buildPartial();
-          } else {
-            pricing_ = value;
-          }
-          onChanged();
-        } else {
-          if (pricingCase_ == 6) {
-            offerSetBuilder_.mergeFrom(value);
-          } else {
-            offerSetBuilder_.setMessage(value);
-          }
-        }
-        pricingCase_ = 6;
-        return this;
-      }
-      /**
-       * <pre>
-       * Available offers to purchase this food item.
-       * </pre>
-       *
-       * <code>.food.menu.v1.OfferSet offer_set = 6;</code>
-       */
-      public Builder clearOfferSet() {
-        if (offerSetBuilder_ == null) {
-          if (pricingCase_ == 6) {
-            pricingCase_ = 0;
-            pricing_ = null;
-            onChanged();
-          }
-        } else {
-          if (pricingCase_ == 6) {
-            pricingCase_ = 0;
-            pricing_ = null;
-          }
-          offerSetBuilder_.clear();
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Available offers to purchase this food item.
-       * </pre>
-       *
-       * <code>.food.menu.v1.OfferSet offer_set = 6;</code>
-       */
-      public food.menu.v1.FoodMenu.OfferSet.Builder getOfferSetBuilder() {
-        return getOfferSetFieldBuilder().getBuilder();
-      }
-      /**
-       * <pre>
-       * Available offers to purchase this food item.
-       * </pre>
-       *
-       * <code>.food.menu.v1.OfferSet offer_set = 6;</code>
-       */
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.OfferSetOrBuilder getOfferSetOrBuilder() {
-        if ((pricingCase_ == 6) && (offerSetBuilder_ != null)) {
-          return offerSetBuilder_.getMessageOrBuilder();
-        } else {
-          if (pricingCase_ == 6) {
-            return (food.menu.v1.FoodMenu.OfferSet) pricing_;
-          }
-          return food.menu.v1.FoodMenu.OfferSet.getDefaultInstance();
-        }
-      }
-      /**
-       * <pre>
-       * Available offers to purchase this food item.
-       * </pre>
-       *
-       * <code>.food.menu.v1.OfferSet offer_set = 6;</code>
-       */
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.OfferSet, food.menu.v1.FoodMenu.OfferSet.Builder, food.menu.v1.FoodMenu.OfferSetOrBuilder> 
-          getOfferSetFieldBuilder() {
-        if (offerSetBuilder_ == null) {
-          if (!(pricingCase_ == 6)) {
-            pricing_ = food.menu.v1.FoodMenu.OfferSet.getDefaultInstance();
-          }
-          offerSetBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
-              food.menu.v1.FoodMenu.OfferSet, food.menu.v1.FoodMenu.OfferSet.Builder, food.menu.v1.FoodMenu.OfferSetOrBuilder>(
-                  (food.menu.v1.FoodMenu.OfferSet) pricing_,
-                  getParentForChildren(),
-                  isClean());
-          pricing_ = null;
-        }
-        pricingCase_ = 6;
-        onChanged();
-        return offerSetBuilder_;
-      }
-
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet, food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet.Builder, food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSetOrBuilder> menuItemOptionSetBuilder_;
-      /**
-       * <pre>
-       * Available options for this menu item.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItem.MenuItemOptionSet menu_item_option_set = 7;</code>
-       * @return Whether the menuItemOptionSet field is set.
-       */
-      @java.lang.Override
-      public boolean hasMenuItemOptionSet() {
-        return pricingCase_ == 7;
-      }
-      /**
-       * <pre>
-       * Available options for this menu item.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItem.MenuItemOptionSet menu_item_option_set = 7;</code>
-       * @return The menuItemOptionSet.
-       */
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet getMenuItemOptionSet() {
-        if (menuItemOptionSetBuilder_ == null) {
-          if (pricingCase_ == 7) {
-            return (food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet) pricing_;
-          }
-          return food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet.getDefaultInstance();
-        } else {
-          if (pricingCase_ == 7) {
-            return menuItemOptionSetBuilder_.getMessage();
-          }
-          return food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet.getDefaultInstance();
-        }
-      }
-      /**
-       * <pre>
-       * Available options for this menu item.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItem.MenuItemOptionSet menu_item_option_set = 7;</code>
-       */
-      public Builder setMenuItemOptionSet(food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet value) {
-        if (menuItemOptionSetBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          pricing_ = value;
-          onChanged();
-        } else {
-          menuItemOptionSetBuilder_.setMessage(value);
-        }
-        pricingCase_ = 7;
-        return this;
-      }
-      /**
-       * <pre>
-       * Available options for this menu item.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItem.MenuItemOptionSet menu_item_option_set = 7;</code>
-       */
-      public Builder setMenuItemOptionSet(
-          food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet.Builder builderForValue) {
-        if (menuItemOptionSetBuilder_ == null) {
-          pricing_ = builderForValue.build();
-          onChanged();
-        } else {
-          menuItemOptionSetBuilder_.setMessage(builderForValue.build());
-        }
-        pricingCase_ = 7;
-        return this;
-      }
-      /**
-       * <pre>
-       * Available options for this menu item.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItem.MenuItemOptionSet menu_item_option_set = 7;</code>
-       */
-      public Builder mergeMenuItemOptionSet(food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet value) {
-        if (menuItemOptionSetBuilder_ == null) {
-          if (pricingCase_ == 7 &&
-              pricing_ != food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet.getDefaultInstance()) {
-            pricing_ = food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet.newBuilder((food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet) pricing_)
-                .mergeFrom(value).buildPartial();
-          } else {
-            pricing_ = value;
-          }
-          onChanged();
-        } else {
-          if (pricingCase_ == 7) {
-            menuItemOptionSetBuilder_.mergeFrom(value);
-          } else {
-            menuItemOptionSetBuilder_.setMessage(value);
-          }
-        }
-        pricingCase_ = 7;
-        return this;
-      }
-      /**
-       * <pre>
-       * Available options for this menu item.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItem.MenuItemOptionSet menu_item_option_set = 7;</code>
-       */
-      public Builder clearMenuItemOptionSet() {
-        if (menuItemOptionSetBuilder_ == null) {
-          if (pricingCase_ == 7) {
-            pricingCase_ = 0;
-            pricing_ = null;
-            onChanged();
-          }
-        } else {
-          if (pricingCase_ == 7) {
-            pricingCase_ = 0;
-            pricing_ = null;
-          }
-          menuItemOptionSetBuilder_.clear();
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Available options for this menu item.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItem.MenuItemOptionSet menu_item_option_set = 7;</code>
-       */
-      public food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet.Builder getMenuItemOptionSetBuilder() {
-        return getMenuItemOptionSetFieldBuilder().getBuilder();
-      }
-      /**
-       * <pre>
-       * Available options for this menu item.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItem.MenuItemOptionSet menu_item_option_set = 7;</code>
-       */
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSetOrBuilder getMenuItemOptionSetOrBuilder() {
-        if ((pricingCase_ == 7) && (menuItemOptionSetBuilder_ != null)) {
-          return menuItemOptionSetBuilder_.getMessageOrBuilder();
-        } else {
-          if (pricingCase_ == 7) {
-            return (food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet) pricing_;
-          }
-          return food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet.getDefaultInstance();
-        }
-      }
-      /**
-       * <pre>
-       * Available options for this menu item.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItem.MenuItemOptionSet menu_item_option_set = 7;</code>
-       */
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet, food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet.Builder, food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSetOrBuilder> 
-          getMenuItemOptionSetFieldBuilder() {
-        if (menuItemOptionSetBuilder_ == null) {
-          if (!(pricingCase_ == 7)) {
-            pricing_ = food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet.getDefaultInstance();
-          }
-          menuItemOptionSetBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
-              food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet, food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet.Builder, food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSetOrBuilder>(
-                  (food.menu.v1.FoodMenu.MenuItem.MenuItemOptionSet) pricing_,
-                  getParentForChildren(),
-                  isClean());
-          pricing_ = null;
-        }
-        pricingCase_ = 7;
-        onChanged();
-        return menuItemOptionSetBuilder_;
-      }
-
-      private food.menu.v1.FoodMenu.MenuItemAttributes itemAttributes_;
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.MenuItemAttributes, food.menu.v1.FoodMenu.MenuItemAttributes.Builder, food.menu.v1.FoodMenu.MenuItemAttributesOrBuilder> itemAttributesBuilder_;
-      /**
-       * <pre>
-       * Attributes about this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItemAttributes item_attributes = 8;</code>
-       * @return Whether the itemAttributes field is set.
-       */
-      public boolean hasItemAttributes() {
-        return ((bitField0_ & 0x00000040) != 0);
-      }
-      /**
-       * <pre>
-       * Attributes about this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItemAttributes item_attributes = 8;</code>
-       * @return The itemAttributes.
-       */
-      public food.menu.v1.FoodMenu.MenuItemAttributes getItemAttributes() {
-        if (itemAttributesBuilder_ == null) {
-          return itemAttributes_ == null ? food.menu.v1.FoodMenu.MenuItemAttributes.getDefaultInstance() : itemAttributes_;
-        } else {
-          return itemAttributesBuilder_.getMessage();
-        }
-      }
-      /**
-       * <pre>
-       * Attributes about this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItemAttributes item_attributes = 8;</code>
-       */
-      public Builder setItemAttributes(food.menu.v1.FoodMenu.MenuItemAttributes value) {
-        if (itemAttributesBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          itemAttributes_ = value;
-        } else {
-          itemAttributesBuilder_.setMessage(value);
-        }
-        bitField0_ |= 0x00000040;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Attributes about this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItemAttributes item_attributes = 8;</code>
-       */
-      public Builder setItemAttributes(
-          food.menu.v1.FoodMenu.MenuItemAttributes.Builder builderForValue) {
-        if (itemAttributesBuilder_ == null) {
-          itemAttributes_ = builderForValue.build();
-        } else {
-          itemAttributesBuilder_.setMessage(builderForValue.build());
-        }
-        bitField0_ |= 0x00000040;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Attributes about this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItemAttributes item_attributes = 8;</code>
-       */
-      public Builder mergeItemAttributes(food.menu.v1.FoodMenu.MenuItemAttributes value) {
-        if (itemAttributesBuilder_ == null) {
-          if (((bitField0_ & 0x00000040) != 0) &&
-            itemAttributes_ != null &&
-            itemAttributes_ != food.menu.v1.FoodMenu.MenuItemAttributes.getDefaultInstance()) {
-            getItemAttributesBuilder().mergeFrom(value);
-          } else {
-            itemAttributes_ = value;
-          }
-        } else {
-          itemAttributesBuilder_.mergeFrom(value);
-        }
-        bitField0_ |= 0x00000040;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Attributes about this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItemAttributes item_attributes = 8;</code>
-       */
-      public Builder clearItemAttributes() {
-        bitField0_ = (bitField0_ & ~0x00000040);
-        itemAttributes_ = null;
-        if (itemAttributesBuilder_ != null) {
-          itemAttributesBuilder_.dispose();
-          itemAttributesBuilder_ = null;
-        }
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Attributes about this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItemAttributes item_attributes = 8;</code>
-       */
-      public food.menu.v1.FoodMenu.MenuItemAttributes.Builder getItemAttributesBuilder() {
-        bitField0_ |= 0x00000040;
-        onChanged();
-        return getItemAttributesFieldBuilder().getBuilder();
-      }
-      /**
-       * <pre>
-       * Attributes about this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItemAttributes item_attributes = 8;</code>
-       */
-      public food.menu.v1.FoodMenu.MenuItemAttributesOrBuilder getItemAttributesOrBuilder() {
-        if (itemAttributesBuilder_ != null) {
-          return itemAttributesBuilder_.getMessageOrBuilder();
-        } else {
-          return itemAttributes_ == null ?
-              food.menu.v1.FoodMenu.MenuItemAttributes.getDefaultInstance() : itemAttributes_;
-        }
-      }
-      /**
-       * <pre>
-       * Attributes about this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItemAttributes item_attributes = 8;</code>
-       */
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.MenuItemAttributes, food.menu.v1.FoodMenu.MenuItemAttributes.Builder, food.menu.v1.FoodMenu.MenuItemAttributesOrBuilder> 
-          getItemAttributesFieldBuilder() {
-        if (itemAttributesBuilder_ == null) {
-          itemAttributesBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
-              food.menu.v1.FoodMenu.MenuItemAttributes, food.menu.v1.FoodMenu.MenuItemAttributes.Builder, food.menu.v1.FoodMenu.MenuItemAttributesOrBuilder>(
-                  getItemAttributes(),
-                  getParentForChildren(),
-                  isClean());
-          itemAttributes_ = null;
-        }
-        return itemAttributesBuilder_;
-      }
-      @java.lang.Override
-      public final Builder setUnknownFields(
-          final com.google.protobuf.UnknownFieldSet unknownFields) {
-        return super.setUnknownFields(unknownFields);
-      }
-
-      @java.lang.Override
-      public final Builder mergeUnknownFields(
-          final com.google.protobuf.UnknownFieldSet unknownFields) {
-        return super.mergeUnknownFields(unknownFields);
-      }
-
-
-      // @@protoc_insertion_point(builder_scope:food.menu.v1.MenuItem)
-    }
-
-    // @@protoc_insertion_point(class_scope:food.menu.v1.MenuItem)
-    private static final food.menu.v1.FoodMenu.MenuItem DEFAULT_INSTANCE;
-    static {
-      DEFAULT_INSTANCE = new food.menu.v1.FoodMenu.MenuItem();
-    }
-
-    public static food.menu.v1.FoodMenu.MenuItem getDefaultInstance() {
-      return DEFAULT_INSTANCE;
-    }
-
-    private static final com.google.protobuf.Parser<MenuItem>
-        PARSER = new com.google.protobuf.AbstractParser<MenuItem>() {
-      @java.lang.Override
-      public MenuItem parsePartialFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws com.google.protobuf.InvalidProtocolBufferException {
-        Builder builder = newBuilder();
-        try {
-          builder.mergeFrom(input, extensionRegistry);
-        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          throw e.setUnfinishedMessage(builder.buildPartial());
-        } catch (com.google.protobuf.UninitializedMessageException e) {
-          throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
-        } catch (java.io.IOException e) {
-          throw new com.google.protobuf.InvalidProtocolBufferException(e)
-              .setUnfinishedMessage(builder.buildPartial());
-        }
-        return builder.buildPartial();
-      }
-    };
-
-    public static com.google.protobuf.Parser<MenuItem> parser() {
-      return PARSER;
-    }
-
-    @java.lang.Override
-    public com.google.protobuf.Parser<MenuItem> getParserForType() {
-      return PARSER;
-    }
-
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.MenuItem getDefaultInstanceForType() {
-      return DEFAULT_INSTANCE;
-    }
-
-  }
-
-  public interface MenuItemOptionOrBuilder extends
-      // @@protoc_insertion_point(interface_extends:food.menu.v1.MenuItemOption)
-      com.google.protobuf.MessageOrBuilder {
-
-    /**
-     * <pre>
-     * An opaque string from an partner which uniquely identifies the
-     * MenuItemOption within the partner feed.
-     * Required.
-     * </pre>
-     *
-     * <code>string menu_item_option_id = 9;</code>
-     * @return The menuItemOptionId.
-     */
-    java.lang.String getMenuItemOptionId();
-    /**
-     * <pre>
-     * An opaque string from an partner which uniquely identifies the
-     * MenuItemOption within the partner feed.
-     * Required.
-     * </pre>
-     *
-     * <code>string menu_item_option_id = 9;</code>
-     * @return The bytes for menuItemOptionId.
-     */
-    com.google.protobuf.ByteString
-        getMenuItemOptionIdBytes();
-
-    /**
-     * <pre>
-     * Option property and value e.g. Size: Small.
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.MenuItemOptionProperty value = 2;</code>
-     * @return Whether the value field is set.
-     */
-    boolean hasValue();
-    /**
-     * <pre>
-     * Option property and value e.g. Size: Small.
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.MenuItemOptionProperty value = 2;</code>
-     * @return The value.
-     */
-    food.menu.v1.FoodMenu.MenuItemOptionProperty getValue();
-    /**
-     * <pre>
-     * Option property and value e.g. Size: Small.
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.MenuItemOptionProperty value = 2;</code>
-     */
-    food.menu.v1.FoodMenu.MenuItemOptionPropertyOrBuilder getValueOrBuilder();
-
-    /**
-     * <pre>
-     * Available offers to purchase this menu item option.
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.OfferSet offer_set = 4;</code>
-     * @return Whether the offerSet field is set.
-     */
-    boolean hasOfferSet();
-    /**
-     * <pre>
-     * Available offers to purchase this menu item option.
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.OfferSet offer_set = 4;</code>
-     * @return The offerSet.
-     */
-    food.menu.v1.FoodMenu.OfferSet getOfferSet();
-    /**
-     * <pre>
-     * Available offers to purchase this menu item option.
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.OfferSet offer_set = 4;</code>
-     */
-    food.menu.v1.FoodMenu.OfferSetOrBuilder getOfferSetOrBuilder();
-
-    /**
-     * <pre>
-     * Attributes about this menu item option.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.MenuItemAttributes item_attributes = 5;</code>
-     * @return Whether the itemAttributes field is set.
-     */
-    boolean hasItemAttributes();
-    /**
-     * <pre>
-     * Attributes about this menu item option.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.MenuItemAttributes item_attributes = 5;</code>
-     * @return The itemAttributes.
-     */
-    food.menu.v1.FoodMenu.MenuItemAttributes getItemAttributes();
-    /**
-     * <pre>
-     * Attributes about this menu item option.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.MenuItemAttributes item_attributes = 5;</code>
-     */
-    food.menu.v1.FoodMenu.MenuItemAttributesOrBuilder getItemAttributesOrBuilder();
-  }
-  /**
-   * <pre>
-   * Describes choices that a user would be required to make when selecting a
-   * dish / combo. The user must select an option, otherwise the order is
-   * considered invalid (e.g. the user must choose small, medium, or large for a
-   * pizza).
-   * </pre>
-   *
-   * Protobuf type {@code food.menu.v1.MenuItemOption}
-   */
-  public static final class MenuItemOption extends
-      com.google.protobuf.GeneratedMessageV3 implements
-      // @@protoc_insertion_point(message_implements:food.menu.v1.MenuItemOption)
-      MenuItemOptionOrBuilder {
-  private static final long serialVersionUID = 0L;
-    // Use MenuItemOption.newBuilder() to construct.
-    private MenuItemOption(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
-      super(builder);
-    }
-    private MenuItemOption() {
-      menuItemOptionId_ = "";
-    }
-
-    @java.lang.Override
-    @SuppressWarnings({"unused"})
-    protected java.lang.Object newInstance(
-        UnusedPrivateParameter unused) {
-      return new MenuItemOption();
-    }
-
-    public static final com.google.protobuf.Descriptors.Descriptor
-        getDescriptor() {
-      return food.menu.v1.FoodMenu.internal_static_food_menu_v1_MenuItemOption_descriptor;
-    }
-
-    @java.lang.Override
-    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-        internalGetFieldAccessorTable() {
-      return food.menu.v1.FoodMenu.internal_static_food_menu_v1_MenuItemOption_fieldAccessorTable
-          .ensureFieldAccessorsInitialized(
-              food.menu.v1.FoodMenu.MenuItemOption.class, food.menu.v1.FoodMenu.MenuItemOption.Builder.class);
-    }
-
-    public static final int MENU_ITEM_OPTION_ID_FIELD_NUMBER = 9;
-    @SuppressWarnings("serial")
-    private volatile java.lang.Object menuItemOptionId_ = "";
-    /**
-     * <pre>
-     * An opaque string from an partner which uniquely identifies the
-     * MenuItemOption within the partner feed.
-     * Required.
-     * </pre>
-     *
-     * <code>string menu_item_option_id = 9;</code>
-     * @return The menuItemOptionId.
-     */
-    @java.lang.Override
-    public java.lang.String getMenuItemOptionId() {
-      java.lang.Object ref = menuItemOptionId_;
-      if (ref instanceof java.lang.String) {
-        return (java.lang.String) ref;
-      } else {
-        com.google.protobuf.ByteString bs = 
-            (com.google.protobuf.ByteString) ref;
-        java.lang.String s = bs.toStringUtf8();
-        menuItemOptionId_ = s;
-        return s;
-      }
-    }
-    /**
-     * <pre>
-     * An opaque string from an partner which uniquely identifies the
-     * MenuItemOption within the partner feed.
-     * Required.
-     * </pre>
-     *
-     * <code>string menu_item_option_id = 9;</code>
-     * @return The bytes for menuItemOptionId.
-     */
-    @java.lang.Override
-    public com.google.protobuf.ByteString
-        getMenuItemOptionIdBytes() {
-      java.lang.Object ref = menuItemOptionId_;
-      if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
-            com.google.protobuf.ByteString.copyFromUtf8(
-                (java.lang.String) ref);
-        menuItemOptionId_ = b;
-        return b;
-      } else {
-        return (com.google.protobuf.ByteString) ref;
-      }
-    }
-
-    public static final int VALUE_FIELD_NUMBER = 2;
-    private food.menu.v1.FoodMenu.MenuItemOptionProperty value_;
-    /**
-     * <pre>
-     * Option property and value e.g. Size: Small.
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.MenuItemOptionProperty value = 2;</code>
-     * @return Whether the value field is set.
-     */
-    @java.lang.Override
-    public boolean hasValue() {
-      return value_ != null;
-    }
-    /**
-     * <pre>
-     * Option property and value e.g. Size: Small.
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.MenuItemOptionProperty value = 2;</code>
-     * @return The value.
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.MenuItemOptionProperty getValue() {
-      return value_ == null ? food.menu.v1.FoodMenu.MenuItemOptionProperty.getDefaultInstance() : value_;
-    }
-    /**
-     * <pre>
-     * Option property and value e.g. Size: Small.
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.MenuItemOptionProperty value = 2;</code>
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.MenuItemOptionPropertyOrBuilder getValueOrBuilder() {
-      return value_ == null ? food.menu.v1.FoodMenu.MenuItemOptionProperty.getDefaultInstance() : value_;
-    }
-
-    public static final int OFFER_SET_FIELD_NUMBER = 4;
-    private food.menu.v1.FoodMenu.OfferSet offerSet_;
-    /**
-     * <pre>
-     * Available offers to purchase this menu item option.
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.OfferSet offer_set = 4;</code>
-     * @return Whether the offerSet field is set.
-     */
-    @java.lang.Override
-    public boolean hasOfferSet() {
-      return offerSet_ != null;
-    }
-    /**
-     * <pre>
-     * Available offers to purchase this menu item option.
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.OfferSet offer_set = 4;</code>
-     * @return The offerSet.
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.OfferSet getOfferSet() {
-      return offerSet_ == null ? food.menu.v1.FoodMenu.OfferSet.getDefaultInstance() : offerSet_;
-    }
-    /**
-     * <pre>
-     * Available offers to purchase this menu item option.
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.OfferSet offer_set = 4;</code>
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.OfferSetOrBuilder getOfferSetOrBuilder() {
-      return offerSet_ == null ? food.menu.v1.FoodMenu.OfferSet.getDefaultInstance() : offerSet_;
-    }
-
-    public static final int ITEM_ATTRIBUTES_FIELD_NUMBER = 5;
-    private food.menu.v1.FoodMenu.MenuItemAttributes itemAttributes_;
-    /**
-     * <pre>
-     * Attributes about this menu item option.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.MenuItemAttributes item_attributes = 5;</code>
-     * @return Whether the itemAttributes field is set.
-     */
-    @java.lang.Override
-    public boolean hasItemAttributes() {
-      return itemAttributes_ != null;
-    }
-    /**
-     * <pre>
-     * Attributes about this menu item option.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.MenuItemAttributes item_attributes = 5;</code>
-     * @return The itemAttributes.
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.MenuItemAttributes getItemAttributes() {
-      return itemAttributes_ == null ? food.menu.v1.FoodMenu.MenuItemAttributes.getDefaultInstance() : itemAttributes_;
-    }
-    /**
-     * <pre>
-     * Attributes about this menu item option.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.MenuItemAttributes item_attributes = 5;</code>
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.MenuItemAttributesOrBuilder getItemAttributesOrBuilder() {
-      return itemAttributes_ == null ? food.menu.v1.FoodMenu.MenuItemAttributes.getDefaultInstance() : itemAttributes_;
-    }
-
-    private byte memoizedIsInitialized = -1;
-    @java.lang.Override
-    public final boolean isInitialized() {
-      byte isInitialized = memoizedIsInitialized;
-      if (isInitialized == 1) return true;
-      if (isInitialized == 0) return false;
-
-      memoizedIsInitialized = 1;
-      return true;
-    }
-
-    @java.lang.Override
-    public void writeTo(com.google.protobuf.CodedOutputStream output)
-                        throws java.io.IOException {
-      if (value_ != null) {
-        output.writeMessage(2, getValue());
-      }
-      if (offerSet_ != null) {
-        output.writeMessage(4, getOfferSet());
-      }
-      if (itemAttributes_ != null) {
-        output.writeMessage(5, getItemAttributes());
-      }
-      if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(menuItemOptionId_)) {
-        com.google.protobuf.GeneratedMessageV3.writeString(output, 9, menuItemOptionId_);
-      }
-      getUnknownFields().writeTo(output);
-    }
-
-    @java.lang.Override
-    public int getSerializedSize() {
-      int size = memoizedSize;
-      if (size != -1) return size;
-
-      size = 0;
-      if (value_ != null) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(2, getValue());
-      }
-      if (offerSet_ != null) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(4, getOfferSet());
-      }
-      if (itemAttributes_ != null) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(5, getItemAttributes());
-      }
-      if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(menuItemOptionId_)) {
-        size += com.google.protobuf.GeneratedMessageV3.computeStringSize(9, menuItemOptionId_);
-      }
-      size += getUnknownFields().getSerializedSize();
-      memoizedSize = size;
-      return size;
-    }
-
-    @java.lang.Override
-    public boolean equals(final java.lang.Object obj) {
-      if (obj == this) {
-       return true;
-      }
-      if (!(obj instanceof food.menu.v1.FoodMenu.MenuItemOption)) {
-        return super.equals(obj);
-      }
-      food.menu.v1.FoodMenu.MenuItemOption other = (food.menu.v1.FoodMenu.MenuItemOption) obj;
-
-      if (!getMenuItemOptionId()
-          .equals(other.getMenuItemOptionId())) return false;
-      if (hasValue() != other.hasValue()) return false;
-      if (hasValue()) {
-        if (!getValue()
-            .equals(other.getValue())) return false;
-      }
-      if (hasOfferSet() != other.hasOfferSet()) return false;
-      if (hasOfferSet()) {
-        if (!getOfferSet()
-            .equals(other.getOfferSet())) return false;
-      }
-      if (hasItemAttributes() != other.hasItemAttributes()) return false;
-      if (hasItemAttributes()) {
-        if (!getItemAttributes()
-            .equals(other.getItemAttributes())) return false;
-      }
-      if (!getUnknownFields().equals(other.getUnknownFields())) return false;
-      return true;
-    }
-
-    @java.lang.Override
-    public int hashCode() {
-      if (memoizedHashCode != 0) {
-        return memoizedHashCode;
-      }
-      int hash = 41;
-      hash = (19 * hash) + getDescriptor().hashCode();
-      hash = (37 * hash) + MENU_ITEM_OPTION_ID_FIELD_NUMBER;
-      hash = (53 * hash) + getMenuItemOptionId().hashCode();
-      if (hasValue()) {
-        hash = (37 * hash) + VALUE_FIELD_NUMBER;
-        hash = (53 * hash) + getValue().hashCode();
-      }
-      if (hasOfferSet()) {
-        hash = (37 * hash) + OFFER_SET_FIELD_NUMBER;
-        hash = (53 * hash) + getOfferSet().hashCode();
-      }
-      if (hasItemAttributes()) {
-        hash = (37 * hash) + ITEM_ATTRIBUTES_FIELD_NUMBER;
-        hash = (53 * hash) + getItemAttributes().hashCode();
-      }
-      hash = (29 * hash) + getUnknownFields().hashCode();
-      memoizedHashCode = hash;
-      return hash;
-    }
-
-    public static food.menu.v1.FoodMenu.MenuItemOption parseFrom(
-        java.nio.ByteBuffer data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.MenuItemOption parseFrom(
-        java.nio.ByteBuffer data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.MenuItemOption parseFrom(
-        com.google.protobuf.ByteString data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.MenuItemOption parseFrom(
-        com.google.protobuf.ByteString data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.MenuItemOption parseFrom(byte[] data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.MenuItemOption parseFrom(
-        byte[] data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.MenuItemOption parseFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.MenuItemOption parseFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.MenuItemOption parseDelimitedFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseDelimitedWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.MenuItemOption parseDelimitedFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.MenuItemOption parseFrom(
-        com.google.protobuf.CodedInputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.MenuItemOption parseFrom(
-        com.google.protobuf.CodedInputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input, extensionRegistry);
-    }
-
-    @java.lang.Override
-    public Builder newBuilderForType() { return newBuilder(); }
-    public static Builder newBuilder() {
-      return DEFAULT_INSTANCE.toBuilder();
-    }
-    public static Builder newBuilder(food.menu.v1.FoodMenu.MenuItemOption prototype) {
-      return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
-    }
-    @java.lang.Override
-    public Builder toBuilder() {
-      return this == DEFAULT_INSTANCE
-          ? new Builder() : new Builder().mergeFrom(this);
-    }
-
-    @java.lang.Override
-    protected Builder newBuilderForType(
-        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-      Builder builder = new Builder(parent);
-      return builder;
-    }
-    /**
-     * <pre>
-     * Describes choices that a user would be required to make when selecting a
-     * dish / combo. The user must select an option, otherwise the order is
-     * considered invalid (e.g. the user must choose small, medium, or large for a
-     * pizza).
-     * </pre>
-     *
-     * Protobuf type {@code food.menu.v1.MenuItemOption}
-     */
-    public static final class Builder extends
-        com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
-        // @@protoc_insertion_point(builder_implements:food.menu.v1.MenuItemOption)
-        food.menu.v1.FoodMenu.MenuItemOptionOrBuilder {
-      public static final com.google.protobuf.Descriptors.Descriptor
-          getDescriptor() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_MenuItemOption_descriptor;
-      }
-
-      @java.lang.Override
-      protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-          internalGetFieldAccessorTable() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_MenuItemOption_fieldAccessorTable
-            .ensureFieldAccessorsInitialized(
-                food.menu.v1.FoodMenu.MenuItemOption.class, food.menu.v1.FoodMenu.MenuItemOption.Builder.class);
-      }
-
-      // Construct using food.menu.v1.FoodMenu.MenuItemOption.newBuilder()
-      private Builder() {
-
-      }
-
-      private Builder(
-          com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-        super(parent);
-
-      }
-      @java.lang.Override
-      public Builder clear() {
-        super.clear();
-        bitField0_ = 0;
-        menuItemOptionId_ = "";
-        value_ = null;
-        if (valueBuilder_ != null) {
-          valueBuilder_.dispose();
-          valueBuilder_ = null;
-        }
-        offerSet_ = null;
-        if (offerSetBuilder_ != null) {
-          offerSetBuilder_.dispose();
-          offerSetBuilder_ = null;
-        }
-        itemAttributes_ = null;
-        if (itemAttributesBuilder_ != null) {
-          itemAttributesBuilder_.dispose();
-          itemAttributesBuilder_ = null;
-        }
-        return this;
-      }
-
-      @java.lang.Override
-      public com.google.protobuf.Descriptors.Descriptor
-          getDescriptorForType() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_MenuItemOption_descriptor;
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.MenuItemOption getDefaultInstanceForType() {
-        return food.menu.v1.FoodMenu.MenuItemOption.getDefaultInstance();
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.MenuItemOption build() {
-        food.menu.v1.FoodMenu.MenuItemOption result = buildPartial();
-        if (!result.isInitialized()) {
-          throw newUninitializedMessageException(result);
-        }
-        return result;
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.MenuItemOption buildPartial() {
-        food.menu.v1.FoodMenu.MenuItemOption result = new food.menu.v1.FoodMenu.MenuItemOption(this);
-        if (bitField0_ != 0) { buildPartial0(result); }
-        onBuilt();
-        return result;
-      }
-
-      private void buildPartial0(food.menu.v1.FoodMenu.MenuItemOption result) {
-        int from_bitField0_ = bitField0_;
-        if (((from_bitField0_ & 0x00000001) != 0)) {
-          result.menuItemOptionId_ = menuItemOptionId_;
-        }
-        if (((from_bitField0_ & 0x00000002) != 0)) {
-          result.value_ = valueBuilder_ == null
-              ? value_
-              : valueBuilder_.build();
-        }
-        if (((from_bitField0_ & 0x00000004) != 0)) {
-          result.offerSet_ = offerSetBuilder_ == null
-              ? offerSet_
-              : offerSetBuilder_.build();
-        }
-        if (((from_bitField0_ & 0x00000008) != 0)) {
-          result.itemAttributes_ = itemAttributesBuilder_ == null
-              ? itemAttributes_
-              : itemAttributesBuilder_.build();
-        }
-      }
-
-      @java.lang.Override
-      public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof food.menu.v1.FoodMenu.MenuItemOption) {
-          return mergeFrom((food.menu.v1.FoodMenu.MenuItemOption)other);
-        } else {
-          super.mergeFrom(other);
-          return this;
-        }
-      }
-
-      public Builder mergeFrom(food.menu.v1.FoodMenu.MenuItemOption other) {
-        if (other == food.menu.v1.FoodMenu.MenuItemOption.getDefaultInstance()) return this;
-        if (!other.getMenuItemOptionId().isEmpty()) {
-          menuItemOptionId_ = other.menuItemOptionId_;
-          bitField0_ |= 0x00000001;
-          onChanged();
-        }
-        if (other.hasValue()) {
-          mergeValue(other.getValue());
-        }
-        if (other.hasOfferSet()) {
-          mergeOfferSet(other.getOfferSet());
-        }
-        if (other.hasItemAttributes()) {
-          mergeItemAttributes(other.getItemAttributes());
-        }
-        this.mergeUnknownFields(other.getUnknownFields());
-        onChanged();
-        return this;
-      }
-
-      @java.lang.Override
-      public final boolean isInitialized() {
-        return true;
-      }
-
-      @java.lang.Override
-      public Builder mergeFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws java.io.IOException {
-        if (extensionRegistry == null) {
-          throw new java.lang.NullPointerException();
-        }
-        try {
-          boolean done = false;
-          while (!done) {
-            int tag = input.readTag();
-            switch (tag) {
-              case 0:
-                done = true;
-                break;
-              case 18: {
-                input.readMessage(
-                    getValueFieldBuilder().getBuilder(),
-                    extensionRegistry);
-                bitField0_ |= 0x00000002;
-                break;
-              } // case 18
-              case 34: {
-                input.readMessage(
-                    getOfferSetFieldBuilder().getBuilder(),
-                    extensionRegistry);
-                bitField0_ |= 0x00000004;
-                break;
-              } // case 34
-              case 42: {
-                input.readMessage(
-                    getItemAttributesFieldBuilder().getBuilder(),
-                    extensionRegistry);
-                bitField0_ |= 0x00000008;
-                break;
-              } // case 42
-              case 74: {
-                menuItemOptionId_ = input.readStringRequireUtf8();
-                bitField0_ |= 0x00000001;
-                break;
-              } // case 74
-              default: {
-                if (!super.parseUnknownField(input, extensionRegistry, tag)) {
-                  done = true; // was an endgroup tag
-                }
-                break;
-              } // default:
-            } // switch (tag)
-          } // while (!done)
-        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          throw e.unwrapIOException();
-        } finally {
-          onChanged();
-        } // finally
-        return this;
-      }
-      private int bitField0_;
-
-      private java.lang.Object menuItemOptionId_ = "";
-      /**
-       * <pre>
-       * An opaque string from an partner which uniquely identifies the
-       * MenuItemOption within the partner feed.
-       * Required.
-       * </pre>
-       *
-       * <code>string menu_item_option_id = 9;</code>
-       * @return The menuItemOptionId.
-       */
-      public java.lang.String getMenuItemOptionId() {
-        java.lang.Object ref = menuItemOptionId_;
-        if (!(ref instanceof java.lang.String)) {
-          com.google.protobuf.ByteString bs =
-              (com.google.protobuf.ByteString) ref;
-          java.lang.String s = bs.toStringUtf8();
-          menuItemOptionId_ = s;
-          return s;
-        } else {
-          return (java.lang.String) ref;
-        }
-      }
-      /**
-       * <pre>
-       * An opaque string from an partner which uniquely identifies the
-       * MenuItemOption within the partner feed.
-       * Required.
-       * </pre>
-       *
-       * <code>string menu_item_option_id = 9;</code>
-       * @return The bytes for menuItemOptionId.
-       */
-      public com.google.protobuf.ByteString
-          getMenuItemOptionIdBytes() {
-        java.lang.Object ref = menuItemOptionId_;
-        if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
-              com.google.protobuf.ByteString.copyFromUtf8(
-                  (java.lang.String) ref);
-          menuItemOptionId_ = b;
-          return b;
-        } else {
-          return (com.google.protobuf.ByteString) ref;
-        }
-      }
-      /**
-       * <pre>
-       * An opaque string from an partner which uniquely identifies the
-       * MenuItemOption within the partner feed.
-       * Required.
-       * </pre>
-       *
-       * <code>string menu_item_option_id = 9;</code>
-       * @param value The menuItemOptionId to set.
-       * @return This builder for chaining.
-       */
-      public Builder setMenuItemOptionId(
-          java.lang.String value) {
-        if (value == null) { throw new NullPointerException(); }
-        menuItemOptionId_ = value;
-        bitField0_ |= 0x00000001;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * An opaque string from an partner which uniquely identifies the
-       * MenuItemOption within the partner feed.
-       * Required.
-       * </pre>
-       *
-       * <code>string menu_item_option_id = 9;</code>
-       * @return This builder for chaining.
-       */
-      public Builder clearMenuItemOptionId() {
-        menuItemOptionId_ = getDefaultInstance().getMenuItemOptionId();
-        bitField0_ = (bitField0_ & ~0x00000001);
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * An opaque string from an partner which uniquely identifies the
-       * MenuItemOption within the partner feed.
-       * Required.
-       * </pre>
-       *
-       * <code>string menu_item_option_id = 9;</code>
-       * @param value The bytes for menuItemOptionId to set.
-       * @return This builder for chaining.
-       */
-      public Builder setMenuItemOptionIdBytes(
-          com.google.protobuf.ByteString value) {
-        if (value == null) { throw new NullPointerException(); }
-        checkByteStringIsUtf8(value);
-        menuItemOptionId_ = value;
-        bitField0_ |= 0x00000001;
-        onChanged();
-        return this;
-      }
-
-      private food.menu.v1.FoodMenu.MenuItemOptionProperty value_;
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.MenuItemOptionProperty, food.menu.v1.FoodMenu.MenuItemOptionProperty.Builder, food.menu.v1.FoodMenu.MenuItemOptionPropertyOrBuilder> valueBuilder_;
-      /**
-       * <pre>
-       * Option property and value e.g. Size: Small.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItemOptionProperty value = 2;</code>
-       * @return Whether the value field is set.
-       */
-      public boolean hasValue() {
-        return ((bitField0_ & 0x00000002) != 0);
-      }
-      /**
-       * <pre>
-       * Option property and value e.g. Size: Small.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItemOptionProperty value = 2;</code>
-       * @return The value.
-       */
-      public food.menu.v1.FoodMenu.MenuItemOptionProperty getValue() {
-        if (valueBuilder_ == null) {
-          return value_ == null ? food.menu.v1.FoodMenu.MenuItemOptionProperty.getDefaultInstance() : value_;
-        } else {
-          return valueBuilder_.getMessage();
-        }
-      }
-      /**
-       * <pre>
-       * Option property and value e.g. Size: Small.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItemOptionProperty value = 2;</code>
-       */
-      public Builder setValue(food.menu.v1.FoodMenu.MenuItemOptionProperty value) {
-        if (valueBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          value_ = value;
-        } else {
-          valueBuilder_.setMessage(value);
-        }
-        bitField0_ |= 0x00000002;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Option property and value e.g. Size: Small.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItemOptionProperty value = 2;</code>
-       */
-      public Builder setValue(
-          food.menu.v1.FoodMenu.MenuItemOptionProperty.Builder builderForValue) {
-        if (valueBuilder_ == null) {
-          value_ = builderForValue.build();
-        } else {
-          valueBuilder_.setMessage(builderForValue.build());
-        }
-        bitField0_ |= 0x00000002;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Option property and value e.g. Size: Small.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItemOptionProperty value = 2;</code>
-       */
-      public Builder mergeValue(food.menu.v1.FoodMenu.MenuItemOptionProperty value) {
-        if (valueBuilder_ == null) {
-          if (((bitField0_ & 0x00000002) != 0) &&
-            value_ != null &&
-            value_ != food.menu.v1.FoodMenu.MenuItemOptionProperty.getDefaultInstance()) {
-            getValueBuilder().mergeFrom(value);
-          } else {
-            value_ = value;
-          }
-        } else {
-          valueBuilder_.mergeFrom(value);
-        }
-        bitField0_ |= 0x00000002;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Option property and value e.g. Size: Small.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItemOptionProperty value = 2;</code>
-       */
-      public Builder clearValue() {
-        bitField0_ = (bitField0_ & ~0x00000002);
-        value_ = null;
-        if (valueBuilder_ != null) {
-          valueBuilder_.dispose();
-          valueBuilder_ = null;
-        }
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Option property and value e.g. Size: Small.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItemOptionProperty value = 2;</code>
-       */
-      public food.menu.v1.FoodMenu.MenuItemOptionProperty.Builder getValueBuilder() {
-        bitField0_ |= 0x00000002;
-        onChanged();
-        return getValueFieldBuilder().getBuilder();
-      }
-      /**
-       * <pre>
-       * Option property and value e.g. Size: Small.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItemOptionProperty value = 2;</code>
-       */
-      public food.menu.v1.FoodMenu.MenuItemOptionPropertyOrBuilder getValueOrBuilder() {
-        if (valueBuilder_ != null) {
-          return valueBuilder_.getMessageOrBuilder();
-        } else {
-          return value_ == null ?
-              food.menu.v1.FoodMenu.MenuItemOptionProperty.getDefaultInstance() : value_;
-        }
-      }
-      /**
-       * <pre>
-       * Option property and value e.g. Size: Small.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItemOptionProperty value = 2;</code>
-       */
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.MenuItemOptionProperty, food.menu.v1.FoodMenu.MenuItemOptionProperty.Builder, food.menu.v1.FoodMenu.MenuItemOptionPropertyOrBuilder> 
-          getValueFieldBuilder() {
-        if (valueBuilder_ == null) {
-          valueBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
-              food.menu.v1.FoodMenu.MenuItemOptionProperty, food.menu.v1.FoodMenu.MenuItemOptionProperty.Builder, food.menu.v1.FoodMenu.MenuItemOptionPropertyOrBuilder>(
-                  getValue(),
-                  getParentForChildren(),
-                  isClean());
-          value_ = null;
-        }
-        return valueBuilder_;
-      }
-
-      private food.menu.v1.FoodMenu.OfferSet offerSet_;
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.OfferSet, food.menu.v1.FoodMenu.OfferSet.Builder, food.menu.v1.FoodMenu.OfferSetOrBuilder> offerSetBuilder_;
-      /**
-       * <pre>
-       * Available offers to purchase this menu item option.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.OfferSet offer_set = 4;</code>
-       * @return Whether the offerSet field is set.
-       */
-      public boolean hasOfferSet() {
-        return ((bitField0_ & 0x00000004) != 0);
-      }
-      /**
-       * <pre>
-       * Available offers to purchase this menu item option.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.OfferSet offer_set = 4;</code>
-       * @return The offerSet.
-       */
-      public food.menu.v1.FoodMenu.OfferSet getOfferSet() {
-        if (offerSetBuilder_ == null) {
-          return offerSet_ == null ? food.menu.v1.FoodMenu.OfferSet.getDefaultInstance() : offerSet_;
-        } else {
-          return offerSetBuilder_.getMessage();
-        }
-      }
-      /**
-       * <pre>
-       * Available offers to purchase this menu item option.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.OfferSet offer_set = 4;</code>
-       */
-      public Builder setOfferSet(food.menu.v1.FoodMenu.OfferSet value) {
-        if (offerSetBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          offerSet_ = value;
-        } else {
-          offerSetBuilder_.setMessage(value);
-        }
-        bitField0_ |= 0x00000004;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Available offers to purchase this menu item option.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.OfferSet offer_set = 4;</code>
-       */
-      public Builder setOfferSet(
-          food.menu.v1.FoodMenu.OfferSet.Builder builderForValue) {
-        if (offerSetBuilder_ == null) {
-          offerSet_ = builderForValue.build();
-        } else {
-          offerSetBuilder_.setMessage(builderForValue.build());
-        }
-        bitField0_ |= 0x00000004;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Available offers to purchase this menu item option.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.OfferSet offer_set = 4;</code>
-       */
-      public Builder mergeOfferSet(food.menu.v1.FoodMenu.OfferSet value) {
-        if (offerSetBuilder_ == null) {
-          if (((bitField0_ & 0x00000004) != 0) &&
-            offerSet_ != null &&
-            offerSet_ != food.menu.v1.FoodMenu.OfferSet.getDefaultInstance()) {
-            getOfferSetBuilder().mergeFrom(value);
-          } else {
-            offerSet_ = value;
-          }
-        } else {
-          offerSetBuilder_.mergeFrom(value);
-        }
-        bitField0_ |= 0x00000004;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Available offers to purchase this menu item option.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.OfferSet offer_set = 4;</code>
-       */
-      public Builder clearOfferSet() {
-        bitField0_ = (bitField0_ & ~0x00000004);
-        offerSet_ = null;
-        if (offerSetBuilder_ != null) {
-          offerSetBuilder_.dispose();
-          offerSetBuilder_ = null;
-        }
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Available offers to purchase this menu item option.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.OfferSet offer_set = 4;</code>
-       */
-      public food.menu.v1.FoodMenu.OfferSet.Builder getOfferSetBuilder() {
-        bitField0_ |= 0x00000004;
-        onChanged();
-        return getOfferSetFieldBuilder().getBuilder();
-      }
-      /**
-       * <pre>
-       * Available offers to purchase this menu item option.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.OfferSet offer_set = 4;</code>
-       */
-      public food.menu.v1.FoodMenu.OfferSetOrBuilder getOfferSetOrBuilder() {
-        if (offerSetBuilder_ != null) {
-          return offerSetBuilder_.getMessageOrBuilder();
-        } else {
-          return offerSet_ == null ?
-              food.menu.v1.FoodMenu.OfferSet.getDefaultInstance() : offerSet_;
-        }
-      }
-      /**
-       * <pre>
-       * Available offers to purchase this menu item option.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.OfferSet offer_set = 4;</code>
-       */
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.OfferSet, food.menu.v1.FoodMenu.OfferSet.Builder, food.menu.v1.FoodMenu.OfferSetOrBuilder> 
-          getOfferSetFieldBuilder() {
-        if (offerSetBuilder_ == null) {
-          offerSetBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
-              food.menu.v1.FoodMenu.OfferSet, food.menu.v1.FoodMenu.OfferSet.Builder, food.menu.v1.FoodMenu.OfferSetOrBuilder>(
-                  getOfferSet(),
-                  getParentForChildren(),
-                  isClean());
-          offerSet_ = null;
-        }
-        return offerSetBuilder_;
-      }
-
-      private food.menu.v1.FoodMenu.MenuItemAttributes itemAttributes_;
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.MenuItemAttributes, food.menu.v1.FoodMenu.MenuItemAttributes.Builder, food.menu.v1.FoodMenu.MenuItemAttributesOrBuilder> itemAttributesBuilder_;
-      /**
-       * <pre>
-       * Attributes about this menu item option.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItemAttributes item_attributes = 5;</code>
-       * @return Whether the itemAttributes field is set.
-       */
-      public boolean hasItemAttributes() {
-        return ((bitField0_ & 0x00000008) != 0);
-      }
-      /**
-       * <pre>
-       * Attributes about this menu item option.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItemAttributes item_attributes = 5;</code>
-       * @return The itemAttributes.
-       */
-      public food.menu.v1.FoodMenu.MenuItemAttributes getItemAttributes() {
-        if (itemAttributesBuilder_ == null) {
-          return itemAttributes_ == null ? food.menu.v1.FoodMenu.MenuItemAttributes.getDefaultInstance() : itemAttributes_;
-        } else {
-          return itemAttributesBuilder_.getMessage();
-        }
-      }
-      /**
-       * <pre>
-       * Attributes about this menu item option.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItemAttributes item_attributes = 5;</code>
-       */
-      public Builder setItemAttributes(food.menu.v1.FoodMenu.MenuItemAttributes value) {
-        if (itemAttributesBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          itemAttributes_ = value;
-        } else {
-          itemAttributesBuilder_.setMessage(value);
-        }
-        bitField0_ |= 0x00000008;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Attributes about this menu item option.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItemAttributes item_attributes = 5;</code>
-       */
-      public Builder setItemAttributes(
-          food.menu.v1.FoodMenu.MenuItemAttributes.Builder builderForValue) {
-        if (itemAttributesBuilder_ == null) {
-          itemAttributes_ = builderForValue.build();
-        } else {
-          itemAttributesBuilder_.setMessage(builderForValue.build());
-        }
-        bitField0_ |= 0x00000008;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Attributes about this menu item option.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItemAttributes item_attributes = 5;</code>
-       */
-      public Builder mergeItemAttributes(food.menu.v1.FoodMenu.MenuItemAttributes value) {
-        if (itemAttributesBuilder_ == null) {
-          if (((bitField0_ & 0x00000008) != 0) &&
-            itemAttributes_ != null &&
-            itemAttributes_ != food.menu.v1.FoodMenu.MenuItemAttributes.getDefaultInstance()) {
-            getItemAttributesBuilder().mergeFrom(value);
-          } else {
-            itemAttributes_ = value;
-          }
-        } else {
-          itemAttributesBuilder_.mergeFrom(value);
-        }
-        bitField0_ |= 0x00000008;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Attributes about this menu item option.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItemAttributes item_attributes = 5;</code>
-       */
-      public Builder clearItemAttributes() {
-        bitField0_ = (bitField0_ & ~0x00000008);
-        itemAttributes_ = null;
-        if (itemAttributesBuilder_ != null) {
-          itemAttributesBuilder_.dispose();
-          itemAttributesBuilder_ = null;
-        }
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Attributes about this menu item option.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItemAttributes item_attributes = 5;</code>
-       */
-      public food.menu.v1.FoodMenu.MenuItemAttributes.Builder getItemAttributesBuilder() {
-        bitField0_ |= 0x00000008;
-        onChanged();
-        return getItemAttributesFieldBuilder().getBuilder();
-      }
-      /**
-       * <pre>
-       * Attributes about this menu item option.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItemAttributes item_attributes = 5;</code>
-       */
-      public food.menu.v1.FoodMenu.MenuItemAttributesOrBuilder getItemAttributesOrBuilder() {
-        if (itemAttributesBuilder_ != null) {
-          return itemAttributesBuilder_.getMessageOrBuilder();
-        } else {
-          return itemAttributes_ == null ?
-              food.menu.v1.FoodMenu.MenuItemAttributes.getDefaultInstance() : itemAttributes_;
-        }
-      }
-      /**
-       * <pre>
-       * Attributes about this menu item option.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItemAttributes item_attributes = 5;</code>
-       */
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.MenuItemAttributes, food.menu.v1.FoodMenu.MenuItemAttributes.Builder, food.menu.v1.FoodMenu.MenuItemAttributesOrBuilder> 
-          getItemAttributesFieldBuilder() {
-        if (itemAttributesBuilder_ == null) {
-          itemAttributesBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
-              food.menu.v1.FoodMenu.MenuItemAttributes, food.menu.v1.FoodMenu.MenuItemAttributes.Builder, food.menu.v1.FoodMenu.MenuItemAttributesOrBuilder>(
-                  getItemAttributes(),
-                  getParentForChildren(),
-                  isClean());
-          itemAttributes_ = null;
-        }
-        return itemAttributesBuilder_;
-      }
-      @java.lang.Override
-      public final Builder setUnknownFields(
-          final com.google.protobuf.UnknownFieldSet unknownFields) {
-        return super.setUnknownFields(unknownFields);
-      }
-
-      @java.lang.Override
-      public final Builder mergeUnknownFields(
-          final com.google.protobuf.UnknownFieldSet unknownFields) {
-        return super.mergeUnknownFields(unknownFields);
-      }
-
-
-      // @@protoc_insertion_point(builder_scope:food.menu.v1.MenuItemOption)
-    }
-
-    // @@protoc_insertion_point(class_scope:food.menu.v1.MenuItemOption)
-    private static final food.menu.v1.FoodMenu.MenuItemOption DEFAULT_INSTANCE;
-    static {
-      DEFAULT_INSTANCE = new food.menu.v1.FoodMenu.MenuItemOption();
-    }
-
-    public static food.menu.v1.FoodMenu.MenuItemOption getDefaultInstance() {
-      return DEFAULT_INSTANCE;
-    }
-
-    private static final com.google.protobuf.Parser<MenuItemOption>
-        PARSER = new com.google.protobuf.AbstractParser<MenuItemOption>() {
-      @java.lang.Override
-      public MenuItemOption parsePartialFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws com.google.protobuf.InvalidProtocolBufferException {
-        Builder builder = newBuilder();
-        try {
-          builder.mergeFrom(input, extensionRegistry);
-        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          throw e.setUnfinishedMessage(builder.buildPartial());
-        } catch (com.google.protobuf.UninitializedMessageException e) {
-          throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
-        } catch (java.io.IOException e) {
-          throw new com.google.protobuf.InvalidProtocolBufferException(e)
-              .setUnfinishedMessage(builder.buildPartial());
-        }
-        return builder.buildPartial();
-      }
-    };
-
-    public static com.google.protobuf.Parser<MenuItemOption> parser() {
-      return PARSER;
-    }
-
-    @java.lang.Override
-    public com.google.protobuf.Parser<MenuItemOption> getParserForType() {
-      return PARSER;
-    }
-
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.MenuItemOption getDefaultInstanceForType() {
-      return DEFAULT_INSTANCE;
-    }
-
-  }
-
-  public interface MenuItemAttributesOrBuilder extends
-      // @@protoc_insertion_point(interface_extends:food.menu.v1.MenuItemAttributes)
-      com.google.protobuf.MessageOrBuilder {
-
-    /**
-     * <pre>
-     * Number of servings available in a given menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>optional int32 number_of_servings = 1;</code>
-     * @return Whether the numberOfServings field is set.
-     */
-    boolean hasNumberOfServings();
-    /**
-     * <pre>
-     * Number of servings available in a given menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>optional int32 number_of_servings = 1;</code>
-     * @return The numberOfServings.
-     */
-    int getNumberOfServings();
-
-    /**
-     * <pre>
-     * Describes all the nutritional information of the item, e.g. calories, fat
-     * content.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.NutritionInformation nutrition_information = 2;</code>
-     * @return Whether the nutritionInformation field is set.
-     */
-    boolean hasNutritionInformation();
-    /**
-     * <pre>
-     * Describes all the nutritional information of the item, e.g. calories, fat
-     * content.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.NutritionInformation nutrition_information = 2;</code>
-     * @return The nutritionInformation.
-     */
-    food.menu.v1.FoodMenu.NutritionInformation getNutritionInformation();
-    /**
-     * <pre>
-     * Describes all the nutritional information of the item, e.g. calories, fat
-     * content.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.NutritionInformation nutrition_information = 2;</code>
-     */
-    food.menu.v1.FoodMenu.NutritionInformationOrBuilder getNutritionInformationOrBuilder();
-
-    /**
-     * <pre>
-     * The dietary restrictions that this menu item complies with.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.DietaryRestriction suitable_diets = 3;</code>
-     * @return A list containing the suitableDiets.
-     */
-    java.util.List<food.menu.v1.FoodMenu.DietaryRestriction> getSuitableDietsList();
-    /**
-     * <pre>
-     * The dietary restrictions that this menu item complies with.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.DietaryRestriction suitable_diets = 3;</code>
-     * @return The count of suitableDiets.
-     */
-    int getSuitableDietsCount();
-    /**
-     * <pre>
-     * The dietary restrictions that this menu item complies with.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.DietaryRestriction suitable_diets = 3;</code>
-     * @param index The index of the element to return.
-     * @return The suitableDiets at the given index.
-     */
-    food.menu.v1.FoodMenu.DietaryRestriction getSuitableDiets(int index);
-    /**
-     * <pre>
-     * The dietary restrictions that this menu item complies with.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.DietaryRestriction suitable_diets = 3;</code>
-     * @return A list containing the enum numeric values on the wire for suitableDiets.
-     */
-    java.util.List<java.lang.Integer>
-    getSuitableDietsValueList();
-    /**
-     * <pre>
-     * The dietary restrictions that this menu item complies with.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.DietaryRestriction suitable_diets = 3;</code>
-     * @param index The index of the value to return.
-     * @return The enum numeric value on the wire of suitableDiets at the given index.
-     */
-    int getSuitableDietsValue(int index);
-
-    /**
-     * <pre>
-     * Additives of this menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Additive additive = 4;</code>
-     */
-    java.util.List<food.menu.v1.FoodMenu.Additive> 
-        getAdditiveList();
-    /**
-     * <pre>
-     * Additives of this menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Additive additive = 4;</code>
-     */
-    food.menu.v1.FoodMenu.Additive getAdditive(int index);
-    /**
-     * <pre>
-     * Additives of this menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Additive additive = 4;</code>
-     */
-    int getAdditiveCount();
-    /**
-     * <pre>
-     * Additives of this menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Additive additive = 4;</code>
-     */
-    java.util.List<? extends food.menu.v1.FoodMenu.AdditiveOrBuilder> 
-        getAdditiveOrBuilderList();
-    /**
-     * <pre>
-     * Additives of this menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Additive additive = 4;</code>
-     */
-    food.menu.v1.FoodMenu.AdditiveOrBuilder getAdditiveOrBuilder(
-        int index);
-
-    /**
-     * <pre>
-     * Allergens of this menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Allergen allergen = 5;</code>
-     */
-    java.util.List<food.menu.v1.FoodMenu.Allergen> 
-        getAllergenList();
-    /**
-     * <pre>
-     * Allergens of this menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Allergen allergen = 5;</code>
-     */
-    food.menu.v1.FoodMenu.Allergen getAllergen(int index);
-    /**
-     * <pre>
-     * Allergens of this menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Allergen allergen = 5;</code>
-     */
-    int getAllergenCount();
-    /**
-     * <pre>
-     * Allergens of this menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Allergen allergen = 5;</code>
-     */
-    java.util.List<? extends food.menu.v1.FoodMenu.AllergenOrBuilder> 
-        getAllergenOrBuilderList();
-    /**
-     * <pre>
-     * Allergens of this menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Allergen allergen = 5;</code>
-     */
-    food.menu.v1.FoodMenu.AllergenOrBuilder getAllergenOrBuilder(
-        int index);
-
-    /**
-     * <pre>
-     * Packaging and recycling information of this menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.DepositInfo packaging_deposit_info = 6;</code>
-     * @return Whether the packagingDepositInfo field is set.
-     */
-    boolean hasPackagingDepositInfo();
-    /**
-     * <pre>
-     * Packaging and recycling information of this menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.DepositInfo packaging_deposit_info = 6;</code>
-     * @return The packagingDepositInfo.
-     */
-    food.menu.v1.FoodMenu.DepositInfo getPackagingDepositInfo();
-    /**
-     * <pre>
-     * Packaging and recycling information of this menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.DepositInfo packaging_deposit_info = 6;</code>
-     */
-    food.menu.v1.FoodMenu.DepositInfoOrBuilder getPackagingDepositInfoOrBuilder();
-  }
-  /**
-   * <pre>
-   * Describes attributes about a particular menu item or option.
-   * </pre>
-   *
-   * Protobuf type {@code food.menu.v1.MenuItemAttributes}
-   */
-  public static final class MenuItemAttributes extends
-      com.google.protobuf.GeneratedMessageV3 implements
-      // @@protoc_insertion_point(message_implements:food.menu.v1.MenuItemAttributes)
-      MenuItemAttributesOrBuilder {
-  private static final long serialVersionUID = 0L;
-    // Use MenuItemAttributes.newBuilder() to construct.
-    private MenuItemAttributes(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
-      super(builder);
-    }
-    private MenuItemAttributes() {
-      suitableDiets_ = java.util.Collections.emptyList();
-      additive_ = java.util.Collections.emptyList();
-      allergen_ = java.util.Collections.emptyList();
-    }
-
-    @java.lang.Override
-    @SuppressWarnings({"unused"})
-    protected java.lang.Object newInstance(
-        UnusedPrivateParameter unused) {
-      return new MenuItemAttributes();
-    }
-
-    public static final com.google.protobuf.Descriptors.Descriptor
-        getDescriptor() {
-      return food.menu.v1.FoodMenu.internal_static_food_menu_v1_MenuItemAttributes_descriptor;
-    }
-
-    @java.lang.Override
-    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-        internalGetFieldAccessorTable() {
-      return food.menu.v1.FoodMenu.internal_static_food_menu_v1_MenuItemAttributes_fieldAccessorTable
-          .ensureFieldAccessorsInitialized(
-              food.menu.v1.FoodMenu.MenuItemAttributes.class, food.menu.v1.FoodMenu.MenuItemAttributes.Builder.class);
-    }
-
-    private int bitField0_;
-    public static final int NUMBER_OF_SERVINGS_FIELD_NUMBER = 1;
-    private int numberOfServings_ = 0;
-    /**
-     * <pre>
-     * Number of servings available in a given menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>optional int32 number_of_servings = 1;</code>
-     * @return Whether the numberOfServings field is set.
-     */
-    @java.lang.Override
-    public boolean hasNumberOfServings() {
-      return ((bitField0_ & 0x00000001) != 0);
-    }
-    /**
-     * <pre>
-     * Number of servings available in a given menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>optional int32 number_of_servings = 1;</code>
-     * @return The numberOfServings.
-     */
-    @java.lang.Override
-    public int getNumberOfServings() {
-      return numberOfServings_;
-    }
-
-    public static final int NUTRITION_INFORMATION_FIELD_NUMBER = 2;
-    private food.menu.v1.FoodMenu.NutritionInformation nutritionInformation_;
-    /**
-     * <pre>
-     * Describes all the nutritional information of the item, e.g. calories, fat
-     * content.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.NutritionInformation nutrition_information = 2;</code>
-     * @return Whether the nutritionInformation field is set.
-     */
-    @java.lang.Override
-    public boolean hasNutritionInformation() {
-      return nutritionInformation_ != null;
-    }
-    /**
-     * <pre>
-     * Describes all the nutritional information of the item, e.g. calories, fat
-     * content.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.NutritionInformation nutrition_information = 2;</code>
-     * @return The nutritionInformation.
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.NutritionInformation getNutritionInformation() {
-      return nutritionInformation_ == null ? food.menu.v1.FoodMenu.NutritionInformation.getDefaultInstance() : nutritionInformation_;
-    }
-    /**
-     * <pre>
-     * Describes all the nutritional information of the item, e.g. calories, fat
-     * content.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.NutritionInformation nutrition_information = 2;</code>
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.NutritionInformationOrBuilder getNutritionInformationOrBuilder() {
-      return nutritionInformation_ == null ? food.menu.v1.FoodMenu.NutritionInformation.getDefaultInstance() : nutritionInformation_;
-    }
-
-    public static final int SUITABLE_DIETS_FIELD_NUMBER = 3;
-    @SuppressWarnings("serial")
-    private java.util.List<java.lang.Integer> suitableDiets_;
-    private static final com.google.protobuf.Internal.ListAdapter.Converter<
-        java.lang.Integer, food.menu.v1.FoodMenu.DietaryRestriction> suitableDiets_converter_ =
-            new com.google.protobuf.Internal.ListAdapter.Converter<
-                java.lang.Integer, food.menu.v1.FoodMenu.DietaryRestriction>() {
-              public food.menu.v1.FoodMenu.DietaryRestriction convert(java.lang.Integer from) {
-                food.menu.v1.FoodMenu.DietaryRestriction result = food.menu.v1.FoodMenu.DietaryRestriction.forNumber(from);
-                return result == null ? food.menu.v1.FoodMenu.DietaryRestriction.UNRECOGNIZED : result;
-              }
-            };
-    /**
-     * <pre>
-     * The dietary restrictions that this menu item complies with.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.DietaryRestriction suitable_diets = 3;</code>
-     * @return A list containing the suitableDiets.
-     */
-    @java.lang.Override
-    public java.util.List<food.menu.v1.FoodMenu.DietaryRestriction> getSuitableDietsList() {
-      return new com.google.protobuf.Internal.ListAdapter<
-          java.lang.Integer, food.menu.v1.FoodMenu.DietaryRestriction>(suitableDiets_, suitableDiets_converter_);
-    }
-    /**
-     * <pre>
-     * The dietary restrictions that this menu item complies with.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.DietaryRestriction suitable_diets = 3;</code>
-     * @return The count of suitableDiets.
-     */
-    @java.lang.Override
-    public int getSuitableDietsCount() {
-      return suitableDiets_.size();
-    }
-    /**
-     * <pre>
-     * The dietary restrictions that this menu item complies with.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.DietaryRestriction suitable_diets = 3;</code>
-     * @param index The index of the element to return.
-     * @return The suitableDiets at the given index.
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.DietaryRestriction getSuitableDiets(int index) {
-      return suitableDiets_converter_.convert(suitableDiets_.get(index));
-    }
-    /**
-     * <pre>
-     * The dietary restrictions that this menu item complies with.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.DietaryRestriction suitable_diets = 3;</code>
-     * @return A list containing the enum numeric values on the wire for suitableDiets.
-     */
-    @java.lang.Override
-    public java.util.List<java.lang.Integer>
-    getSuitableDietsValueList() {
-      return suitableDiets_;
-    }
-    /**
-     * <pre>
-     * The dietary restrictions that this menu item complies with.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.DietaryRestriction suitable_diets = 3;</code>
-     * @param index The index of the value to return.
-     * @return The enum numeric value on the wire of suitableDiets at the given index.
-     */
-    @java.lang.Override
-    public int getSuitableDietsValue(int index) {
-      return suitableDiets_.get(index);
-    }
-    private int suitableDietsMemoizedSerializedSize;
-
-    public static final int ADDITIVE_FIELD_NUMBER = 4;
-    @SuppressWarnings("serial")
-    private java.util.List<food.menu.v1.FoodMenu.Additive> additive_;
-    /**
-     * <pre>
-     * Additives of this menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Additive additive = 4;</code>
-     */
-    @java.lang.Override
-    public java.util.List<food.menu.v1.FoodMenu.Additive> getAdditiveList() {
-      return additive_;
-    }
-    /**
-     * <pre>
-     * Additives of this menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Additive additive = 4;</code>
-     */
-    @java.lang.Override
-    public java.util.List<? extends food.menu.v1.FoodMenu.AdditiveOrBuilder> 
-        getAdditiveOrBuilderList() {
-      return additive_;
-    }
-    /**
-     * <pre>
-     * Additives of this menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Additive additive = 4;</code>
-     */
-    @java.lang.Override
-    public int getAdditiveCount() {
-      return additive_.size();
-    }
-    /**
-     * <pre>
-     * Additives of this menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Additive additive = 4;</code>
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.Additive getAdditive(int index) {
-      return additive_.get(index);
-    }
-    /**
-     * <pre>
-     * Additives of this menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Additive additive = 4;</code>
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.AdditiveOrBuilder getAdditiveOrBuilder(
-        int index) {
-      return additive_.get(index);
-    }
-
-    public static final int ALLERGEN_FIELD_NUMBER = 5;
-    @SuppressWarnings("serial")
-    private java.util.List<food.menu.v1.FoodMenu.Allergen> allergen_;
-    /**
-     * <pre>
-     * Allergens of this menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Allergen allergen = 5;</code>
-     */
-    @java.lang.Override
-    public java.util.List<food.menu.v1.FoodMenu.Allergen> getAllergenList() {
-      return allergen_;
-    }
-    /**
-     * <pre>
-     * Allergens of this menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Allergen allergen = 5;</code>
-     */
-    @java.lang.Override
-    public java.util.List<? extends food.menu.v1.FoodMenu.AllergenOrBuilder> 
-        getAllergenOrBuilderList() {
-      return allergen_;
-    }
-    /**
-     * <pre>
-     * Allergens of this menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Allergen allergen = 5;</code>
-     */
-    @java.lang.Override
-    public int getAllergenCount() {
-      return allergen_.size();
-    }
-    /**
-     * <pre>
-     * Allergens of this menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Allergen allergen = 5;</code>
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.Allergen getAllergen(int index) {
-      return allergen_.get(index);
-    }
-    /**
-     * <pre>
-     * Allergens of this menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Allergen allergen = 5;</code>
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.AllergenOrBuilder getAllergenOrBuilder(
-        int index) {
-      return allergen_.get(index);
-    }
-
-    public static final int PACKAGING_DEPOSIT_INFO_FIELD_NUMBER = 6;
-    private food.menu.v1.FoodMenu.DepositInfo packagingDepositInfo_;
-    /**
-     * <pre>
-     * Packaging and recycling information of this menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.DepositInfo packaging_deposit_info = 6;</code>
-     * @return Whether the packagingDepositInfo field is set.
-     */
-    @java.lang.Override
-    public boolean hasPackagingDepositInfo() {
-      return packagingDepositInfo_ != null;
-    }
-    /**
-     * <pre>
-     * Packaging and recycling information of this menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.DepositInfo packaging_deposit_info = 6;</code>
-     * @return The packagingDepositInfo.
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.DepositInfo getPackagingDepositInfo() {
-      return packagingDepositInfo_ == null ? food.menu.v1.FoodMenu.DepositInfo.getDefaultInstance() : packagingDepositInfo_;
-    }
-    /**
-     * <pre>
-     * Packaging and recycling information of this menu item.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.DepositInfo packaging_deposit_info = 6;</code>
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.DepositInfoOrBuilder getPackagingDepositInfoOrBuilder() {
-      return packagingDepositInfo_ == null ? food.menu.v1.FoodMenu.DepositInfo.getDefaultInstance() : packagingDepositInfo_;
-    }
-
-    private byte memoizedIsInitialized = -1;
-    @java.lang.Override
-    public final boolean isInitialized() {
-      byte isInitialized = memoizedIsInitialized;
-      if (isInitialized == 1) return true;
-      if (isInitialized == 0) return false;
-
-      memoizedIsInitialized = 1;
-      return true;
-    }
-
-    @java.lang.Override
-    public void writeTo(com.google.protobuf.CodedOutputStream output)
-                        throws java.io.IOException {
-      getSerializedSize();
-      if (((bitField0_ & 0x00000001) != 0)) {
-        output.writeInt32(1, numberOfServings_);
-      }
-      if (nutritionInformation_ != null) {
-        output.writeMessage(2, getNutritionInformation());
-      }
-      if (getSuitableDietsList().size() > 0) {
-        output.writeUInt32NoTag(26);
-        output.writeUInt32NoTag(suitableDietsMemoizedSerializedSize);
-      }
-      for (int i = 0; i < suitableDiets_.size(); i++) {
-        output.writeEnumNoTag(suitableDiets_.get(i));
-      }
-      for (int i = 0; i < additive_.size(); i++) {
-        output.writeMessage(4, additive_.get(i));
-      }
-      for (int i = 0; i < allergen_.size(); i++) {
-        output.writeMessage(5, allergen_.get(i));
-      }
-      if (packagingDepositInfo_ != null) {
-        output.writeMessage(6, getPackagingDepositInfo());
-      }
-      getUnknownFields().writeTo(output);
-    }
-
-    @java.lang.Override
-    public int getSerializedSize() {
-      int size = memoizedSize;
-      if (size != -1) return size;
-
-      size = 0;
-      if (((bitField0_ & 0x00000001) != 0)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeInt32Size(1, numberOfServings_);
-      }
-      if (nutritionInformation_ != null) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(2, getNutritionInformation());
-      }
-      {
-        int dataSize = 0;
-        for (int i = 0; i < suitableDiets_.size(); i++) {
-          dataSize += com.google.protobuf.CodedOutputStream
-            .computeEnumSizeNoTag(suitableDiets_.get(i));
-        }
-        size += dataSize;
-        if (!getSuitableDietsList().isEmpty()) {  size += 1;
-          size += com.google.protobuf.CodedOutputStream
-            .computeUInt32SizeNoTag(dataSize);
-        }suitableDietsMemoizedSerializedSize = dataSize;
-      }
-      for (int i = 0; i < additive_.size(); i++) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(4, additive_.get(i));
-      }
-      for (int i = 0; i < allergen_.size(); i++) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(5, allergen_.get(i));
-      }
-      if (packagingDepositInfo_ != null) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(6, getPackagingDepositInfo());
-      }
-      size += getUnknownFields().getSerializedSize();
-      memoizedSize = size;
-      return size;
-    }
-
-    @java.lang.Override
-    public boolean equals(final java.lang.Object obj) {
-      if (obj == this) {
-       return true;
-      }
-      if (!(obj instanceof food.menu.v1.FoodMenu.MenuItemAttributes)) {
-        return super.equals(obj);
-      }
-      food.menu.v1.FoodMenu.MenuItemAttributes other = (food.menu.v1.FoodMenu.MenuItemAttributes) obj;
-
-      if (hasNumberOfServings() != other.hasNumberOfServings()) return false;
-      if (hasNumberOfServings()) {
-        if (getNumberOfServings()
-            != other.getNumberOfServings()) return false;
-      }
-      if (hasNutritionInformation() != other.hasNutritionInformation()) return false;
-      if (hasNutritionInformation()) {
-        if (!getNutritionInformation()
-            .equals(other.getNutritionInformation())) return false;
-      }
-      if (!suitableDiets_.equals(other.suitableDiets_)) return false;
-      if (!getAdditiveList()
-          .equals(other.getAdditiveList())) return false;
-      if (!getAllergenList()
-          .equals(other.getAllergenList())) return false;
-      if (hasPackagingDepositInfo() != other.hasPackagingDepositInfo()) return false;
-      if (hasPackagingDepositInfo()) {
-        if (!getPackagingDepositInfo()
-            .equals(other.getPackagingDepositInfo())) return false;
-      }
-      if (!getUnknownFields().equals(other.getUnknownFields())) return false;
-      return true;
-    }
-
-    @java.lang.Override
-    public int hashCode() {
-      if (memoizedHashCode != 0) {
-        return memoizedHashCode;
-      }
-      int hash = 41;
-      hash = (19 * hash) + getDescriptor().hashCode();
-      if (hasNumberOfServings()) {
-        hash = (37 * hash) + NUMBER_OF_SERVINGS_FIELD_NUMBER;
-        hash = (53 * hash) + getNumberOfServings();
-      }
-      if (hasNutritionInformation()) {
-        hash = (37 * hash) + NUTRITION_INFORMATION_FIELD_NUMBER;
-        hash = (53 * hash) + getNutritionInformation().hashCode();
-      }
-      if (getSuitableDietsCount() > 0) {
-        hash = (37 * hash) + SUITABLE_DIETS_FIELD_NUMBER;
-        hash = (53 * hash) + suitableDiets_.hashCode();
-      }
-      if (getAdditiveCount() > 0) {
-        hash = (37 * hash) + ADDITIVE_FIELD_NUMBER;
-        hash = (53 * hash) + getAdditiveList().hashCode();
-      }
-      if (getAllergenCount() > 0) {
-        hash = (37 * hash) + ALLERGEN_FIELD_NUMBER;
-        hash = (53 * hash) + getAllergenList().hashCode();
-      }
-      if (hasPackagingDepositInfo()) {
-        hash = (37 * hash) + PACKAGING_DEPOSIT_INFO_FIELD_NUMBER;
-        hash = (53 * hash) + getPackagingDepositInfo().hashCode();
-      }
-      hash = (29 * hash) + getUnknownFields().hashCode();
-      memoizedHashCode = hash;
-      return hash;
-    }
-
-    public static food.menu.v1.FoodMenu.MenuItemAttributes parseFrom(
-        java.nio.ByteBuffer data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.MenuItemAttributes parseFrom(
-        java.nio.ByteBuffer data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.MenuItemAttributes parseFrom(
-        com.google.protobuf.ByteString data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.MenuItemAttributes parseFrom(
-        com.google.protobuf.ByteString data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.MenuItemAttributes parseFrom(byte[] data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.MenuItemAttributes parseFrom(
-        byte[] data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.MenuItemAttributes parseFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.MenuItemAttributes parseFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.MenuItemAttributes parseDelimitedFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseDelimitedWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.MenuItemAttributes parseDelimitedFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.MenuItemAttributes parseFrom(
-        com.google.protobuf.CodedInputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.MenuItemAttributes parseFrom(
-        com.google.protobuf.CodedInputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input, extensionRegistry);
-    }
-
-    @java.lang.Override
-    public Builder newBuilderForType() { return newBuilder(); }
-    public static Builder newBuilder() {
-      return DEFAULT_INSTANCE.toBuilder();
-    }
-    public static Builder newBuilder(food.menu.v1.FoodMenu.MenuItemAttributes prototype) {
-      return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
-    }
-    @java.lang.Override
-    public Builder toBuilder() {
-      return this == DEFAULT_INSTANCE
-          ? new Builder() : new Builder().mergeFrom(this);
-    }
-
-    @java.lang.Override
-    protected Builder newBuilderForType(
-        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-      Builder builder = new Builder(parent);
-      return builder;
-    }
-    /**
-     * <pre>
-     * Describes attributes about a particular menu item or option.
-     * </pre>
-     *
-     * Protobuf type {@code food.menu.v1.MenuItemAttributes}
-     */
-    public static final class Builder extends
-        com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
-        // @@protoc_insertion_point(builder_implements:food.menu.v1.MenuItemAttributes)
-        food.menu.v1.FoodMenu.MenuItemAttributesOrBuilder {
-      public static final com.google.protobuf.Descriptors.Descriptor
-          getDescriptor() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_MenuItemAttributes_descriptor;
-      }
-
-      @java.lang.Override
-      protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-          internalGetFieldAccessorTable() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_MenuItemAttributes_fieldAccessorTable
-            .ensureFieldAccessorsInitialized(
-                food.menu.v1.FoodMenu.MenuItemAttributes.class, food.menu.v1.FoodMenu.MenuItemAttributes.Builder.class);
-      }
-
-      // Construct using food.menu.v1.FoodMenu.MenuItemAttributes.newBuilder()
-      private Builder() {
-
-      }
-
-      private Builder(
-          com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-        super(parent);
-
-      }
-      @java.lang.Override
-      public Builder clear() {
-        super.clear();
-        bitField0_ = 0;
-        numberOfServings_ = 0;
-        nutritionInformation_ = null;
-        if (nutritionInformationBuilder_ != null) {
-          nutritionInformationBuilder_.dispose();
-          nutritionInformationBuilder_ = null;
-        }
-        suitableDiets_ = java.util.Collections.emptyList();
-        bitField0_ = (bitField0_ & ~0x00000004);
-        if (additiveBuilder_ == null) {
-          additive_ = java.util.Collections.emptyList();
-        } else {
-          additive_ = null;
-          additiveBuilder_.clear();
-        }
-        bitField0_ = (bitField0_ & ~0x00000008);
-        if (allergenBuilder_ == null) {
-          allergen_ = java.util.Collections.emptyList();
-        } else {
-          allergen_ = null;
-          allergenBuilder_.clear();
-        }
-        bitField0_ = (bitField0_ & ~0x00000010);
-        packagingDepositInfo_ = null;
-        if (packagingDepositInfoBuilder_ != null) {
-          packagingDepositInfoBuilder_.dispose();
-          packagingDepositInfoBuilder_ = null;
-        }
-        return this;
-      }
-
-      @java.lang.Override
-      public com.google.protobuf.Descriptors.Descriptor
-          getDescriptorForType() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_MenuItemAttributes_descriptor;
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.MenuItemAttributes getDefaultInstanceForType() {
-        return food.menu.v1.FoodMenu.MenuItemAttributes.getDefaultInstance();
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.MenuItemAttributes build() {
-        food.menu.v1.FoodMenu.MenuItemAttributes result = buildPartial();
-        if (!result.isInitialized()) {
-          throw newUninitializedMessageException(result);
-        }
-        return result;
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.MenuItemAttributes buildPartial() {
-        food.menu.v1.FoodMenu.MenuItemAttributes result = new food.menu.v1.FoodMenu.MenuItemAttributes(this);
-        buildPartialRepeatedFields(result);
-        if (bitField0_ != 0) { buildPartial0(result); }
-        onBuilt();
-        return result;
-      }
-
-      private void buildPartialRepeatedFields(food.menu.v1.FoodMenu.MenuItemAttributes result) {
-        if (((bitField0_ & 0x00000004) != 0)) {
-          suitableDiets_ = java.util.Collections.unmodifiableList(suitableDiets_);
-          bitField0_ = (bitField0_ & ~0x00000004);
-        }
-        result.suitableDiets_ = suitableDiets_;
-        if (additiveBuilder_ == null) {
-          if (((bitField0_ & 0x00000008) != 0)) {
-            additive_ = java.util.Collections.unmodifiableList(additive_);
-            bitField0_ = (bitField0_ & ~0x00000008);
-          }
-          result.additive_ = additive_;
-        } else {
-          result.additive_ = additiveBuilder_.build();
-        }
-        if (allergenBuilder_ == null) {
-          if (((bitField0_ & 0x00000010) != 0)) {
-            allergen_ = java.util.Collections.unmodifiableList(allergen_);
-            bitField0_ = (bitField0_ & ~0x00000010);
-          }
-          result.allergen_ = allergen_;
-        } else {
-          result.allergen_ = allergenBuilder_.build();
-        }
-      }
-
-      private void buildPartial0(food.menu.v1.FoodMenu.MenuItemAttributes result) {
-        int from_bitField0_ = bitField0_;
-        int to_bitField0_ = 0;
-        if (((from_bitField0_ & 0x00000001) != 0)) {
-          result.numberOfServings_ = numberOfServings_;
-          to_bitField0_ |= 0x00000001;
-        }
-        if (((from_bitField0_ & 0x00000002) != 0)) {
-          result.nutritionInformation_ = nutritionInformationBuilder_ == null
-              ? nutritionInformation_
-              : nutritionInformationBuilder_.build();
-        }
-        if (((from_bitField0_ & 0x00000020) != 0)) {
-          result.packagingDepositInfo_ = packagingDepositInfoBuilder_ == null
-              ? packagingDepositInfo_
-              : packagingDepositInfoBuilder_.build();
-        }
-        result.bitField0_ |= to_bitField0_;
-      }
-
-      @java.lang.Override
-      public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof food.menu.v1.FoodMenu.MenuItemAttributes) {
-          return mergeFrom((food.menu.v1.FoodMenu.MenuItemAttributes)other);
-        } else {
-          super.mergeFrom(other);
-          return this;
-        }
-      }
-
-      public Builder mergeFrom(food.menu.v1.FoodMenu.MenuItemAttributes other) {
-        if (other == food.menu.v1.FoodMenu.MenuItemAttributes.getDefaultInstance()) return this;
-        if (other.hasNumberOfServings()) {
-          setNumberOfServings(other.getNumberOfServings());
-        }
-        if (other.hasNutritionInformation()) {
-          mergeNutritionInformation(other.getNutritionInformation());
-        }
-        if (!other.suitableDiets_.isEmpty()) {
-          if (suitableDiets_.isEmpty()) {
-            suitableDiets_ = other.suitableDiets_;
-            bitField0_ = (bitField0_ & ~0x00000004);
-          } else {
-            ensureSuitableDietsIsMutable();
-            suitableDiets_.addAll(other.suitableDiets_);
-          }
-          onChanged();
-        }
-        if (additiveBuilder_ == null) {
-          if (!other.additive_.isEmpty()) {
-            if (additive_.isEmpty()) {
-              additive_ = other.additive_;
-              bitField0_ = (bitField0_ & ~0x00000008);
-            } else {
-              ensureAdditiveIsMutable();
-              additive_.addAll(other.additive_);
-            }
-            onChanged();
-          }
-        } else {
-          if (!other.additive_.isEmpty()) {
-            if (additiveBuilder_.isEmpty()) {
-              additiveBuilder_.dispose();
-              additiveBuilder_ = null;
-              additive_ = other.additive_;
-              bitField0_ = (bitField0_ & ~0x00000008);
-              additiveBuilder_ = 
-                com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ?
-                   getAdditiveFieldBuilder() : null;
-            } else {
-              additiveBuilder_.addAllMessages(other.additive_);
-            }
-          }
-        }
-        if (allergenBuilder_ == null) {
-          if (!other.allergen_.isEmpty()) {
-            if (allergen_.isEmpty()) {
-              allergen_ = other.allergen_;
-              bitField0_ = (bitField0_ & ~0x00000010);
-            } else {
-              ensureAllergenIsMutable();
-              allergen_.addAll(other.allergen_);
-            }
-            onChanged();
-          }
-        } else {
-          if (!other.allergen_.isEmpty()) {
-            if (allergenBuilder_.isEmpty()) {
-              allergenBuilder_.dispose();
-              allergenBuilder_ = null;
-              allergen_ = other.allergen_;
-              bitField0_ = (bitField0_ & ~0x00000010);
-              allergenBuilder_ = 
-                com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ?
-                   getAllergenFieldBuilder() : null;
-            } else {
-              allergenBuilder_.addAllMessages(other.allergen_);
-            }
-          }
-        }
-        if (other.hasPackagingDepositInfo()) {
-          mergePackagingDepositInfo(other.getPackagingDepositInfo());
-        }
-        this.mergeUnknownFields(other.getUnknownFields());
-        onChanged();
-        return this;
-      }
-
-      @java.lang.Override
-      public final boolean isInitialized() {
-        return true;
-      }
-
-      @java.lang.Override
-      public Builder mergeFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws java.io.IOException {
-        if (extensionRegistry == null) {
-          throw new java.lang.NullPointerException();
-        }
-        try {
-          boolean done = false;
-          while (!done) {
-            int tag = input.readTag();
-            switch (tag) {
-              case 0:
-                done = true;
-                break;
-              case 8: {
-                numberOfServings_ = input.readInt32();
-                bitField0_ |= 0x00000001;
-                break;
-              } // case 8
-              case 18: {
-                input.readMessage(
-                    getNutritionInformationFieldBuilder().getBuilder(),
-                    extensionRegistry);
-                bitField0_ |= 0x00000002;
-                break;
-              } // case 18
-              case 24: {
-                int tmpRaw = input.readEnum();
-                ensureSuitableDietsIsMutable();
-                suitableDiets_.add(tmpRaw);
-                break;
-              } // case 24
-              case 26: {
-                int length = input.readRawVarint32();
-                int oldLimit = input.pushLimit(length);
-                while(input.getBytesUntilLimit() > 0) {
-                  int tmpRaw = input.readEnum();
-                  ensureSuitableDietsIsMutable();
-                  suitableDiets_.add(tmpRaw);
-                }
-                input.popLimit(oldLimit);
-                break;
-              } // case 26
-              case 34: {
-                food.menu.v1.FoodMenu.Additive m =
-                    input.readMessage(
-                        food.menu.v1.FoodMenu.Additive.parser(),
-                        extensionRegistry);
-                if (additiveBuilder_ == null) {
-                  ensureAdditiveIsMutable();
-                  additive_.add(m);
-                } else {
-                  additiveBuilder_.addMessage(m);
-                }
-                break;
-              } // case 34
-              case 42: {
-                food.menu.v1.FoodMenu.Allergen m =
-                    input.readMessage(
-                        food.menu.v1.FoodMenu.Allergen.parser(),
-                        extensionRegistry);
-                if (allergenBuilder_ == null) {
-                  ensureAllergenIsMutable();
-                  allergen_.add(m);
-                } else {
-                  allergenBuilder_.addMessage(m);
-                }
-                break;
-              } // case 42
-              case 50: {
-                input.readMessage(
-                    getPackagingDepositInfoFieldBuilder().getBuilder(),
-                    extensionRegistry);
-                bitField0_ |= 0x00000020;
-                break;
-              } // case 50
-              default: {
-                if (!super.parseUnknownField(input, extensionRegistry, tag)) {
-                  done = true; // was an endgroup tag
-                }
-                break;
-              } // default:
-            } // switch (tag)
-          } // while (!done)
-        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          throw e.unwrapIOException();
-        } finally {
-          onChanged();
-        } // finally
-        return this;
-      }
-      private int bitField0_;
-
-      private int numberOfServings_ ;
-      /**
-       * <pre>
-       * Number of servings available in a given menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>optional int32 number_of_servings = 1;</code>
-       * @return Whether the numberOfServings field is set.
-       */
-      @java.lang.Override
-      public boolean hasNumberOfServings() {
-        return ((bitField0_ & 0x00000001) != 0);
-      }
-      /**
-       * <pre>
-       * Number of servings available in a given menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>optional int32 number_of_servings = 1;</code>
-       * @return The numberOfServings.
-       */
-      @java.lang.Override
-      public int getNumberOfServings() {
-        return numberOfServings_;
-      }
-      /**
-       * <pre>
-       * Number of servings available in a given menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>optional int32 number_of_servings = 1;</code>
-       * @param value The numberOfServings to set.
-       * @return This builder for chaining.
-       */
-      public Builder setNumberOfServings(int value) {
-
-        numberOfServings_ = value;
-        bitField0_ |= 0x00000001;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Number of servings available in a given menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>optional int32 number_of_servings = 1;</code>
-       * @return This builder for chaining.
-       */
-      public Builder clearNumberOfServings() {
-        bitField0_ = (bitField0_ & ~0x00000001);
-        numberOfServings_ = 0;
-        onChanged();
-        return this;
-      }
-
-      private food.menu.v1.FoodMenu.NutritionInformation nutritionInformation_;
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.NutritionInformation, food.menu.v1.FoodMenu.NutritionInformation.Builder, food.menu.v1.FoodMenu.NutritionInformationOrBuilder> nutritionInformationBuilder_;
-      /**
-       * <pre>
-       * Describes all the nutritional information of the item, e.g. calories, fat
-       * content.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.NutritionInformation nutrition_information = 2;</code>
-       * @return Whether the nutritionInformation field is set.
-       */
-      public boolean hasNutritionInformation() {
-        return ((bitField0_ & 0x00000002) != 0);
-      }
-      /**
-       * <pre>
-       * Describes all the nutritional information of the item, e.g. calories, fat
-       * content.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.NutritionInformation nutrition_information = 2;</code>
-       * @return The nutritionInformation.
-       */
-      public food.menu.v1.FoodMenu.NutritionInformation getNutritionInformation() {
-        if (nutritionInformationBuilder_ == null) {
-          return nutritionInformation_ == null ? food.menu.v1.FoodMenu.NutritionInformation.getDefaultInstance() : nutritionInformation_;
-        } else {
-          return nutritionInformationBuilder_.getMessage();
-        }
-      }
-      /**
-       * <pre>
-       * Describes all the nutritional information of the item, e.g. calories, fat
-       * content.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.NutritionInformation nutrition_information = 2;</code>
-       */
-      public Builder setNutritionInformation(food.menu.v1.FoodMenu.NutritionInformation value) {
-        if (nutritionInformationBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          nutritionInformation_ = value;
-        } else {
-          nutritionInformationBuilder_.setMessage(value);
-        }
-        bitField0_ |= 0x00000002;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Describes all the nutritional information of the item, e.g. calories, fat
-       * content.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.NutritionInformation nutrition_information = 2;</code>
-       */
-      public Builder setNutritionInformation(
-          food.menu.v1.FoodMenu.NutritionInformation.Builder builderForValue) {
-        if (nutritionInformationBuilder_ == null) {
-          nutritionInformation_ = builderForValue.build();
-        } else {
-          nutritionInformationBuilder_.setMessage(builderForValue.build());
-        }
-        bitField0_ |= 0x00000002;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Describes all the nutritional information of the item, e.g. calories, fat
-       * content.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.NutritionInformation nutrition_information = 2;</code>
-       */
-      public Builder mergeNutritionInformation(food.menu.v1.FoodMenu.NutritionInformation value) {
-        if (nutritionInformationBuilder_ == null) {
-          if (((bitField0_ & 0x00000002) != 0) &&
-            nutritionInformation_ != null &&
-            nutritionInformation_ != food.menu.v1.FoodMenu.NutritionInformation.getDefaultInstance()) {
-            getNutritionInformationBuilder().mergeFrom(value);
-          } else {
-            nutritionInformation_ = value;
-          }
-        } else {
-          nutritionInformationBuilder_.mergeFrom(value);
-        }
-        bitField0_ |= 0x00000002;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Describes all the nutritional information of the item, e.g. calories, fat
-       * content.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.NutritionInformation nutrition_information = 2;</code>
-       */
-      public Builder clearNutritionInformation() {
-        bitField0_ = (bitField0_ & ~0x00000002);
-        nutritionInformation_ = null;
-        if (nutritionInformationBuilder_ != null) {
-          nutritionInformationBuilder_.dispose();
-          nutritionInformationBuilder_ = null;
-        }
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Describes all the nutritional information of the item, e.g. calories, fat
-       * content.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.NutritionInformation nutrition_information = 2;</code>
-       */
-      public food.menu.v1.FoodMenu.NutritionInformation.Builder getNutritionInformationBuilder() {
-        bitField0_ |= 0x00000002;
-        onChanged();
-        return getNutritionInformationFieldBuilder().getBuilder();
-      }
-      /**
-       * <pre>
-       * Describes all the nutritional information of the item, e.g. calories, fat
-       * content.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.NutritionInformation nutrition_information = 2;</code>
-       */
-      public food.menu.v1.FoodMenu.NutritionInformationOrBuilder getNutritionInformationOrBuilder() {
-        if (nutritionInformationBuilder_ != null) {
-          return nutritionInformationBuilder_.getMessageOrBuilder();
-        } else {
-          return nutritionInformation_ == null ?
-              food.menu.v1.FoodMenu.NutritionInformation.getDefaultInstance() : nutritionInformation_;
-        }
-      }
-      /**
-       * <pre>
-       * Describes all the nutritional information of the item, e.g. calories, fat
-       * content.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.NutritionInformation nutrition_information = 2;</code>
-       */
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.NutritionInformation, food.menu.v1.FoodMenu.NutritionInformation.Builder, food.menu.v1.FoodMenu.NutritionInformationOrBuilder> 
-          getNutritionInformationFieldBuilder() {
-        if (nutritionInformationBuilder_ == null) {
-          nutritionInformationBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
-              food.menu.v1.FoodMenu.NutritionInformation, food.menu.v1.FoodMenu.NutritionInformation.Builder, food.menu.v1.FoodMenu.NutritionInformationOrBuilder>(
-                  getNutritionInformation(),
-                  getParentForChildren(),
-                  isClean());
-          nutritionInformation_ = null;
-        }
-        return nutritionInformationBuilder_;
-      }
-
-      private java.util.List<java.lang.Integer> suitableDiets_ =
-        java.util.Collections.emptyList();
-      private void ensureSuitableDietsIsMutable() {
-        if (!((bitField0_ & 0x00000004) != 0)) {
-          suitableDiets_ = new java.util.ArrayList<java.lang.Integer>(suitableDiets_);
-          bitField0_ |= 0x00000004;
-        }
-      }
-      /**
-       * <pre>
-       * The dietary restrictions that this menu item complies with.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.DietaryRestriction suitable_diets = 3;</code>
-       * @return A list containing the suitableDiets.
-       */
-      public java.util.List<food.menu.v1.FoodMenu.DietaryRestriction> getSuitableDietsList() {
-        return new com.google.protobuf.Internal.ListAdapter<
-            java.lang.Integer, food.menu.v1.FoodMenu.DietaryRestriction>(suitableDiets_, suitableDiets_converter_);
-      }
-      /**
-       * <pre>
-       * The dietary restrictions that this menu item complies with.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.DietaryRestriction suitable_diets = 3;</code>
-       * @return The count of suitableDiets.
-       */
-      public int getSuitableDietsCount() {
-        return suitableDiets_.size();
-      }
-      /**
-       * <pre>
-       * The dietary restrictions that this menu item complies with.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.DietaryRestriction suitable_diets = 3;</code>
-       * @param index The index of the element to return.
-       * @return The suitableDiets at the given index.
-       */
-      public food.menu.v1.FoodMenu.DietaryRestriction getSuitableDiets(int index) {
-        return suitableDiets_converter_.convert(suitableDiets_.get(index));
-      }
-      /**
-       * <pre>
-       * The dietary restrictions that this menu item complies with.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.DietaryRestriction suitable_diets = 3;</code>
-       * @param index The index to set the value at.
-       * @param value The suitableDiets to set.
-       * @return This builder for chaining.
-       */
-      public Builder setSuitableDiets(
-          int index, food.menu.v1.FoodMenu.DietaryRestriction value) {
-        if (value == null) {
-          throw new NullPointerException();
-        }
-        ensureSuitableDietsIsMutable();
-        suitableDiets_.set(index, value.getNumber());
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * The dietary restrictions that this menu item complies with.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.DietaryRestriction suitable_diets = 3;</code>
-       * @param value The suitableDiets to add.
-       * @return This builder for chaining.
-       */
-      public Builder addSuitableDiets(food.menu.v1.FoodMenu.DietaryRestriction value) {
-        if (value == null) {
-          throw new NullPointerException();
-        }
-        ensureSuitableDietsIsMutable();
-        suitableDiets_.add(value.getNumber());
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * The dietary restrictions that this menu item complies with.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.DietaryRestriction suitable_diets = 3;</code>
-       * @param values The suitableDiets to add.
-       * @return This builder for chaining.
-       */
-      public Builder addAllSuitableDiets(
-          java.lang.Iterable<? extends food.menu.v1.FoodMenu.DietaryRestriction> values) {
-        ensureSuitableDietsIsMutable();
-        for (food.menu.v1.FoodMenu.DietaryRestriction value : values) {
-          suitableDiets_.add(value.getNumber());
-        }
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * The dietary restrictions that this menu item complies with.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.DietaryRestriction suitable_diets = 3;</code>
-       * @return This builder for chaining.
-       */
-      public Builder clearSuitableDiets() {
-        suitableDiets_ = java.util.Collections.emptyList();
-        bitField0_ = (bitField0_ & ~0x00000004);
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * The dietary restrictions that this menu item complies with.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.DietaryRestriction suitable_diets = 3;</code>
-       * @return A list containing the enum numeric values on the wire for suitableDiets.
-       */
-      public java.util.List<java.lang.Integer>
-      getSuitableDietsValueList() {
-        return java.util.Collections.unmodifiableList(suitableDiets_);
-      }
-      /**
-       * <pre>
-       * The dietary restrictions that this menu item complies with.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.DietaryRestriction suitable_diets = 3;</code>
-       * @param index The index of the value to return.
-       * @return The enum numeric value on the wire of suitableDiets at the given index.
-       */
-      public int getSuitableDietsValue(int index) {
-        return suitableDiets_.get(index);
-      }
-      /**
-       * <pre>
-       * The dietary restrictions that this menu item complies with.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.DietaryRestriction suitable_diets = 3;</code>
-       * @param index The index to set the value at.
-       * @param value The enum numeric value on the wire for suitableDiets to set.
-       * @return This builder for chaining.
-       */
-      public Builder setSuitableDietsValue(
-          int index, int value) {
-        ensureSuitableDietsIsMutable();
-        suitableDiets_.set(index, value);
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * The dietary restrictions that this menu item complies with.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.DietaryRestriction suitable_diets = 3;</code>
-       * @param value The enum numeric value on the wire for suitableDiets to add.
-       * @return This builder for chaining.
-       */
-      public Builder addSuitableDietsValue(int value) {
-        ensureSuitableDietsIsMutable();
-        suitableDiets_.add(value);
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * The dietary restrictions that this menu item complies with.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.DietaryRestriction suitable_diets = 3;</code>
-       * @param values The enum numeric values on the wire for suitableDiets to add.
-       * @return This builder for chaining.
-       */
-      public Builder addAllSuitableDietsValue(
-          java.lang.Iterable<java.lang.Integer> values) {
-        ensureSuitableDietsIsMutable();
-        for (int value : values) {
-          suitableDiets_.add(value);
-        }
-        onChanged();
-        return this;
-      }
-
-      private java.util.List<food.menu.v1.FoodMenu.Additive> additive_ =
-        java.util.Collections.emptyList();
-      private void ensureAdditiveIsMutable() {
-        if (!((bitField0_ & 0x00000008) != 0)) {
-          additive_ = new java.util.ArrayList<food.menu.v1.FoodMenu.Additive>(additive_);
-          bitField0_ |= 0x00000008;
-         }
-      }
-
-      private com.google.protobuf.RepeatedFieldBuilderV3<
-          food.menu.v1.FoodMenu.Additive, food.menu.v1.FoodMenu.Additive.Builder, food.menu.v1.FoodMenu.AdditiveOrBuilder> additiveBuilder_;
-
-      /**
-       * <pre>
-       * Additives of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Additive additive = 4;</code>
-       */
-      public java.util.List<food.menu.v1.FoodMenu.Additive> getAdditiveList() {
-        if (additiveBuilder_ == null) {
-          return java.util.Collections.unmodifiableList(additive_);
-        } else {
-          return additiveBuilder_.getMessageList();
-        }
-      }
-      /**
-       * <pre>
-       * Additives of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Additive additive = 4;</code>
-       */
-      public int getAdditiveCount() {
-        if (additiveBuilder_ == null) {
-          return additive_.size();
-        } else {
-          return additiveBuilder_.getCount();
-        }
-      }
-      /**
-       * <pre>
-       * Additives of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Additive additive = 4;</code>
-       */
-      public food.menu.v1.FoodMenu.Additive getAdditive(int index) {
-        if (additiveBuilder_ == null) {
-          return additive_.get(index);
-        } else {
-          return additiveBuilder_.getMessage(index);
-        }
-      }
-      /**
-       * <pre>
-       * Additives of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Additive additive = 4;</code>
-       */
-      public Builder setAdditive(
-          int index, food.menu.v1.FoodMenu.Additive value) {
-        if (additiveBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          ensureAdditiveIsMutable();
-          additive_.set(index, value);
-          onChanged();
-        } else {
-          additiveBuilder_.setMessage(index, value);
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Additives of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Additive additive = 4;</code>
-       */
-      public Builder setAdditive(
-          int index, food.menu.v1.FoodMenu.Additive.Builder builderForValue) {
-        if (additiveBuilder_ == null) {
-          ensureAdditiveIsMutable();
-          additive_.set(index, builderForValue.build());
-          onChanged();
-        } else {
-          additiveBuilder_.setMessage(index, builderForValue.build());
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Additives of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Additive additive = 4;</code>
-       */
-      public Builder addAdditive(food.menu.v1.FoodMenu.Additive value) {
-        if (additiveBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          ensureAdditiveIsMutable();
-          additive_.add(value);
-          onChanged();
-        } else {
-          additiveBuilder_.addMessage(value);
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Additives of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Additive additive = 4;</code>
-       */
-      public Builder addAdditive(
-          int index, food.menu.v1.FoodMenu.Additive value) {
-        if (additiveBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          ensureAdditiveIsMutable();
-          additive_.add(index, value);
-          onChanged();
-        } else {
-          additiveBuilder_.addMessage(index, value);
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Additives of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Additive additive = 4;</code>
-       */
-      public Builder addAdditive(
-          food.menu.v1.FoodMenu.Additive.Builder builderForValue) {
-        if (additiveBuilder_ == null) {
-          ensureAdditiveIsMutable();
-          additive_.add(builderForValue.build());
-          onChanged();
-        } else {
-          additiveBuilder_.addMessage(builderForValue.build());
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Additives of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Additive additive = 4;</code>
-       */
-      public Builder addAdditive(
-          int index, food.menu.v1.FoodMenu.Additive.Builder builderForValue) {
-        if (additiveBuilder_ == null) {
-          ensureAdditiveIsMutable();
-          additive_.add(index, builderForValue.build());
-          onChanged();
-        } else {
-          additiveBuilder_.addMessage(index, builderForValue.build());
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Additives of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Additive additive = 4;</code>
-       */
-      public Builder addAllAdditive(
-          java.lang.Iterable<? extends food.menu.v1.FoodMenu.Additive> values) {
-        if (additiveBuilder_ == null) {
-          ensureAdditiveIsMutable();
-          com.google.protobuf.AbstractMessageLite.Builder.addAll(
-              values, additive_);
-          onChanged();
-        } else {
-          additiveBuilder_.addAllMessages(values);
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Additives of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Additive additive = 4;</code>
-       */
-      public Builder clearAdditive() {
-        if (additiveBuilder_ == null) {
-          additive_ = java.util.Collections.emptyList();
-          bitField0_ = (bitField0_ & ~0x00000008);
-          onChanged();
-        } else {
-          additiveBuilder_.clear();
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Additives of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Additive additive = 4;</code>
-       */
-      public Builder removeAdditive(int index) {
-        if (additiveBuilder_ == null) {
-          ensureAdditiveIsMutable();
-          additive_.remove(index);
-          onChanged();
-        } else {
-          additiveBuilder_.remove(index);
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Additives of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Additive additive = 4;</code>
-       */
-      public food.menu.v1.FoodMenu.Additive.Builder getAdditiveBuilder(
-          int index) {
-        return getAdditiveFieldBuilder().getBuilder(index);
-      }
-      /**
-       * <pre>
-       * Additives of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Additive additive = 4;</code>
-       */
-      public food.menu.v1.FoodMenu.AdditiveOrBuilder getAdditiveOrBuilder(
-          int index) {
-        if (additiveBuilder_ == null) {
-          return additive_.get(index);  } else {
-          return additiveBuilder_.getMessageOrBuilder(index);
-        }
-      }
-      /**
-       * <pre>
-       * Additives of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Additive additive = 4;</code>
-       */
-      public java.util.List<? extends food.menu.v1.FoodMenu.AdditiveOrBuilder> 
-           getAdditiveOrBuilderList() {
-        if (additiveBuilder_ != null) {
-          return additiveBuilder_.getMessageOrBuilderList();
-        } else {
-          return java.util.Collections.unmodifiableList(additive_);
-        }
-      }
-      /**
-       * <pre>
-       * Additives of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Additive additive = 4;</code>
-       */
-      public food.menu.v1.FoodMenu.Additive.Builder addAdditiveBuilder() {
-        return getAdditiveFieldBuilder().addBuilder(
-            food.menu.v1.FoodMenu.Additive.getDefaultInstance());
-      }
-      /**
-       * <pre>
-       * Additives of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Additive additive = 4;</code>
-       */
-      public food.menu.v1.FoodMenu.Additive.Builder addAdditiveBuilder(
-          int index) {
-        return getAdditiveFieldBuilder().addBuilder(
-            index, food.menu.v1.FoodMenu.Additive.getDefaultInstance());
-      }
-      /**
-       * <pre>
-       * Additives of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Additive additive = 4;</code>
-       */
-      public java.util.List<food.menu.v1.FoodMenu.Additive.Builder> 
-           getAdditiveBuilderList() {
-        return getAdditiveFieldBuilder().getBuilderList();
-      }
-      private com.google.protobuf.RepeatedFieldBuilderV3<
-          food.menu.v1.FoodMenu.Additive, food.menu.v1.FoodMenu.Additive.Builder, food.menu.v1.FoodMenu.AdditiveOrBuilder> 
-          getAdditiveFieldBuilder() {
-        if (additiveBuilder_ == null) {
-          additiveBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3<
-              food.menu.v1.FoodMenu.Additive, food.menu.v1.FoodMenu.Additive.Builder, food.menu.v1.FoodMenu.AdditiveOrBuilder>(
-                  additive_,
-                  ((bitField0_ & 0x00000008) != 0),
-                  getParentForChildren(),
-                  isClean());
-          additive_ = null;
-        }
-        return additiveBuilder_;
-      }
-
-      private java.util.List<food.menu.v1.FoodMenu.Allergen> allergen_ =
-        java.util.Collections.emptyList();
-      private void ensureAllergenIsMutable() {
-        if (!((bitField0_ & 0x00000010) != 0)) {
-          allergen_ = new java.util.ArrayList<food.menu.v1.FoodMenu.Allergen>(allergen_);
-          bitField0_ |= 0x00000010;
-         }
-      }
-
-      private com.google.protobuf.RepeatedFieldBuilderV3<
-          food.menu.v1.FoodMenu.Allergen, food.menu.v1.FoodMenu.Allergen.Builder, food.menu.v1.FoodMenu.AllergenOrBuilder> allergenBuilder_;
-
-      /**
-       * <pre>
-       * Allergens of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Allergen allergen = 5;</code>
-       */
-      public java.util.List<food.menu.v1.FoodMenu.Allergen> getAllergenList() {
-        if (allergenBuilder_ == null) {
-          return java.util.Collections.unmodifiableList(allergen_);
-        } else {
-          return allergenBuilder_.getMessageList();
-        }
-      }
-      /**
-       * <pre>
-       * Allergens of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Allergen allergen = 5;</code>
-       */
-      public int getAllergenCount() {
-        if (allergenBuilder_ == null) {
-          return allergen_.size();
-        } else {
-          return allergenBuilder_.getCount();
-        }
-      }
-      /**
-       * <pre>
-       * Allergens of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Allergen allergen = 5;</code>
-       */
-      public food.menu.v1.FoodMenu.Allergen getAllergen(int index) {
-        if (allergenBuilder_ == null) {
-          return allergen_.get(index);
-        } else {
-          return allergenBuilder_.getMessage(index);
-        }
-      }
-      /**
-       * <pre>
-       * Allergens of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Allergen allergen = 5;</code>
-       */
-      public Builder setAllergen(
-          int index, food.menu.v1.FoodMenu.Allergen value) {
-        if (allergenBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          ensureAllergenIsMutable();
-          allergen_.set(index, value);
-          onChanged();
-        } else {
-          allergenBuilder_.setMessage(index, value);
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Allergens of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Allergen allergen = 5;</code>
-       */
-      public Builder setAllergen(
-          int index, food.menu.v1.FoodMenu.Allergen.Builder builderForValue) {
-        if (allergenBuilder_ == null) {
-          ensureAllergenIsMutable();
-          allergen_.set(index, builderForValue.build());
-          onChanged();
-        } else {
-          allergenBuilder_.setMessage(index, builderForValue.build());
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Allergens of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Allergen allergen = 5;</code>
-       */
-      public Builder addAllergen(food.menu.v1.FoodMenu.Allergen value) {
-        if (allergenBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          ensureAllergenIsMutable();
-          allergen_.add(value);
-          onChanged();
-        } else {
-          allergenBuilder_.addMessage(value);
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Allergens of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Allergen allergen = 5;</code>
-       */
-      public Builder addAllergen(
-          int index, food.menu.v1.FoodMenu.Allergen value) {
-        if (allergenBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          ensureAllergenIsMutable();
-          allergen_.add(index, value);
-          onChanged();
-        } else {
-          allergenBuilder_.addMessage(index, value);
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Allergens of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Allergen allergen = 5;</code>
-       */
-      public Builder addAllergen(
-          food.menu.v1.FoodMenu.Allergen.Builder builderForValue) {
-        if (allergenBuilder_ == null) {
-          ensureAllergenIsMutable();
-          allergen_.add(builderForValue.build());
-          onChanged();
-        } else {
-          allergenBuilder_.addMessage(builderForValue.build());
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Allergens of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Allergen allergen = 5;</code>
-       */
-      public Builder addAllergen(
-          int index, food.menu.v1.FoodMenu.Allergen.Builder builderForValue) {
-        if (allergenBuilder_ == null) {
-          ensureAllergenIsMutable();
-          allergen_.add(index, builderForValue.build());
-          onChanged();
-        } else {
-          allergenBuilder_.addMessage(index, builderForValue.build());
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Allergens of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Allergen allergen = 5;</code>
-       */
-      public Builder addAllAllergen(
-          java.lang.Iterable<? extends food.menu.v1.FoodMenu.Allergen> values) {
-        if (allergenBuilder_ == null) {
-          ensureAllergenIsMutable();
-          com.google.protobuf.AbstractMessageLite.Builder.addAll(
-              values, allergen_);
-          onChanged();
-        } else {
-          allergenBuilder_.addAllMessages(values);
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Allergens of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Allergen allergen = 5;</code>
-       */
-      public Builder clearAllergen() {
-        if (allergenBuilder_ == null) {
-          allergen_ = java.util.Collections.emptyList();
-          bitField0_ = (bitField0_ & ~0x00000010);
-          onChanged();
-        } else {
-          allergenBuilder_.clear();
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Allergens of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Allergen allergen = 5;</code>
-       */
-      public Builder removeAllergen(int index) {
-        if (allergenBuilder_ == null) {
-          ensureAllergenIsMutable();
-          allergen_.remove(index);
-          onChanged();
-        } else {
-          allergenBuilder_.remove(index);
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Allergens of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Allergen allergen = 5;</code>
-       */
-      public food.menu.v1.FoodMenu.Allergen.Builder getAllergenBuilder(
-          int index) {
-        return getAllergenFieldBuilder().getBuilder(index);
-      }
-      /**
-       * <pre>
-       * Allergens of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Allergen allergen = 5;</code>
-       */
-      public food.menu.v1.FoodMenu.AllergenOrBuilder getAllergenOrBuilder(
-          int index) {
-        if (allergenBuilder_ == null) {
-          return allergen_.get(index);  } else {
-          return allergenBuilder_.getMessageOrBuilder(index);
-        }
-      }
-      /**
-       * <pre>
-       * Allergens of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Allergen allergen = 5;</code>
-       */
-      public java.util.List<? extends food.menu.v1.FoodMenu.AllergenOrBuilder> 
-           getAllergenOrBuilderList() {
-        if (allergenBuilder_ != null) {
-          return allergenBuilder_.getMessageOrBuilderList();
-        } else {
-          return java.util.Collections.unmodifiableList(allergen_);
-        }
-      }
-      /**
-       * <pre>
-       * Allergens of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Allergen allergen = 5;</code>
-       */
-      public food.menu.v1.FoodMenu.Allergen.Builder addAllergenBuilder() {
-        return getAllergenFieldBuilder().addBuilder(
-            food.menu.v1.FoodMenu.Allergen.getDefaultInstance());
-      }
-      /**
-       * <pre>
-       * Allergens of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Allergen allergen = 5;</code>
-       */
-      public food.menu.v1.FoodMenu.Allergen.Builder addAllergenBuilder(
-          int index) {
-        return getAllergenFieldBuilder().addBuilder(
-            index, food.menu.v1.FoodMenu.Allergen.getDefaultInstance());
-      }
-      /**
-       * <pre>
-       * Allergens of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Allergen allergen = 5;</code>
-       */
-      public java.util.List<food.menu.v1.FoodMenu.Allergen.Builder> 
-           getAllergenBuilderList() {
-        return getAllergenFieldBuilder().getBuilderList();
-      }
-      private com.google.protobuf.RepeatedFieldBuilderV3<
-          food.menu.v1.FoodMenu.Allergen, food.menu.v1.FoodMenu.Allergen.Builder, food.menu.v1.FoodMenu.AllergenOrBuilder> 
-          getAllergenFieldBuilder() {
-        if (allergenBuilder_ == null) {
-          allergenBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3<
-              food.menu.v1.FoodMenu.Allergen, food.menu.v1.FoodMenu.Allergen.Builder, food.menu.v1.FoodMenu.AllergenOrBuilder>(
-                  allergen_,
-                  ((bitField0_ & 0x00000010) != 0),
-                  getParentForChildren(),
-                  isClean());
-          allergen_ = null;
-        }
-        return allergenBuilder_;
-      }
-
-      private food.menu.v1.FoodMenu.DepositInfo packagingDepositInfo_;
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.DepositInfo, food.menu.v1.FoodMenu.DepositInfo.Builder, food.menu.v1.FoodMenu.DepositInfoOrBuilder> packagingDepositInfoBuilder_;
-      /**
-       * <pre>
-       * Packaging and recycling information of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.DepositInfo packaging_deposit_info = 6;</code>
-       * @return Whether the packagingDepositInfo field is set.
-       */
-      public boolean hasPackagingDepositInfo() {
-        return ((bitField0_ & 0x00000020) != 0);
-      }
-      /**
-       * <pre>
-       * Packaging and recycling information of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.DepositInfo packaging_deposit_info = 6;</code>
-       * @return The packagingDepositInfo.
-       */
-      public food.menu.v1.FoodMenu.DepositInfo getPackagingDepositInfo() {
-        if (packagingDepositInfoBuilder_ == null) {
-          return packagingDepositInfo_ == null ? food.menu.v1.FoodMenu.DepositInfo.getDefaultInstance() : packagingDepositInfo_;
-        } else {
-          return packagingDepositInfoBuilder_.getMessage();
-        }
-      }
-      /**
-       * <pre>
-       * Packaging and recycling information of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.DepositInfo packaging_deposit_info = 6;</code>
-       */
-      public Builder setPackagingDepositInfo(food.menu.v1.FoodMenu.DepositInfo value) {
-        if (packagingDepositInfoBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          packagingDepositInfo_ = value;
-        } else {
-          packagingDepositInfoBuilder_.setMessage(value);
-        }
-        bitField0_ |= 0x00000020;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Packaging and recycling information of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.DepositInfo packaging_deposit_info = 6;</code>
-       */
-      public Builder setPackagingDepositInfo(
-          food.menu.v1.FoodMenu.DepositInfo.Builder builderForValue) {
-        if (packagingDepositInfoBuilder_ == null) {
-          packagingDepositInfo_ = builderForValue.build();
-        } else {
-          packagingDepositInfoBuilder_.setMessage(builderForValue.build());
-        }
-        bitField0_ |= 0x00000020;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Packaging and recycling information of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.DepositInfo packaging_deposit_info = 6;</code>
-       */
-      public Builder mergePackagingDepositInfo(food.menu.v1.FoodMenu.DepositInfo value) {
-        if (packagingDepositInfoBuilder_ == null) {
-          if (((bitField0_ & 0x00000020) != 0) &&
-            packagingDepositInfo_ != null &&
-            packagingDepositInfo_ != food.menu.v1.FoodMenu.DepositInfo.getDefaultInstance()) {
-            getPackagingDepositInfoBuilder().mergeFrom(value);
-          } else {
-            packagingDepositInfo_ = value;
-          }
-        } else {
-          packagingDepositInfoBuilder_.mergeFrom(value);
-        }
-        bitField0_ |= 0x00000020;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Packaging and recycling information of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.DepositInfo packaging_deposit_info = 6;</code>
-       */
-      public Builder clearPackagingDepositInfo() {
-        bitField0_ = (bitField0_ & ~0x00000020);
-        packagingDepositInfo_ = null;
-        if (packagingDepositInfoBuilder_ != null) {
-          packagingDepositInfoBuilder_.dispose();
-          packagingDepositInfoBuilder_ = null;
-        }
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Packaging and recycling information of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.DepositInfo packaging_deposit_info = 6;</code>
-       */
-      public food.menu.v1.FoodMenu.DepositInfo.Builder getPackagingDepositInfoBuilder() {
-        bitField0_ |= 0x00000020;
-        onChanged();
-        return getPackagingDepositInfoFieldBuilder().getBuilder();
-      }
-      /**
-       * <pre>
-       * Packaging and recycling information of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.DepositInfo packaging_deposit_info = 6;</code>
-       */
-      public food.menu.v1.FoodMenu.DepositInfoOrBuilder getPackagingDepositInfoOrBuilder() {
-        if (packagingDepositInfoBuilder_ != null) {
-          return packagingDepositInfoBuilder_.getMessageOrBuilder();
-        } else {
-          return packagingDepositInfo_ == null ?
-              food.menu.v1.FoodMenu.DepositInfo.getDefaultInstance() : packagingDepositInfo_;
-        }
-      }
-      /**
-       * <pre>
-       * Packaging and recycling information of this menu item.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.DepositInfo packaging_deposit_info = 6;</code>
-       */
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.DepositInfo, food.menu.v1.FoodMenu.DepositInfo.Builder, food.menu.v1.FoodMenu.DepositInfoOrBuilder> 
-          getPackagingDepositInfoFieldBuilder() {
-        if (packagingDepositInfoBuilder_ == null) {
-          packagingDepositInfoBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
-              food.menu.v1.FoodMenu.DepositInfo, food.menu.v1.FoodMenu.DepositInfo.Builder, food.menu.v1.FoodMenu.DepositInfoOrBuilder>(
-                  getPackagingDepositInfo(),
-                  getParentForChildren(),
-                  isClean());
-          packagingDepositInfo_ = null;
-        }
-        return packagingDepositInfoBuilder_;
-      }
-      @java.lang.Override
-      public final Builder setUnknownFields(
-          final com.google.protobuf.UnknownFieldSet unknownFields) {
-        return super.setUnknownFields(unknownFields);
-      }
-
-      @java.lang.Override
-      public final Builder mergeUnknownFields(
-          final com.google.protobuf.UnknownFieldSet unknownFields) {
-        return super.mergeUnknownFields(unknownFields);
-      }
-
-
-      // @@protoc_insertion_point(builder_scope:food.menu.v1.MenuItemAttributes)
-    }
-
-    // @@protoc_insertion_point(class_scope:food.menu.v1.MenuItemAttributes)
-    private static final food.menu.v1.FoodMenu.MenuItemAttributes DEFAULT_INSTANCE;
-    static {
-      DEFAULT_INSTANCE = new food.menu.v1.FoodMenu.MenuItemAttributes();
-    }
-
-    public static food.menu.v1.FoodMenu.MenuItemAttributes getDefaultInstance() {
-      return DEFAULT_INSTANCE;
-    }
-
-    private static final com.google.protobuf.Parser<MenuItemAttributes>
-        PARSER = new com.google.protobuf.AbstractParser<MenuItemAttributes>() {
-      @java.lang.Override
-      public MenuItemAttributes parsePartialFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws com.google.protobuf.InvalidProtocolBufferException {
-        Builder builder = newBuilder();
-        try {
-          builder.mergeFrom(input, extensionRegistry);
-        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          throw e.setUnfinishedMessage(builder.buildPartial());
-        } catch (com.google.protobuf.UninitializedMessageException e) {
-          throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
-        } catch (java.io.IOException e) {
-          throw new com.google.protobuf.InvalidProtocolBufferException(e)
-              .setUnfinishedMessage(builder.buildPartial());
-        }
-        return builder.buildPartial();
-      }
-    };
-
-    public static com.google.protobuf.Parser<MenuItemAttributes> parser() {
-      return PARSER;
-    }
-
-    @java.lang.Override
-    public com.google.protobuf.Parser<MenuItemAttributes> getParserForType() {
-      return PARSER;
-    }
-
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.MenuItemAttributes getDefaultInstanceForType() {
-      return DEFAULT_INSTANCE;
-    }
-
-  }
-
-  public interface OfferSetOrBuilder extends
-      // @@protoc_insertion_point(interface_extends:food.menu.v1.OfferSet)
-      com.google.protobuf.MessageOrBuilder {
-
-    /**
-     * <pre>
-     * List of possible offers.
-     * Required.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Offer offers = 1;</code>
-     */
-    java.util.List<food.menu.v1.FoodMenu.Offer> 
-        getOffersList();
-    /**
-     * <pre>
-     * List of possible offers.
-     * Required.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Offer offers = 1;</code>
-     */
-    food.menu.v1.FoodMenu.Offer getOffers(int index);
-    /**
-     * <pre>
-     * List of possible offers.
-     * Required.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Offer offers = 1;</code>
-     */
-    int getOffersCount();
-    /**
-     * <pre>
-     * List of possible offers.
-     * Required.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Offer offers = 1;</code>
-     */
-    java.util.List<? extends food.menu.v1.FoodMenu.OfferOrBuilder> 
-        getOffersOrBuilderList();
-    /**
-     * <pre>
-     * List of possible offers.
-     * Required.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Offer offers = 1;</code>
-     */
-    food.menu.v1.FoodMenu.OfferOrBuilder getOffersOrBuilder(
-        int index);
-  }
-  /**
-   * <pre>
-   * Container for a list of offers available on a menu item / option.
-   * Only one offer should be applicable/valid at one particular time.
-   * For example, a drink can have 2 offers where one is applicable in the morning
-   * while the other is applicable in the evening during happy hours.
-   * </pre>
-   *
-   * Protobuf type {@code food.menu.v1.OfferSet}
-   */
-  public static final class OfferSet extends
-      com.google.protobuf.GeneratedMessageV3 implements
-      // @@protoc_insertion_point(message_implements:food.menu.v1.OfferSet)
-      OfferSetOrBuilder {
-  private static final long serialVersionUID = 0L;
-    // Use OfferSet.newBuilder() to construct.
-    private OfferSet(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
-      super(builder);
-    }
-    private OfferSet() {
-      offers_ = java.util.Collections.emptyList();
-    }
-
-    @java.lang.Override
-    @SuppressWarnings({"unused"})
-    protected java.lang.Object newInstance(
-        UnusedPrivateParameter unused) {
-      return new OfferSet();
-    }
-
-    public static final com.google.protobuf.Descriptors.Descriptor
-        getDescriptor() {
-      return food.menu.v1.FoodMenu.internal_static_food_menu_v1_OfferSet_descriptor;
-    }
-
-    @java.lang.Override
-    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-        internalGetFieldAccessorTable() {
-      return food.menu.v1.FoodMenu.internal_static_food_menu_v1_OfferSet_fieldAccessorTable
-          .ensureFieldAccessorsInitialized(
-              food.menu.v1.FoodMenu.OfferSet.class, food.menu.v1.FoodMenu.OfferSet.Builder.class);
-    }
-
-    public static final int OFFERS_FIELD_NUMBER = 1;
-    @SuppressWarnings("serial")
-    private java.util.List<food.menu.v1.FoodMenu.Offer> offers_;
-    /**
-     * <pre>
-     * List of possible offers.
-     * Required.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Offer offers = 1;</code>
-     */
-    @java.lang.Override
-    public java.util.List<food.menu.v1.FoodMenu.Offer> getOffersList() {
-      return offers_;
-    }
-    /**
-     * <pre>
-     * List of possible offers.
-     * Required.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Offer offers = 1;</code>
-     */
-    @java.lang.Override
-    public java.util.List<? extends food.menu.v1.FoodMenu.OfferOrBuilder> 
-        getOffersOrBuilderList() {
-      return offers_;
-    }
-    /**
-     * <pre>
-     * List of possible offers.
-     * Required.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Offer offers = 1;</code>
-     */
-    @java.lang.Override
-    public int getOffersCount() {
-      return offers_.size();
-    }
-    /**
-     * <pre>
-     * List of possible offers.
-     * Required.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Offer offers = 1;</code>
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.Offer getOffers(int index) {
-      return offers_.get(index);
-    }
-    /**
-     * <pre>
-     * List of possible offers.
-     * Required.
-     * </pre>
-     *
-     * <code>repeated .food.menu.v1.Offer offers = 1;</code>
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.OfferOrBuilder getOffersOrBuilder(
-        int index) {
-      return offers_.get(index);
-    }
-
-    private byte memoizedIsInitialized = -1;
-    @java.lang.Override
-    public final boolean isInitialized() {
-      byte isInitialized = memoizedIsInitialized;
-      if (isInitialized == 1) return true;
-      if (isInitialized == 0) return false;
-
-      memoizedIsInitialized = 1;
-      return true;
-    }
-
-    @java.lang.Override
-    public void writeTo(com.google.protobuf.CodedOutputStream output)
-                        throws java.io.IOException {
-      for (int i = 0; i < offers_.size(); i++) {
-        output.writeMessage(1, offers_.get(i));
-      }
-      getUnknownFields().writeTo(output);
-    }
-
-    @java.lang.Override
-    public int getSerializedSize() {
-      int size = memoizedSize;
-      if (size != -1) return size;
-
-      size = 0;
-      for (int i = 0; i < offers_.size(); i++) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(1, offers_.get(i));
-      }
-      size += getUnknownFields().getSerializedSize();
-      memoizedSize = size;
-      return size;
-    }
-
-    @java.lang.Override
-    public boolean equals(final java.lang.Object obj) {
-      if (obj == this) {
-       return true;
-      }
-      if (!(obj instanceof food.menu.v1.FoodMenu.OfferSet)) {
-        return super.equals(obj);
-      }
-      food.menu.v1.FoodMenu.OfferSet other = (food.menu.v1.FoodMenu.OfferSet) obj;
-
-      if (!getOffersList()
-          .equals(other.getOffersList())) return false;
-      if (!getUnknownFields().equals(other.getUnknownFields())) return false;
-      return true;
-    }
-
-    @java.lang.Override
-    public int hashCode() {
-      if (memoizedHashCode != 0) {
-        return memoizedHashCode;
-      }
-      int hash = 41;
-      hash = (19 * hash) + getDescriptor().hashCode();
-      if (getOffersCount() > 0) {
-        hash = (37 * hash) + OFFERS_FIELD_NUMBER;
-        hash = (53 * hash) + getOffersList().hashCode();
-      }
-      hash = (29 * hash) + getUnknownFields().hashCode();
-      memoizedHashCode = hash;
-      return hash;
-    }
-
-    public static food.menu.v1.FoodMenu.OfferSet parseFrom(
-        java.nio.ByteBuffer data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.OfferSet parseFrom(
-        java.nio.ByteBuffer data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.OfferSet parseFrom(
-        com.google.protobuf.ByteString data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.OfferSet parseFrom(
-        com.google.protobuf.ByteString data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.OfferSet parseFrom(byte[] data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.OfferSet parseFrom(
-        byte[] data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.OfferSet parseFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.OfferSet parseFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.OfferSet parseDelimitedFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseDelimitedWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.OfferSet parseDelimitedFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.OfferSet parseFrom(
-        com.google.protobuf.CodedInputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.OfferSet parseFrom(
-        com.google.protobuf.CodedInputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input, extensionRegistry);
-    }
-
-    @java.lang.Override
-    public Builder newBuilderForType() { return newBuilder(); }
-    public static Builder newBuilder() {
-      return DEFAULT_INSTANCE.toBuilder();
-    }
-    public static Builder newBuilder(food.menu.v1.FoodMenu.OfferSet prototype) {
-      return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
-    }
-    @java.lang.Override
-    public Builder toBuilder() {
-      return this == DEFAULT_INSTANCE
-          ? new Builder() : new Builder().mergeFrom(this);
-    }
-
-    @java.lang.Override
-    protected Builder newBuilderForType(
-        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-      Builder builder = new Builder(parent);
-      return builder;
-    }
-    /**
-     * <pre>
-     * Container for a list of offers available on a menu item / option.
-     * Only one offer should be applicable/valid at one particular time.
-     * For example, a drink can have 2 offers where one is applicable in the morning
-     * while the other is applicable in the evening during happy hours.
-     * </pre>
-     *
-     * Protobuf type {@code food.menu.v1.OfferSet}
-     */
-    public static final class Builder extends
-        com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
-        // @@protoc_insertion_point(builder_implements:food.menu.v1.OfferSet)
-        food.menu.v1.FoodMenu.OfferSetOrBuilder {
-      public static final com.google.protobuf.Descriptors.Descriptor
-          getDescriptor() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_OfferSet_descriptor;
-      }
-
-      @java.lang.Override
-      protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-          internalGetFieldAccessorTable() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_OfferSet_fieldAccessorTable
-            .ensureFieldAccessorsInitialized(
-                food.menu.v1.FoodMenu.OfferSet.class, food.menu.v1.FoodMenu.OfferSet.Builder.class);
-      }
-
-      // Construct using food.menu.v1.FoodMenu.OfferSet.newBuilder()
-      private Builder() {
-
-      }
-
-      private Builder(
-          com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-        super(parent);
-
-      }
-      @java.lang.Override
-      public Builder clear() {
-        super.clear();
-        bitField0_ = 0;
-        if (offersBuilder_ == null) {
-          offers_ = java.util.Collections.emptyList();
-        } else {
-          offers_ = null;
-          offersBuilder_.clear();
-        }
-        bitField0_ = (bitField0_ & ~0x00000001);
-        return this;
-      }
-
-      @java.lang.Override
-      public com.google.protobuf.Descriptors.Descriptor
-          getDescriptorForType() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_OfferSet_descriptor;
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.OfferSet getDefaultInstanceForType() {
-        return food.menu.v1.FoodMenu.OfferSet.getDefaultInstance();
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.OfferSet build() {
-        food.menu.v1.FoodMenu.OfferSet result = buildPartial();
-        if (!result.isInitialized()) {
-          throw newUninitializedMessageException(result);
-        }
-        return result;
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.OfferSet buildPartial() {
-        food.menu.v1.FoodMenu.OfferSet result = new food.menu.v1.FoodMenu.OfferSet(this);
-        buildPartialRepeatedFields(result);
-        if (bitField0_ != 0) { buildPartial0(result); }
-        onBuilt();
-        return result;
-      }
-
-      private void buildPartialRepeatedFields(food.menu.v1.FoodMenu.OfferSet result) {
-        if (offersBuilder_ == null) {
-          if (((bitField0_ & 0x00000001) != 0)) {
-            offers_ = java.util.Collections.unmodifiableList(offers_);
-            bitField0_ = (bitField0_ & ~0x00000001);
-          }
-          result.offers_ = offers_;
-        } else {
-          result.offers_ = offersBuilder_.build();
-        }
-      }
-
-      private void buildPartial0(food.menu.v1.FoodMenu.OfferSet result) {
-        int from_bitField0_ = bitField0_;
-      }
-
-      @java.lang.Override
-      public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof food.menu.v1.FoodMenu.OfferSet) {
-          return mergeFrom((food.menu.v1.FoodMenu.OfferSet)other);
-        } else {
-          super.mergeFrom(other);
-          return this;
-        }
-      }
-
-      public Builder mergeFrom(food.menu.v1.FoodMenu.OfferSet other) {
-        if (other == food.menu.v1.FoodMenu.OfferSet.getDefaultInstance()) return this;
-        if (offersBuilder_ == null) {
-          if (!other.offers_.isEmpty()) {
-            if (offers_.isEmpty()) {
-              offers_ = other.offers_;
-              bitField0_ = (bitField0_ & ~0x00000001);
-            } else {
-              ensureOffersIsMutable();
-              offers_.addAll(other.offers_);
-            }
-            onChanged();
-          }
-        } else {
-          if (!other.offers_.isEmpty()) {
-            if (offersBuilder_.isEmpty()) {
-              offersBuilder_.dispose();
-              offersBuilder_ = null;
-              offers_ = other.offers_;
-              bitField0_ = (bitField0_ & ~0x00000001);
-              offersBuilder_ = 
-                com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ?
-                   getOffersFieldBuilder() : null;
-            } else {
-              offersBuilder_.addAllMessages(other.offers_);
-            }
-          }
-        }
-        this.mergeUnknownFields(other.getUnknownFields());
-        onChanged();
-        return this;
-      }
-
-      @java.lang.Override
-      public final boolean isInitialized() {
-        return true;
-      }
-
-      @java.lang.Override
-      public Builder mergeFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws java.io.IOException {
-        if (extensionRegistry == null) {
-          throw new java.lang.NullPointerException();
-        }
-        try {
-          boolean done = false;
-          while (!done) {
-            int tag = input.readTag();
-            switch (tag) {
-              case 0:
-                done = true;
-                break;
-              case 10: {
-                food.menu.v1.FoodMenu.Offer m =
-                    input.readMessage(
-                        food.menu.v1.FoodMenu.Offer.parser(),
-                        extensionRegistry);
-                if (offersBuilder_ == null) {
-                  ensureOffersIsMutable();
-                  offers_.add(m);
-                } else {
-                  offersBuilder_.addMessage(m);
-                }
-                break;
-              } // case 10
-              default: {
-                if (!super.parseUnknownField(input, extensionRegistry, tag)) {
-                  done = true; // was an endgroup tag
-                }
-                break;
-              } // default:
-            } // switch (tag)
-          } // while (!done)
-        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          throw e.unwrapIOException();
-        } finally {
-          onChanged();
-        } // finally
-        return this;
-      }
-      private int bitField0_;
-
-      private java.util.List<food.menu.v1.FoodMenu.Offer> offers_ =
-        java.util.Collections.emptyList();
-      private void ensureOffersIsMutable() {
-        if (!((bitField0_ & 0x00000001) != 0)) {
-          offers_ = new java.util.ArrayList<food.menu.v1.FoodMenu.Offer>(offers_);
-          bitField0_ |= 0x00000001;
-         }
-      }
-
-      private com.google.protobuf.RepeatedFieldBuilderV3<
-          food.menu.v1.FoodMenu.Offer, food.menu.v1.FoodMenu.Offer.Builder, food.menu.v1.FoodMenu.OfferOrBuilder> offersBuilder_;
-
-      /**
-       * <pre>
-       * List of possible offers.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Offer offers = 1;</code>
-       */
-      public java.util.List<food.menu.v1.FoodMenu.Offer> getOffersList() {
-        if (offersBuilder_ == null) {
-          return java.util.Collections.unmodifiableList(offers_);
-        } else {
-          return offersBuilder_.getMessageList();
-        }
-      }
-      /**
-       * <pre>
-       * List of possible offers.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Offer offers = 1;</code>
-       */
-      public int getOffersCount() {
-        if (offersBuilder_ == null) {
-          return offers_.size();
-        } else {
-          return offersBuilder_.getCount();
-        }
-      }
-      /**
-       * <pre>
-       * List of possible offers.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Offer offers = 1;</code>
-       */
-      public food.menu.v1.FoodMenu.Offer getOffers(int index) {
-        if (offersBuilder_ == null) {
-          return offers_.get(index);
-        } else {
-          return offersBuilder_.getMessage(index);
-        }
-      }
-      /**
-       * <pre>
-       * List of possible offers.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Offer offers = 1;</code>
-       */
-      public Builder setOffers(
-          int index, food.menu.v1.FoodMenu.Offer value) {
-        if (offersBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          ensureOffersIsMutable();
-          offers_.set(index, value);
-          onChanged();
-        } else {
-          offersBuilder_.setMessage(index, value);
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * List of possible offers.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Offer offers = 1;</code>
-       */
-      public Builder setOffers(
-          int index, food.menu.v1.FoodMenu.Offer.Builder builderForValue) {
-        if (offersBuilder_ == null) {
-          ensureOffersIsMutable();
-          offers_.set(index, builderForValue.build());
-          onChanged();
-        } else {
-          offersBuilder_.setMessage(index, builderForValue.build());
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * List of possible offers.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Offer offers = 1;</code>
-       */
-      public Builder addOffers(food.menu.v1.FoodMenu.Offer value) {
-        if (offersBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          ensureOffersIsMutable();
-          offers_.add(value);
-          onChanged();
-        } else {
-          offersBuilder_.addMessage(value);
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * List of possible offers.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Offer offers = 1;</code>
-       */
-      public Builder addOffers(
-          int index, food.menu.v1.FoodMenu.Offer value) {
-        if (offersBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          ensureOffersIsMutable();
-          offers_.add(index, value);
-          onChanged();
-        } else {
-          offersBuilder_.addMessage(index, value);
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * List of possible offers.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Offer offers = 1;</code>
-       */
-      public Builder addOffers(
-          food.menu.v1.FoodMenu.Offer.Builder builderForValue) {
-        if (offersBuilder_ == null) {
-          ensureOffersIsMutable();
-          offers_.add(builderForValue.build());
-          onChanged();
-        } else {
-          offersBuilder_.addMessage(builderForValue.build());
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * List of possible offers.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Offer offers = 1;</code>
-       */
-      public Builder addOffers(
-          int index, food.menu.v1.FoodMenu.Offer.Builder builderForValue) {
-        if (offersBuilder_ == null) {
-          ensureOffersIsMutable();
-          offers_.add(index, builderForValue.build());
-          onChanged();
-        } else {
-          offersBuilder_.addMessage(index, builderForValue.build());
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * List of possible offers.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Offer offers = 1;</code>
-       */
-      public Builder addAllOffers(
-          java.lang.Iterable<? extends food.menu.v1.FoodMenu.Offer> values) {
-        if (offersBuilder_ == null) {
-          ensureOffersIsMutable();
-          com.google.protobuf.AbstractMessageLite.Builder.addAll(
-              values, offers_);
-          onChanged();
-        } else {
-          offersBuilder_.addAllMessages(values);
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * List of possible offers.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Offer offers = 1;</code>
-       */
-      public Builder clearOffers() {
-        if (offersBuilder_ == null) {
-          offers_ = java.util.Collections.emptyList();
-          bitField0_ = (bitField0_ & ~0x00000001);
-          onChanged();
-        } else {
-          offersBuilder_.clear();
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * List of possible offers.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Offer offers = 1;</code>
-       */
-      public Builder removeOffers(int index) {
-        if (offersBuilder_ == null) {
-          ensureOffersIsMutable();
-          offers_.remove(index);
-          onChanged();
-        } else {
-          offersBuilder_.remove(index);
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * List of possible offers.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Offer offers = 1;</code>
-       */
-      public food.menu.v1.FoodMenu.Offer.Builder getOffersBuilder(
-          int index) {
-        return getOffersFieldBuilder().getBuilder(index);
-      }
-      /**
-       * <pre>
-       * List of possible offers.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Offer offers = 1;</code>
-       */
-      public food.menu.v1.FoodMenu.OfferOrBuilder getOffersOrBuilder(
-          int index) {
-        if (offersBuilder_ == null) {
-          return offers_.get(index);  } else {
-          return offersBuilder_.getMessageOrBuilder(index);
-        }
-      }
-      /**
-       * <pre>
-       * List of possible offers.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Offer offers = 1;</code>
-       */
-      public java.util.List<? extends food.menu.v1.FoodMenu.OfferOrBuilder> 
-           getOffersOrBuilderList() {
-        if (offersBuilder_ != null) {
-          return offersBuilder_.getMessageOrBuilderList();
-        } else {
-          return java.util.Collections.unmodifiableList(offers_);
-        }
-      }
-      /**
-       * <pre>
-       * List of possible offers.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Offer offers = 1;</code>
-       */
-      public food.menu.v1.FoodMenu.Offer.Builder addOffersBuilder() {
-        return getOffersFieldBuilder().addBuilder(
-            food.menu.v1.FoodMenu.Offer.getDefaultInstance());
-      }
-      /**
-       * <pre>
-       * List of possible offers.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Offer offers = 1;</code>
-       */
-      public food.menu.v1.FoodMenu.Offer.Builder addOffersBuilder(
-          int index) {
-        return getOffersFieldBuilder().addBuilder(
-            index, food.menu.v1.FoodMenu.Offer.getDefaultInstance());
-      }
-      /**
-       * <pre>
-       * List of possible offers.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated .food.menu.v1.Offer offers = 1;</code>
-       */
-      public java.util.List<food.menu.v1.FoodMenu.Offer.Builder> 
-           getOffersBuilderList() {
-        return getOffersFieldBuilder().getBuilderList();
-      }
-      private com.google.protobuf.RepeatedFieldBuilderV3<
-          food.menu.v1.FoodMenu.Offer, food.menu.v1.FoodMenu.Offer.Builder, food.menu.v1.FoodMenu.OfferOrBuilder> 
-          getOffersFieldBuilder() {
-        if (offersBuilder_ == null) {
-          offersBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3<
-              food.menu.v1.FoodMenu.Offer, food.menu.v1.FoodMenu.Offer.Builder, food.menu.v1.FoodMenu.OfferOrBuilder>(
-                  offers_,
-                  ((bitField0_ & 0x00000001) != 0),
-                  getParentForChildren(),
-                  isClean());
-          offers_ = null;
-        }
-        return offersBuilder_;
-      }
-      @java.lang.Override
-      public final Builder setUnknownFields(
-          final com.google.protobuf.UnknownFieldSet unknownFields) {
-        return super.setUnknownFields(unknownFields);
-      }
-
-      @java.lang.Override
-      public final Builder mergeUnknownFields(
-          final com.google.protobuf.UnknownFieldSet unknownFields) {
-        return super.mergeUnknownFields(unknownFields);
-      }
-
-
-      // @@protoc_insertion_point(builder_scope:food.menu.v1.OfferSet)
-    }
-
-    // @@protoc_insertion_point(class_scope:food.menu.v1.OfferSet)
-    private static final food.menu.v1.FoodMenu.OfferSet DEFAULT_INSTANCE;
-    static {
-      DEFAULT_INSTANCE = new food.menu.v1.FoodMenu.OfferSet();
-    }
-
-    public static food.menu.v1.FoodMenu.OfferSet getDefaultInstance() {
-      return DEFAULT_INSTANCE;
-    }
-
-    private static final com.google.protobuf.Parser<OfferSet>
-        PARSER = new com.google.protobuf.AbstractParser<OfferSet>() {
-      @java.lang.Override
-      public OfferSet parsePartialFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws com.google.protobuf.InvalidProtocolBufferException {
-        Builder builder = newBuilder();
-        try {
-          builder.mergeFrom(input, extensionRegistry);
-        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          throw e.setUnfinishedMessage(builder.buildPartial());
-        } catch (com.google.protobuf.UninitializedMessageException e) {
-          throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
-        } catch (java.io.IOException e) {
-          throw new com.google.protobuf.InvalidProtocolBufferException(e)
-              .setUnfinishedMessage(builder.buildPartial());
-        }
-        return builder.buildPartial();
-      }
-    };
-
-    public static com.google.protobuf.Parser<OfferSet> parser() {
-      return PARSER;
-    }
-
-    @java.lang.Override
-    public com.google.protobuf.Parser<OfferSet> getParserForType() {
-      return PARSER;
-    }
-
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.OfferSet getDefaultInstanceForType() {
-      return DEFAULT_INSTANCE;
-    }
-
-  }
-
-  public interface OfferOrBuilder extends
-      // @@protoc_insertion_point(interface_extends:food.menu.v1.Offer)
-      com.google.protobuf.MessageOrBuilder {
-
-    /**
-     * <pre>
-     * Monetary value of the menu item/option on sale. Can be 0 to represent free.
-     * Required.
-     * </pre>
-     *
-     * <code>.google.type.Money price = 1;</code>
-     * @return Whether the price field is set.
-     */
-    boolean hasPrice();
-    /**
-     * <pre>
-     * Monetary value of the menu item/option on sale. Can be 0 to represent free.
-     * Required.
-     * </pre>
-     *
-     * <code>.google.type.Money price = 1;</code>
-     * @return The price.
-     */
-    com.google.type.Money getPrice();
-    /**
-     * <pre>
-     * Monetary value of the menu item/option on sale. Can be 0 to represent free.
-     * Required.
-     * </pre>
-     *
-     * <code>.google.type.Money price = 1;</code>
-     */
-    com.google.type.MoneyOrBuilder getPriceOrBuilder();
-  }
-  /**
-   * <pre>
-   * Represents pricing and availability information for MenuItems and
-   * MenuItemOptions.
-   * </pre>
-   *
-   * Protobuf type {@code food.menu.v1.Offer}
-   */
-  public static final class Offer extends
-      com.google.protobuf.GeneratedMessageV3 implements
-      // @@protoc_insertion_point(message_implements:food.menu.v1.Offer)
-      OfferOrBuilder {
-  private static final long serialVersionUID = 0L;
-    // Use Offer.newBuilder() to construct.
-    private Offer(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
-      super(builder);
-    }
-    private Offer() {
-    }
-
-    @java.lang.Override
-    @SuppressWarnings({"unused"})
-    protected java.lang.Object newInstance(
-        UnusedPrivateParameter unused) {
-      return new Offer();
-    }
-
-    public static final com.google.protobuf.Descriptors.Descriptor
-        getDescriptor() {
-      return food.menu.v1.FoodMenu.internal_static_food_menu_v1_Offer_descriptor;
-    }
-
-    @java.lang.Override
-    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-        internalGetFieldAccessorTable() {
-      return food.menu.v1.FoodMenu.internal_static_food_menu_v1_Offer_fieldAccessorTable
-          .ensureFieldAccessorsInitialized(
-              food.menu.v1.FoodMenu.Offer.class, food.menu.v1.FoodMenu.Offer.Builder.class);
-    }
-
-    public static final int PRICE_FIELD_NUMBER = 1;
-    private com.google.type.Money price_;
-    /**
-     * <pre>
-     * Monetary value of the menu item/option on sale. Can be 0 to represent free.
-     * Required.
-     * </pre>
-     *
-     * <code>.google.type.Money price = 1;</code>
-     * @return Whether the price field is set.
-     */
-    @java.lang.Override
-    public boolean hasPrice() {
-      return price_ != null;
-    }
-    /**
-     * <pre>
-     * Monetary value of the menu item/option on sale. Can be 0 to represent free.
-     * Required.
-     * </pre>
-     *
-     * <code>.google.type.Money price = 1;</code>
-     * @return The price.
-     */
-    @java.lang.Override
-    public com.google.type.Money getPrice() {
-      return price_ == null ? com.google.type.Money.getDefaultInstance() : price_;
-    }
-    /**
-     * <pre>
-     * Monetary value of the menu item/option on sale. Can be 0 to represent free.
-     * Required.
-     * </pre>
-     *
-     * <code>.google.type.Money price = 1;</code>
-     */
-    @java.lang.Override
-    public com.google.type.MoneyOrBuilder getPriceOrBuilder() {
-      return price_ == null ? com.google.type.Money.getDefaultInstance() : price_;
-    }
-
-    private byte memoizedIsInitialized = -1;
-    @java.lang.Override
-    public final boolean isInitialized() {
-      byte isInitialized = memoizedIsInitialized;
-      if (isInitialized == 1) return true;
-      if (isInitialized == 0) return false;
-
-      memoizedIsInitialized = 1;
-      return true;
-    }
-
-    @java.lang.Override
-    public void writeTo(com.google.protobuf.CodedOutputStream output)
-                        throws java.io.IOException {
-      if (price_ != null) {
-        output.writeMessage(1, getPrice());
-      }
-      getUnknownFields().writeTo(output);
-    }
-
-    @java.lang.Override
-    public int getSerializedSize() {
-      int size = memoizedSize;
-      if (size != -1) return size;
-
-      size = 0;
-      if (price_ != null) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(1, getPrice());
-      }
-      size += getUnknownFields().getSerializedSize();
-      memoizedSize = size;
-      return size;
-    }
-
-    @java.lang.Override
-    public boolean equals(final java.lang.Object obj) {
-      if (obj == this) {
-       return true;
-      }
-      if (!(obj instanceof food.menu.v1.FoodMenu.Offer)) {
-        return super.equals(obj);
-      }
-      food.menu.v1.FoodMenu.Offer other = (food.menu.v1.FoodMenu.Offer) obj;
-
-      if (hasPrice() != other.hasPrice()) return false;
-      if (hasPrice()) {
-        if (!getPrice()
-            .equals(other.getPrice())) return false;
-      }
-      if (!getUnknownFields().equals(other.getUnknownFields())) return false;
-      return true;
-    }
-
-    @java.lang.Override
-    public int hashCode() {
-      if (memoizedHashCode != 0) {
-        return memoizedHashCode;
-      }
-      int hash = 41;
-      hash = (19 * hash) + getDescriptor().hashCode();
-      if (hasPrice()) {
-        hash = (37 * hash) + PRICE_FIELD_NUMBER;
-        hash = (53 * hash) + getPrice().hashCode();
-      }
-      hash = (29 * hash) + getUnknownFields().hashCode();
-      memoizedHashCode = hash;
-      return hash;
-    }
-
-    public static food.menu.v1.FoodMenu.Offer parseFrom(
-        java.nio.ByteBuffer data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.Offer parseFrom(
-        java.nio.ByteBuffer data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.Offer parseFrom(
-        com.google.protobuf.ByteString data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.Offer parseFrom(
-        com.google.protobuf.ByteString data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.Offer parseFrom(byte[] data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.Offer parseFrom(
-        byte[] data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.Offer parseFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.Offer parseFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.Offer parseDelimitedFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseDelimitedWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.Offer parseDelimitedFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.Offer parseFrom(
-        com.google.protobuf.CodedInputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.Offer parseFrom(
-        com.google.protobuf.CodedInputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input, extensionRegistry);
-    }
-
-    @java.lang.Override
-    public Builder newBuilderForType() { return newBuilder(); }
-    public static Builder newBuilder() {
-      return DEFAULT_INSTANCE.toBuilder();
-    }
-    public static Builder newBuilder(food.menu.v1.FoodMenu.Offer prototype) {
-      return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
-    }
-    @java.lang.Override
-    public Builder toBuilder() {
-      return this == DEFAULT_INSTANCE
-          ? new Builder() : new Builder().mergeFrom(this);
-    }
-
-    @java.lang.Override
-    protected Builder newBuilderForType(
-        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-      Builder builder = new Builder(parent);
-      return builder;
-    }
-    /**
-     * <pre>
-     * Represents pricing and availability information for MenuItems and
-     * MenuItemOptions.
-     * </pre>
-     *
-     * Protobuf type {@code food.menu.v1.Offer}
-     */
-    public static final class Builder extends
-        com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
-        // @@protoc_insertion_point(builder_implements:food.menu.v1.Offer)
-        food.menu.v1.FoodMenu.OfferOrBuilder {
-      public static final com.google.protobuf.Descriptors.Descriptor
-          getDescriptor() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_Offer_descriptor;
-      }
-
-      @java.lang.Override
-      protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-          internalGetFieldAccessorTable() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_Offer_fieldAccessorTable
-            .ensureFieldAccessorsInitialized(
-                food.menu.v1.FoodMenu.Offer.class, food.menu.v1.FoodMenu.Offer.Builder.class);
-      }
-
-      // Construct using food.menu.v1.FoodMenu.Offer.newBuilder()
-      private Builder() {
-
-      }
-
-      private Builder(
-          com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-        super(parent);
-
-      }
-      @java.lang.Override
-      public Builder clear() {
-        super.clear();
-        bitField0_ = 0;
-        price_ = null;
-        if (priceBuilder_ != null) {
-          priceBuilder_.dispose();
-          priceBuilder_ = null;
-        }
-        return this;
-      }
-
-      @java.lang.Override
-      public com.google.protobuf.Descriptors.Descriptor
-          getDescriptorForType() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_Offer_descriptor;
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.Offer getDefaultInstanceForType() {
-        return food.menu.v1.FoodMenu.Offer.getDefaultInstance();
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.Offer build() {
-        food.menu.v1.FoodMenu.Offer result = buildPartial();
-        if (!result.isInitialized()) {
-          throw newUninitializedMessageException(result);
-        }
-        return result;
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.Offer buildPartial() {
-        food.menu.v1.FoodMenu.Offer result = new food.menu.v1.FoodMenu.Offer(this);
-        if (bitField0_ != 0) { buildPartial0(result); }
-        onBuilt();
-        return result;
-      }
-
-      private void buildPartial0(food.menu.v1.FoodMenu.Offer result) {
-        int from_bitField0_ = bitField0_;
-        if (((from_bitField0_ & 0x00000001) != 0)) {
-          result.price_ = priceBuilder_ == null
-              ? price_
-              : priceBuilder_.build();
-        }
-      }
-
-      @java.lang.Override
-      public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof food.menu.v1.FoodMenu.Offer) {
-          return mergeFrom((food.menu.v1.FoodMenu.Offer)other);
-        } else {
-          super.mergeFrom(other);
-          return this;
-        }
-      }
-
-      public Builder mergeFrom(food.menu.v1.FoodMenu.Offer other) {
-        if (other == food.menu.v1.FoodMenu.Offer.getDefaultInstance()) return this;
-        if (other.hasPrice()) {
-          mergePrice(other.getPrice());
-        }
-        this.mergeUnknownFields(other.getUnknownFields());
-        onChanged();
-        return this;
-      }
-
-      @java.lang.Override
-      public final boolean isInitialized() {
-        return true;
-      }
-
-      @java.lang.Override
-      public Builder mergeFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws java.io.IOException {
-        if (extensionRegistry == null) {
-          throw new java.lang.NullPointerException();
-        }
-        try {
-          boolean done = false;
-          while (!done) {
-            int tag = input.readTag();
-            switch (tag) {
-              case 0:
-                done = true;
-                break;
-              case 10: {
-                input.readMessage(
-                    getPriceFieldBuilder().getBuilder(),
-                    extensionRegistry);
-                bitField0_ |= 0x00000001;
-                break;
-              } // case 10
-              default: {
-                if (!super.parseUnknownField(input, extensionRegistry, tag)) {
-                  done = true; // was an endgroup tag
-                }
-                break;
-              } // default:
-            } // switch (tag)
-          } // while (!done)
-        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          throw e.unwrapIOException();
-        } finally {
-          onChanged();
-        } // finally
-        return this;
-      }
-      private int bitField0_;
-
-      private com.google.type.Money price_;
-      private com.google.protobuf.SingleFieldBuilderV3<
-          com.google.type.Money, com.google.type.Money.Builder, com.google.type.MoneyOrBuilder> priceBuilder_;
-      /**
-       * <pre>
-       * Monetary value of the menu item/option on sale. Can be 0 to represent free.
-       * Required.
-       * </pre>
-       *
-       * <code>.google.type.Money price = 1;</code>
-       * @return Whether the price field is set.
-       */
-      public boolean hasPrice() {
-        return ((bitField0_ & 0x00000001) != 0);
-      }
-      /**
-       * <pre>
-       * Monetary value of the menu item/option on sale. Can be 0 to represent free.
-       * Required.
-       * </pre>
-       *
-       * <code>.google.type.Money price = 1;</code>
-       * @return The price.
-       */
-      public com.google.type.Money getPrice() {
-        if (priceBuilder_ == null) {
-          return price_ == null ? com.google.type.Money.getDefaultInstance() : price_;
-        } else {
-          return priceBuilder_.getMessage();
-        }
-      }
-      /**
-       * <pre>
-       * Monetary value of the menu item/option on sale. Can be 0 to represent free.
-       * Required.
-       * </pre>
-       *
-       * <code>.google.type.Money price = 1;</code>
-       */
-      public Builder setPrice(com.google.type.Money value) {
-        if (priceBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          price_ = value;
-        } else {
-          priceBuilder_.setMessage(value);
-        }
-        bitField0_ |= 0x00000001;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Monetary value of the menu item/option on sale. Can be 0 to represent free.
-       * Required.
-       * </pre>
-       *
-       * <code>.google.type.Money price = 1;</code>
-       */
-      public Builder setPrice(
-          com.google.type.Money.Builder builderForValue) {
-        if (priceBuilder_ == null) {
-          price_ = builderForValue.build();
-        } else {
-          priceBuilder_.setMessage(builderForValue.build());
-        }
-        bitField0_ |= 0x00000001;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Monetary value of the menu item/option on sale. Can be 0 to represent free.
-       * Required.
-       * </pre>
-       *
-       * <code>.google.type.Money price = 1;</code>
-       */
-      public Builder mergePrice(com.google.type.Money value) {
-        if (priceBuilder_ == null) {
-          if (((bitField0_ & 0x00000001) != 0) &&
-            price_ != null &&
-            price_ != com.google.type.Money.getDefaultInstance()) {
-            getPriceBuilder().mergeFrom(value);
-          } else {
-            price_ = value;
-          }
-        } else {
-          priceBuilder_.mergeFrom(value);
-        }
-        bitField0_ |= 0x00000001;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Monetary value of the menu item/option on sale. Can be 0 to represent free.
-       * Required.
-       * </pre>
-       *
-       * <code>.google.type.Money price = 1;</code>
-       */
-      public Builder clearPrice() {
-        bitField0_ = (bitField0_ & ~0x00000001);
-        price_ = null;
-        if (priceBuilder_ != null) {
-          priceBuilder_.dispose();
-          priceBuilder_ = null;
-        }
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Monetary value of the menu item/option on sale. Can be 0 to represent free.
-       * Required.
-       * </pre>
-       *
-       * <code>.google.type.Money price = 1;</code>
-       */
-      public com.google.type.Money.Builder getPriceBuilder() {
-        bitField0_ |= 0x00000001;
-        onChanged();
-        return getPriceFieldBuilder().getBuilder();
-      }
-      /**
-       * <pre>
-       * Monetary value of the menu item/option on sale. Can be 0 to represent free.
-       * Required.
-       * </pre>
-       *
-       * <code>.google.type.Money price = 1;</code>
-       */
-      public com.google.type.MoneyOrBuilder getPriceOrBuilder() {
-        if (priceBuilder_ != null) {
-          return priceBuilder_.getMessageOrBuilder();
-        } else {
-          return price_ == null ?
-              com.google.type.Money.getDefaultInstance() : price_;
-        }
-      }
-      /**
-       * <pre>
-       * Monetary value of the menu item/option on sale. Can be 0 to represent free.
-       * Required.
-       * </pre>
-       *
-       * <code>.google.type.Money price = 1;</code>
-       */
-      private com.google.protobuf.SingleFieldBuilderV3<
-          com.google.type.Money, com.google.type.Money.Builder, com.google.type.MoneyOrBuilder> 
-          getPriceFieldBuilder() {
-        if (priceBuilder_ == null) {
-          priceBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
-              com.google.type.Money, com.google.type.Money.Builder, com.google.type.MoneyOrBuilder>(
-                  getPrice(),
-                  getParentForChildren(),
-                  isClean());
-          price_ = null;
-        }
-        return priceBuilder_;
-      }
-      @java.lang.Override
-      public final Builder setUnknownFields(
-          final com.google.protobuf.UnknownFieldSet unknownFields) {
-        return super.setUnknownFields(unknownFields);
-      }
-
-      @java.lang.Override
-      public final Builder mergeUnknownFields(
-          final com.google.protobuf.UnknownFieldSet unknownFields) {
-        return super.mergeUnknownFields(unknownFields);
-      }
-
-
-      // @@protoc_insertion_point(builder_scope:food.menu.v1.Offer)
-    }
-
-    // @@protoc_insertion_point(class_scope:food.menu.v1.Offer)
-    private static final food.menu.v1.FoodMenu.Offer DEFAULT_INSTANCE;
-    static {
-      DEFAULT_INSTANCE = new food.menu.v1.FoodMenu.Offer();
-    }
-
-    public static food.menu.v1.FoodMenu.Offer getDefaultInstance() {
-      return DEFAULT_INSTANCE;
-    }
-
-    private static final com.google.protobuf.Parser<Offer>
-        PARSER = new com.google.protobuf.AbstractParser<Offer>() {
-      @java.lang.Override
-      public Offer parsePartialFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws com.google.protobuf.InvalidProtocolBufferException {
-        Builder builder = newBuilder();
-        try {
-          builder.mergeFrom(input, extensionRegistry);
-        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          throw e.setUnfinishedMessage(builder.buildPartial());
-        } catch (com.google.protobuf.UninitializedMessageException e) {
-          throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
-        } catch (java.io.IOException e) {
-          throw new com.google.protobuf.InvalidProtocolBufferException(e)
-              .setUnfinishedMessage(builder.buildPartial());
-        }
-        return builder.buildPartial();
-      }
-    };
-
-    public static com.google.protobuf.Parser<Offer> parser() {
-      return PARSER;
-    }
-
-    @java.lang.Override
-    public com.google.protobuf.Parser<Offer> getParserForType() {
-      return PARSER;
-    }
-
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.Offer getDefaultInstanceForType() {
-      return DEFAULT_INSTANCE;
-    }
-
-  }
-
-  public interface DisclaimerOrBuilder extends
-      // @@protoc_insertion_point(interface_extends:food.menu.v1.Disclaimer)
-      com.google.protobuf.MessageOrBuilder {
-
-    /**
-     * <pre>
-     * Body of the disclaimer text to be shown to the user.
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField text = 1;</code>
-     * @return Whether the text field is set.
-     */
-    boolean hasText();
-    /**
-     * <pre>
-     * Body of the disclaimer text to be shown to the user.
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField text = 1;</code>
-     * @return The text.
-     */
-    food.menu.v1.FoodMenu.TextField getText();
-    /**
-     * <pre>
-     * Body of the disclaimer text to be shown to the user.
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField text = 1;</code>
-     */
-    food.menu.v1.FoodMenu.TextFieldOrBuilder getTextOrBuilder();
-
-    /**
-     * <pre>
-     * URL containing more information about the disclaimer.
-     * Optional.
-     * </pre>
-     *
-     * <code>string uri = 2;</code>
-     * @return The uri.
-     */
-    java.lang.String getUri();
-    /**
-     * <pre>
-     * URL containing more information about the disclaimer.
-     * Optional.
-     * </pre>
-     *
-     * <code>string uri = 2;</code>
-     * @return The bytes for uri.
-     */
-    com.google.protobuf.ByteString
-        getUriBytes();
-  }
-  /**
-   * <pre>
-   * Partner provided disclaimer shown to the user. Contains a text disclaimer
-   * along with an optional URL for more information.
-   * Some example include: associated medical risks/warnings, any additional
-   * fees/gratutity, etc.
-   * </pre>
-   *
-   * Protobuf type {@code food.menu.v1.Disclaimer}
-   */
-  public static final class Disclaimer extends
-      com.google.protobuf.GeneratedMessageV3 implements
-      // @@protoc_insertion_point(message_implements:food.menu.v1.Disclaimer)
-      DisclaimerOrBuilder {
-  private static final long serialVersionUID = 0L;
-    // Use Disclaimer.newBuilder() to construct.
-    private Disclaimer(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
-      super(builder);
-    }
-    private Disclaimer() {
-      uri_ = "";
-    }
-
-    @java.lang.Override
-    @SuppressWarnings({"unused"})
-    protected java.lang.Object newInstance(
-        UnusedPrivateParameter unused) {
-      return new Disclaimer();
-    }
-
-    public static final com.google.protobuf.Descriptors.Descriptor
-        getDescriptor() {
-      return food.menu.v1.FoodMenu.internal_static_food_menu_v1_Disclaimer_descriptor;
-    }
-
-    @java.lang.Override
-    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-        internalGetFieldAccessorTable() {
-      return food.menu.v1.FoodMenu.internal_static_food_menu_v1_Disclaimer_fieldAccessorTable
-          .ensureFieldAccessorsInitialized(
-              food.menu.v1.FoodMenu.Disclaimer.class, food.menu.v1.FoodMenu.Disclaimer.Builder.class);
-    }
-
-    public static final int TEXT_FIELD_NUMBER = 1;
-    private food.menu.v1.FoodMenu.TextField text_;
-    /**
-     * <pre>
-     * Body of the disclaimer text to be shown to the user.
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField text = 1;</code>
-     * @return Whether the text field is set.
-     */
-    @java.lang.Override
-    public boolean hasText() {
-      return text_ != null;
-    }
-    /**
-     * <pre>
-     * Body of the disclaimer text to be shown to the user.
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField text = 1;</code>
-     * @return The text.
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.TextField getText() {
-      return text_ == null ? food.menu.v1.FoodMenu.TextField.getDefaultInstance() : text_;
-    }
-    /**
-     * <pre>
-     * Body of the disclaimer text to be shown to the user.
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField text = 1;</code>
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.TextFieldOrBuilder getTextOrBuilder() {
-      return text_ == null ? food.menu.v1.FoodMenu.TextField.getDefaultInstance() : text_;
-    }
-
-    public static final int URI_FIELD_NUMBER = 2;
-    @SuppressWarnings("serial")
-    private volatile java.lang.Object uri_ = "";
-    /**
-     * <pre>
-     * URL containing more information about the disclaimer.
-     * Optional.
-     * </pre>
-     *
-     * <code>string uri = 2;</code>
-     * @return The uri.
-     */
-    @java.lang.Override
-    public java.lang.String getUri() {
-      java.lang.Object ref = uri_;
-      if (ref instanceof java.lang.String) {
-        return (java.lang.String) ref;
-      } else {
-        com.google.protobuf.ByteString bs = 
-            (com.google.protobuf.ByteString) ref;
-        java.lang.String s = bs.toStringUtf8();
-        uri_ = s;
-        return s;
-      }
-    }
-    /**
-     * <pre>
-     * URL containing more information about the disclaimer.
-     * Optional.
-     * </pre>
-     *
-     * <code>string uri = 2;</code>
-     * @return The bytes for uri.
-     */
-    @java.lang.Override
-    public com.google.protobuf.ByteString
-        getUriBytes() {
-      java.lang.Object ref = uri_;
-      if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
-            com.google.protobuf.ByteString.copyFromUtf8(
-                (java.lang.String) ref);
-        uri_ = b;
-        return b;
-      } else {
-        return (com.google.protobuf.ByteString) ref;
-      }
-    }
-
-    private byte memoizedIsInitialized = -1;
-    @java.lang.Override
-    public final boolean isInitialized() {
-      byte isInitialized = memoizedIsInitialized;
-      if (isInitialized == 1) return true;
-      if (isInitialized == 0) return false;
-
-      memoizedIsInitialized = 1;
-      return true;
-    }
-
-    @java.lang.Override
-    public void writeTo(com.google.protobuf.CodedOutputStream output)
-                        throws java.io.IOException {
-      if (text_ != null) {
-        output.writeMessage(1, getText());
-      }
-      if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(uri_)) {
-        com.google.protobuf.GeneratedMessageV3.writeString(output, 2, uri_);
-      }
-      getUnknownFields().writeTo(output);
-    }
-
-    @java.lang.Override
-    public int getSerializedSize() {
-      int size = memoizedSize;
-      if (size != -1) return size;
-
-      size = 0;
-      if (text_ != null) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(1, getText());
-      }
-      if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(uri_)) {
-        size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, uri_);
-      }
-      size += getUnknownFields().getSerializedSize();
-      memoizedSize = size;
-      return size;
-    }
-
-    @java.lang.Override
-    public boolean equals(final java.lang.Object obj) {
-      if (obj == this) {
-       return true;
-      }
-      if (!(obj instanceof food.menu.v1.FoodMenu.Disclaimer)) {
-        return super.equals(obj);
-      }
-      food.menu.v1.FoodMenu.Disclaimer other = (food.menu.v1.FoodMenu.Disclaimer) obj;
-
-      if (hasText() != other.hasText()) return false;
-      if (hasText()) {
-        if (!getText()
-            .equals(other.getText())) return false;
-      }
-      if (!getUri()
-          .equals(other.getUri())) return false;
-      if (!getUnknownFields().equals(other.getUnknownFields())) return false;
-      return true;
-    }
-
-    @java.lang.Override
-    public int hashCode() {
-      if (memoizedHashCode != 0) {
-        return memoizedHashCode;
-      }
-      int hash = 41;
-      hash = (19 * hash) + getDescriptor().hashCode();
-      if (hasText()) {
-        hash = (37 * hash) + TEXT_FIELD_NUMBER;
-        hash = (53 * hash) + getText().hashCode();
-      }
-      hash = (37 * hash) + URI_FIELD_NUMBER;
-      hash = (53 * hash) + getUri().hashCode();
-      hash = (29 * hash) + getUnknownFields().hashCode();
-      memoizedHashCode = hash;
-      return hash;
-    }
-
-    public static food.menu.v1.FoodMenu.Disclaimer parseFrom(
-        java.nio.ByteBuffer data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.Disclaimer parseFrom(
-        java.nio.ByteBuffer data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.Disclaimer parseFrom(
-        com.google.protobuf.ByteString data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.Disclaimer parseFrom(
-        com.google.protobuf.ByteString data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.Disclaimer parseFrom(byte[] data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.Disclaimer parseFrom(
-        byte[] data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.Disclaimer parseFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.Disclaimer parseFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.Disclaimer parseDelimitedFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseDelimitedWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.Disclaimer parseDelimitedFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.Disclaimer parseFrom(
-        com.google.protobuf.CodedInputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.Disclaimer parseFrom(
-        com.google.protobuf.CodedInputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input, extensionRegistry);
-    }
-
-    @java.lang.Override
-    public Builder newBuilderForType() { return newBuilder(); }
-    public static Builder newBuilder() {
-      return DEFAULT_INSTANCE.toBuilder();
-    }
-    public static Builder newBuilder(food.menu.v1.FoodMenu.Disclaimer prototype) {
-      return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
-    }
-    @java.lang.Override
-    public Builder toBuilder() {
-      return this == DEFAULT_INSTANCE
-          ? new Builder() : new Builder().mergeFrom(this);
-    }
-
-    @java.lang.Override
-    protected Builder newBuilderForType(
-        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-      Builder builder = new Builder(parent);
-      return builder;
-    }
-    /**
-     * <pre>
-     * Partner provided disclaimer shown to the user. Contains a text disclaimer
-     * along with an optional URL for more information.
-     * Some example include: associated medical risks/warnings, any additional
-     * fees/gratutity, etc.
-     * </pre>
-     *
-     * Protobuf type {@code food.menu.v1.Disclaimer}
-     */
-    public static final class Builder extends
-        com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
-        // @@protoc_insertion_point(builder_implements:food.menu.v1.Disclaimer)
-        food.menu.v1.FoodMenu.DisclaimerOrBuilder {
-      public static final com.google.protobuf.Descriptors.Descriptor
-          getDescriptor() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_Disclaimer_descriptor;
-      }
-
-      @java.lang.Override
-      protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-          internalGetFieldAccessorTable() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_Disclaimer_fieldAccessorTable
-            .ensureFieldAccessorsInitialized(
-                food.menu.v1.FoodMenu.Disclaimer.class, food.menu.v1.FoodMenu.Disclaimer.Builder.class);
-      }
-
-      // Construct using food.menu.v1.FoodMenu.Disclaimer.newBuilder()
-      private Builder() {
-
-      }
-
-      private Builder(
-          com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-        super(parent);
-
-      }
-      @java.lang.Override
-      public Builder clear() {
-        super.clear();
-        bitField0_ = 0;
-        text_ = null;
-        if (textBuilder_ != null) {
-          textBuilder_.dispose();
-          textBuilder_ = null;
-        }
-        uri_ = "";
-        return this;
-      }
-
-      @java.lang.Override
-      public com.google.protobuf.Descriptors.Descriptor
-          getDescriptorForType() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_Disclaimer_descriptor;
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.Disclaimer getDefaultInstanceForType() {
-        return food.menu.v1.FoodMenu.Disclaimer.getDefaultInstance();
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.Disclaimer build() {
-        food.menu.v1.FoodMenu.Disclaimer result = buildPartial();
-        if (!result.isInitialized()) {
-          throw newUninitializedMessageException(result);
-        }
-        return result;
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.Disclaimer buildPartial() {
-        food.menu.v1.FoodMenu.Disclaimer result = new food.menu.v1.FoodMenu.Disclaimer(this);
-        if (bitField0_ != 0) { buildPartial0(result); }
-        onBuilt();
-        return result;
-      }
-
-      private void buildPartial0(food.menu.v1.FoodMenu.Disclaimer result) {
-        int from_bitField0_ = bitField0_;
-        if (((from_bitField0_ & 0x00000001) != 0)) {
-          result.text_ = textBuilder_ == null
-              ? text_
-              : textBuilder_.build();
-        }
-        if (((from_bitField0_ & 0x00000002) != 0)) {
-          result.uri_ = uri_;
-        }
-      }
-
-      @java.lang.Override
-      public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof food.menu.v1.FoodMenu.Disclaimer) {
-          return mergeFrom((food.menu.v1.FoodMenu.Disclaimer)other);
-        } else {
-          super.mergeFrom(other);
-          return this;
-        }
-      }
-
-      public Builder mergeFrom(food.menu.v1.FoodMenu.Disclaimer other) {
-        if (other == food.menu.v1.FoodMenu.Disclaimer.getDefaultInstance()) return this;
-        if (other.hasText()) {
-          mergeText(other.getText());
-        }
-        if (!other.getUri().isEmpty()) {
-          uri_ = other.uri_;
-          bitField0_ |= 0x00000002;
-          onChanged();
-        }
-        this.mergeUnknownFields(other.getUnknownFields());
-        onChanged();
-        return this;
-      }
-
-      @java.lang.Override
-      public final boolean isInitialized() {
-        return true;
-      }
-
-      @java.lang.Override
-      public Builder mergeFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws java.io.IOException {
-        if (extensionRegistry == null) {
-          throw new java.lang.NullPointerException();
-        }
-        try {
-          boolean done = false;
-          while (!done) {
-            int tag = input.readTag();
-            switch (tag) {
-              case 0:
-                done = true;
-                break;
-              case 10: {
-                input.readMessage(
-                    getTextFieldBuilder().getBuilder(),
-                    extensionRegistry);
-                bitField0_ |= 0x00000001;
-                break;
-              } // case 10
-              case 18: {
-                uri_ = input.readStringRequireUtf8();
-                bitField0_ |= 0x00000002;
-                break;
-              } // case 18
-              default: {
-                if (!super.parseUnknownField(input, extensionRegistry, tag)) {
-                  done = true; // was an endgroup tag
-                }
-                break;
-              } // default:
-            } // switch (tag)
-          } // while (!done)
-        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          throw e.unwrapIOException();
-        } finally {
-          onChanged();
-        } // finally
-        return this;
-      }
-      private int bitField0_;
-
-      private food.menu.v1.FoodMenu.TextField text_;
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.TextField, food.menu.v1.FoodMenu.TextField.Builder, food.menu.v1.FoodMenu.TextFieldOrBuilder> textBuilder_;
-      /**
-       * <pre>
-       * Body of the disclaimer text to be shown to the user.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField text = 1;</code>
-       * @return Whether the text field is set.
-       */
-      public boolean hasText() {
-        return ((bitField0_ & 0x00000001) != 0);
-      }
-      /**
-       * <pre>
-       * Body of the disclaimer text to be shown to the user.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField text = 1;</code>
-       * @return The text.
-       */
-      public food.menu.v1.FoodMenu.TextField getText() {
-        if (textBuilder_ == null) {
-          return text_ == null ? food.menu.v1.FoodMenu.TextField.getDefaultInstance() : text_;
-        } else {
-          return textBuilder_.getMessage();
-        }
-      }
-      /**
-       * <pre>
-       * Body of the disclaimer text to be shown to the user.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField text = 1;</code>
-       */
-      public Builder setText(food.menu.v1.FoodMenu.TextField value) {
-        if (textBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          text_ = value;
-        } else {
-          textBuilder_.setMessage(value);
-        }
-        bitField0_ |= 0x00000001;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Body of the disclaimer text to be shown to the user.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField text = 1;</code>
-       */
-      public Builder setText(
-          food.menu.v1.FoodMenu.TextField.Builder builderForValue) {
-        if (textBuilder_ == null) {
-          text_ = builderForValue.build();
-        } else {
-          textBuilder_.setMessage(builderForValue.build());
-        }
-        bitField0_ |= 0x00000001;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Body of the disclaimer text to be shown to the user.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField text = 1;</code>
-       */
-      public Builder mergeText(food.menu.v1.FoodMenu.TextField value) {
-        if (textBuilder_ == null) {
-          if (((bitField0_ & 0x00000001) != 0) &&
-            text_ != null &&
-            text_ != food.menu.v1.FoodMenu.TextField.getDefaultInstance()) {
-            getTextBuilder().mergeFrom(value);
-          } else {
-            text_ = value;
-          }
-        } else {
-          textBuilder_.mergeFrom(value);
-        }
-        bitField0_ |= 0x00000001;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Body of the disclaimer text to be shown to the user.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField text = 1;</code>
-       */
-      public Builder clearText() {
-        bitField0_ = (bitField0_ & ~0x00000001);
-        text_ = null;
-        if (textBuilder_ != null) {
-          textBuilder_.dispose();
-          textBuilder_ = null;
-        }
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Body of the disclaimer text to be shown to the user.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField text = 1;</code>
-       */
-      public food.menu.v1.FoodMenu.TextField.Builder getTextBuilder() {
-        bitField0_ |= 0x00000001;
-        onChanged();
-        return getTextFieldBuilder().getBuilder();
-      }
-      /**
-       * <pre>
-       * Body of the disclaimer text to be shown to the user.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField text = 1;</code>
-       */
-      public food.menu.v1.FoodMenu.TextFieldOrBuilder getTextOrBuilder() {
-        if (textBuilder_ != null) {
-          return textBuilder_.getMessageOrBuilder();
-        } else {
-          return text_ == null ?
-              food.menu.v1.FoodMenu.TextField.getDefaultInstance() : text_;
-        }
-      }
-      /**
-       * <pre>
-       * Body of the disclaimer text to be shown to the user.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField text = 1;</code>
-       */
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.TextField, food.menu.v1.FoodMenu.TextField.Builder, food.menu.v1.FoodMenu.TextFieldOrBuilder> 
-          getTextFieldBuilder() {
-        if (textBuilder_ == null) {
-          textBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
-              food.menu.v1.FoodMenu.TextField, food.menu.v1.FoodMenu.TextField.Builder, food.menu.v1.FoodMenu.TextFieldOrBuilder>(
-                  getText(),
-                  getParentForChildren(),
-                  isClean());
-          text_ = null;
-        }
-        return textBuilder_;
-      }
-
-      private java.lang.Object uri_ = "";
-      /**
-       * <pre>
-       * URL containing more information about the disclaimer.
-       * Optional.
-       * </pre>
-       *
-       * <code>string uri = 2;</code>
-       * @return The uri.
-       */
-      public java.lang.String getUri() {
-        java.lang.Object ref = uri_;
-        if (!(ref instanceof java.lang.String)) {
-          com.google.protobuf.ByteString bs =
-              (com.google.protobuf.ByteString) ref;
-          java.lang.String s = bs.toStringUtf8();
-          uri_ = s;
-          return s;
-        } else {
-          return (java.lang.String) ref;
-        }
-      }
-      /**
-       * <pre>
-       * URL containing more information about the disclaimer.
-       * Optional.
-       * </pre>
-       *
-       * <code>string uri = 2;</code>
-       * @return The bytes for uri.
-       */
-      public com.google.protobuf.ByteString
-          getUriBytes() {
-        java.lang.Object ref = uri_;
-        if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
-              com.google.protobuf.ByteString.copyFromUtf8(
-                  (java.lang.String) ref);
-          uri_ = b;
-          return b;
-        } else {
-          return (com.google.protobuf.ByteString) ref;
-        }
-      }
-      /**
-       * <pre>
-       * URL containing more information about the disclaimer.
-       * Optional.
-       * </pre>
-       *
-       * <code>string uri = 2;</code>
-       * @param value The uri to set.
-       * @return This builder for chaining.
-       */
-      public Builder setUri(
-          java.lang.String value) {
-        if (value == null) { throw new NullPointerException(); }
-        uri_ = value;
-        bitField0_ |= 0x00000002;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * URL containing more information about the disclaimer.
-       * Optional.
-       * </pre>
-       *
-       * <code>string uri = 2;</code>
-       * @return This builder for chaining.
-       */
-      public Builder clearUri() {
-        uri_ = getDefaultInstance().getUri();
-        bitField0_ = (bitField0_ & ~0x00000002);
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * URL containing more information about the disclaimer.
-       * Optional.
-       * </pre>
-       *
-       * <code>string uri = 2;</code>
-       * @param value The bytes for uri to set.
-       * @return This builder for chaining.
-       */
-      public Builder setUriBytes(
-          com.google.protobuf.ByteString value) {
-        if (value == null) { throw new NullPointerException(); }
-        checkByteStringIsUtf8(value);
-        uri_ = value;
-        bitField0_ |= 0x00000002;
-        onChanged();
-        return this;
-      }
-      @java.lang.Override
-      public final Builder setUnknownFields(
-          final com.google.protobuf.UnknownFieldSet unknownFields) {
-        return super.setUnknownFields(unknownFields);
-      }
-
-      @java.lang.Override
-      public final Builder mergeUnknownFields(
-          final com.google.protobuf.UnknownFieldSet unknownFields) {
-        return super.mergeUnknownFields(unknownFields);
-      }
-
-
-      // @@protoc_insertion_point(builder_scope:food.menu.v1.Disclaimer)
-    }
-
-    // @@protoc_insertion_point(class_scope:food.menu.v1.Disclaimer)
-    private static final food.menu.v1.FoodMenu.Disclaimer DEFAULT_INSTANCE;
-    static {
-      DEFAULT_INSTANCE = new food.menu.v1.FoodMenu.Disclaimer();
-    }
-
-    public static food.menu.v1.FoodMenu.Disclaimer getDefaultInstance() {
-      return DEFAULT_INSTANCE;
-    }
-
-    private static final com.google.protobuf.Parser<Disclaimer>
-        PARSER = new com.google.protobuf.AbstractParser<Disclaimer>() {
-      @java.lang.Override
-      public Disclaimer parsePartialFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws com.google.protobuf.InvalidProtocolBufferException {
-        Builder builder = newBuilder();
-        try {
-          builder.mergeFrom(input, extensionRegistry);
-        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          throw e.setUnfinishedMessage(builder.buildPartial());
-        } catch (com.google.protobuf.UninitializedMessageException e) {
-          throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
-        } catch (java.io.IOException e) {
-          throw new com.google.protobuf.InvalidProtocolBufferException(e)
-              .setUnfinishedMessage(builder.buildPartial());
-        }
-        return builder.buildPartial();
-      }
-    };
-
-    public static com.google.protobuf.Parser<Disclaimer> parser() {
-      return PARSER;
-    }
-
-    @java.lang.Override
-    public com.google.protobuf.Parser<Disclaimer> getParserForType() {
-      return PARSER;
-    }
-
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.Disclaimer getDefaultInstanceForType() {
-      return DEFAULT_INSTANCE;
-    }
-
-  }
-
-  public interface TextFieldOrBuilder extends
-      // @@protoc_insertion_point(interface_extends:food.menu.v1.TextField)
-      com.google.protobuf.MessageOrBuilder {
-
-    /**
-     * <pre>
-     * Per-locale text values.
-     *
-     * If there is only one desired locale support, then the language_code within
-     * each text is not required to be set and the language will be inferred from
-     * the default language of the menu.
-     *
-     * If there are multiple texts across different locales, then the
-     * language_code must be set for each text. The first text in the list is
-     * considered the preferred representation.
-     * Required.
-     * </pre>
-     *
-     * <code>repeated .google.type.LocalizedText text = 1;</code>
-     */
-    java.util.List<com.google.type.LocalizedText> 
-        getTextList();
-    /**
-     * <pre>
-     * Per-locale text values.
-     *
-     * If there is only one desired locale support, then the language_code within
-     * each text is not required to be set and the language will be inferred from
-     * the default language of the menu.
-     *
-     * If there are multiple texts across different locales, then the
-     * language_code must be set for each text. The first text in the list is
-     * considered the preferred representation.
-     * Required.
-     * </pre>
-     *
-     * <code>repeated .google.type.LocalizedText text = 1;</code>
-     */
-    com.google.type.LocalizedText getText(int index);
-    /**
-     * <pre>
-     * Per-locale text values.
-     *
-     * If there is only one desired locale support, then the language_code within
-     * each text is not required to be set and the language will be inferred from
-     * the default language of the menu.
-     *
-     * If there are multiple texts across different locales, then the
-     * language_code must be set for each text. The first text in the list is
-     * considered the preferred representation.
-     * Required.
-     * </pre>
-     *
-     * <code>repeated .google.type.LocalizedText text = 1;</code>
-     */
-    int getTextCount();
-    /**
-     * <pre>
-     * Per-locale text values.
-     *
-     * If there is only one desired locale support, then the language_code within
-     * each text is not required to be set and the language will be inferred from
-     * the default language of the menu.
-     *
-     * If there are multiple texts across different locales, then the
-     * language_code must be set for each text. The first text in the list is
-     * considered the preferred representation.
-     * Required.
-     * </pre>
-     *
-     * <code>repeated .google.type.LocalizedText text = 1;</code>
-     */
-    java.util.List<? extends com.google.type.LocalizedTextOrBuilder> 
-        getTextOrBuilderList();
-    /**
-     * <pre>
-     * Per-locale text values.
-     *
-     * If there is only one desired locale support, then the language_code within
-     * each text is not required to be set and the language will be inferred from
-     * the default language of the menu.
-     *
-     * If there are multiple texts across different locales, then the
-     * language_code must be set for each text. The first text in the list is
-     * considered the preferred representation.
-     * Required.
-     * </pre>
-     *
-     * <code>repeated .google.type.LocalizedText text = 1;</code>
-     */
-    com.google.type.LocalizedTextOrBuilder getTextOrBuilder(
-        int index);
-  }
-  /**
-   * <pre>
-   * A text payload that contains one or more localized values.
-   * </pre>
-   *
-   * Protobuf type {@code food.menu.v1.TextField}
-   */
-  public static final class TextField extends
-      com.google.protobuf.GeneratedMessageV3 implements
-      // @@protoc_insertion_point(message_implements:food.menu.v1.TextField)
-      TextFieldOrBuilder {
-  private static final long serialVersionUID = 0L;
-    // Use TextField.newBuilder() to construct.
-    private TextField(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
-      super(builder);
-    }
-    private TextField() {
-      text_ = java.util.Collections.emptyList();
-    }
-
-    @java.lang.Override
-    @SuppressWarnings({"unused"})
-    protected java.lang.Object newInstance(
-        UnusedPrivateParameter unused) {
-      return new TextField();
-    }
-
-    public static final com.google.protobuf.Descriptors.Descriptor
-        getDescriptor() {
-      return food.menu.v1.FoodMenu.internal_static_food_menu_v1_TextField_descriptor;
-    }
-
-    @java.lang.Override
-    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-        internalGetFieldAccessorTable() {
-      return food.menu.v1.FoodMenu.internal_static_food_menu_v1_TextField_fieldAccessorTable
-          .ensureFieldAccessorsInitialized(
-              food.menu.v1.FoodMenu.TextField.class, food.menu.v1.FoodMenu.TextField.Builder.class);
-    }
-
-    public static final int TEXT_FIELD_NUMBER = 1;
-    @SuppressWarnings("serial")
-    private java.util.List<com.google.type.LocalizedText> text_;
-    /**
-     * <pre>
-     * Per-locale text values.
-     *
-     * If there is only one desired locale support, then the language_code within
-     * each text is not required to be set and the language will be inferred from
-     * the default language of the menu.
-     *
-     * If there are multiple texts across different locales, then the
-     * language_code must be set for each text. The first text in the list is
-     * considered the preferred representation.
-     * Required.
-     * </pre>
-     *
-     * <code>repeated .google.type.LocalizedText text = 1;</code>
-     */
-    @java.lang.Override
-    public java.util.List<com.google.type.LocalizedText> getTextList() {
-      return text_;
-    }
-    /**
-     * <pre>
-     * Per-locale text values.
-     *
-     * If there is only one desired locale support, then the language_code within
-     * each text is not required to be set and the language will be inferred from
-     * the default language of the menu.
-     *
-     * If there are multiple texts across different locales, then the
-     * language_code must be set for each text. The first text in the list is
-     * considered the preferred representation.
-     * Required.
-     * </pre>
-     *
-     * <code>repeated .google.type.LocalizedText text = 1;</code>
-     */
-    @java.lang.Override
-    public java.util.List<? extends com.google.type.LocalizedTextOrBuilder> 
-        getTextOrBuilderList() {
-      return text_;
-    }
-    /**
-     * <pre>
-     * Per-locale text values.
-     *
-     * If there is only one desired locale support, then the language_code within
-     * each text is not required to be set and the language will be inferred from
-     * the default language of the menu.
-     *
-     * If there are multiple texts across different locales, then the
-     * language_code must be set for each text. The first text in the list is
-     * considered the preferred representation.
-     * Required.
-     * </pre>
-     *
-     * <code>repeated .google.type.LocalizedText text = 1;</code>
-     */
-    @java.lang.Override
-    public int getTextCount() {
-      return text_.size();
-    }
-    /**
-     * <pre>
-     * Per-locale text values.
-     *
-     * If there is only one desired locale support, then the language_code within
-     * each text is not required to be set and the language will be inferred from
-     * the default language of the menu.
-     *
-     * If there are multiple texts across different locales, then the
-     * language_code must be set for each text. The first text in the list is
-     * considered the preferred representation.
-     * Required.
-     * </pre>
-     *
-     * <code>repeated .google.type.LocalizedText text = 1;</code>
-     */
-    @java.lang.Override
-    public com.google.type.LocalizedText getText(int index) {
-      return text_.get(index);
-    }
-    /**
-     * <pre>
-     * Per-locale text values.
-     *
-     * If there is only one desired locale support, then the language_code within
-     * each text is not required to be set and the language will be inferred from
-     * the default language of the menu.
-     *
-     * If there are multiple texts across different locales, then the
-     * language_code must be set for each text. The first text in the list is
-     * considered the preferred representation.
-     * Required.
-     * </pre>
-     *
-     * <code>repeated .google.type.LocalizedText text = 1;</code>
-     */
-    @java.lang.Override
-    public com.google.type.LocalizedTextOrBuilder getTextOrBuilder(
-        int index) {
-      return text_.get(index);
-    }
-
-    private byte memoizedIsInitialized = -1;
-    @java.lang.Override
-    public final boolean isInitialized() {
-      byte isInitialized = memoizedIsInitialized;
-      if (isInitialized == 1) return true;
-      if (isInitialized == 0) return false;
-
-      memoizedIsInitialized = 1;
-      return true;
-    }
-
-    @java.lang.Override
-    public void writeTo(com.google.protobuf.CodedOutputStream output)
-                        throws java.io.IOException {
-      for (int i = 0; i < text_.size(); i++) {
-        output.writeMessage(1, text_.get(i));
-      }
-      getUnknownFields().writeTo(output);
-    }
-
-    @java.lang.Override
-    public int getSerializedSize() {
-      int size = memoizedSize;
-      if (size != -1) return size;
-
-      size = 0;
-      for (int i = 0; i < text_.size(); i++) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(1, text_.get(i));
-      }
-      size += getUnknownFields().getSerializedSize();
-      memoizedSize = size;
-      return size;
-    }
-
-    @java.lang.Override
-    public boolean equals(final java.lang.Object obj) {
-      if (obj == this) {
-       return true;
-      }
-      if (!(obj instanceof food.menu.v1.FoodMenu.TextField)) {
-        return super.equals(obj);
-      }
-      food.menu.v1.FoodMenu.TextField other = (food.menu.v1.FoodMenu.TextField) obj;
-
-      if (!getTextList()
-          .equals(other.getTextList())) return false;
-      if (!getUnknownFields().equals(other.getUnknownFields())) return false;
-      return true;
-    }
-
-    @java.lang.Override
-    public int hashCode() {
-      if (memoizedHashCode != 0) {
-        return memoizedHashCode;
-      }
-      int hash = 41;
-      hash = (19 * hash) + getDescriptor().hashCode();
-      if (getTextCount() > 0) {
-        hash = (37 * hash) + TEXT_FIELD_NUMBER;
-        hash = (53 * hash) + getTextList().hashCode();
-      }
-      hash = (29 * hash) + getUnknownFields().hashCode();
-      memoizedHashCode = hash;
-      return hash;
-    }
-
-    public static food.menu.v1.FoodMenu.TextField parseFrom(
-        java.nio.ByteBuffer data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.TextField parseFrom(
-        java.nio.ByteBuffer data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.TextField parseFrom(
-        com.google.protobuf.ByteString data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.TextField parseFrom(
-        com.google.protobuf.ByteString data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.TextField parseFrom(byte[] data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.TextField parseFrom(
-        byte[] data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.TextField parseFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.TextField parseFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.TextField parseDelimitedFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseDelimitedWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.TextField parseDelimitedFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.TextField parseFrom(
-        com.google.protobuf.CodedInputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.TextField parseFrom(
-        com.google.protobuf.CodedInputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input, extensionRegistry);
-    }
-
-    @java.lang.Override
-    public Builder newBuilderForType() { return newBuilder(); }
-    public static Builder newBuilder() {
-      return DEFAULT_INSTANCE.toBuilder();
-    }
-    public static Builder newBuilder(food.menu.v1.FoodMenu.TextField prototype) {
-      return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
-    }
-    @java.lang.Override
-    public Builder toBuilder() {
-      return this == DEFAULT_INSTANCE
-          ? new Builder() : new Builder().mergeFrom(this);
-    }
-
-    @java.lang.Override
-    protected Builder newBuilderForType(
-        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-      Builder builder = new Builder(parent);
-      return builder;
-    }
-    /**
-     * <pre>
-     * A text payload that contains one or more localized values.
-     * </pre>
-     *
-     * Protobuf type {@code food.menu.v1.TextField}
-     */
-    public static final class Builder extends
-        com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
-        // @@protoc_insertion_point(builder_implements:food.menu.v1.TextField)
-        food.menu.v1.FoodMenu.TextFieldOrBuilder {
-      public static final com.google.protobuf.Descriptors.Descriptor
-          getDescriptor() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_TextField_descriptor;
-      }
-
-      @java.lang.Override
-      protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-          internalGetFieldAccessorTable() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_TextField_fieldAccessorTable
-            .ensureFieldAccessorsInitialized(
-                food.menu.v1.FoodMenu.TextField.class, food.menu.v1.FoodMenu.TextField.Builder.class);
-      }
-
-      // Construct using food.menu.v1.FoodMenu.TextField.newBuilder()
-      private Builder() {
-
-      }
-
-      private Builder(
-          com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-        super(parent);
-
-      }
-      @java.lang.Override
-      public Builder clear() {
-        super.clear();
-        bitField0_ = 0;
-        if (textBuilder_ == null) {
-          text_ = java.util.Collections.emptyList();
-        } else {
-          text_ = null;
-          textBuilder_.clear();
-        }
-        bitField0_ = (bitField0_ & ~0x00000001);
-        return this;
-      }
-
-      @java.lang.Override
-      public com.google.protobuf.Descriptors.Descriptor
-          getDescriptorForType() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_TextField_descriptor;
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.TextField getDefaultInstanceForType() {
-        return food.menu.v1.FoodMenu.TextField.getDefaultInstance();
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.TextField build() {
-        food.menu.v1.FoodMenu.TextField result = buildPartial();
-        if (!result.isInitialized()) {
-          throw newUninitializedMessageException(result);
-        }
-        return result;
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.TextField buildPartial() {
-        food.menu.v1.FoodMenu.TextField result = new food.menu.v1.FoodMenu.TextField(this);
-        buildPartialRepeatedFields(result);
-        if (bitField0_ != 0) { buildPartial0(result); }
-        onBuilt();
-        return result;
-      }
-
-      private void buildPartialRepeatedFields(food.menu.v1.FoodMenu.TextField result) {
-        if (textBuilder_ == null) {
-          if (((bitField0_ & 0x00000001) != 0)) {
-            text_ = java.util.Collections.unmodifiableList(text_);
-            bitField0_ = (bitField0_ & ~0x00000001);
-          }
-          result.text_ = text_;
-        } else {
-          result.text_ = textBuilder_.build();
-        }
-      }
-
-      private void buildPartial0(food.menu.v1.FoodMenu.TextField result) {
-        int from_bitField0_ = bitField0_;
-      }
-
-      @java.lang.Override
-      public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof food.menu.v1.FoodMenu.TextField) {
-          return mergeFrom((food.menu.v1.FoodMenu.TextField)other);
-        } else {
-          super.mergeFrom(other);
-          return this;
-        }
-      }
-
-      public Builder mergeFrom(food.menu.v1.FoodMenu.TextField other) {
-        if (other == food.menu.v1.FoodMenu.TextField.getDefaultInstance()) return this;
-        if (textBuilder_ == null) {
-          if (!other.text_.isEmpty()) {
-            if (text_.isEmpty()) {
-              text_ = other.text_;
-              bitField0_ = (bitField0_ & ~0x00000001);
-            } else {
-              ensureTextIsMutable();
-              text_.addAll(other.text_);
-            }
-            onChanged();
-          }
-        } else {
-          if (!other.text_.isEmpty()) {
-            if (textBuilder_.isEmpty()) {
-              textBuilder_.dispose();
-              textBuilder_ = null;
-              text_ = other.text_;
-              bitField0_ = (bitField0_ & ~0x00000001);
-              textBuilder_ = 
-                com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ?
-                   getTextFieldBuilder() : null;
-            } else {
-              textBuilder_.addAllMessages(other.text_);
-            }
-          }
-        }
-        this.mergeUnknownFields(other.getUnknownFields());
-        onChanged();
-        return this;
-      }
-
-      @java.lang.Override
-      public final boolean isInitialized() {
-        return true;
-      }
-
-      @java.lang.Override
-      public Builder mergeFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws java.io.IOException {
-        if (extensionRegistry == null) {
-          throw new java.lang.NullPointerException();
-        }
-        try {
-          boolean done = false;
-          while (!done) {
-            int tag = input.readTag();
-            switch (tag) {
-              case 0:
-                done = true;
-                break;
-              case 10: {
-                com.google.type.LocalizedText m =
-                    input.readMessage(
-                        com.google.type.LocalizedText.parser(),
-                        extensionRegistry);
-                if (textBuilder_ == null) {
-                  ensureTextIsMutable();
-                  text_.add(m);
-                } else {
-                  textBuilder_.addMessage(m);
-                }
-                break;
-              } // case 10
-              default: {
-                if (!super.parseUnknownField(input, extensionRegistry, tag)) {
-                  done = true; // was an endgroup tag
-                }
-                break;
-              } // default:
-            } // switch (tag)
-          } // while (!done)
-        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          throw e.unwrapIOException();
-        } finally {
-          onChanged();
-        } // finally
-        return this;
-      }
-      private int bitField0_;
-
-      private java.util.List<com.google.type.LocalizedText> text_ =
-        java.util.Collections.emptyList();
-      private void ensureTextIsMutable() {
-        if (!((bitField0_ & 0x00000001) != 0)) {
-          text_ = new java.util.ArrayList<com.google.type.LocalizedText>(text_);
-          bitField0_ |= 0x00000001;
-         }
-      }
-
-      private com.google.protobuf.RepeatedFieldBuilderV3<
-          com.google.type.LocalizedText, com.google.type.LocalizedText.Builder, com.google.type.LocalizedTextOrBuilder> textBuilder_;
-
-      /**
-       * <pre>
-       * Per-locale text values.
-       *
-       * If there is only one desired locale support, then the language_code within
-       * each text is not required to be set and the language will be inferred from
-       * the default language of the menu.
-       *
-       * If there are multiple texts across different locales, then the
-       * language_code must be set for each text. The first text in the list is
-       * considered the preferred representation.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated .google.type.LocalizedText text = 1;</code>
-       */
-      public java.util.List<com.google.type.LocalizedText> getTextList() {
-        if (textBuilder_ == null) {
-          return java.util.Collections.unmodifiableList(text_);
-        } else {
-          return textBuilder_.getMessageList();
-        }
-      }
-      /**
-       * <pre>
-       * Per-locale text values.
-       *
-       * If there is only one desired locale support, then the language_code within
-       * each text is not required to be set and the language will be inferred from
-       * the default language of the menu.
-       *
-       * If there are multiple texts across different locales, then the
-       * language_code must be set for each text. The first text in the list is
-       * considered the preferred representation.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated .google.type.LocalizedText text = 1;</code>
-       */
-      public int getTextCount() {
-        if (textBuilder_ == null) {
-          return text_.size();
-        } else {
-          return textBuilder_.getCount();
-        }
-      }
-      /**
-       * <pre>
-       * Per-locale text values.
-       *
-       * If there is only one desired locale support, then the language_code within
-       * each text is not required to be set and the language will be inferred from
-       * the default language of the menu.
-       *
-       * If there are multiple texts across different locales, then the
-       * language_code must be set for each text. The first text in the list is
-       * considered the preferred representation.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated .google.type.LocalizedText text = 1;</code>
-       */
-      public com.google.type.LocalizedText getText(int index) {
-        if (textBuilder_ == null) {
-          return text_.get(index);
-        } else {
-          return textBuilder_.getMessage(index);
-        }
-      }
-      /**
-       * <pre>
-       * Per-locale text values.
-       *
-       * If there is only one desired locale support, then the language_code within
-       * each text is not required to be set and the language will be inferred from
-       * the default language of the menu.
-       *
-       * If there are multiple texts across different locales, then the
-       * language_code must be set for each text. The first text in the list is
-       * considered the preferred representation.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated .google.type.LocalizedText text = 1;</code>
-       */
-      public Builder setText(
-          int index, com.google.type.LocalizedText value) {
-        if (textBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          ensureTextIsMutable();
-          text_.set(index, value);
-          onChanged();
-        } else {
-          textBuilder_.setMessage(index, value);
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Per-locale text values.
-       *
-       * If there is only one desired locale support, then the language_code within
-       * each text is not required to be set and the language will be inferred from
-       * the default language of the menu.
-       *
-       * If there are multiple texts across different locales, then the
-       * language_code must be set for each text. The first text in the list is
-       * considered the preferred representation.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated .google.type.LocalizedText text = 1;</code>
-       */
-      public Builder setText(
-          int index, com.google.type.LocalizedText.Builder builderForValue) {
-        if (textBuilder_ == null) {
-          ensureTextIsMutable();
-          text_.set(index, builderForValue.build());
-          onChanged();
-        } else {
-          textBuilder_.setMessage(index, builderForValue.build());
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Per-locale text values.
-       *
-       * If there is only one desired locale support, then the language_code within
-       * each text is not required to be set and the language will be inferred from
-       * the default language of the menu.
-       *
-       * If there are multiple texts across different locales, then the
-       * language_code must be set for each text. The first text in the list is
-       * considered the preferred representation.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated .google.type.LocalizedText text = 1;</code>
-       */
-      public Builder addText(com.google.type.LocalizedText value) {
-        if (textBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          ensureTextIsMutable();
-          text_.add(value);
-          onChanged();
-        } else {
-          textBuilder_.addMessage(value);
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Per-locale text values.
-       *
-       * If there is only one desired locale support, then the language_code within
-       * each text is not required to be set and the language will be inferred from
-       * the default language of the menu.
-       *
-       * If there are multiple texts across different locales, then the
-       * language_code must be set for each text. The first text in the list is
-       * considered the preferred representation.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated .google.type.LocalizedText text = 1;</code>
-       */
-      public Builder addText(
-          int index, com.google.type.LocalizedText value) {
-        if (textBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          ensureTextIsMutable();
-          text_.add(index, value);
-          onChanged();
-        } else {
-          textBuilder_.addMessage(index, value);
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Per-locale text values.
-       *
-       * If there is only one desired locale support, then the language_code within
-       * each text is not required to be set and the language will be inferred from
-       * the default language of the menu.
-       *
-       * If there are multiple texts across different locales, then the
-       * language_code must be set for each text. The first text in the list is
-       * considered the preferred representation.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated .google.type.LocalizedText text = 1;</code>
-       */
-      public Builder addText(
-          com.google.type.LocalizedText.Builder builderForValue) {
-        if (textBuilder_ == null) {
-          ensureTextIsMutable();
-          text_.add(builderForValue.build());
-          onChanged();
-        } else {
-          textBuilder_.addMessage(builderForValue.build());
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Per-locale text values.
-       *
-       * If there is only one desired locale support, then the language_code within
-       * each text is not required to be set and the language will be inferred from
-       * the default language of the menu.
-       *
-       * If there are multiple texts across different locales, then the
-       * language_code must be set for each text. The first text in the list is
-       * considered the preferred representation.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated .google.type.LocalizedText text = 1;</code>
-       */
-      public Builder addText(
-          int index, com.google.type.LocalizedText.Builder builderForValue) {
-        if (textBuilder_ == null) {
-          ensureTextIsMutable();
-          text_.add(index, builderForValue.build());
-          onChanged();
-        } else {
-          textBuilder_.addMessage(index, builderForValue.build());
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Per-locale text values.
-       *
-       * If there is only one desired locale support, then the language_code within
-       * each text is not required to be set and the language will be inferred from
-       * the default language of the menu.
-       *
-       * If there are multiple texts across different locales, then the
-       * language_code must be set for each text. The first text in the list is
-       * considered the preferred representation.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated .google.type.LocalizedText text = 1;</code>
-       */
-      public Builder addAllText(
-          java.lang.Iterable<? extends com.google.type.LocalizedText> values) {
-        if (textBuilder_ == null) {
-          ensureTextIsMutable();
-          com.google.protobuf.AbstractMessageLite.Builder.addAll(
-              values, text_);
-          onChanged();
-        } else {
-          textBuilder_.addAllMessages(values);
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Per-locale text values.
-       *
-       * If there is only one desired locale support, then the language_code within
-       * each text is not required to be set and the language will be inferred from
-       * the default language of the menu.
-       *
-       * If there are multiple texts across different locales, then the
-       * language_code must be set for each text. The first text in the list is
-       * considered the preferred representation.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated .google.type.LocalizedText text = 1;</code>
-       */
-      public Builder clearText() {
-        if (textBuilder_ == null) {
-          text_ = java.util.Collections.emptyList();
-          bitField0_ = (bitField0_ & ~0x00000001);
-          onChanged();
-        } else {
-          textBuilder_.clear();
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Per-locale text values.
-       *
-       * If there is only one desired locale support, then the language_code within
-       * each text is not required to be set and the language will be inferred from
-       * the default language of the menu.
-       *
-       * If there are multiple texts across different locales, then the
-       * language_code must be set for each text. The first text in the list is
-       * considered the preferred representation.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated .google.type.LocalizedText text = 1;</code>
-       */
-      public Builder removeText(int index) {
-        if (textBuilder_ == null) {
-          ensureTextIsMutable();
-          text_.remove(index);
-          onChanged();
-        } else {
-          textBuilder_.remove(index);
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * Per-locale text values.
-       *
-       * If there is only one desired locale support, then the language_code within
-       * each text is not required to be set and the language will be inferred from
-       * the default language of the menu.
-       *
-       * If there are multiple texts across different locales, then the
-       * language_code must be set for each text. The first text in the list is
-       * considered the preferred representation.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated .google.type.LocalizedText text = 1;</code>
-       */
-      public com.google.type.LocalizedText.Builder getTextBuilder(
-          int index) {
-        return getTextFieldBuilder().getBuilder(index);
-      }
-      /**
-       * <pre>
-       * Per-locale text values.
-       *
-       * If there is only one desired locale support, then the language_code within
-       * each text is not required to be set and the language will be inferred from
-       * the default language of the menu.
-       *
-       * If there are multiple texts across different locales, then the
-       * language_code must be set for each text. The first text in the list is
-       * considered the preferred representation.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated .google.type.LocalizedText text = 1;</code>
-       */
-      public com.google.type.LocalizedTextOrBuilder getTextOrBuilder(
-          int index) {
-        if (textBuilder_ == null) {
-          return text_.get(index);  } else {
-          return textBuilder_.getMessageOrBuilder(index);
-        }
-      }
-      /**
-       * <pre>
-       * Per-locale text values.
-       *
-       * If there is only one desired locale support, then the language_code within
-       * each text is not required to be set and the language will be inferred from
-       * the default language of the menu.
-       *
-       * If there are multiple texts across different locales, then the
-       * language_code must be set for each text. The first text in the list is
-       * considered the preferred representation.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated .google.type.LocalizedText text = 1;</code>
-       */
-      public java.util.List<? extends com.google.type.LocalizedTextOrBuilder> 
-           getTextOrBuilderList() {
-        if (textBuilder_ != null) {
-          return textBuilder_.getMessageOrBuilderList();
-        } else {
-          return java.util.Collections.unmodifiableList(text_);
-        }
-      }
-      /**
-       * <pre>
-       * Per-locale text values.
-       *
-       * If there is only one desired locale support, then the language_code within
-       * each text is not required to be set and the language will be inferred from
-       * the default language of the menu.
-       *
-       * If there are multiple texts across different locales, then the
-       * language_code must be set for each text. The first text in the list is
-       * considered the preferred representation.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated .google.type.LocalizedText text = 1;</code>
-       */
-      public com.google.type.LocalizedText.Builder addTextBuilder() {
-        return getTextFieldBuilder().addBuilder(
-            com.google.type.LocalizedText.getDefaultInstance());
-      }
-      /**
-       * <pre>
-       * Per-locale text values.
-       *
-       * If there is only one desired locale support, then the language_code within
-       * each text is not required to be set and the language will be inferred from
-       * the default language of the menu.
-       *
-       * If there are multiple texts across different locales, then the
-       * language_code must be set for each text. The first text in the list is
-       * considered the preferred representation.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated .google.type.LocalizedText text = 1;</code>
-       */
-      public com.google.type.LocalizedText.Builder addTextBuilder(
-          int index) {
-        return getTextFieldBuilder().addBuilder(
-            index, com.google.type.LocalizedText.getDefaultInstance());
-      }
-      /**
-       * <pre>
-       * Per-locale text values.
-       *
-       * If there is only one desired locale support, then the language_code within
-       * each text is not required to be set and the language will be inferred from
-       * the default language of the menu.
-       *
-       * If there are multiple texts across different locales, then the
-       * language_code must be set for each text. The first text in the list is
-       * considered the preferred representation.
-       * Required.
-       * </pre>
-       *
-       * <code>repeated .google.type.LocalizedText text = 1;</code>
-       */
-      public java.util.List<com.google.type.LocalizedText.Builder> 
-           getTextBuilderList() {
-        return getTextFieldBuilder().getBuilderList();
-      }
-      private com.google.protobuf.RepeatedFieldBuilderV3<
-          com.google.type.LocalizedText, com.google.type.LocalizedText.Builder, com.google.type.LocalizedTextOrBuilder> 
-          getTextFieldBuilder() {
-        if (textBuilder_ == null) {
-          textBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3<
-              com.google.type.LocalizedText, com.google.type.LocalizedText.Builder, com.google.type.LocalizedTextOrBuilder>(
-                  text_,
-                  ((bitField0_ & 0x00000001) != 0),
-                  getParentForChildren(),
-                  isClean());
-          text_ = null;
-        }
-        return textBuilder_;
-      }
-      @java.lang.Override
-      public final Builder setUnknownFields(
-          final com.google.protobuf.UnknownFieldSet unknownFields) {
-        return super.setUnknownFields(unknownFields);
-      }
-
-      @java.lang.Override
-      public final Builder mergeUnknownFields(
-          final com.google.protobuf.UnknownFieldSet unknownFields) {
-        return super.mergeUnknownFields(unknownFields);
-      }
-
-
-      // @@protoc_insertion_point(builder_scope:food.menu.v1.TextField)
-    }
-
-    // @@protoc_insertion_point(class_scope:food.menu.v1.TextField)
-    private static final food.menu.v1.FoodMenu.TextField DEFAULT_INSTANCE;
-    static {
-      DEFAULT_INSTANCE = new food.menu.v1.FoodMenu.TextField();
-    }
-
-    public static food.menu.v1.FoodMenu.TextField getDefaultInstance() {
-      return DEFAULT_INSTANCE;
-    }
-
-    private static final com.google.protobuf.Parser<TextField>
-        PARSER = new com.google.protobuf.AbstractParser<TextField>() {
-      @java.lang.Override
-      public TextField parsePartialFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws com.google.protobuf.InvalidProtocolBufferException {
-        Builder builder = newBuilder();
-        try {
-          builder.mergeFrom(input, extensionRegistry);
-        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          throw e.setUnfinishedMessage(builder.buildPartial());
-        } catch (com.google.protobuf.UninitializedMessageException e) {
-          throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
-        } catch (java.io.IOException e) {
-          throw new com.google.protobuf.InvalidProtocolBufferException(e)
-              .setUnfinishedMessage(builder.buildPartial());
-        }
-        return builder.buildPartial();
-      }
-    };
-
-    public static com.google.protobuf.Parser<TextField> parser() {
-      return PARSER;
-    }
-
-    @java.lang.Override
-    public com.google.protobuf.Parser<TextField> getParserForType() {
-      return PARSER;
-    }
-
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.TextField getDefaultInstanceForType() {
-      return DEFAULT_INSTANCE;
-    }
-
-  }
-
-  public interface ImageOrBuilder extends
-      // @@protoc_insertion_point(interface_extends:food.menu.v1.Image)
-      com.google.protobuf.MessageOrBuilder {
-
-    /**
-     * <pre>
-     * URL containing the raw pixels of the image.
-     * Required.
-     * </pre>
-     *
-     * <code>string uri = 1;</code>
-     * @return The uri.
-     */
-    java.lang.String getUri();
-    /**
-     * <pre>
-     * URL containing the raw pixels of the image.
-     * Required.
-     * </pre>
-     *
-     * <code>string uri = 1;</code>
-     * @return The bytes for uri.
-     */
-    com.google.protobuf.ByteString
-        getUriBytes();
-  }
-  /**
-   * <pre>
-   * Represents an image associated with a menu entity.
-   * </pre>
-   *
-   * Protobuf type {@code food.menu.v1.Image}
-   */
-  public static final class Image extends
-      com.google.protobuf.GeneratedMessageV3 implements
-      // @@protoc_insertion_point(message_implements:food.menu.v1.Image)
-      ImageOrBuilder {
-  private static final long serialVersionUID = 0L;
-    // Use Image.newBuilder() to construct.
-    private Image(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
-      super(builder);
-    }
-    private Image() {
-      uri_ = "";
-    }
-
-    @java.lang.Override
-    @SuppressWarnings({"unused"})
-    protected java.lang.Object newInstance(
-        UnusedPrivateParameter unused) {
-      return new Image();
-    }
-
-    public static final com.google.protobuf.Descriptors.Descriptor
-        getDescriptor() {
-      return food.menu.v1.FoodMenu.internal_static_food_menu_v1_Image_descriptor;
-    }
-
-    @java.lang.Override
-    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-        internalGetFieldAccessorTable() {
-      return food.menu.v1.FoodMenu.internal_static_food_menu_v1_Image_fieldAccessorTable
-          .ensureFieldAccessorsInitialized(
-              food.menu.v1.FoodMenu.Image.class, food.menu.v1.FoodMenu.Image.Builder.class);
-    }
-
-    public static final int URI_FIELD_NUMBER = 1;
-    @SuppressWarnings("serial")
-    private volatile java.lang.Object uri_ = "";
-    /**
-     * <pre>
-     * URL containing the raw pixels of the image.
-     * Required.
-     * </pre>
-     *
-     * <code>string uri = 1;</code>
-     * @return The uri.
-     */
-    @java.lang.Override
-    public java.lang.String getUri() {
-      java.lang.Object ref = uri_;
-      if (ref instanceof java.lang.String) {
-        return (java.lang.String) ref;
-      } else {
-        com.google.protobuf.ByteString bs = 
-            (com.google.protobuf.ByteString) ref;
-        java.lang.String s = bs.toStringUtf8();
-        uri_ = s;
-        return s;
-      }
-    }
-    /**
-     * <pre>
-     * URL containing the raw pixels of the image.
-     * Required.
-     * </pre>
-     *
-     * <code>string uri = 1;</code>
-     * @return The bytes for uri.
-     */
-    @java.lang.Override
-    public com.google.protobuf.ByteString
-        getUriBytes() {
-      java.lang.Object ref = uri_;
-      if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
-            com.google.protobuf.ByteString.copyFromUtf8(
-                (java.lang.String) ref);
-        uri_ = b;
-        return b;
-      } else {
-        return (com.google.protobuf.ByteString) ref;
-      }
-    }
-
-    private byte memoizedIsInitialized = -1;
-    @java.lang.Override
-    public final boolean isInitialized() {
-      byte isInitialized = memoizedIsInitialized;
-      if (isInitialized == 1) return true;
-      if (isInitialized == 0) return false;
-
-      memoizedIsInitialized = 1;
-      return true;
-    }
-
-    @java.lang.Override
-    public void writeTo(com.google.protobuf.CodedOutputStream output)
-                        throws java.io.IOException {
-      if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(uri_)) {
-        com.google.protobuf.GeneratedMessageV3.writeString(output, 1, uri_);
-      }
-      getUnknownFields().writeTo(output);
-    }
-
-    @java.lang.Override
-    public int getSerializedSize() {
-      int size = memoizedSize;
-      if (size != -1) return size;
-
-      size = 0;
-      if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(uri_)) {
-        size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, uri_);
-      }
-      size += getUnknownFields().getSerializedSize();
-      memoizedSize = size;
-      return size;
-    }
-
-    @java.lang.Override
-    public boolean equals(final java.lang.Object obj) {
-      if (obj == this) {
-       return true;
-      }
-      if (!(obj instanceof food.menu.v1.FoodMenu.Image)) {
-        return super.equals(obj);
-      }
-      food.menu.v1.FoodMenu.Image other = (food.menu.v1.FoodMenu.Image) obj;
-
-      if (!getUri()
-          .equals(other.getUri())) return false;
-      if (!getUnknownFields().equals(other.getUnknownFields())) return false;
-      return true;
-    }
-
-    @java.lang.Override
-    public int hashCode() {
-      if (memoizedHashCode != 0) {
-        return memoizedHashCode;
-      }
-      int hash = 41;
-      hash = (19 * hash) + getDescriptor().hashCode();
-      hash = (37 * hash) + URI_FIELD_NUMBER;
-      hash = (53 * hash) + getUri().hashCode();
-      hash = (29 * hash) + getUnknownFields().hashCode();
-      memoizedHashCode = hash;
-      return hash;
-    }
-
-    public static food.menu.v1.FoodMenu.Image parseFrom(
-        java.nio.ByteBuffer data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.Image parseFrom(
-        java.nio.ByteBuffer data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.Image parseFrom(
-        com.google.protobuf.ByteString data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.Image parseFrom(
-        com.google.protobuf.ByteString data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.Image parseFrom(byte[] data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.Image parseFrom(
-        byte[] data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.Image parseFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.Image parseFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.Image parseDelimitedFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseDelimitedWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.Image parseDelimitedFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.Image parseFrom(
-        com.google.protobuf.CodedInputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.Image parseFrom(
-        com.google.protobuf.CodedInputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input, extensionRegistry);
-    }
-
-    @java.lang.Override
-    public Builder newBuilderForType() { return newBuilder(); }
-    public static Builder newBuilder() {
-      return DEFAULT_INSTANCE.toBuilder();
-    }
-    public static Builder newBuilder(food.menu.v1.FoodMenu.Image prototype) {
-      return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
-    }
-    @java.lang.Override
-    public Builder toBuilder() {
-      return this == DEFAULT_INSTANCE
-          ? new Builder() : new Builder().mergeFrom(this);
-    }
-
-    @java.lang.Override
-    protected Builder newBuilderForType(
-        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-      Builder builder = new Builder(parent);
-      return builder;
-    }
-    /**
-     * <pre>
-     * Represents an image associated with a menu entity.
-     * </pre>
-     *
-     * Protobuf type {@code food.menu.v1.Image}
-     */
-    public static final class Builder extends
-        com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
-        // @@protoc_insertion_point(builder_implements:food.menu.v1.Image)
-        food.menu.v1.FoodMenu.ImageOrBuilder {
-      public static final com.google.protobuf.Descriptors.Descriptor
-          getDescriptor() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_Image_descriptor;
-      }
-
-      @java.lang.Override
-      protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-          internalGetFieldAccessorTable() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_Image_fieldAccessorTable
-            .ensureFieldAccessorsInitialized(
-                food.menu.v1.FoodMenu.Image.class, food.menu.v1.FoodMenu.Image.Builder.class);
-      }
-
-      // Construct using food.menu.v1.FoodMenu.Image.newBuilder()
-      private Builder() {
-
-      }
-
-      private Builder(
-          com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-        super(parent);
-
-      }
-      @java.lang.Override
-      public Builder clear() {
-        super.clear();
-        bitField0_ = 0;
-        uri_ = "";
-        return this;
-      }
-
-      @java.lang.Override
-      public com.google.protobuf.Descriptors.Descriptor
-          getDescriptorForType() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_Image_descriptor;
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.Image getDefaultInstanceForType() {
-        return food.menu.v1.FoodMenu.Image.getDefaultInstance();
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.Image build() {
-        food.menu.v1.FoodMenu.Image result = buildPartial();
-        if (!result.isInitialized()) {
-          throw newUninitializedMessageException(result);
-        }
-        return result;
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.Image buildPartial() {
-        food.menu.v1.FoodMenu.Image result = new food.menu.v1.FoodMenu.Image(this);
-        if (bitField0_ != 0) { buildPartial0(result); }
-        onBuilt();
-        return result;
-      }
-
-      private void buildPartial0(food.menu.v1.FoodMenu.Image result) {
-        int from_bitField0_ = bitField0_;
-        if (((from_bitField0_ & 0x00000001) != 0)) {
-          result.uri_ = uri_;
-        }
-      }
-
-      @java.lang.Override
-      public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof food.menu.v1.FoodMenu.Image) {
-          return mergeFrom((food.menu.v1.FoodMenu.Image)other);
-        } else {
-          super.mergeFrom(other);
-          return this;
-        }
-      }
-
-      public Builder mergeFrom(food.menu.v1.FoodMenu.Image other) {
-        if (other == food.menu.v1.FoodMenu.Image.getDefaultInstance()) return this;
-        if (!other.getUri().isEmpty()) {
-          uri_ = other.uri_;
-          bitField0_ |= 0x00000001;
-          onChanged();
-        }
-        this.mergeUnknownFields(other.getUnknownFields());
-        onChanged();
-        return this;
-      }
-
-      @java.lang.Override
-      public final boolean isInitialized() {
-        return true;
-      }
-
-      @java.lang.Override
-      public Builder mergeFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws java.io.IOException {
-        if (extensionRegistry == null) {
-          throw new java.lang.NullPointerException();
-        }
-        try {
-          boolean done = false;
-          while (!done) {
-            int tag = input.readTag();
-            switch (tag) {
-              case 0:
-                done = true;
-                break;
-              case 10: {
-                uri_ = input.readStringRequireUtf8();
-                bitField0_ |= 0x00000001;
-                break;
-              } // case 10
-              default: {
-                if (!super.parseUnknownField(input, extensionRegistry, tag)) {
-                  done = true; // was an endgroup tag
-                }
-                break;
-              } // default:
-            } // switch (tag)
-          } // while (!done)
-        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          throw e.unwrapIOException();
-        } finally {
-          onChanged();
-        } // finally
-        return this;
-      }
-      private int bitField0_;
-
-      private java.lang.Object uri_ = "";
-      /**
-       * <pre>
-       * URL containing the raw pixels of the image.
-       * Required.
-       * </pre>
-       *
-       * <code>string uri = 1;</code>
-       * @return The uri.
-       */
-      public java.lang.String getUri() {
-        java.lang.Object ref = uri_;
-        if (!(ref instanceof java.lang.String)) {
-          com.google.protobuf.ByteString bs =
-              (com.google.protobuf.ByteString) ref;
-          java.lang.String s = bs.toStringUtf8();
-          uri_ = s;
-          return s;
-        } else {
-          return (java.lang.String) ref;
-        }
-      }
-      /**
-       * <pre>
-       * URL containing the raw pixels of the image.
-       * Required.
-       * </pre>
-       *
-       * <code>string uri = 1;</code>
-       * @return The bytes for uri.
-       */
-      public com.google.protobuf.ByteString
-          getUriBytes() {
-        java.lang.Object ref = uri_;
-        if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
-              com.google.protobuf.ByteString.copyFromUtf8(
-                  (java.lang.String) ref);
-          uri_ = b;
-          return b;
-        } else {
-          return (com.google.protobuf.ByteString) ref;
-        }
-      }
-      /**
-       * <pre>
-       * URL containing the raw pixels of the image.
-       * Required.
-       * </pre>
-       *
-       * <code>string uri = 1;</code>
-       * @param value The uri to set.
-       * @return This builder for chaining.
-       */
-      public Builder setUri(
-          java.lang.String value) {
-        if (value == null) { throw new NullPointerException(); }
-        uri_ = value;
-        bitField0_ |= 0x00000001;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * URL containing the raw pixels of the image.
-       * Required.
-       * </pre>
-       *
-       * <code>string uri = 1;</code>
-       * @return This builder for chaining.
-       */
-      public Builder clearUri() {
-        uri_ = getDefaultInstance().getUri();
-        bitField0_ = (bitField0_ & ~0x00000001);
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * URL containing the raw pixels of the image.
-       * Required.
-       * </pre>
-       *
-       * <code>string uri = 1;</code>
-       * @param value The bytes for uri to set.
-       * @return This builder for chaining.
-       */
-      public Builder setUriBytes(
-          com.google.protobuf.ByteString value) {
-        if (value == null) { throw new NullPointerException(); }
-        checkByteStringIsUtf8(value);
-        uri_ = value;
-        bitField0_ |= 0x00000001;
-        onChanged();
-        return this;
-      }
-      @java.lang.Override
-      public final Builder setUnknownFields(
-          final com.google.protobuf.UnknownFieldSet unknownFields) {
-        return super.setUnknownFields(unknownFields);
-      }
-
-      @java.lang.Override
-      public final Builder mergeUnknownFields(
-          final com.google.protobuf.UnknownFieldSet unknownFields) {
-        return super.mergeUnknownFields(unknownFields);
-      }
-
-
-      // @@protoc_insertion_point(builder_scope:food.menu.v1.Image)
-    }
-
-    // @@protoc_insertion_point(class_scope:food.menu.v1.Image)
-    private static final food.menu.v1.FoodMenu.Image DEFAULT_INSTANCE;
-    static {
-      DEFAULT_INSTANCE = new food.menu.v1.FoodMenu.Image();
-    }
-
-    public static food.menu.v1.FoodMenu.Image getDefaultInstance() {
-      return DEFAULT_INSTANCE;
-    }
-
-    private static final com.google.protobuf.Parser<Image>
-        PARSER = new com.google.protobuf.AbstractParser<Image>() {
-      @java.lang.Override
-      public Image parsePartialFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws com.google.protobuf.InvalidProtocolBufferException {
-        Builder builder = newBuilder();
-        try {
-          builder.mergeFrom(input, extensionRegistry);
-        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          throw e.setUnfinishedMessage(builder.buildPartial());
-        } catch (com.google.protobuf.UninitializedMessageException e) {
-          throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
-        } catch (java.io.IOException e) {
-          throw new com.google.protobuf.InvalidProtocolBufferException(e)
-              .setUnfinishedMessage(builder.buildPartial());
-        }
-        return builder.buildPartial();
-      }
-    };
-
-    public static com.google.protobuf.Parser<Image> parser() {
-      return PARSER;
-    }
-
-    @java.lang.Override
-    public com.google.protobuf.Parser<Image> getParserForType() {
-      return PARSER;
-    }
-
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.Image getDefaultInstanceForType() {
-      return DEFAULT_INSTANCE;
-    }
-
-  }
-
-  public interface MenuItemOptionPropertyOrBuilder extends
-      // @@protoc_insertion_point(interface_extends:food.menu.v1.MenuItemOptionProperty)
-      com.google.protobuf.MessageOrBuilder {
-
-    /**
-     * <pre>
-     * The type of this option property.
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.MenuItemOptionProperty.PropertyType property_type = 1;</code>
-     * @return The enum numeric value on the wire for propertyType.
-     */
-    int getPropertyTypeValue();
-    /**
-     * <pre>
-     * The type of this option property.
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.MenuItemOptionProperty.PropertyType property_type = 1;</code>
-     * @return The propertyType.
-     */
-    food.menu.v1.FoodMenu.MenuItemOptionProperty.PropertyType getPropertyType();
-
-    /**
-     * <pre>
-     * A well-defined value for the option property. Currently only expected
-     * if the property_type is PIZZA_SIDE.
-     * </pre>
-     *
-     * <code>.food.menu.v1.MenuItemOptionProperty.PropertyValue property_val = 2;</code>
-     * @return Whether the propertyVal field is set.
-     */
-    boolean hasPropertyVal();
-    /**
-     * <pre>
-     * A well-defined value for the option property. Currently only expected
-     * if the property_type is PIZZA_SIDE.
-     * </pre>
-     *
-     * <code>.food.menu.v1.MenuItemOptionProperty.PropertyValue property_val = 2;</code>
-     * @return The enum numeric value on the wire for propertyVal.
-     */
-    int getPropertyValValue();
-    /**
-     * <pre>
-     * A well-defined value for the option property. Currently only expected
-     * if the property_type is PIZZA_SIDE.
-     * </pre>
-     *
-     * <code>.food.menu.v1.MenuItemOptionProperty.PropertyValue property_val = 2;</code>
-     * @return The propertyVal.
-     */
-    food.menu.v1.FoodMenu.MenuItemOptionProperty.PropertyValue getPropertyVal();
-
-    /**
-     * <pre>
-     * A free-form text for the value of the property. Expected for
-     * property_type OPTION and SIZE.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField text_val = 3;</code>
-     * @return Whether the textVal field is set.
-     */
-    boolean hasTextVal();
-    /**
-     * <pre>
-     * A free-form text for the value of the property. Expected for
-     * property_type OPTION and SIZE.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField text_val = 3;</code>
-     * @return The textVal.
-     */
-    food.menu.v1.FoodMenu.TextField getTextVal();
-    /**
-     * <pre>
-     * A free-form text for the value of the property. Expected for
-     * property_type OPTION and SIZE.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField text_val = 3;</code>
-     */
-    food.menu.v1.FoodMenu.TextFieldOrBuilder getTextValOrBuilder();
-
-    food.menu.v1.FoodMenu.MenuItemOptionProperty.ValueCase getValueCase();
-  }
-  /**
-   * <pre>
-   * Describes the property of a menu item option and its value.
-   * </pre>
-   *
-   * Protobuf type {@code food.menu.v1.MenuItemOptionProperty}
-   */
-  public static final class MenuItemOptionProperty extends
-      com.google.protobuf.GeneratedMessageV3 implements
-      // @@protoc_insertion_point(message_implements:food.menu.v1.MenuItemOptionProperty)
-      MenuItemOptionPropertyOrBuilder {
-  private static final long serialVersionUID = 0L;
-    // Use MenuItemOptionProperty.newBuilder() to construct.
-    private MenuItemOptionProperty(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
-      super(builder);
-    }
-    private MenuItemOptionProperty() {
-      propertyType_ = 0;
-    }
-
-    @java.lang.Override
-    @SuppressWarnings({"unused"})
-    protected java.lang.Object newInstance(
-        UnusedPrivateParameter unused) {
-      return new MenuItemOptionProperty();
-    }
-
-    public static final com.google.protobuf.Descriptors.Descriptor
-        getDescriptor() {
-      return food.menu.v1.FoodMenu.internal_static_food_menu_v1_MenuItemOptionProperty_descriptor;
-    }
-
-    @java.lang.Override
-    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-        internalGetFieldAccessorTable() {
-      return food.menu.v1.FoodMenu.internal_static_food_menu_v1_MenuItemOptionProperty_fieldAccessorTable
-          .ensureFieldAccessorsInitialized(
-              food.menu.v1.FoodMenu.MenuItemOptionProperty.class, food.menu.v1.FoodMenu.MenuItemOptionProperty.Builder.class);
-    }
-
-    /**
-     * <pre>
-     * Types of property that the option is for.
-     * </pre>
-     *
-     * Protobuf enum {@code food.menu.v1.MenuItemOptionProperty.PropertyType}
-     */
-    public enum PropertyType
-        implements com.google.protobuf.ProtocolMessageEnum {
-      /**
-       * <pre>
-       * Do not use. The property type is not explicitly specified.
-       * </pre>
-       *
-       * <code>UNKNOWN_PROPERTY_TYPE = 0;</code>
-       */
-      UNKNOWN_PROPERTY_TYPE(0),
-      /**
-       * <pre>
-       * A generic menu item option property, which is not one of the more
-       * specific types below. Use this if the property is not of type
-       * SIZE or PIZZA_SIDE.
-       * </pre>
-       *
-       * <code>OPTION = 1;</code>
-       */
-      OPTION(1),
-      /**
-       * <pre>
-       * Denotes the menu item option property of size (e.g. small, medium, or
-       * large).
-       * </pre>
-       *
-       * <code>SIZE = 2;</code>
-       */
-      SIZE(2),
-      /**
-       * <pre>
-       * Property specific to pizzas. For example: this MenuItemOption is only
-       * valid for a portion/whole pizza, such as mushroom toppings on the left
-       * side, right side, or whole pizza).
-       * </pre>
-       *
-       * <code>PIZZA_SIDE = 3;</code>
-       */
-      PIZZA_SIDE(3),
-      UNRECOGNIZED(-1),
-      ;
-
-      /**
-       * <pre>
-       * Do not use. The property type is not explicitly specified.
-       * </pre>
-       *
-       * <code>UNKNOWN_PROPERTY_TYPE = 0;</code>
-       */
-      public static final int UNKNOWN_PROPERTY_TYPE_VALUE = 0;
-      /**
-       * <pre>
-       * A generic menu item option property, which is not one of the more
-       * specific types below. Use this if the property is not of type
-       * SIZE or PIZZA_SIDE.
-       * </pre>
-       *
-       * <code>OPTION = 1;</code>
-       */
-      public static final int OPTION_VALUE = 1;
-      /**
-       * <pre>
-       * Denotes the menu item option property of size (e.g. small, medium, or
-       * large).
-       * </pre>
-       *
-       * <code>SIZE = 2;</code>
-       */
-      public static final int SIZE_VALUE = 2;
-      /**
-       * <pre>
-       * Property specific to pizzas. For example: this MenuItemOption is only
-       * valid for a portion/whole pizza, such as mushroom toppings on the left
-       * side, right side, or whole pizza).
-       * </pre>
-       *
-       * <code>PIZZA_SIDE = 3;</code>
-       */
-      public static final int PIZZA_SIDE_VALUE = 3;
-
-
-      public final int getNumber() {
-        if (this == UNRECOGNIZED) {
-          throw new java.lang.IllegalArgumentException(
-              "Can't get the number of an unknown enum value.");
-        }
-        return value;
-      }
-
-      /**
-       * @param value The numeric wire value of the corresponding enum entry.
-       * @return The enum associated with the given numeric wire value.
-       * @deprecated Use {@link #forNumber(int)} instead.
-       */
-      @java.lang.Deprecated
-      public static PropertyType valueOf(int value) {
-        return forNumber(value);
-      }
-
-      /**
-       * @param value The numeric wire value of the corresponding enum entry.
-       * @return The enum associated with the given numeric wire value.
-       */
-      public static PropertyType forNumber(int value) {
-        switch (value) {
-          case 0: return UNKNOWN_PROPERTY_TYPE;
-          case 1: return OPTION;
-          case 2: return SIZE;
-          case 3: return PIZZA_SIDE;
-          default: return null;
-        }
-      }
-
-      public static com.google.protobuf.Internal.EnumLiteMap<PropertyType>
-          internalGetValueMap() {
-        return internalValueMap;
-      }
-      private static final com.google.protobuf.Internal.EnumLiteMap<
-          PropertyType> internalValueMap =
-            new com.google.protobuf.Internal.EnumLiteMap<PropertyType>() {
-              public PropertyType findValueByNumber(int number) {
-                return PropertyType.forNumber(number);
-              }
-            };
-
-      public final com.google.protobuf.Descriptors.EnumValueDescriptor
-          getValueDescriptor() {
-        if (this == UNRECOGNIZED) {
-          throw new java.lang.IllegalStateException(
-              "Can't get the descriptor of an unrecognized enum value.");
-        }
-        return getDescriptor().getValues().get(ordinal());
-      }
-      public final com.google.protobuf.Descriptors.EnumDescriptor
-          getDescriptorForType() {
-        return getDescriptor();
-      }
-      public static final com.google.protobuf.Descriptors.EnumDescriptor
-          getDescriptor() {
-        return food.menu.v1.FoodMenu.MenuItemOptionProperty.getDescriptor().getEnumTypes().get(0);
-      }
-
-      private static final PropertyType[] VALUES = values();
-
-      public static PropertyType valueOf(
-          com.google.protobuf.Descriptors.EnumValueDescriptor desc) {
-        if (desc.getType() != getDescriptor()) {
-          throw new java.lang.IllegalArgumentException(
-            "EnumValueDescriptor is not for this type.");
-        }
-        if (desc.getIndex() == -1) {
-          return UNRECOGNIZED;
-        }
-        return VALUES[desc.getIndex()];
-      }
-
-      private final int value;
-
-      private PropertyType(int value) {
-        this.value = value;
-      }
-
-      // @@protoc_insertion_point(enum_scope:food.menu.v1.MenuItemOptionProperty.PropertyType)
-    }
-
-    /**
-     * <pre>
-     * Well-defined values for the option property.
-     * </pre>
-     *
-     * Protobuf enum {@code food.menu.v1.MenuItemOptionProperty.PropertyValue}
-     */
-    public enum PropertyValue
-        implements com.google.protobuf.ProtocolMessageEnum {
-      /**
-       * <pre>
-       * Do not use. The property value is not explicitly specified.
-       * </pre>
-       *
-       * <code>UNKNOWN_PROPERTY_VALUE = 0;</code>
-       */
-      UNKNOWN_PROPERTY_VALUE(0),
-      /**
-       * <pre>
-       * The MenuItemOption applies only to the left side of a pizza.
-       * </pre>
-       *
-       * <code>PIZZA_SIDE_LEFT = 1;</code>
-       */
-      PIZZA_SIDE_LEFT(1),
-      /**
-       * <pre>
-       * The MenuItemOption applies only to the right side of a pizza.
-       * </pre>
-       *
-       * <code>PIZZA_SIDE_RIGHT = 2;</code>
-       */
-      PIZZA_SIDE_RIGHT(2),
-      /**
-       * <pre>
-       * The MenuItemOption applies to the entire pizza.
-       * </pre>
-       *
-       * <code>PIZZA_SIDE_WHOLE = 3;</code>
-       */
-      PIZZA_SIDE_WHOLE(3),
-      UNRECOGNIZED(-1),
-      ;
-
-      /**
-       * <pre>
-       * Do not use. The property value is not explicitly specified.
-       * </pre>
-       *
-       * <code>UNKNOWN_PROPERTY_VALUE = 0;</code>
-       */
-      public static final int UNKNOWN_PROPERTY_VALUE_VALUE = 0;
-      /**
-       * <pre>
-       * The MenuItemOption applies only to the left side of a pizza.
-       * </pre>
-       *
-       * <code>PIZZA_SIDE_LEFT = 1;</code>
-       */
-      public static final int PIZZA_SIDE_LEFT_VALUE = 1;
-      /**
-       * <pre>
-       * The MenuItemOption applies only to the right side of a pizza.
-       * </pre>
-       *
-       * <code>PIZZA_SIDE_RIGHT = 2;</code>
-       */
-      public static final int PIZZA_SIDE_RIGHT_VALUE = 2;
-      /**
-       * <pre>
-       * The MenuItemOption applies to the entire pizza.
-       * </pre>
-       *
-       * <code>PIZZA_SIDE_WHOLE = 3;</code>
-       */
-      public static final int PIZZA_SIDE_WHOLE_VALUE = 3;
-
-
-      public final int getNumber() {
-        if (this == UNRECOGNIZED) {
-          throw new java.lang.IllegalArgumentException(
-              "Can't get the number of an unknown enum value.");
-        }
-        return value;
-      }
-
-      /**
-       * @param value The numeric wire value of the corresponding enum entry.
-       * @return The enum associated with the given numeric wire value.
-       * @deprecated Use {@link #forNumber(int)} instead.
-       */
-      @java.lang.Deprecated
-      public static PropertyValue valueOf(int value) {
-        return forNumber(value);
-      }
-
-      /**
-       * @param value The numeric wire value of the corresponding enum entry.
-       * @return The enum associated with the given numeric wire value.
-       */
-      public static PropertyValue forNumber(int value) {
-        switch (value) {
-          case 0: return UNKNOWN_PROPERTY_VALUE;
-          case 1: return PIZZA_SIDE_LEFT;
-          case 2: return PIZZA_SIDE_RIGHT;
-          case 3: return PIZZA_SIDE_WHOLE;
-          default: return null;
-        }
-      }
-
-      public static com.google.protobuf.Internal.EnumLiteMap<PropertyValue>
-          internalGetValueMap() {
-        return internalValueMap;
-      }
-      private static final com.google.protobuf.Internal.EnumLiteMap<
-          PropertyValue> internalValueMap =
-            new com.google.protobuf.Internal.EnumLiteMap<PropertyValue>() {
-              public PropertyValue findValueByNumber(int number) {
-                return PropertyValue.forNumber(number);
-              }
-            };
-
-      public final com.google.protobuf.Descriptors.EnumValueDescriptor
-          getValueDescriptor() {
-        if (this == UNRECOGNIZED) {
-          throw new java.lang.IllegalStateException(
-              "Can't get the descriptor of an unrecognized enum value.");
-        }
-        return getDescriptor().getValues().get(ordinal());
-      }
-      public final com.google.protobuf.Descriptors.EnumDescriptor
-          getDescriptorForType() {
-        return getDescriptor();
-      }
-      public static final com.google.protobuf.Descriptors.EnumDescriptor
-          getDescriptor() {
-        return food.menu.v1.FoodMenu.MenuItemOptionProperty.getDescriptor().getEnumTypes().get(1);
-      }
-
-      private static final PropertyValue[] VALUES = values();
-
-      public static PropertyValue valueOf(
-          com.google.protobuf.Descriptors.EnumValueDescriptor desc) {
-        if (desc.getType() != getDescriptor()) {
-          throw new java.lang.IllegalArgumentException(
-            "EnumValueDescriptor is not for this type.");
-        }
-        if (desc.getIndex() == -1) {
-          return UNRECOGNIZED;
-        }
-        return VALUES[desc.getIndex()];
-      }
-
-      private final int value;
-
-      private PropertyValue(int value) {
-        this.value = value;
-      }
-
-      // @@protoc_insertion_point(enum_scope:food.menu.v1.MenuItemOptionProperty.PropertyValue)
-    }
-
-    private int valueCase_ = 0;
-    @SuppressWarnings("serial")
-    private java.lang.Object value_;
-    public enum ValueCase
-        implements com.google.protobuf.Internal.EnumLite,
-            com.google.protobuf.AbstractMessage.InternalOneOfEnum {
-      PROPERTY_VAL(2),
-      TEXT_VAL(3),
-      VALUE_NOT_SET(0);
-      private final int value;
-      private ValueCase(int value) {
-        this.value = value;
-      }
-      /**
-       * @param value The number of the enum to look for.
-       * @return The enum associated with the given number.
-       * @deprecated Use {@link #forNumber(int)} instead.
-       */
-      @java.lang.Deprecated
-      public static ValueCase valueOf(int value) {
-        return forNumber(value);
-      }
-
-      public static ValueCase forNumber(int value) {
-        switch (value) {
-          case 2: return PROPERTY_VAL;
-          case 3: return TEXT_VAL;
-          case 0: return VALUE_NOT_SET;
-          default: return null;
-        }
-      }
-      public int getNumber() {
-        return this.value;
-      }
-    };
-
-    public ValueCase
-    getValueCase() {
-      return ValueCase.forNumber(
-          valueCase_);
-    }
-
-    public static final int PROPERTY_TYPE_FIELD_NUMBER = 1;
-    private int propertyType_ = 0;
-    /**
-     * <pre>
-     * The type of this option property.
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.MenuItemOptionProperty.PropertyType property_type = 1;</code>
-     * @return The enum numeric value on the wire for propertyType.
-     */
-    @java.lang.Override public int getPropertyTypeValue() {
-      return propertyType_;
-    }
-    /**
-     * <pre>
-     * The type of this option property.
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.MenuItemOptionProperty.PropertyType property_type = 1;</code>
-     * @return The propertyType.
-     */
-    @java.lang.Override public food.menu.v1.FoodMenu.MenuItemOptionProperty.PropertyType getPropertyType() {
-      food.menu.v1.FoodMenu.MenuItemOptionProperty.PropertyType result = food.menu.v1.FoodMenu.MenuItemOptionProperty.PropertyType.forNumber(propertyType_);
-      return result == null ? food.menu.v1.FoodMenu.MenuItemOptionProperty.PropertyType.UNRECOGNIZED : result;
-    }
-
-    public static final int PROPERTY_VAL_FIELD_NUMBER = 2;
-    /**
-     * <pre>
-     * A well-defined value for the option property. Currently only expected
-     * if the property_type is PIZZA_SIDE.
-     * </pre>
-     *
-     * <code>.food.menu.v1.MenuItemOptionProperty.PropertyValue property_val = 2;</code>
-     * @return Whether the propertyVal field is set.
-     */
-    public boolean hasPropertyVal() {
-      return valueCase_ == 2;
-    }
-    /**
-     * <pre>
-     * A well-defined value for the option property. Currently only expected
-     * if the property_type is PIZZA_SIDE.
-     * </pre>
-     *
-     * <code>.food.menu.v1.MenuItemOptionProperty.PropertyValue property_val = 2;</code>
-     * @return The enum numeric value on the wire for propertyVal.
-     */
-    public int getPropertyValValue() {
-      if (valueCase_ == 2) {
-        return (java.lang.Integer) value_;
-      }
-      return 0;
-    }
-    /**
-     * <pre>
-     * A well-defined value for the option property. Currently only expected
-     * if the property_type is PIZZA_SIDE.
-     * </pre>
-     *
-     * <code>.food.menu.v1.MenuItemOptionProperty.PropertyValue property_val = 2;</code>
-     * @return The propertyVal.
-     */
-    public food.menu.v1.FoodMenu.MenuItemOptionProperty.PropertyValue getPropertyVal() {
-      if (valueCase_ == 2) {
-        food.menu.v1.FoodMenu.MenuItemOptionProperty.PropertyValue result = food.menu.v1.FoodMenu.MenuItemOptionProperty.PropertyValue.forNumber(
-            (java.lang.Integer) value_);
-        return result == null ? food.menu.v1.FoodMenu.MenuItemOptionProperty.PropertyValue.UNRECOGNIZED : result;
-      }
-      return food.menu.v1.FoodMenu.MenuItemOptionProperty.PropertyValue.UNKNOWN_PROPERTY_VALUE;
-    }
-
-    public static final int TEXT_VAL_FIELD_NUMBER = 3;
-    /**
-     * <pre>
-     * A free-form text for the value of the property. Expected for
-     * property_type OPTION and SIZE.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField text_val = 3;</code>
-     * @return Whether the textVal field is set.
-     */
-    @java.lang.Override
-    public boolean hasTextVal() {
-      return valueCase_ == 3;
-    }
-    /**
-     * <pre>
-     * A free-form text for the value of the property. Expected for
-     * property_type OPTION and SIZE.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField text_val = 3;</code>
-     * @return The textVal.
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.TextField getTextVal() {
-      if (valueCase_ == 3) {
-         return (food.menu.v1.FoodMenu.TextField) value_;
-      }
-      return food.menu.v1.FoodMenu.TextField.getDefaultInstance();
-    }
-    /**
-     * <pre>
-     * A free-form text for the value of the property. Expected for
-     * property_type OPTION and SIZE.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField text_val = 3;</code>
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.TextFieldOrBuilder getTextValOrBuilder() {
-      if (valueCase_ == 3) {
-         return (food.menu.v1.FoodMenu.TextField) value_;
-      }
-      return food.menu.v1.FoodMenu.TextField.getDefaultInstance();
-    }
-
-    private byte memoizedIsInitialized = -1;
-    @java.lang.Override
-    public final boolean isInitialized() {
-      byte isInitialized = memoizedIsInitialized;
-      if (isInitialized == 1) return true;
-      if (isInitialized == 0) return false;
-
-      memoizedIsInitialized = 1;
-      return true;
-    }
-
-    @java.lang.Override
-    public void writeTo(com.google.protobuf.CodedOutputStream output)
-                        throws java.io.IOException {
-      if (propertyType_ != food.menu.v1.FoodMenu.MenuItemOptionProperty.PropertyType.UNKNOWN_PROPERTY_TYPE.getNumber()) {
-        output.writeEnum(1, propertyType_);
-      }
-      if (valueCase_ == 2) {
-        output.writeEnum(2, ((java.lang.Integer) value_));
-      }
-      if (valueCase_ == 3) {
-        output.writeMessage(3, (food.menu.v1.FoodMenu.TextField) value_);
-      }
-      getUnknownFields().writeTo(output);
-    }
-
-    @java.lang.Override
-    public int getSerializedSize() {
-      int size = memoizedSize;
-      if (size != -1) return size;
-
-      size = 0;
-      if (propertyType_ != food.menu.v1.FoodMenu.MenuItemOptionProperty.PropertyType.UNKNOWN_PROPERTY_TYPE.getNumber()) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeEnumSize(1, propertyType_);
-      }
-      if (valueCase_ == 2) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeEnumSize(2, ((java.lang.Integer) value_));
-      }
-      if (valueCase_ == 3) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(3, (food.menu.v1.FoodMenu.TextField) value_);
-      }
-      size += getUnknownFields().getSerializedSize();
-      memoizedSize = size;
-      return size;
-    }
-
-    @java.lang.Override
-    public boolean equals(final java.lang.Object obj) {
-      if (obj == this) {
-       return true;
-      }
-      if (!(obj instanceof food.menu.v1.FoodMenu.MenuItemOptionProperty)) {
-        return super.equals(obj);
-      }
-      food.menu.v1.FoodMenu.MenuItemOptionProperty other = (food.menu.v1.FoodMenu.MenuItemOptionProperty) obj;
-
-      if (propertyType_ != other.propertyType_) return false;
-      if (!getValueCase().equals(other.getValueCase())) return false;
-      switch (valueCase_) {
-        case 2:
-          if (getPropertyValValue()
-              != other.getPropertyValValue()) return false;
-          break;
-        case 3:
-          if (!getTextVal()
-              .equals(other.getTextVal())) return false;
-          break;
-        case 0:
-        default:
-      }
-      if (!getUnknownFields().equals(other.getUnknownFields())) return false;
-      return true;
-    }
-
-    @java.lang.Override
-    public int hashCode() {
-      if (memoizedHashCode != 0) {
-        return memoizedHashCode;
-      }
-      int hash = 41;
-      hash = (19 * hash) + getDescriptor().hashCode();
-      hash = (37 * hash) + PROPERTY_TYPE_FIELD_NUMBER;
-      hash = (53 * hash) + propertyType_;
-      switch (valueCase_) {
-        case 2:
-          hash = (37 * hash) + PROPERTY_VAL_FIELD_NUMBER;
-          hash = (53 * hash) + getPropertyValValue();
-          break;
-        case 3:
-          hash = (37 * hash) + TEXT_VAL_FIELD_NUMBER;
-          hash = (53 * hash) + getTextVal().hashCode();
-          break;
-        case 0:
-        default:
-      }
-      hash = (29 * hash) + getUnknownFields().hashCode();
-      memoizedHashCode = hash;
-      return hash;
-    }
-
-    public static food.menu.v1.FoodMenu.MenuItemOptionProperty parseFrom(
-        java.nio.ByteBuffer data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.MenuItemOptionProperty parseFrom(
-        java.nio.ByteBuffer data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.MenuItemOptionProperty parseFrom(
-        com.google.protobuf.ByteString data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.MenuItemOptionProperty parseFrom(
-        com.google.protobuf.ByteString data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.MenuItemOptionProperty parseFrom(byte[] data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.MenuItemOptionProperty parseFrom(
-        byte[] data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.MenuItemOptionProperty parseFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.MenuItemOptionProperty parseFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.MenuItemOptionProperty parseDelimitedFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseDelimitedWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.MenuItemOptionProperty parseDelimitedFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.MenuItemOptionProperty parseFrom(
-        com.google.protobuf.CodedInputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.MenuItemOptionProperty parseFrom(
-        com.google.protobuf.CodedInputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input, extensionRegistry);
-    }
-
-    @java.lang.Override
-    public Builder newBuilderForType() { return newBuilder(); }
-    public static Builder newBuilder() {
-      return DEFAULT_INSTANCE.toBuilder();
-    }
-    public static Builder newBuilder(food.menu.v1.FoodMenu.MenuItemOptionProperty prototype) {
-      return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
-    }
-    @java.lang.Override
-    public Builder toBuilder() {
-      return this == DEFAULT_INSTANCE
-          ? new Builder() : new Builder().mergeFrom(this);
-    }
-
-    @java.lang.Override
-    protected Builder newBuilderForType(
-        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-      Builder builder = new Builder(parent);
-      return builder;
-    }
-    /**
-     * <pre>
-     * Describes the property of a menu item option and its value.
-     * </pre>
-     *
-     * Protobuf type {@code food.menu.v1.MenuItemOptionProperty}
-     */
-    public static final class Builder extends
-        com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
-        // @@protoc_insertion_point(builder_implements:food.menu.v1.MenuItemOptionProperty)
-        food.menu.v1.FoodMenu.MenuItemOptionPropertyOrBuilder {
-      public static final com.google.protobuf.Descriptors.Descriptor
-          getDescriptor() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_MenuItemOptionProperty_descriptor;
-      }
-
-      @java.lang.Override
-      protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-          internalGetFieldAccessorTable() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_MenuItemOptionProperty_fieldAccessorTable
-            .ensureFieldAccessorsInitialized(
-                food.menu.v1.FoodMenu.MenuItemOptionProperty.class, food.menu.v1.FoodMenu.MenuItemOptionProperty.Builder.class);
-      }
-
-      // Construct using food.menu.v1.FoodMenu.MenuItemOptionProperty.newBuilder()
-      private Builder() {
-
-      }
-
-      private Builder(
-          com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-        super(parent);
-
-      }
-      @java.lang.Override
-      public Builder clear() {
-        super.clear();
-        bitField0_ = 0;
-        propertyType_ = 0;
-        if (textValBuilder_ != null) {
-          textValBuilder_.clear();
-        }
-        valueCase_ = 0;
-        value_ = null;
-        return this;
-      }
-
-      @java.lang.Override
-      public com.google.protobuf.Descriptors.Descriptor
-          getDescriptorForType() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_MenuItemOptionProperty_descriptor;
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.MenuItemOptionProperty getDefaultInstanceForType() {
-        return food.menu.v1.FoodMenu.MenuItemOptionProperty.getDefaultInstance();
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.MenuItemOptionProperty build() {
-        food.menu.v1.FoodMenu.MenuItemOptionProperty result = buildPartial();
-        if (!result.isInitialized()) {
-          throw newUninitializedMessageException(result);
-        }
-        return result;
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.MenuItemOptionProperty buildPartial() {
-        food.menu.v1.FoodMenu.MenuItemOptionProperty result = new food.menu.v1.FoodMenu.MenuItemOptionProperty(this);
-        if (bitField0_ != 0) { buildPartial0(result); }
-        buildPartialOneofs(result);
-        onBuilt();
-        return result;
-      }
-
-      private void buildPartial0(food.menu.v1.FoodMenu.MenuItemOptionProperty result) {
-        int from_bitField0_ = bitField0_;
-        if (((from_bitField0_ & 0x00000001) != 0)) {
-          result.propertyType_ = propertyType_;
-        }
-      }
-
-      private void buildPartialOneofs(food.menu.v1.FoodMenu.MenuItemOptionProperty result) {
-        result.valueCase_ = valueCase_;
-        result.value_ = this.value_;
-        if (valueCase_ == 3 &&
-            textValBuilder_ != null) {
-          result.value_ = textValBuilder_.build();
-        }
-      }
-
-      @java.lang.Override
-      public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof food.menu.v1.FoodMenu.MenuItemOptionProperty) {
-          return mergeFrom((food.menu.v1.FoodMenu.MenuItemOptionProperty)other);
-        } else {
-          super.mergeFrom(other);
-          return this;
-        }
-      }
-
-      public Builder mergeFrom(food.menu.v1.FoodMenu.MenuItemOptionProperty other) {
-        if (other == food.menu.v1.FoodMenu.MenuItemOptionProperty.getDefaultInstance()) return this;
-        if (other.propertyType_ != 0) {
-          setPropertyTypeValue(other.getPropertyTypeValue());
-        }
-        switch (other.getValueCase()) {
-          case PROPERTY_VAL: {
-            setPropertyValValue(other.getPropertyValValue());
-            break;
-          }
-          case TEXT_VAL: {
-            mergeTextVal(other.getTextVal());
-            break;
-          }
-          case VALUE_NOT_SET: {
-            break;
-          }
-        }
-        this.mergeUnknownFields(other.getUnknownFields());
-        onChanged();
-        return this;
-      }
-
-      @java.lang.Override
-      public final boolean isInitialized() {
-        return true;
-      }
-
-      @java.lang.Override
-      public Builder mergeFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws java.io.IOException {
-        if (extensionRegistry == null) {
-          throw new java.lang.NullPointerException();
-        }
-        try {
-          boolean done = false;
-          while (!done) {
-            int tag = input.readTag();
-            switch (tag) {
-              case 0:
-                done = true;
-                break;
-              case 8: {
-                propertyType_ = input.readEnum();
-                bitField0_ |= 0x00000001;
-                break;
-              } // case 8
-              case 16: {
-                int rawValue = input.readEnum();
-                valueCase_ = 2;
-                value_ = rawValue;
-                break;
-              } // case 16
-              case 26: {
-                input.readMessage(
-                    getTextValFieldBuilder().getBuilder(),
-                    extensionRegistry);
-                valueCase_ = 3;
-                break;
-              } // case 26
-              default: {
-                if (!super.parseUnknownField(input, extensionRegistry, tag)) {
-                  done = true; // was an endgroup tag
-                }
-                break;
-              } // default:
-            } // switch (tag)
-          } // while (!done)
-        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          throw e.unwrapIOException();
-        } finally {
-          onChanged();
-        } // finally
-        return this;
-      }
-      private int valueCase_ = 0;
-      private java.lang.Object value_;
-      public ValueCase
-          getValueCase() {
-        return ValueCase.forNumber(
-            valueCase_);
-      }
-
-      public Builder clearValue() {
-        valueCase_ = 0;
-        value_ = null;
-        onChanged();
-        return this;
-      }
-
-      private int bitField0_;
-
-      private int propertyType_ = 0;
-      /**
-       * <pre>
-       * The type of this option property.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItemOptionProperty.PropertyType property_type = 1;</code>
-       * @return The enum numeric value on the wire for propertyType.
-       */
-      @java.lang.Override public int getPropertyTypeValue() {
-        return propertyType_;
-      }
-      /**
-       * <pre>
-       * The type of this option property.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItemOptionProperty.PropertyType property_type = 1;</code>
-       * @param value The enum numeric value on the wire for propertyType to set.
-       * @return This builder for chaining.
-       */
-      public Builder setPropertyTypeValue(int value) {
-        propertyType_ = value;
-        bitField0_ |= 0x00000001;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * The type of this option property.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItemOptionProperty.PropertyType property_type = 1;</code>
-       * @return The propertyType.
-       */
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.MenuItemOptionProperty.PropertyType getPropertyType() {
-        food.menu.v1.FoodMenu.MenuItemOptionProperty.PropertyType result = food.menu.v1.FoodMenu.MenuItemOptionProperty.PropertyType.forNumber(propertyType_);
-        return result == null ? food.menu.v1.FoodMenu.MenuItemOptionProperty.PropertyType.UNRECOGNIZED : result;
-      }
-      /**
-       * <pre>
-       * The type of this option property.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItemOptionProperty.PropertyType property_type = 1;</code>
-       * @param value The propertyType to set.
-       * @return This builder for chaining.
-       */
-      public Builder setPropertyType(food.menu.v1.FoodMenu.MenuItemOptionProperty.PropertyType value) {
-        if (value == null) {
-          throw new NullPointerException();
-        }
-        bitField0_ |= 0x00000001;
-        propertyType_ = value.getNumber();
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * The type of this option property.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItemOptionProperty.PropertyType property_type = 1;</code>
-       * @return This builder for chaining.
-       */
-      public Builder clearPropertyType() {
-        bitField0_ = (bitField0_ & ~0x00000001);
-        propertyType_ = 0;
-        onChanged();
-        return this;
-      }
-
-      /**
-       * <pre>
-       * A well-defined value for the option property. Currently only expected
-       * if the property_type is PIZZA_SIDE.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItemOptionProperty.PropertyValue property_val = 2;</code>
-       * @return Whether the propertyVal field is set.
-       */
-      @java.lang.Override
-      public boolean hasPropertyVal() {
-        return valueCase_ == 2;
-      }
-      /**
-       * <pre>
-       * A well-defined value for the option property. Currently only expected
-       * if the property_type is PIZZA_SIDE.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItemOptionProperty.PropertyValue property_val = 2;</code>
-       * @return The enum numeric value on the wire for propertyVal.
-       */
-      @java.lang.Override
-      public int getPropertyValValue() {
-        if (valueCase_ == 2) {
-          return ((java.lang.Integer) value_).intValue();
-        }
-        return 0;
-      }
-      /**
-       * <pre>
-       * A well-defined value for the option property. Currently only expected
-       * if the property_type is PIZZA_SIDE.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItemOptionProperty.PropertyValue property_val = 2;</code>
-       * @param value The enum numeric value on the wire for propertyVal to set.
-       * @return This builder for chaining.
-       */
-      public Builder setPropertyValValue(int value) {
-        valueCase_ = 2;
-        value_ = value;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * A well-defined value for the option property. Currently only expected
-       * if the property_type is PIZZA_SIDE.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItemOptionProperty.PropertyValue property_val = 2;</code>
-       * @return The propertyVal.
-       */
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.MenuItemOptionProperty.PropertyValue getPropertyVal() {
-        if (valueCase_ == 2) {
-          food.menu.v1.FoodMenu.MenuItemOptionProperty.PropertyValue result = food.menu.v1.FoodMenu.MenuItemOptionProperty.PropertyValue.forNumber(
-              (java.lang.Integer) value_);
-          return result == null ? food.menu.v1.FoodMenu.MenuItemOptionProperty.PropertyValue.UNRECOGNIZED : result;
-        }
-        return food.menu.v1.FoodMenu.MenuItemOptionProperty.PropertyValue.UNKNOWN_PROPERTY_VALUE;
-      }
-      /**
-       * <pre>
-       * A well-defined value for the option property. Currently only expected
-       * if the property_type is PIZZA_SIDE.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItemOptionProperty.PropertyValue property_val = 2;</code>
-       * @param value The propertyVal to set.
-       * @return This builder for chaining.
-       */
-      public Builder setPropertyVal(food.menu.v1.FoodMenu.MenuItemOptionProperty.PropertyValue value) {
-        if (value == null) {
-          throw new NullPointerException();
-        }
-        valueCase_ = 2;
-        value_ = value.getNumber();
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * A well-defined value for the option property. Currently only expected
-       * if the property_type is PIZZA_SIDE.
-       * </pre>
-       *
-       * <code>.food.menu.v1.MenuItemOptionProperty.PropertyValue property_val = 2;</code>
-       * @return This builder for chaining.
-       */
-      public Builder clearPropertyVal() {
-        if (valueCase_ == 2) {
-          valueCase_ = 0;
-          value_ = null;
-          onChanged();
-        }
-        return this;
-      }
-
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.TextField, food.menu.v1.FoodMenu.TextField.Builder, food.menu.v1.FoodMenu.TextFieldOrBuilder> textValBuilder_;
-      /**
-       * <pre>
-       * A free-form text for the value of the property. Expected for
-       * property_type OPTION and SIZE.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField text_val = 3;</code>
-       * @return Whether the textVal field is set.
-       */
-      @java.lang.Override
-      public boolean hasTextVal() {
-        return valueCase_ == 3;
-      }
-      /**
-       * <pre>
-       * A free-form text for the value of the property. Expected for
-       * property_type OPTION and SIZE.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField text_val = 3;</code>
-       * @return The textVal.
-       */
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.TextField getTextVal() {
-        if (textValBuilder_ == null) {
-          if (valueCase_ == 3) {
-            return (food.menu.v1.FoodMenu.TextField) value_;
-          }
-          return food.menu.v1.FoodMenu.TextField.getDefaultInstance();
-        } else {
-          if (valueCase_ == 3) {
-            return textValBuilder_.getMessage();
-          }
-          return food.menu.v1.FoodMenu.TextField.getDefaultInstance();
-        }
-      }
-      /**
-       * <pre>
-       * A free-form text for the value of the property. Expected for
-       * property_type OPTION and SIZE.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField text_val = 3;</code>
-       */
-      public Builder setTextVal(food.menu.v1.FoodMenu.TextField value) {
-        if (textValBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          value_ = value;
-          onChanged();
-        } else {
-          textValBuilder_.setMessage(value);
-        }
-        valueCase_ = 3;
-        return this;
-      }
-      /**
-       * <pre>
-       * A free-form text for the value of the property. Expected for
-       * property_type OPTION and SIZE.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField text_val = 3;</code>
-       */
-      public Builder setTextVal(
-          food.menu.v1.FoodMenu.TextField.Builder builderForValue) {
-        if (textValBuilder_ == null) {
-          value_ = builderForValue.build();
-          onChanged();
-        } else {
-          textValBuilder_.setMessage(builderForValue.build());
-        }
-        valueCase_ = 3;
-        return this;
-      }
-      /**
-       * <pre>
-       * A free-form text for the value of the property. Expected for
-       * property_type OPTION and SIZE.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField text_val = 3;</code>
-       */
-      public Builder mergeTextVal(food.menu.v1.FoodMenu.TextField value) {
-        if (textValBuilder_ == null) {
-          if (valueCase_ == 3 &&
-              value_ != food.menu.v1.FoodMenu.TextField.getDefaultInstance()) {
-            value_ = food.menu.v1.FoodMenu.TextField.newBuilder((food.menu.v1.FoodMenu.TextField) value_)
-                .mergeFrom(value).buildPartial();
-          } else {
-            value_ = value;
-          }
-          onChanged();
-        } else {
-          if (valueCase_ == 3) {
-            textValBuilder_.mergeFrom(value);
-          } else {
-            textValBuilder_.setMessage(value);
-          }
-        }
-        valueCase_ = 3;
-        return this;
-      }
-      /**
-       * <pre>
-       * A free-form text for the value of the property. Expected for
-       * property_type OPTION and SIZE.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField text_val = 3;</code>
-       */
-      public Builder clearTextVal() {
-        if (textValBuilder_ == null) {
-          if (valueCase_ == 3) {
-            valueCase_ = 0;
-            value_ = null;
-            onChanged();
-          }
-        } else {
-          if (valueCase_ == 3) {
-            valueCase_ = 0;
-            value_ = null;
-          }
-          textValBuilder_.clear();
-        }
-        return this;
-      }
-      /**
-       * <pre>
-       * A free-form text for the value of the property. Expected for
-       * property_type OPTION and SIZE.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField text_val = 3;</code>
-       */
-      public food.menu.v1.FoodMenu.TextField.Builder getTextValBuilder() {
-        return getTextValFieldBuilder().getBuilder();
-      }
-      /**
-       * <pre>
-       * A free-form text for the value of the property. Expected for
-       * property_type OPTION and SIZE.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField text_val = 3;</code>
-       */
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.TextFieldOrBuilder getTextValOrBuilder() {
-        if ((valueCase_ == 3) && (textValBuilder_ != null)) {
-          return textValBuilder_.getMessageOrBuilder();
-        } else {
-          if (valueCase_ == 3) {
-            return (food.menu.v1.FoodMenu.TextField) value_;
-          }
-          return food.menu.v1.FoodMenu.TextField.getDefaultInstance();
-        }
-      }
-      /**
-       * <pre>
-       * A free-form text for the value of the property. Expected for
-       * property_type OPTION and SIZE.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField text_val = 3;</code>
-       */
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.TextField, food.menu.v1.FoodMenu.TextField.Builder, food.menu.v1.FoodMenu.TextFieldOrBuilder> 
-          getTextValFieldBuilder() {
-        if (textValBuilder_ == null) {
-          if (!(valueCase_ == 3)) {
-            value_ = food.menu.v1.FoodMenu.TextField.getDefaultInstance();
-          }
-          textValBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
-              food.menu.v1.FoodMenu.TextField, food.menu.v1.FoodMenu.TextField.Builder, food.menu.v1.FoodMenu.TextFieldOrBuilder>(
-                  (food.menu.v1.FoodMenu.TextField) value_,
-                  getParentForChildren(),
-                  isClean());
-          value_ = null;
-        }
-        valueCase_ = 3;
-        onChanged();
-        return textValBuilder_;
-      }
-      @java.lang.Override
-      public final Builder setUnknownFields(
-          final com.google.protobuf.UnknownFieldSet unknownFields) {
-        return super.setUnknownFields(unknownFields);
-      }
-
-      @java.lang.Override
-      public final Builder mergeUnknownFields(
-          final com.google.protobuf.UnknownFieldSet unknownFields) {
-        return super.mergeUnknownFields(unknownFields);
-      }
-
-
-      // @@protoc_insertion_point(builder_scope:food.menu.v1.MenuItemOptionProperty)
-    }
-
-    // @@protoc_insertion_point(class_scope:food.menu.v1.MenuItemOptionProperty)
-    private static final food.menu.v1.FoodMenu.MenuItemOptionProperty DEFAULT_INSTANCE;
-    static {
-      DEFAULT_INSTANCE = new food.menu.v1.FoodMenu.MenuItemOptionProperty();
-    }
-
-    public static food.menu.v1.FoodMenu.MenuItemOptionProperty getDefaultInstance() {
-      return DEFAULT_INSTANCE;
-    }
-
-    private static final com.google.protobuf.Parser<MenuItemOptionProperty>
-        PARSER = new com.google.protobuf.AbstractParser<MenuItemOptionProperty>() {
-      @java.lang.Override
-      public MenuItemOptionProperty parsePartialFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws com.google.protobuf.InvalidProtocolBufferException {
-        Builder builder = newBuilder();
-        try {
-          builder.mergeFrom(input, extensionRegistry);
-        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          throw e.setUnfinishedMessage(builder.buildPartial());
-        } catch (com.google.protobuf.UninitializedMessageException e) {
-          throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
-        } catch (java.io.IOException e) {
-          throw new com.google.protobuf.InvalidProtocolBufferException(e)
-              .setUnfinishedMessage(builder.buildPartial());
-        }
-        return builder.buildPartial();
-      }
-    };
-
-    public static com.google.protobuf.Parser<MenuItemOptionProperty> parser() {
-      return PARSER;
-    }
-
-    @java.lang.Override
-    public com.google.protobuf.Parser<MenuItemOptionProperty> getParserForType() {
-      return PARSER;
-    }
-
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.MenuItemOptionProperty getDefaultInstanceForType() {
-      return DEFAULT_INSTANCE;
-    }
-
-  }
-
-  public interface NutritionInformationOrBuilder extends
-      // @@protoc_insertion_point(interface_extends:food.menu.v1.NutritionInformation)
-      com.google.protobuf.MessageOrBuilder {
-
-    /**
-     * <pre>
-     * The amount of nutritional energy of the serving of food. Can be defined
-     * in Calories or kilojoules.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.NutritionInformation.NutritionValue energy = 1;</code>
-     * @return Whether the energy field is set.
-     */
-    boolean hasEnergy();
-    /**
-     * <pre>
-     * The amount of nutritional energy of the serving of food. Can be defined
-     * in Calories or kilojoules.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.NutritionInformation.NutritionValue energy = 1;</code>
-     * @return The energy.
-     */
-    food.menu.v1.FoodMenu.NutritionInformation.NutritionValue getEnergy();
-    /**
-     * <pre>
-     * The amount of nutritional energy of the serving of food. Can be defined
-     * in Calories or kilojoules.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.NutritionInformation.NutritionValue energy = 1;</code>
-     */
-    food.menu.v1.FoodMenu.NutritionInformation.NutritionValueOrBuilder getEnergyOrBuilder();
-
-    /**
-     * <pre>
-     * The amount of sodium content, measured in grams or milligrams.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.NutritionInformation.NutritionValue sodium_content = 2;</code>
-     * @return Whether the sodiumContent field is set.
-     */
-    boolean hasSodiumContent();
-    /**
-     * <pre>
-     * The amount of sodium content, measured in grams or milligrams.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.NutritionInformation.NutritionValue sodium_content = 2;</code>
-     * @return The sodiumContent.
-     */
-    food.menu.v1.FoodMenu.NutritionInformation.NutritionValue getSodiumContent();
-    /**
-     * <pre>
-     * The amount of sodium content, measured in grams or milligrams.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.NutritionInformation.NutritionValue sodium_content = 2;</code>
-     */
-    food.menu.v1.FoodMenu.NutritionInformation.NutritionValueOrBuilder getSodiumContentOrBuilder();
-
-    /**
-     * <pre>
-     * The number of servings the nutrition value applies to.
-     * Optional.
-     * </pre>
-     *
-     * <code>optional int32 serving_size = 3;</code>
-     * @return Whether the servingSize field is set.
-     */
-    boolean hasServingSize();
-    /**
-     * <pre>
-     * The number of servings the nutrition value applies to.
-     * Optional.
-     * </pre>
-     *
-     * <code>optional int32 serving_size = 3;</code>
-     * @return The servingSize.
-     */
-    int getServingSize();
-
-    /**
-     * <pre>
-     * Nutrition information in free text. For example "Contains preservatives".
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField description = 4;</code>
-     * @return Whether the description field is set.
-     */
-    boolean hasDescription();
-    /**
-     * <pre>
-     * Nutrition information in free text. For example "Contains preservatives".
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField description = 4;</code>
-     * @return The description.
-     */
-    food.menu.v1.FoodMenu.TextField getDescription();
-    /**
-     * <pre>
-     * Nutrition information in free text. For example "Contains preservatives".
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField description = 4;</code>
-     */
-    food.menu.v1.FoodMenu.TextFieldOrBuilder getDescriptionOrBuilder();
-  }
-  /**
-   * <pre>
-   * Describes all the nutritional measurements of a MenuItem or add-on.
-   * </pre>
-   *
-   * Protobuf type {@code food.menu.v1.NutritionInformation}
-   */
-  public static final class NutritionInformation extends
-      com.google.protobuf.GeneratedMessageV3 implements
-      // @@protoc_insertion_point(message_implements:food.menu.v1.NutritionInformation)
-      NutritionInformationOrBuilder {
-  private static final long serialVersionUID = 0L;
-    // Use NutritionInformation.newBuilder() to construct.
-    private NutritionInformation(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
-      super(builder);
-    }
-    private NutritionInformation() {
-    }
-
-    @java.lang.Override
-    @SuppressWarnings({"unused"})
-    protected java.lang.Object newInstance(
-        UnusedPrivateParameter unused) {
-      return new NutritionInformation();
-    }
-
-    public static final com.google.protobuf.Descriptors.Descriptor
-        getDescriptor() {
-      return food.menu.v1.FoodMenu.internal_static_food_menu_v1_NutritionInformation_descriptor;
-    }
-
-    @java.lang.Override
-    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-        internalGetFieldAccessorTable() {
-      return food.menu.v1.FoodMenu.internal_static_food_menu_v1_NutritionInformation_fieldAccessorTable
-          .ensureFieldAccessorsInitialized(
-              food.menu.v1.FoodMenu.NutritionInformation.class, food.menu.v1.FoodMenu.NutritionInformation.Builder.class);
-    }
-
-    public interface NutritionValueOrBuilder extends
-        // @@protoc_insertion_point(interface_extends:food.menu.v1.NutritionInformation.NutritionValue)
-        com.google.protobuf.MessageOrBuilder {
-
-      /**
-       * <pre>
-       * A single number representing the amount of nutritional value.
-       * </pre>
-       *
-       * <code>double amount = 1;</code>
-       * @return Whether the amount field is set.
-       */
-      boolean hasAmount();
-      /**
-       * <pre>
-       * A single number representing the amount of nutritional value.
-       * </pre>
-       *
-       * <code>double amount = 1;</code>
-       * @return The amount.
-       */
-      double getAmount();
-
-      /**
-       * <pre>
-       * A range representing the amount of nutritional value.
-       * </pre>
-       *
-       * <code>.food.menu.v1.NutritionInformation.NutritionValue.Range range = 3;</code>
-       * @return Whether the range field is set.
-       */
-      boolean hasRange();
-      /**
-       * <pre>
-       * A range representing the amount of nutritional value.
-       * </pre>
-       *
-       * <code>.food.menu.v1.NutritionInformation.NutritionValue.Range range = 3;</code>
-       * @return The range.
-       */
-      food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range getRange();
-      /**
-       * <pre>
-       * A range representing the amount of nutritional value.
-       * </pre>
-       *
-       * <code>.food.menu.v1.NutritionInformation.NutritionValue.Range range = 3;</code>
-       */
-      food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.RangeOrBuilder getRangeOrBuilder();
-
-      /**
-       * <pre>
-       * The unit associated with the amount as specified from the partner. We
-       * will validate the feed so that the unit for each type of nutrition value
-       * is expected for that type of value. For example, only ENERGY_CALORIES
-       * and ENERGY_KILOJOULES are expected on energy property of
-       * NutritionalInformation.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.NutritionValueUnit unit = 2;</code>
-       * @return The enum numeric value on the wire for unit.
-       */
-      int getUnitValue();
-      /**
-       * <pre>
-       * The unit associated with the amount as specified from the partner. We
-       * will validate the feed so that the unit for each type of nutrition value
-       * is expected for that type of value. For example, only ENERGY_CALORIES
-       * and ENERGY_KILOJOULES are expected on energy property of
-       * NutritionalInformation.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.NutritionValueUnit unit = 2;</code>
-       * @return The unit.
-       */
-      food.menu.v1.FoodMenu.NutritionValueUnit getUnit();
-
-      food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.ValueCase getValueCase();
-    }
-    /**
-     * <pre>
-     * Describes a single nutritional measurement of the serving of food.
-     * </pre>
-     *
-     * Protobuf type {@code food.menu.v1.NutritionInformation.NutritionValue}
-     */
-    public static final class NutritionValue extends
-        com.google.protobuf.GeneratedMessageV3 implements
-        // @@protoc_insertion_point(message_implements:food.menu.v1.NutritionInformation.NutritionValue)
-        NutritionValueOrBuilder {
-    private static final long serialVersionUID = 0L;
-      // Use NutritionValue.newBuilder() to construct.
-      private NutritionValue(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
-        super(builder);
-      }
-      private NutritionValue() {
-        unit_ = 0;
-      }
-
-      @java.lang.Override
-      @SuppressWarnings({"unused"})
-      protected java.lang.Object newInstance(
-          UnusedPrivateParameter unused) {
-        return new NutritionValue();
-      }
-
-      public static final com.google.protobuf.Descriptors.Descriptor
-          getDescriptor() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_NutritionInformation_NutritionValue_descriptor;
-      }
-
-      @java.lang.Override
-      protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-          internalGetFieldAccessorTable() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_NutritionInformation_NutritionValue_fieldAccessorTable
-            .ensureFieldAccessorsInitialized(
-                food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.class, food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Builder.class);
-      }
-
-      public interface RangeOrBuilder extends
-          // @@protoc_insertion_point(interface_extends:food.menu.v1.NutritionInformation.NutritionValue.Range)
-          com.google.protobuf.MessageOrBuilder {
-
-        /**
-         * <pre>
-         * The minimum amount of nutrition value.
-         * Required.
-         * </pre>
-         *
-         * <code>double min = 1;</code>
-         * @return The min.
-         */
-        double getMin();
-
-        /**
-         * <pre>
-         * The maximum amount of nutrition value.
-         * Required.
-         * </pre>
-         *
-         * <code>double max = 2;</code>
-         * @return The max.
-         */
-        double getMax();
-      }
-      /**
-       * <pre>
-       * Describes a closed range for the nutrition value. E.g. "100-150 cal"
-       * </pre>
-       *
-       * Protobuf type {@code food.menu.v1.NutritionInformation.NutritionValue.Range}
-       */
-      public static final class Range extends
-          com.google.protobuf.GeneratedMessageV3 implements
-          // @@protoc_insertion_point(message_implements:food.menu.v1.NutritionInformation.NutritionValue.Range)
-          RangeOrBuilder {
-      private static final long serialVersionUID = 0L;
-        // Use Range.newBuilder() to construct.
-        private Range(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
-          super(builder);
-        }
-        private Range() {
-        }
-
-        @java.lang.Override
-        @SuppressWarnings({"unused"})
-        protected java.lang.Object newInstance(
-            UnusedPrivateParameter unused) {
-          return new Range();
-        }
-
-        public static final com.google.protobuf.Descriptors.Descriptor
-            getDescriptor() {
-          return food.menu.v1.FoodMenu.internal_static_food_menu_v1_NutritionInformation_NutritionValue_Range_descriptor;
-        }
-
-        @java.lang.Override
-        protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-            internalGetFieldAccessorTable() {
-          return food.menu.v1.FoodMenu.internal_static_food_menu_v1_NutritionInformation_NutritionValue_Range_fieldAccessorTable
-              .ensureFieldAccessorsInitialized(
-                  food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range.class, food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range.Builder.class);
-        }
-
-        public static final int MIN_FIELD_NUMBER = 1;
-        private double min_ = 0D;
-        /**
-         * <pre>
-         * The minimum amount of nutrition value.
-         * Required.
-         * </pre>
-         *
-         * <code>double min = 1;</code>
-         * @return The min.
-         */
-        @java.lang.Override
-        public double getMin() {
-          return min_;
-        }
-
-        public static final int MAX_FIELD_NUMBER = 2;
-        private double max_ = 0D;
-        /**
-         * <pre>
-         * The maximum amount of nutrition value.
-         * Required.
-         * </pre>
-         *
-         * <code>double max = 2;</code>
-         * @return The max.
-         */
-        @java.lang.Override
-        public double getMax() {
-          return max_;
-        }
-
-        private byte memoizedIsInitialized = -1;
-        @java.lang.Override
-        public final boolean isInitialized() {
-          byte isInitialized = memoizedIsInitialized;
-          if (isInitialized == 1) return true;
-          if (isInitialized == 0) return false;
-
-          memoizedIsInitialized = 1;
-          return true;
-        }
-
-        @java.lang.Override
-        public void writeTo(com.google.protobuf.CodedOutputStream output)
-                            throws java.io.IOException {
-          if (java.lang.Double.doubleToRawLongBits(min_) != 0) {
-            output.writeDouble(1, min_);
-          }
-          if (java.lang.Double.doubleToRawLongBits(max_) != 0) {
-            output.writeDouble(2, max_);
-          }
-          getUnknownFields().writeTo(output);
-        }
-
-        @java.lang.Override
-        public int getSerializedSize() {
-          int size = memoizedSize;
-          if (size != -1) return size;
-
-          size = 0;
-          if (java.lang.Double.doubleToRawLongBits(min_) != 0) {
-            size += com.google.protobuf.CodedOutputStream
-              .computeDoubleSize(1, min_);
-          }
-          if (java.lang.Double.doubleToRawLongBits(max_) != 0) {
-            size += com.google.protobuf.CodedOutputStream
-              .computeDoubleSize(2, max_);
-          }
-          size += getUnknownFields().getSerializedSize();
-          memoizedSize = size;
-          return size;
-        }
-
-        @java.lang.Override
-        public boolean equals(final java.lang.Object obj) {
-          if (obj == this) {
-           return true;
-          }
-          if (!(obj instanceof food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range)) {
-            return super.equals(obj);
-          }
-          food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range other = (food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range) obj;
-
-          if (java.lang.Double.doubleToLongBits(getMin())
-              != java.lang.Double.doubleToLongBits(
-                  other.getMin())) return false;
-          if (java.lang.Double.doubleToLongBits(getMax())
-              != java.lang.Double.doubleToLongBits(
-                  other.getMax())) return false;
-          if (!getUnknownFields().equals(other.getUnknownFields())) return false;
-          return true;
-        }
-
-        @java.lang.Override
-        public int hashCode() {
-          if (memoizedHashCode != 0) {
-            return memoizedHashCode;
-          }
-          int hash = 41;
-          hash = (19 * hash) + getDescriptor().hashCode();
-          hash = (37 * hash) + MIN_FIELD_NUMBER;
-          hash = (53 * hash) + com.google.protobuf.Internal.hashLong(
-              java.lang.Double.doubleToLongBits(getMin()));
-          hash = (37 * hash) + MAX_FIELD_NUMBER;
-          hash = (53 * hash) + com.google.protobuf.Internal.hashLong(
-              java.lang.Double.doubleToLongBits(getMax()));
-          hash = (29 * hash) + getUnknownFields().hashCode();
-          memoizedHashCode = hash;
-          return hash;
-        }
-
-        public static food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range parseFrom(
-            java.nio.ByteBuffer data)
-            throws com.google.protobuf.InvalidProtocolBufferException {
-          return PARSER.parseFrom(data);
-        }
-        public static food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range parseFrom(
-            java.nio.ByteBuffer data,
-            com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-            throws com.google.protobuf.InvalidProtocolBufferException {
-          return PARSER.parseFrom(data, extensionRegistry);
-        }
-        public static food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range parseFrom(
-            com.google.protobuf.ByteString data)
-            throws com.google.protobuf.InvalidProtocolBufferException {
-          return PARSER.parseFrom(data);
-        }
-        public static food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range parseFrom(
-            com.google.protobuf.ByteString data,
-            com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-            throws com.google.protobuf.InvalidProtocolBufferException {
-          return PARSER.parseFrom(data, extensionRegistry);
-        }
-        public static food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range parseFrom(byte[] data)
-            throws com.google.protobuf.InvalidProtocolBufferException {
-          return PARSER.parseFrom(data);
-        }
-        public static food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range parseFrom(
-            byte[] data,
-            com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-            throws com.google.protobuf.InvalidProtocolBufferException {
-          return PARSER.parseFrom(data, extensionRegistry);
-        }
-        public static food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range parseFrom(java.io.InputStream input)
-            throws java.io.IOException {
-          return com.google.protobuf.GeneratedMessageV3
-              .parseWithIOException(PARSER, input);
-        }
-        public static food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range parseFrom(
-            java.io.InputStream input,
-            com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-            throws java.io.IOException {
-          return com.google.protobuf.GeneratedMessageV3
-              .parseWithIOException(PARSER, input, extensionRegistry);
-        }
-        public static food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range parseDelimitedFrom(java.io.InputStream input)
-            throws java.io.IOException {
-          return com.google.protobuf.GeneratedMessageV3
-              .parseDelimitedWithIOException(PARSER, input);
-        }
-        public static food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range parseDelimitedFrom(
-            java.io.InputStream input,
-            com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-            throws java.io.IOException {
-          return com.google.protobuf.GeneratedMessageV3
-              .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
-        }
-        public static food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range parseFrom(
-            com.google.protobuf.CodedInputStream input)
-            throws java.io.IOException {
-          return com.google.protobuf.GeneratedMessageV3
-              .parseWithIOException(PARSER, input);
-        }
-        public static food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range parseFrom(
-            com.google.protobuf.CodedInputStream input,
-            com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-            throws java.io.IOException {
-          return com.google.protobuf.GeneratedMessageV3
-              .parseWithIOException(PARSER, input, extensionRegistry);
-        }
-
-        @java.lang.Override
-        public Builder newBuilderForType() { return newBuilder(); }
-        public static Builder newBuilder() {
-          return DEFAULT_INSTANCE.toBuilder();
-        }
-        public static Builder newBuilder(food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range prototype) {
-          return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
-        }
-        @java.lang.Override
-        public Builder toBuilder() {
-          return this == DEFAULT_INSTANCE
-              ? new Builder() : new Builder().mergeFrom(this);
-        }
-
-        @java.lang.Override
-        protected Builder newBuilderForType(
-            com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-          Builder builder = new Builder(parent);
-          return builder;
-        }
-        /**
-         * <pre>
-         * Describes a closed range for the nutrition value. E.g. "100-150 cal"
-         * </pre>
-         *
-         * Protobuf type {@code food.menu.v1.NutritionInformation.NutritionValue.Range}
-         */
-        public static final class Builder extends
-            com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
-            // @@protoc_insertion_point(builder_implements:food.menu.v1.NutritionInformation.NutritionValue.Range)
-            food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.RangeOrBuilder {
-          public static final com.google.protobuf.Descriptors.Descriptor
-              getDescriptor() {
-            return food.menu.v1.FoodMenu.internal_static_food_menu_v1_NutritionInformation_NutritionValue_Range_descriptor;
-          }
-
-          @java.lang.Override
-          protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-              internalGetFieldAccessorTable() {
-            return food.menu.v1.FoodMenu.internal_static_food_menu_v1_NutritionInformation_NutritionValue_Range_fieldAccessorTable
-                .ensureFieldAccessorsInitialized(
-                    food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range.class, food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range.Builder.class);
-          }
-
-          // Construct using food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range.newBuilder()
-          private Builder() {
-
-          }
-
-          private Builder(
-              com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-            super(parent);
-
-          }
-          @java.lang.Override
-          public Builder clear() {
-            super.clear();
-            bitField0_ = 0;
-            min_ = 0D;
-            max_ = 0D;
-            return this;
-          }
-
-          @java.lang.Override
-          public com.google.protobuf.Descriptors.Descriptor
-              getDescriptorForType() {
-            return food.menu.v1.FoodMenu.internal_static_food_menu_v1_NutritionInformation_NutritionValue_Range_descriptor;
-          }
-
-          @java.lang.Override
-          public food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range getDefaultInstanceForType() {
-            return food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range.getDefaultInstance();
-          }
-
-          @java.lang.Override
-          public food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range build() {
-            food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range result = buildPartial();
-            if (!result.isInitialized()) {
-              throw newUninitializedMessageException(result);
-            }
-            return result;
-          }
-
-          @java.lang.Override
-          public food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range buildPartial() {
-            food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range result = new food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range(this);
-            if (bitField0_ != 0) { buildPartial0(result); }
-            onBuilt();
-            return result;
-          }
-
-          private void buildPartial0(food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range result) {
-            int from_bitField0_ = bitField0_;
-            if (((from_bitField0_ & 0x00000001) != 0)) {
-              result.min_ = min_;
-            }
-            if (((from_bitField0_ & 0x00000002) != 0)) {
-              result.max_ = max_;
-            }
-          }
-
-          @java.lang.Override
-          public Builder mergeFrom(com.google.protobuf.Message other) {
-            if (other instanceof food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range) {
-              return mergeFrom((food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range)other);
-            } else {
-              super.mergeFrom(other);
-              return this;
-            }
-          }
-
-          public Builder mergeFrom(food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range other) {
-            if (other == food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range.getDefaultInstance()) return this;
-            if (other.getMin() != 0D) {
-              setMin(other.getMin());
-            }
-            if (other.getMax() != 0D) {
-              setMax(other.getMax());
-            }
-            this.mergeUnknownFields(other.getUnknownFields());
-            onChanged();
-            return this;
-          }
-
-          @java.lang.Override
-          public final boolean isInitialized() {
-            return true;
-          }
-
-          @java.lang.Override
-          public Builder mergeFrom(
-              com.google.protobuf.CodedInputStream input,
-              com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-              throws java.io.IOException {
-            if (extensionRegistry == null) {
-              throw new java.lang.NullPointerException();
-            }
-            try {
-              boolean done = false;
-              while (!done) {
-                int tag = input.readTag();
-                switch (tag) {
-                  case 0:
-                    done = true;
-                    break;
-                  case 9: {
-                    min_ = input.readDouble();
-                    bitField0_ |= 0x00000001;
-                    break;
-                  } // case 9
-                  case 17: {
-                    max_ = input.readDouble();
-                    bitField0_ |= 0x00000002;
-                    break;
-                  } // case 17
-                  default: {
-                    if (!super.parseUnknownField(input, extensionRegistry, tag)) {
-                      done = true; // was an endgroup tag
-                    }
-                    break;
-                  } // default:
-                } // switch (tag)
-              } // while (!done)
-            } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-              throw e.unwrapIOException();
-            } finally {
-              onChanged();
-            } // finally
-            return this;
-          }
-          private int bitField0_;
-
-          private double min_ ;
-          /**
-           * <pre>
-           * The minimum amount of nutrition value.
-           * Required.
-           * </pre>
-           *
-           * <code>double min = 1;</code>
-           * @return The min.
-           */
-          @java.lang.Override
-          public double getMin() {
-            return min_;
-          }
-          /**
-           * <pre>
-           * The minimum amount of nutrition value.
-           * Required.
-           * </pre>
-           *
-           * <code>double min = 1;</code>
-           * @param value The min to set.
-           * @return This builder for chaining.
-           */
-          public Builder setMin(double value) {
-
-            min_ = value;
-            bitField0_ |= 0x00000001;
-            onChanged();
-            return this;
-          }
-          /**
-           * <pre>
-           * The minimum amount of nutrition value.
-           * Required.
-           * </pre>
-           *
-           * <code>double min = 1;</code>
-           * @return This builder for chaining.
-           */
-          public Builder clearMin() {
-            bitField0_ = (bitField0_ & ~0x00000001);
-            min_ = 0D;
-            onChanged();
-            return this;
-          }
-
-          private double max_ ;
-          /**
-           * <pre>
-           * The maximum amount of nutrition value.
-           * Required.
-           * </pre>
-           *
-           * <code>double max = 2;</code>
-           * @return The max.
-           */
-          @java.lang.Override
-          public double getMax() {
-            return max_;
-          }
-          /**
-           * <pre>
-           * The maximum amount of nutrition value.
-           * Required.
-           * </pre>
-           *
-           * <code>double max = 2;</code>
-           * @param value The max to set.
-           * @return This builder for chaining.
-           */
-          public Builder setMax(double value) {
-
-            max_ = value;
-            bitField0_ |= 0x00000002;
-            onChanged();
-            return this;
-          }
-          /**
-           * <pre>
-           * The maximum amount of nutrition value.
-           * Required.
-           * </pre>
-           *
-           * <code>double max = 2;</code>
-           * @return This builder for chaining.
-           */
-          public Builder clearMax() {
-            bitField0_ = (bitField0_ & ~0x00000002);
-            max_ = 0D;
-            onChanged();
-            return this;
-          }
-          @java.lang.Override
-          public final Builder setUnknownFields(
-              final com.google.protobuf.UnknownFieldSet unknownFields) {
-            return super.setUnknownFields(unknownFields);
-          }
-
-          @java.lang.Override
-          public final Builder mergeUnknownFields(
-              final com.google.protobuf.UnknownFieldSet unknownFields) {
-            return super.mergeUnknownFields(unknownFields);
-          }
-
-
-          // @@protoc_insertion_point(builder_scope:food.menu.v1.NutritionInformation.NutritionValue.Range)
-        }
-
-        // @@protoc_insertion_point(class_scope:food.menu.v1.NutritionInformation.NutritionValue.Range)
-        private static final food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range DEFAULT_INSTANCE;
-        static {
-          DEFAULT_INSTANCE = new food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range();
-        }
-
-        public static food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range getDefaultInstance() {
-          return DEFAULT_INSTANCE;
-        }
-
-        private static final com.google.protobuf.Parser<Range>
-            PARSER = new com.google.protobuf.AbstractParser<Range>() {
-          @java.lang.Override
-          public Range parsePartialFrom(
-              com.google.protobuf.CodedInputStream input,
-              com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-              throws com.google.protobuf.InvalidProtocolBufferException {
-            Builder builder = newBuilder();
-            try {
-              builder.mergeFrom(input, extensionRegistry);
-            } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-              throw e.setUnfinishedMessage(builder.buildPartial());
-            } catch (com.google.protobuf.UninitializedMessageException e) {
-              throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
-            } catch (java.io.IOException e) {
-              throw new com.google.protobuf.InvalidProtocolBufferException(e)
-                  .setUnfinishedMessage(builder.buildPartial());
-            }
-            return builder.buildPartial();
-          }
-        };
-
-        public static com.google.protobuf.Parser<Range> parser() {
-          return PARSER;
-        }
-
-        @java.lang.Override
-        public com.google.protobuf.Parser<Range> getParserForType() {
-          return PARSER;
-        }
-
-        @java.lang.Override
-        public food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range getDefaultInstanceForType() {
-          return DEFAULT_INSTANCE;
-        }
-
-      }
-
-      private int valueCase_ = 0;
-      @SuppressWarnings("serial")
-      private java.lang.Object value_;
-      public enum ValueCase
-          implements com.google.protobuf.Internal.EnumLite,
-              com.google.protobuf.AbstractMessage.InternalOneOfEnum {
-        AMOUNT(1),
-        RANGE(3),
-        VALUE_NOT_SET(0);
-        private final int value;
-        private ValueCase(int value) {
-          this.value = value;
-        }
-        /**
-         * @param value The number of the enum to look for.
-         * @return The enum associated with the given number.
-         * @deprecated Use {@link #forNumber(int)} instead.
-         */
-        @java.lang.Deprecated
-        public static ValueCase valueOf(int value) {
-          return forNumber(value);
-        }
-
-        public static ValueCase forNumber(int value) {
-          switch (value) {
-            case 1: return AMOUNT;
-            case 3: return RANGE;
-            case 0: return VALUE_NOT_SET;
-            default: return null;
-          }
-        }
-        public int getNumber() {
-          return this.value;
-        }
-      };
-
-      public ValueCase
-      getValueCase() {
-        return ValueCase.forNumber(
-            valueCase_);
-      }
-
-      public static final int AMOUNT_FIELD_NUMBER = 1;
-      /**
-       * <pre>
-       * A single number representing the amount of nutritional value.
-       * </pre>
-       *
-       * <code>double amount = 1;</code>
-       * @return Whether the amount field is set.
-       */
-      @java.lang.Override
-      public boolean hasAmount() {
-        return valueCase_ == 1;
-      }
-      /**
-       * <pre>
-       * A single number representing the amount of nutritional value.
-       * </pre>
-       *
-       * <code>double amount = 1;</code>
-       * @return The amount.
-       */
-      @java.lang.Override
-      public double getAmount() {
-        if (valueCase_ == 1) {
-          return (java.lang.Double) value_;
-        }
-        return 0D;
-      }
-
-      public static final int RANGE_FIELD_NUMBER = 3;
-      /**
-       * <pre>
-       * A range representing the amount of nutritional value.
-       * </pre>
-       *
-       * <code>.food.menu.v1.NutritionInformation.NutritionValue.Range range = 3;</code>
-       * @return Whether the range field is set.
-       */
-      @java.lang.Override
-      public boolean hasRange() {
-        return valueCase_ == 3;
-      }
-      /**
-       * <pre>
-       * A range representing the amount of nutritional value.
-       * </pre>
-       *
-       * <code>.food.menu.v1.NutritionInformation.NutritionValue.Range range = 3;</code>
-       * @return The range.
-       */
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range getRange() {
-        if (valueCase_ == 3) {
-           return (food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range) value_;
-        }
-        return food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range.getDefaultInstance();
-      }
-      /**
-       * <pre>
-       * A range representing the amount of nutritional value.
-       * </pre>
-       *
-       * <code>.food.menu.v1.NutritionInformation.NutritionValue.Range range = 3;</code>
-       */
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.RangeOrBuilder getRangeOrBuilder() {
-        if (valueCase_ == 3) {
-           return (food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range) value_;
-        }
-        return food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range.getDefaultInstance();
-      }
-
-      public static final int UNIT_FIELD_NUMBER = 2;
-      private int unit_ = 0;
-      /**
-       * <pre>
-       * The unit associated with the amount as specified from the partner. We
-       * will validate the feed so that the unit for each type of nutrition value
-       * is expected for that type of value. For example, only ENERGY_CALORIES
-       * and ENERGY_KILOJOULES are expected on energy property of
-       * NutritionalInformation.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.NutritionValueUnit unit = 2;</code>
-       * @return The enum numeric value on the wire for unit.
-       */
-      @java.lang.Override public int getUnitValue() {
-        return unit_;
-      }
-      /**
-       * <pre>
-       * The unit associated with the amount as specified from the partner. We
-       * will validate the feed so that the unit for each type of nutrition value
-       * is expected for that type of value. For example, only ENERGY_CALORIES
-       * and ENERGY_KILOJOULES are expected on energy property of
-       * NutritionalInformation.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.NutritionValueUnit unit = 2;</code>
-       * @return The unit.
-       */
-      @java.lang.Override public food.menu.v1.FoodMenu.NutritionValueUnit getUnit() {
-        food.menu.v1.FoodMenu.NutritionValueUnit result = food.menu.v1.FoodMenu.NutritionValueUnit.forNumber(unit_);
-        return result == null ? food.menu.v1.FoodMenu.NutritionValueUnit.UNRECOGNIZED : result;
-      }
-
-      private byte memoizedIsInitialized = -1;
-      @java.lang.Override
-      public final boolean isInitialized() {
-        byte isInitialized = memoizedIsInitialized;
-        if (isInitialized == 1) return true;
-        if (isInitialized == 0) return false;
-
-        memoizedIsInitialized = 1;
-        return true;
-      }
-
-      @java.lang.Override
-      public void writeTo(com.google.protobuf.CodedOutputStream output)
-                          throws java.io.IOException {
-        if (valueCase_ == 1) {
-          output.writeDouble(
-              1, (double)((java.lang.Double) value_));
-        }
-        if (unit_ != food.menu.v1.FoodMenu.NutritionValueUnit.NUTRITION_VALUE_UNIT_UNSPECIFIED.getNumber()) {
-          output.writeEnum(2, unit_);
-        }
-        if (valueCase_ == 3) {
-          output.writeMessage(3, (food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range) value_);
-        }
-        getUnknownFields().writeTo(output);
-      }
-
-      @java.lang.Override
-      public int getSerializedSize() {
-        int size = memoizedSize;
-        if (size != -1) return size;
-
-        size = 0;
-        if (valueCase_ == 1) {
-          size += com.google.protobuf.CodedOutputStream
-            .computeDoubleSize(
-                1, (double)((java.lang.Double) value_));
-        }
-        if (unit_ != food.menu.v1.FoodMenu.NutritionValueUnit.NUTRITION_VALUE_UNIT_UNSPECIFIED.getNumber()) {
-          size += com.google.protobuf.CodedOutputStream
-            .computeEnumSize(2, unit_);
-        }
-        if (valueCase_ == 3) {
-          size += com.google.protobuf.CodedOutputStream
-            .computeMessageSize(3, (food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range) value_);
-        }
-        size += getUnknownFields().getSerializedSize();
-        memoizedSize = size;
-        return size;
-      }
-
-      @java.lang.Override
-      public boolean equals(final java.lang.Object obj) {
-        if (obj == this) {
-         return true;
-        }
-        if (!(obj instanceof food.menu.v1.FoodMenu.NutritionInformation.NutritionValue)) {
-          return super.equals(obj);
-        }
-        food.menu.v1.FoodMenu.NutritionInformation.NutritionValue other = (food.menu.v1.FoodMenu.NutritionInformation.NutritionValue) obj;
-
-        if (unit_ != other.unit_) return false;
-        if (!getValueCase().equals(other.getValueCase())) return false;
-        switch (valueCase_) {
-          case 1:
-            if (java.lang.Double.doubleToLongBits(getAmount())
-                != java.lang.Double.doubleToLongBits(
-                    other.getAmount())) return false;
-            break;
-          case 3:
-            if (!getRange()
-                .equals(other.getRange())) return false;
-            break;
-          case 0:
-          default:
-        }
-        if (!getUnknownFields().equals(other.getUnknownFields())) return false;
-        return true;
-      }
-
-      @java.lang.Override
-      public int hashCode() {
-        if (memoizedHashCode != 0) {
-          return memoizedHashCode;
-        }
-        int hash = 41;
-        hash = (19 * hash) + getDescriptor().hashCode();
-        hash = (37 * hash) + UNIT_FIELD_NUMBER;
-        hash = (53 * hash) + unit_;
-        switch (valueCase_) {
-          case 1:
-            hash = (37 * hash) + AMOUNT_FIELD_NUMBER;
-            hash = (53 * hash) + com.google.protobuf.Internal.hashLong(
-                java.lang.Double.doubleToLongBits(getAmount()));
-            break;
-          case 3:
-            hash = (37 * hash) + RANGE_FIELD_NUMBER;
-            hash = (53 * hash) + getRange().hashCode();
-            break;
-          case 0:
-          default:
-        }
-        hash = (29 * hash) + getUnknownFields().hashCode();
-        memoizedHashCode = hash;
-        return hash;
-      }
-
-      public static food.menu.v1.FoodMenu.NutritionInformation.NutritionValue parseFrom(
-          java.nio.ByteBuffer data)
-          throws com.google.protobuf.InvalidProtocolBufferException {
-        return PARSER.parseFrom(data);
-      }
-      public static food.menu.v1.FoodMenu.NutritionInformation.NutritionValue parseFrom(
-          java.nio.ByteBuffer data,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws com.google.protobuf.InvalidProtocolBufferException {
-        return PARSER.parseFrom(data, extensionRegistry);
-      }
-      public static food.menu.v1.FoodMenu.NutritionInformation.NutritionValue parseFrom(
-          com.google.protobuf.ByteString data)
-          throws com.google.protobuf.InvalidProtocolBufferException {
-        return PARSER.parseFrom(data);
-      }
-      public static food.menu.v1.FoodMenu.NutritionInformation.NutritionValue parseFrom(
-          com.google.protobuf.ByteString data,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws com.google.protobuf.InvalidProtocolBufferException {
-        return PARSER.parseFrom(data, extensionRegistry);
-      }
-      public static food.menu.v1.FoodMenu.NutritionInformation.NutritionValue parseFrom(byte[] data)
-          throws com.google.protobuf.InvalidProtocolBufferException {
-        return PARSER.parseFrom(data);
-      }
-      public static food.menu.v1.FoodMenu.NutritionInformation.NutritionValue parseFrom(
-          byte[] data,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws com.google.protobuf.InvalidProtocolBufferException {
-        return PARSER.parseFrom(data, extensionRegistry);
-      }
-      public static food.menu.v1.FoodMenu.NutritionInformation.NutritionValue parseFrom(java.io.InputStream input)
-          throws java.io.IOException {
-        return com.google.protobuf.GeneratedMessageV3
-            .parseWithIOException(PARSER, input);
-      }
-      public static food.menu.v1.FoodMenu.NutritionInformation.NutritionValue parseFrom(
-          java.io.InputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws java.io.IOException {
-        return com.google.protobuf.GeneratedMessageV3
-            .parseWithIOException(PARSER, input, extensionRegistry);
-      }
-      public static food.menu.v1.FoodMenu.NutritionInformation.NutritionValue parseDelimitedFrom(java.io.InputStream input)
-          throws java.io.IOException {
-        return com.google.protobuf.GeneratedMessageV3
-            .parseDelimitedWithIOException(PARSER, input);
-      }
-      public static food.menu.v1.FoodMenu.NutritionInformation.NutritionValue parseDelimitedFrom(
-          java.io.InputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws java.io.IOException {
-        return com.google.protobuf.GeneratedMessageV3
-            .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
-      }
-      public static food.menu.v1.FoodMenu.NutritionInformation.NutritionValue parseFrom(
-          com.google.protobuf.CodedInputStream input)
-          throws java.io.IOException {
-        return com.google.protobuf.GeneratedMessageV3
-            .parseWithIOException(PARSER, input);
-      }
-      public static food.menu.v1.FoodMenu.NutritionInformation.NutritionValue parseFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws java.io.IOException {
-        return com.google.protobuf.GeneratedMessageV3
-            .parseWithIOException(PARSER, input, extensionRegistry);
-      }
-
-      @java.lang.Override
-      public Builder newBuilderForType() { return newBuilder(); }
-      public static Builder newBuilder() {
-        return DEFAULT_INSTANCE.toBuilder();
-      }
-      public static Builder newBuilder(food.menu.v1.FoodMenu.NutritionInformation.NutritionValue prototype) {
-        return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
-      }
-      @java.lang.Override
-      public Builder toBuilder() {
-        return this == DEFAULT_INSTANCE
-            ? new Builder() : new Builder().mergeFrom(this);
-      }
-
-      @java.lang.Override
-      protected Builder newBuilderForType(
-          com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-        Builder builder = new Builder(parent);
-        return builder;
-      }
-      /**
-       * <pre>
-       * Describes a single nutritional measurement of the serving of food.
-       * </pre>
-       *
-       * Protobuf type {@code food.menu.v1.NutritionInformation.NutritionValue}
-       */
-      public static final class Builder extends
-          com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
-          // @@protoc_insertion_point(builder_implements:food.menu.v1.NutritionInformation.NutritionValue)
-          food.menu.v1.FoodMenu.NutritionInformation.NutritionValueOrBuilder {
-        public static final com.google.protobuf.Descriptors.Descriptor
-            getDescriptor() {
-          return food.menu.v1.FoodMenu.internal_static_food_menu_v1_NutritionInformation_NutritionValue_descriptor;
-        }
-
-        @java.lang.Override
-        protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-            internalGetFieldAccessorTable() {
-          return food.menu.v1.FoodMenu.internal_static_food_menu_v1_NutritionInformation_NutritionValue_fieldAccessorTable
-              .ensureFieldAccessorsInitialized(
-                  food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.class, food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Builder.class);
-        }
-
-        // Construct using food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.newBuilder()
-        private Builder() {
-
-        }
-
-        private Builder(
-            com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-          super(parent);
-
-        }
-        @java.lang.Override
-        public Builder clear() {
-          super.clear();
-          bitField0_ = 0;
-          if (rangeBuilder_ != null) {
-            rangeBuilder_.clear();
-          }
-          unit_ = 0;
-          valueCase_ = 0;
-          value_ = null;
-          return this;
-        }
-
-        @java.lang.Override
-        public com.google.protobuf.Descriptors.Descriptor
-            getDescriptorForType() {
-          return food.menu.v1.FoodMenu.internal_static_food_menu_v1_NutritionInformation_NutritionValue_descriptor;
-        }
-
-        @java.lang.Override
-        public food.menu.v1.FoodMenu.NutritionInformation.NutritionValue getDefaultInstanceForType() {
-          return food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.getDefaultInstance();
-        }
-
-        @java.lang.Override
-        public food.menu.v1.FoodMenu.NutritionInformation.NutritionValue build() {
-          food.menu.v1.FoodMenu.NutritionInformation.NutritionValue result = buildPartial();
-          if (!result.isInitialized()) {
-            throw newUninitializedMessageException(result);
-          }
-          return result;
-        }
-
-        @java.lang.Override
-        public food.menu.v1.FoodMenu.NutritionInformation.NutritionValue buildPartial() {
-          food.menu.v1.FoodMenu.NutritionInformation.NutritionValue result = new food.menu.v1.FoodMenu.NutritionInformation.NutritionValue(this);
-          if (bitField0_ != 0) { buildPartial0(result); }
-          buildPartialOneofs(result);
-          onBuilt();
-          return result;
-        }
-
-        private void buildPartial0(food.menu.v1.FoodMenu.NutritionInformation.NutritionValue result) {
-          int from_bitField0_ = bitField0_;
-          if (((from_bitField0_ & 0x00000004) != 0)) {
-            result.unit_ = unit_;
-          }
-        }
-
-        private void buildPartialOneofs(food.menu.v1.FoodMenu.NutritionInformation.NutritionValue result) {
-          result.valueCase_ = valueCase_;
-          result.value_ = this.value_;
-          if (valueCase_ == 3 &&
-              rangeBuilder_ != null) {
-            result.value_ = rangeBuilder_.build();
-          }
-        }
-
-        @java.lang.Override
-        public Builder mergeFrom(com.google.protobuf.Message other) {
-          if (other instanceof food.menu.v1.FoodMenu.NutritionInformation.NutritionValue) {
-            return mergeFrom((food.menu.v1.FoodMenu.NutritionInformation.NutritionValue)other);
-          } else {
-            super.mergeFrom(other);
-            return this;
-          }
-        }
-
-        public Builder mergeFrom(food.menu.v1.FoodMenu.NutritionInformation.NutritionValue other) {
-          if (other == food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.getDefaultInstance()) return this;
-          if (other.unit_ != 0) {
-            setUnitValue(other.getUnitValue());
-          }
-          switch (other.getValueCase()) {
-            case AMOUNT: {
-              setAmount(other.getAmount());
-              break;
-            }
-            case RANGE: {
-              mergeRange(other.getRange());
-              break;
-            }
-            case VALUE_NOT_SET: {
-              break;
-            }
-          }
-          this.mergeUnknownFields(other.getUnknownFields());
-          onChanged();
-          return this;
-        }
-
-        @java.lang.Override
-        public final boolean isInitialized() {
-          return true;
-        }
-
-        @java.lang.Override
-        public Builder mergeFrom(
-            com.google.protobuf.CodedInputStream input,
-            com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-            throws java.io.IOException {
-          if (extensionRegistry == null) {
-            throw new java.lang.NullPointerException();
-          }
-          try {
-            boolean done = false;
-            while (!done) {
-              int tag = input.readTag();
-              switch (tag) {
-                case 0:
-                  done = true;
-                  break;
-                case 9: {
-                  value_ = input.readDouble();
-                  valueCase_ = 1;
-                  break;
-                } // case 9
-                case 16: {
-                  unit_ = input.readEnum();
-                  bitField0_ |= 0x00000004;
-                  break;
-                } // case 16
-                case 26: {
-                  input.readMessage(
-                      getRangeFieldBuilder().getBuilder(),
-                      extensionRegistry);
-                  valueCase_ = 3;
-                  break;
-                } // case 26
-                default: {
-                  if (!super.parseUnknownField(input, extensionRegistry, tag)) {
-                    done = true; // was an endgroup tag
-                  }
-                  break;
-                } // default:
-              } // switch (tag)
-            } // while (!done)
-          } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-            throw e.unwrapIOException();
-          } finally {
-            onChanged();
-          } // finally
-          return this;
-        }
-        private int valueCase_ = 0;
-        private java.lang.Object value_;
-        public ValueCase
-            getValueCase() {
-          return ValueCase.forNumber(
-              valueCase_);
-        }
-
-        public Builder clearValue() {
-          valueCase_ = 0;
-          value_ = null;
-          onChanged();
-          return this;
-        }
-
-        private int bitField0_;
-
-        /**
-         * <pre>
-         * A single number representing the amount of nutritional value.
-         * </pre>
-         *
-         * <code>double amount = 1;</code>
-         * @return Whether the amount field is set.
-         */
-        public boolean hasAmount() {
-          return valueCase_ == 1;
-        }
-        /**
-         * <pre>
-         * A single number representing the amount of nutritional value.
-         * </pre>
-         *
-         * <code>double amount = 1;</code>
-         * @return The amount.
-         */
-        public double getAmount() {
-          if (valueCase_ == 1) {
-            return (java.lang.Double) value_;
-          }
-          return 0D;
-        }
-        /**
-         * <pre>
-         * A single number representing the amount of nutritional value.
-         * </pre>
-         *
-         * <code>double amount = 1;</code>
-         * @param value The amount to set.
-         * @return This builder for chaining.
-         */
-        public Builder setAmount(double value) {
-
-          valueCase_ = 1;
-          value_ = value;
-          onChanged();
-          return this;
-        }
-        /**
-         * <pre>
-         * A single number representing the amount of nutritional value.
-         * </pre>
-         *
-         * <code>double amount = 1;</code>
-         * @return This builder for chaining.
-         */
-        public Builder clearAmount() {
-          if (valueCase_ == 1) {
-            valueCase_ = 0;
-            value_ = null;
-            onChanged();
-          }
-          return this;
-        }
-
-        private com.google.protobuf.SingleFieldBuilderV3<
-            food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range, food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range.Builder, food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.RangeOrBuilder> rangeBuilder_;
-        /**
-         * <pre>
-         * A range representing the amount of nutritional value.
-         * </pre>
-         *
-         * <code>.food.menu.v1.NutritionInformation.NutritionValue.Range range = 3;</code>
-         * @return Whether the range field is set.
-         */
-        @java.lang.Override
-        public boolean hasRange() {
-          return valueCase_ == 3;
-        }
-        /**
-         * <pre>
-         * A range representing the amount of nutritional value.
-         * </pre>
-         *
-         * <code>.food.menu.v1.NutritionInformation.NutritionValue.Range range = 3;</code>
-         * @return The range.
-         */
-        @java.lang.Override
-        public food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range getRange() {
-          if (rangeBuilder_ == null) {
-            if (valueCase_ == 3) {
-              return (food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range) value_;
-            }
-            return food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range.getDefaultInstance();
-          } else {
-            if (valueCase_ == 3) {
-              return rangeBuilder_.getMessage();
-            }
-            return food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range.getDefaultInstance();
-          }
-        }
-        /**
-         * <pre>
-         * A range representing the amount of nutritional value.
-         * </pre>
-         *
-         * <code>.food.menu.v1.NutritionInformation.NutritionValue.Range range = 3;</code>
-         */
-        public Builder setRange(food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range value) {
-          if (rangeBuilder_ == null) {
-            if (value == null) {
-              throw new NullPointerException();
-            }
-            value_ = value;
-            onChanged();
-          } else {
-            rangeBuilder_.setMessage(value);
-          }
-          valueCase_ = 3;
-          return this;
-        }
-        /**
-         * <pre>
-         * A range representing the amount of nutritional value.
-         * </pre>
-         *
-         * <code>.food.menu.v1.NutritionInformation.NutritionValue.Range range = 3;</code>
-         */
-        public Builder setRange(
-            food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range.Builder builderForValue) {
-          if (rangeBuilder_ == null) {
-            value_ = builderForValue.build();
-            onChanged();
-          } else {
-            rangeBuilder_.setMessage(builderForValue.build());
-          }
-          valueCase_ = 3;
-          return this;
-        }
-        /**
-         * <pre>
-         * A range representing the amount of nutritional value.
-         * </pre>
-         *
-         * <code>.food.menu.v1.NutritionInformation.NutritionValue.Range range = 3;</code>
-         */
-        public Builder mergeRange(food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range value) {
-          if (rangeBuilder_ == null) {
-            if (valueCase_ == 3 &&
-                value_ != food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range.getDefaultInstance()) {
-              value_ = food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range.newBuilder((food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range) value_)
-                  .mergeFrom(value).buildPartial();
-            } else {
-              value_ = value;
-            }
-            onChanged();
-          } else {
-            if (valueCase_ == 3) {
-              rangeBuilder_.mergeFrom(value);
-            } else {
-              rangeBuilder_.setMessage(value);
-            }
-          }
-          valueCase_ = 3;
-          return this;
-        }
-        /**
-         * <pre>
-         * A range representing the amount of nutritional value.
-         * </pre>
-         *
-         * <code>.food.menu.v1.NutritionInformation.NutritionValue.Range range = 3;</code>
-         */
-        public Builder clearRange() {
-          if (rangeBuilder_ == null) {
-            if (valueCase_ == 3) {
-              valueCase_ = 0;
-              value_ = null;
-              onChanged();
-            }
-          } else {
-            if (valueCase_ == 3) {
-              valueCase_ = 0;
-              value_ = null;
-            }
-            rangeBuilder_.clear();
-          }
-          return this;
-        }
-        /**
-         * <pre>
-         * A range representing the amount of nutritional value.
-         * </pre>
-         *
-         * <code>.food.menu.v1.NutritionInformation.NutritionValue.Range range = 3;</code>
-         */
-        public food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range.Builder getRangeBuilder() {
-          return getRangeFieldBuilder().getBuilder();
-        }
-        /**
-         * <pre>
-         * A range representing the amount of nutritional value.
-         * </pre>
-         *
-         * <code>.food.menu.v1.NutritionInformation.NutritionValue.Range range = 3;</code>
-         */
-        @java.lang.Override
-        public food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.RangeOrBuilder getRangeOrBuilder() {
-          if ((valueCase_ == 3) && (rangeBuilder_ != null)) {
-            return rangeBuilder_.getMessageOrBuilder();
-          } else {
-            if (valueCase_ == 3) {
-              return (food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range) value_;
-            }
-            return food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range.getDefaultInstance();
-          }
-        }
-        /**
-         * <pre>
-         * A range representing the amount of nutritional value.
-         * </pre>
-         *
-         * <code>.food.menu.v1.NutritionInformation.NutritionValue.Range range = 3;</code>
-         */
-        private com.google.protobuf.SingleFieldBuilderV3<
-            food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range, food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range.Builder, food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.RangeOrBuilder> 
-            getRangeFieldBuilder() {
-          if (rangeBuilder_ == null) {
-            if (!(valueCase_ == 3)) {
-              value_ = food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range.getDefaultInstance();
-            }
-            rangeBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
-                food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range, food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range.Builder, food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.RangeOrBuilder>(
-                    (food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Range) value_,
-                    getParentForChildren(),
-                    isClean());
-            value_ = null;
-          }
-          valueCase_ = 3;
-          onChanged();
-          return rangeBuilder_;
-        }
-
-        private int unit_ = 0;
-        /**
-         * <pre>
-         * The unit associated with the amount as specified from the partner. We
-         * will validate the feed so that the unit for each type of nutrition value
-         * is expected for that type of value. For example, only ENERGY_CALORIES
-         * and ENERGY_KILOJOULES are expected on energy property of
-         * NutritionalInformation.
-         * Required.
-         * </pre>
-         *
-         * <code>.food.menu.v1.NutritionValueUnit unit = 2;</code>
-         * @return The enum numeric value on the wire for unit.
-         */
-        @java.lang.Override public int getUnitValue() {
-          return unit_;
-        }
-        /**
-         * <pre>
-         * The unit associated with the amount as specified from the partner. We
-         * will validate the feed so that the unit for each type of nutrition value
-         * is expected for that type of value. For example, only ENERGY_CALORIES
-         * and ENERGY_KILOJOULES are expected on energy property of
-         * NutritionalInformation.
-         * Required.
-         * </pre>
-         *
-         * <code>.food.menu.v1.NutritionValueUnit unit = 2;</code>
-         * @param value The enum numeric value on the wire for unit to set.
-         * @return This builder for chaining.
-         */
-        public Builder setUnitValue(int value) {
-          unit_ = value;
-          bitField0_ |= 0x00000004;
-          onChanged();
-          return this;
-        }
-        /**
-         * <pre>
-         * The unit associated with the amount as specified from the partner. We
-         * will validate the feed so that the unit for each type of nutrition value
-         * is expected for that type of value. For example, only ENERGY_CALORIES
-         * and ENERGY_KILOJOULES are expected on energy property of
-         * NutritionalInformation.
-         * Required.
-         * </pre>
-         *
-         * <code>.food.menu.v1.NutritionValueUnit unit = 2;</code>
-         * @return The unit.
-         */
-        @java.lang.Override
-        public food.menu.v1.FoodMenu.NutritionValueUnit getUnit() {
-          food.menu.v1.FoodMenu.NutritionValueUnit result = food.menu.v1.FoodMenu.NutritionValueUnit.forNumber(unit_);
-          return result == null ? food.menu.v1.FoodMenu.NutritionValueUnit.UNRECOGNIZED : result;
-        }
-        /**
-         * <pre>
-         * The unit associated with the amount as specified from the partner. We
-         * will validate the feed so that the unit for each type of nutrition value
-         * is expected for that type of value. For example, only ENERGY_CALORIES
-         * and ENERGY_KILOJOULES are expected on energy property of
-         * NutritionalInformation.
-         * Required.
-         * </pre>
-         *
-         * <code>.food.menu.v1.NutritionValueUnit unit = 2;</code>
-         * @param value The unit to set.
-         * @return This builder for chaining.
-         */
-        public Builder setUnit(food.menu.v1.FoodMenu.NutritionValueUnit value) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          bitField0_ |= 0x00000004;
-          unit_ = value.getNumber();
-          onChanged();
-          return this;
-        }
-        /**
-         * <pre>
-         * The unit associated with the amount as specified from the partner. We
-         * will validate the feed so that the unit for each type of nutrition value
-         * is expected for that type of value. For example, only ENERGY_CALORIES
-         * and ENERGY_KILOJOULES are expected on energy property of
-         * NutritionalInformation.
-         * Required.
-         * </pre>
-         *
-         * <code>.food.menu.v1.NutritionValueUnit unit = 2;</code>
-         * @return This builder for chaining.
-         */
-        public Builder clearUnit() {
-          bitField0_ = (bitField0_ & ~0x00000004);
-          unit_ = 0;
-          onChanged();
-          return this;
-        }
-        @java.lang.Override
-        public final Builder setUnknownFields(
-            final com.google.protobuf.UnknownFieldSet unknownFields) {
-          return super.setUnknownFields(unknownFields);
-        }
-
-        @java.lang.Override
-        public final Builder mergeUnknownFields(
-            final com.google.protobuf.UnknownFieldSet unknownFields) {
-          return super.mergeUnknownFields(unknownFields);
-        }
-
-
-        // @@protoc_insertion_point(builder_scope:food.menu.v1.NutritionInformation.NutritionValue)
-      }
-
-      // @@protoc_insertion_point(class_scope:food.menu.v1.NutritionInformation.NutritionValue)
-      private static final food.menu.v1.FoodMenu.NutritionInformation.NutritionValue DEFAULT_INSTANCE;
-      static {
-        DEFAULT_INSTANCE = new food.menu.v1.FoodMenu.NutritionInformation.NutritionValue();
-      }
-
-      public static food.menu.v1.FoodMenu.NutritionInformation.NutritionValue getDefaultInstance() {
-        return DEFAULT_INSTANCE;
-      }
-
-      private static final com.google.protobuf.Parser<NutritionValue>
-          PARSER = new com.google.protobuf.AbstractParser<NutritionValue>() {
-        @java.lang.Override
-        public NutritionValue parsePartialFrom(
-            com.google.protobuf.CodedInputStream input,
-            com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-            throws com.google.protobuf.InvalidProtocolBufferException {
-          Builder builder = newBuilder();
-          try {
-            builder.mergeFrom(input, extensionRegistry);
-          } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-            throw e.setUnfinishedMessage(builder.buildPartial());
-          } catch (com.google.protobuf.UninitializedMessageException e) {
-            throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
-          } catch (java.io.IOException e) {
-            throw new com.google.protobuf.InvalidProtocolBufferException(e)
-                .setUnfinishedMessage(builder.buildPartial());
-          }
-          return builder.buildPartial();
-        }
-      };
-
-      public static com.google.protobuf.Parser<NutritionValue> parser() {
-        return PARSER;
-      }
-
-      @java.lang.Override
-      public com.google.protobuf.Parser<NutritionValue> getParserForType() {
-        return PARSER;
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.NutritionInformation.NutritionValue getDefaultInstanceForType() {
-        return DEFAULT_INSTANCE;
-      }
-
-    }
-
-    private int bitField0_;
-    public static final int ENERGY_FIELD_NUMBER = 1;
-    private food.menu.v1.FoodMenu.NutritionInformation.NutritionValue energy_;
-    /**
-     * <pre>
-     * The amount of nutritional energy of the serving of food. Can be defined
-     * in Calories or kilojoules.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.NutritionInformation.NutritionValue energy = 1;</code>
-     * @return Whether the energy field is set.
-     */
-    @java.lang.Override
-    public boolean hasEnergy() {
-      return energy_ != null;
-    }
-    /**
-     * <pre>
-     * The amount of nutritional energy of the serving of food. Can be defined
-     * in Calories or kilojoules.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.NutritionInformation.NutritionValue energy = 1;</code>
-     * @return The energy.
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.NutritionInformation.NutritionValue getEnergy() {
-      return energy_ == null ? food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.getDefaultInstance() : energy_;
-    }
-    /**
-     * <pre>
-     * The amount of nutritional energy of the serving of food. Can be defined
-     * in Calories or kilojoules.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.NutritionInformation.NutritionValue energy = 1;</code>
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.NutritionInformation.NutritionValueOrBuilder getEnergyOrBuilder() {
-      return energy_ == null ? food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.getDefaultInstance() : energy_;
-    }
-
-    public static final int SODIUM_CONTENT_FIELD_NUMBER = 2;
-    private food.menu.v1.FoodMenu.NutritionInformation.NutritionValue sodiumContent_;
-    /**
-     * <pre>
-     * The amount of sodium content, measured in grams or milligrams.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.NutritionInformation.NutritionValue sodium_content = 2;</code>
-     * @return Whether the sodiumContent field is set.
-     */
-    @java.lang.Override
-    public boolean hasSodiumContent() {
-      return sodiumContent_ != null;
-    }
-    /**
-     * <pre>
-     * The amount of sodium content, measured in grams or milligrams.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.NutritionInformation.NutritionValue sodium_content = 2;</code>
-     * @return The sodiumContent.
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.NutritionInformation.NutritionValue getSodiumContent() {
-      return sodiumContent_ == null ? food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.getDefaultInstance() : sodiumContent_;
-    }
-    /**
-     * <pre>
-     * The amount of sodium content, measured in grams or milligrams.
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.NutritionInformation.NutritionValue sodium_content = 2;</code>
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.NutritionInformation.NutritionValueOrBuilder getSodiumContentOrBuilder() {
-      return sodiumContent_ == null ? food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.getDefaultInstance() : sodiumContent_;
-    }
-
-    public static final int SERVING_SIZE_FIELD_NUMBER = 3;
-    private int servingSize_ = 0;
-    /**
-     * <pre>
-     * The number of servings the nutrition value applies to.
-     * Optional.
-     * </pre>
-     *
-     * <code>optional int32 serving_size = 3;</code>
-     * @return Whether the servingSize field is set.
-     */
-    @java.lang.Override
-    public boolean hasServingSize() {
-      return ((bitField0_ & 0x00000001) != 0);
-    }
-    /**
-     * <pre>
-     * The number of servings the nutrition value applies to.
-     * Optional.
-     * </pre>
-     *
-     * <code>optional int32 serving_size = 3;</code>
-     * @return The servingSize.
-     */
-    @java.lang.Override
-    public int getServingSize() {
-      return servingSize_;
-    }
-
-    public static final int DESCRIPTION_FIELD_NUMBER = 4;
-    private food.menu.v1.FoodMenu.TextField description_;
-    /**
-     * <pre>
-     * Nutrition information in free text. For example "Contains preservatives".
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField description = 4;</code>
-     * @return Whether the description field is set.
-     */
-    @java.lang.Override
-    public boolean hasDescription() {
-      return description_ != null;
-    }
-    /**
-     * <pre>
-     * Nutrition information in free text. For example "Contains preservatives".
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField description = 4;</code>
-     * @return The description.
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.TextField getDescription() {
-      return description_ == null ? food.menu.v1.FoodMenu.TextField.getDefaultInstance() : description_;
-    }
-    /**
-     * <pre>
-     * Nutrition information in free text. For example "Contains preservatives".
-     * Optional.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField description = 4;</code>
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.TextFieldOrBuilder getDescriptionOrBuilder() {
-      return description_ == null ? food.menu.v1.FoodMenu.TextField.getDefaultInstance() : description_;
-    }
-
-    private byte memoizedIsInitialized = -1;
-    @java.lang.Override
-    public final boolean isInitialized() {
-      byte isInitialized = memoizedIsInitialized;
-      if (isInitialized == 1) return true;
-      if (isInitialized == 0) return false;
-
-      memoizedIsInitialized = 1;
-      return true;
-    }
-
-    @java.lang.Override
-    public void writeTo(com.google.protobuf.CodedOutputStream output)
-                        throws java.io.IOException {
-      if (energy_ != null) {
-        output.writeMessage(1, getEnergy());
-      }
-      if (sodiumContent_ != null) {
-        output.writeMessage(2, getSodiumContent());
-      }
-      if (((bitField0_ & 0x00000001) != 0)) {
-        output.writeInt32(3, servingSize_);
-      }
-      if (description_ != null) {
-        output.writeMessage(4, getDescription());
-      }
-      getUnknownFields().writeTo(output);
-    }
-
-    @java.lang.Override
-    public int getSerializedSize() {
-      int size = memoizedSize;
-      if (size != -1) return size;
-
-      size = 0;
-      if (energy_ != null) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(1, getEnergy());
-      }
-      if (sodiumContent_ != null) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(2, getSodiumContent());
-      }
-      if (((bitField0_ & 0x00000001) != 0)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeInt32Size(3, servingSize_);
-      }
-      if (description_ != null) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(4, getDescription());
-      }
-      size += getUnknownFields().getSerializedSize();
-      memoizedSize = size;
-      return size;
-    }
-
-    @java.lang.Override
-    public boolean equals(final java.lang.Object obj) {
-      if (obj == this) {
-       return true;
-      }
-      if (!(obj instanceof food.menu.v1.FoodMenu.NutritionInformation)) {
-        return super.equals(obj);
-      }
-      food.menu.v1.FoodMenu.NutritionInformation other = (food.menu.v1.FoodMenu.NutritionInformation) obj;
-
-      if (hasEnergy() != other.hasEnergy()) return false;
-      if (hasEnergy()) {
-        if (!getEnergy()
-            .equals(other.getEnergy())) return false;
-      }
-      if (hasSodiumContent() != other.hasSodiumContent()) return false;
-      if (hasSodiumContent()) {
-        if (!getSodiumContent()
-            .equals(other.getSodiumContent())) return false;
-      }
-      if (hasServingSize() != other.hasServingSize()) return false;
-      if (hasServingSize()) {
-        if (getServingSize()
-            != other.getServingSize()) return false;
-      }
-      if (hasDescription() != other.hasDescription()) return false;
-      if (hasDescription()) {
-        if (!getDescription()
-            .equals(other.getDescription())) return false;
-      }
-      if (!getUnknownFields().equals(other.getUnknownFields())) return false;
-      return true;
-    }
-
-    @java.lang.Override
-    public int hashCode() {
-      if (memoizedHashCode != 0) {
-        return memoizedHashCode;
-      }
-      int hash = 41;
-      hash = (19 * hash) + getDescriptor().hashCode();
-      if (hasEnergy()) {
-        hash = (37 * hash) + ENERGY_FIELD_NUMBER;
-        hash = (53 * hash) + getEnergy().hashCode();
-      }
-      if (hasSodiumContent()) {
-        hash = (37 * hash) + SODIUM_CONTENT_FIELD_NUMBER;
-        hash = (53 * hash) + getSodiumContent().hashCode();
-      }
-      if (hasServingSize()) {
-        hash = (37 * hash) + SERVING_SIZE_FIELD_NUMBER;
-        hash = (53 * hash) + getServingSize();
-      }
-      if (hasDescription()) {
-        hash = (37 * hash) + DESCRIPTION_FIELD_NUMBER;
-        hash = (53 * hash) + getDescription().hashCode();
-      }
-      hash = (29 * hash) + getUnknownFields().hashCode();
-      memoizedHashCode = hash;
-      return hash;
-    }
-
-    public static food.menu.v1.FoodMenu.NutritionInformation parseFrom(
-        java.nio.ByteBuffer data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.NutritionInformation parseFrom(
-        java.nio.ByteBuffer data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.NutritionInformation parseFrom(
-        com.google.protobuf.ByteString data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.NutritionInformation parseFrom(
-        com.google.protobuf.ByteString data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.NutritionInformation parseFrom(byte[] data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.NutritionInformation parseFrom(
-        byte[] data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.NutritionInformation parseFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.NutritionInformation parseFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.NutritionInformation parseDelimitedFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseDelimitedWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.NutritionInformation parseDelimitedFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.NutritionInformation parseFrom(
-        com.google.protobuf.CodedInputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.NutritionInformation parseFrom(
-        com.google.protobuf.CodedInputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input, extensionRegistry);
-    }
-
-    @java.lang.Override
-    public Builder newBuilderForType() { return newBuilder(); }
-    public static Builder newBuilder() {
-      return DEFAULT_INSTANCE.toBuilder();
-    }
-    public static Builder newBuilder(food.menu.v1.FoodMenu.NutritionInformation prototype) {
-      return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
-    }
-    @java.lang.Override
-    public Builder toBuilder() {
-      return this == DEFAULT_INSTANCE
-          ? new Builder() : new Builder().mergeFrom(this);
-    }
-
-    @java.lang.Override
-    protected Builder newBuilderForType(
-        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-      Builder builder = new Builder(parent);
-      return builder;
-    }
-    /**
-     * <pre>
-     * Describes all the nutritional measurements of a MenuItem or add-on.
-     * </pre>
-     *
-     * Protobuf type {@code food.menu.v1.NutritionInformation}
-     */
-    public static final class Builder extends
-        com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
-        // @@protoc_insertion_point(builder_implements:food.menu.v1.NutritionInformation)
-        food.menu.v1.FoodMenu.NutritionInformationOrBuilder {
-      public static final com.google.protobuf.Descriptors.Descriptor
-          getDescriptor() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_NutritionInformation_descriptor;
-      }
-
-      @java.lang.Override
-      protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-          internalGetFieldAccessorTable() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_NutritionInformation_fieldAccessorTable
-            .ensureFieldAccessorsInitialized(
-                food.menu.v1.FoodMenu.NutritionInformation.class, food.menu.v1.FoodMenu.NutritionInformation.Builder.class);
-      }
-
-      // Construct using food.menu.v1.FoodMenu.NutritionInformation.newBuilder()
-      private Builder() {
-
-      }
-
-      private Builder(
-          com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-        super(parent);
-
-      }
-      @java.lang.Override
-      public Builder clear() {
-        super.clear();
-        bitField0_ = 0;
-        energy_ = null;
-        if (energyBuilder_ != null) {
-          energyBuilder_.dispose();
-          energyBuilder_ = null;
-        }
-        sodiumContent_ = null;
-        if (sodiumContentBuilder_ != null) {
-          sodiumContentBuilder_.dispose();
-          sodiumContentBuilder_ = null;
-        }
-        servingSize_ = 0;
-        description_ = null;
-        if (descriptionBuilder_ != null) {
-          descriptionBuilder_.dispose();
-          descriptionBuilder_ = null;
-        }
-        return this;
-      }
-
-      @java.lang.Override
-      public com.google.protobuf.Descriptors.Descriptor
-          getDescriptorForType() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_NutritionInformation_descriptor;
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.NutritionInformation getDefaultInstanceForType() {
-        return food.menu.v1.FoodMenu.NutritionInformation.getDefaultInstance();
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.NutritionInformation build() {
-        food.menu.v1.FoodMenu.NutritionInformation result = buildPartial();
-        if (!result.isInitialized()) {
-          throw newUninitializedMessageException(result);
-        }
-        return result;
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.NutritionInformation buildPartial() {
-        food.menu.v1.FoodMenu.NutritionInformation result = new food.menu.v1.FoodMenu.NutritionInformation(this);
-        if (bitField0_ != 0) { buildPartial0(result); }
-        onBuilt();
-        return result;
-      }
-
-      private void buildPartial0(food.menu.v1.FoodMenu.NutritionInformation result) {
-        int from_bitField0_ = bitField0_;
-        if (((from_bitField0_ & 0x00000001) != 0)) {
-          result.energy_ = energyBuilder_ == null
-              ? energy_
-              : energyBuilder_.build();
-        }
-        if (((from_bitField0_ & 0x00000002) != 0)) {
-          result.sodiumContent_ = sodiumContentBuilder_ == null
-              ? sodiumContent_
-              : sodiumContentBuilder_.build();
-        }
-        int to_bitField0_ = 0;
-        if (((from_bitField0_ & 0x00000004) != 0)) {
-          result.servingSize_ = servingSize_;
-          to_bitField0_ |= 0x00000001;
-        }
-        if (((from_bitField0_ & 0x00000008) != 0)) {
-          result.description_ = descriptionBuilder_ == null
-              ? description_
-              : descriptionBuilder_.build();
-        }
-        result.bitField0_ |= to_bitField0_;
-      }
-
-      @java.lang.Override
-      public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof food.menu.v1.FoodMenu.NutritionInformation) {
-          return mergeFrom((food.menu.v1.FoodMenu.NutritionInformation)other);
-        } else {
-          super.mergeFrom(other);
-          return this;
-        }
-      }
-
-      public Builder mergeFrom(food.menu.v1.FoodMenu.NutritionInformation other) {
-        if (other == food.menu.v1.FoodMenu.NutritionInformation.getDefaultInstance()) return this;
-        if (other.hasEnergy()) {
-          mergeEnergy(other.getEnergy());
-        }
-        if (other.hasSodiumContent()) {
-          mergeSodiumContent(other.getSodiumContent());
-        }
-        if (other.hasServingSize()) {
-          setServingSize(other.getServingSize());
-        }
-        if (other.hasDescription()) {
-          mergeDescription(other.getDescription());
-        }
-        this.mergeUnknownFields(other.getUnknownFields());
-        onChanged();
-        return this;
-      }
-
-      @java.lang.Override
-      public final boolean isInitialized() {
-        return true;
-      }
-
-      @java.lang.Override
-      public Builder mergeFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws java.io.IOException {
-        if (extensionRegistry == null) {
-          throw new java.lang.NullPointerException();
-        }
-        try {
-          boolean done = false;
-          while (!done) {
-            int tag = input.readTag();
-            switch (tag) {
-              case 0:
-                done = true;
-                break;
-              case 10: {
-                input.readMessage(
-                    getEnergyFieldBuilder().getBuilder(),
-                    extensionRegistry);
-                bitField0_ |= 0x00000001;
-                break;
-              } // case 10
-              case 18: {
-                input.readMessage(
-                    getSodiumContentFieldBuilder().getBuilder(),
-                    extensionRegistry);
-                bitField0_ |= 0x00000002;
-                break;
-              } // case 18
-              case 24: {
-                servingSize_ = input.readInt32();
-                bitField0_ |= 0x00000004;
-                break;
-              } // case 24
-              case 34: {
-                input.readMessage(
-                    getDescriptionFieldBuilder().getBuilder(),
-                    extensionRegistry);
-                bitField0_ |= 0x00000008;
-                break;
-              } // case 34
-              default: {
-                if (!super.parseUnknownField(input, extensionRegistry, tag)) {
-                  done = true; // was an endgroup tag
-                }
-                break;
-              } // default:
-            } // switch (tag)
-          } // while (!done)
-        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          throw e.unwrapIOException();
-        } finally {
-          onChanged();
-        } // finally
-        return this;
-      }
-      private int bitField0_;
-
-      private food.menu.v1.FoodMenu.NutritionInformation.NutritionValue energy_;
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.NutritionInformation.NutritionValue, food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Builder, food.menu.v1.FoodMenu.NutritionInformation.NutritionValueOrBuilder> energyBuilder_;
-      /**
-       * <pre>
-       * The amount of nutritional energy of the serving of food. Can be defined
-       * in Calories or kilojoules.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.NutritionInformation.NutritionValue energy = 1;</code>
-       * @return Whether the energy field is set.
-       */
-      public boolean hasEnergy() {
-        return ((bitField0_ & 0x00000001) != 0);
-      }
-      /**
-       * <pre>
-       * The amount of nutritional energy of the serving of food. Can be defined
-       * in Calories or kilojoules.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.NutritionInformation.NutritionValue energy = 1;</code>
-       * @return The energy.
-       */
-      public food.menu.v1.FoodMenu.NutritionInformation.NutritionValue getEnergy() {
-        if (energyBuilder_ == null) {
-          return energy_ == null ? food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.getDefaultInstance() : energy_;
-        } else {
-          return energyBuilder_.getMessage();
-        }
-      }
-      /**
-       * <pre>
-       * The amount of nutritional energy of the serving of food. Can be defined
-       * in Calories or kilojoules.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.NutritionInformation.NutritionValue energy = 1;</code>
-       */
-      public Builder setEnergy(food.menu.v1.FoodMenu.NutritionInformation.NutritionValue value) {
-        if (energyBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          energy_ = value;
-        } else {
-          energyBuilder_.setMessage(value);
-        }
-        bitField0_ |= 0x00000001;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * The amount of nutritional energy of the serving of food. Can be defined
-       * in Calories or kilojoules.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.NutritionInformation.NutritionValue energy = 1;</code>
-       */
-      public Builder setEnergy(
-          food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Builder builderForValue) {
-        if (energyBuilder_ == null) {
-          energy_ = builderForValue.build();
-        } else {
-          energyBuilder_.setMessage(builderForValue.build());
-        }
-        bitField0_ |= 0x00000001;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * The amount of nutritional energy of the serving of food. Can be defined
-       * in Calories or kilojoules.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.NutritionInformation.NutritionValue energy = 1;</code>
-       */
-      public Builder mergeEnergy(food.menu.v1.FoodMenu.NutritionInformation.NutritionValue value) {
-        if (energyBuilder_ == null) {
-          if (((bitField0_ & 0x00000001) != 0) &&
-            energy_ != null &&
-            energy_ != food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.getDefaultInstance()) {
-            getEnergyBuilder().mergeFrom(value);
-          } else {
-            energy_ = value;
-          }
-        } else {
-          energyBuilder_.mergeFrom(value);
-        }
-        bitField0_ |= 0x00000001;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * The amount of nutritional energy of the serving of food. Can be defined
-       * in Calories or kilojoules.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.NutritionInformation.NutritionValue energy = 1;</code>
-       */
-      public Builder clearEnergy() {
-        bitField0_ = (bitField0_ & ~0x00000001);
-        energy_ = null;
-        if (energyBuilder_ != null) {
-          energyBuilder_.dispose();
-          energyBuilder_ = null;
-        }
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * The amount of nutritional energy of the serving of food. Can be defined
-       * in Calories or kilojoules.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.NutritionInformation.NutritionValue energy = 1;</code>
-       */
-      public food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Builder getEnergyBuilder() {
-        bitField0_ |= 0x00000001;
-        onChanged();
-        return getEnergyFieldBuilder().getBuilder();
-      }
-      /**
-       * <pre>
-       * The amount of nutritional energy of the serving of food. Can be defined
-       * in Calories or kilojoules.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.NutritionInformation.NutritionValue energy = 1;</code>
-       */
-      public food.menu.v1.FoodMenu.NutritionInformation.NutritionValueOrBuilder getEnergyOrBuilder() {
-        if (energyBuilder_ != null) {
-          return energyBuilder_.getMessageOrBuilder();
-        } else {
-          return energy_ == null ?
-              food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.getDefaultInstance() : energy_;
-        }
-      }
-      /**
-       * <pre>
-       * The amount of nutritional energy of the serving of food. Can be defined
-       * in Calories or kilojoules.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.NutritionInformation.NutritionValue energy = 1;</code>
-       */
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.NutritionInformation.NutritionValue, food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Builder, food.menu.v1.FoodMenu.NutritionInformation.NutritionValueOrBuilder> 
-          getEnergyFieldBuilder() {
-        if (energyBuilder_ == null) {
-          energyBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
-              food.menu.v1.FoodMenu.NutritionInformation.NutritionValue, food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Builder, food.menu.v1.FoodMenu.NutritionInformation.NutritionValueOrBuilder>(
-                  getEnergy(),
-                  getParentForChildren(),
-                  isClean());
-          energy_ = null;
-        }
-        return energyBuilder_;
-      }
-
-      private food.menu.v1.FoodMenu.NutritionInformation.NutritionValue sodiumContent_;
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.NutritionInformation.NutritionValue, food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Builder, food.menu.v1.FoodMenu.NutritionInformation.NutritionValueOrBuilder> sodiumContentBuilder_;
-      /**
-       * <pre>
-       * The amount of sodium content, measured in grams or milligrams.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.NutritionInformation.NutritionValue sodium_content = 2;</code>
-       * @return Whether the sodiumContent field is set.
-       */
-      public boolean hasSodiumContent() {
-        return ((bitField0_ & 0x00000002) != 0);
-      }
-      /**
-       * <pre>
-       * The amount of sodium content, measured in grams or milligrams.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.NutritionInformation.NutritionValue sodium_content = 2;</code>
-       * @return The sodiumContent.
-       */
-      public food.menu.v1.FoodMenu.NutritionInformation.NutritionValue getSodiumContent() {
-        if (sodiumContentBuilder_ == null) {
-          return sodiumContent_ == null ? food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.getDefaultInstance() : sodiumContent_;
-        } else {
-          return sodiumContentBuilder_.getMessage();
-        }
-      }
-      /**
-       * <pre>
-       * The amount of sodium content, measured in grams or milligrams.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.NutritionInformation.NutritionValue sodium_content = 2;</code>
-       */
-      public Builder setSodiumContent(food.menu.v1.FoodMenu.NutritionInformation.NutritionValue value) {
-        if (sodiumContentBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          sodiumContent_ = value;
-        } else {
-          sodiumContentBuilder_.setMessage(value);
-        }
-        bitField0_ |= 0x00000002;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * The amount of sodium content, measured in grams or milligrams.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.NutritionInformation.NutritionValue sodium_content = 2;</code>
-       */
-      public Builder setSodiumContent(
-          food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Builder builderForValue) {
-        if (sodiumContentBuilder_ == null) {
-          sodiumContent_ = builderForValue.build();
-        } else {
-          sodiumContentBuilder_.setMessage(builderForValue.build());
-        }
-        bitField0_ |= 0x00000002;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * The amount of sodium content, measured in grams or milligrams.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.NutritionInformation.NutritionValue sodium_content = 2;</code>
-       */
-      public Builder mergeSodiumContent(food.menu.v1.FoodMenu.NutritionInformation.NutritionValue value) {
-        if (sodiumContentBuilder_ == null) {
-          if (((bitField0_ & 0x00000002) != 0) &&
-            sodiumContent_ != null &&
-            sodiumContent_ != food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.getDefaultInstance()) {
-            getSodiumContentBuilder().mergeFrom(value);
-          } else {
-            sodiumContent_ = value;
-          }
-        } else {
-          sodiumContentBuilder_.mergeFrom(value);
-        }
-        bitField0_ |= 0x00000002;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * The amount of sodium content, measured in grams or milligrams.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.NutritionInformation.NutritionValue sodium_content = 2;</code>
-       */
-      public Builder clearSodiumContent() {
-        bitField0_ = (bitField0_ & ~0x00000002);
-        sodiumContent_ = null;
-        if (sodiumContentBuilder_ != null) {
-          sodiumContentBuilder_.dispose();
-          sodiumContentBuilder_ = null;
-        }
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * The amount of sodium content, measured in grams or milligrams.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.NutritionInformation.NutritionValue sodium_content = 2;</code>
-       */
-      public food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Builder getSodiumContentBuilder() {
-        bitField0_ |= 0x00000002;
-        onChanged();
-        return getSodiumContentFieldBuilder().getBuilder();
-      }
-      /**
-       * <pre>
-       * The amount of sodium content, measured in grams or milligrams.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.NutritionInformation.NutritionValue sodium_content = 2;</code>
-       */
-      public food.menu.v1.FoodMenu.NutritionInformation.NutritionValueOrBuilder getSodiumContentOrBuilder() {
-        if (sodiumContentBuilder_ != null) {
-          return sodiumContentBuilder_.getMessageOrBuilder();
-        } else {
-          return sodiumContent_ == null ?
-              food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.getDefaultInstance() : sodiumContent_;
-        }
-      }
-      /**
-       * <pre>
-       * The amount of sodium content, measured in grams or milligrams.
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.NutritionInformation.NutritionValue sodium_content = 2;</code>
-       */
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.NutritionInformation.NutritionValue, food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Builder, food.menu.v1.FoodMenu.NutritionInformation.NutritionValueOrBuilder> 
-          getSodiumContentFieldBuilder() {
-        if (sodiumContentBuilder_ == null) {
-          sodiumContentBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
-              food.menu.v1.FoodMenu.NutritionInformation.NutritionValue, food.menu.v1.FoodMenu.NutritionInformation.NutritionValue.Builder, food.menu.v1.FoodMenu.NutritionInformation.NutritionValueOrBuilder>(
-                  getSodiumContent(),
-                  getParentForChildren(),
-                  isClean());
-          sodiumContent_ = null;
-        }
-        return sodiumContentBuilder_;
-      }
-
-      private int servingSize_ ;
-      /**
-       * <pre>
-       * The number of servings the nutrition value applies to.
-       * Optional.
-       * </pre>
-       *
-       * <code>optional int32 serving_size = 3;</code>
-       * @return Whether the servingSize field is set.
-       */
-      @java.lang.Override
-      public boolean hasServingSize() {
-        return ((bitField0_ & 0x00000004) != 0);
-      }
-      /**
-       * <pre>
-       * The number of servings the nutrition value applies to.
-       * Optional.
-       * </pre>
-       *
-       * <code>optional int32 serving_size = 3;</code>
-       * @return The servingSize.
-       */
-      @java.lang.Override
-      public int getServingSize() {
-        return servingSize_;
-      }
-      /**
-       * <pre>
-       * The number of servings the nutrition value applies to.
-       * Optional.
-       * </pre>
-       *
-       * <code>optional int32 serving_size = 3;</code>
-       * @param value The servingSize to set.
-       * @return This builder for chaining.
-       */
-      public Builder setServingSize(int value) {
-
-        servingSize_ = value;
-        bitField0_ |= 0x00000004;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * The number of servings the nutrition value applies to.
-       * Optional.
-       * </pre>
-       *
-       * <code>optional int32 serving_size = 3;</code>
-       * @return This builder for chaining.
-       */
-      public Builder clearServingSize() {
-        bitField0_ = (bitField0_ & ~0x00000004);
-        servingSize_ = 0;
-        onChanged();
-        return this;
-      }
-
-      private food.menu.v1.FoodMenu.TextField description_;
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.TextField, food.menu.v1.FoodMenu.TextField.Builder, food.menu.v1.FoodMenu.TextFieldOrBuilder> descriptionBuilder_;
-      /**
-       * <pre>
-       * Nutrition information in free text. For example "Contains preservatives".
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField description = 4;</code>
-       * @return Whether the description field is set.
-       */
-      public boolean hasDescription() {
-        return ((bitField0_ & 0x00000008) != 0);
-      }
-      /**
-       * <pre>
-       * Nutrition information in free text. For example "Contains preservatives".
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField description = 4;</code>
-       * @return The description.
-       */
-      public food.menu.v1.FoodMenu.TextField getDescription() {
-        if (descriptionBuilder_ == null) {
-          return description_ == null ? food.menu.v1.FoodMenu.TextField.getDefaultInstance() : description_;
-        } else {
-          return descriptionBuilder_.getMessage();
-        }
-      }
-      /**
-       * <pre>
-       * Nutrition information in free text. For example "Contains preservatives".
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField description = 4;</code>
-       */
-      public Builder setDescription(food.menu.v1.FoodMenu.TextField value) {
-        if (descriptionBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          description_ = value;
-        } else {
-          descriptionBuilder_.setMessage(value);
-        }
-        bitField0_ |= 0x00000008;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Nutrition information in free text. For example "Contains preservatives".
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField description = 4;</code>
-       */
-      public Builder setDescription(
-          food.menu.v1.FoodMenu.TextField.Builder builderForValue) {
-        if (descriptionBuilder_ == null) {
-          description_ = builderForValue.build();
-        } else {
-          descriptionBuilder_.setMessage(builderForValue.build());
-        }
-        bitField0_ |= 0x00000008;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Nutrition information in free text. For example "Contains preservatives".
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField description = 4;</code>
-       */
-      public Builder mergeDescription(food.menu.v1.FoodMenu.TextField value) {
-        if (descriptionBuilder_ == null) {
-          if (((bitField0_ & 0x00000008) != 0) &&
-            description_ != null &&
-            description_ != food.menu.v1.FoodMenu.TextField.getDefaultInstance()) {
-            getDescriptionBuilder().mergeFrom(value);
-          } else {
-            description_ = value;
-          }
-        } else {
-          descriptionBuilder_.mergeFrom(value);
-        }
-        bitField0_ |= 0x00000008;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Nutrition information in free text. For example "Contains preservatives".
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField description = 4;</code>
-       */
-      public Builder clearDescription() {
-        bitField0_ = (bitField0_ & ~0x00000008);
-        description_ = null;
-        if (descriptionBuilder_ != null) {
-          descriptionBuilder_.dispose();
-          descriptionBuilder_ = null;
-        }
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Nutrition information in free text. For example "Contains preservatives".
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField description = 4;</code>
-       */
-      public food.menu.v1.FoodMenu.TextField.Builder getDescriptionBuilder() {
-        bitField0_ |= 0x00000008;
-        onChanged();
-        return getDescriptionFieldBuilder().getBuilder();
-      }
-      /**
-       * <pre>
-       * Nutrition information in free text. For example "Contains preservatives".
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField description = 4;</code>
-       */
-      public food.menu.v1.FoodMenu.TextFieldOrBuilder getDescriptionOrBuilder() {
-        if (descriptionBuilder_ != null) {
-          return descriptionBuilder_.getMessageOrBuilder();
-        } else {
-          return description_ == null ?
-              food.menu.v1.FoodMenu.TextField.getDefaultInstance() : description_;
-        }
-      }
-      /**
-       * <pre>
-       * Nutrition information in free text. For example "Contains preservatives".
-       * Optional.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField description = 4;</code>
-       */
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.TextField, food.menu.v1.FoodMenu.TextField.Builder, food.menu.v1.FoodMenu.TextFieldOrBuilder> 
-          getDescriptionFieldBuilder() {
-        if (descriptionBuilder_ == null) {
-          descriptionBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
-              food.menu.v1.FoodMenu.TextField, food.menu.v1.FoodMenu.TextField.Builder, food.menu.v1.FoodMenu.TextFieldOrBuilder>(
-                  getDescription(),
-                  getParentForChildren(),
-                  isClean());
-          description_ = null;
-        }
-        return descriptionBuilder_;
-      }
-      @java.lang.Override
-      public final Builder setUnknownFields(
-          final com.google.protobuf.UnknownFieldSet unknownFields) {
-        return super.setUnknownFields(unknownFields);
-      }
-
-      @java.lang.Override
-      public final Builder mergeUnknownFields(
-          final com.google.protobuf.UnknownFieldSet unknownFields) {
-        return super.mergeUnknownFields(unknownFields);
-      }
-
-
-      // @@protoc_insertion_point(builder_scope:food.menu.v1.NutritionInformation)
-    }
-
-    // @@protoc_insertion_point(class_scope:food.menu.v1.NutritionInformation)
-    private static final food.menu.v1.FoodMenu.NutritionInformation DEFAULT_INSTANCE;
-    static {
-      DEFAULT_INSTANCE = new food.menu.v1.FoodMenu.NutritionInformation();
-    }
-
-    public static food.menu.v1.FoodMenu.NutritionInformation getDefaultInstance() {
-      return DEFAULT_INSTANCE;
-    }
-
-    private static final com.google.protobuf.Parser<NutritionInformation>
-        PARSER = new com.google.protobuf.AbstractParser<NutritionInformation>() {
-      @java.lang.Override
-      public NutritionInformation parsePartialFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws com.google.protobuf.InvalidProtocolBufferException {
-        Builder builder = newBuilder();
-        try {
-          builder.mergeFrom(input, extensionRegistry);
-        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          throw e.setUnfinishedMessage(builder.buildPartial());
-        } catch (com.google.protobuf.UninitializedMessageException e) {
-          throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
-        } catch (java.io.IOException e) {
-          throw new com.google.protobuf.InvalidProtocolBufferException(e)
-              .setUnfinishedMessage(builder.buildPartial());
-        }
-        return builder.buildPartial();
-      }
-    };
-
-    public static com.google.protobuf.Parser<NutritionInformation> parser() {
-      return PARSER;
-    }
-
-    @java.lang.Override
-    public com.google.protobuf.Parser<NutritionInformation> getParserForType() {
-      return PARSER;
-    }
-
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.NutritionInformation getDefaultInstanceForType() {
-      return DEFAULT_INSTANCE;
-    }
-
-  }
-
-  public interface AdditiveOrBuilder extends
-      // @@protoc_insertion_point(interface_extends:food.menu.v1.Additive)
-      com.google.protobuf.MessageOrBuilder {
-
-    /**
-     * <pre>
-     * Descriptive text of the additive, e.g. "preservatives".
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField name = 1;</code>
-     * @return Whether the name field is set.
-     */
-    boolean hasName();
-    /**
-     * <pre>
-     * Descriptive text of the additive, e.g. "preservatives".
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField name = 1;</code>
-     * @return The name.
-     */
-    food.menu.v1.FoodMenu.TextField getName();
-    /**
-     * <pre>
-     * Descriptive text of the additive, e.g. "preservatives".
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField name = 1;</code>
-     */
-    food.menu.v1.FoodMenu.TextFieldOrBuilder getNameOrBuilder();
-
-    /**
-     * <pre>
-     * Whether the MenuItem contains, may contain, or is free from this additive.
-     * Defaults to contains.
-     * Optional.
-     * </pre>
-     *
-     * <code>optional .food.menu.v1.ContainmentLevelCode containment_level_code = 2;</code>
-     * @return Whether the containmentLevelCode field is set.
-     */
-    boolean hasContainmentLevelCode();
-    /**
-     * <pre>
-     * Whether the MenuItem contains, may contain, or is free from this additive.
-     * Defaults to contains.
-     * Optional.
-     * </pre>
-     *
-     * <code>optional .food.menu.v1.ContainmentLevelCode containment_level_code = 2;</code>
-     * @return The enum numeric value on the wire for containmentLevelCode.
-     */
-    int getContainmentLevelCodeValue();
-    /**
-     * <pre>
-     * Whether the MenuItem contains, may contain, or is free from this additive.
-     * Defaults to contains.
-     * Optional.
-     * </pre>
-     *
-     * <code>optional .food.menu.v1.ContainmentLevelCode containment_level_code = 2;</code>
-     * @return The containmentLevelCode.
-     */
-    food.menu.v1.FoodMenu.ContainmentLevelCode getContainmentLevelCode();
-  }
-  /**
-   * <pre>
-   * Additive shown to the user on the MenuItem. An additive preserves or enhances
-   * the quality of the food.
-   * </pre>
-   *
-   * Protobuf type {@code food.menu.v1.Additive}
-   */
-  public static final class Additive extends
-      com.google.protobuf.GeneratedMessageV3 implements
-      // @@protoc_insertion_point(message_implements:food.menu.v1.Additive)
-      AdditiveOrBuilder {
-  private static final long serialVersionUID = 0L;
-    // Use Additive.newBuilder() to construct.
-    private Additive(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
-      super(builder);
-    }
-    private Additive() {
-      containmentLevelCode_ = 0;
-    }
-
-    @java.lang.Override
-    @SuppressWarnings({"unused"})
-    protected java.lang.Object newInstance(
-        UnusedPrivateParameter unused) {
-      return new Additive();
-    }
-
-    public static final com.google.protobuf.Descriptors.Descriptor
-        getDescriptor() {
-      return food.menu.v1.FoodMenu.internal_static_food_menu_v1_Additive_descriptor;
-    }
-
-    @java.lang.Override
-    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-        internalGetFieldAccessorTable() {
-      return food.menu.v1.FoodMenu.internal_static_food_menu_v1_Additive_fieldAccessorTable
-          .ensureFieldAccessorsInitialized(
-              food.menu.v1.FoodMenu.Additive.class, food.menu.v1.FoodMenu.Additive.Builder.class);
-    }
-
-    private int bitField0_;
-    public static final int NAME_FIELD_NUMBER = 1;
-    private food.menu.v1.FoodMenu.TextField name_;
-    /**
-     * <pre>
-     * Descriptive text of the additive, e.g. "preservatives".
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField name = 1;</code>
-     * @return Whether the name field is set.
-     */
-    @java.lang.Override
-    public boolean hasName() {
-      return name_ != null;
-    }
-    /**
-     * <pre>
-     * Descriptive text of the additive, e.g. "preservatives".
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField name = 1;</code>
-     * @return The name.
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.TextField getName() {
-      return name_ == null ? food.menu.v1.FoodMenu.TextField.getDefaultInstance() : name_;
-    }
-    /**
-     * <pre>
-     * Descriptive text of the additive, e.g. "preservatives".
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.TextField name = 1;</code>
-     */
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.TextFieldOrBuilder getNameOrBuilder() {
-      return name_ == null ? food.menu.v1.FoodMenu.TextField.getDefaultInstance() : name_;
-    }
-
-    public static final int CONTAINMENT_LEVEL_CODE_FIELD_NUMBER = 2;
-    private int containmentLevelCode_ = 0;
-    /**
-     * <pre>
-     * Whether the MenuItem contains, may contain, or is free from this additive.
-     * Defaults to contains.
-     * Optional.
-     * </pre>
-     *
-     * <code>optional .food.menu.v1.ContainmentLevelCode containment_level_code = 2;</code>
-     * @return Whether the containmentLevelCode field is set.
-     */
-    @java.lang.Override public boolean hasContainmentLevelCode() {
-      return ((bitField0_ & 0x00000001) != 0);
-    }
-    /**
-     * <pre>
-     * Whether the MenuItem contains, may contain, or is free from this additive.
-     * Defaults to contains.
-     * Optional.
-     * </pre>
-     *
-     * <code>optional .food.menu.v1.ContainmentLevelCode containment_level_code = 2;</code>
-     * @return The enum numeric value on the wire for containmentLevelCode.
-     */
-    @java.lang.Override public int getContainmentLevelCodeValue() {
-      return containmentLevelCode_;
-    }
-    /**
-     * <pre>
-     * Whether the MenuItem contains, may contain, or is free from this additive.
-     * Defaults to contains.
-     * Optional.
-     * </pre>
-     *
-     * <code>optional .food.menu.v1.ContainmentLevelCode containment_level_code = 2;</code>
-     * @return The containmentLevelCode.
-     */
-    @java.lang.Override public food.menu.v1.FoodMenu.ContainmentLevelCode getContainmentLevelCode() {
-      food.menu.v1.FoodMenu.ContainmentLevelCode result = food.menu.v1.FoodMenu.ContainmentLevelCode.forNumber(containmentLevelCode_);
-      return result == null ? food.menu.v1.FoodMenu.ContainmentLevelCode.UNRECOGNIZED : result;
-    }
-
-    private byte memoizedIsInitialized = -1;
-    @java.lang.Override
-    public final boolean isInitialized() {
-      byte isInitialized = memoizedIsInitialized;
-      if (isInitialized == 1) return true;
-      if (isInitialized == 0) return false;
-
-      memoizedIsInitialized = 1;
-      return true;
-    }
-
-    @java.lang.Override
-    public void writeTo(com.google.protobuf.CodedOutputStream output)
-                        throws java.io.IOException {
-      if (name_ != null) {
-        output.writeMessage(1, getName());
-      }
-      if (((bitField0_ & 0x00000001) != 0)) {
-        output.writeEnum(2, containmentLevelCode_);
-      }
-      getUnknownFields().writeTo(output);
-    }
-
-    @java.lang.Override
-    public int getSerializedSize() {
-      int size = memoizedSize;
-      if (size != -1) return size;
-
-      size = 0;
-      if (name_ != null) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(1, getName());
-      }
-      if (((bitField0_ & 0x00000001) != 0)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeEnumSize(2, containmentLevelCode_);
-      }
-      size += getUnknownFields().getSerializedSize();
-      memoizedSize = size;
-      return size;
-    }
-
-    @java.lang.Override
-    public boolean equals(final java.lang.Object obj) {
-      if (obj == this) {
-       return true;
-      }
-      if (!(obj instanceof food.menu.v1.FoodMenu.Additive)) {
-        return super.equals(obj);
-      }
-      food.menu.v1.FoodMenu.Additive other = (food.menu.v1.FoodMenu.Additive) obj;
-
-      if (hasName() != other.hasName()) return false;
-      if (hasName()) {
-        if (!getName()
-            .equals(other.getName())) return false;
-      }
-      if (hasContainmentLevelCode() != other.hasContainmentLevelCode()) return false;
-      if (hasContainmentLevelCode()) {
-        if (containmentLevelCode_ != other.containmentLevelCode_) return false;
-      }
-      if (!getUnknownFields().equals(other.getUnknownFields())) return false;
-      return true;
-    }
-
-    @java.lang.Override
-    public int hashCode() {
-      if (memoizedHashCode != 0) {
-        return memoizedHashCode;
-      }
-      int hash = 41;
-      hash = (19 * hash) + getDescriptor().hashCode();
-      if (hasName()) {
-        hash = (37 * hash) + NAME_FIELD_NUMBER;
-        hash = (53 * hash) + getName().hashCode();
-      }
-      if (hasContainmentLevelCode()) {
-        hash = (37 * hash) + CONTAINMENT_LEVEL_CODE_FIELD_NUMBER;
-        hash = (53 * hash) + containmentLevelCode_;
-      }
-      hash = (29 * hash) + getUnknownFields().hashCode();
-      memoizedHashCode = hash;
-      return hash;
-    }
-
-    public static food.menu.v1.FoodMenu.Additive parseFrom(
-        java.nio.ByteBuffer data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.Additive parseFrom(
-        java.nio.ByteBuffer data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.Additive parseFrom(
-        com.google.protobuf.ByteString data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.Additive parseFrom(
-        com.google.protobuf.ByteString data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.Additive parseFrom(byte[] data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.Additive parseFrom(
-        byte[] data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.Additive parseFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.Additive parseFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.Additive parseDelimitedFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseDelimitedWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.Additive parseDelimitedFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.Additive parseFrom(
-        com.google.protobuf.CodedInputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.Additive parseFrom(
-        com.google.protobuf.CodedInputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input, extensionRegistry);
-    }
-
-    @java.lang.Override
-    public Builder newBuilderForType() { return newBuilder(); }
-    public static Builder newBuilder() {
-      return DEFAULT_INSTANCE.toBuilder();
-    }
-    public static Builder newBuilder(food.menu.v1.FoodMenu.Additive prototype) {
-      return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
-    }
-    @java.lang.Override
-    public Builder toBuilder() {
-      return this == DEFAULT_INSTANCE
-          ? new Builder() : new Builder().mergeFrom(this);
-    }
-
-    @java.lang.Override
-    protected Builder newBuilderForType(
-        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-      Builder builder = new Builder(parent);
-      return builder;
-    }
-    /**
-     * <pre>
-     * Additive shown to the user on the MenuItem. An additive preserves or enhances
-     * the quality of the food.
-     * </pre>
-     *
-     * Protobuf type {@code food.menu.v1.Additive}
-     */
-    public static final class Builder extends
-        com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
-        // @@protoc_insertion_point(builder_implements:food.menu.v1.Additive)
-        food.menu.v1.FoodMenu.AdditiveOrBuilder {
-      public static final com.google.protobuf.Descriptors.Descriptor
-          getDescriptor() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_Additive_descriptor;
-      }
-
-      @java.lang.Override
-      protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-          internalGetFieldAccessorTable() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_Additive_fieldAccessorTable
-            .ensureFieldAccessorsInitialized(
-                food.menu.v1.FoodMenu.Additive.class, food.menu.v1.FoodMenu.Additive.Builder.class);
-      }
-
-      // Construct using food.menu.v1.FoodMenu.Additive.newBuilder()
-      private Builder() {
-
-      }
-
-      private Builder(
-          com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-        super(parent);
-
-      }
-      @java.lang.Override
-      public Builder clear() {
-        super.clear();
-        bitField0_ = 0;
-        name_ = null;
-        if (nameBuilder_ != null) {
-          nameBuilder_.dispose();
-          nameBuilder_ = null;
-        }
-        containmentLevelCode_ = 0;
-        return this;
-      }
-
-      @java.lang.Override
-      public com.google.protobuf.Descriptors.Descriptor
-          getDescriptorForType() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_Additive_descriptor;
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.Additive getDefaultInstanceForType() {
-        return food.menu.v1.FoodMenu.Additive.getDefaultInstance();
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.Additive build() {
-        food.menu.v1.FoodMenu.Additive result = buildPartial();
-        if (!result.isInitialized()) {
-          throw newUninitializedMessageException(result);
-        }
-        return result;
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.Additive buildPartial() {
-        food.menu.v1.FoodMenu.Additive result = new food.menu.v1.FoodMenu.Additive(this);
-        if (bitField0_ != 0) { buildPartial0(result); }
-        onBuilt();
-        return result;
-      }
-
-      private void buildPartial0(food.menu.v1.FoodMenu.Additive result) {
-        int from_bitField0_ = bitField0_;
-        if (((from_bitField0_ & 0x00000001) != 0)) {
-          result.name_ = nameBuilder_ == null
-              ? name_
-              : nameBuilder_.build();
-        }
-        int to_bitField0_ = 0;
-        if (((from_bitField0_ & 0x00000002) != 0)) {
-          result.containmentLevelCode_ = containmentLevelCode_;
-          to_bitField0_ |= 0x00000001;
-        }
-        result.bitField0_ |= to_bitField0_;
-      }
-
-      @java.lang.Override
-      public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof food.menu.v1.FoodMenu.Additive) {
-          return mergeFrom((food.menu.v1.FoodMenu.Additive)other);
-        } else {
-          super.mergeFrom(other);
-          return this;
-        }
-      }
-
-      public Builder mergeFrom(food.menu.v1.FoodMenu.Additive other) {
-        if (other == food.menu.v1.FoodMenu.Additive.getDefaultInstance()) return this;
-        if (other.hasName()) {
-          mergeName(other.getName());
-        }
-        if (other.hasContainmentLevelCode()) {
-          setContainmentLevelCode(other.getContainmentLevelCode());
-        }
-        this.mergeUnknownFields(other.getUnknownFields());
-        onChanged();
-        return this;
-      }
-
-      @java.lang.Override
-      public final boolean isInitialized() {
-        return true;
-      }
-
-      @java.lang.Override
-      public Builder mergeFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws java.io.IOException {
-        if (extensionRegistry == null) {
-          throw new java.lang.NullPointerException();
-        }
-        try {
-          boolean done = false;
-          while (!done) {
-            int tag = input.readTag();
-            switch (tag) {
-              case 0:
-                done = true;
-                break;
-              case 10: {
-                input.readMessage(
-                    getNameFieldBuilder().getBuilder(),
-                    extensionRegistry);
-                bitField0_ |= 0x00000001;
-                break;
-              } // case 10
-              case 16: {
-                containmentLevelCode_ = input.readEnum();
-                bitField0_ |= 0x00000002;
-                break;
-              } // case 16
-              default: {
-                if (!super.parseUnknownField(input, extensionRegistry, tag)) {
-                  done = true; // was an endgroup tag
-                }
-                break;
-              } // default:
-            } // switch (tag)
-          } // while (!done)
-        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          throw e.unwrapIOException();
-        } finally {
-          onChanged();
-        } // finally
-        return this;
-      }
-      private int bitField0_;
-
-      private food.menu.v1.FoodMenu.TextField name_;
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.TextField, food.menu.v1.FoodMenu.TextField.Builder, food.menu.v1.FoodMenu.TextFieldOrBuilder> nameBuilder_;
-      /**
-       * <pre>
-       * Descriptive text of the additive, e.g. "preservatives".
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField name = 1;</code>
-       * @return Whether the name field is set.
-       */
-      public boolean hasName() {
-        return ((bitField0_ & 0x00000001) != 0);
-      }
-      /**
-       * <pre>
-       * Descriptive text of the additive, e.g. "preservatives".
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField name = 1;</code>
-       * @return The name.
-       */
-      public food.menu.v1.FoodMenu.TextField getName() {
-        if (nameBuilder_ == null) {
-          return name_ == null ? food.menu.v1.FoodMenu.TextField.getDefaultInstance() : name_;
-        } else {
-          return nameBuilder_.getMessage();
-        }
-      }
-      /**
-       * <pre>
-       * Descriptive text of the additive, e.g. "preservatives".
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField name = 1;</code>
-       */
-      public Builder setName(food.menu.v1.FoodMenu.TextField value) {
-        if (nameBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          name_ = value;
-        } else {
-          nameBuilder_.setMessage(value);
-        }
-        bitField0_ |= 0x00000001;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Descriptive text of the additive, e.g. "preservatives".
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField name = 1;</code>
-       */
-      public Builder setName(
-          food.menu.v1.FoodMenu.TextField.Builder builderForValue) {
-        if (nameBuilder_ == null) {
-          name_ = builderForValue.build();
-        } else {
-          nameBuilder_.setMessage(builderForValue.build());
-        }
-        bitField0_ |= 0x00000001;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Descriptive text of the additive, e.g. "preservatives".
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField name = 1;</code>
-       */
-      public Builder mergeName(food.menu.v1.FoodMenu.TextField value) {
-        if (nameBuilder_ == null) {
-          if (((bitField0_ & 0x00000001) != 0) &&
-            name_ != null &&
-            name_ != food.menu.v1.FoodMenu.TextField.getDefaultInstance()) {
-            getNameBuilder().mergeFrom(value);
-          } else {
-            name_ = value;
-          }
-        } else {
-          nameBuilder_.mergeFrom(value);
-        }
-        bitField0_ |= 0x00000001;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Descriptive text of the additive, e.g. "preservatives".
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField name = 1;</code>
-       */
-      public Builder clearName() {
-        bitField0_ = (bitField0_ & ~0x00000001);
-        name_ = null;
-        if (nameBuilder_ != null) {
-          nameBuilder_.dispose();
-          nameBuilder_ = null;
-        }
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Descriptive text of the additive, e.g. "preservatives".
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField name = 1;</code>
-       */
-      public food.menu.v1.FoodMenu.TextField.Builder getNameBuilder() {
-        bitField0_ |= 0x00000001;
-        onChanged();
-        return getNameFieldBuilder().getBuilder();
-      }
-      /**
-       * <pre>
-       * Descriptive text of the additive, e.g. "preservatives".
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField name = 1;</code>
-       */
-      public food.menu.v1.FoodMenu.TextFieldOrBuilder getNameOrBuilder() {
-        if (nameBuilder_ != null) {
-          return nameBuilder_.getMessageOrBuilder();
-        } else {
-          return name_ == null ?
-              food.menu.v1.FoodMenu.TextField.getDefaultInstance() : name_;
-        }
-      }
-      /**
-       * <pre>
-       * Descriptive text of the additive, e.g. "preservatives".
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.TextField name = 1;</code>
-       */
-      private com.google.protobuf.SingleFieldBuilderV3<
-          food.menu.v1.FoodMenu.TextField, food.menu.v1.FoodMenu.TextField.Builder, food.menu.v1.FoodMenu.TextFieldOrBuilder> 
-          getNameFieldBuilder() {
-        if (nameBuilder_ == null) {
-          nameBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
-              food.menu.v1.FoodMenu.TextField, food.menu.v1.FoodMenu.TextField.Builder, food.menu.v1.FoodMenu.TextFieldOrBuilder>(
-                  getName(),
-                  getParentForChildren(),
-                  isClean());
-          name_ = null;
-        }
-        return nameBuilder_;
-      }
-
-      private int containmentLevelCode_ = 0;
-      /**
-       * <pre>
-       * Whether the MenuItem contains, may contain, or is free from this additive.
-       * Defaults to contains.
-       * Optional.
-       * </pre>
-       *
-       * <code>optional .food.menu.v1.ContainmentLevelCode containment_level_code = 2;</code>
-       * @return Whether the containmentLevelCode field is set.
-       */
-      @java.lang.Override public boolean hasContainmentLevelCode() {
-        return ((bitField0_ & 0x00000002) != 0);
-      }
-      /**
-       * <pre>
-       * Whether the MenuItem contains, may contain, or is free from this additive.
-       * Defaults to contains.
-       * Optional.
-       * </pre>
-       *
-       * <code>optional .food.menu.v1.ContainmentLevelCode containment_level_code = 2;</code>
-       * @return The enum numeric value on the wire for containmentLevelCode.
-       */
-      @java.lang.Override public int getContainmentLevelCodeValue() {
-        return containmentLevelCode_;
-      }
-      /**
-       * <pre>
-       * Whether the MenuItem contains, may contain, or is free from this additive.
-       * Defaults to contains.
-       * Optional.
-       * </pre>
-       *
-       * <code>optional .food.menu.v1.ContainmentLevelCode containment_level_code = 2;</code>
-       * @param value The enum numeric value on the wire for containmentLevelCode to set.
-       * @return This builder for chaining.
-       */
-      public Builder setContainmentLevelCodeValue(int value) {
-        containmentLevelCode_ = value;
-        bitField0_ |= 0x00000002;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Whether the MenuItem contains, may contain, or is free from this additive.
-       * Defaults to contains.
-       * Optional.
-       * </pre>
-       *
-       * <code>optional .food.menu.v1.ContainmentLevelCode containment_level_code = 2;</code>
-       * @return The containmentLevelCode.
-       */
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.ContainmentLevelCode getContainmentLevelCode() {
-        food.menu.v1.FoodMenu.ContainmentLevelCode result = food.menu.v1.FoodMenu.ContainmentLevelCode.forNumber(containmentLevelCode_);
-        return result == null ? food.menu.v1.FoodMenu.ContainmentLevelCode.UNRECOGNIZED : result;
-      }
-      /**
-       * <pre>
-       * Whether the MenuItem contains, may contain, or is free from this additive.
-       * Defaults to contains.
-       * Optional.
-       * </pre>
-       *
-       * <code>optional .food.menu.v1.ContainmentLevelCode containment_level_code = 2;</code>
-       * @param value The containmentLevelCode to set.
-       * @return This builder for chaining.
-       */
-      public Builder setContainmentLevelCode(food.menu.v1.FoodMenu.ContainmentLevelCode value) {
-        if (value == null) {
-          throw new NullPointerException();
-        }
-        bitField0_ |= 0x00000002;
-        containmentLevelCode_ = value.getNumber();
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Whether the MenuItem contains, may contain, or is free from this additive.
-       * Defaults to contains.
-       * Optional.
-       * </pre>
-       *
-       * <code>optional .food.menu.v1.ContainmentLevelCode containment_level_code = 2;</code>
-       * @return This builder for chaining.
-       */
-      public Builder clearContainmentLevelCode() {
-        bitField0_ = (bitField0_ & ~0x00000002);
-        containmentLevelCode_ = 0;
-        onChanged();
-        return this;
-      }
-      @java.lang.Override
-      public final Builder setUnknownFields(
-          final com.google.protobuf.UnknownFieldSet unknownFields) {
-        return super.setUnknownFields(unknownFields);
-      }
-
-      @java.lang.Override
-      public final Builder mergeUnknownFields(
-          final com.google.protobuf.UnknownFieldSet unknownFields) {
-        return super.mergeUnknownFields(unknownFields);
-      }
-
-
-      // @@protoc_insertion_point(builder_scope:food.menu.v1.Additive)
-    }
-
-    // @@protoc_insertion_point(class_scope:food.menu.v1.Additive)
-    private static final food.menu.v1.FoodMenu.Additive DEFAULT_INSTANCE;
-    static {
-      DEFAULT_INSTANCE = new food.menu.v1.FoodMenu.Additive();
-    }
-
-    public static food.menu.v1.FoodMenu.Additive getDefaultInstance() {
-      return DEFAULT_INSTANCE;
-    }
-
-    private static final com.google.protobuf.Parser<Additive>
-        PARSER = new com.google.protobuf.AbstractParser<Additive>() {
-      @java.lang.Override
-      public Additive parsePartialFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws com.google.protobuf.InvalidProtocolBufferException {
-        Builder builder = newBuilder();
-        try {
-          builder.mergeFrom(input, extensionRegistry);
-        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          throw e.setUnfinishedMessage(builder.buildPartial());
-        } catch (com.google.protobuf.UninitializedMessageException e) {
-          throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
-        } catch (java.io.IOException e) {
-          throw new com.google.protobuf.InvalidProtocolBufferException(e)
-              .setUnfinishedMessage(builder.buildPartial());
-        }
-        return builder.buildPartial();
-      }
-    };
-
-    public static com.google.protobuf.Parser<Additive> parser() {
-      return PARSER;
-    }
-
-    @java.lang.Override
-    public com.google.protobuf.Parser<Additive> getParserForType() {
-      return PARSER;
-    }
-
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.Additive getDefaultInstanceForType() {
-      return DEFAULT_INSTANCE;
-    }
-
-  }
-
-  public interface AllergenOrBuilder extends
-      // @@protoc_insertion_point(interface_extends:food.menu.v1.Allergen)
-      com.google.protobuf.MessageOrBuilder {
-
-    /**
-     * <pre>
-     * Type of allergen.
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.AllergenTypeCode allergen_type_code = 1;</code>
-     * @return The enum numeric value on the wire for allergenTypeCode.
-     */
-    int getAllergenTypeCodeValue();
-    /**
-     * <pre>
-     * Type of allergen.
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.AllergenTypeCode allergen_type_code = 1;</code>
-     * @return The allergenTypeCode.
-     */
-    food.menu.v1.FoodMenu.AllergenTypeCode getAllergenTypeCode();
-
-    /**
-     * <pre>
-     * Whether the MenuItem contains, may contain, or is free from this allergen.
-     * Defaults to contains.
-     * Optional.
-     * </pre>
-     *
-     * <code>optional .food.menu.v1.ContainmentLevelCode containment_level_code = 2;</code>
-     * @return Whether the containmentLevelCode field is set.
-     */
-    boolean hasContainmentLevelCode();
-    /**
-     * <pre>
-     * Whether the MenuItem contains, may contain, or is free from this allergen.
-     * Defaults to contains.
-     * Optional.
-     * </pre>
-     *
-     * <code>optional .food.menu.v1.ContainmentLevelCode containment_level_code = 2;</code>
-     * @return The enum numeric value on the wire for containmentLevelCode.
-     */
-    int getContainmentLevelCodeValue();
-    /**
-     * <pre>
-     * Whether the MenuItem contains, may contain, or is free from this allergen.
-     * Defaults to contains.
-     * Optional.
-     * </pre>
-     *
-     * <code>optional .food.menu.v1.ContainmentLevelCode containment_level_code = 2;</code>
-     * @return The containmentLevelCode.
-     */
-    food.menu.v1.FoodMenu.ContainmentLevelCode getContainmentLevelCode();
-  }
-  /**
-   * <pre>
-   * Allergen shown to the user on the MenuItem. An allergen relates to qualities
-   * of food that causes allergic reactions.
-   * </pre>
-   *
-   * Protobuf type {@code food.menu.v1.Allergen}
-   */
-  public static final class Allergen extends
-      com.google.protobuf.GeneratedMessageV3 implements
-      // @@protoc_insertion_point(message_implements:food.menu.v1.Allergen)
-      AllergenOrBuilder {
-  private static final long serialVersionUID = 0L;
-    // Use Allergen.newBuilder() to construct.
-    private Allergen(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
-      super(builder);
-    }
-    private Allergen() {
-      allergenTypeCode_ = 0;
-      containmentLevelCode_ = 0;
-    }
-
-    @java.lang.Override
-    @SuppressWarnings({"unused"})
-    protected java.lang.Object newInstance(
-        UnusedPrivateParameter unused) {
-      return new Allergen();
-    }
-
-    public static final com.google.protobuf.Descriptors.Descriptor
-        getDescriptor() {
-      return food.menu.v1.FoodMenu.internal_static_food_menu_v1_Allergen_descriptor;
-    }
-
-    @java.lang.Override
-    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-        internalGetFieldAccessorTable() {
-      return food.menu.v1.FoodMenu.internal_static_food_menu_v1_Allergen_fieldAccessorTable
-          .ensureFieldAccessorsInitialized(
-              food.menu.v1.FoodMenu.Allergen.class, food.menu.v1.FoodMenu.Allergen.Builder.class);
-    }
-
-    private int bitField0_;
-    public static final int ALLERGEN_TYPE_CODE_FIELD_NUMBER = 1;
-    private int allergenTypeCode_ = 0;
-    /**
-     * <pre>
-     * Type of allergen.
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.AllergenTypeCode allergen_type_code = 1;</code>
-     * @return The enum numeric value on the wire for allergenTypeCode.
-     */
-    @java.lang.Override public int getAllergenTypeCodeValue() {
-      return allergenTypeCode_;
-    }
-    /**
-     * <pre>
-     * Type of allergen.
-     * Required.
-     * </pre>
-     *
-     * <code>.food.menu.v1.AllergenTypeCode allergen_type_code = 1;</code>
-     * @return The allergenTypeCode.
-     */
-    @java.lang.Override public food.menu.v1.FoodMenu.AllergenTypeCode getAllergenTypeCode() {
-      food.menu.v1.FoodMenu.AllergenTypeCode result = food.menu.v1.FoodMenu.AllergenTypeCode.forNumber(allergenTypeCode_);
-      return result == null ? food.menu.v1.FoodMenu.AllergenTypeCode.UNRECOGNIZED : result;
-    }
-
-    public static final int CONTAINMENT_LEVEL_CODE_FIELD_NUMBER = 2;
-    private int containmentLevelCode_ = 0;
-    /**
-     * <pre>
-     * Whether the MenuItem contains, may contain, or is free from this allergen.
-     * Defaults to contains.
-     * Optional.
-     * </pre>
-     *
-     * <code>optional .food.menu.v1.ContainmentLevelCode containment_level_code = 2;</code>
-     * @return Whether the containmentLevelCode field is set.
-     */
-    @java.lang.Override public boolean hasContainmentLevelCode() {
-      return ((bitField0_ & 0x00000001) != 0);
-    }
-    /**
-     * <pre>
-     * Whether the MenuItem contains, may contain, or is free from this allergen.
-     * Defaults to contains.
-     * Optional.
-     * </pre>
-     *
-     * <code>optional .food.menu.v1.ContainmentLevelCode containment_level_code = 2;</code>
-     * @return The enum numeric value on the wire for containmentLevelCode.
-     */
-    @java.lang.Override public int getContainmentLevelCodeValue() {
-      return containmentLevelCode_;
-    }
-    /**
-     * <pre>
-     * Whether the MenuItem contains, may contain, or is free from this allergen.
-     * Defaults to contains.
-     * Optional.
-     * </pre>
-     *
-     * <code>optional .food.menu.v1.ContainmentLevelCode containment_level_code = 2;</code>
-     * @return The containmentLevelCode.
-     */
-    @java.lang.Override public food.menu.v1.FoodMenu.ContainmentLevelCode getContainmentLevelCode() {
-      food.menu.v1.FoodMenu.ContainmentLevelCode result = food.menu.v1.FoodMenu.ContainmentLevelCode.forNumber(containmentLevelCode_);
-      return result == null ? food.menu.v1.FoodMenu.ContainmentLevelCode.UNRECOGNIZED : result;
-    }
-
-    private byte memoizedIsInitialized = -1;
-    @java.lang.Override
-    public final boolean isInitialized() {
-      byte isInitialized = memoizedIsInitialized;
-      if (isInitialized == 1) return true;
-      if (isInitialized == 0) return false;
-
-      memoizedIsInitialized = 1;
-      return true;
-    }
-
-    @java.lang.Override
-    public void writeTo(com.google.protobuf.CodedOutputStream output)
-                        throws java.io.IOException {
-      if (allergenTypeCode_ != food.menu.v1.FoodMenu.AllergenTypeCode.ALLERGEN_TYPE_CODE_UNSPECIFIED.getNumber()) {
-        output.writeEnum(1, allergenTypeCode_);
-      }
-      if (((bitField0_ & 0x00000001) != 0)) {
-        output.writeEnum(2, containmentLevelCode_);
-      }
-      getUnknownFields().writeTo(output);
-    }
-
-    @java.lang.Override
-    public int getSerializedSize() {
-      int size = memoizedSize;
-      if (size != -1) return size;
-
-      size = 0;
-      if (allergenTypeCode_ != food.menu.v1.FoodMenu.AllergenTypeCode.ALLERGEN_TYPE_CODE_UNSPECIFIED.getNumber()) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeEnumSize(1, allergenTypeCode_);
-      }
-      if (((bitField0_ & 0x00000001) != 0)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeEnumSize(2, containmentLevelCode_);
-      }
-      size += getUnknownFields().getSerializedSize();
-      memoizedSize = size;
-      return size;
-    }
-
-    @java.lang.Override
-    public boolean equals(final java.lang.Object obj) {
-      if (obj == this) {
-       return true;
-      }
-      if (!(obj instanceof food.menu.v1.FoodMenu.Allergen)) {
-        return super.equals(obj);
-      }
-      food.menu.v1.FoodMenu.Allergen other = (food.menu.v1.FoodMenu.Allergen) obj;
-
-      if (allergenTypeCode_ != other.allergenTypeCode_) return false;
-      if (hasContainmentLevelCode() != other.hasContainmentLevelCode()) return false;
-      if (hasContainmentLevelCode()) {
-        if (containmentLevelCode_ != other.containmentLevelCode_) return false;
-      }
-      if (!getUnknownFields().equals(other.getUnknownFields())) return false;
-      return true;
-    }
-
-    @java.lang.Override
-    public int hashCode() {
-      if (memoizedHashCode != 0) {
-        return memoizedHashCode;
-      }
-      int hash = 41;
-      hash = (19 * hash) + getDescriptor().hashCode();
-      hash = (37 * hash) + ALLERGEN_TYPE_CODE_FIELD_NUMBER;
-      hash = (53 * hash) + allergenTypeCode_;
-      if (hasContainmentLevelCode()) {
-        hash = (37 * hash) + CONTAINMENT_LEVEL_CODE_FIELD_NUMBER;
-        hash = (53 * hash) + containmentLevelCode_;
-      }
-      hash = (29 * hash) + getUnknownFields().hashCode();
-      memoizedHashCode = hash;
-      return hash;
-    }
-
-    public static food.menu.v1.FoodMenu.Allergen parseFrom(
-        java.nio.ByteBuffer data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.Allergen parseFrom(
-        java.nio.ByteBuffer data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.Allergen parseFrom(
-        com.google.protobuf.ByteString data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.Allergen parseFrom(
-        com.google.protobuf.ByteString data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.Allergen parseFrom(byte[] data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.Allergen parseFrom(
-        byte[] data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.Allergen parseFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.Allergen parseFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.Allergen parseDelimitedFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseDelimitedWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.Allergen parseDelimitedFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.Allergen parseFrom(
-        com.google.protobuf.CodedInputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.Allergen parseFrom(
-        com.google.protobuf.CodedInputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input, extensionRegistry);
-    }
-
-    @java.lang.Override
-    public Builder newBuilderForType() { return newBuilder(); }
-    public static Builder newBuilder() {
-      return DEFAULT_INSTANCE.toBuilder();
-    }
-    public static Builder newBuilder(food.menu.v1.FoodMenu.Allergen prototype) {
-      return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
-    }
-    @java.lang.Override
-    public Builder toBuilder() {
-      return this == DEFAULT_INSTANCE
-          ? new Builder() : new Builder().mergeFrom(this);
-    }
-
-    @java.lang.Override
-    protected Builder newBuilderForType(
-        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-      Builder builder = new Builder(parent);
-      return builder;
-    }
-    /**
-     * <pre>
-     * Allergen shown to the user on the MenuItem. An allergen relates to qualities
-     * of food that causes allergic reactions.
-     * </pre>
-     *
-     * Protobuf type {@code food.menu.v1.Allergen}
-     */
-    public static final class Builder extends
-        com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
-        // @@protoc_insertion_point(builder_implements:food.menu.v1.Allergen)
-        food.menu.v1.FoodMenu.AllergenOrBuilder {
-      public static final com.google.protobuf.Descriptors.Descriptor
-          getDescriptor() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_Allergen_descriptor;
-      }
-
-      @java.lang.Override
-      protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-          internalGetFieldAccessorTable() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_Allergen_fieldAccessorTable
-            .ensureFieldAccessorsInitialized(
-                food.menu.v1.FoodMenu.Allergen.class, food.menu.v1.FoodMenu.Allergen.Builder.class);
-      }
-
-      // Construct using food.menu.v1.FoodMenu.Allergen.newBuilder()
-      private Builder() {
-
-      }
-
-      private Builder(
-          com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-        super(parent);
-
-      }
-      @java.lang.Override
-      public Builder clear() {
-        super.clear();
-        bitField0_ = 0;
-        allergenTypeCode_ = 0;
-        containmentLevelCode_ = 0;
-        return this;
-      }
-
-      @java.lang.Override
-      public com.google.protobuf.Descriptors.Descriptor
-          getDescriptorForType() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_Allergen_descriptor;
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.Allergen getDefaultInstanceForType() {
-        return food.menu.v1.FoodMenu.Allergen.getDefaultInstance();
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.Allergen build() {
-        food.menu.v1.FoodMenu.Allergen result = buildPartial();
-        if (!result.isInitialized()) {
-          throw newUninitializedMessageException(result);
-        }
-        return result;
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.Allergen buildPartial() {
-        food.menu.v1.FoodMenu.Allergen result = new food.menu.v1.FoodMenu.Allergen(this);
-        if (bitField0_ != 0) { buildPartial0(result); }
-        onBuilt();
-        return result;
-      }
-
-      private void buildPartial0(food.menu.v1.FoodMenu.Allergen result) {
-        int from_bitField0_ = bitField0_;
-        if (((from_bitField0_ & 0x00000001) != 0)) {
-          result.allergenTypeCode_ = allergenTypeCode_;
-        }
-        int to_bitField0_ = 0;
-        if (((from_bitField0_ & 0x00000002) != 0)) {
-          result.containmentLevelCode_ = containmentLevelCode_;
-          to_bitField0_ |= 0x00000001;
-        }
-        result.bitField0_ |= to_bitField0_;
-      }
-
-      @java.lang.Override
-      public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof food.menu.v1.FoodMenu.Allergen) {
-          return mergeFrom((food.menu.v1.FoodMenu.Allergen)other);
-        } else {
-          super.mergeFrom(other);
-          return this;
-        }
-      }
-
-      public Builder mergeFrom(food.menu.v1.FoodMenu.Allergen other) {
-        if (other == food.menu.v1.FoodMenu.Allergen.getDefaultInstance()) return this;
-        if (other.allergenTypeCode_ != 0) {
-          setAllergenTypeCodeValue(other.getAllergenTypeCodeValue());
-        }
-        if (other.hasContainmentLevelCode()) {
-          setContainmentLevelCode(other.getContainmentLevelCode());
-        }
-        this.mergeUnknownFields(other.getUnknownFields());
-        onChanged();
-        return this;
-      }
-
-      @java.lang.Override
-      public final boolean isInitialized() {
-        return true;
-      }
-
-      @java.lang.Override
-      public Builder mergeFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws java.io.IOException {
-        if (extensionRegistry == null) {
-          throw new java.lang.NullPointerException();
-        }
-        try {
-          boolean done = false;
-          while (!done) {
-            int tag = input.readTag();
-            switch (tag) {
-              case 0:
-                done = true;
-                break;
-              case 8: {
-                allergenTypeCode_ = input.readEnum();
-                bitField0_ |= 0x00000001;
-                break;
-              } // case 8
-              case 16: {
-                containmentLevelCode_ = input.readEnum();
-                bitField0_ |= 0x00000002;
-                break;
-              } // case 16
-              default: {
-                if (!super.parseUnknownField(input, extensionRegistry, tag)) {
-                  done = true; // was an endgroup tag
-                }
-                break;
-              } // default:
-            } // switch (tag)
-          } // while (!done)
-        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          throw e.unwrapIOException();
-        } finally {
-          onChanged();
-        } // finally
-        return this;
-      }
-      private int bitField0_;
-
-      private int allergenTypeCode_ = 0;
-      /**
-       * <pre>
-       * Type of allergen.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.AllergenTypeCode allergen_type_code = 1;</code>
-       * @return The enum numeric value on the wire for allergenTypeCode.
-       */
-      @java.lang.Override public int getAllergenTypeCodeValue() {
-        return allergenTypeCode_;
-      }
-      /**
-       * <pre>
-       * Type of allergen.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.AllergenTypeCode allergen_type_code = 1;</code>
-       * @param value The enum numeric value on the wire for allergenTypeCode to set.
-       * @return This builder for chaining.
-       */
-      public Builder setAllergenTypeCodeValue(int value) {
-        allergenTypeCode_ = value;
-        bitField0_ |= 0x00000001;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Type of allergen.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.AllergenTypeCode allergen_type_code = 1;</code>
-       * @return The allergenTypeCode.
-       */
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.AllergenTypeCode getAllergenTypeCode() {
-        food.menu.v1.FoodMenu.AllergenTypeCode result = food.menu.v1.FoodMenu.AllergenTypeCode.forNumber(allergenTypeCode_);
-        return result == null ? food.menu.v1.FoodMenu.AllergenTypeCode.UNRECOGNIZED : result;
-      }
-      /**
-       * <pre>
-       * Type of allergen.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.AllergenTypeCode allergen_type_code = 1;</code>
-       * @param value The allergenTypeCode to set.
-       * @return This builder for chaining.
-       */
-      public Builder setAllergenTypeCode(food.menu.v1.FoodMenu.AllergenTypeCode value) {
-        if (value == null) {
-          throw new NullPointerException();
-        }
-        bitField0_ |= 0x00000001;
-        allergenTypeCode_ = value.getNumber();
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Type of allergen.
-       * Required.
-       * </pre>
-       *
-       * <code>.food.menu.v1.AllergenTypeCode allergen_type_code = 1;</code>
-       * @return This builder for chaining.
-       */
-      public Builder clearAllergenTypeCode() {
-        bitField0_ = (bitField0_ & ~0x00000001);
-        allergenTypeCode_ = 0;
-        onChanged();
-        return this;
-      }
-
-      private int containmentLevelCode_ = 0;
-      /**
-       * <pre>
-       * Whether the MenuItem contains, may contain, or is free from this allergen.
-       * Defaults to contains.
-       * Optional.
-       * </pre>
-       *
-       * <code>optional .food.menu.v1.ContainmentLevelCode containment_level_code = 2;</code>
-       * @return Whether the containmentLevelCode field is set.
-       */
-      @java.lang.Override public boolean hasContainmentLevelCode() {
-        return ((bitField0_ & 0x00000002) != 0);
-      }
-      /**
-       * <pre>
-       * Whether the MenuItem contains, may contain, or is free from this allergen.
-       * Defaults to contains.
-       * Optional.
-       * </pre>
-       *
-       * <code>optional .food.menu.v1.ContainmentLevelCode containment_level_code = 2;</code>
-       * @return The enum numeric value on the wire for containmentLevelCode.
-       */
-      @java.lang.Override public int getContainmentLevelCodeValue() {
-        return containmentLevelCode_;
-      }
-      /**
-       * <pre>
-       * Whether the MenuItem contains, may contain, or is free from this allergen.
-       * Defaults to contains.
-       * Optional.
-       * </pre>
-       *
-       * <code>optional .food.menu.v1.ContainmentLevelCode containment_level_code = 2;</code>
-       * @param value The enum numeric value on the wire for containmentLevelCode to set.
-       * @return This builder for chaining.
-       */
-      public Builder setContainmentLevelCodeValue(int value) {
-        containmentLevelCode_ = value;
-        bitField0_ |= 0x00000002;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Whether the MenuItem contains, may contain, or is free from this allergen.
-       * Defaults to contains.
-       * Optional.
-       * </pre>
-       *
-       * <code>optional .food.menu.v1.ContainmentLevelCode containment_level_code = 2;</code>
-       * @return The containmentLevelCode.
-       */
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.ContainmentLevelCode getContainmentLevelCode() {
-        food.menu.v1.FoodMenu.ContainmentLevelCode result = food.menu.v1.FoodMenu.ContainmentLevelCode.forNumber(containmentLevelCode_);
-        return result == null ? food.menu.v1.FoodMenu.ContainmentLevelCode.UNRECOGNIZED : result;
-      }
-      /**
-       * <pre>
-       * Whether the MenuItem contains, may contain, or is free from this allergen.
-       * Defaults to contains.
-       * Optional.
-       * </pre>
-       *
-       * <code>optional .food.menu.v1.ContainmentLevelCode containment_level_code = 2;</code>
-       * @param value The containmentLevelCode to set.
-       * @return This builder for chaining.
-       */
-      public Builder setContainmentLevelCode(food.menu.v1.FoodMenu.ContainmentLevelCode value) {
-        if (value == null) {
-          throw new NullPointerException();
-        }
-        bitField0_ |= 0x00000002;
-        containmentLevelCode_ = value.getNumber();
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Whether the MenuItem contains, may contain, or is free from this allergen.
-       * Defaults to contains.
-       * Optional.
-       * </pre>
-       *
-       * <code>optional .food.menu.v1.ContainmentLevelCode containment_level_code = 2;</code>
-       * @return This builder for chaining.
-       */
-      public Builder clearContainmentLevelCode() {
-        bitField0_ = (bitField0_ & ~0x00000002);
-        containmentLevelCode_ = 0;
-        onChanged();
-        return this;
-      }
-      @java.lang.Override
-      public final Builder setUnknownFields(
-          final com.google.protobuf.UnknownFieldSet unknownFields) {
-        return super.setUnknownFields(unknownFields);
-      }
-
-      @java.lang.Override
-      public final Builder mergeUnknownFields(
-          final com.google.protobuf.UnknownFieldSet unknownFields) {
-        return super.mergeUnknownFields(unknownFields);
-      }
-
-
-      // @@protoc_insertion_point(builder_scope:food.menu.v1.Allergen)
-    }
-
-    // @@protoc_insertion_point(class_scope:food.menu.v1.Allergen)
-    private static final food.menu.v1.FoodMenu.Allergen DEFAULT_INSTANCE;
-    static {
-      DEFAULT_INSTANCE = new food.menu.v1.FoodMenu.Allergen();
-    }
-
-    public static food.menu.v1.FoodMenu.Allergen getDefaultInstance() {
-      return DEFAULT_INSTANCE;
-    }
-
-    private static final com.google.protobuf.Parser<Allergen>
-        PARSER = new com.google.protobuf.AbstractParser<Allergen>() {
-      @java.lang.Override
-      public Allergen parsePartialFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws com.google.protobuf.InvalidProtocolBufferException {
-        Builder builder = newBuilder();
-        try {
-          builder.mergeFrom(input, extensionRegistry);
-        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          throw e.setUnfinishedMessage(builder.buildPartial());
-        } catch (com.google.protobuf.UninitializedMessageException e) {
-          throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
-        } catch (java.io.IOException e) {
-          throw new com.google.protobuf.InvalidProtocolBufferException(e)
-              .setUnfinishedMessage(builder.buildPartial());
-        }
-        return builder.buildPartial();
-      }
-    };
-
-    public static com.google.protobuf.Parser<Allergen> parser() {
-      return PARSER;
-    }
-
-    @java.lang.Override
-    public com.google.protobuf.Parser<Allergen> getParserForType() {
-      return PARSER;
-    }
-
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.Allergen getDefaultInstanceForType() {
-      return DEFAULT_INSTANCE;
-    }
-
-  }
-
-  public interface DepositInfoOrBuilder extends
-      // @@protoc_insertion_point(interface_extends:food.menu.v1.DepositInfo)
-      com.google.protobuf.MessageOrBuilder {
-
-    /**
-     * <pre>
-     * The deposit strategy to employ, e.g. "reusable".
-     * Optional.
-     * </pre>
-     *
-     * <code>optional .food.menu.v1.DepositCode deposit_code = 1;</code>
-     * @return Whether the depositCode field is set.
-     */
-    boolean hasDepositCode();
-    /**
-     * <pre>
-     * The deposit strategy to employ, e.g. "reusable".
-     * Optional.
-     * </pre>
-     *
-     * <code>optional .food.menu.v1.DepositCode deposit_code = 1;</code>
-     * @return The enum numeric value on the wire for depositCode.
-     */
-    int getDepositCodeValue();
-    /**
-     * <pre>
-     * The deposit strategy to employ, e.g. "reusable".
-     * Optional.
-     * </pre>
-     *
-     * <code>optional .food.menu.v1.DepositCode deposit_code = 1;</code>
-     * @return The depositCode.
-     */
-    food.menu.v1.FoodMenu.DepositCode getDepositCode();
-
-    /**
-     * <pre>
-     * Value refunded for depositing the item properly.
-     * Optional.
-     * </pre>
-     *
-     * <code>.google.type.Money deposit_value = 2;</code>
-     * @return Whether the depositValue field is set.
-     */
-    boolean hasDepositValue();
-    /**
-     * <pre>
-     * Value refunded for depositing the item properly.
-     * Optional.
-     * </pre>
-     *
-     * <code>.google.type.Money deposit_value = 2;</code>
-     * @return The depositValue.
-     */
-    com.google.type.Money getDepositValue();
-    /**
-     * <pre>
-     * Value refunded for depositing the item properly.
-     * Optional.
-     * </pre>
-     *
-     * <code>.google.type.Money deposit_value = 2;</code>
-     */
-    com.google.type.MoneyOrBuilder getDepositValueOrBuilder();
-  }
-  /**
-   * <pre>
-   * Partner provided deposit info to instruct the user how to deposit a food item
-   * or bottle and the value of such deposit.
-   * </pre>
-   *
-   * Protobuf type {@code food.menu.v1.DepositInfo}
-   */
-  public static final class DepositInfo extends
-      com.google.protobuf.GeneratedMessageV3 implements
-      // @@protoc_insertion_point(message_implements:food.menu.v1.DepositInfo)
-      DepositInfoOrBuilder {
-  private static final long serialVersionUID = 0L;
-    // Use DepositInfo.newBuilder() to construct.
-    private DepositInfo(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
-      super(builder);
-    }
-    private DepositInfo() {
-      depositCode_ = 0;
-    }
-
-    @java.lang.Override
-    @SuppressWarnings({"unused"})
-    protected java.lang.Object newInstance(
-        UnusedPrivateParameter unused) {
-      return new DepositInfo();
-    }
-
-    public static final com.google.protobuf.Descriptors.Descriptor
-        getDescriptor() {
-      return food.menu.v1.FoodMenu.internal_static_food_menu_v1_DepositInfo_descriptor;
-    }
-
-    @java.lang.Override
-    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-        internalGetFieldAccessorTable() {
-      return food.menu.v1.FoodMenu.internal_static_food_menu_v1_DepositInfo_fieldAccessorTable
-          .ensureFieldAccessorsInitialized(
-              food.menu.v1.FoodMenu.DepositInfo.class, food.menu.v1.FoodMenu.DepositInfo.Builder.class);
-    }
-
-    private int bitField0_;
-    public static final int DEPOSIT_CODE_FIELD_NUMBER = 1;
-    private int depositCode_ = 0;
-    /**
-     * <pre>
-     * The deposit strategy to employ, e.g. "reusable".
-     * Optional.
-     * </pre>
-     *
-     * <code>optional .food.menu.v1.DepositCode deposit_code = 1;</code>
-     * @return Whether the depositCode field is set.
-     */
-    @java.lang.Override public boolean hasDepositCode() {
-      return ((bitField0_ & 0x00000001) != 0);
-    }
-    /**
-     * <pre>
-     * The deposit strategy to employ, e.g. "reusable".
-     * Optional.
-     * </pre>
-     *
-     * <code>optional .food.menu.v1.DepositCode deposit_code = 1;</code>
-     * @return The enum numeric value on the wire for depositCode.
-     */
-    @java.lang.Override public int getDepositCodeValue() {
-      return depositCode_;
-    }
-    /**
-     * <pre>
-     * The deposit strategy to employ, e.g. "reusable".
-     * Optional.
-     * </pre>
-     *
-     * <code>optional .food.menu.v1.DepositCode deposit_code = 1;</code>
-     * @return The depositCode.
-     */
-    @java.lang.Override public food.menu.v1.FoodMenu.DepositCode getDepositCode() {
-      food.menu.v1.FoodMenu.DepositCode result = food.menu.v1.FoodMenu.DepositCode.forNumber(depositCode_);
-      return result == null ? food.menu.v1.FoodMenu.DepositCode.UNRECOGNIZED : result;
-    }
-
-    public static final int DEPOSIT_VALUE_FIELD_NUMBER = 2;
-    private com.google.type.Money depositValue_;
-    /**
-     * <pre>
-     * Value refunded for depositing the item properly.
-     * Optional.
-     * </pre>
-     *
-     * <code>.google.type.Money deposit_value = 2;</code>
-     * @return Whether the depositValue field is set.
-     */
-    @java.lang.Override
-    public boolean hasDepositValue() {
-      return depositValue_ != null;
-    }
-    /**
-     * <pre>
-     * Value refunded for depositing the item properly.
-     * Optional.
-     * </pre>
-     *
-     * <code>.google.type.Money deposit_value = 2;</code>
-     * @return The depositValue.
-     */
-    @java.lang.Override
-    public com.google.type.Money getDepositValue() {
-      return depositValue_ == null ? com.google.type.Money.getDefaultInstance() : depositValue_;
-    }
-    /**
-     * <pre>
-     * Value refunded for depositing the item properly.
-     * Optional.
-     * </pre>
-     *
-     * <code>.google.type.Money deposit_value = 2;</code>
-     */
-    @java.lang.Override
-    public com.google.type.MoneyOrBuilder getDepositValueOrBuilder() {
-      return depositValue_ == null ? com.google.type.Money.getDefaultInstance() : depositValue_;
-    }
-
-    private byte memoizedIsInitialized = -1;
-    @java.lang.Override
-    public final boolean isInitialized() {
-      byte isInitialized = memoizedIsInitialized;
-      if (isInitialized == 1) return true;
-      if (isInitialized == 0) return false;
-
-      memoizedIsInitialized = 1;
-      return true;
-    }
-
-    @java.lang.Override
-    public void writeTo(com.google.protobuf.CodedOutputStream output)
-                        throws java.io.IOException {
-      if (((bitField0_ & 0x00000001) != 0)) {
-        output.writeEnum(1, depositCode_);
-      }
-      if (depositValue_ != null) {
-        output.writeMessage(2, getDepositValue());
-      }
-      getUnknownFields().writeTo(output);
-    }
-
-    @java.lang.Override
-    public int getSerializedSize() {
-      int size = memoizedSize;
-      if (size != -1) return size;
-
-      size = 0;
-      if (((bitField0_ & 0x00000001) != 0)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeEnumSize(1, depositCode_);
-      }
-      if (depositValue_ != null) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(2, getDepositValue());
-      }
-      size += getUnknownFields().getSerializedSize();
-      memoizedSize = size;
-      return size;
-    }
-
-    @java.lang.Override
-    public boolean equals(final java.lang.Object obj) {
-      if (obj == this) {
-       return true;
-      }
-      if (!(obj instanceof food.menu.v1.FoodMenu.DepositInfo)) {
-        return super.equals(obj);
-      }
-      food.menu.v1.FoodMenu.DepositInfo other = (food.menu.v1.FoodMenu.DepositInfo) obj;
-
-      if (hasDepositCode() != other.hasDepositCode()) return false;
-      if (hasDepositCode()) {
-        if (depositCode_ != other.depositCode_) return false;
-      }
-      if (hasDepositValue() != other.hasDepositValue()) return false;
-      if (hasDepositValue()) {
-        if (!getDepositValue()
-            .equals(other.getDepositValue())) return false;
-      }
-      if (!getUnknownFields().equals(other.getUnknownFields())) return false;
-      return true;
-    }
-
-    @java.lang.Override
-    public int hashCode() {
-      if (memoizedHashCode != 0) {
-        return memoizedHashCode;
-      }
-      int hash = 41;
-      hash = (19 * hash) + getDescriptor().hashCode();
-      if (hasDepositCode()) {
-        hash = (37 * hash) + DEPOSIT_CODE_FIELD_NUMBER;
-        hash = (53 * hash) + depositCode_;
-      }
-      if (hasDepositValue()) {
-        hash = (37 * hash) + DEPOSIT_VALUE_FIELD_NUMBER;
-        hash = (53 * hash) + getDepositValue().hashCode();
-      }
-      hash = (29 * hash) + getUnknownFields().hashCode();
-      memoizedHashCode = hash;
-      return hash;
-    }
-
-    public static food.menu.v1.FoodMenu.DepositInfo parseFrom(
-        java.nio.ByteBuffer data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.DepositInfo parseFrom(
-        java.nio.ByteBuffer data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.DepositInfo parseFrom(
-        com.google.protobuf.ByteString data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.DepositInfo parseFrom(
-        com.google.protobuf.ByteString data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.DepositInfo parseFrom(byte[] data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static food.menu.v1.FoodMenu.DepositInfo parseFrom(
-        byte[] data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.DepositInfo parseFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.DepositInfo parseFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.DepositInfo parseDelimitedFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseDelimitedWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.DepositInfo parseDelimitedFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
-    }
-    public static food.menu.v1.FoodMenu.DepositInfo parseFrom(
-        com.google.protobuf.CodedInputStream input)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input);
-    }
-    public static food.menu.v1.FoodMenu.DepositInfo parseFrom(
-        com.google.protobuf.CodedInputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return com.google.protobuf.GeneratedMessageV3
-          .parseWithIOException(PARSER, input, extensionRegistry);
-    }
-
-    @java.lang.Override
-    public Builder newBuilderForType() { return newBuilder(); }
-    public static Builder newBuilder() {
-      return DEFAULT_INSTANCE.toBuilder();
-    }
-    public static Builder newBuilder(food.menu.v1.FoodMenu.DepositInfo prototype) {
-      return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
-    }
-    @java.lang.Override
-    public Builder toBuilder() {
-      return this == DEFAULT_INSTANCE
-          ? new Builder() : new Builder().mergeFrom(this);
-    }
-
-    @java.lang.Override
-    protected Builder newBuilderForType(
-        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-      Builder builder = new Builder(parent);
-      return builder;
-    }
-    /**
-     * <pre>
-     * Partner provided deposit info to instruct the user how to deposit a food item
-     * or bottle and the value of such deposit.
-     * </pre>
-     *
-     * Protobuf type {@code food.menu.v1.DepositInfo}
-     */
-    public static final class Builder extends
-        com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
-        // @@protoc_insertion_point(builder_implements:food.menu.v1.DepositInfo)
-        food.menu.v1.FoodMenu.DepositInfoOrBuilder {
-      public static final com.google.protobuf.Descriptors.Descriptor
-          getDescriptor() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_DepositInfo_descriptor;
-      }
-
-      @java.lang.Override
-      protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-          internalGetFieldAccessorTable() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_DepositInfo_fieldAccessorTable
-            .ensureFieldAccessorsInitialized(
-                food.menu.v1.FoodMenu.DepositInfo.class, food.menu.v1.FoodMenu.DepositInfo.Builder.class);
-      }
-
-      // Construct using food.menu.v1.FoodMenu.DepositInfo.newBuilder()
-      private Builder() {
-
-      }
-
-      private Builder(
-          com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
-        super(parent);
-
-      }
-      @java.lang.Override
-      public Builder clear() {
-        super.clear();
-        bitField0_ = 0;
-        depositCode_ = 0;
-        depositValue_ = null;
-        if (depositValueBuilder_ != null) {
-          depositValueBuilder_.dispose();
-          depositValueBuilder_ = null;
-        }
-        return this;
-      }
-
-      @java.lang.Override
-      public com.google.protobuf.Descriptors.Descriptor
-          getDescriptorForType() {
-        return food.menu.v1.FoodMenu.internal_static_food_menu_v1_DepositInfo_descriptor;
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.DepositInfo getDefaultInstanceForType() {
-        return food.menu.v1.FoodMenu.DepositInfo.getDefaultInstance();
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.DepositInfo build() {
-        food.menu.v1.FoodMenu.DepositInfo result = buildPartial();
-        if (!result.isInitialized()) {
-          throw newUninitializedMessageException(result);
-        }
-        return result;
-      }
-
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.DepositInfo buildPartial() {
-        food.menu.v1.FoodMenu.DepositInfo result = new food.menu.v1.FoodMenu.DepositInfo(this);
-        if (bitField0_ != 0) { buildPartial0(result); }
-        onBuilt();
-        return result;
-      }
-
-      private void buildPartial0(food.menu.v1.FoodMenu.DepositInfo result) {
-        int from_bitField0_ = bitField0_;
-        int to_bitField0_ = 0;
-        if (((from_bitField0_ & 0x00000001) != 0)) {
-          result.depositCode_ = depositCode_;
-          to_bitField0_ |= 0x00000001;
-        }
-        if (((from_bitField0_ & 0x00000002) != 0)) {
-          result.depositValue_ = depositValueBuilder_ == null
-              ? depositValue_
-              : depositValueBuilder_.build();
-        }
-        result.bitField0_ |= to_bitField0_;
-      }
-
-      @java.lang.Override
-      public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof food.menu.v1.FoodMenu.DepositInfo) {
-          return mergeFrom((food.menu.v1.FoodMenu.DepositInfo)other);
-        } else {
-          super.mergeFrom(other);
-          return this;
-        }
-      }
-
-      public Builder mergeFrom(food.menu.v1.FoodMenu.DepositInfo other) {
-        if (other == food.menu.v1.FoodMenu.DepositInfo.getDefaultInstance()) return this;
-        if (other.hasDepositCode()) {
-          setDepositCode(other.getDepositCode());
-        }
-        if (other.hasDepositValue()) {
-          mergeDepositValue(other.getDepositValue());
-        }
-        this.mergeUnknownFields(other.getUnknownFields());
-        onChanged();
-        return this;
-      }
-
-      @java.lang.Override
-      public final boolean isInitialized() {
-        return true;
-      }
-
-      @java.lang.Override
-      public Builder mergeFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws java.io.IOException {
-        if (extensionRegistry == null) {
-          throw new java.lang.NullPointerException();
-        }
-        try {
-          boolean done = false;
-          while (!done) {
-            int tag = input.readTag();
-            switch (tag) {
-              case 0:
-                done = true;
-                break;
-              case 8: {
-                depositCode_ = input.readEnum();
-                bitField0_ |= 0x00000001;
-                break;
-              } // case 8
-              case 18: {
-                input.readMessage(
-                    getDepositValueFieldBuilder().getBuilder(),
-                    extensionRegistry);
-                bitField0_ |= 0x00000002;
-                break;
-              } // case 18
-              default: {
-                if (!super.parseUnknownField(input, extensionRegistry, tag)) {
-                  done = true; // was an endgroup tag
-                }
-                break;
-              } // default:
-            } // switch (tag)
-          } // while (!done)
-        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          throw e.unwrapIOException();
-        } finally {
-          onChanged();
-        } // finally
-        return this;
-      }
-      private int bitField0_;
-
-      private int depositCode_ = 0;
-      /**
-       * <pre>
-       * The deposit strategy to employ, e.g. "reusable".
-       * Optional.
-       * </pre>
-       *
-       * <code>optional .food.menu.v1.DepositCode deposit_code = 1;</code>
-       * @return Whether the depositCode field is set.
-       */
-      @java.lang.Override public boolean hasDepositCode() {
-        return ((bitField0_ & 0x00000001) != 0);
-      }
-      /**
-       * <pre>
-       * The deposit strategy to employ, e.g. "reusable".
-       * Optional.
-       * </pre>
-       *
-       * <code>optional .food.menu.v1.DepositCode deposit_code = 1;</code>
-       * @return The enum numeric value on the wire for depositCode.
-       */
-      @java.lang.Override public int getDepositCodeValue() {
-        return depositCode_;
-      }
-      /**
-       * <pre>
-       * The deposit strategy to employ, e.g. "reusable".
-       * Optional.
-       * </pre>
-       *
-       * <code>optional .food.menu.v1.DepositCode deposit_code = 1;</code>
-       * @param value The enum numeric value on the wire for depositCode to set.
-       * @return This builder for chaining.
-       */
-      public Builder setDepositCodeValue(int value) {
-        depositCode_ = value;
-        bitField0_ |= 0x00000001;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * The deposit strategy to employ, e.g. "reusable".
-       * Optional.
-       * </pre>
-       *
-       * <code>optional .food.menu.v1.DepositCode deposit_code = 1;</code>
-       * @return The depositCode.
-       */
-      @java.lang.Override
-      public food.menu.v1.FoodMenu.DepositCode getDepositCode() {
-        food.menu.v1.FoodMenu.DepositCode result = food.menu.v1.FoodMenu.DepositCode.forNumber(depositCode_);
-        return result == null ? food.menu.v1.FoodMenu.DepositCode.UNRECOGNIZED : result;
-      }
-      /**
-       * <pre>
-       * The deposit strategy to employ, e.g. "reusable".
-       * Optional.
-       * </pre>
-       *
-       * <code>optional .food.menu.v1.DepositCode deposit_code = 1;</code>
-       * @param value The depositCode to set.
-       * @return This builder for chaining.
-       */
-      public Builder setDepositCode(food.menu.v1.FoodMenu.DepositCode value) {
-        if (value == null) {
-          throw new NullPointerException();
-        }
-        bitField0_ |= 0x00000001;
-        depositCode_ = value.getNumber();
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * The deposit strategy to employ, e.g. "reusable".
-       * Optional.
-       * </pre>
-       *
-       * <code>optional .food.menu.v1.DepositCode deposit_code = 1;</code>
-       * @return This builder for chaining.
-       */
-      public Builder clearDepositCode() {
-        bitField0_ = (bitField0_ & ~0x00000001);
-        depositCode_ = 0;
-        onChanged();
-        return this;
-      }
-
-      private com.google.type.Money depositValue_;
-      private com.google.protobuf.SingleFieldBuilderV3<
-          com.google.type.Money, com.google.type.Money.Builder, com.google.type.MoneyOrBuilder> depositValueBuilder_;
-      /**
-       * <pre>
-       * Value refunded for depositing the item properly.
-       * Optional.
-       * </pre>
-       *
-       * <code>.google.type.Money deposit_value = 2;</code>
-       * @return Whether the depositValue field is set.
-       */
-      public boolean hasDepositValue() {
-        return ((bitField0_ & 0x00000002) != 0);
-      }
-      /**
-       * <pre>
-       * Value refunded for depositing the item properly.
-       * Optional.
-       * </pre>
-       *
-       * <code>.google.type.Money deposit_value = 2;</code>
-       * @return The depositValue.
-       */
-      public com.google.type.Money getDepositValue() {
-        if (depositValueBuilder_ == null) {
-          return depositValue_ == null ? com.google.type.Money.getDefaultInstance() : depositValue_;
-        } else {
-          return depositValueBuilder_.getMessage();
-        }
-      }
-      /**
-       * <pre>
-       * Value refunded for depositing the item properly.
-       * Optional.
-       * </pre>
-       *
-       * <code>.google.type.Money deposit_value = 2;</code>
-       */
-      public Builder setDepositValue(com.google.type.Money value) {
-        if (depositValueBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          depositValue_ = value;
-        } else {
-          depositValueBuilder_.setMessage(value);
-        }
-        bitField0_ |= 0x00000002;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Value refunded for depositing the item properly.
-       * Optional.
-       * </pre>
-       *
-       * <code>.google.type.Money deposit_value = 2;</code>
-       */
-      public Builder setDepositValue(
-          com.google.type.Money.Builder builderForValue) {
-        if (depositValueBuilder_ == null) {
-          depositValue_ = builderForValue.build();
-        } else {
-          depositValueBuilder_.setMessage(builderForValue.build());
-        }
-        bitField0_ |= 0x00000002;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Value refunded for depositing the item properly.
-       * Optional.
-       * </pre>
-       *
-       * <code>.google.type.Money deposit_value = 2;</code>
-       */
-      public Builder mergeDepositValue(com.google.type.Money value) {
-        if (depositValueBuilder_ == null) {
-          if (((bitField0_ & 0x00000002) != 0) &&
-            depositValue_ != null &&
-            depositValue_ != com.google.type.Money.getDefaultInstance()) {
-            getDepositValueBuilder().mergeFrom(value);
-          } else {
-            depositValue_ = value;
-          }
-        } else {
-          depositValueBuilder_.mergeFrom(value);
-        }
-        bitField0_ |= 0x00000002;
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Value refunded for depositing the item properly.
-       * Optional.
-       * </pre>
-       *
-       * <code>.google.type.Money deposit_value = 2;</code>
-       */
-      public Builder clearDepositValue() {
-        bitField0_ = (bitField0_ & ~0x00000002);
-        depositValue_ = null;
-        if (depositValueBuilder_ != null) {
-          depositValueBuilder_.dispose();
-          depositValueBuilder_ = null;
-        }
-        onChanged();
-        return this;
-      }
-      /**
-       * <pre>
-       * Value refunded for depositing the item properly.
-       * Optional.
-       * </pre>
-       *
-       * <code>.google.type.Money deposit_value = 2;</code>
-       */
-      public com.google.type.Money.Builder getDepositValueBuilder() {
-        bitField0_ |= 0x00000002;
-        onChanged();
-        return getDepositValueFieldBuilder().getBuilder();
-      }
-      /**
-       * <pre>
-       * Value refunded for depositing the item properly.
-       * Optional.
-       * </pre>
-       *
-       * <code>.google.type.Money deposit_value = 2;</code>
-       */
-      public com.google.type.MoneyOrBuilder getDepositValueOrBuilder() {
-        if (depositValueBuilder_ != null) {
-          return depositValueBuilder_.getMessageOrBuilder();
-        } else {
-          return depositValue_ == null ?
-              com.google.type.Money.getDefaultInstance() : depositValue_;
-        }
-      }
-      /**
-       * <pre>
-       * Value refunded for depositing the item properly.
-       * Optional.
-       * </pre>
-       *
-       * <code>.google.type.Money deposit_value = 2;</code>
-       */
-      private com.google.protobuf.SingleFieldBuilderV3<
-          com.google.type.Money, com.google.type.Money.Builder, com.google.type.MoneyOrBuilder> 
-          getDepositValueFieldBuilder() {
-        if (depositValueBuilder_ == null) {
-          depositValueBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
-              com.google.type.Money, com.google.type.Money.Builder, com.google.type.MoneyOrBuilder>(
-                  getDepositValue(),
-                  getParentForChildren(),
-                  isClean());
-          depositValue_ = null;
-        }
-        return depositValueBuilder_;
-      }
-      @java.lang.Override
-      public final Builder setUnknownFields(
-          final com.google.protobuf.UnknownFieldSet unknownFields) {
-        return super.setUnknownFields(unknownFields);
-      }
-
-      @java.lang.Override
-      public final Builder mergeUnknownFields(
-          final com.google.protobuf.UnknownFieldSet unknownFields) {
-        return super.mergeUnknownFields(unknownFields);
-      }
-
-
-      // @@protoc_insertion_point(builder_scope:food.menu.v1.DepositInfo)
-    }
-
-    // @@protoc_insertion_point(class_scope:food.menu.v1.DepositInfo)
-    private static final food.menu.v1.FoodMenu.DepositInfo DEFAULT_INSTANCE;
-    static {
-      DEFAULT_INSTANCE = new food.menu.v1.FoodMenu.DepositInfo();
-    }
-
-    public static food.menu.v1.FoodMenu.DepositInfo getDefaultInstance() {
-      return DEFAULT_INSTANCE;
-    }
-
-    private static final com.google.protobuf.Parser<DepositInfo>
-        PARSER = new com.google.protobuf.AbstractParser<DepositInfo>() {
-      @java.lang.Override
-      public DepositInfo parsePartialFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws com.google.protobuf.InvalidProtocolBufferException {
-        Builder builder = newBuilder();
-        try {
-          builder.mergeFrom(input, extensionRegistry);
-        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          throw e.setUnfinishedMessage(builder.buildPartial());
-        } catch (com.google.protobuf.UninitializedMessageException e) {
-          throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
-        } catch (java.io.IOException e) {
-          throw new com.google.protobuf.InvalidProtocolBufferException(e)
-              .setUnfinishedMessage(builder.buildPartial());
-        }
-        return builder.buildPartial();
-      }
-    };
-
-    public static com.google.protobuf.Parser<DepositInfo> parser() {
-      return PARSER;
-    }
-
-    @java.lang.Override
-    public com.google.protobuf.Parser<DepositInfo> getParserForType() {
-      return PARSER;
-    }
-
-    @java.lang.Override
-    public food.menu.v1.FoodMenu.DepositInfo getDefaultInstanceForType() {
-      return DEFAULT_INSTANCE;
-    }
-
-  }
-
-  private static final com.google.protobuf.Descriptors.Descriptor
-    internal_static_food_menu_v1_FoodMenuFeed_descriptor;
-  private static final 
-    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-      internal_static_food_menu_v1_FoodMenuFeed_fieldAccessorTable;
-  private static final com.google.protobuf.Descriptors.Descriptor
-    internal_static_food_menu_v1_MenuComponent_descriptor;
-  private static final 
-    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-      internal_static_food_menu_v1_MenuComponent_fieldAccessorTable;
-  private static final com.google.protobuf.Descriptors.Descriptor
-    internal_static_food_menu_v1_Menu_descriptor;
-  private static final 
-    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-      internal_static_food_menu_v1_Menu_fieldAccessorTable;
-  private static final com.google.protobuf.Descriptors.Descriptor
-    internal_static_food_menu_v1_MenuSection_descriptor;
-  private static final 
-    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-      internal_static_food_menu_v1_MenuSection_fieldAccessorTable;
-  private static final com.google.protobuf.Descriptors.Descriptor
-    internal_static_food_menu_v1_MenuItem_descriptor;
-  private static final 
-    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-      internal_static_food_menu_v1_MenuItem_fieldAccessorTable;
-  private static final com.google.protobuf.Descriptors.Descriptor
-    internal_static_food_menu_v1_MenuItem_MenuItemOptionSet_descriptor;
-  private static final 
-    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-      internal_static_food_menu_v1_MenuItem_MenuItemOptionSet_fieldAccessorTable;
-  private static final com.google.protobuf.Descriptors.Descriptor
-    internal_static_food_menu_v1_MenuItemOption_descriptor;
-  private static final 
-    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-      internal_static_food_menu_v1_MenuItemOption_fieldAccessorTable;
-  private static final com.google.protobuf.Descriptors.Descriptor
-    internal_static_food_menu_v1_MenuItemAttributes_descriptor;
-  private static final 
-    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-      internal_static_food_menu_v1_MenuItemAttributes_fieldAccessorTable;
-  private static final com.google.protobuf.Descriptors.Descriptor
-    internal_static_food_menu_v1_OfferSet_descriptor;
-  private static final 
-    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-      internal_static_food_menu_v1_OfferSet_fieldAccessorTable;
-  private static final com.google.protobuf.Descriptors.Descriptor
-    internal_static_food_menu_v1_Offer_descriptor;
-  private static final 
-    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-      internal_static_food_menu_v1_Offer_fieldAccessorTable;
-  private static final com.google.protobuf.Descriptors.Descriptor
-    internal_static_food_menu_v1_Disclaimer_descriptor;
-  private static final 
-    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-      internal_static_food_menu_v1_Disclaimer_fieldAccessorTable;
-  private static final com.google.protobuf.Descriptors.Descriptor
-    internal_static_food_menu_v1_TextField_descriptor;
-  private static final 
-    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-      internal_static_food_menu_v1_TextField_fieldAccessorTable;
-  private static final com.google.protobuf.Descriptors.Descriptor
-    internal_static_food_menu_v1_Image_descriptor;
-  private static final 
-    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-      internal_static_food_menu_v1_Image_fieldAccessorTable;
-  private static final com.google.protobuf.Descriptors.Descriptor
-    internal_static_food_menu_v1_MenuItemOptionProperty_descriptor;
-  private static final 
-    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-      internal_static_food_menu_v1_MenuItemOptionProperty_fieldAccessorTable;
-  private static final com.google.protobuf.Descriptors.Descriptor
-    internal_static_food_menu_v1_NutritionInformation_descriptor;
-  private static final 
-    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-      internal_static_food_menu_v1_NutritionInformation_fieldAccessorTable;
-  private static final com.google.protobuf.Descriptors.Descriptor
-    internal_static_food_menu_v1_NutritionInformation_NutritionValue_descriptor;
-  private static final 
-    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-      internal_static_food_menu_v1_NutritionInformation_NutritionValue_fieldAccessorTable;
-  private static final com.google.protobuf.Descriptors.Descriptor
-    internal_static_food_menu_v1_NutritionInformation_NutritionValue_Range_descriptor;
-  private static final 
-    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-      internal_static_food_menu_v1_NutritionInformation_NutritionValue_Range_fieldAccessorTable;
-  private static final com.google.protobuf.Descriptors.Descriptor
-    internal_static_food_menu_v1_Additive_descriptor;
-  private static final 
-    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-      internal_static_food_menu_v1_Additive_fieldAccessorTable;
-  private static final com.google.protobuf.Descriptors.Descriptor
-    internal_static_food_menu_v1_Allergen_descriptor;
-  private static final 
-    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-      internal_static_food_menu_v1_Allergen_fieldAccessorTable;
-  private static final com.google.protobuf.Descriptors.Descriptor
-    internal_static_food_menu_v1_DepositInfo_descriptor;
-  private static final 
-    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-      internal_static_food_menu_v1_DepositInfo_fieldAccessorTable;
-
-  public static com.google.protobuf.Descriptors.FileDescriptor
-      getDescriptor() {
-    return descriptor;
-  }
-  private static  com.google.protobuf.Descriptors.FileDescriptor
-      descriptor;
-  static {
-    java.lang.String[] descriptorData = {
-      "\n\017food_menu.proto\022\014food.menu.v1\032\037google/" +
-      "protobuf/timestamp.proto\032\024localized_text" +
-      ".proto\032\013money.proto\"9\n\014FoodMenuFeed\022)\n\004d" +
-      "ata\030\001 \003(\0132\033.food.menu.v1.MenuComponent\"\301" +
-      "\001\n\rMenuComponent\022\"\n\004menu\030\001 \001(\0132\022.food.me" +
-      "nu.v1.MenuH\000\022,\n\007section\030\002 \001(\0132\031.food.men" +
-      "u.v1.MenuSectionH\000\022&\n\004item\030\003 \001(\0132\026.food." +
-      "menu.v1.MenuItemH\000\022.\n\006option\030\004 \001(\0132\034.foo" +
-      "d.menu.v1.MenuItemOptionH\000B\006\n\004type\"\214\002\n\004M" +
-      "enu\022\017\n\007menu_id\030\001 \001(\t\022\024\n\014merchant_ids\030\002 \003" +
-      "(\t\022-\n\014display_name\030\003 \001(\0132\027.food.menu.v1." +
-      "TextField\022\020\n\010language\030\004 \001(\t\022,\n\ndisclaime" +
-      "r\030\005 \001(\0132\030.food.menu.v1.Disclaimer\022\025\n\rmen" +
-      "u_item_ids\030\006 \003(\t\022\030\n\020menu_section_ids\030\007 \003" +
-      "(\t\022=\n\031last_merchant_update_time\030\010 \001(\0132\032." +
-      "google.protobuf.Timestamp\"\331\001\n\013MenuSectio" +
-      "n\022\027\n\017menu_section_id\030\001 \001(\t\022-\n\014display_na" +
-      "me\030\002 \001(\0132\027.food.menu.v1.TextField\022,\n\013des" +
-      "cription\030\003 \001(\0132\027.food.menu.v1.TextField\022" +
-      "#\n\006images\030\004 \003(\0132\023.food.menu.v1.Image\022\025\n\r" +
-      "menu_item_ids\030\006 \003(\t\022\030\n\020menu_section_ids\030" +
-      "\007 \003(\t\"\222\003\n\010MenuItem\022\024\n\014menu_item_id\030\001 \001(\t" +
-      "\022-\n\014display_name\030\002 \001(\0132\027.food.menu.v1.Te" +
-      "xtField\022,\n\013description\030\003 \001(\0132\027.food.menu" +
-      ".v1.TextField\022#\n\006images\030\004 \003(\0132\023.food.men" +
-      "u.v1.Image\022+\n\toffer_set\030\006 \001(\0132\026.food.men" +
-      "u.v1.OfferSetH\000\022H\n\024menu_item_option_set\030" +
-      "\007 \001(\0132(.food.menu.v1.MenuItem.MenuItemOp" +
-      "tionSetH\000\0229\n\017item_attributes\030\010 \001(\0132 .foo" +
-      "d.menu.v1.MenuItemAttributes\0321\n\021MenuItem" +
-      "OptionSet\022\034\n\024menu_item_option_ids\030\001 \003(\tB" +
-      "\t\n\007pricing\"\310\001\n\016MenuItemOption\022\033\n\023menu_it" +
-      "em_option_id\030\t \001(\t\0223\n\005value\030\002 \001(\0132$.food" +
-      ".menu.v1.MenuItemOptionProperty\022)\n\toffer" +
-      "_set\030\004 \001(\0132\026.food.menu.v1.OfferSet\0229\n\017it" +
-      "em_attributes\030\005 \001(\0132 .food.menu.v1.MenuI" +
-      "temAttributes\"\330\002\n\022MenuItemAttributes\022\037\n\022" +
-      "number_of_servings\030\001 \001(\005H\000\210\001\001\022A\n\025nutriti" +
-      "on_information\030\002 \001(\0132\".food.menu.v1.Nutr" +
-      "itionInformation\0228\n\016suitable_diets\030\003 \003(\016" +
-      "2 .food.menu.v1.DietaryRestriction\022(\n\010ad" +
-      "ditive\030\004 \003(\0132\026.food.menu.v1.Additive\022(\n\010" +
-      "allergen\030\005 \003(\0132\026.food.menu.v1.Allergen\0229" +
-      "\n\026packaging_deposit_info\030\006 \001(\0132\031.food.me" +
-      "nu.v1.DepositInfoB\025\n\023_number_of_servings" +
-      "\"/\n\010OfferSet\022#\n\006offers\030\001 \003(\0132\023.food.menu" +
-      ".v1.Offer\"*\n\005Offer\022!\n\005price\030\001 \001(\0132\022.goog" +
-      "le.type.Money\"@\n\nDisclaimer\022%\n\004text\030\001 \001(" +
-      "\0132\027.food.menu.v1.TextField\022\013\n\003uri\030\002 \001(\t\"" +
-      "5\n\tTextField\022(\n\004text\030\001 \003(\0132\032.google.type" +
-      ".LocalizedText\"\024\n\005Image\022\013\n\003uri\030\001 \001(\t\"\243\003\n" +
-      "\026MenuItemOptionProperty\022H\n\rproperty_type" +
-      "\030\001 \001(\01621.food.menu.v1.MenuItemOptionProp" +
-      "erty.PropertyType\022J\n\014property_val\030\002 \001(\0162" +
-      "2.food.menu.v1.MenuItemOptionProperty.Pr" +
-      "opertyValueH\000\022+\n\010text_val\030\003 \001(\0132\027.food.m" +
-      "enu.v1.TextFieldH\000\"O\n\014PropertyType\022\031\n\025UN" +
-      "KNOWN_PROPERTY_TYPE\020\000\022\n\n\006OPTION\020\001\022\010\n\004SIZ" +
-      "E\020\002\022\016\n\nPIZZA_SIDE\020\003\"l\n\rPropertyValue\022\032\n\026" +
-      "UNKNOWN_PROPERTY_VALUE\020\000\022\023\n\017PIZZA_SIDE_L" +
-      "EFT\020\001\022\024\n\020PIZZA_SIDE_RIGHT\020\002\022\024\n\020PIZZA_SID" +
-      "E_WHOLE\020\003B\007\n\005value\"\311\003\n\024NutritionInformat" +
-      "ion\022A\n\006energy\030\001 \001(\01321.food.menu.v1.Nutri" +
-      "tionInformation.NutritionValue\022I\n\016sodium" +
-      "_content\030\002 \001(\01321.food.menu.v1.NutritionI" +
-      "nformation.NutritionValue\022\031\n\014serving_siz" +
-      "e\030\003 \001(\005H\000\210\001\001\022,\n\013description\030\004 \001(\0132\027.food" +
-      ".menu.v1.TextField\032\310\001\n\016NutritionValue\022\020\n" +
-      "\006amount\030\001 \001(\001H\000\022H\n\005range\030\003 \001(\01327.food.me" +
-      "nu.v1.NutritionInformation.NutritionValu" +
-      "e.RangeH\000\022.\n\004unit\030\002 \001(\0162 .food.menu.v1.N" +
-      "utritionValueUnit\032!\n\005Range\022\013\n\003min\030\001 \001(\001\022" +
-      "\013\n\003max\030\002 \001(\001B\007\n\005valueB\017\n\r_serving_size\"\225" +
-      "\001\n\010Additive\022%\n\004name\030\001 \001(\0132\027.food.menu.v1" +
-      ".TextField\022G\n\026containment_level_code\030\002 \001" +
-      "(\0162\".food.menu.v1.ContainmentLevelCodeH\000" +
-      "\210\001\001B\031\n\027_containment_level_code\"\252\001\n\010Aller" +
-      "gen\022:\n\022allergen_type_code\030\001 \001(\0162\036.food.m" +
-      "enu.v1.AllergenTypeCode\022G\n\026containment_l" +
-      "evel_code\030\002 \001(\0162\".food.menu.v1.Containme" +
-      "ntLevelCodeH\000\210\001\001B\031\n\027_containment_level_c" +
-      "ode\"\177\n\013DepositInfo\0224\n\014deposit_code\030\001 \001(\016" +
-      "2\031.food.menu.v1.DepositCodeH\000\210\001\001\022)\n\rdepo" +
-      "sit_value\030\002 \001(\0132\022.google.type.MoneyB\017\n\r_" +
-      "deposit_code*\372\001\n\022DietaryRestriction\022\024\n\020D" +
-      "IET_UNSPECIFIED\020\000\022\021\n\rDIET_DIABETIC\020\001\022\024\n\020" +
-      "DIET_GLUTEN_FREE\020\002\022\016\n\nDIET_HALAL\020\003\022\016\n\nDI" +
-      "ET_HINDU\020\004\022\017\n\013DIET_KOSHER\020\005\022\024\n\020DIET_LOW_" +
-      "CALORIE\020\006\022\020\n\014DIET_LOW_FAT\020\007\022\024\n\020DIET_LOW_" +
-      "LACTOSE\020\010\022\021\n\rDIET_LOW_SALT\020\t\022\016\n\nDIET_VEG" +
-      "AN\020\n\022\023\n\017DIET_VEGETARIAN\020\013*\207\022\n\020AllergenTy" +
-      "peCode\022\"\n\036ALLERGEN_TYPE_CODE_UNSPECIFIED" +
-      "\020\000\022\036\n\032ALLERGEN_TYPE_CODE_ALMONDS\020\001\022-\n)AL" +
-      "LERGEN_TYPE_CODE_ALPHA_ISOMETHYL_IONONE\020" +
-      "\002\022\036\n\032ALLERGEN_TYPE_CODE_ALCOHOL\020\003\022$\n ALL" +
-      "ERGEN_TYPE_CODE_AMYL_CINNAMAL\020\004\022$\n ALLER" +
-      "GEN_TYPE_CODE_ANISE_ALCOHOL\020\005\022\035\n\031ALLERGE" +
-      "N_TYPE_CODE_BARLEY\020\006\022%\n!ALLERGEN_TYPE_CO" +
-      "DE_BENZYL_ALCOHOL\020\007\022&\n\"ALLERGEN_TYPE_COD" +
-      "E_BENZYL_BENZOATE\020\010\022\'\n#ALLERGEN_TYPE_COD" +
-      "E_BENZYL_CINNAMATE\020\t\022(\n$ALLERGEN_TYPE_CO" +
-      "DE_BENZYL_SALICYLATE\020\n\022\"\n\036ALLERGEN_TYPE_" +
-      "CODE_BRAZIL_NUTS\020\013\0223\n/ALLERGEN_TYPE_CODE" +
-      "_BUTYLPHENYL_METHYLPROPIONATE\020\014\022\036\n\032ALLER" +
-      "GEN_TYPE_CODE_CARROTS\020\r\022\"\n\036ALLERGEN_TYPE" +
-      "_CODE_CASHEW_NUTS\020\016\022\035\n\031ALLERGEN_TYPE_COD" +
-      "E_CELERY\020\017\0220\n,ALLERGEN_TYPE_CODE_CEREALS" +
-      "_CONTAINING_GLUTEN\020\020\022\037\n\033ALLERGEN_TYPE_CO" +
-      "DE_CINNAMAL\020\021\022\'\n#ALLERGEN_TYPE_CODE_CINN" +
-      "AMYL_ALCOHOL\020\022\022\035\n\031ALLERGEN_TYPE_CODE_CIT" +
-      "RAL\020\023\022\"\n\036ALLERGEN_TYPE_CODE_CITRONELLOL\020" +
-      "\024\022\034\n\030ALLERGEN_TYPE_CODE_COCOA\020\025\022 \n\034ALLER" +
-      "GEN_TYPE_CODE_CORIANDER\020\026\022\033\n\027ALLERGEN_TY" +
-      "PE_CODE_CORN\020\027\022\037\n\033ALLERGEN_TYPE_CODE_COU" +
-      "MARIN\020\030\022\"\n\036ALLERGEN_TYPE_CODE_CRUSTACEAN" +
-      "S\020\031\022\033\n\027ALLERGEN_TYPE_CODE_EGGS\020\032\022\036\n\032ALLE" +
-      "RGEN_TYPE_CODE_EUGENOL\020\033\022)\n%ALLERGEN_TYP" +
-      "E_CODE_EVERNIA_FURFURACEA\020\034\022(\n$ALLERGEN_" +
-      "TYPE_CODE_EVERNIA_PRUNASTRI\020\035\022\037\n\033ALLERGE" +
-      "N_TYPE_CODE_FARNESOL\020\036\022\033\n\027ALLERGEN_TYPE_" +
-      "CODE_FISH\020\037\022\037\n\033ALLERGEN_TYPE_CODE_GERANI" +
-      "OL\020 \022\035\n\031ALLERGEN_TYPE_CODE_GLUTEN\020!\022 \n\034A" +
-      "LLERGEN_TYPE_CODE_HAZELNUTS\020\"\022%\n!ALLERGE" +
-      "N_TYPE_CODE_HEXYL_CINNAMAL\020#\022)\n%ALLERGEN" +
-      "_TYPE_CODE_HYDROXYCITRONELLAL\020$\022]\nYALLER" +
-      "GEN_TYPE_CODE_HYDROXYISOHEXYL_3_CYCLOHEX" +
-      "ENE_CARBOXALDEHYDE_ISOEUGENOL_LIMONENE_L" +
-      "INAL\020%\022\034\n\030ALLERGEN_TYPE_CODE_KAMUT\020&\022\036\n\032" +
-      "ALLERGEN_TYPE_CODE_LACTOSE\020\'\022\035\n\031ALLERGEN" +
-      "_TYPE_CODE_LUPINE\020(\022%\n!ALLERGEN_TYPE_COD" +
-      "E_MACADAMIA_NUTS\020)\022)\n%ALLERGEN_TYPE_CODE" +
-      "_METHYL_2_OCTYNOATE\020*\022\033\n\027ALLERGEN_TYPE_C" +
-      "ODE_MILK\020+\022\037\n\033ALLERGEN_TYPE_CODE_MOLLUSC" +
-      "S\020,\022\036\n\032ALLERGEN_TYPE_CODE_MUSTARD\020-\022,\n(A" +
-      "LLERGEN_TYPE_CODE_NO_DECLARED_ALLERGENS\020" +
-      ".\022\032\n\026ALLERGEN_TYPE_CODE_OAT\020/\022\036\n\032ALLERGE" +
-      "N_TYPE_CODE_PEANUTS\0200\022\033\n\027ALLERGEN_TYPE_C" +
-      "ODE_PEAS\0201\022!\n\035ALLERGEN_TYPE_CODE_PECAN_N" +
-      "UTS\0202\022!\n\035ALLERGEN_TYPE_CODE_PISTACHIOS\0203" +
-      "\022!\n\035ALLERGEN_TYPE_CODE_POD_FRUITS\0204\022&\n\"A" +
-      "LLERGEN_TYPE_CODE_QUEENSLAND_NUTS\0205\022\032\n\026A" +
-      "LLERGEN_TYPE_CODE_RYE\0206\022#\n\037ALLERGEN_TYPE" +
-      "_CODE_SESAME_SEEDS\0207\022\037\n\033ALLERGEN_TYPE_CO" +
-      "DE_SOYBEANS\0208\022\034\n\030ALLERGEN_TYPE_CODE_SPEL" +
-      "T\0209\022&\n\"ALLERGEN_TYPE_CODE_SULPHUR_DIOXID" +
-      "E\020:\022 \n\034ALLERGEN_TYPE_CODE_TREE_NUTS\020;\022&\n" +
-      "\"ALLERGEN_TYPE_CODE_TREE_NUT_TRACES\020<\022\036\n" +
-      "\032ALLERGEN_TYPE_CODE_WALNUTS\020=\022\034\n\030ALLERGE" +
-      "N_TYPE_CODE_WHEAT\020>*\217\001\n\022NutritionValueUn" +
-      "it\022$\n NUTRITION_VALUE_UNIT_UNSPECIFIED\020\000" +
-      "\022\023\n\017ENERGY_CALORIES\020\001\022\025\n\021ENERGY_KILOJOUL" +
-      "ES\020\002\022\025\n\021WEIGHT_MILLIGRAMS\020\003\022\020\n\014WEIGHT_GR" +
-      "AMS\020\004*\270\001\n\024ContainmentLevelCode\022&\n\"CONTAI" +
-      "NMENT_LEVEL_CODE_UNSPECIFIED\020\000\022#\n\037CONTAI" +
-      "NMENT_LEVEL_CODE_CONTAINS\020\001\022+\n\'CONTAINME" +
-      "NT_LEVEL_CODE_DOES_NOT_CONTAIN\020\002\022&\n\"CONT" +
-      "AINMENT_LEVEL_CODE_MAY_CONTAIN\020\003*c\n\013Depo" +
-      "sitCode\022\034\n\030DEPOSIT_CODE_UNSPECIFIED\020\000\022\031\n" +
-      "\025DEPOSIT_CODE_REUSABLE\020\001\022\033\n\027DEPOSIT_CODE" +
-      "_RECYCLABLE\020\002b\006proto3"
-    };
-    descriptor = com.google.protobuf.Descriptors.FileDescriptor
-      .internalBuildGeneratedFileFrom(descriptorData,
-        new com.google.protobuf.Descriptors.FileDescriptor[] {
-          com.google.protobuf.TimestampProto.getDescriptor(),
-          com.google.type.LocalizedTextProto.getDescriptor(),
-          com.google.type.MoneyProto.getDescriptor(),
-        });
-    internal_static_food_menu_v1_FoodMenuFeed_descriptor =
-      getDescriptor().getMessageTypes().get(0);
-    internal_static_food_menu_v1_FoodMenuFeed_fieldAccessorTable = new
-      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
-        internal_static_food_menu_v1_FoodMenuFeed_descriptor,
-        new java.lang.String[] { "Data", });
-    internal_static_food_menu_v1_MenuComponent_descriptor =
-      getDescriptor().getMessageTypes().get(1);
-    internal_static_food_menu_v1_MenuComponent_fieldAccessorTable = new
-      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
-        internal_static_food_menu_v1_MenuComponent_descriptor,
-        new java.lang.String[] { "Menu", "Section", "Item", "Option", "Type", });
-    internal_static_food_menu_v1_Menu_descriptor =
-      getDescriptor().getMessageTypes().get(2);
-    internal_static_food_menu_v1_Menu_fieldAccessorTable = new
-      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
-        internal_static_food_menu_v1_Menu_descriptor,
-        new java.lang.String[] { "MenuId", "MerchantIds", "DisplayName", "Language", "Disclaimer", "MenuItemIds", "MenuSectionIds", "LastMerchantUpdateTime", });
-    internal_static_food_menu_v1_MenuSection_descriptor =
-      getDescriptor().getMessageTypes().get(3);
-    internal_static_food_menu_v1_MenuSection_fieldAccessorTable = new
-      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
-        internal_static_food_menu_v1_MenuSection_descriptor,
-        new java.lang.String[] { "MenuSectionId", "DisplayName", "Description", "Images", "MenuItemIds", "MenuSectionIds", });
-    internal_static_food_menu_v1_MenuItem_descriptor =
-      getDescriptor().getMessageTypes().get(4);
-    internal_static_food_menu_v1_MenuItem_fieldAccessorTable = new
-      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
-        internal_static_food_menu_v1_MenuItem_descriptor,
-        new java.lang.String[] { "MenuItemId", "DisplayName", "Description", "Images", "OfferSet", "MenuItemOptionSet", "ItemAttributes", "Pricing", });
-    internal_static_food_menu_v1_MenuItem_MenuItemOptionSet_descriptor =
-      internal_static_food_menu_v1_MenuItem_descriptor.getNestedTypes().get(0);
-    internal_static_food_menu_v1_MenuItem_MenuItemOptionSet_fieldAccessorTable = new
-      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
-        internal_static_food_menu_v1_MenuItem_MenuItemOptionSet_descriptor,
-        new java.lang.String[] { "MenuItemOptionIds", });
-    internal_static_food_menu_v1_MenuItemOption_descriptor =
-      getDescriptor().getMessageTypes().get(5);
-    internal_static_food_menu_v1_MenuItemOption_fieldAccessorTable = new
-      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
-        internal_static_food_menu_v1_MenuItemOption_descriptor,
-        new java.lang.String[] { "MenuItemOptionId", "Value", "OfferSet", "ItemAttributes", });
-    internal_static_food_menu_v1_MenuItemAttributes_descriptor =
-      getDescriptor().getMessageTypes().get(6);
-    internal_static_food_menu_v1_MenuItemAttributes_fieldAccessorTable = new
-      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
-        internal_static_food_menu_v1_MenuItemAttributes_descriptor,
-        new java.lang.String[] { "NumberOfServings", "NutritionInformation", "SuitableDiets", "Additive", "Allergen", "PackagingDepositInfo", "NumberOfServings", });
-    internal_static_food_menu_v1_OfferSet_descriptor =
-      getDescriptor().getMessageTypes().get(7);
-    internal_static_food_menu_v1_OfferSet_fieldAccessorTable = new
-      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
-        internal_static_food_menu_v1_OfferSet_descriptor,
-        new java.lang.String[] { "Offers", });
-    internal_static_food_menu_v1_Offer_descriptor =
-      getDescriptor().getMessageTypes().get(8);
-    internal_static_food_menu_v1_Offer_fieldAccessorTable = new
-      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
-        internal_static_food_menu_v1_Offer_descriptor,
-        new java.lang.String[] { "Price", });
-    internal_static_food_menu_v1_Disclaimer_descriptor =
-      getDescriptor().getMessageTypes().get(9);
-    internal_static_food_menu_v1_Disclaimer_fieldAccessorTable = new
-      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
-        internal_static_food_menu_v1_Disclaimer_descriptor,
-        new java.lang.String[] { "Text", "Uri", });
-    internal_static_food_menu_v1_TextField_descriptor =
-      getDescriptor().getMessageTypes().get(10);
-    internal_static_food_menu_v1_TextField_fieldAccessorTable = new
-      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
-        internal_static_food_menu_v1_TextField_descriptor,
-        new java.lang.String[] { "Text", });
-    internal_static_food_menu_v1_Image_descriptor =
-      getDescriptor().getMessageTypes().get(11);
-    internal_static_food_menu_v1_Image_fieldAccessorTable = new
-      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
-        internal_static_food_menu_v1_Image_descriptor,
-        new java.lang.String[] { "Uri", });
-    internal_static_food_menu_v1_MenuItemOptionProperty_descriptor =
-      getDescriptor().getMessageTypes().get(12);
-    internal_static_food_menu_v1_MenuItemOptionProperty_fieldAccessorTable = new
-      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
-        internal_static_food_menu_v1_MenuItemOptionProperty_descriptor,
-        new java.lang.String[] { "PropertyType", "PropertyVal", "TextVal", "Value", });
-    internal_static_food_menu_v1_NutritionInformation_descriptor =
-      getDescriptor().getMessageTypes().get(13);
-    internal_static_food_menu_v1_NutritionInformation_fieldAccessorTable = new
-      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
-        internal_static_food_menu_v1_NutritionInformation_descriptor,
-        new java.lang.String[] { "Energy", "SodiumContent", "ServingSize", "Description", "ServingSize", });
-    internal_static_food_menu_v1_NutritionInformation_NutritionValue_descriptor =
-      internal_static_food_menu_v1_NutritionInformation_descriptor.getNestedTypes().get(0);
-    internal_static_food_menu_v1_NutritionInformation_NutritionValue_fieldAccessorTable = new
-      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
-        internal_static_food_menu_v1_NutritionInformation_NutritionValue_descriptor,
-        new java.lang.String[] { "Amount", "Range", "Unit", "Value", });
-    internal_static_food_menu_v1_NutritionInformation_NutritionValue_Range_descriptor =
-      internal_static_food_menu_v1_NutritionInformation_NutritionValue_descriptor.getNestedTypes().get(0);
-    internal_static_food_menu_v1_NutritionInformation_NutritionValue_Range_fieldAccessorTable = new
-      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
-        internal_static_food_menu_v1_NutritionInformation_NutritionValue_Range_descriptor,
-        new java.lang.String[] { "Min", "Max", });
-    internal_static_food_menu_v1_Additive_descriptor =
-      getDescriptor().getMessageTypes().get(14);
-    internal_static_food_menu_v1_Additive_fieldAccessorTable = new
-      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
-        internal_static_food_menu_v1_Additive_descriptor,
-        new java.lang.String[] { "Name", "ContainmentLevelCode", "ContainmentLevelCode", });
-    internal_static_food_menu_v1_Allergen_descriptor =
-      getDescriptor().getMessageTypes().get(15);
-    internal_static_food_menu_v1_Allergen_fieldAccessorTable = new
-      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
-        internal_static_food_menu_v1_Allergen_descriptor,
-        new java.lang.String[] { "AllergenTypeCode", "ContainmentLevelCode", "ContainmentLevelCode", });
-    internal_static_food_menu_v1_DepositInfo_descriptor =
-      getDescriptor().getMessageTypes().get(16);
-    internal_static_food_menu_v1_DepositInfo_fieldAccessorTable = new
-      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
-        internal_static_food_menu_v1_DepositInfo_descriptor,
-        new java.lang.String[] { "DepositCode", "DepositValue", "DepositCode", });
-    com.google.protobuf.TimestampProto.getDescriptor();
-    com.google.type.LocalizedTextProto.getDescriptor();
-    com.google.type.MoneyProto.getDescriptor();
-  }
-
-  // @@protoc_insertion_point(outer_class_scope)
-}
diff --git a/menu-feed/proto/food_menu.proto b/menu-feed/proto/food_menu.proto
deleted file mode 100644
index 62689d8..0000000
--- a/menu-feed/proto/food_menu.proto
+++ /dev/null
@@ -1,531 +0,0 @@
-
-  // Feeds declaration
-  syntax = "proto3";
-  
-  package food.menu.v1;
-
-  import "google/protobuf/timestamp.proto";
-  import "money.proto";
-  import "localized_text.proto";
-
-  option go_package = "food/menu/v1/proto";
-
-  
-  message FoodMenuFeed {
-  repeated MenuComponent data = 1;
-}
-  
-  message MenuComponent {
-  oneof type {
-    food.menu.v1.Menu menu = 1;
-    food.menu.v1.MenuSection section = 2;
-    food.menu.v1.MenuItem item = 3;
-    food.menu.v1.MenuItemOption option = 4;
-  }
-}
-  
-  // Top-level catalog of food items offered by a Food establishment. Menu
-// contains a list of merchant ids and the menu that apply to those merchants.
-// A Menu can be used to represent single merchant with the menu, or multiple
-// merchants (typically chain restaurants) with the menus.
-message Menu {
-  // An opaque string from a partner which uniquely identifies the Menu within
-  // the partner feed.
-  // Required.
-  string menu_id = 1;
-
-  // The merchants to whom the menu apply.
-  // Note: This field is repeated so chain restaurants can share the same menu
-  // across multiple locations, each of which is a separate merchant.
-  // Required.
-  repeated string merchant_ids = 2;
-
-  // The name that can identify the Menu when a user is browsing the menu.
-  // Optional.
-  TextField display_name = 3;
-
-  // The default language code associated with the text labels contained in the
-  // menu. Expects BCP-47 language code, such as "en-US" or "sr-Latn".
-  //
-  // For more information, see
-  // http://www.unicode.org/reports/tr35/#Unicode_locale_identifier.
-  // Optional.
-  string language = 4;
-
-  // Disclaimer to be shown to the user for the menu. For example, nutritional
-  // information disclosure and allergen disclosure.
-  // Optional.
-  Disclaimer disclaimer = 5;
-
-  // IDs of items contained within this menu. Expects first-level menu items
-  // only.
-  // Optional.
-  repeated string menu_item_ids = 6;
-
-  // IDs of sections contained within this menu. Expects first-level menu
-  // sections only.
-  // Optional.
-  repeated string menu_section_ids = 7;
-
-  // Timestamp when this Menu or any of its contents was last updated by the
-  // restaurant; i.e. a date to be associated with the phrase “accurate as of
-  // date”.
-  // Optional.
-  google.protobuf.Timestamp last_merchant_update_time = 8;
-
-}
-  
-  // A menu section is a grouping of items on a menu. Separate MenuSections are
-// usually created for each logical grouping of items on a menu. For example,
-// meal course type (Appetizer, Main, Dessert) and food categories (Burgers,
-// Drinks) are typical sections.
-message MenuSection {
-  // An opaque string from an partner which uniquely identifies the MenuSection
-  // within the partner feed.
-  // Required.
-  string menu_section_id = 1;
-
-  // The name that can identify the MenuSection when a user is browsing the
-  // menu.
-  // Required.
-  TextField display_name = 2;
-
-  // A description of the menu section.
-  // Optional.
-  TextField description = 3;
-
-  // Image(s) of the menu section.
-  // Optional.
-  repeated Image images = 4;
-
-
-  // IDs of MenuItem entities that correspond to this MenuSection entity. A
-  // section is expected to have at least 1 item if it does not contain any
-  // sub-sections.
-  // Optional.
-  repeated string menu_item_ids = 6;
-
-  // Child MenuSections (sub-sections) that correspond to this MenuSection
-  // entity.
-  // Optional.
-  repeated string menu_section_ids = 7;
-
-
-
-
-
-
-}
-  
-  // Represents a single food or drink item offered by a Food establishment.
-message MenuItem {
-  // An opaque string from an partner which uniquely identifies the MenuItem
-  // within the partner feed.
-  // Required.
-  string menu_item_id = 1;
-
-  // The name that can identify the MenuItem when a user is browsing the menu.
-  // Required.
-  TextField display_name = 2;
-
-  // A description of the menu item.
-  // Optional.
-  TextField description = 3;
-
-  // Image(s) of the menu item.
-  // Optional.
-  repeated Image images = 4;
-
-  // Container that specifies a list of options available on an item.
-  message MenuItemOptionSet {
-    // IDs of menu item options that are applicable to this menu item.
-    // Required.
-    repeated string menu_item_option_ids = 1;
-  }
-
-  // The menu item must either have a price, or a set of menu item options.
-  // Required.
-  oneof pricing {
-    // Available offers to purchase this food item.
-    OfferSet offer_set = 6;
-
-    // Available options for this menu item.
-    MenuItemOptionSet menu_item_option_set = 7;
-  }
-
-  // Attributes about this menu item.
-  // Optional.
-  MenuItemAttributes item_attributes = 8;
-
-
-}
-  
-  // Describes choices that a user would be required to make when selecting a
-// dish / combo. The user must select an option, otherwise the order is
-// considered invalid (e.g. the user must choose small, medium, or large for a
-// pizza).
-message MenuItemOption {
-  // An opaque string from an partner which uniquely identifies the
-  // MenuItemOption within the partner feed.
-  // Required.
-  string menu_item_option_id = 9;
-
-  // Option property and value e.g. Size: Small.
-  // Required.
-  MenuItemOptionProperty value = 2;
-
-
-
-  // Available offers to purchase this menu item option.
-  // Required.
-  OfferSet offer_set = 4;
-
-  // Attributes about this menu item option.
-  // Optional.
-  MenuItemAttributes item_attributes = 5;
-
-
-}
-  
-  // Describes attributes about a particular menu item or option.
-message MenuItemAttributes {
-  // Number of servings available in a given menu item.
-  // Optional.
-  optional int32 number_of_servings = 1;
-
-  // Describes all the nutritional information of the item, e.g. calories, fat
-  // content.
-  // Optional.
-  NutritionInformation nutrition_information = 2;
-
-  // The dietary restrictions that this menu item complies with.
-  // Optional.
-  repeated DietaryRestriction suitable_diets = 3;
-
-  // Additives of this menu item.
-  // Optional.
-  repeated Additive additive = 4;
-
-  // Allergens of this menu item.
-  // Optional.
-  repeated Allergen allergen = 5;
-
-  // Packaging and recycling information of this menu item.
-  // Optional.
-  DepositInfo packaging_deposit_info = 6;
-}
-  
-  // Container for a list of offers available on a menu item / option.
-// Only one offer should be applicable/valid at one particular time.
-// For example, a drink can have 2 offers where one is applicable in the morning
-// while the other is applicable in the evening during happy hours.
-message OfferSet {
-  // List of possible offers.
-  // Required.
-  repeated Offer offers = 1;
-}
-
-  // Represents pricing and availability information for MenuItems and
-// MenuItemOptions.
-message Offer {
-  // Monetary value of the menu item/option on sale. Can be 0 to represent free.
-  // Required.
-  google.type.Money price = 1;
-
-
-
-
-
-
-}
-  
-  // Partner provided disclaimer shown to the user. Contains a text disclaimer
-// along with an optional URL for more information.
-// Some example include: associated medical risks/warnings, any additional
-// fees/gratutity, etc.
-message Disclaimer {
-  // Body of the disclaimer text to be shown to the user.
-  // Required.
-  TextField text = 1;
-
-  // URL containing more information about the disclaimer.
-  // Optional.
-  string uri = 2;
-}
-  
-  // A text payload that contains one or more localized values.
-message TextField {
-  // Per-locale text values.
-  //
-  // If there is only one desired locale support, then the language_code within
-  // each text is not required to be set and the language will be inferred from
-  // the default language of the menu.
-  //
-  // If there are multiple texts across different locales, then the
-  // language_code must be set for each text. The first text in the list is
-  // considered the preferred representation.
-  // Required.
-  repeated google.type.LocalizedText text = 1;
-}
-  
-  // Represents an image associated with a menu entity.
-message Image {
-  // URL containing the raw pixels of the image.
-  // Required.
-  string uri = 1;
-}
-
-  // Describes the property of a menu item option and its value.
-message MenuItemOptionProperty {
-  // Types of property that the option is for.
-  enum PropertyType {
-    // Do not use. The property type is not explicitly specified.
-    UNKNOWN_PROPERTY_TYPE = 0;
-    // A generic menu item option property, which is not one of the more
-    // specific types below. Use this if the property is not of type
-    // SIZE or PIZZA_SIDE.
-    OPTION = 1;
-    // Denotes the menu item option property of size (e.g. small, medium, or
-    // large).
-    SIZE = 2;
-    // Property specific to pizzas. For example: this MenuItemOption is only
-    // valid for a portion/whole pizza, such as mushroom toppings on the left
-    // side, right side, or whole pizza).
-    PIZZA_SIDE = 3;
-  }
-
-  // Well-defined values for the option property.
-  enum PropertyValue {
-    // Do not use. The property value is not explicitly specified.
-    UNKNOWN_PROPERTY_VALUE = 0;
-    // The MenuItemOption applies only to the left side of a pizza.
-    PIZZA_SIDE_LEFT = 1;
-    // The MenuItemOption applies only to the right side of a pizza.
-    PIZZA_SIDE_RIGHT = 2;
-    // The MenuItemOption applies to the entire pizza.
-    PIZZA_SIDE_WHOLE = 3;
-  }
-
-  // The type of this option property.
-  // Required.
-  PropertyType property_type = 1;
-
-  // Required.
-  oneof value {
-    // A well-defined value for the option property. Currently only expected
-    // if the property_type is PIZZA_SIDE.
-    PropertyValue property_val = 2;
-
-    // A free-form text for the value of the property. Expected for
-    // property_type OPTION and SIZE.
-    TextField text_val = 3;
-  }
-}
-  
-  // Describes all the nutritional measurements of a MenuItem or add-on.
-message NutritionInformation {
-  // Describes a single nutritional measurement of the serving of food.
-  message NutritionValue {
-    // Describes a closed range for the nutrition value. E.g. "100-150 cal"
-    message Range {
-      // The minimum amount of nutrition value.
-      // Required.
-      double min = 1;
-
-      // The maximum amount of nutrition value.
-      // Required.
-      double max = 2;
-    }
-
-    // Required oneof.
-    oneof value {
-      // A single number representing the amount of nutritional value.
-      double amount = 1;
-
-      // A range representing the amount of nutritional value.
-      Range range = 3;
-    }
-
-    // The unit associated with the amount as specified from the partner. We
-    // will validate the feed so that the unit for each type of nutrition value
-    // is expected for that type of value. For example, only ENERGY_CALORIES
-    // and ENERGY_KILOJOULES are expected on energy property of
-    // NutritionalInformation.
-    // Required.
-    NutritionValueUnit unit = 2;
-  }
-
-  // The amount of nutritional energy of the serving of food. Can be defined
-  // in Calories or kilojoules.
-  // Optional.
-  NutritionValue energy = 1;
-
-  // The amount of sodium content, measured in grams or milligrams.
-  // Optional.
-  NutritionValue sodium_content = 2;
-
-  // The number of servings the nutrition value applies to.
-  // Optional.
-  optional int32 serving_size = 3;
-
-  // Nutrition information in free text. For example "Contains preservatives".
-  // Optional.
-  TextField description = 4;
-}
-  
-  // Indicates a dietary restriction or guideline adhered to during
-// food preparation.
-enum DietaryRestriction {
-  // Do not use. The dietary restriction is not explicitly specified.
-  DIET_UNSPECIFIED = 0;
-  DIET_DIABETIC = 1;
-  DIET_GLUTEN_FREE = 2;
-  DIET_HALAL = 3;
-  DIET_HINDU = 4;
-  DIET_KOSHER = 5;
-  DIET_LOW_CALORIE = 6;
-  DIET_LOW_FAT = 7;
-  DIET_LOW_LACTOSE = 8;
-  DIET_LOW_SALT = 9;
-  DIET_VEGAN = 10;
-  DIET_VEGETARIAN = 11;
-}
-
-  // Additive shown to the user on the MenuItem. An additive preserves or enhances
-// the quality of the food.
-message Additive {
-  // Descriptive text of the additive, e.g. "preservatives".
-  // Required.
-  TextField name = 1;
-
-  // Whether the MenuItem contains, may contain, or is free from this additive.
-  // Defaults to contains.
-  // Optional.
-  optional ContainmentLevelCode containment_level_code = 2;
-}
-  
-  // Allergen shown to the user on the MenuItem. An allergen relates to qualities
-// of food that causes allergic reactions.
-message Allergen {
-  // Type of allergen.
-  // Required.
-  AllergenTypeCode allergen_type_code = 1;
-
-  // Whether the MenuItem contains, may contain, or is free from this allergen.
-  // Defaults to contains.
-  // Optional.
-  optional ContainmentLevelCode containment_level_code = 2;
-}
-
-  // Allergen type derived from GS1: http://gs1.org/voc/AllergenTypeCode
-enum AllergenTypeCode {
-  // Do not use. The allergen type code is not explicitly specified.
-  ALLERGEN_TYPE_CODE_UNSPECIFIED = 0;
-  ALLERGEN_TYPE_CODE_ALMONDS = 1;
-  ALLERGEN_TYPE_CODE_ALPHA_ISOMETHYL_IONONE = 2;
-  ALLERGEN_TYPE_CODE_ALCOHOL = 3;
-  ALLERGEN_TYPE_CODE_AMYL_CINNAMAL = 4;
-  ALLERGEN_TYPE_CODE_ANISE_ALCOHOL = 5;
-  ALLERGEN_TYPE_CODE_BARLEY = 6;
-  ALLERGEN_TYPE_CODE_BENZYL_ALCOHOL = 7;
-  ALLERGEN_TYPE_CODE_BENZYL_BENZOATE = 8;
-  ALLERGEN_TYPE_CODE_BENZYL_CINNAMATE = 9;
-  ALLERGEN_TYPE_CODE_BENZYL_SALICYLATE = 10;
-  ALLERGEN_TYPE_CODE_BRAZIL_NUTS = 11;
-  ALLERGEN_TYPE_CODE_BUTYLPHENYL_METHYLPROPIONATE = 12;
-  ALLERGEN_TYPE_CODE_CARROTS = 13;
-  ALLERGEN_TYPE_CODE_CASHEW_NUTS = 14;
-  ALLERGEN_TYPE_CODE_CELERY = 15;
-  ALLERGEN_TYPE_CODE_CEREALS_CONTAINING_GLUTEN = 16;
-  ALLERGEN_TYPE_CODE_CINNAMAL = 17;
-  ALLERGEN_TYPE_CODE_CINNAMYL_ALCOHOL = 18;
-  ALLERGEN_TYPE_CODE_CITRAL = 19;
-  ALLERGEN_TYPE_CODE_CITRONELLOL = 20;
-  ALLERGEN_TYPE_CODE_COCOA = 21;
-  ALLERGEN_TYPE_CODE_CORIANDER = 22;
-  ALLERGEN_TYPE_CODE_CORN = 23;
-  ALLERGEN_TYPE_CODE_COUMARIN = 24;
-  ALLERGEN_TYPE_CODE_CRUSTACEANS = 25;
-  ALLERGEN_TYPE_CODE_EGGS = 26;
-  ALLERGEN_TYPE_CODE_EUGENOL = 27;
-  ALLERGEN_TYPE_CODE_EVERNIA_FURFURACEA = 28;
-  ALLERGEN_TYPE_CODE_EVERNIA_PRUNASTRI = 29;
-  ALLERGEN_TYPE_CODE_FARNESOL = 30;
-  ALLERGEN_TYPE_CODE_FISH = 31;
-  ALLERGEN_TYPE_CODE_GERANIOL = 32;
-  ALLERGEN_TYPE_CODE_GLUTEN = 33;
-  ALLERGEN_TYPE_CODE_HAZELNUTS = 34;
-  ALLERGEN_TYPE_CODE_HEXYL_CINNAMAL = 35;
-  ALLERGEN_TYPE_CODE_HYDROXYCITRONELLAL = 36;
-  ALLERGEN_TYPE_CODE_HYDROXYISOHEXYL_3_CYCLOHEXENE_CARBOXALDEHYDE_ISOEUGENOL_LIMONENE_LINAL =
-      37;
-  ALLERGEN_TYPE_CODE_KAMUT = 38;
-  ALLERGEN_TYPE_CODE_LACTOSE = 39;
-  ALLERGEN_TYPE_CODE_LUPINE = 40;
-  ALLERGEN_TYPE_CODE_MACADAMIA_NUTS = 41;
-  ALLERGEN_TYPE_CODE_METHYL_2_OCTYNOATE = 42;
-  ALLERGEN_TYPE_CODE_MILK = 43;
-  ALLERGEN_TYPE_CODE_MOLLUSCS = 44;
-  ALLERGEN_TYPE_CODE_MUSTARD = 45;
-  ALLERGEN_TYPE_CODE_NO_DECLARED_ALLERGENS = 46;
-  ALLERGEN_TYPE_CODE_OAT = 47;
-  ALLERGEN_TYPE_CODE_PEANUTS = 48;
-  ALLERGEN_TYPE_CODE_PEAS = 49;
-  ALLERGEN_TYPE_CODE_PECAN_NUTS = 50;
-  ALLERGEN_TYPE_CODE_PISTACHIOS = 51;
-  ALLERGEN_TYPE_CODE_POD_FRUITS = 52;
-  ALLERGEN_TYPE_CODE_QUEENSLAND_NUTS = 53;
-  ALLERGEN_TYPE_CODE_RYE = 54;
-  ALLERGEN_TYPE_CODE_SESAME_SEEDS = 55;
-  ALLERGEN_TYPE_CODE_SOYBEANS = 56;
-  ALLERGEN_TYPE_CODE_SPELT = 57;
-  ALLERGEN_TYPE_CODE_SULPHUR_DIOXIDE = 58;
-  ALLERGEN_TYPE_CODE_TREE_NUTS = 59;
-  ALLERGEN_TYPE_CODE_TREE_NUT_TRACES = 60;
-  ALLERGEN_TYPE_CODE_WALNUTS = 61;
-  ALLERGEN_TYPE_CODE_WHEAT = 62;
-}
-
-  // Partner provided deposit info to instruct the user how to deposit a food item
-// or bottle and the value of such deposit.
-message DepositInfo {
-  // The deposit strategy to employ, e.g. "reusable".
-  // Optional.
-  optional DepositCode deposit_code = 1;
-
-  // Value refunded for depositing the item properly.
-  // Optional.
-  google.type.Money deposit_value = 2;
-}
-
-  enum NutritionValueUnit {
-  // Do not use. The nutrition value unit is not explicitly set.
-  NUTRITION_VALUE_UNIT_UNSPECIFIED = 0;
-
-  // Units used to express the amount of energy in a menu item.
-  ENERGY_CALORIES = 1;
-  ENERGY_KILOJOULES = 2;
-
-  // Units used to express the amount in weight a substance is present in the
-  // menu item.
-  WEIGHT_MILLIGRAMS = 3;
-  WEIGHT_GRAMS = 4;
-}
-
-  // Indicates the level of containment a food item has of a certain attribute,
-// such as allergens or additives.
-enum ContainmentLevelCode {
-  // Do not use. The containment level code is not explicitly specified.
-  CONTAINMENT_LEVEL_CODE_UNSPECIFIED = 0;
-  CONTAINMENT_LEVEL_CODE_CONTAINS = 1;
-  CONTAINMENT_LEVEL_CODE_DOES_NOT_CONTAIN = 2;
-  CONTAINMENT_LEVEL_CODE_MAY_CONTAIN = 3;
-}
-
-  // Indicates how to properly deposit a food item or bottle.
-enum DepositCode {
-  // Do not use. The deposite code is not explicitly specified.
-  DEPOSIT_CODE_UNSPECIFIED = 0;
-  DEPOSIT_CODE_REUSABLE = 1;
-  DEPOSIT_CODE_RECYCLABLE = 2;
-}
diff --git a/menu-feed/proto/localized_text.proto b/menu-feed/proto/localized_text.proto
deleted file mode 100644
index df7ebf2..0000000
--- a/menu-feed/proto/localized_text.proto
+++ /dev/null
@@ -1,37 +0,0 @@
-  // Copyright 2021 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-syntax = "proto3";
-
-package google.type;
-
-option cc_enable_arenas = true;
-option go_package = "google.golang.org/genproto/googleapis/type/localized_text;localized_text";
-option java_multiple_files = true;
-option java_outer_classname = "LocalizedTextProto";
-option java_package = "com.google.type";
-option objc_class_prefix = "GTP";
-
-// Localized variant of a text in a particular language.
-message LocalizedText {
-  // Localized string in the language corresponding to `language_code' below.
-  string text = 1;
-
-  // The text's BCP-47 language code, such as "en-US" or "sr-Latn".
-  //
-  // For more information, see
-  // http://www.unicode.org/reports/tr35/#Unicode_locale_identifier.
-  string language_code = 2;
-}
-
diff --git a/menu-feed/proto/money.proto b/menu-feed/proto/money.proto
deleted file mode 100644
index dbd61d6..0000000
--- a/menu-feed/proto/money.proto
+++ /dev/null
@@ -1,43 +0,0 @@
-  // Copyright 2021 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-syntax = "proto3";
-
-package google.type;
-
-option cc_enable_arenas = true;
-option go_package = "google.golang.org/genproto/googleapis/type/money;money";
-option java_multiple_files = true;
-option java_outer_classname = "MoneyProto";
-option java_package = "com.google.type";
-option objc_class_prefix = "GTP";
-
-// Represents an amount of money with its currency type.
-message Money {
-  // The three-letter currency code defined in ISO 4217.
-  string currency_code = 1;
-
-  // The whole units of the amount.
-  // For example if `currencyCode` is `"USD"`, then 1 unit is one US dollar.
-  int64 units = 2;
-
-  // Number of nano (10^-9) units of the amount.
-  // The value must be between -999,999,999 and +999,999,999 inclusive.
-  // If `units` is positive, `nanos` must be positive or zero.
-  // If `units` is zero, `nanos` can be positive, zero, or negative.
-  // If `units` is negative, `nanos` must be negative or zero.
-  // For example $-1.75 is represented as `units`=-1 and `nanos`=-750,000,000.
-  int32 nanos = 3;
-}
-
diff --git a/menu-feed/python/feed.py b/menu-feed/python/feed.py
index 33c5435..9a12687 100644
--- a/menu-feed/python/feed.py
+++ b/menu-feed/python/feed.py
@@ -64,5 +64,14 @@
 optionOffer.price.units = 8
 optionOffer.price.nanos = 0
 
+# Example testing for menu feed size
+# Protocol buffer message must be less than 2 GiB
+# https://protobuf.dev/programming-guides/proto-limits/
+# It is recommended to not exceed 200 MB, as there is an Actions
+# Center limit of 200 MB per file after compression.
+if feed.ByteSize() > 200 * 1024 * 1024:
+		# start new file
+    print('starting new file...')
+
 feedJSON = json.dumps(MessageToDict(feed, preserving_proto_field_name=True))
 print(feedJSON)
diff --git a/menu-feed/typescript/dist/feed.js b/menu-feed/typescript/dist/feed.js
index 7b199a6..4f5056d 100644
--- a/menu-feed/typescript/dist/feed.js
+++ b/menu-feed/typescript/dist/feed.js
@@ -52,5 +52,13 @@
 const feed = {
     data: [{ menu }, { section }, { item }, { option }]
 };
+// Example testing for menu feed size
+// Protocol buffer message must be less than 2 GiB
+// https://protobuf.dev/programming-guides/proto-limits/
+// It is recommended to not exceed 200 MB, as there is an Actions
+// Center limit of 200 MB per file after compression.
+if (new Blob([JSON.stringify(feed)]).size > 200 * 1024 * 1024) {
+    // create a new file
+}
 console.log(JSON.stringify(feed));
 //# sourceMappingURL=feed.js.map
\ No newline at end of file
diff --git a/menu-feed/typescript/src/feed.ts b/menu-feed/typescript/src/feed.ts
index 8e91388..91ad4f1 100644
--- a/menu-feed/typescript/src/feed.ts
+++ b/menu-feed/typescript/src/feed.ts
@@ -57,4 +57,13 @@
   data: [{menu}, {section}, {item}, {option}]
 };
 
+// Example testing for menu feed size
+// Protocol buffer message must be less than 2 GiB
+// https://protobuf.dev/programming-guides/proto-limits/
+// It is recommended to not exceed 200 MB, as there is an Actions
+// Center limit of 200 MB per file after compression.
+if (new Blob([JSON.stringify(feed)]).size > 200 * 1024 * 1024) {
+  // create a new file
+}
+
 console.log(JSON.stringify(feed));
diff --git a/order-redirect/README.md b/order-redirect/README.md
new file mode 100644
index 0000000..65d5b46
--- /dev/null
+++ b/order-redirect/README.md
@@ -0,0 +1,5 @@
+#Creating Google Ordering Redirect Feed Examples
+
+- Download the lastest version of protoc from https://github.com/protocolbuffers/protobuf/releases
+- Create a proto directory for source protos inside project directory. For Java use java/src/main/proto.
+- Download the protos from https://developers.google.com/actions-center/verticals/ordering/redirect/reference/feeds/feed-proto-bundle
diff --git a/order-redirect/go/action/action.go b/order-redirect/go/action/action.go
index 2680666..2873885 100644
--- a/order-redirect/go/action/action.go
+++ b/order-redirect/go/action/action.go
@@ -3,7 +3,7 @@
 Download lastest version of protoc from https://github.com/protocolbuffers/protobuf/releases.
 Generate proto classes with:
 	go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
-	protoc --proto_path=../proto/ --go_out=generated ../proto/action.proto
+	protoc --proto_path=proto/ --go_out=generated proto/action.proto
 
 See https://protobuf.dev/reference/go/go-generated/ for more details.
 **/
diff --git a/order-redirect/go/entity/entity.go b/order-redirect/go/entity/entity.go
index 4e20c79..6516c98 100644
--- a/order-redirect/go/entity/entity.go
+++ b/order-redirect/go/entity/entity.go
@@ -3,7 +3,7 @@
 Download lastest version of protoc from https://github.com/protocolbuffers/protobuf/releases.
 Generate proto classes with:
 	go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
-	protoc --proto_path=../proto/ --go_out=generated ../proto/entity.proto
+	protoc --proto_path=proto/ --go_out=generated proto/entity.proto
 
 See https://protobuf.dev/reference/go/go-generated/ for more details.
 **/
diff --git a/order-redirect/java/pom.xml b/order-redirect/java/pom.xml
index d159c16..20514c5 100644
--- a/order-redirect/java/pom.xml
+++ b/order-redirect/java/pom.xml
@@ -63,22 +63,22 @@
                     </execution>
                 </executions>
             </plugin>
-          <plugin>
-        <groupId>org.xolstice.maven.plugins</groupId>
-        <artifactId>protobuf-maven-plugin</artifactId>
-        <version>0.6.1</version>
-        <configuration>
-          <protocExecutable>protoc</protocExecutable>
-        </configuration>
-        <executions>
-          <execution>
-            <goals>
-              <goal>compile</goal>
-              <goal>test-compile</goal>
-            </goals>
-          </execution>
-        </executions>
-      </plugin>
-    </plugins>
+            <plugin>
+                <groupId>org.xolstice.maven.plugins</groupId>
+                <artifactId>protobuf-maven-plugin</artifactId>
+                <version>0.6.1</version>
+                <configuration>
+                    <protocExecutable>protoc</protocExecutable>
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>compile</goal>
+                            <goal>test-compile</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
     </build>
 </project>
diff --git a/order-redirect/java/src/main/proto/action.proto b/order-redirect/java/src/main/proto/action.proto
deleted file mode 100644
index 9a8d50e..0000000
--- a/order-redirect/java/src/main/proto/action.proto
+++ /dev/null
@@ -1,46 +0,0 @@
-
-// Feeds declaration
-syntax = "proto3";
-
-package madden.ingestion;
-
-option java_multiple_files = true;
-option java_package = "com.google.madden.ingestion";
-option go_package = "google/madden/ingestion";
-
-message ActionFeed {
-  repeated ActionDetail data = 1;
-}
-
-message ActionDetail {
-  // Reference to entity id
-  optional string entity_id = 2;
-  optional string link_id = 3;
-  // Deep link for action detail
-  optional string url = 4;
-  repeated Action actions = 1;
-}
-
-// Information about an Action which could be performed.
-message Action {
-  // Deprecated fields not to be reused.
-  reserved 1;
-  oneof action_info {
-    FoodOrderingInfo food_ordering_info = 3;
-  }
-}
-
-message AppointmentInfo {
-  // Deep link for appointment action.
-  string url = 1;
-}
-
-message FoodOrderingInfo {
-  // Service type for food ordering action.
-  enum ServiceType {
-    UNKNOWN = 0;
-    DELIVERY = 1;
-    TAKEOUT = 2;
-  }
-  ServiceType service_type = 1;
-}
diff --git a/order-redirect/java/src/main/proto/entity.proto b/order-redirect/java/src/main/proto/entity.proto
deleted file mode 100644
index 451c639..0000000
--- a/order-redirect/java/src/main/proto/entity.proto
+++ /dev/null
@@ -1,71 +0,0 @@
-// Feeds declaration
-syntax = "proto3";
-
-package madden.ingestion;
-
-option java_multiple_files = true;
-option java_package = "com.google.madden.ingestion";
-option go_package = "google/madden/ingestion";
-
-message EntityFeed {
-  repeated Entity data = 1;
-}
-
-//
-// Information about an Entity that is on the partner's platform. For example,
-// an Entity could be a retail store, a hospital, an online business etc.
-//
-message Entity {
-  // An opaque string generated by the partner that identifies an Entity.
-  // Must be unique across all entities.
-  // Strongly recommended to only include URL-safe characters. (required)
-  string entity_id = 1;
-
-  // If present, the name, telephone, url and location are used to support
-  // matching partner inventory with entities already present on Google. This
-  // information will not be displayed.
-
-  // The name of the Entity. (required)
-  string name = 2;
-
-  // The contact telephone number of the Entity including its country and area
-  // codes, e.g. +14567891234. Highly recommended. (optional)
-  string telephone = 3;
-
-  // The url of the Entity's public website. Highly recommended. (optional)
-  string url = 4;
-
-  // The location of the Entity (required)
-  madden.ingestion.GeoCoordinates location = 5;
-}
-
-// The Geo data of a location, including latitude, longitude, and address.
-// At least one of [lat/lng or address] should be provided (or both).
-message GeoCoordinates {
-  double latitude = 1;   // In degrees. (optional)
-  double longitude = 2;  // In degrees. (optional)
-
-  // Address for a location, could either be structured or unstructured.
-  oneof addresses {
-    // Postal address of the location, preferred.
-    PostalAddress address = 3;
-    // An unstructured address could also be provided as a fallback.
-    // E.g. "1600 amphitheatre parkway mountain view, ca 94043"
-    string unstructured_address = 4;
-  }
-}
-
-// The postal address for a merchant.
-message PostalAddress {
-  // The country, using ISO 3166-1 alpha-2 country code, e.g. "US" (required)
-  string country = 1;
-  // The locality/city, e.g. "Mountain View". (required)
-  string locality = 2;
-  // The region/state/province, e.g. "CA". This field is only required in
-  // countries where region is commonly a part of the address. (optional)
-  string region = 3;
-  // The postal code, e.g. "94043". (required)
-  string postal_code = 4;
-  // The street address, e.g. "1600 Amphitheatre Pkwy". (required)
-  string street_address = 5;
-}
\ No newline at end of file
diff --git a/order-redirect/java/src/main/proto/food-service.proto b/order-redirect/java/src/main/proto/food-service.proto
deleted file mode 100644
index e5151c9..0000000
--- a/order-redirect/java/src/main/proto/food-service.proto
+++ /dev/null
@@ -1,313 +0,0 @@
-
-// Feeds declaration
-syntax = "proto3";
-
-package food.ordering.service.v1;
-
-option go_package = "google/food/ordering/services/v1";
-option java_package = "com.google.food.ordering.services.v1";
-option java_multiple_files = true;
-
-import "google/protobuf/duration.proto";
-import "google/protobuf/timestamp.proto";
-import "google/type/timeofday.proto";
-import "google/type/latlng.proto";
-import "google/type/money.proto";
-import "google/type/dayofweek.proto";
-
-// Food Ordering Team's EPA Service Feeds Spec.
-message FoodServiceFeed {
-  // Service feed entity data.
-  repeated ServiceData data = 1;
-}
-
-// Service feed entity data.
-message ServiceData {
-  oneof type {
-    FoodOrderingService service = 1;
-    ServiceHours service_hours = 2;
-    ServiceArea service_area = 3;
-    Fee fee = 4;
-  }
-}
-
-message FoodOrderingService {
-  // Unique identifier of the provided service.
-  // Required.
-  string service_id = 1
-      ;
-  enum ServiceType {
-    SERVICE_TYPE_UNKNOWN = 0;
-    DELIVERY = 1;
-    TAKEOUT = 2;
-  }
-  // The type of the service.
-  // Required and cannot be SERVICE_TYPE_UNKNOWN.
-  ServiceType service_type = 2
-      ;
-  // The parent entity’s ID.
-  // Required.
-  string parent_entity_id = 3
-      ;
-  // Indicates if the entity is disabled.
-  // Optional.
-  optional bool disabled = 4;
-  // The lead time given in the service entity will apply to all
-  // the service hours unless an overridden property is set in the
-  // service hours entity.
-  // Required.
-  ETA lead_time = 5
-      ;
-
-  // Parent action detail's link ID.
-  // Required.
-  string action_link_id = 6
-      ;
-}
-
-// Lead time range [min, max). At least one of min or max needs to be provided.
-// In the case of only one field is given, the lead time is treated as a fixed
-// value instead of a range.
-message ETA {
-  // Indicates a range of ETA duration.
-  google.protobuf.Duration min_lead_time_duration = 1
-      ;
-  google.protobuf.Duration max_lead_time_duration = 2
-      ;
-}
-
-// A closed-open time range.
-message TimeOfDayRange {
-  // A Time indicating the beginning time of the day of the range (inclusive).
-  // Required. If not given, we assume 00:00:00.
-  google.type.TimeOfDay open_time = 1;
-  // A Time indicating the ending time of the day of the range (exclusive).
-  // Required. If not given, we assume 23:59:59.
-  google.type.TimeOfDay close_time = 2;
-}
-
-// A closed-open duration range.
-message DurationInterval {
-  // The minimum duration (inclusive).
-  // Required.
-  google.protobuf.Duration min_offset = 1
-      ;
-  // The maximum duration (exclusive).
-  // Required.
-  google.protobuf.Duration max_offset = 2
-      ;
-}
-
-// A closed-open timestamp range.
-message ValidityRange {
-  // The beginning time of the range (inclusive).
-  // Optional.
-  google.protobuf.Timestamp valid_from_time = 1
-      ;
-  // The ending time of the range (exclusive).
-  // Optional.
-  google.protobuf.Timestamp valid_through_time = 2
-      ;
-}
-
-// The TimeWindow object is a composite entity that describes a list
-// of windows the user's order can be either placed or fulfilled.
-message TimeOfDayWindow {
-  // The time window the order can be placed/fulfilled.
-  // Required.
-  TimeOfDayRange time_windows = 1
-      ;
-  // The list of days in a week the windows are applied.
-  // Required. If not given, we assume 7 days a week.
-  repeated google.type.DayOfWeek day_of_week = 2
-      ;
-}
-
-message AsapTimeWindow {
-  // A time window the ASAP order can be placed and fulfilled.
-  // Required.
-  TimeOfDayWindow time_windows = 1
-      ;
-
-  // Indicates the lead time, specific to service_time, the service can
-  // be fulfilled.
-  // Optional.
-  ETA lead_time = 2;
-}
-
-// The fulfillment time window for advance orders.
-message AdvanceTimeWindow {
-  // A time window the advance order can be fulfilled.
-  // Required.
-  TimeOfDayWindow time_windows = 1
-      ;
-  // a window that an advance order can be placed.  For example, an advance
-  // order must be placed at least 60 minutes ahead and not exceeding 2
-  // days, the interval would be [PT60M, P2D).
-  // Optional.
-  DurationInterval advance_booking_interval = 2;
-}
-
-// Service hours entity for ASAP/Advance orders.
-message ServiceHours {
-  // Unique identifier of the provided advance service hours.
-  // Required.
-  string hours_id = 1
-      ;
-
-  // The unique identifier of the Service entity correlated to this ServiceHours
-  // entity.
-  // Required.
-  repeated string service_ids = 2
-      ;
-  // The hours the orders can be fulfilled. For ASAP services, this is also
-  // orderable time.
-  // One of the fields (asap_hours/advance_hours) is required to be set.
-  repeated AsapTimeWindow asap_hours = 3
-      ;
-  repeated AdvanceTimeWindow advance_hours = 4;
-
-  // When advance ordering services, this is the time windows the orders can be
-  // placed.
-  // Required when advance_hour is given. Invalid when asap_hour is given.
-  repeated TimeOfDayWindow orderable_time = 5
-      ;
-
-  // Indicates if the service hours are for special occasions
-  // (e.g. Thanksgiving/...)
-  // Optional
-  optional bool special_hour = 6;
-  // A timestamp window indicating the validity of the special hours.
-  // Optional. Required if it's special hours.
-  ValidityRange validity_range = 7
-      ;
-}
-
-// Geographical circular area described by a point and radius.
-message GeoCircle {
-  // Geographical center of the area.
-  // Required.
-  google.type.LatLng center =
-      1
-      ;
-
-  // Radius for the circular area, in meters. Must be greater than 0.
-  // Required.
-  double radius = 2
-      ;
-}
-
-// Geolocation of interests.
-message Locality {
-  string country_code = 1
-      ;
-
-  // Postal code in the country's local format in string.
-  string postal_code =
-      2
-      ;
-}
-
-// Represents a loop of geo coordinates. This should be a valid S2Loop.
-message Loop {
-  // Points making the boundary of loop.
-  repeated google.type.LatLng point =
-      1
-      ;
-}
-
-// Represents a polygon shaped region.
-message Polygon {
-  reserved 1;
-
-  // List of S2Loops which defines a polygon. A point is considered in the
-  // polygon if it is contained in odd number of loops.
-  repeated Loop loops = 2
-      ;
-}
-
-message ServiceArea {
-  // Unique identifier.
-  // Required.
-  string area_id = 1
-      ;
-  // Identifier to the parent service entity.
-  // Required.
-  repeated string service_ids = 2
-      ;
-  // One of the following needs to be provided to define the service area.
-  // Required.
-  oneof region {
-
-    GeoCircle circle = 3;
-    Locality locality = 4;
-    Polygon polygon = 5;
-  }
-
-  // Sets to true if the assigned area is excluded from serving.
-  // Optional.
-  optional bool excluded_area = 6;
-}
-
-// Wrapper for a range of monetary amount that could be bounded or unbounded.
-// At least one of min_amount or max_amount is required.
-message MoneyRange {
-  // Minimum amount.
-  google.type.Money min_amount = 1
-      ;
-  // Maximum amount.
-  google.type.Money max_amount = 2
-      ;
-}
-
-// Variable fee which changes based on the price of the order.
-message PercentageBasedFee {
-  // Optional, base fee not including the variable percentage based fee.
-  google.type.Money base_value = 1
-      ;
-
-  // Optional, overall range of possible values of the PercentageBasedFee.
-  optional MoneyRange range = 2;
-
-  // Optional, percentage representing an additional variable fee based on
-  // the cart subtotal. E.g. 15.0 represents a fee of 15% of the cart.
-  optional double percentage_of_cart_value = 3
-      ;
-}
-
-message Fee {
-  // Unique identifier to the Fee entity.
-  // Required.
-  string fee_id = 1
-      ;
-  enum FeeType {
-    FEE_TYPE_UNKNOWN = 0;
-    DELIVERY = 1;
-    SERVICE = 2;
-  }
-  // Indicates the nature of the service, e.g. delivery fee/service fee.
-  // Required.
-  FeeType fee_type = 2
-      ;
-
-  oneof amount {
-
-    // A fixed amount of fees to be collected.
-    google.type.Money fixed_amount = 3;
-    // A range of fees that could be collected. Will mirror
-    // madden.ingestion.MoneyRange for the starting point.
-    MoneyRange range_amount = 4;
-    // Fees in terms of amount percentage. Will mirror
-    // madden.ingestion.QuantitativeValue for the starter.
-    PercentageBasedFee cart_percentage = 5;
-  }
-  // Service association needs to be provided.
-  // Required.
-  repeated string service_ids = 6
-      ;
-  // Service area can be provided to further restrict eligibility of the
-  // fee.
-  // Optional.
-  repeated string area_ids = 7
-      ;
-}
diff --git a/order-redirect/java/src/main/proto/google/protobuf/duration.proto b/order-redirect/java/src/main/proto/google/protobuf/duration.proto
deleted file mode 100644
index 41f40c2..0000000
--- a/order-redirect/java/src/main/proto/google/protobuf/duration.proto
+++ /dev/null
@@ -1,115 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-syntax = "proto3";
-
-package google.protobuf;
-
-option cc_enable_arenas = true;
-option go_package = "google.golang.org/protobuf/types/known/durationpb";
-option java_package = "com.google.protobuf";
-option java_outer_classname = "DurationProto";
-option java_multiple_files = true;
-option objc_class_prefix = "GPB";
-option csharp_namespace = "Google.Protobuf.WellKnownTypes";
-
-// A Duration represents a signed, fixed-length span of time represented
-// as a count of seconds and fractions of seconds at nanosecond
-// resolution. It is independent of any calendar and concepts like "day"
-// or "month". It is related to Timestamp in that the difference between
-// two Timestamp values is a Duration and it can be added or subtracted
-// from a Timestamp. Range is approximately +-10,000 years.
-//
-// # Examples
-//
-// Example 1: Compute Duration from two Timestamps in pseudo code.
-//
-//     Timestamp start = ...;
-//     Timestamp end = ...;
-//     Duration duration = ...;
-//
-//     duration.seconds = end.seconds - start.seconds;
-//     duration.nanos = end.nanos - start.nanos;
-//
-//     if (duration.seconds < 0 && duration.nanos > 0) {
-//       duration.seconds += 1;
-//       duration.nanos -= 1000000000;
-//     } else if (duration.seconds > 0 && duration.nanos < 0) {
-//       duration.seconds -= 1;
-//       duration.nanos += 1000000000;
-//     }
-//
-// Example 2: Compute Timestamp from Timestamp + Duration in pseudo code.
-//
-//     Timestamp start = ...;
-//     Duration duration = ...;
-//     Timestamp end = ...;
-//
-//     end.seconds = start.seconds + duration.seconds;
-//     end.nanos = start.nanos + duration.nanos;
-//
-//     if (end.nanos < 0) {
-//       end.seconds -= 1;
-//       end.nanos += 1000000000;
-//     } else if (end.nanos >= 1000000000) {
-//       end.seconds += 1;
-//       end.nanos -= 1000000000;
-//     }
-//
-// Example 3: Compute Duration from datetime.timedelta in Python.
-//
-//     td = datetime.timedelta(days=3, minutes=10)
-//     duration = Duration()
-//     duration.FromTimedelta(td)
-//
-// # JSON Mapping
-//
-// In JSON format, the Duration type is encoded as a string rather than an
-// object, where the string ends in the suffix "s" (indicating seconds) and
-// is preceded by the number of seconds, with nanoseconds expressed as
-// fractional seconds. For example, 3 seconds with 0 nanoseconds should be
-// encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should
-// be expressed in JSON format as "3.000000001s", and 3 seconds and 1
-// microsecond should be expressed in JSON format as "3.000001s".
-//
-message Duration {
-  // Signed seconds of the span of time. Must be from -315,576,000,000
-  // to +315,576,000,000 inclusive. Note: these bounds are computed from:
-  // 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years
-  int64 seconds = 1;
-
-  // Signed fractions of a second at nanosecond resolution of the span
-  // of time. Durations less than one second are represented with a 0
-  // `seconds` field and a positive or negative `nanos` field. For durations
-  // of one second or more, a non-zero value for the `nanos` field must be
-  // of the same sign as the `seconds` field. Must be from -999,999,999
-  // to +999,999,999 inclusive.
-  int32 nanos = 2;
-}
diff --git a/order-redirect/java/src/main/proto/google/protobuf/timestamp.proto b/order-redirect/java/src/main/proto/google/protobuf/timestamp.proto
deleted file mode 100644
index fd0bc07..0000000
--- a/order-redirect/java/src/main/proto/google/protobuf/timestamp.proto
+++ /dev/null
@@ -1,144 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-syntax = "proto3";
-
-package google.protobuf;
-
-option cc_enable_arenas = true;
-option go_package = "google.golang.org/protobuf/types/known/timestamppb";
-option java_package = "com.google.protobuf";
-option java_outer_classname = "TimestampProto";
-option java_multiple_files = true;
-option objc_class_prefix = "GPB";
-option csharp_namespace = "Google.Protobuf.WellKnownTypes";
-
-// A Timestamp represents a point in time independent of any time zone or local
-// calendar, encoded as a count of seconds and fractions of seconds at
-// nanosecond resolution. The count is relative to an epoch at UTC midnight on
-// January 1, 1970, in the proleptic Gregorian calendar which extends the
-// Gregorian calendar backwards to year one.
-//
-// All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap
-// second table is needed for interpretation, using a [24-hour linear
-// smear](https://developers.google.com/time/smear).
-//
-// The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By
-// restricting to that range, we ensure that we can convert to and from [RFC
-// 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings.
-//
-// # Examples
-//
-// Example 1: Compute Timestamp from POSIX `time()`.
-//
-//     Timestamp timestamp;
-//     timestamp.set_seconds(time(NULL));
-//     timestamp.set_nanos(0);
-//
-// Example 2: Compute Timestamp from POSIX `gettimeofday()`.
-//
-//     struct timeval tv;
-//     gettimeofday(&tv, NULL);
-//
-//     Timestamp timestamp;
-//     timestamp.set_seconds(tv.tv_sec);
-//     timestamp.set_nanos(tv.tv_usec * 1000);
-//
-// Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`.
-//
-//     FILETIME ft;
-//     GetSystemTimeAsFileTime(&ft);
-//     UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
-//
-//     // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z
-//     // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z.
-//     Timestamp timestamp;
-//     timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));
-//     timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));
-//
-// Example 4: Compute Timestamp from Java `System.currentTimeMillis()`.
-//
-//     long millis = System.currentTimeMillis();
-//
-//     Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
-//         .setNanos((int) ((millis % 1000) * 1000000)).build();
-//
-// Example 5: Compute Timestamp from Java `Instant.now()`.
-//
-//     Instant now = Instant.now();
-//
-//     Timestamp timestamp =
-//         Timestamp.newBuilder().setSeconds(now.getEpochSecond())
-//             .setNanos(now.getNano()).build();
-//
-// Example 6: Compute Timestamp from current time in Python.
-//
-//     timestamp = Timestamp()
-//     timestamp.GetCurrentTime()
-//
-// # JSON Mapping
-//
-// In JSON format, the Timestamp type is encoded as a string in the
-// [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the
-// format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z"
-// where {year} is always expressed using four digits while {month}, {day},
-// {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional
-// seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution),
-// are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone
-// is required. A proto3 JSON serializer should always use UTC (as indicated by
-// "Z") when printing the Timestamp type and a proto3 JSON parser should be
-// able to accept both UTC and other timezones (as indicated by an offset).
-//
-// For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past
-// 01:30 UTC on January 15, 2017.
-//
-// In JavaScript, one can convert a Date object to this format using the
-// standard
-// [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString)
-// method. In Python, a standard `datetime.datetime` object can be converted
-// to this format using
-// [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with
-// the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use
-// the Joda Time's [`ISODateTimeFormat.dateTime()`](
-// http://joda-time.sourceforge.net/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime()
-// ) to obtain a formatter capable of generating timestamps in this format.
-//
-message Timestamp {
-  // Represents seconds of UTC time since Unix epoch
-  // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
-  // 9999-12-31T23:59:59Z inclusive.
-  int64 seconds = 1;
-
-  // Non-negative fractions of a second at nanosecond resolution. Negative
-  // second values with fractions must still have non-negative nanos values
-  // that count forward in time. Must be from 0 to 999,999,999
-  // inclusive.
-  int32 nanos = 2;
-}
diff --git a/order-redirect/java/src/main/proto/google/type/dayofweek.proto b/order-redirect/java/src/main/proto/google/type/dayofweek.proto
deleted file mode 100644
index 4c80c62..0000000
--- a/order-redirect/java/src/main/proto/google/type/dayofweek.proto
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2021 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-syntax = "proto3";
-
-package google.type;
-
-option go_package = "google.golang.org/genproto/googleapis/type/dayofweek;dayofweek";
-option java_multiple_files = true;
-option java_outer_classname = "DayOfWeekProto";
-option java_package = "com.google.type";
-option objc_class_prefix = "GTP";
-
-// Represents a day of the week.
-enum DayOfWeek {
-  // The day of the week is unspecified.
-  DAY_OF_WEEK_UNSPECIFIED = 0;
-
-  // Monday
-  MONDAY = 1;
-
-  // Tuesday
-  TUESDAY = 2;
-
-  // Wednesday
-  WEDNESDAY = 3;
-
-  // Thursday
-  THURSDAY = 4;
-
-  // Friday
-  FRIDAY = 5;
-
-  // Saturday
-  SATURDAY = 6;
-
-  // Sunday
-  SUNDAY = 7;
-}
diff --git a/order-redirect/java/src/main/proto/google/type/latlng.proto b/order-redirect/java/src/main/proto/google/type/latlng.proto
deleted file mode 100644
index 9231456..0000000
--- a/order-redirect/java/src/main/proto/google/type/latlng.proto
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2021 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-syntax = "proto3";
-
-package google.type;
-
-option cc_enable_arenas = true;
-option go_package = "google.golang.org/genproto/googleapis/type/latlng;latlng";
-option java_multiple_files = true;
-option java_outer_classname = "LatLngProto";
-option java_package = "com.google.type";
-option objc_class_prefix = "GTP";
-
-// An object that represents a latitude/longitude pair. This is expressed as a
-// pair of doubles to represent degrees latitude and degrees longitude. Unless
-// specified otherwise, this must conform to the
-// <a href="http://www.unoosa.org/pdf/icg/2012/template/WGS_84.pdf">WGS84
-// standard</a>. Values must be within normalized ranges.
-message LatLng {
-  // The latitude in degrees. It must be in the range [-90.0, +90.0].
-  double latitude = 1;
-
-  // The longitude in degrees. It must be in the range [-180.0, +180.0].
-  double longitude = 2;
-}
diff --git a/order-redirect/java/src/main/proto/google/type/money.proto b/order-redirect/java/src/main/proto/google/type/money.proto
deleted file mode 100644
index 98d6494..0000000
--- a/order-redirect/java/src/main/proto/google/type/money.proto
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2021 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-syntax = "proto3";
-
-package google.type;
-
-option cc_enable_arenas = true;
-option go_package = "google.golang.org/genproto/googleapis/type/money;money";
-option java_multiple_files = true;
-option java_outer_classname = "MoneyProto";
-option java_package = "com.google.type";
-option objc_class_prefix = "GTP";
-
-// Represents an amount of money with its currency type.
-message Money {
-  // The three-letter currency code defined in ISO 4217.
-  string currency_code = 1;
-
-  // The whole units of the amount.
-  // For example if `currencyCode` is `"USD"`, then 1 unit is one US dollar.
-  int64 units = 2;
-
-  // Number of nano (10^-9) units of the amount.
-  // The value must be between -999,999,999 and +999,999,999 inclusive.
-  // If `units` is positive, `nanos` must be positive or zero.
-  // If `units` is zero, `nanos` can be positive, zero, or negative.
-  // If `units` is negative, `nanos` must be negative or zero.
-  // For example $-1.75 is represented as `units`=-1 and `nanos`=-750,000,000.
-  int32 nanos = 3;
-}
diff --git a/order-redirect/java/src/main/proto/google/type/timeofday.proto b/order-redirect/java/src/main/proto/google/type/timeofday.proto
deleted file mode 100644
index 5cb48aa..0000000
--- a/order-redirect/java/src/main/proto/google/type/timeofday.proto
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2021 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-syntax = "proto3";
-
-package google.type;
-
-option cc_enable_arenas = true;
-option go_package = "google.golang.org/genproto/googleapis/type/timeofday;timeofday";
-option java_multiple_files = true;
-option java_outer_classname = "TimeOfDayProto";
-option java_package = "com.google.type";
-option objc_class_prefix = "GTP";
-
-// Represents a time of day. The date and time zone are either not significant
-// or are specified elsewhere. An API may choose to allow leap seconds. Related
-// types are [google.type.Date][google.type.Date] and
-// `google.protobuf.Timestamp`.
-message TimeOfDay {
-  // Hours of day in 24 hour format. Should be from 0 to 23. An API may choose
-  // to allow the value "24:00:00" for scenarios like business closing time.
-  int32 hours = 1;
-
-  // Minutes of hour of day. Must be from 0 to 59.
-  int32 minutes = 2;
-
-  // Seconds of minutes of the time. Must normally be from 0 to 59. An API may
-  // allow the value 60 if it allows leap-seconds.
-  int32 seconds = 3;
-
-  // Fractions of seconds in nanoseconds. Must be from 0 to 999,999,999.
-  int32 nanos = 4;
-}
diff --git a/order-redirect/php/ActionFeedExample.php b/order-redirect/php/ActionFeedExample.php
index 09ebf61..5ebb5b1 100644
--- a/order-redirect/php/ActionFeedExample.php
+++ b/order-redirect/php/ActionFeedExample.php
@@ -3,7 +3,7 @@
 Example Action feed for Google Order Redirect. Create build/gen directory for generated proto classes.
 Download lastest version of protoc from https://github.com/protocolbuffers/protobuf/releases.
 Generate proto classes with:
-    protoc --php_out=./build/gen --proto_path=../proto/ ../proto/action.proto
+    protoc --php_out=./build/gen --proto_path=proto/ proto/action.proto
 
 See https://protobuf.dev/reference/php/php-generated/ for more details.
 */
diff --git a/order-redirect/php/EntityFeedExample.php b/order-redirect/php/EntityFeedExample.php
index 905c81d..70556ba 100644
--- a/order-redirect/php/EntityFeedExample.php
+++ b/order-redirect/php/EntityFeedExample.php
@@ -3,7 +3,7 @@
 Example Entity feed for Google Order Redirect. Create build/gen directory for generated proto classes.
 Download lastest version of protoc from https://github.com/protocolbuffers/protobuf/releases
 Generate proto classes with:
-    protoc --php_out=./build/gen --proto_path=../proto/ ../proto/entity.proto
+    protoc --php_out=./build/gen --proto_path=proto/ proto/entity.proto
 
 See https://protobuf.dev/reference/php/php-generated/ for more details.
 */
diff --git a/order-redirect/proto/action.proto b/order-redirect/proto/action.proto
deleted file mode 100644
index b26cee7..0000000
--- a/order-redirect/proto/action.proto
+++ /dev/null
@@ -1,47 +0,0 @@
-
-// Feeds declaration
-syntax = "proto3";
-
-package madden.ingestion;
-
-option java_multiple_files = true;
-option java_package = "com.google.madden.ingestion";
-option go_package = "google/madden/ingestion";
-
-message ActionFeed {
-  repeated ActionDetail data = 1;
-}
-
-message ActionDetail {
-  // Reference to entity id
-  optional string entity_id = 2;
-  optional string link_id = 3;
-  // Deep link for action detail
-  optional string url = 4;
-  repeated Action actions = 1;
-}
-
-// Information about an Action which could be performed.
-message Action {
-  // Deprecated fields not to be reused.
-  reserved 1;
-  oneof action_info {
-    AppointmentInfo appointment_info = 2;
-    FoodOrderingInfo food_ordering_info = 3;
-  }
-}
-
-message AppointmentInfo {
-  // Deep link for appointment action.
-  string url = 1;
-}
-
-message FoodOrderingInfo {
-  // Service type for food ordering action.
-  enum ServiceType {
-    UNKNOWN = 0;
-    DELIVERY = 1;
-    TAKEOUT = 2;
-  }
-  ServiceType service_type = 1;
-}
diff --git a/order-redirect/proto/entity.proto b/order-redirect/proto/entity.proto
deleted file mode 100644
index 451c639..0000000
--- a/order-redirect/proto/entity.proto
+++ /dev/null
@@ -1,71 +0,0 @@
-// Feeds declaration
-syntax = "proto3";
-
-package madden.ingestion;
-
-option java_multiple_files = true;
-option java_package = "com.google.madden.ingestion";
-option go_package = "google/madden/ingestion";
-
-message EntityFeed {
-  repeated Entity data = 1;
-}
-
-//
-// Information about an Entity that is on the partner's platform. For example,
-// an Entity could be a retail store, a hospital, an online business etc.
-//
-message Entity {
-  // An opaque string generated by the partner that identifies an Entity.
-  // Must be unique across all entities.
-  // Strongly recommended to only include URL-safe characters. (required)
-  string entity_id = 1;
-
-  // If present, the name, telephone, url and location are used to support
-  // matching partner inventory with entities already present on Google. This
-  // information will not be displayed.
-
-  // The name of the Entity. (required)
-  string name = 2;
-
-  // The contact telephone number of the Entity including its country and area
-  // codes, e.g. +14567891234. Highly recommended. (optional)
-  string telephone = 3;
-
-  // The url of the Entity's public website. Highly recommended. (optional)
-  string url = 4;
-
-  // The location of the Entity (required)
-  madden.ingestion.GeoCoordinates location = 5;
-}
-
-// The Geo data of a location, including latitude, longitude, and address.
-// At least one of [lat/lng or address] should be provided (or both).
-message GeoCoordinates {
-  double latitude = 1;   // In degrees. (optional)
-  double longitude = 2;  // In degrees. (optional)
-
-  // Address for a location, could either be structured or unstructured.
-  oneof addresses {
-    // Postal address of the location, preferred.
-    PostalAddress address = 3;
-    // An unstructured address could also be provided as a fallback.
-    // E.g. "1600 amphitheatre parkway mountain view, ca 94043"
-    string unstructured_address = 4;
-  }
-}
-
-// The postal address for a merchant.
-message PostalAddress {
-  // The country, using ISO 3166-1 alpha-2 country code, e.g. "US" (required)
-  string country = 1;
-  // The locality/city, e.g. "Mountain View". (required)
-  string locality = 2;
-  // The region/state/province, e.g. "CA". This field is only required in
-  // countries where region is commonly a part of the address. (optional)
-  string region = 3;
-  // The postal code, e.g. "94043". (required)
-  string postal_code = 4;
-  // The street address, e.g. "1600 Amphitheatre Pkwy". (required)
-  string street_address = 5;
-}
\ No newline at end of file
diff --git a/order-redirect/proto/food-service.proto b/order-redirect/proto/food-service.proto
deleted file mode 100644
index e5151c9..0000000
--- a/order-redirect/proto/food-service.proto
+++ /dev/null
@@ -1,313 +0,0 @@
-
-// Feeds declaration
-syntax = "proto3";
-
-package food.ordering.service.v1;
-
-option go_package = "google/food/ordering/services/v1";
-option java_package = "com.google.food.ordering.services.v1";
-option java_multiple_files = true;
-
-import "google/protobuf/duration.proto";
-import "google/protobuf/timestamp.proto";
-import "google/type/timeofday.proto";
-import "google/type/latlng.proto";
-import "google/type/money.proto";
-import "google/type/dayofweek.proto";
-
-// Food Ordering Team's EPA Service Feeds Spec.
-message FoodServiceFeed {
-  // Service feed entity data.
-  repeated ServiceData data = 1;
-}
-
-// Service feed entity data.
-message ServiceData {
-  oneof type {
-    FoodOrderingService service = 1;
-    ServiceHours service_hours = 2;
-    ServiceArea service_area = 3;
-    Fee fee = 4;
-  }
-}
-
-message FoodOrderingService {
-  // Unique identifier of the provided service.
-  // Required.
-  string service_id = 1
-      ;
-  enum ServiceType {
-    SERVICE_TYPE_UNKNOWN = 0;
-    DELIVERY = 1;
-    TAKEOUT = 2;
-  }
-  // The type of the service.
-  // Required and cannot be SERVICE_TYPE_UNKNOWN.
-  ServiceType service_type = 2
-      ;
-  // The parent entity’s ID.
-  // Required.
-  string parent_entity_id = 3
-      ;
-  // Indicates if the entity is disabled.
-  // Optional.
-  optional bool disabled = 4;
-  // The lead time given in the service entity will apply to all
-  // the service hours unless an overridden property is set in the
-  // service hours entity.
-  // Required.
-  ETA lead_time = 5
-      ;
-
-  // Parent action detail's link ID.
-  // Required.
-  string action_link_id = 6
-      ;
-}
-
-// Lead time range [min, max). At least one of min or max needs to be provided.
-// In the case of only one field is given, the lead time is treated as a fixed
-// value instead of a range.
-message ETA {
-  // Indicates a range of ETA duration.
-  google.protobuf.Duration min_lead_time_duration = 1
-      ;
-  google.protobuf.Duration max_lead_time_duration = 2
-      ;
-}
-
-// A closed-open time range.
-message TimeOfDayRange {
-  // A Time indicating the beginning time of the day of the range (inclusive).
-  // Required. If not given, we assume 00:00:00.
-  google.type.TimeOfDay open_time = 1;
-  // A Time indicating the ending time of the day of the range (exclusive).
-  // Required. If not given, we assume 23:59:59.
-  google.type.TimeOfDay close_time = 2;
-}
-
-// A closed-open duration range.
-message DurationInterval {
-  // The minimum duration (inclusive).
-  // Required.
-  google.protobuf.Duration min_offset = 1
-      ;
-  // The maximum duration (exclusive).
-  // Required.
-  google.protobuf.Duration max_offset = 2
-      ;
-}
-
-// A closed-open timestamp range.
-message ValidityRange {
-  // The beginning time of the range (inclusive).
-  // Optional.
-  google.protobuf.Timestamp valid_from_time = 1
-      ;
-  // The ending time of the range (exclusive).
-  // Optional.
-  google.protobuf.Timestamp valid_through_time = 2
-      ;
-}
-
-// The TimeWindow object is a composite entity that describes a list
-// of windows the user's order can be either placed or fulfilled.
-message TimeOfDayWindow {
-  // The time window the order can be placed/fulfilled.
-  // Required.
-  TimeOfDayRange time_windows = 1
-      ;
-  // The list of days in a week the windows are applied.
-  // Required. If not given, we assume 7 days a week.
-  repeated google.type.DayOfWeek day_of_week = 2
-      ;
-}
-
-message AsapTimeWindow {
-  // A time window the ASAP order can be placed and fulfilled.
-  // Required.
-  TimeOfDayWindow time_windows = 1
-      ;
-
-  // Indicates the lead time, specific to service_time, the service can
-  // be fulfilled.
-  // Optional.
-  ETA lead_time = 2;
-}
-
-// The fulfillment time window for advance orders.
-message AdvanceTimeWindow {
-  // A time window the advance order can be fulfilled.
-  // Required.
-  TimeOfDayWindow time_windows = 1
-      ;
-  // a window that an advance order can be placed.  For example, an advance
-  // order must be placed at least 60 minutes ahead and not exceeding 2
-  // days, the interval would be [PT60M, P2D).
-  // Optional.
-  DurationInterval advance_booking_interval = 2;
-}
-
-// Service hours entity for ASAP/Advance orders.
-message ServiceHours {
-  // Unique identifier of the provided advance service hours.
-  // Required.
-  string hours_id = 1
-      ;
-
-  // The unique identifier of the Service entity correlated to this ServiceHours
-  // entity.
-  // Required.
-  repeated string service_ids = 2
-      ;
-  // The hours the orders can be fulfilled. For ASAP services, this is also
-  // orderable time.
-  // One of the fields (asap_hours/advance_hours) is required to be set.
-  repeated AsapTimeWindow asap_hours = 3
-      ;
-  repeated AdvanceTimeWindow advance_hours = 4;
-
-  // When advance ordering services, this is the time windows the orders can be
-  // placed.
-  // Required when advance_hour is given. Invalid when asap_hour is given.
-  repeated TimeOfDayWindow orderable_time = 5
-      ;
-
-  // Indicates if the service hours are for special occasions
-  // (e.g. Thanksgiving/...)
-  // Optional
-  optional bool special_hour = 6;
-  // A timestamp window indicating the validity of the special hours.
-  // Optional. Required if it's special hours.
-  ValidityRange validity_range = 7
-      ;
-}
-
-// Geographical circular area described by a point and radius.
-message GeoCircle {
-  // Geographical center of the area.
-  // Required.
-  google.type.LatLng center =
-      1
-      ;
-
-  // Radius for the circular area, in meters. Must be greater than 0.
-  // Required.
-  double radius = 2
-      ;
-}
-
-// Geolocation of interests.
-message Locality {
-  string country_code = 1
-      ;
-
-  // Postal code in the country's local format in string.
-  string postal_code =
-      2
-      ;
-}
-
-// Represents a loop of geo coordinates. This should be a valid S2Loop.
-message Loop {
-  // Points making the boundary of loop.
-  repeated google.type.LatLng point =
-      1
-      ;
-}
-
-// Represents a polygon shaped region.
-message Polygon {
-  reserved 1;
-
-  // List of S2Loops which defines a polygon. A point is considered in the
-  // polygon if it is contained in odd number of loops.
-  repeated Loop loops = 2
-      ;
-}
-
-message ServiceArea {
-  // Unique identifier.
-  // Required.
-  string area_id = 1
-      ;
-  // Identifier to the parent service entity.
-  // Required.
-  repeated string service_ids = 2
-      ;
-  // One of the following needs to be provided to define the service area.
-  // Required.
-  oneof region {
-
-    GeoCircle circle = 3;
-    Locality locality = 4;
-    Polygon polygon = 5;
-  }
-
-  // Sets to true if the assigned area is excluded from serving.
-  // Optional.
-  optional bool excluded_area = 6;
-}
-
-// Wrapper for a range of monetary amount that could be bounded or unbounded.
-// At least one of min_amount or max_amount is required.
-message MoneyRange {
-  // Minimum amount.
-  google.type.Money min_amount = 1
-      ;
-  // Maximum amount.
-  google.type.Money max_amount = 2
-      ;
-}
-
-// Variable fee which changes based on the price of the order.
-message PercentageBasedFee {
-  // Optional, base fee not including the variable percentage based fee.
-  google.type.Money base_value = 1
-      ;
-
-  // Optional, overall range of possible values of the PercentageBasedFee.
-  optional MoneyRange range = 2;
-
-  // Optional, percentage representing an additional variable fee based on
-  // the cart subtotal. E.g. 15.0 represents a fee of 15% of the cart.
-  optional double percentage_of_cart_value = 3
-      ;
-}
-
-message Fee {
-  // Unique identifier to the Fee entity.
-  // Required.
-  string fee_id = 1
-      ;
-  enum FeeType {
-    FEE_TYPE_UNKNOWN = 0;
-    DELIVERY = 1;
-    SERVICE = 2;
-  }
-  // Indicates the nature of the service, e.g. delivery fee/service fee.
-  // Required.
-  FeeType fee_type = 2
-      ;
-
-  oneof amount {
-
-    // A fixed amount of fees to be collected.
-    google.type.Money fixed_amount = 3;
-    // A range of fees that could be collected. Will mirror
-    // madden.ingestion.MoneyRange for the starting point.
-    MoneyRange range_amount = 4;
-    // Fees in terms of amount percentage. Will mirror
-    // madden.ingestion.QuantitativeValue for the starter.
-    PercentageBasedFee cart_percentage = 5;
-  }
-  // Service association needs to be provided.
-  // Required.
-  repeated string service_ids = 6
-      ;
-  // Service area can be provided to further restrict eligibility of the
-  // fee.
-  // Optional.
-  repeated string area_ids = 7
-      ;
-}
diff --git a/order-redirect/proto/google/type/dayofweek.proto b/order-redirect/proto/google/type/dayofweek.proto
deleted file mode 100644
index 4c80c62..0000000
--- a/order-redirect/proto/google/type/dayofweek.proto
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2021 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-syntax = "proto3";
-
-package google.type;
-
-option go_package = "google.golang.org/genproto/googleapis/type/dayofweek;dayofweek";
-option java_multiple_files = true;
-option java_outer_classname = "DayOfWeekProto";
-option java_package = "com.google.type";
-option objc_class_prefix = "GTP";
-
-// Represents a day of the week.
-enum DayOfWeek {
-  // The day of the week is unspecified.
-  DAY_OF_WEEK_UNSPECIFIED = 0;
-
-  // Monday
-  MONDAY = 1;
-
-  // Tuesday
-  TUESDAY = 2;
-
-  // Wednesday
-  WEDNESDAY = 3;
-
-  // Thursday
-  THURSDAY = 4;
-
-  // Friday
-  FRIDAY = 5;
-
-  // Saturday
-  SATURDAY = 6;
-
-  // Sunday
-  SUNDAY = 7;
-}
diff --git a/order-redirect/proto/google/type/latlng.proto b/order-redirect/proto/google/type/latlng.proto
deleted file mode 100644
index 9231456..0000000
--- a/order-redirect/proto/google/type/latlng.proto
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2021 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-syntax = "proto3";
-
-package google.type;
-
-option cc_enable_arenas = true;
-option go_package = "google.golang.org/genproto/googleapis/type/latlng;latlng";
-option java_multiple_files = true;
-option java_outer_classname = "LatLngProto";
-option java_package = "com.google.type";
-option objc_class_prefix = "GTP";
-
-// An object that represents a latitude/longitude pair. This is expressed as a
-// pair of doubles to represent degrees latitude and degrees longitude. Unless
-// specified otherwise, this must conform to the
-// <a href="http://www.unoosa.org/pdf/icg/2012/template/WGS_84.pdf">WGS84
-// standard</a>. Values must be within normalized ranges.
-message LatLng {
-  // The latitude in degrees. It must be in the range [-90.0, +90.0].
-  double latitude = 1;
-
-  // The longitude in degrees. It must be in the range [-180.0, +180.0].
-  double longitude = 2;
-}
diff --git a/order-redirect/proto/google/type/money.proto b/order-redirect/proto/google/type/money.proto
deleted file mode 100644
index 98d6494..0000000
--- a/order-redirect/proto/google/type/money.proto
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2021 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-syntax = "proto3";
-
-package google.type;
-
-option cc_enable_arenas = true;
-option go_package = "google.golang.org/genproto/googleapis/type/money;money";
-option java_multiple_files = true;
-option java_outer_classname = "MoneyProto";
-option java_package = "com.google.type";
-option objc_class_prefix = "GTP";
-
-// Represents an amount of money with its currency type.
-message Money {
-  // The three-letter currency code defined in ISO 4217.
-  string currency_code = 1;
-
-  // The whole units of the amount.
-  // For example if `currencyCode` is `"USD"`, then 1 unit is one US dollar.
-  int64 units = 2;
-
-  // Number of nano (10^-9) units of the amount.
-  // The value must be between -999,999,999 and +999,999,999 inclusive.
-  // If `units` is positive, `nanos` must be positive or zero.
-  // If `units` is zero, `nanos` can be positive, zero, or negative.
-  // If `units` is negative, `nanos` must be negative or zero.
-  // For example $-1.75 is represented as `units`=-1 and `nanos`=-750,000,000.
-  int32 nanos = 3;
-}
diff --git a/order-redirect/proto/google/type/timeofday.proto b/order-redirect/proto/google/type/timeofday.proto
deleted file mode 100644
index 5cb48aa..0000000
--- a/order-redirect/proto/google/type/timeofday.proto
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2021 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-syntax = "proto3";
-
-package google.type;
-
-option cc_enable_arenas = true;
-option go_package = "google.golang.org/genproto/googleapis/type/timeofday;timeofday";
-option java_multiple_files = true;
-option java_outer_classname = "TimeOfDayProto";
-option java_package = "com.google.type";
-option objc_class_prefix = "GTP";
-
-// Represents a time of day. The date and time zone are either not significant
-// or are specified elsewhere. An API may choose to allow leap seconds. Related
-// types are [google.type.Date][google.type.Date] and
-// `google.protobuf.Timestamp`.
-message TimeOfDay {
-  // Hours of day in 24 hour format. Should be from 0 to 23. An API may choose
-  // to allow the value "24:00:00" for scenarios like business closing time.
-  int32 hours = 1;
-
-  // Minutes of hour of day. Must be from 0 to 59.
-  int32 minutes = 2;
-
-  // Seconds of minutes of the time. Must normally be from 0 to 59. An API may
-  // allow the value 60 if it allows leap-seconds.
-  int32 seconds = 3;
-
-  // Fractions of seconds in nanoseconds. Must be from 0 to 999,999,999.
-  int32 nanos = 4;
-}
diff --git a/order-redirect/python/action_feed_example.py b/order-redirect/python/action_feed_example.py
index b57ea8e..76f90cd 100644
--- a/order-redirect/python/action_feed_example.py
+++ b/order-redirect/python/action_feed_example.py
@@ -2,7 +2,7 @@
 Example Action feed for Google Order Redirect. Create "generated" directory for generated proto classes.
 Download lastest version of protoc from https://github.com/protocolbuffers/protobuf/releases
 Generate proto classes with:
-    protoc --python_out=./generated --proto_path=../proto/ ../proto/action.proto
+    protoc --python_out=./generated --proto_path=proto/ proto/action.proto
 
 See https://protobuf.dev/reference/python/python-generated/ for more details.
 '''
diff --git a/order-redirect/python/entity_feed_example.py b/order-redirect/python/entity_feed_example.py
index 53fc107..6b81761 100644
--- a/order-redirect/python/entity_feed_example.py
+++ b/order-redirect/python/entity_feed_example.py
@@ -2,7 +2,7 @@
 Example Action feed for Google Order Redirect.Create "generated" directory for generated proto classes.
 Download lastest version of protoc from https://github.com/protocolbuffers/protobuf/releases
 Generate proto classes with:
-    protoc --python_out=./generated --proto_path=../proto/ ../proto/entity.proto
+    protoc --python_out=./generated --proto_path=proto/ proto/entity.proto
 
 See https://protobuf.dev/reference/python/python-generated/ for more details.
 '''
diff --git a/order-redirect/python/service_feed_example.py b/order-redirect/python/service_feed_example.py
index 26817ef..9903d46 100644
--- a/order-redirect/python/service_feed_example.py
+++ b/order-redirect/python/service_feed_example.py
@@ -3,7 +3,7 @@
 Download lastest version of protoc from https://github.com/protocolbuffers/protobuf/releases
 Generate proto classes with:
     mkdir generated
-    protoc --python_out=./generated --proto_path=../proto/ ../proto/*.proto ../proto/google/type/*.proto
+    protoc --python_out=./generated --proto_path=proto/ proto/*.proto proto/google/type/*.proto
 
 See https://protobuf.dev/reference/python/python-generated/ for more details.
 '''
diff --git a/order-redirect/typescript/src/action_feed_example.ts b/order-redirect/typescript/src/action_feed_example.ts
index b738ba7..7f9835a 100644
--- a/order-redirect/typescript/src/action_feed_example.ts
+++ b/order-redirect/typescript/src/action_feed_example.ts
@@ -3,7 +3,7 @@
 Download lastest version of protoc from https://github.com/protocolbuffers/protobuf/releases.
 Generate proto classes with:
     npm i ts-proto
-    protoc --plugin="./node_modules/.bin/protoc-gen-ts_proto" --ts_proto_opt=useOptionals=all --ts_proto_opt=snakeToCamel=false --ts_proto_opt=onlyTypes=true --ts_proto_out="./src/generated" ../proto/action.proto
+    protoc --plugin="./node_modules/.bin/protoc-gen-ts_proto" --ts_proto_opt=useOptionals=all --ts_proto_opt=snakeToCamel=false --ts_proto_opt=onlyTypes=true --ts_proto_out="./src/generated" proto/action.proto
 */
 
 import {
diff --git a/order-redirect/typescript/src/entity_feed_example.ts b/order-redirect/typescript/src/entity_feed_example.ts
index 94146e9..ba113e1 100644
--- a/order-redirect/typescript/src/entity_feed_example.ts
+++ b/order-redirect/typescript/src/entity_feed_example.ts
@@ -3,7 +3,7 @@
 Download lastest version of protoc from https://github.com/protocolbuffers/protobuf/releases.
 Generate proto classes with:
     npm i ts-proto
-    protoc --plugin="./node_modules/.bin/protoc-gen-ts_proto" --ts_proto_opt=useOptionals=all --ts_proto_opt=snakeToCamel=false --ts_proto_opt=onlyTypes=true --ts_proto_out="./src/generated" ../proto/entity.proto
+    protoc --plugin="./node_modules/.bin/protoc-gen-ts_proto" --ts_proto_opt=useOptionals=all --ts_proto_opt=snakeToCamel=false --ts_proto_opt=onlyTypes=true --ts_proto_out="./src/generated" proto/entity.proto
 */
 
 import {
