/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */
// Generated by the protocol buffer compiler.  DO NOT EDIT!
// source: org/waveprotocol/box/server/persistence/protos/delta-store.proto

package org.waveprotocol.box.server.persistence.protos;

public final class ProtoDeltaStoreData {
  private ProtoDeltaStoreData() {}
  public static void registerAllExtensions(
      com.google.protobuf.ExtensionRegistry registry) {
  }
  public interface ProtoTransformedWaveletDeltaOrBuilder
      extends com.google.protobuf.MessageOrBuilder {

    // required string author = 1;
    /**
     * <code>required string author = 1;</code>
     */
    boolean hasAuthor();
    /**
     * <code>required string author = 1;</code>
     */
    java.lang.String getAuthor();
    /**
     * <code>required string author = 1;</code>
     */
    com.google.protobuf.ByteString
        getAuthorBytes();

    // required .federation.ProtocolHashedVersion resulting_version = 2;
    /**
     * <code>required .federation.ProtocolHashedVersion resulting_version = 2;</code>
     */
    boolean hasResultingVersion();
    /**
     * <code>required .federation.ProtocolHashedVersion resulting_version = 2;</code>
     */
    org.waveprotocol.wave.federation.Proto.ProtocolHashedVersion getResultingVersion();
    /**
     * <code>required .federation.ProtocolHashedVersion resulting_version = 2;</code>
     */
    org.waveprotocol.wave.federation.Proto.ProtocolHashedVersionOrBuilder getResultingVersionOrBuilder();

    // required int64 application_timestamp = 3;
    /**
     * <code>required int64 application_timestamp = 3;</code>
     */
    boolean hasApplicationTimestamp();
    /**
     * <code>required int64 application_timestamp = 3;</code>
     */
    long getApplicationTimestamp();

    // repeated .federation.ProtocolWaveletOperation operation = 4;
    /**
     * <code>repeated .federation.ProtocolWaveletOperation operation = 4;</code>
     */
    java.util.List<org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperation> 
        getOperationList();
    /**
     * <code>repeated .federation.ProtocolWaveletOperation operation = 4;</code>
     */
    org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperation getOperation(int index);
    /**
     * <code>repeated .federation.ProtocolWaveletOperation operation = 4;</code>
     */
    int getOperationCount();
    /**
     * <code>repeated .federation.ProtocolWaveletOperation operation = 4;</code>
     */
    java.util.List<? extends org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperationOrBuilder> 
        getOperationOrBuilderList();
    /**
     * <code>repeated .federation.ProtocolWaveletOperation operation = 4;</code>
     */
    org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperationOrBuilder getOperationOrBuilder(
        int index);
  }
  /**
   * Protobuf type {@code protodeltastore.ProtoTransformedWaveletDelta}
   */
  public static final class ProtoTransformedWaveletDelta extends
      com.google.protobuf.GeneratedMessage
      implements ProtoTransformedWaveletDeltaOrBuilder {
    // Use ProtoTransformedWaveletDelta.newBuilder() to construct.
    private ProtoTransformedWaveletDelta(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
      super(builder);
      this.unknownFields = builder.getUnknownFields();
    }
    private ProtoTransformedWaveletDelta(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }

    private static final ProtoTransformedWaveletDelta defaultInstance;
    public static ProtoTransformedWaveletDelta getDefaultInstance() {
      return defaultInstance;
    }

    public ProtoTransformedWaveletDelta getDefaultInstanceForType() {
      return defaultInstance;
    }

    private final com.google.protobuf.UnknownFieldSet unknownFields;
    @java.lang.Override
    public final com.google.protobuf.UnknownFieldSet
        getUnknownFields() {
      return this.unknownFields;
    }
    private ProtoTransformedWaveletDelta(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      initFields();
      int mutable_bitField0_ = 0;
      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
          com.google.protobuf.UnknownFieldSet.newBuilder();
      try {
        boolean done = false;
        while (!done) {
          int tag = input.readTag();
          switch (tag) {
            case 0:
              done = true;
              break;
            default: {
              if (!parseUnknownField(input, unknownFields,
                                     extensionRegistry, tag)) {
                done = true;
              }
              break;
            }
            case 10: {
              bitField0_ |= 0x00000001;
              author_ = input.readBytes();
              break;
            }
            case 18: {
              org.waveprotocol.wave.federation.Proto.ProtocolHashedVersion.Builder subBuilder = null;
              if (((bitField0_ & 0x00000002) == 0x00000002)) {
                subBuilder = resultingVersion_.toBuilder();
              }
              resultingVersion_ = input.readMessage(org.waveprotocol.wave.federation.Proto.ProtocolHashedVersion.PARSER, extensionRegistry);
              if (subBuilder != null) {
                subBuilder.mergeFrom(resultingVersion_);
                resultingVersion_ = subBuilder.buildPartial();
              }
              bitField0_ |= 0x00000002;
              break;
            }
            case 24: {
              bitField0_ |= 0x00000004;
              applicationTimestamp_ = input.readInt64();
              break;
            }
            case 34: {
              if (!((mutable_bitField0_ & 0x00000008) == 0x00000008)) {
                operation_ = new java.util.ArrayList<org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperation>();
                mutable_bitField0_ |= 0x00000008;
              }
              operation_.add(input.readMessage(org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperation.PARSER, extensionRegistry));
              break;
            }
          }
        }
      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
        throw e.setUnfinishedMessage(this);
      } catch (java.io.IOException e) {
        throw new com.google.protobuf.InvalidProtocolBufferException(
            e.getMessage()).setUnfinishedMessage(this);
      } finally {
        if (((mutable_bitField0_ & 0x00000008) == 0x00000008)) {
          operation_ = java.util.Collections.unmodifiableList(operation_);
        }
        this.unknownFields = unknownFields.build();
        makeExtensionsImmutable();
      }
    }
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return org.waveprotocol.box.server.persistence.protos.ProtoDeltaStoreData.internal_static_protodeltastore_ProtoTransformedWaveletDelta_descriptor;
    }

    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return org.waveprotocol.box.server.persistence.protos.ProtoDeltaStoreData.internal_static_protodeltastore_ProtoTransformedWaveletDelta_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              org.waveprotocol.box.server.persistence.protos.ProtoDeltaStoreData.ProtoTransformedWaveletDelta.class, org.waveprotocol.box.server.persistence.protos.ProtoDeltaStoreData.ProtoTransformedWaveletDelta.Builder.class);
    }

    public static com.google.protobuf.Parser<ProtoTransformedWaveletDelta> PARSER =
        new com.google.protobuf.AbstractParser<ProtoTransformedWaveletDelta>() {
      public ProtoTransformedWaveletDelta parsePartialFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws com.google.protobuf.InvalidProtocolBufferException {
        return new ProtoTransformedWaveletDelta(input, extensionRegistry);
      }
    };

    @java.lang.Override
    public com.google.protobuf.Parser<ProtoTransformedWaveletDelta> getParserForType() {
      return PARSER;
    }

    private int bitField0_;
    // required string author = 1;
    public static final int AUTHOR_FIELD_NUMBER = 1;
    private java.lang.Object author_;
    /**
     * <code>required string author = 1;</code>
     */
    public boolean hasAuthor() {
      return ((bitField0_ & 0x00000001) == 0x00000001);
    }
    /**
     * <code>required string author = 1;</code>
     */
    public java.lang.String getAuthor() {
      java.lang.Object ref = author_;
      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();
        if (bs.isValidUtf8()) {
          author_ = s;
        }
        return s;
      }
    }
    /**
     * <code>required string author = 1;</code>
     */
    public com.google.protobuf.ByteString
        getAuthorBytes() {
      java.lang.Object ref = author_;
      if (ref instanceof java.lang.String) {
        com.google.protobuf.ByteString b = 
            com.google.protobuf.ByteString.copyFromUtf8(
                (java.lang.String) ref);
        author_ = b;
        return b;
      } else {
        return (com.google.protobuf.ByteString) ref;
      }
    }

    // required .federation.ProtocolHashedVersion resulting_version = 2;
    public static final int RESULTING_VERSION_FIELD_NUMBER = 2;
    private org.waveprotocol.wave.federation.Proto.ProtocolHashedVersion resultingVersion_;
    /**
     * <code>required .federation.ProtocolHashedVersion resulting_version = 2;</code>
     */
    public boolean hasResultingVersion() {
      return ((bitField0_ & 0x00000002) == 0x00000002);
    }
    /**
     * <code>required .federation.ProtocolHashedVersion resulting_version = 2;</code>
     */
    public org.waveprotocol.wave.federation.Proto.ProtocolHashedVersion getResultingVersion() {
      return resultingVersion_;
    }
    /**
     * <code>required .federation.ProtocolHashedVersion resulting_version = 2;</code>
     */
    public org.waveprotocol.wave.federation.Proto.ProtocolHashedVersionOrBuilder getResultingVersionOrBuilder() {
      return resultingVersion_;
    }

    // required int64 application_timestamp = 3;
    public static final int APPLICATION_TIMESTAMP_FIELD_NUMBER = 3;
    private long applicationTimestamp_;
    /**
     * <code>required int64 application_timestamp = 3;</code>
     */
    public boolean hasApplicationTimestamp() {
      return ((bitField0_ & 0x00000004) == 0x00000004);
    }
    /**
     * <code>required int64 application_timestamp = 3;</code>
     */
    public long getApplicationTimestamp() {
      return applicationTimestamp_;
    }

    // repeated .federation.ProtocolWaveletOperation operation = 4;
    public static final int OPERATION_FIELD_NUMBER = 4;
    private java.util.List<org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperation> operation_;
    /**
     * <code>repeated .federation.ProtocolWaveletOperation operation = 4;</code>
     */
    public java.util.List<org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperation> getOperationList() {
      return operation_;
    }
    /**
     * <code>repeated .federation.ProtocolWaveletOperation operation = 4;</code>
     */
    public java.util.List<? extends org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperationOrBuilder> 
        getOperationOrBuilderList() {
      return operation_;
    }
    /**
     * <code>repeated .federation.ProtocolWaveletOperation operation = 4;</code>
     */
    public int getOperationCount() {
      return operation_.size();
    }
    /**
     * <code>repeated .federation.ProtocolWaveletOperation operation = 4;</code>
     */
    public org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperation getOperation(int index) {
      return operation_.get(index);
    }
    /**
     * <code>repeated .federation.ProtocolWaveletOperation operation = 4;</code>
     */
    public org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperationOrBuilder getOperationOrBuilder(
        int index) {
      return operation_.get(index);
    }

    private void initFields() {
      author_ = "";
      resultingVersion_ = org.waveprotocol.wave.federation.Proto.ProtocolHashedVersion.getDefaultInstance();
      applicationTimestamp_ = 0L;
      operation_ = java.util.Collections.emptyList();
    }
    private byte memoizedIsInitialized = -1;
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized != -1) return isInitialized == 1;

      if (!hasAuthor()) {
        memoizedIsInitialized = 0;
        return false;
      }
      if (!hasResultingVersion()) {
        memoizedIsInitialized = 0;
        return false;
      }
      if (!hasApplicationTimestamp()) {
        memoizedIsInitialized = 0;
        return false;
      }
      if (!getResultingVersion().isInitialized()) {
        memoizedIsInitialized = 0;
        return false;
      }
      for (int i = 0; i < getOperationCount(); i++) {
        if (!getOperation(i).isInitialized()) {
          memoizedIsInitialized = 0;
          return false;
        }
      }
      memoizedIsInitialized = 1;
      return true;
    }

    public void writeTo(com.google.protobuf.CodedOutputStream output)
                        throws java.io.IOException {
      getSerializedSize();
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        output.writeBytes(1, getAuthorBytes());
      }
      if (((bitField0_ & 0x00000002) == 0x00000002)) {
        output.writeMessage(2, resultingVersion_);
      }
      if (((bitField0_ & 0x00000004) == 0x00000004)) {
        output.writeInt64(3, applicationTimestamp_);
      }
      for (int i = 0; i < operation_.size(); i++) {
        output.writeMessage(4, operation_.get(i));
      }
      getUnknownFields().writeTo(output);
    }

    private int memoizedSerializedSize = -1;
    public int getSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBytesSize(1, getAuthorBytes());
      }
      if (((bitField0_ & 0x00000002) == 0x00000002)) {
        size += com.google.protobuf.CodedOutputStream
          .computeMessageSize(2, resultingVersion_);
      }
      if (((bitField0_ & 0x00000004) == 0x00000004)) {
        size += com.google.protobuf.CodedOutputStream
          .computeInt64Size(3, applicationTimestamp_);
      }
      for (int i = 0; i < operation_.size(); i++) {
        size += com.google.protobuf.CodedOutputStream
          .computeMessageSize(4, operation_.get(i));
      }
      size += getUnknownFields().getSerializedSize();
      memoizedSerializedSize = size;
      return size;
    }

    private static final long serialVersionUID = 0L;
    @java.lang.Override
    protected java.lang.Object writeReplace()
        throws java.io.ObjectStreamException {
      return super.writeReplace();
    }

    public static org.waveprotocol.box.server.persistence.protos.ProtoDeltaStoreData.ProtoTransformedWaveletDelta parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.waveprotocol.box.server.persistence.protos.ProtoDeltaStoreData.ProtoTransformedWaveletDelta parseFrom(
        com.google.protobuf.ByteString data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static org.waveprotocol.box.server.persistence.protos.ProtoDeltaStoreData.ProtoTransformedWaveletDelta parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.waveprotocol.box.server.persistence.protos.ProtoDeltaStoreData.ProtoTransformedWaveletDelta parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static org.waveprotocol.box.server.persistence.protos.ProtoDeltaStoreData.ProtoTransformedWaveletDelta parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.waveprotocol.box.server.persistence.protos.ProtoDeltaStoreData.ProtoTransformedWaveletDelta parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }
    public static org.waveprotocol.box.server.persistence.protos.ProtoDeltaStoreData.ProtoTransformedWaveletDelta parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input);
    }
    public static org.waveprotocol.box.server.persistence.protos.ProtoDeltaStoreData.ProtoTransformedWaveletDelta parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input, extensionRegistry);
    }
    public static org.waveprotocol.box.server.persistence.protos.ProtoDeltaStoreData.ProtoTransformedWaveletDelta parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.waveprotocol.box.server.persistence.protos.ProtoDeltaStoreData.ProtoTransformedWaveletDelta parseFrom(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }

    public static Builder newBuilder() { return Builder.create(); }
    public Builder newBuilderForType() { return newBuilder(); }
    public static Builder newBuilder(org.waveprotocol.box.server.persistence.protos.ProtoDeltaStoreData.ProtoTransformedWaveletDelta prototype) {
      return newBuilder().mergeFrom(prototype);
    }
    public Builder toBuilder() { return newBuilder(this); }

    @java.lang.Override
    protected Builder newBuilderForType(
        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
      Builder builder = new Builder(parent);
      return builder;
    }
    /**
     * Protobuf type {@code protodeltastore.ProtoTransformedWaveletDelta}
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessage.Builder<Builder>
       implements org.waveprotocol.box.server.persistence.protos.ProtoDeltaStoreData.ProtoTransformedWaveletDeltaOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return org.waveprotocol.box.server.persistence.protos.ProtoDeltaStoreData.internal_static_protodeltastore_ProtoTransformedWaveletDelta_descriptor;
      }

      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
          internalGetFieldAccessorTable() {
        return org.waveprotocol.box.server.persistence.protos.ProtoDeltaStoreData.internal_static_protodeltastore_ProtoTransformedWaveletDelta_fieldAccessorTable
            .ensureFieldAccessorsInitialized(
                org.waveprotocol.box.server.persistence.protos.ProtoDeltaStoreData.ProtoTransformedWaveletDelta.class, org.waveprotocol.box.server.persistence.protos.ProtoDeltaStoreData.ProtoTransformedWaveletDelta.Builder.class);
      }

      // Construct using org.waveprotocol.box.server.persistence.protos.ProtoDeltaStoreData.ProtoTransformedWaveletDelta.newBuilder()
      private Builder() {
        maybeForceBuilderInitialization();
      }

      private Builder(
          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
        super(parent);
        maybeForceBuilderInitialization();
      }
      private void maybeForceBuilderInitialization() {
        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
          getResultingVersionFieldBuilder();
          getOperationFieldBuilder();
        }
      }
      private static Builder create() {
        return new Builder();
      }

      public Builder clear() {
        super.clear();
        author_ = "";
        bitField0_ = (bitField0_ & ~0x00000001);
        if (resultingVersionBuilder_ == null) {
          resultingVersion_ = org.waveprotocol.wave.federation.Proto.ProtocolHashedVersion.getDefaultInstance();
        } else {
          resultingVersionBuilder_.clear();
        }
        bitField0_ = (bitField0_ & ~0x00000002);
        applicationTimestamp_ = 0L;
        bitField0_ = (bitField0_ & ~0x00000004);
        if (operationBuilder_ == null) {
          operation_ = java.util.Collections.emptyList();
          bitField0_ = (bitField0_ & ~0x00000008);
        } else {
          operationBuilder_.clear();
        }
        return this;
      }

      public Builder clone() {
        return create().mergeFrom(buildPartial());
      }

      public com.google.protobuf.Descriptors.Descriptor
          getDescriptorForType() {
        return org.waveprotocol.box.server.persistence.protos.ProtoDeltaStoreData.internal_static_protodeltastore_ProtoTransformedWaveletDelta_descriptor;
      }

      public org.waveprotocol.box.server.persistence.protos.ProtoDeltaStoreData.ProtoTransformedWaveletDelta getDefaultInstanceForType() {
        return org.waveprotocol.box.server.persistence.protos.ProtoDeltaStoreData.ProtoTransformedWaveletDelta.getDefaultInstance();
      }

      public org.waveprotocol.box.server.persistence.protos.ProtoDeltaStoreData.ProtoTransformedWaveletDelta build() {
        org.waveprotocol.box.server.persistence.protos.ProtoDeltaStoreData.ProtoTransformedWaveletDelta result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      public org.waveprotocol.box.server.persistence.protos.ProtoDeltaStoreData.ProtoTransformedWaveletDelta buildPartial() {
        org.waveprotocol.box.server.persistence.protos.ProtoDeltaStoreData.ProtoTransformedWaveletDelta result = new org.waveprotocol.box.server.persistence.protos.ProtoDeltaStoreData.ProtoTransformedWaveletDelta(this);
        int from_bitField0_ = bitField0_;
        int to_bitField0_ = 0;
        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
          to_bitField0_ |= 0x00000001;
        }
        result.author_ = author_;
        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
          to_bitField0_ |= 0x00000002;
        }
        if (resultingVersionBuilder_ == null) {
          result.resultingVersion_ = resultingVersion_;
        } else {
          result.resultingVersion_ = resultingVersionBuilder_.build();
        }
        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
          to_bitField0_ |= 0x00000004;
        }
        result.applicationTimestamp_ = applicationTimestamp_;
        if (operationBuilder_ == null) {
          if (((bitField0_ & 0x00000008) == 0x00000008)) {
            operation_ = java.util.Collections.unmodifiableList(operation_);
            bitField0_ = (bitField0_ & ~0x00000008);
          }
          result.operation_ = operation_;
        } else {
          result.operation_ = operationBuilder_.build();
        }
        result.bitField0_ = to_bitField0_;
        onBuilt();
        return result;
      }

      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof org.waveprotocol.box.server.persistence.protos.ProtoDeltaStoreData.ProtoTransformedWaveletDelta) {
          return mergeFrom((org.waveprotocol.box.server.persistence.protos.ProtoDeltaStoreData.ProtoTransformedWaveletDelta)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(org.waveprotocol.box.server.persistence.protos.ProtoDeltaStoreData.ProtoTransformedWaveletDelta other) {
        if (other == org.waveprotocol.box.server.persistence.protos.ProtoDeltaStoreData.ProtoTransformedWaveletDelta.getDefaultInstance()) return this;
        if (other.hasAuthor()) {
          bitField0_ |= 0x00000001;
          author_ = other.author_;
          onChanged();
        }
        if (other.hasResultingVersion()) {
          mergeResultingVersion(other.getResultingVersion());
        }
        if (other.hasApplicationTimestamp()) {
          setApplicationTimestamp(other.getApplicationTimestamp());
        }
        if (operationBuilder_ == null) {
          if (!other.operation_.isEmpty()) {
            if (operation_.isEmpty()) {
              operation_ = other.operation_;
              bitField0_ = (bitField0_ & ~0x00000008);
            } else {
              ensureOperationIsMutable();
              operation_.addAll(other.operation_);
            }
            onChanged();
          }
        } else {
          if (!other.operation_.isEmpty()) {
            if (operationBuilder_.isEmpty()) {
              operationBuilder_.dispose();
              operationBuilder_ = null;
              operation_ = other.operation_;
              bitField0_ = (bitField0_ & ~0x00000008);
              operationBuilder_ = 
                com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
                   getOperationFieldBuilder() : null;
            } else {
              operationBuilder_.addAllMessages(other.operation_);
            }
          }
        }
        this.mergeUnknownFields(other.getUnknownFields());
        return this;
      }

      public final boolean isInitialized() {
        if (!hasAuthor()) {
          
          return false;
        }
        if (!hasResultingVersion()) {
          
          return false;
        }
        if (!hasApplicationTimestamp()) {
          
          return false;
        }
        if (!getResultingVersion().isInitialized()) {
          
          return false;
        }
        for (int i = 0; i < getOperationCount(); i++) {
          if (!getOperation(i).isInitialized()) {
            
            return false;
          }
        }
        return true;
      }

      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        org.waveprotocol.box.server.persistence.protos.ProtoDeltaStoreData.ProtoTransformedWaveletDelta parsedMessage = null;
        try {
          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          parsedMessage = (org.waveprotocol.box.server.persistence.protos.ProtoDeltaStoreData.ProtoTransformedWaveletDelta) e.getUnfinishedMessage();
          throw e;
        } finally {
          if (parsedMessage != null) {
            mergeFrom(parsedMessage);
          }
        }
        return this;
      }
      private int bitField0_;

      // required string author = 1;
      private java.lang.Object author_ = "";
      /**
       * <code>required string author = 1;</code>
       */
      public boolean hasAuthor() {
        return ((bitField0_ & 0x00000001) == 0x00000001);
      }
      /**
       * <code>required string author = 1;</code>
       */
      public java.lang.String getAuthor() {
        java.lang.Object ref = author_;
        if (!(ref instanceof java.lang.String)) {
          java.lang.String s = ((com.google.protobuf.ByteString) ref)
              .toStringUtf8();
          author_ = s;
          return s;
        } else {
          return (java.lang.String) ref;
        }
      }
      /**
       * <code>required string author = 1;</code>
       */
      public com.google.protobuf.ByteString
          getAuthorBytes() {
        java.lang.Object ref = author_;
        if (ref instanceof String) {
          com.google.protobuf.ByteString b = 
              com.google.protobuf.ByteString.copyFromUtf8(
                  (java.lang.String) ref);
          author_ = b;
          return b;
        } else {
          return (com.google.protobuf.ByteString) ref;
        }
      }
      /**
       * <code>required string author = 1;</code>
       */
      public Builder setAuthor(
          java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000001;
        author_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required string author = 1;</code>
       */
      public Builder clearAuthor() {
        bitField0_ = (bitField0_ & ~0x00000001);
        author_ = getDefaultInstance().getAuthor();
        onChanged();
        return this;
      }
      /**
       * <code>required string author = 1;</code>
       */
      public Builder setAuthorBytes(
          com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000001;
        author_ = value;
        onChanged();
        return this;
      }

      // required .federation.ProtocolHashedVersion resulting_version = 2;
      private org.waveprotocol.wave.federation.Proto.ProtocolHashedVersion resultingVersion_ = org.waveprotocol.wave.federation.Proto.ProtocolHashedVersion.getDefaultInstance();
      private com.google.protobuf.SingleFieldBuilder<
          org.waveprotocol.wave.federation.Proto.ProtocolHashedVersion, org.waveprotocol.wave.federation.Proto.ProtocolHashedVersion.Builder, org.waveprotocol.wave.federation.Proto.ProtocolHashedVersionOrBuilder> resultingVersionBuilder_;
      /**
       * <code>required .federation.ProtocolHashedVersion resulting_version = 2;</code>
       */
      public boolean hasResultingVersion() {
        return ((bitField0_ & 0x00000002) == 0x00000002);
      }
      /**
       * <code>required .federation.ProtocolHashedVersion resulting_version = 2;</code>
       */
      public org.waveprotocol.wave.federation.Proto.ProtocolHashedVersion getResultingVersion() {
        if (resultingVersionBuilder_ == null) {
          return resultingVersion_;
        } else {
          return resultingVersionBuilder_.getMessage();
        }
      }
      /**
       * <code>required .federation.ProtocolHashedVersion resulting_version = 2;</code>
       */
      public Builder setResultingVersion(org.waveprotocol.wave.federation.Proto.ProtocolHashedVersion value) {
        if (resultingVersionBuilder_ == null) {
          if (value == null) {
            throw new NullPointerException();
          }
          resultingVersion_ = value;
          onChanged();
        } else {
          resultingVersionBuilder_.setMessage(value);
        }
        bitField0_ |= 0x00000002;
        return this;
      }
      /**
       * <code>required .federation.ProtocolHashedVersion resulting_version = 2;</code>
       */
      public Builder setResultingVersion(
          org.waveprotocol.wave.federation.Proto.ProtocolHashedVersion.Builder builderForValue) {
        if (resultingVersionBuilder_ == null) {
          resultingVersion_ = builderForValue.build();
          onChanged();
        } else {
          resultingVersionBuilder_.setMessage(builderForValue.build());
        }
        bitField0_ |= 0x00000002;
        return this;
      }
      /**
       * <code>required .federation.ProtocolHashedVersion resulting_version = 2;</code>
       */
      public Builder mergeResultingVersion(org.waveprotocol.wave.federation.Proto.ProtocolHashedVersion value) {
        if (resultingVersionBuilder_ == null) {
          if (((bitField0_ & 0x00000002) == 0x00000002) &&
              resultingVersion_ != org.waveprotocol.wave.federation.Proto.ProtocolHashedVersion.getDefaultInstance()) {
            resultingVersion_ =
              org.waveprotocol.wave.federation.Proto.ProtocolHashedVersion.newBuilder(resultingVersion_).mergeFrom(value).buildPartial();
          } else {
            resultingVersion_ = value;
          }
          onChanged();
        } else {
          resultingVersionBuilder_.mergeFrom(value);
        }
        bitField0_ |= 0x00000002;
        return this;
      }
      /**
       * <code>required .federation.ProtocolHashedVersion resulting_version = 2;</code>
       */
      public Builder clearResultingVersion() {
        if (resultingVersionBuilder_ == null) {
          resultingVersion_ = org.waveprotocol.wave.federation.Proto.ProtocolHashedVersion.getDefaultInstance();
          onChanged();
        } else {
          resultingVersionBuilder_.clear();
        }
        bitField0_ = (bitField0_ & ~0x00000002);
        return this;
      }
      /**
       * <code>required .federation.ProtocolHashedVersion resulting_version = 2;</code>
       */
      public org.waveprotocol.wave.federation.Proto.ProtocolHashedVersion.Builder getResultingVersionBuilder() {
        bitField0_ |= 0x00000002;
        onChanged();
        return getResultingVersionFieldBuilder().getBuilder();
      }
      /**
       * <code>required .federation.ProtocolHashedVersion resulting_version = 2;</code>
       */
      public org.waveprotocol.wave.federation.Proto.ProtocolHashedVersionOrBuilder getResultingVersionOrBuilder() {
        if (resultingVersionBuilder_ != null) {
          return resultingVersionBuilder_.getMessageOrBuilder();
        } else {
          return resultingVersion_;
        }
      }
      /**
       * <code>required .federation.ProtocolHashedVersion resulting_version = 2;</code>
       */
      private com.google.protobuf.SingleFieldBuilder<
          org.waveprotocol.wave.federation.Proto.ProtocolHashedVersion, org.waveprotocol.wave.federation.Proto.ProtocolHashedVersion.Builder, org.waveprotocol.wave.federation.Proto.ProtocolHashedVersionOrBuilder> 
          getResultingVersionFieldBuilder() {
        if (resultingVersionBuilder_ == null) {
          resultingVersionBuilder_ = new com.google.protobuf.SingleFieldBuilder<
              org.waveprotocol.wave.federation.Proto.ProtocolHashedVersion, org.waveprotocol.wave.federation.Proto.ProtocolHashedVersion.Builder, org.waveprotocol.wave.federation.Proto.ProtocolHashedVersionOrBuilder>(
                  resultingVersion_,
                  getParentForChildren(),
                  isClean());
          resultingVersion_ = null;
        }
        return resultingVersionBuilder_;
      }

      // required int64 application_timestamp = 3;
      private long applicationTimestamp_ ;
      /**
       * <code>required int64 application_timestamp = 3;</code>
       */
      public boolean hasApplicationTimestamp() {
        return ((bitField0_ & 0x00000004) == 0x00000004);
      }
      /**
       * <code>required int64 application_timestamp = 3;</code>
       */
      public long getApplicationTimestamp() {
        return applicationTimestamp_;
      }
      /**
       * <code>required int64 application_timestamp = 3;</code>
       */
      public Builder setApplicationTimestamp(long value) {
        bitField0_ |= 0x00000004;
        applicationTimestamp_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required int64 application_timestamp = 3;</code>
       */
      public Builder clearApplicationTimestamp() {
        bitField0_ = (bitField0_ & ~0x00000004);
        applicationTimestamp_ = 0L;
        onChanged();
        return this;
      }

      // repeated .federation.ProtocolWaveletOperation operation = 4;
      private java.util.List<org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperation> operation_ =
        java.util.Collections.emptyList();
      private void ensureOperationIsMutable() {
        if (!((bitField0_ & 0x00000008) == 0x00000008)) {
          operation_ = new java.util.ArrayList<org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperation>(operation_);
          bitField0_ |= 0x00000008;
         }
      }

      private com.google.protobuf.RepeatedFieldBuilder<
          org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperation, org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperation.Builder, org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperationOrBuilder> operationBuilder_;

      /**
       * <code>repeated .federation.ProtocolWaveletOperation operation = 4;</code>
       */
      public java.util.List<org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperation> getOperationList() {
        if (operationBuilder_ == null) {
          return java.util.Collections.unmodifiableList(operation_);
        } else {
          return operationBuilder_.getMessageList();
        }
      }
      /**
       * <code>repeated .federation.ProtocolWaveletOperation operation = 4;</code>
       */
      public int getOperationCount() {
        if (operationBuilder_ == null) {
          return operation_.size();
        } else {
          return operationBuilder_.getCount();
        }
      }
      /**
       * <code>repeated .federation.ProtocolWaveletOperation operation = 4;</code>
       */
      public org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperation getOperation(int index) {
        if (operationBuilder_ == null) {
          return operation_.get(index);
        } else {
          return operationBuilder_.getMessage(index);
        }
      }
      /**
       * <code>repeated .federation.ProtocolWaveletOperation operation = 4;</code>
       */
      public Builder setOperation(
          int index, org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperation value) {
        if (operationBuilder_ == null) {
          if (value == null) {
            throw new NullPointerException();
          }
          ensureOperationIsMutable();
          operation_.set(index, value);
          onChanged();
        } else {
          operationBuilder_.setMessage(index, value);
        }
        return this;
      }
      /**
       * <code>repeated .federation.ProtocolWaveletOperation operation = 4;</code>
       */
      public Builder setOperation(
          int index, org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperation.Builder builderForValue) {
        if (operationBuilder_ == null) {
          ensureOperationIsMutable();
          operation_.set(index, builderForValue.build());
          onChanged();
        } else {
          operationBuilder_.setMessage(index, builderForValue.build());
        }
        return this;
      }
      /**
       * <code>repeated .federation.ProtocolWaveletOperation operation = 4;</code>
       */
      public Builder addOperation(org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperation value) {
        if (operationBuilder_ == null) {
          if (value == null) {
            throw new NullPointerException();
          }
          ensureOperationIsMutable();
          operation_.add(value);
          onChanged();
        } else {
          operationBuilder_.addMessage(value);
        }
        return this;
      }
      /**
       * <code>repeated .federation.ProtocolWaveletOperation operation = 4;</code>
       */
      public Builder addOperation(
          int index, org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperation value) {
        if (operationBuilder_ == null) {
          if (value == null) {
            throw new NullPointerException();
          }
          ensureOperationIsMutable();
          operation_.add(index, value);
          onChanged();
        } else {
          operationBuilder_.addMessage(index, value);
        }
        return this;
      }
      /**
       * <code>repeated .federation.ProtocolWaveletOperation operation = 4;</code>
       */
      public Builder addOperation(
          org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperation.Builder builderForValue) {
        if (operationBuilder_ == null) {
          ensureOperationIsMutable();
          operation_.add(builderForValue.build());
          onChanged();
        } else {
          operationBuilder_.addMessage(builderForValue.build());
        }
        return this;
      }
      /**
       * <code>repeated .federation.ProtocolWaveletOperation operation = 4;</code>
       */
      public Builder addOperation(
          int index, org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperation.Builder builderForValue) {
        if (operationBuilder_ == null) {
          ensureOperationIsMutable();
          operation_.add(index, builderForValue.build());
          onChanged();
        } else {
          operationBuilder_.addMessage(index, builderForValue.build());
        }
        return this;
      }
      /**
       * <code>repeated .federation.ProtocolWaveletOperation operation = 4;</code>
       */
      public Builder addAllOperation(
          java.lang.Iterable<? extends org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperation> values) {
        if (operationBuilder_ == null) {
          ensureOperationIsMutable();
          super.addAll(values, operation_);
          onChanged();
        } else {
          operationBuilder_.addAllMessages(values);
        }
        return this;
      }
      /**
       * <code>repeated .federation.ProtocolWaveletOperation operation = 4;</code>
       */
      public Builder clearOperation() {
        if (operationBuilder_ == null) {
          operation_ = java.util.Collections.emptyList();
          bitField0_ = (bitField0_ & ~0x00000008);
          onChanged();
        } else {
          operationBuilder_.clear();
        }
        return this;
      }
      /**
       * <code>repeated .federation.ProtocolWaveletOperation operation = 4;</code>
       */
      public Builder removeOperation(int index) {
        if (operationBuilder_ == null) {
          ensureOperationIsMutable();
          operation_.remove(index);
          onChanged();
        } else {
          operationBuilder_.remove(index);
        }
        return this;
      }
      /**
       * <code>repeated .federation.ProtocolWaveletOperation operation = 4;</code>
       */
      public org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperation.Builder getOperationBuilder(
          int index) {
        return getOperationFieldBuilder().getBuilder(index);
      }
      /**
       * <code>repeated .federation.ProtocolWaveletOperation operation = 4;</code>
       */
      public org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperationOrBuilder getOperationOrBuilder(
          int index) {
        if (operationBuilder_ == null) {
          return operation_.get(index);  } else {
          return operationBuilder_.getMessageOrBuilder(index);
        }
      }
      /**
       * <code>repeated .federation.ProtocolWaveletOperation operation = 4;</code>
       */
      public java.util.List<? extends org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperationOrBuilder> 
           getOperationOrBuilderList() {
        if (operationBuilder_ != null) {
          return operationBuilder_.getMessageOrBuilderList();
        } else {
          return java.util.Collections.unmodifiableList(operation_);
        }
      }
      /**
       * <code>repeated .federation.ProtocolWaveletOperation operation = 4;</code>
       */
      public org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperation.Builder addOperationBuilder() {
        return getOperationFieldBuilder().addBuilder(
            org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperation.getDefaultInstance());
      }
      /**
       * <code>repeated .federation.ProtocolWaveletOperation operation = 4;</code>
       */
      public org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperation.Builder addOperationBuilder(
          int index) {
        return getOperationFieldBuilder().addBuilder(
            index, org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperation.getDefaultInstance());
      }
      /**
       * <code>repeated .federation.ProtocolWaveletOperation operation = 4;</code>
       */
      public java.util.List<org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperation.Builder> 
           getOperationBuilderList() {
        return getOperationFieldBuilder().getBuilderList();
      }
      private com.google.protobuf.RepeatedFieldBuilder<
          org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperation, org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperation.Builder, org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperationOrBuilder> 
          getOperationFieldBuilder() {
        if (operationBuilder_ == null) {
          operationBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
              org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperation, org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperation.Builder, org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperationOrBuilder>(
                  operation_,
                  ((bitField0_ & 0x00000008) == 0x00000008),
                  getParentForChildren(),
                  isClean());
          operation_ = null;
        }
        return operationBuilder_;
      }

      // @@protoc_insertion_point(builder_scope:protodeltastore.ProtoTransformedWaveletDelta)
    }

    static {
      defaultInstance = new ProtoTransformedWaveletDelta(true);
      defaultInstance.initFields();
    }

    // @@protoc_insertion_point(class_scope:protodeltastore.ProtoTransformedWaveletDelta)
  }

  private static com.google.protobuf.Descriptors.Descriptor
    internal_static_protodeltastore_ProtoTransformedWaveletDelta_descriptor;
  private static
    com.google.protobuf.GeneratedMessage.FieldAccessorTable
      internal_static_protodeltastore_ProtoTransformedWaveletDelta_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@org/waveprotocol/box/server/persistenc" +
      "e/protos/delta-store.proto\022\017protodeltast" +
      "ore\0326org/waveprotocol/wave/federation/fe" +
      "deration.protodevel\"\304\001\n\034ProtoTransformed" +
      "WaveletDelta\022\016\n\006author\030\001 \002(\t\022<\n\021resultin" +
      "g_version\030\002 \002(\0132!.federation.ProtocolHas" +
      "hedVersion\022\035\n\025application_timestamp\030\003 \002(" +
      "\003\0227\n\toperation\030\004 \003(\0132$.federation.Protoc" +
      "olWaveletOperationBE\n.org.waveprotocol.b" +
      "ox.server.persistence.protosB\023ProtoDelta",
      "StoreData"
    };
    com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
      new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
        public com.google.protobuf.ExtensionRegistry assignDescriptors(
            com.google.protobuf.Descriptors.FileDescriptor root) {
          descriptor = root;
          internal_static_protodeltastore_ProtoTransformedWaveletDelta_descriptor =
            getDescriptor().getMessageTypes().get(0);
          internal_static_protodeltastore_ProtoTransformedWaveletDelta_fieldAccessorTable = new
            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
              internal_static_protodeltastore_ProtoTransformedWaveletDelta_descriptor,
              new java.lang.String[] { "Author", "ResultingVersion", "ApplicationTimestamp", "Operation", });
          return null;
        }
      };
    com.google.protobuf.Descriptors.FileDescriptor
      .internalBuildGeneratedFileFrom(descriptorData,
        new com.google.protobuf.Descriptors.FileDescriptor[] {
          org.waveprotocol.wave.federation.Proto.getDescriptor(),
        }, assigner);
  }

  // @@protoc_insertion_point(outer_class_scope)
}
