@Override
  public boolean equals(final Object obj) {
    if (this == obj) {
      return true;
    }

    if (!(obj instanceof PartitionAttributesImpl)) {
      return false;
    }

    PartitionAttributesImpl other = (PartitionAttributesImpl) obj;

    if (this.redundancy != other.getRedundantCopies()
        || getLocalMaxMemory() != other.getLocalMaxMemory()
        || this.offHeap != other.getOffHeap()
        || this.totalNumBuckets != other.getTotalNumBuckets()
        || this.totalMaxMemory != other.getTotalMaxMemory()
        || this.startupRecoveryDelay != other.getStartupRecoveryDelay()
        || this.recoveryDelay != other.getRecoveryDelay()
        //          || ! this.localProperties.equals(other.getLocalProperties())
        //          || ! this.globalProperties.equals(other.getGlobalProperties())
        || ((this.partitionResolver == null) != (other.getPartitionResolver() == null))
        || (this.partitionResolver != null
            && !this.partitionResolver.equals(other.getPartitionResolver()))
        || ((this.colocatedRegionName == null) != (other.getColocatedWith() == null))
        || (this.colocatedRegionName != null
            && !this.colocatedRegionName.equals(other.getColocatedWith()))
        || ((this.fixedPAttrs == null) != (other.getFixedPartitionAttributes() == null))
        || (this.fixedPAttrs != null
            && !this.fixedPAttrs.equals(other.getFixedPartitionAttributes()))) {
      // throw new RuntimeException("this="+this.toString() + "   other=" + other.toString());
      return false;
    }

    PartitionListener[] otherPListeners = other.getPartitionListeners();
    PartitionListener[] thisPListeners = this.getPartitionListeners();

    if (otherPListeners.length != thisPListeners.length) {
      return false;
    }
    Set<String> otherListenerClassName = new HashSet<String>();
    for (int i = 0; i < otherPListeners.length; i++) {
      PartitionListener listener = otherPListeners[i];
      otherListenerClassName.add(listener.getClass().getName());
    }
    Set<String> thisListenerClassName = new HashSet<String>();
    for (int i = 0; i < thisPListeners.length; i++) {
      PartitionListener listener = thisPListeners[i];
      thisListenerClassName.add(listener.getClass().getName());
    }
    if (!thisListenerClassName.equals(otherListenerClassName)) {
      return false;
    }

    return true;
  }
 /**
  * Added for bug 45749. The attributes in pa are merged into this. Only attributes explicitly set
  * in pa will be merged into this. Any attribute set in pa will take precedence over an attribute
  * in this.
  *
  * @param pa the attributes to merge into this.
  * @since 7.0
  */
 public void merge(PartitionAttributesImpl pa) {
   if (pa.hasRedundancy) {
     setRedundantCopies(pa.getRedundantCopies());
   }
   if (pa.hasLocalMaxMemory) {
     setLocalMaxMemory(pa.getLocalMaxMemory());
   }
   if (pa.hasOffHeap) {
     setOffHeap(pa.getOffHeap());
   }
   if (pa.hasTotalMaxMemory) {
     setTotalMaxMemory(pa.getTotalMaxMemory());
   }
   if (pa.hasTotalNumBuckets) {
     setTotalNumBuckets(pa.getTotalNumBuckets());
   }
   if (pa.hasPartitionResolver) {
     setPartitionResolver(pa.getPartitionResolver());
   }
   if (pa.hasColocatedRegionName) {
     setColocatedWith(pa.getColocatedWith());
   }
   if (pa.hasRecoveryDelay) {
     setRecoveryDelay(pa.getRecoveryDelay());
   }
   if (pa.hasStartupRecoveryDelay) {
     setStartupRecoveryDelay(pa.getStartupRecoveryDelay());
   }
   if (pa.hasFixedPAttrs) {
     addFixedPartitionAttributes(pa.getFixedPartitionAttributes());
   }
   if (pa.hasPartitionListeners) {
     this.addPartitionListeners(pa.partitionListeners);
   }
 }