// Generated by the protocol buffer compiler.  DO NOT EDIT!
// source: protobuf/ramcloud.proto

package net.onrc.onos.core.datastore;

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

    // required int64 dpid = 1;
    /**
     * <code>required int64 dpid = 1;</code>
     */
    boolean hasDpid();
    /**
     * <code>required int64 dpid = 1;</code>
     */
    long getDpid();

    // required int32 status = 2;
    /**
     * <code>required int32 status = 2;</code>
     */
    boolean hasStatus();
    /**
     * <code>required int32 status = 2;</code>
     */
    int getStatus();

    // optional bytes value = 3;
    /**
     * <code>optional bytes value = 3;</code>
     */
    boolean hasValue();
    /**
     * <code>optional bytes value = 3;</code>
     */
    com.google.protobuf.ByteString getValue();
  }
  /**
   * Protobuf type {@code RCProtos.SwitchProperty}
   */
  public static final class SwitchProperty extends
      com.google.protobuf.GeneratedMessage
      implements SwitchPropertyOrBuilder {
    // Use SwitchProperty.newBuilder() to construct.
    private SwitchProperty(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
      super(builder);
      this.unknownFields = builder.getUnknownFields();
    }
    private SwitchProperty(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }

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

    public SwitchProperty getDefaultInstanceForType() {
      return defaultInstance;
    }

    private final com.google.protobuf.UnknownFieldSet unknownFields;
    @java.lang.Override
    public final com.google.protobuf.UnknownFieldSet
        getUnknownFields() {
      return this.unknownFields;
    }
    private SwitchProperty(
        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 8: {
              bitField0_ |= 0x00000001;
              dpid_ = input.readInt64();
              break;
            }
            case 16: {
              bitField0_ |= 0x00000002;
              status_ = input.readInt32();
              break;
            }
            case 26: {
              bitField0_ |= 0x00000004;
              value_ = input.readBytes();
              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 {
        this.unknownFields = unknownFields.build();
        makeExtensionsImmutable();
      }
    }
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return net.onrc.onos.core.datastore.RCProtos.internal_static_ProtoBuffer_SwitchProperty_descriptor;
    }

    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return net.onrc.onos.core.datastore.RCProtos.internal_static_ProtoBuffer_SwitchProperty_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              net.onrc.onos.core.datastore.RCProtos.SwitchProperty.class, net.onrc.onos.core.datastore.RCProtos.SwitchProperty.Builder.class);
    }

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

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

    private int bitField0_;
    // required int64 dpid = 1;
    public static final int DPID_FIELD_NUMBER = 1;
    private long dpid_;
    /**
     * <code>required int64 dpid = 1;</code>
     */
    public boolean hasDpid() {
      return ((bitField0_ & 0x00000001) == 0x00000001);
    }
    /**
     * <code>required int64 dpid = 1;</code>
     */
    public long getDpid() {
      return dpid_;
    }

    // required int32 status = 2;
    public static final int STATUS_FIELD_NUMBER = 2;
    private int status_;
    /**
     * <code>required int32 status = 2;</code>
     */
    public boolean hasStatus() {
      return ((bitField0_ & 0x00000002) == 0x00000002);
    }
    /**
     * <code>required int32 status = 2;</code>
     */
    public int getStatus() {
      return status_;
    }

    // optional bytes value = 3;
    public static final int VALUE_FIELD_NUMBER = 3;
    private com.google.protobuf.ByteString value_;
    /**
     * <code>optional bytes value = 3;</code>
     */
    public boolean hasValue() {
      return ((bitField0_ & 0x00000004) == 0x00000004);
    }
    /**
     * <code>optional bytes value = 3;</code>
     */
    public com.google.protobuf.ByteString getValue() {
      return value_;
    }

    private void initFields() {
      dpid_ = 0L;
      status_ = 0;
      value_ = com.google.protobuf.ByteString.EMPTY;
    }
    private byte memoizedIsInitialized = -1;
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized != -1) return isInitialized == 1;

      if (!hasDpid()) {
        memoizedIsInitialized = 0;
        return false;
      }
      if (!hasStatus()) {
        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.writeInt64(1, dpid_);
      }
      if (((bitField0_ & 0x00000002) == 0x00000002)) {
        output.writeInt32(2, status_);
      }
      if (((bitField0_ & 0x00000004) == 0x00000004)) {
        output.writeBytes(3, value_);
      }
      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
          .computeInt64Size(1, dpid_);
      }
      if (((bitField0_ & 0x00000002) == 0x00000002)) {
        size += com.google.protobuf.CodedOutputStream
          .computeInt32Size(2, status_);
      }
      if (((bitField0_ & 0x00000004) == 0x00000004)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBytesSize(3, value_);
      }
      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 net.onrc.onos.core.datastore.RCProtos.SwitchProperty parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static net.onrc.onos.core.datastore.RCProtos.SwitchProperty parseFrom(
        com.google.protobuf.ByteString data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static net.onrc.onos.core.datastore.RCProtos.SwitchProperty parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static net.onrc.onos.core.datastore.RCProtos.SwitchProperty parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static net.onrc.onos.core.datastore.RCProtos.SwitchProperty parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static net.onrc.onos.core.datastore.RCProtos.SwitchProperty parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }
    public static net.onrc.onos.core.datastore.RCProtos.SwitchProperty parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input);
    }
    public static net.onrc.onos.core.datastore.RCProtos.SwitchProperty parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input, extensionRegistry);
    }
    public static net.onrc.onos.core.datastore.RCProtos.SwitchProperty parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static net.onrc.onos.core.datastore.RCProtos.SwitchProperty 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(net.onrc.onos.core.datastore.RCProtos.SwitchProperty 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 RCProtos.SwitchProperty}
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessage.Builder<Builder>
       implements net.onrc.onos.core.datastore.RCProtos.SwitchPropertyOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return net.onrc.onos.core.datastore.RCProtos.internal_static_ProtoBuffer_SwitchProperty_descriptor;
      }

      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
          internalGetFieldAccessorTable() {
        return net.onrc.onos.core.datastore.RCProtos.internal_static_ProtoBuffer_SwitchProperty_fieldAccessorTable
            .ensureFieldAccessorsInitialized(
                net.onrc.onos.core.datastore.RCProtos.SwitchProperty.class, net.onrc.onos.core.datastore.RCProtos.SwitchProperty.Builder.class);
      }

      // Construct using net.onrc.onos.core.datastore.RCProtos.SwitchProperty.newBuilder()
      private Builder() {
        maybeForceBuilderInitialization();
      }

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

      public Builder clear() {
        super.clear();
        dpid_ = 0L;
        bitField0_ = (bitField0_ & ~0x00000001);
        status_ = 0;
        bitField0_ = (bitField0_ & ~0x00000002);
        value_ = com.google.protobuf.ByteString.EMPTY;
        bitField0_ = (bitField0_ & ~0x00000004);
        return this;
      }

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

      public com.google.protobuf.Descriptors.Descriptor
          getDescriptorForType() {
        return net.onrc.onos.core.datastore.RCProtos.internal_static_ProtoBuffer_SwitchProperty_descriptor;
      }

      public net.onrc.onos.core.datastore.RCProtos.SwitchProperty getDefaultInstanceForType() {
        return net.onrc.onos.core.datastore.RCProtos.SwitchProperty.getDefaultInstance();
      }

      public net.onrc.onos.core.datastore.RCProtos.SwitchProperty build() {
        net.onrc.onos.core.datastore.RCProtos.SwitchProperty result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      public net.onrc.onos.core.datastore.RCProtos.SwitchProperty buildPartial() {
        net.onrc.onos.core.datastore.RCProtos.SwitchProperty result = new net.onrc.onos.core.datastore.RCProtos.SwitchProperty(this);
        int from_bitField0_ = bitField0_;
        int to_bitField0_ = 0;
        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
          to_bitField0_ |= 0x00000001;
        }
        result.dpid_ = dpid_;
        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
          to_bitField0_ |= 0x00000002;
        }
        result.status_ = status_;
        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
          to_bitField0_ |= 0x00000004;
        }
        result.value_ = value_;
        result.bitField0_ = to_bitField0_;
        onBuilt();
        return result;
      }

      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof net.onrc.onos.core.datastore.RCProtos.SwitchProperty) {
          return mergeFrom((net.onrc.onos.core.datastore.RCProtos.SwitchProperty)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(net.onrc.onos.core.datastore.RCProtos.SwitchProperty other) {
        if (other == net.onrc.onos.core.datastore.RCProtos.SwitchProperty.getDefaultInstance()) return this;
        if (other.hasDpid()) {
          setDpid(other.getDpid());
        }
        if (other.hasStatus()) {
          setStatus(other.getStatus());
        }
        if (other.hasValue()) {
          setValue(other.getValue());
        }
        this.mergeUnknownFields(other.getUnknownFields());
        return this;
      }

      public final boolean isInitialized() {
        if (!hasDpid()) {
          
          return false;
        }
        if (!hasStatus()) {
          
          return false;
        }
        return true;
      }

      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        net.onrc.onos.core.datastore.RCProtos.SwitchProperty parsedMessage = null;
        try {
          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          parsedMessage = (net.onrc.onos.core.datastore.RCProtos.SwitchProperty) e.getUnfinishedMessage();
          throw e;
        } finally {
          if (parsedMessage != null) {
            mergeFrom(parsedMessage);
          }
        }
        return this;
      }
      private int bitField0_;

      // required int64 dpid = 1;
      private long dpid_ ;
      /**
       * <code>required int64 dpid = 1;</code>
       */
      public boolean hasDpid() {
        return ((bitField0_ & 0x00000001) == 0x00000001);
      }
      /**
       * <code>required int64 dpid = 1;</code>
       */
      public long getDpid() {
        return dpid_;
      }
      /**
       * <code>required int64 dpid = 1;</code>
       */
      public Builder setDpid(long value) {
        bitField0_ |= 0x00000001;
        dpid_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required int64 dpid = 1;</code>
       */
      public Builder clearDpid() {
        bitField0_ = (bitField0_ & ~0x00000001);
        dpid_ = 0L;
        onChanged();
        return this;
      }

      // required int32 status = 2;
      private int status_ ;
      /**
       * <code>required int32 status = 2;</code>
       */
      public boolean hasStatus() {
        return ((bitField0_ & 0x00000002) == 0x00000002);
      }
      /**
       * <code>required int32 status = 2;</code>
       */
      public int getStatus() {
        return status_;
      }
      /**
       * <code>required int32 status = 2;</code>
       */
      public Builder setStatus(int value) {
        bitField0_ |= 0x00000002;
        status_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required int32 status = 2;</code>
       */
      public Builder clearStatus() {
        bitField0_ = (bitField0_ & ~0x00000002);
        status_ = 0;
        onChanged();
        return this;
      }

      // optional bytes value = 3;
      private com.google.protobuf.ByteString value_ = com.google.protobuf.ByteString.EMPTY;
      /**
       * <code>optional bytes value = 3;</code>
       */
      public boolean hasValue() {
        return ((bitField0_ & 0x00000004) == 0x00000004);
      }
      /**
       * <code>optional bytes value = 3;</code>
       */
      public com.google.protobuf.ByteString getValue() {
        return value_;
      }
      /**
       * <code>optional bytes value = 3;</code>
       */
      public Builder setValue(com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000004;
        value_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>optional bytes value = 3;</code>
       */
      public Builder clearValue() {
        bitField0_ = (bitField0_ & ~0x00000004);
        value_ = getDefaultInstance().getValue();
        onChanged();
        return this;
      }

      // @@protoc_insertion_point(builder_scope:RCProtos.SwitchProperty)
    }

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

    // @@protoc_insertion_point(class_scope:RCProtos.SwitchProperty)
  }

  public interface PortPropertyOrBuilder
      extends com.google.protobuf.MessageOrBuilder {

    // required int64 dpid = 1;
    /**
     * <code>required int64 dpid = 1;</code>
     */
    boolean hasDpid();
    /**
     * <code>required int64 dpid = 1;</code>
     */
    long getDpid();

    // required int64 number = 2;
    /**
     * <code>required int64 number = 2;</code>
     */
    boolean hasNumber();
    /**
     * <code>required int64 number = 2;</code>
     */
    long getNumber();

    // required int32 status = 3;
    /**
     * <code>required int32 status = 3;</code>
     */
    boolean hasStatus();
    /**
     * <code>required int32 status = 3;</code>
     */
    int getStatus();

    // optional bytes value = 4;
    /**
     * <code>optional bytes value = 4;</code>
     */
    boolean hasValue();
    /**
     * <code>optional bytes value = 4;</code>
     */
    com.google.protobuf.ByteString getValue();
  }
  /**
   * Protobuf type {@code RCProtos.PortProperty}
   */
  public static final class PortProperty extends
      com.google.protobuf.GeneratedMessage
      implements PortPropertyOrBuilder {
    // Use PortProperty.newBuilder() to construct.
    private PortProperty(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
      super(builder);
      this.unknownFields = builder.getUnknownFields();
    }
    private PortProperty(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }

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

    public PortProperty getDefaultInstanceForType() {
      return defaultInstance;
    }

    private final com.google.protobuf.UnknownFieldSet unknownFields;
    @java.lang.Override
    public final com.google.protobuf.UnknownFieldSet
        getUnknownFields() {
      return this.unknownFields;
    }
    private PortProperty(
        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 8: {
              bitField0_ |= 0x00000001;
              dpid_ = input.readInt64();
              break;
            }
            case 16: {
              bitField0_ |= 0x00000002;
              number_ = input.readInt64();
              break;
            }
            case 24: {
              bitField0_ |= 0x00000004;
              status_ = input.readInt32();
              break;
            }
            case 34: {
              bitField0_ |= 0x00000008;
              value_ = input.readBytes();
              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 {
        this.unknownFields = unknownFields.build();
        makeExtensionsImmutable();
      }
    }
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return net.onrc.onos.core.datastore.RCProtos.internal_static_ProtoBuffer_PortProperty_descriptor;
    }

    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return net.onrc.onos.core.datastore.RCProtos.internal_static_ProtoBuffer_PortProperty_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              net.onrc.onos.core.datastore.RCProtos.PortProperty.class, net.onrc.onos.core.datastore.RCProtos.PortProperty.Builder.class);
    }

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

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

    private int bitField0_;
    // required int64 dpid = 1;
    public static final int DPID_FIELD_NUMBER = 1;
    private long dpid_;
    /**
     * <code>required int64 dpid = 1;</code>
     */
    public boolean hasDpid() {
      return ((bitField0_ & 0x00000001) == 0x00000001);
    }
    /**
     * <code>required int64 dpid = 1;</code>
     */
    public long getDpid() {
      return dpid_;
    }

    // required int64 number = 2;
    public static final int NUMBER_FIELD_NUMBER = 2;
    private long number_;
    /**
     * <code>required int64 number = 2;</code>
     */
    public boolean hasNumber() {
      return ((bitField0_ & 0x00000002) == 0x00000002);
    }
    /**
     * <code>required int64 number = 2;</code>
     */
    public long getNumber() {
      return number_;
    }

    // required int32 status = 3;
    public static final int STATUS_FIELD_NUMBER = 3;
    private int status_;
    /**
     * <code>required int32 status = 3;</code>
     */
    public boolean hasStatus() {
      return ((bitField0_ & 0x00000004) == 0x00000004);
    }
    /**
     * <code>required int32 status = 3;</code>
     */
    public int getStatus() {
      return status_;
    }

    // optional bytes value = 4;
    public static final int VALUE_FIELD_NUMBER = 4;
    private com.google.protobuf.ByteString value_;
    /**
     * <code>optional bytes value = 4;</code>
     */
    public boolean hasValue() {
      return ((bitField0_ & 0x00000008) == 0x00000008);
    }
    /**
     * <code>optional bytes value = 4;</code>
     */
    public com.google.protobuf.ByteString getValue() {
      return value_;
    }

    private void initFields() {
      dpid_ = 0L;
      number_ = 0L;
      status_ = 0;
      value_ = com.google.protobuf.ByteString.EMPTY;
    }
    private byte memoizedIsInitialized = -1;
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized != -1) return isInitialized == 1;

      if (!hasDpid()) {
        memoizedIsInitialized = 0;
        return false;
      }
      if (!hasNumber()) {
        memoizedIsInitialized = 0;
        return false;
      }
      if (!hasStatus()) {
        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.writeInt64(1, dpid_);
      }
      if (((bitField0_ & 0x00000002) == 0x00000002)) {
        output.writeInt64(2, number_);
      }
      if (((bitField0_ & 0x00000004) == 0x00000004)) {
        output.writeInt32(3, status_);
      }
      if (((bitField0_ & 0x00000008) == 0x00000008)) {
        output.writeBytes(4, value_);
      }
      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
          .computeInt64Size(1, dpid_);
      }
      if (((bitField0_ & 0x00000002) == 0x00000002)) {
        size += com.google.protobuf.CodedOutputStream
          .computeInt64Size(2, number_);
      }
      if (((bitField0_ & 0x00000004) == 0x00000004)) {
        size += com.google.protobuf.CodedOutputStream
          .computeInt32Size(3, status_);
      }
      if (((bitField0_ & 0x00000008) == 0x00000008)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBytesSize(4, value_);
      }
      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 net.onrc.onos.core.datastore.RCProtos.PortProperty parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static net.onrc.onos.core.datastore.RCProtos.PortProperty parseFrom(
        com.google.protobuf.ByteString data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static net.onrc.onos.core.datastore.RCProtos.PortProperty parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static net.onrc.onos.core.datastore.RCProtos.PortProperty parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static net.onrc.onos.core.datastore.RCProtos.PortProperty parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static net.onrc.onos.core.datastore.RCProtos.PortProperty parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }
    public static net.onrc.onos.core.datastore.RCProtos.PortProperty parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input);
    }
    public static net.onrc.onos.core.datastore.RCProtos.PortProperty parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input, extensionRegistry);
    }
    public static net.onrc.onos.core.datastore.RCProtos.PortProperty parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static net.onrc.onos.core.datastore.RCProtos.PortProperty 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(net.onrc.onos.core.datastore.RCProtos.PortProperty 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 RCProtos.PortProperty}
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessage.Builder<Builder>
       implements net.onrc.onos.core.datastore.RCProtos.PortPropertyOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return net.onrc.onos.core.datastore.RCProtos.internal_static_ProtoBuffer_PortProperty_descriptor;
      }

      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
          internalGetFieldAccessorTable() {
        return net.onrc.onos.core.datastore.RCProtos.internal_static_ProtoBuffer_PortProperty_fieldAccessorTable
            .ensureFieldAccessorsInitialized(
                net.onrc.onos.core.datastore.RCProtos.PortProperty.class, net.onrc.onos.core.datastore.RCProtos.PortProperty.Builder.class);
      }

      // Construct using net.onrc.onos.core.datastore.RCProtos.PortProperty.newBuilder()
      private Builder() {
        maybeForceBuilderInitialization();
      }

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

      public Builder clear() {
        super.clear();
        dpid_ = 0L;
        bitField0_ = (bitField0_ & ~0x00000001);
        number_ = 0L;
        bitField0_ = (bitField0_ & ~0x00000002);
        status_ = 0;
        bitField0_ = (bitField0_ & ~0x00000004);
        value_ = com.google.protobuf.ByteString.EMPTY;
        bitField0_ = (bitField0_ & ~0x00000008);
        return this;
      }

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

      public com.google.protobuf.Descriptors.Descriptor
          getDescriptorForType() {
        return net.onrc.onos.core.datastore.RCProtos.internal_static_ProtoBuffer_PortProperty_descriptor;
      }

      public net.onrc.onos.core.datastore.RCProtos.PortProperty getDefaultInstanceForType() {
        return net.onrc.onos.core.datastore.RCProtos.PortProperty.getDefaultInstance();
      }

      public net.onrc.onos.core.datastore.RCProtos.PortProperty build() {
        net.onrc.onos.core.datastore.RCProtos.PortProperty result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      public net.onrc.onos.core.datastore.RCProtos.PortProperty buildPartial() {
        net.onrc.onos.core.datastore.RCProtos.PortProperty result = new net.onrc.onos.core.datastore.RCProtos.PortProperty(this);
        int from_bitField0_ = bitField0_;
        int to_bitField0_ = 0;
        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
          to_bitField0_ |= 0x00000001;
        }
        result.dpid_ = dpid_;
        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
          to_bitField0_ |= 0x00000002;
        }
        result.number_ = number_;
        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
          to_bitField0_ |= 0x00000004;
        }
        result.status_ = status_;
        if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
          to_bitField0_ |= 0x00000008;
        }
        result.value_ = value_;
        result.bitField0_ = to_bitField0_;
        onBuilt();
        return result;
      }

      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof net.onrc.onos.core.datastore.RCProtos.PortProperty) {
          return mergeFrom((net.onrc.onos.core.datastore.RCProtos.PortProperty)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(net.onrc.onos.core.datastore.RCProtos.PortProperty other) {
        if (other == net.onrc.onos.core.datastore.RCProtos.PortProperty.getDefaultInstance()) return this;
        if (other.hasDpid()) {
          setDpid(other.getDpid());
        }
        if (other.hasNumber()) {
          setNumber(other.getNumber());
        }
        if (other.hasStatus()) {
          setStatus(other.getStatus());
        }
        if (other.hasValue()) {
          setValue(other.getValue());
        }
        this.mergeUnknownFields(other.getUnknownFields());
        return this;
      }

      public final boolean isInitialized() {
        if (!hasDpid()) {
          
          return false;
        }
        if (!hasNumber()) {
          
          return false;
        }
        if (!hasStatus()) {
          
          return false;
        }
        return true;
      }

      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        net.onrc.onos.core.datastore.RCProtos.PortProperty parsedMessage = null;
        try {
          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          parsedMessage = (net.onrc.onos.core.datastore.RCProtos.PortProperty) e.getUnfinishedMessage();
          throw e;
        } finally {
          if (parsedMessage != null) {
            mergeFrom(parsedMessage);
          }
        }
        return this;
      }
      private int bitField0_;

      // required int64 dpid = 1;
      private long dpid_ ;
      /**
       * <code>required int64 dpid = 1;</code>
       */
      public boolean hasDpid() {
        return ((bitField0_ & 0x00000001) == 0x00000001);
      }
      /**
       * <code>required int64 dpid = 1;</code>
       */
      public long getDpid() {
        return dpid_;
      }
      /**
       * <code>required int64 dpid = 1;</code>
       */
      public Builder setDpid(long value) {
        bitField0_ |= 0x00000001;
        dpid_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required int64 dpid = 1;</code>
       */
      public Builder clearDpid() {
        bitField0_ = (bitField0_ & ~0x00000001);
        dpid_ = 0L;
        onChanged();
        return this;
      }

      // required int64 number = 2;
      private long number_ ;
      /**
       * <code>required int64 number = 2;</code>
       */
      public boolean hasNumber() {
        return ((bitField0_ & 0x00000002) == 0x00000002);
      }
      /**
       * <code>required int64 number = 2;</code>
       */
      public long getNumber() {
        return number_;
      }
      /**
       * <code>required int64 number = 2;</code>
       */
      public Builder setNumber(long value) {
        bitField0_ |= 0x00000002;
        number_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required int64 number = 2;</code>
       */
      public Builder clearNumber() {
        bitField0_ = (bitField0_ & ~0x00000002);
        number_ = 0L;
        onChanged();
        return this;
      }

      // required int32 status = 3;
      private int status_ ;
      /**
       * <code>required int32 status = 3;</code>
       */
      public boolean hasStatus() {
        return ((bitField0_ & 0x00000004) == 0x00000004);
      }
      /**
       * <code>required int32 status = 3;</code>
       */
      public int getStatus() {
        return status_;
      }
      /**
       * <code>required int32 status = 3;</code>
       */
      public Builder setStatus(int value) {
        bitField0_ |= 0x00000004;
        status_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required int32 status = 3;</code>
       */
      public Builder clearStatus() {
        bitField0_ = (bitField0_ & ~0x00000004);
        status_ = 0;
        onChanged();
        return this;
      }

      // optional bytes value = 4;
      private com.google.protobuf.ByteString value_ = com.google.protobuf.ByteString.EMPTY;
      /**
       * <code>optional bytes value = 4;</code>
       */
      public boolean hasValue() {
        return ((bitField0_ & 0x00000008) == 0x00000008);
      }
      /**
       * <code>optional bytes value = 4;</code>
       */
      public com.google.protobuf.ByteString getValue() {
        return value_;
      }
      /**
       * <code>optional bytes value = 4;</code>
       */
      public Builder setValue(com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000008;
        value_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>optional bytes value = 4;</code>
       */
      public Builder clearValue() {
        bitField0_ = (bitField0_ & ~0x00000008);
        value_ = getDefaultInstance().getValue();
        onChanged();
        return this;
      }

      // @@protoc_insertion_point(builder_scope:RCProtos.PortProperty)
    }

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

    // @@protoc_insertion_point(class_scope:RCProtos.PortProperty)
  }

  public interface LinkPropertyOrBuilder
      extends com.google.protobuf.MessageOrBuilder {

    // required bytes srcSwId = 1;
    /**
     * <code>required bytes srcSwId = 1;</code>
     */
    boolean hasSrcSwId();
    /**
     * <code>required bytes srcSwId = 1;</code>
     */
    com.google.protobuf.ByteString getSrcSwId();

    // required bytes srcPortId = 2;
    /**
     * <code>required bytes srcPortId = 2;</code>
     */
    boolean hasSrcPortId();
    /**
     * <code>required bytes srcPortId = 2;</code>
     */
    com.google.protobuf.ByteString getSrcPortId();

    // required bytes dstSwId = 3;
    /**
     * <code>required bytes dstSwId = 3;</code>
     */
    boolean hasDstSwId();
    /**
     * <code>required bytes dstSwId = 3;</code>
     */
    com.google.protobuf.ByteString getDstSwId();

    // required bytes dstPortId = 4;
    /**
     * <code>required bytes dstPortId = 4;</code>
     */
    boolean hasDstPortId();
    /**
     * <code>required bytes dstPortId = 4;</code>
     */
    com.google.protobuf.ByteString getDstPortId();

    // required int32 status = 5;
    /**
     * <code>required int32 status = 5;</code>
     */
    boolean hasStatus();
    /**
     * <code>required int32 status = 5;</code>
     */
    int getStatus();

    // optional bytes value = 6;
    /**
     * <code>optional bytes value = 6;</code>
     */
    boolean hasValue();
    /**
     * <code>optional bytes value = 6;</code>
     */
    com.google.protobuf.ByteString getValue();
  }
  /**
   * Protobuf type {@code RCProtos.LinkProperty}
   */
  public static final class LinkProperty extends
      com.google.protobuf.GeneratedMessage
      implements LinkPropertyOrBuilder {
    // Use LinkProperty.newBuilder() to construct.
    private LinkProperty(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
      super(builder);
      this.unknownFields = builder.getUnknownFields();
    }
    private LinkProperty(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }

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

    public LinkProperty getDefaultInstanceForType() {
      return defaultInstance;
    }

    private final com.google.protobuf.UnknownFieldSet unknownFields;
    @java.lang.Override
    public final com.google.protobuf.UnknownFieldSet
        getUnknownFields() {
      return this.unknownFields;
    }
    private LinkProperty(
        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;
              srcSwId_ = input.readBytes();
              break;
            }
            case 18: {
              bitField0_ |= 0x00000002;
              srcPortId_ = input.readBytes();
              break;
            }
            case 26: {
              bitField0_ |= 0x00000004;
              dstSwId_ = input.readBytes();
              break;
            }
            case 34: {
              bitField0_ |= 0x00000008;
              dstPortId_ = input.readBytes();
              break;
            }
            case 40: {
              bitField0_ |= 0x00000010;
              status_ = input.readInt32();
              break;
            }
            case 50: {
              bitField0_ |= 0x00000020;
              value_ = input.readBytes();
              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 {
        this.unknownFields = unknownFields.build();
        makeExtensionsImmutable();
      }
    }
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return net.onrc.onos.core.datastore.RCProtos.internal_static_ProtoBuffer_LinkProperty_descriptor;
    }

    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return net.onrc.onos.core.datastore.RCProtos.internal_static_ProtoBuffer_LinkProperty_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              net.onrc.onos.core.datastore.RCProtos.LinkProperty.class, net.onrc.onos.core.datastore.RCProtos.LinkProperty.Builder.class);
    }

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

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

    private int bitField0_;
    // required bytes srcSwId = 1;
    public static final int SRCSWID_FIELD_NUMBER = 1;
    private com.google.protobuf.ByteString srcSwId_;
    /**
     * <code>required bytes srcSwId = 1;</code>
     */
    public boolean hasSrcSwId() {
      return ((bitField0_ & 0x00000001) == 0x00000001);
    }
    /**
     * <code>required bytes srcSwId = 1;</code>
     */
    public com.google.protobuf.ByteString getSrcSwId() {
      return srcSwId_;
    }

    // required bytes srcPortId = 2;
    public static final int SRCPORTID_FIELD_NUMBER = 2;
    private com.google.protobuf.ByteString srcPortId_;
    /**
     * <code>required bytes srcPortId = 2;</code>
     */
    public boolean hasSrcPortId() {
      return ((bitField0_ & 0x00000002) == 0x00000002);
    }
    /**
     * <code>required bytes srcPortId = 2;</code>
     */
    public com.google.protobuf.ByteString getSrcPortId() {
      return srcPortId_;
    }

    // required bytes dstSwId = 3;
    public static final int DSTSWID_FIELD_NUMBER = 3;
    private com.google.protobuf.ByteString dstSwId_;
    /**
     * <code>required bytes dstSwId = 3;</code>
     */
    public boolean hasDstSwId() {
      return ((bitField0_ & 0x00000004) == 0x00000004);
    }
    /**
     * <code>required bytes dstSwId = 3;</code>
     */
    public com.google.protobuf.ByteString getDstSwId() {
      return dstSwId_;
    }

    // required bytes dstPortId = 4;
    public static final int DSTPORTID_FIELD_NUMBER = 4;
    private com.google.protobuf.ByteString dstPortId_;
    /**
     * <code>required bytes dstPortId = 4;</code>
     */
    public boolean hasDstPortId() {
      return ((bitField0_ & 0x00000008) == 0x00000008);
    }
    /**
     * <code>required bytes dstPortId = 4;</code>
     */
    public com.google.protobuf.ByteString getDstPortId() {
      return dstPortId_;
    }

    // required int32 status = 5;
    public static final int STATUS_FIELD_NUMBER = 5;
    private int status_;
    /**
     * <code>required int32 status = 5;</code>
     */
    public boolean hasStatus() {
      return ((bitField0_ & 0x00000010) == 0x00000010);
    }
    /**
     * <code>required int32 status = 5;</code>
     */
    public int getStatus() {
      return status_;
    }

    // optional bytes value = 6;
    public static final int VALUE_FIELD_NUMBER = 6;
    private com.google.protobuf.ByteString value_;
    /**
     * <code>optional bytes value = 6;</code>
     */
    public boolean hasValue() {
      return ((bitField0_ & 0x00000020) == 0x00000020);
    }
    /**
     * <code>optional bytes value = 6;</code>
     */
    public com.google.protobuf.ByteString getValue() {
      return value_;
    }

    private void initFields() {
      srcSwId_ = com.google.protobuf.ByteString.EMPTY;
      srcPortId_ = com.google.protobuf.ByteString.EMPTY;
      dstSwId_ = com.google.protobuf.ByteString.EMPTY;
      dstPortId_ = com.google.protobuf.ByteString.EMPTY;
      status_ = 0;
      value_ = com.google.protobuf.ByteString.EMPTY;
    }
    private byte memoizedIsInitialized = -1;
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized != -1) return isInitialized == 1;

      if (!hasSrcSwId()) {
        memoizedIsInitialized = 0;
        return false;
      }
      if (!hasSrcPortId()) {
        memoizedIsInitialized = 0;
        return false;
      }
      if (!hasDstSwId()) {
        memoizedIsInitialized = 0;
        return false;
      }
      if (!hasDstPortId()) {
        memoizedIsInitialized = 0;
        return false;
      }
      if (!hasStatus()) {
        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, srcSwId_);
      }
      if (((bitField0_ & 0x00000002) == 0x00000002)) {
        output.writeBytes(2, srcPortId_);
      }
      if (((bitField0_ & 0x00000004) == 0x00000004)) {
        output.writeBytes(3, dstSwId_);
      }
      if (((bitField0_ & 0x00000008) == 0x00000008)) {
        output.writeBytes(4, dstPortId_);
      }
      if (((bitField0_ & 0x00000010) == 0x00000010)) {
        output.writeInt32(5, status_);
      }
      if (((bitField0_ & 0x00000020) == 0x00000020)) {
        output.writeBytes(6, value_);
      }
      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, srcSwId_);
      }
      if (((bitField0_ & 0x00000002) == 0x00000002)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBytesSize(2, srcPortId_);
      }
      if (((bitField0_ & 0x00000004) == 0x00000004)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBytesSize(3, dstSwId_);
      }
      if (((bitField0_ & 0x00000008) == 0x00000008)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBytesSize(4, dstPortId_);
      }
      if (((bitField0_ & 0x00000010) == 0x00000010)) {
        size += com.google.protobuf.CodedOutputStream
          .computeInt32Size(5, status_);
      }
      if (((bitField0_ & 0x00000020) == 0x00000020)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBytesSize(6, value_);
      }
      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 net.onrc.onos.core.datastore.RCProtos.LinkProperty parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static net.onrc.onos.core.datastore.RCProtos.LinkProperty parseFrom(
        com.google.protobuf.ByteString data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static net.onrc.onos.core.datastore.RCProtos.LinkProperty parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static net.onrc.onos.core.datastore.RCProtos.LinkProperty parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static net.onrc.onos.core.datastore.RCProtos.LinkProperty parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static net.onrc.onos.core.datastore.RCProtos.LinkProperty parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }
    public static net.onrc.onos.core.datastore.RCProtos.LinkProperty parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input);
    }
    public static net.onrc.onos.core.datastore.RCProtos.LinkProperty parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input, extensionRegistry);
    }
    public static net.onrc.onos.core.datastore.RCProtos.LinkProperty parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static net.onrc.onos.core.datastore.RCProtos.LinkProperty 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(net.onrc.onos.core.datastore.RCProtos.LinkProperty 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 RCProtos.LinkProperty}
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessage.Builder<Builder>
       implements net.onrc.onos.core.datastore.RCProtos.LinkPropertyOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return net.onrc.onos.core.datastore.RCProtos.internal_static_ProtoBuffer_LinkProperty_descriptor;
      }

      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
          internalGetFieldAccessorTable() {
        return net.onrc.onos.core.datastore.RCProtos.internal_static_ProtoBuffer_LinkProperty_fieldAccessorTable
            .ensureFieldAccessorsInitialized(
                net.onrc.onos.core.datastore.RCProtos.LinkProperty.class, net.onrc.onos.core.datastore.RCProtos.LinkProperty.Builder.class);
      }

      // Construct using net.onrc.onos.core.datastore.RCProtos.LinkProperty.newBuilder()
      private Builder() {
        maybeForceBuilderInitialization();
      }

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

      public Builder clear() {
        super.clear();
        srcSwId_ = com.google.protobuf.ByteString.EMPTY;
        bitField0_ = (bitField0_ & ~0x00000001);
        srcPortId_ = com.google.protobuf.ByteString.EMPTY;
        bitField0_ = (bitField0_ & ~0x00000002);
        dstSwId_ = com.google.protobuf.ByteString.EMPTY;
        bitField0_ = (bitField0_ & ~0x00000004);
        dstPortId_ = com.google.protobuf.ByteString.EMPTY;
        bitField0_ = (bitField0_ & ~0x00000008);
        status_ = 0;
        bitField0_ = (bitField0_ & ~0x00000010);
        value_ = com.google.protobuf.ByteString.EMPTY;
        bitField0_ = (bitField0_ & ~0x00000020);
        return this;
      }

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

      public com.google.protobuf.Descriptors.Descriptor
          getDescriptorForType() {
        return net.onrc.onos.core.datastore.RCProtos.internal_static_ProtoBuffer_LinkProperty_descriptor;
      }

      public net.onrc.onos.core.datastore.RCProtos.LinkProperty getDefaultInstanceForType() {
        return net.onrc.onos.core.datastore.RCProtos.LinkProperty.getDefaultInstance();
      }

      public net.onrc.onos.core.datastore.RCProtos.LinkProperty build() {
        net.onrc.onos.core.datastore.RCProtos.LinkProperty result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      public net.onrc.onos.core.datastore.RCProtos.LinkProperty buildPartial() {
        net.onrc.onos.core.datastore.RCProtos.LinkProperty result = new net.onrc.onos.core.datastore.RCProtos.LinkProperty(this);
        int from_bitField0_ = bitField0_;
        int to_bitField0_ = 0;
        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
          to_bitField0_ |= 0x00000001;
        }
        result.srcSwId_ = srcSwId_;
        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
          to_bitField0_ |= 0x00000002;
        }
        result.srcPortId_ = srcPortId_;
        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
          to_bitField0_ |= 0x00000004;
        }
        result.dstSwId_ = dstSwId_;
        if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
          to_bitField0_ |= 0x00000008;
        }
        result.dstPortId_ = dstPortId_;
        if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
          to_bitField0_ |= 0x00000010;
        }
        result.status_ = status_;
        if (((from_bitField0_ & 0x00000020) == 0x00000020)) {
          to_bitField0_ |= 0x00000020;
        }
        result.value_ = value_;
        result.bitField0_ = to_bitField0_;
        onBuilt();
        return result;
      }

      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof net.onrc.onos.core.datastore.RCProtos.LinkProperty) {
          return mergeFrom((net.onrc.onos.core.datastore.RCProtos.LinkProperty)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(net.onrc.onos.core.datastore.RCProtos.LinkProperty other) {
        if (other == net.onrc.onos.core.datastore.RCProtos.LinkProperty.getDefaultInstance()) return this;
        if (other.hasSrcSwId()) {
          setSrcSwId(other.getSrcSwId());
        }
        if (other.hasSrcPortId()) {
          setSrcPortId(other.getSrcPortId());
        }
        if (other.hasDstSwId()) {
          setDstSwId(other.getDstSwId());
        }
        if (other.hasDstPortId()) {
          setDstPortId(other.getDstPortId());
        }
        if (other.hasStatus()) {
          setStatus(other.getStatus());
        }
        if (other.hasValue()) {
          setValue(other.getValue());
        }
        this.mergeUnknownFields(other.getUnknownFields());
        return this;
      }

      public final boolean isInitialized() {
        if (!hasSrcSwId()) {
          
          return false;
        }
        if (!hasSrcPortId()) {
          
          return false;
        }
        if (!hasDstSwId()) {
          
          return false;
        }
        if (!hasDstPortId()) {
          
          return false;
        }
        if (!hasStatus()) {
          
          return false;
        }
        return true;
      }

      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        net.onrc.onos.core.datastore.RCProtos.LinkProperty parsedMessage = null;
        try {
          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          parsedMessage = (net.onrc.onos.core.datastore.RCProtos.LinkProperty) e.getUnfinishedMessage();
          throw e;
        } finally {
          if (parsedMessage != null) {
            mergeFrom(parsedMessage);
          }
        }
        return this;
      }
      private int bitField0_;

      // required bytes srcSwId = 1;
      private com.google.protobuf.ByteString srcSwId_ = com.google.protobuf.ByteString.EMPTY;
      /**
       * <code>required bytes srcSwId = 1;</code>
       */
      public boolean hasSrcSwId() {
        return ((bitField0_ & 0x00000001) == 0x00000001);
      }
      /**
       * <code>required bytes srcSwId = 1;</code>
       */
      public com.google.protobuf.ByteString getSrcSwId() {
        return srcSwId_;
      }
      /**
       * <code>required bytes srcSwId = 1;</code>
       */
      public Builder setSrcSwId(com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000001;
        srcSwId_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required bytes srcSwId = 1;</code>
       */
      public Builder clearSrcSwId() {
        bitField0_ = (bitField0_ & ~0x00000001);
        srcSwId_ = getDefaultInstance().getSrcSwId();
        onChanged();
        return this;
      }

      // required bytes srcPortId = 2;
      private com.google.protobuf.ByteString srcPortId_ = com.google.protobuf.ByteString.EMPTY;
      /**
       * <code>required bytes srcPortId = 2;</code>
       */
      public boolean hasSrcPortId() {
        return ((bitField0_ & 0x00000002) == 0x00000002);
      }
      /**
       * <code>required bytes srcPortId = 2;</code>
       */
      public com.google.protobuf.ByteString getSrcPortId() {
        return srcPortId_;
      }
      /**
       * <code>required bytes srcPortId = 2;</code>
       */
      public Builder setSrcPortId(com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000002;
        srcPortId_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required bytes srcPortId = 2;</code>
       */
      public Builder clearSrcPortId() {
        bitField0_ = (bitField0_ & ~0x00000002);
        srcPortId_ = getDefaultInstance().getSrcPortId();
        onChanged();
        return this;
      }

      // required bytes dstSwId = 3;
      private com.google.protobuf.ByteString dstSwId_ = com.google.protobuf.ByteString.EMPTY;
      /**
       * <code>required bytes dstSwId = 3;</code>
       */
      public boolean hasDstSwId() {
        return ((bitField0_ & 0x00000004) == 0x00000004);
      }
      /**
       * <code>required bytes dstSwId = 3;</code>
       */
      public com.google.protobuf.ByteString getDstSwId() {
        return dstSwId_;
      }
      /**
       * <code>required bytes dstSwId = 3;</code>
       */
      public Builder setDstSwId(com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000004;
        dstSwId_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required bytes dstSwId = 3;</code>
       */
      public Builder clearDstSwId() {
        bitField0_ = (bitField0_ & ~0x00000004);
        dstSwId_ = getDefaultInstance().getDstSwId();
        onChanged();
        return this;
      }

      // required bytes dstPortId = 4;
      private com.google.protobuf.ByteString dstPortId_ = com.google.protobuf.ByteString.EMPTY;
      /**
       * <code>required bytes dstPortId = 4;</code>
       */
      public boolean hasDstPortId() {
        return ((bitField0_ & 0x00000008) == 0x00000008);
      }
      /**
       * <code>required bytes dstPortId = 4;</code>
       */
      public com.google.protobuf.ByteString getDstPortId() {
        return dstPortId_;
      }
      /**
       * <code>required bytes dstPortId = 4;</code>
       */
      public Builder setDstPortId(com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000008;
        dstPortId_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required bytes dstPortId = 4;</code>
       */
      public Builder clearDstPortId() {
        bitField0_ = (bitField0_ & ~0x00000008);
        dstPortId_ = getDefaultInstance().getDstPortId();
        onChanged();
        return this;
      }

      // required int32 status = 5;
      private int status_ ;
      /**
       * <code>required int32 status = 5;</code>
       */
      public boolean hasStatus() {
        return ((bitField0_ & 0x00000010) == 0x00000010);
      }
      /**
       * <code>required int32 status = 5;</code>
       */
      public int getStatus() {
        return status_;
      }
      /**
       * <code>required int32 status = 5;</code>
       */
      public Builder setStatus(int value) {
        bitField0_ |= 0x00000010;
        status_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required int32 status = 5;</code>
       */
      public Builder clearStatus() {
        bitField0_ = (bitField0_ & ~0x00000010);
        status_ = 0;
        onChanged();
        return this;
      }

      // optional bytes value = 6;
      private com.google.protobuf.ByteString value_ = com.google.protobuf.ByteString.EMPTY;
      /**
       * <code>optional bytes value = 6;</code>
       */
      public boolean hasValue() {
        return ((bitField0_ & 0x00000020) == 0x00000020);
      }
      /**
       * <code>optional bytes value = 6;</code>
       */
      public com.google.protobuf.ByteString getValue() {
        return value_;
      }
      /**
       * <code>optional bytes value = 6;</code>
       */
      public Builder setValue(com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000020;
        value_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>optional bytes value = 6;</code>
       */
      public Builder clearValue() {
        bitField0_ = (bitField0_ & ~0x00000020);
        value_ = getDefaultInstance().getValue();
        onChanged();
        return this;
      }

      // @@protoc_insertion_point(builder_scope:RCProtos.LinkProperty)
    }

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

    // @@protoc_insertion_point(class_scope:RCProtos.LinkProperty)
  }

  private static com.google.protobuf.Descriptors.Descriptor
    internal_static_ProtoBuffer_SwitchProperty_descriptor;
  private static
    com.google.protobuf.GeneratedMessage.FieldAccessorTable
      internal_static_ProtoBuffer_SwitchProperty_fieldAccessorTable;
  private static com.google.protobuf.Descriptors.Descriptor
    internal_static_ProtoBuffer_PortProperty_descriptor;
  private static
    com.google.protobuf.GeneratedMessage.FieldAccessorTable
      internal_static_ProtoBuffer_PortProperty_fieldAccessorTable;
  private static com.google.protobuf.Descriptors.Descriptor
    internal_static_ProtoBuffer_LinkProperty_descriptor;
  private static
    com.google.protobuf.GeneratedMessage.FieldAccessorTable
      internal_static_ProtoBuffer_LinkProperty_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\027protobuf/ramcloud.proto\022\013ProtoBuffer\"=" +
      "\n\016SwitchProperty\022\014\n\004dpid\030\001 \002(\003\022\016\n\006status" +
      "\030\002 \002(\005\022\r\n\005value\030\003 \001(\014\"K\n\014PortProperty\022\014\n" +
      "\004dpid\030\001 \002(\003\022\016\n\006number\030\002 \002(\003\022\016\n\006status\030\003 " +
      "\002(\005\022\r\n\005value\030\004 \001(\014\"u\n\014LinkProperty\022\017\n\007sr" +
      "cSwId\030\001 \002(\014\022\021\n\tsrcPortId\030\002 \002(\014\022\017\n\007dstSwI" +
      "d\030\003 \002(\014\022\021\n\tdstPortId\030\004 \002(\014\022\016\n\006status\030\005 \002" +
      "(\005\022\r\n\005value\030\006 \001(\014B&\n\027net.onrc.onos.datas" +
      "toreB\013ProtoBuffer"
    };
    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_ProtoBuffer_SwitchProperty_descriptor =
            getDescriptor().getMessageTypes().get(0);
          internal_static_ProtoBuffer_SwitchProperty_fieldAccessorTable = new
            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
              internal_static_ProtoBuffer_SwitchProperty_descriptor,
              new java.lang.String[] { "Dpid", "Status", "Value", });
          internal_static_ProtoBuffer_PortProperty_descriptor =
            getDescriptor().getMessageTypes().get(1);
          internal_static_ProtoBuffer_PortProperty_fieldAccessorTable = new
            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
              internal_static_ProtoBuffer_PortProperty_descriptor,
              new java.lang.String[] { "Dpid", "Number", "Status", "Value", });
          internal_static_ProtoBuffer_LinkProperty_descriptor =
            getDescriptor().getMessageTypes().get(2);
          internal_static_ProtoBuffer_LinkProperty_fieldAccessorTable = new
            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
              internal_static_ProtoBuffer_LinkProperty_descriptor,
              new java.lang.String[] { "SrcSwId", "SrcPortId", "DstSwId", "DstPortId", "Status", "Value", });
          return null;
        }
      };
    com.google.protobuf.Descriptors.FileDescriptor
      .internalBuildGeneratedFileFrom(descriptorData,
        new com.google.protobuf.Descriptors.FileDescriptor[] {
        }, assigner);
  }

  // @@protoc_insertion_point(outer_class_scope)
}
