/**
   * Edits a dynamic {@link EndpointDescription}.
   *
   * @param oldName old name of {@link EndpointDescription}
   * @param newName new name of {@link EndpointDescription}
   * @param newDataType new {@link DataType}
   * @param newMetaData new meta data {@link Map}
   * @param newDynEndpointId new name of endpoint the input belongs to
   * @param newParentGroup new name of endpoint parent group the input belongs to
   * @return {@link EndpointDescription} edited
   * @throws IllegalArgumentException if no dynamic endpoint description with given name exists or
   *     new name is invalid
   */
  public synchronized EndpointDescription editDynamicEndpointDescription(
      String oldName,
      String newName,
      DataType newDataType,
      Map<String, String> newMetaData,
      String newDynEndpointId,
      String newParentGroup)
      throws IllegalArgumentException {

    EndpointDescription description = dynamicEndpointDescriptions.remove(oldName);
    if (description == null) {
      throw new IllegalArgumentException(
          StringUtils.format(MESSAGE_DYNAMIC_ENDPOINT_DESCRIPTION_DOESNT_EXIST, oldName));
    }
    EndpointDescription oldDescription = EndpointDescription.copy(description);
    try {
      if (!isValidEndpointName(newName)) {
        throw new IllegalArgumentException(MESSAGE_DESIRED_ENDPOINT_NAME_ALREADY_EXISTS + newName);
      }
      description.setName(newName);
      description.setDataType(newDataType);
      description.setMetaData(newMetaData);
      description
          .getMetaData()
          .put(
              LoopComponentConstants.META_KEY_LOOP_ENDPOINT_TYPE,
              oldDescription.getMetaDataValue(LoopComponentConstants.META_KEY_LOOP_ENDPOINT_TYPE));
      if (newDynEndpointId != null) {
        description.setDynamicEndpointIdentifier(newDynEndpointId);
      }
      description.setParentGroupName(newParentGroup);
    } catch (IllegalArgumentException e) {
      dynamicEndpointDescriptions.put(oldName, description);
      throw e;
    }

    dynamicEndpointDescriptions.put(newName, description);

    firePropertyChange(
        PROPERTY_ENDPOINT,
        new EndpointChange(EndpointChange.Type.Modified, description, oldDescription));

    return description;
  }