private void generate(String id, RegionAttributes<?, ?> attrs) throws SAXException {
    AttributesImpl atts = new AttributesImpl();

    if (id != null) {
      atts.addAttribute("", "", ID, "", id);
    }

    // Unless, the attrs is a "creation" instance,
    // we have no way of generating a refid, because by this
    // point, the refid information is lost.
    if (attrs instanceof RegionAttributesCreation) {
      String refId = ((RegionAttributesCreation) attrs).getRefid();
      if (refId != null) {
        atts.addAttribute("", "", REFID, "", refId);
      }
    }

    if ((!(attrs instanceof RegionAttributesCreation)
        || ((RegionAttributesCreation) attrs).hasScope())) {
      String scopeString;
      Scope scope = attrs.getScope();
      if (scope.equals(Scope.LOCAL)) {
        scopeString = LOCAL;

      } else if (scope.equals(Scope.DISTRIBUTED_NO_ACK)) {
        scopeString = DISTRIBUTED_NO_ACK;

      } else if (scope.equals(Scope.DISTRIBUTED_ACK)) {
        scopeString = DISTRIBUTED_ACK;

      } else if (scope.equals(Scope.GLOBAL)) {
        scopeString = GLOBAL;

      } else {
        throw new InternalGemFireException(
            String.format("Unknown scope: %s", scope));
      }


      final boolean isPartitionedRegion;
      if (attrs instanceof RegionAttributesCreation) {
        RegionAttributesCreation rac = (RegionAttributesCreation) attrs;
        isPartitionedRegion = rac.getPartitionAttributes() != null
            || (rac.hasDataPolicy() && rac.getDataPolicy().withPartitioning());
      } else {
        isPartitionedRegion =
            attrs.getPartitionAttributes() != null || attrs.getDataPolicy().withPartitioning();
      }

      if (!isPartitionedRegion) {
        // Partitioned Region don't support setting scope
        if (generateDefaults() || !scope.equals(AbstractRegion.DEFAULT_SCOPE)) {
          atts.addAttribute("", "", SCOPE, "", scopeString);
        }
      }
    } // hasScope

    if ((!(attrs instanceof RegionAttributesCreation)
        || ((RegionAttributesCreation) attrs).hasEarlyAck())) {
      if (generateDefaults() || attrs.getEarlyAck()) {
        atts.addAttribute("", "", EARLY_ACK, "", String.valueOf(attrs.getEarlyAck()));
      }
    }

    if ((!(attrs instanceof RegionAttributesCreation)
        || ((RegionAttributesCreation) attrs).hasMulticastEnabled())) {
      if (generateDefaults() || attrs.getMulticastEnabled()) {
        atts.addAttribute("", "", MULTICAST_ENABLED, "",
            String.valueOf(attrs.getMulticastEnabled()));
      }
    }
    if ((!(attrs instanceof RegionAttributesCreation)
        || ((RegionAttributesCreation) attrs).hasPublisher())) {
      if (generateDefaults() || attrs.getPublisher()) {
        atts.addAttribute("", "", PUBLISHER, "", String.valueOf(attrs.getPublisher()));
      }
    }

    if ((!(attrs instanceof RegionAttributesCreation)
        || ((RegionAttributesCreation) attrs).hasEnableAsyncConflation())) {
      if (generateDefaults() || attrs.getEnableAsyncConflation()) {
        atts.addAttribute("", "", ENABLE_ASYNC_CONFLATION, "",
            String.valueOf(attrs.getEnableAsyncConflation()));
      }
    }

    if (version.compareTo(CacheXmlVersion.GEMFIRE_5_0) >= 0) {

      if ((!(attrs instanceof RegionAttributesCreation)
          || ((RegionAttributesCreation) attrs).hasEnableSubscriptionConflation())) {
        if (version.compareTo(CacheXmlVersion.GEMFIRE_5_7) >= 0) {
          // starting with 5.7 it is enable-subscription-conflation
          if (generateDefaults() || attrs.getEnableSubscriptionConflation()) {
            atts.addAttribute("", "", ENABLE_SUBSCRIPTION_CONFLATION, "",
                String.valueOf(attrs.getEnableSubscriptionConflation()));
          }
        } else {
          // before 5.7 it was enable-bridge-conflation
          if (generateDefaults() || attrs.getEnableSubscriptionConflation()) {
            atts.addAttribute("", "", ENABLE_BRIDGE_CONFLATION, "",
                String.valueOf(attrs.getEnableSubscriptionConflation()));
          }
        }
      }

      if ((!(attrs instanceof RegionAttributesCreation)
          || ((RegionAttributesCreation) attrs).hasDataPolicy())) {
        String dpString;
        DataPolicy dp = attrs.getDataPolicy();
        if (dp.isEmpty()) {
          dpString = EMPTY_DP;
        } else if (dp.isNormal()) {
          dpString = NORMAL_DP;
        } else if (dp.isPreloaded()) {
          dpString = PRELOADED_DP;
        } else if (dp.isReplicate()) {
          dpString = REPLICATE_DP;
        } else if (dp == DataPolicy.PERSISTENT_REPLICATE) {
          dpString = PERSISTENT_REPLICATE_DP;
        } else if (dp == DataPolicy.PERSISTENT_PARTITION) {
          dpString = PERSISTENT_PARTITION_DP;
        } else if (dp.isPartition()) {
          if (version.compareTo(CacheXmlVersion.GEMFIRE_5_1) >= 0) {
            dpString = PARTITION_DP;
          } else {
            // prior to 5.1 the data policy for partitioned regions was EMPTY
            dpString = EMPTY_DP;
          }
        } else {
          throw new InternalGemFireException(
              String.format("Unknown data policy: %s", dp));
        }

        if (generateDefaults() || !dp.equals(DataPolicy.DEFAULT)) {
          atts.addAttribute("", "", DATA_POLICY, "", dpString);
        }
      } // hasDataPolicy
    } // GEMFIRE_5_0 >= 0
    else { // GEMFIRE_5_0 < 0
      if ((!(attrs instanceof RegionAttributesCreation)
          || ((RegionAttributesCreation) attrs).hasEnableSubscriptionConflation())) {
        if (generateDefaults() || attrs.getEnableSubscriptionConflation()) {
          atts.addAttribute("", "", "enable-conflation", "",
              String.valueOf(attrs.getEnableSubscriptionConflation()));
        }
      }

      if ((!(attrs instanceof RegionAttributesCreation)
          || ((RegionAttributesCreation) attrs).hasMirrorType())) {
        String mirrorString;
        MirrorType mirror = attrs.getMirrorType();
        if (mirror.equals(MirrorType.NONE)) {
          mirrorString = NONE;
        } else if (mirror.equals(MirrorType.KEYS)) {
          mirrorString = KEYS;
        } else if (mirror.equals(MirrorType.KEYS_VALUES)) {
          mirrorString = KEYS_VALUES;
        } else {
          throw new InternalGemFireException(
              String.format("Unknown mirror type: %s", mirror));
        }
        atts.addAttribute("", "", MIRROR_TYPE, "", mirrorString);
      }
      if ((!(attrs instanceof RegionAttributesCreation)
          || ((RegionAttributesCreation) attrs).hasPersistBackup())) {
        atts.addAttribute("", "", PERSIST_BACKUP, "",
            String.valueOf(attrs.getDataPolicy() == DataPolicy.PERSISTENT_REPLICATE));
      }
    } // GEMFIRE_5_0 < 0

    if ((!(attrs instanceof RegionAttributesCreation)
        || ((RegionAttributesCreation) attrs).hasInitialCapacity())) {
      if (generateDefaults() || attrs.getInitialCapacity() != 16) {
        atts.addAttribute("", "", INITIAL_CAPACITY, "", String.valueOf(attrs.getInitialCapacity()));
      }
    }

    if ((!(attrs instanceof RegionAttributesCreation)
        || ((RegionAttributesCreation) attrs).hasLoadFactor())) {
      if (generateDefaults() || attrs.getLoadFactor() != 0.75f) {
        atts.addAttribute("", "", LOAD_FACTOR, "", String.valueOf(attrs.getLoadFactor()));
      }
    }

    if ((!(attrs instanceof RegionAttributesCreation)
        || ((RegionAttributesCreation) attrs).hasConcurrencyLevel())) {
      if (generateDefaults() || attrs.getConcurrencyLevel() != 16) {
        atts.addAttribute("", "", CONCURRENCY_LEVEL, "",
            String.valueOf(attrs.getConcurrencyLevel()));
      }
    }

    if (version.compareTo(CacheXmlVersion.GEMFIRE_7_0) >= 0) {
      if ((!(attrs instanceof RegionAttributesCreation)
          || ((RegionAttributesCreation) attrs).hasConcurrencyChecksEnabled())) {
        if (generateDefaults() || !attrs.getConcurrencyChecksEnabled()) {
          atts.addAttribute("", "", CONCURRENCY_CHECKS_ENABLED, "",
              String.valueOf(attrs.getConcurrencyChecksEnabled()));
        }
      }
    }

    if ((!(attrs instanceof RegionAttributesCreation)
        || ((RegionAttributesCreation) attrs).hasStatisticsEnabled())) {
      if (generateDefaults() || attrs.getStatisticsEnabled()) {
        atts.addAttribute("", "", STATISTICS_ENABLED, "",
            String.valueOf(attrs.getStatisticsEnabled()));
      }
    }

    if (!(attrs instanceof RegionAttributesCreation)
        || ((RegionAttributesCreation) attrs).hasIgnoreJTA()) {
      if (generateDefaults() || attrs.getIgnoreJTA()) {
        atts.addAttribute("", "", IGNORE_JTA, "", String.valueOf(attrs.getIgnoreJTA()));
      }
    }

    if (version.compareTo(CacheXmlVersion.GEMFIRE_4_0) >= 0) {
      if ((!(attrs instanceof RegionAttributesCreation)
          || ((RegionAttributesCreation) attrs).hasIsLockGrantor())) {
        if (generateDefaults() || attrs.isLockGrantor()) {
          atts.addAttribute("", "", IS_LOCK_GRANTOR, "", String.valueOf(attrs.isLockGrantor()));
        }
      }
    }
    if (version.compareTo(CacheXmlVersion.GEMFIRE_5_7) >= 0) {
      if ((!(attrs instanceof RegionAttributesCreation)
          || ((RegionAttributesCreation) attrs).hasPoolName())) {
        String cpVal = attrs.getPoolName();
        if (cpVal == null) {
          cpVal = "";
        }
        if (generateDefaults() || !cpVal.equals("")) {
          atts.addAttribute("", "", POOL_NAME, "", cpVal);
        }
      }
    }
    if (version.compareTo(CacheXmlVersion.GEMFIRE_6_5) >= 0) {
      if ((!(attrs instanceof RegionAttributesCreation)
          || ((RegionAttributesCreation) attrs).hasDiskStoreName())) {
        String dsVal = attrs.getDiskStoreName();
        if (dsVal != null) {
          atts.addAttribute("", "", DISK_STORE_NAME, "", dsVal);
        }
      }
      if ((!(attrs instanceof RegionAttributesCreation)
          || ((RegionAttributesCreation) attrs).hasDiskSynchronous())) {
        if (generateDefaults()
            || attrs.isDiskSynchronous() != AttributesFactory.DEFAULT_DISK_SYNCHRONOUS) {
          atts.addAttribute("", "", DISK_SYNCHRONOUS, "",
              String.valueOf(attrs.isDiskSynchronous()));
        }
      }
    }
    if (version.compareTo(CacheXmlVersion.GEMFIRE_6_1) >= 0) {
      if ((!(attrs instanceof RegionAttributesCreation)
          || ((RegionAttributesCreation) attrs).hasCloningEnabled())) {
        if (generateDefaults() || attrs.getCloningEnabled()) {
          atts.addAttribute("", "", CLONING_ENABLED, "", String.valueOf(attrs.getCloningEnabled()));
        }
      }
    }

    if (version.compareTo(CacheXmlVersion.GEMFIRE_7_0) >= 0) {
      if ((!(attrs instanceof RegionAttributesCreation)
          || ((RegionAttributesCreation) attrs).hasGatewaySenderId())) {
        Set<String> senderIds = new HashSet<>(attrs.getGatewaySenderIds());
        StringBuilder senderStringBuff = new StringBuilder();
        if (senderIds.size() != 0) {
          for (String senderId : senderIds) {
            if (!(senderStringBuff.length() == 0)) {
              senderStringBuff.append(",");
            }
            senderStringBuff.append(senderId);
          }
        }
        if (generateDefaults() || senderStringBuff.length() > 0) {
          atts.addAttribute("", "", GATEWAY_SENDER_IDS, "", senderStringBuff.toString());
        }
      }
    }

    if (version.compareTo(CacheXmlVersion.GEMFIRE_7_0) >= 0) {
      if ((!(attrs instanceof RegionAttributesCreation)
          || ((RegionAttributesCreation) attrs).hasAsyncEventListeners())) {
        Set<String> asyncEventQueueIds = new HashSet<>(attrs.getAsyncEventQueueIds());
        StringBuilder asyncEventQueueStringBuff = new StringBuilder();
        if (asyncEventQueueIds.size() != 0) {
          for (String asyncEventQueueId : asyncEventQueueIds) {
            if (!(asyncEventQueueStringBuff.length() == 0)) {
              asyncEventQueueStringBuff.append(",");
            }
            asyncEventQueueStringBuff.append(asyncEventQueueId);
          }
        }
        if (generateDefaults() || asyncEventQueueStringBuff.length() > 0) {
          atts.addAttribute("", "", ASYNC_EVENT_QUEUE_IDS, "",
              asyncEventQueueStringBuff.toString());
        }
      }
    }

    if (version.compareTo(CacheXmlVersion.GEODE_1_0) >= 0) {
      if ((!(attrs instanceof RegionAttributesCreation)
          || ((RegionAttributesCreation) attrs).hasOffHeap())) {
        if (generateDefaults() || attrs.getOffHeap()) {
          atts.addAttribute("", "", OFF_HEAP, "", String.valueOf(attrs.getOffHeap()));
        }
      }
    }

    handler.startElement("", REGION_ATTRIBUTES, REGION_ATTRIBUTES, atts);

    if ((!(attrs instanceof RegionAttributesCreation)
        || ((RegionAttributesCreation) attrs).hasKeyConstraint())) {
      generate(attrs.getKeyConstraint(), KEY_CONSTRAINT);
    }

    if ((!(attrs instanceof RegionAttributesCreation)
        || ((RegionAttributesCreation) attrs).hasValueConstraint())) {
      generate(attrs.getValueConstraint(), VALUE_CONSTRAINT);
    }

    if ((!(attrs instanceof RegionAttributesCreation)
        || ((RegionAttributesCreation) attrs).hasRegionTimeToLive())) {
      if (generateDefaults() || !attrs.getRegionTimeToLive().equals(ExpirationAttributes.DEFAULT)) {
        generate(REGION_TIME_TO_LIVE, attrs.getRegionTimeToLive(), null);
      }
    }

    if ((!(attrs instanceof RegionAttributesCreation)
        || ((RegionAttributesCreation) attrs).hasRegionIdleTimeout())) {
      if (generateDefaults()
          || !attrs.getRegionIdleTimeout().equals(ExpirationAttributes.DEFAULT)) {
        generate(REGION_IDLE_TIME, attrs.getRegionIdleTimeout(), null);
      }
    }

    if ((!(attrs instanceof RegionAttributesCreation)
        || ((RegionAttributesCreation) attrs).hasEntryTimeToLive()
        || ((RegionAttributesCreation) attrs).hasCustomEntryTimeToLive())) {
      if (generateDefaults() || !attrs.getEntryTimeToLive().equals(ExpirationAttributes.DEFAULT)
          || attrs.getCustomEntryTimeToLive() != null) {
        generate(ENTRY_TIME_TO_LIVE, attrs.getEntryTimeToLive(), attrs.getCustomEntryTimeToLive());
      }
    }

    if ((!(attrs instanceof RegionAttributesCreation)
        || ((RegionAttributesCreation) attrs).hasEntryIdleTimeout()
        || ((RegionAttributesCreation) attrs).hasCustomEntryIdleTimeout())) {
      if (generateDefaults() || !attrs.getEntryIdleTimeout().equals(ExpirationAttributes.DEFAULT)
          || attrs.getCustomEntryIdleTimeout() != null) {
        generate(ENTRY_IDLE_TIME, attrs.getEntryIdleTimeout(), attrs.getCustomEntryIdleTimeout());
      }
    }

    if (attrs.getDiskStoreName() == null
        && (generateDefaults() || version.compareTo(CacheXmlVersion.GEMFIRE_6_5) < 0)) {
      if ((!(attrs instanceof RegionAttributesCreation)
          || ((RegionAttributesCreation) attrs).hasDiskWriteAttributes())) {
        generate(attrs.getDiskWriteAttributes());
      }

      if ((!(attrs instanceof RegionAttributesCreation)
          || ((RegionAttributesCreation) attrs).hasDiskDirs())) {
        File[] diskDirs = attrs.getDiskDirs();
        int[] diskSizes = attrs.getDiskDirSizes();
        if (diskDirs != null && diskDirs.length > 0) {
          handler.startElement("", DISK_DIRS, DISK_DIRS, EMPTY);
          for (int i = 0; i < diskDirs.length; i++) {
            AttributesImpl diskAtts = new AttributesImpl();
            if (diskSizes[i] != DiskStoreFactory.DEFAULT_DISK_DIR_SIZE) {
              diskAtts.addAttribute("", "", DIR_SIZE, "", String.valueOf(diskSizes[i]));
            }
            handler.startElement("", DISK_DIR, DISK_DIR, diskAtts);
            File dir = diskDirs[i];
            String name = generateDefaults() ? dir.getAbsolutePath() : dir.getPath();
            handler.characters(name.toCharArray(), 0, name.length());
            handler.endElement("", DISK_DIR, DISK_DIR);
          }
          handler.endElement("", DISK_DIRS, DISK_DIRS);
        }
      }
    } // pre 6.5

    if (version.compareTo(CacheXmlVersion.GEMFIRE_5_0) >= 0) {
      if ((!(attrs instanceof RegionAttributesCreation)
          || ((RegionAttributesCreation) attrs).hasPartitionAttributes())) {
        PartitionAttributes p = attrs.getPartitionAttributes();
        if (p != null) {
          generate(p);
        }
      }
    }

    if (version.compareTo(CacheXmlVersion.GEMFIRE_5_0) >= 0) {
      MembershipAttributes p = attrs.getMembershipAttributes();
      if (p != null && p.hasRequiredRoles()) {
        generate(p);
      }
    }

    if (version.compareTo(CacheXmlVersion.GEMFIRE_5_0) >= 0) {
      if ((!(attrs instanceof RegionAttributesCreation)
          || ((RegionAttributesCreation) attrs).hasSubscriptionAttributes())) {
        SubscriptionAttributes sa = attrs.getSubscriptionAttributes();
        if (sa != null) {
          if (generateDefaults() || !sa.equals(new SubscriptionAttributes())) {
            generate(sa);
          }
        }
      }
    }

    if ((!(attrs instanceof RegionAttributesCreation)
        || ((RegionAttributesCreation) attrs).hasCacheLoader())) {
      generate(CACHE_LOADER, attrs.getCacheLoader());
    }
    if ((!(attrs instanceof RegionAttributesCreation)
        || ((RegionAttributesCreation) attrs).hasCacheWriter())) {
      generate(CACHE_WRITER, attrs.getCacheWriter());
    }
    if ((!(attrs instanceof RegionAttributesCreation)
        || ((RegionAttributesCreation) attrs).hasCacheListeners())) {
      CacheListener[] listeners = attrs.getCacheListeners();
      for (CacheListener listener : listeners) {
        generate(CACHE_LISTENER, listener);
      }
    }

    if (version.compareTo(CacheXmlVersion.GEMFIRE_8_0) >= 0) {
      if ((!(attrs instanceof RegionAttributesCreation)
          || ((RegionAttributesCreation) attrs).hasCompressor())) {
        generate(COMPRESSOR, attrs.getCompressor());
      }
    }

    if ((!(attrs instanceof RegionAttributesCreation)
        || ((RegionAttributesCreation) attrs).hasEvictionAttributes())) {
      generate(attrs.getEvictionAttributes());
    }

    handler.endElement("", REGION_ATTRIBUTES, REGION_ATTRIBUTES);
  }
Generates XML for region attributes.

@param id The id of the named region attributes (may be <code>null</code>)
geode-core/src/main/java/org/apache/geode/internal/cache/xmlcache/CacheXmlGenerator.java