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

package net.onrc.onos.core.datastore.serializers;

public final class Topology {
  private Topology() {}
  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 topology.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 mutableBitField0 = 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.serializers.Topology.internalStaticTopologySwitchPropertyDescriptor;
    }

    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return net.onrc.onos.core.datastore.serializers.Topology.internalStaticTopologySwitchPropertyFieldAccessorTable
          .ensureFieldAccessorsInitialized(
              net.onrc.onos.core.datastore.serializers.Topology.SwitchProperty.class, net.onrc.onos.core.datastore.serializers.Topology.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.serializers.Topology.SwitchProperty parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static net.onrc.onos.core.datastore.serializers.Topology.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.serializers.Topology.SwitchProperty parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static net.onrc.onos.core.datastore.serializers.Topology.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.serializers.Topology.SwitchProperty parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static net.onrc.onos.core.datastore.serializers.Topology.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.serializers.Topology.SwitchProperty parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input);
    }
    public static net.onrc.onos.core.datastore.serializers.Topology.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.serializers.Topology.SwitchProperty parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static net.onrc.onos.core.datastore.serializers.Topology.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.serializers.Topology.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 topology.SwitchProperty}
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessage.Builder<Builder>
       implements net.onrc.onos.core.datastore.serializers.Topology.SwitchPropertyOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return net.onrc.onos.core.datastore.serializers.Topology.internalStaticTopologySwitchPropertyDescriptor;
      }

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

      // Construct using net.onrc.onos.core.datastore.serializers.Topology.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.serializers.Topology.internalStaticTopologySwitchPropertyDescriptor;
      }

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

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

      public net.onrc.onos.core.datastore.serializers.Topology.SwitchProperty buildPartial() {
        net.onrc.onos.core.datastore.serializers.Topology.SwitchProperty result = new net.onrc.onos.core.datastore.serializers.Topology.SwitchProperty(this);
        int fromBitField0 = bitField0;
        int toBitField0 = 0;
        if (((fromBitField0 & 0x00000001) == 0x00000001)) {
          toBitField0 |= 0x00000001;
        }
        result.dpid = dpid;
        if (((fromBitField0 & 0x00000002) == 0x00000002)) {
          toBitField0 |= 0x00000002;
        }
        result.status = status;
        if (((fromBitField0 & 0x00000004) == 0x00000004)) {
          toBitField0 |= 0x00000004;
        }
        result.value = value;
        result.bitField0 = toBitField0;
        onBuilt();
        return result;
      }

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

      public Builder mergeFrom(net.onrc.onos.core.datastore.serializers.Topology.SwitchProperty other) {
        if (other == net.onrc.onos.core.datastore.serializers.Topology.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.serializers.Topology.SwitchProperty parsedMessage = null;
        try {
          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          parsedMessage = (net.onrc.onos.core.datastore.serializers.Topology.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;
        this.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:topology.SwitchProperty)
    }

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

    // @@protoc_insertion_point(class_scope:topology.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 topology.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 mutableBitField0 = 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.serializers.Topology.internalStaticTopologyPortPropertyDescriptor;
    }

    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return net.onrc.onos.core.datastore.serializers.Topology.internalStaticTopologyPortPropertyFieldAccessorTable
          .ensureFieldAccessorsInitialized(
              net.onrc.onos.core.datastore.serializers.Topology.PortProperty.class, net.onrc.onos.core.datastore.serializers.Topology.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.serializers.Topology.PortProperty parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static net.onrc.onos.core.datastore.serializers.Topology.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.serializers.Topology.PortProperty parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static net.onrc.onos.core.datastore.serializers.Topology.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.serializers.Topology.PortProperty parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static net.onrc.onos.core.datastore.serializers.Topology.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.serializers.Topology.PortProperty parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input);
    }
    public static net.onrc.onos.core.datastore.serializers.Topology.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.serializers.Topology.PortProperty parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static net.onrc.onos.core.datastore.serializers.Topology.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.serializers.Topology.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 topology.PortProperty}
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessage.Builder<Builder>
       implements net.onrc.onos.core.datastore.serializers.Topology.PortPropertyOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return net.onrc.onos.core.datastore.serializers.Topology.internalStaticTopologyPortPropertyDescriptor;
      }

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

      // Construct using net.onrc.onos.core.datastore.serializers.Topology.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.serializers.Topology.internalStaticTopologyPortPropertyDescriptor;
      }

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

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

      public net.onrc.onos.core.datastore.serializers.Topology.PortProperty buildPartial() {
        net.onrc.onos.core.datastore.serializers.Topology.PortProperty result = new net.onrc.onos.core.datastore.serializers.Topology.PortProperty(this);
        int bitField0 = this.bitField0;
        int toBitField0 = 0;
        if (((bitField0 & 0x00000001) == 0x00000001)) {
          toBitField0 |= 0x00000001;
        }
        result.dpid = dpid;
        if (((bitField0 & 0x00000002) == 0x00000002)) {
          toBitField0 |= 0x00000002;
        }
        result.number = number;
        if (((bitField0 & 0x00000004) == 0x00000004)) {
          toBitField0 |= 0x00000004;
        }
        result.status = status;
        if (((bitField0 & 0x00000008) == 0x00000008)) {
          toBitField0 |= 0x00000008;
        }
        result.value = value;
        result.bitField0 = toBitField0;
        onBuilt();
        return result;
      }

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

      public Builder mergeFrom(net.onrc.onos.core.datastore.serializers.Topology.PortProperty other) {
        if (other == net.onrc.onos.core.datastore.serializers.Topology.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.serializers.Topology.PortProperty parsedMessage = null;
        try {
          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          parsedMessage = (net.onrc.onos.core.datastore.serializers.Topology.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;
        this.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:topology.PortProperty)
    }

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

    // @@protoc_insertion_point(class_scope:topology.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 topology.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 mutableBitField0 = 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.serializers.Topology.internalStaticTopologyLinkPropertyDescriptor;
    }

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

    public static final 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.serializers.Topology.LinkProperty parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static net.onrc.onos.core.datastore.serializers.Topology.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.serializers.Topology.LinkProperty parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static net.onrc.onos.core.datastore.serializers.Topology.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.serializers.Topology.LinkProperty parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static net.onrc.onos.core.datastore.serializers.Topology.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.serializers.Topology.LinkProperty parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input);
    }
    public static net.onrc.onos.core.datastore.serializers.Topology.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.serializers.Topology.LinkProperty parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static net.onrc.onos.core.datastore.serializers.Topology.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.serializers.Topology.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 topology.LinkProperty}
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessage.Builder<Builder>
       implements net.onrc.onos.core.datastore.serializers.Topology.LinkPropertyOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return net.onrc.onos.core.datastore.serializers.Topology.internalStaticTopologyLinkPropertyDescriptor;
      }

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

      // Construct using net.onrc.onos.core.datastore.serializers.Topology.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.serializers.Topology.internalStaticTopologyLinkPropertyDescriptor;
      }

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

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

      public net.onrc.onos.core.datastore.serializers.Topology.LinkProperty buildPartial() {
        net.onrc.onos.core.datastore.serializers.Topology.LinkProperty result = new net.onrc.onos.core.datastore.serializers.Topology.LinkProperty(this);
        int fromBitField0 = bitField0;
        int toBitField0 = 0;
        if (((fromBitField0 & 0x00000001) == 0x00000001)) {
          toBitField0 |= 0x00000001;
        }
        result.srcSwId = srcSwId;
        if (((fromBitField0 & 0x00000002) == 0x00000002)) {
          toBitField0 |= 0x00000002;
        }
        result.srcPortId = srcPortId;
        if (((fromBitField0 & 0x00000004) == 0x00000004)) {
          toBitField0 |= 0x00000004;
        }
        result.dstSwId = dstSwId;
        if (((fromBitField0 & 0x00000008) == 0x00000008)) {
          toBitField0 |= 0x00000008;
        }
        result.dstPortId = dstPortId;
        if (((fromBitField0 & 0x00000010) == 0x00000010)) {
          toBitField0 |= 0x00000010;
        }
        result.status = status;
        if (((fromBitField0 & 0x00000020) == 0x00000020)) {
          toBitField0 |= 0x00000020;
        }
        result.value = value;
        result.bitField0 = toBitField0;
        onBuilt();
        return result;
      }

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

      public Builder mergeFrom(net.onrc.onos.core.datastore.serializers.Topology.LinkProperty other) {
        if (other == net.onrc.onos.core.datastore.serializers.Topology.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.serializers.Topology.LinkProperty parsedMessage = null;
        try {
          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          parsedMessage = (net.onrc.onos.core.datastore.serializers.Topology.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;
        this.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:topology.LinkProperty)
    }

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

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

  private static com.google.protobuf.Descriptors.Descriptor
          internalStaticTopologySwitchPropertyDescriptor;
  private static
    com.google.protobuf.GeneratedMessage.FieldAccessorTable
          internalStaticTopologySwitchPropertyFieldAccessorTable;
  private static com.google.protobuf.Descriptors.Descriptor
          internalStaticTopologyPortPropertyDescriptor;
  private static
    com.google.protobuf.GeneratedMessage.FieldAccessorTable
          internalStaticTopologyPortPropertyFieldAccessorTable;
  private static com.google.protobuf.Descriptors.Descriptor
          internalStaticTopologyLinkPropertyDescriptor;
  private static
    com.google.protobuf.GeneratedMessage.FieldAccessorTable
          internalStaticTopologyLinkPropertyFieldAccessorTable;

  public static com.google.protobuf.Descriptors.FileDescriptor
      getDescriptor() {
    return descriptor;
  }
  private static com.google.protobuf.Descriptors.FileDescriptor
      descriptor;
  static {
    java.lang.String[] descriptorData = {
      "\n\016topology.proto\022\010topology\"=\n\016SwitchProp" +
      "erty\022\014\n\004dpid\030\001 \002(\003\022\016\n\006status\030\002 \002(\005\022\r\n\005va" +
      "lue\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\007srcSwId\030\001 \002(\014\022" +
      "\021\n\tsrcPortId\030\002 \002(\014\022\017\n\007dstSwId\030\003 \002(\014\022\021\n\td" +
      "stPortId\030\004 \002(\014\022\016\n\006status\030\005 \002(\005\022\r\n\005value\030" +
      "\006 \001(\014B4\n(net.onrc.onos.core.datastore.se" +
      "rializersB\010Topology"
    };
    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;
          internalStaticTopologySwitchPropertyDescriptor =
            getDescriptor().getMessageTypes().get(0);
          internalStaticTopologySwitchPropertyFieldAccessorTable = new
            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
                  internalStaticTopologySwitchPropertyDescriptor,
              new java.lang.String[] { "Dpid", "Status", "Value", });
          internalStaticTopologyPortPropertyDescriptor =
            getDescriptor().getMessageTypes().get(1);
          internalStaticTopologyPortPropertyFieldAccessorTable = new
            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
                  internalStaticTopologyPortPropertyDescriptor,
              new java.lang.String[] { "Dpid", "Number", "Status", "Value", });
          internalStaticTopologyLinkPropertyDescriptor =
            getDescriptor().getMessageTypes().get(2);
          internalStaticTopologyLinkPropertyFieldAccessorTable = new
            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
                  internalStaticTopologyLinkPropertyDescriptor,
              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)
}
