docs: private AttributeDefinition renameAttribute(String currDefId, ExtendedAttributeDefinition oldAttribute, ExtendedAttributeDefinition newAttribute, boolean required) {
  
          AttributeDefinitionSpecification result = new AttributeDefinitionSpecification();
  
          // Set some original values
          result.setId(newAttribute.getID());
          result.setType(oldAttribute.getType());
          result.setRequired(required);
  
          if (result.getType() != newAttribute.getType()) {
              // If the type of the new Attribute doesn't match the type of the original we need to issue a warning.
              error("schemagen.invalid.type.override", new Object[] { newAttribute.getID(), currDefId, result.getType() });
          }
  
          result.setName((newAttribute.getName() != null) ? newAttribute.getName() : oldAttribute.getName());
          result.setDescription((newAttribute.getDescription() != null) ? newAttribute.getDescription() : oldAttribute.getDescription());
          result.setDefaultValue((newAttribute.getDefaultValue() != null) ? newAttribute.getDefaultValue() : oldAttribute.getDefaultValue());
  
          result.setCardinality((newAttribute.getCardinality() != 0) ? newAttribute.getCardinality() : oldAttribute.getCardinality());
  
          // We need to build up the valueOptions. We have to do this by getting the labels and options, because there are no methods that
          // return the valueOptions in a list.
          String[] optionLabels = newAttribute.getOptionLabels();
          String[] optionValues = newAttribute.getOptionValues();
  
          if (optionLabels == null || optionLabels.length == 0)
              optionLabels = oldAttribute.getOptionLabels();
  
          if (optionValues == null || optionValues.length == 0)
              optionValues = oldAttribute.getOptionValues();
  
          // We need to carefully build up the arrays that are stored in the list.
          List<String[]> valueOptions = new ArrayList<String[]>();
  
          if (optionLabels != null) {
              for (int i = 0; i < optionLabels.length; i++) {
                  String[] newArray = new String[] { optionValues[i], optionLabels[i] };
                  valueOptions.add(newArray);
              }
          }
  
          result.setValueOptions(valueOptions);
  
          // We need to build up the extensions into an ExtendableHelper. Again we can get the individual extensions but have to build
          // the map of maps ourselves. We also make sure any overridden extension uris are also replaced in the final map.
          // _Linked_HashMaps are used to preserve insertion order, for tools
          Map<String, Map<String, String>> extensions = new LinkedHashMap<String, Map<String, String>>();
          // Get a list of all the Extension URIs in both the old and new Attribute.
          Set<String> extensionURIs = new LinkedHashSet<String>();
          Set<String> newExtensionURIs = newAttribute.getExtensionUris();
  
          extensionURIs.addAll(oldAttribute.getExtensionUris());
          extensionURIs.addAll(newExtensionURIs);
  
          // Now go and get the extensions for each of the URIs.
          for (String currUri : extensionURIs) {
              Map<String, String> currExtensions = new LinkedHashMap<String, String>();
              if (newExtensionURIs.contains(currUri))
                  currExtensions.putAll(newAttribute.getExtensions(currUri));
              else
                  currExtensions.putAll(oldAttribute.getExtensions(currUri));
  
              // If we're dealing with the metatype extension uri, remove the rename extension.
              if (SchemaGenConstants.METATYPE_EXTENSION_URI.equals(currUri)) {
                  currExtensions.remove("rename");
              }
              extensions.put(currUri, Collections.unmodifiableMap(currExtensions));
          }
  
          ExtendableHelper helper = new ExtendableHelper(extensions);
          result.setExtendedAttributes(helper);
  
          return result;
      }