/**
  * Creates and returns a business object data attribute key from a specified business object data
  * attribute entity.
  *
  * @param businessObjectDataAttributeEntity the business object data attribute entity
  * @return the newly created business object data attribute key
  */
 private BusinessObjectDataAttributeKey getBusinessObjectDataAttributeKey(
     BusinessObjectDataAttributeEntity businessObjectDataAttributeEntity) {
   return new BusinessObjectDataAttributeKey(
       businessObjectDataAttributeEntity
           .getBusinessObjectData()
           .getBusinessObjectFormat()
           .getBusinessObjectDefinition()
           .getNamespace()
           .getCode(),
       businessObjectDataAttributeEntity
           .getBusinessObjectData()
           .getBusinessObjectFormat()
           .getBusinessObjectDefinition()
           .getName(),
       businessObjectDataAttributeEntity
           .getBusinessObjectData()
           .getBusinessObjectFormat()
           .getUsage(),
       businessObjectDataAttributeEntity
           .getBusinessObjectData()
           .getBusinessObjectFormat()
           .getFileType()
           .getCode(),
       businessObjectDataAttributeEntity
           .getBusinessObjectData()
           .getBusinessObjectFormat()
           .getBusinessObjectFormatVersion(),
       businessObjectDataAttributeEntity.getBusinessObjectData().getPartitionValue(),
       dmHelper.getSubPartitionValues(businessObjectDataAttributeEntity.getBusinessObjectData()),
       businessObjectDataAttributeEntity.getBusinessObjectData().getVersion(),
       businessObjectDataAttributeEntity.getName());
 }
  /**
   * Gets a list of keys for all existing business object data attributes.
   *
   * @return the business object data attribute keys
   */
  @Override
  public BusinessObjectDataAttributeKeys getBusinessObjectDataAttributes(
      BusinessObjectDataKey businessObjectDataKey) {
    // Validate and trim the business object data key.
    dmHelper.validateBusinessObjectDataKey(businessObjectDataKey, false, true, true);

    // If namespace is not specified, get the namespace code by locating the legacy business object
    // definition.
    businessObjectDataHelper.populateLegacyNamespace(businessObjectDataKey);

    // Retrieve the business object data and ensure it exists.
    BusinessObjectDataEntity businessObjectDataEntity =
        dmDaoHelper.getBusinessObjectDataEntity(businessObjectDataKey);

    // Create and populate a list of business object data attribute keys.
    BusinessObjectDataAttributeKeys businessObjectDataAttributeKeys =
        new BusinessObjectDataAttributeKeys();
    for (BusinessObjectDataAttributeEntity businessObjectDataAttributeEntity :
        businessObjectDataEntity.getAttributes()) {
      businessObjectDataAttributeKeys
          .getBusinessObjectDataAttributeKeys()
          .add(getBusinessObjectDataAttributeKey(businessObjectDataAttributeEntity));
    }

    return businessObjectDataAttributeKeys;
  }
  /**
   * Updates an existing business object data attribute by key.
   *
   * @param businessObjectDataAttributeKey the business object data attribute key
   * @return the business object data attribute information
   */
  @Override
  public BusinessObjectDataAttribute updateBusinessObjectDataAttribute(
      BusinessObjectDataAttributeKey businessObjectDataAttributeKey,
      BusinessObjectDataAttributeUpdateRequest request) {
    // Validate and trim the key.
    dmHelper.validateBusinessObjectDataAttributeKey(businessObjectDataAttributeKey);

    // If namespace is not specified, get the namespace code by locating the legacy business object
    // definition.
    populateLegacyNamespace(businessObjectDataAttributeKey);

    // Get the business object format and ensure it exists.
    BusinessObjectFormatEntity businessObjectFormatEntity =
        dmDaoHelper.getBusinessObjectFormatEntity(
            new BusinessObjectFormatKey(
                businessObjectDataAttributeKey.getNamespace(),
                businessObjectDataAttributeKey.getBusinessObjectDefinitionName(),
                businessObjectDataAttributeKey.getBusinessObjectFormatUsage(),
                businessObjectDataAttributeKey.getBusinessObjectFormatFileType(),
                businessObjectDataAttributeKey.getBusinessObjectFormatVersion()));

    // Validate the attribute value.
    if (dmDaoHelper.isBusinessObjectDataAttributeRequired(
        businessObjectDataAttributeKey.getBusinessObjectDataAttributeName(),
        businessObjectFormatEntity)) {
      Assert.hasText(
          request.getBusinessObjectDataAttributeValue(),
          String.format(
              "A business object data attribute value must be specified since \"%s\" is a required attribute for business object format {%s}.",
              businessObjectDataAttributeKey.getBusinessObjectDataAttributeName(),
              dmDaoHelper.businessObjectFormatEntityAltKeyToString(businessObjectFormatEntity)));
    }

    // Retrieve and ensure that a business object data attribute exists with the specified key.
    BusinessObjectDataAttributeEntity businessObjectDataAttributeEntity =
        dmDaoHelper.getBusinessObjectDataAttributeEntity(businessObjectDataAttributeKey);

    // Update the entity with the new values.
    businessObjectDataAttributeEntity.setValue(request.getBusinessObjectDataAttributeValue());

    // Persist the entity.
    businessObjectDataAttributeEntity = dmDao.saveAndRefresh(businessObjectDataAttributeEntity);

    // Create and return the business object data attribute object from the persisted entity.
    return createBusinessObjectDataAttributeFromEntity(businessObjectDataAttributeEntity);
  }
  /**
   * Gets an existing business object data attribute by key.
   *
   * @param businessObjectDataAttributeKey the business object data attribute key
   * @return the business object data attribute information
   */
  @Override
  public BusinessObjectDataAttribute getBusinessObjectDataAttribute(
      BusinessObjectDataAttributeKey businessObjectDataAttributeKey) {
    // Validate and trim the key.
    dmHelper.validateBusinessObjectDataAttributeKey(businessObjectDataAttributeKey);

    // If namespace is not specified, get the namespace code by locating the legacy business object
    // definition.
    populateLegacyNamespace(businessObjectDataAttributeKey);

    // Retrieve and ensure that a business object data attribute exists with the specified key.
    BusinessObjectDataAttributeEntity businessObjectDataAttributeEntity =
        dmDaoHelper.getBusinessObjectDataAttributeEntity(businessObjectDataAttributeKey);

    // Create and return the business object data attribute object from the persisted entity.
    return createBusinessObjectDataAttributeFromEntity(businessObjectDataAttributeEntity);
  }
  /**
   * Deletes an existing business object data attribute by key.
   *
   * @param businessObjectDataAttributeKey the business object data attribute key
   * @return the business object data attribute that got deleted
   */
  @Override
  public BusinessObjectDataAttribute deleteBusinessObjectDataAttribute(
      BusinessObjectDataAttributeKey businessObjectDataAttributeKey) {
    // Validate and trim the key.
    dmHelper.validateBusinessObjectDataAttributeKey(businessObjectDataAttributeKey);

    // If namespace is not specified, get the namespace code by locating the legacy business object
    // definition.
    populateLegacyNamespace(businessObjectDataAttributeKey);

    // Get the business object format and ensure it exists.
    BusinessObjectFormatEntity businessObjectFormatEntity =
        dmDaoHelper.getBusinessObjectFormatEntity(
            new BusinessObjectFormatKey(
                businessObjectDataAttributeKey.getNamespace(),
                businessObjectDataAttributeKey.getBusinessObjectDefinitionName(),
                businessObjectDataAttributeKey.getBusinessObjectFormatUsage(),
                businessObjectDataAttributeKey.getBusinessObjectFormatFileType(),
                businessObjectDataAttributeKey.getBusinessObjectFormatVersion()));

    // Make sure we are not trying to delete a required attribute.
    if (dmDaoHelper.isBusinessObjectDataAttributeRequired(
        businessObjectDataAttributeKey.getBusinessObjectDataAttributeName(),
        businessObjectFormatEntity)) {
      throw new IllegalArgumentException(
          String.format(
              "Cannot delete \"%s\" attribute since it is a required attribute for business object format {%s}.",
              businessObjectDataAttributeKey.getBusinessObjectDataAttributeName(),
              dmDaoHelper.businessObjectFormatEntityAltKeyToString(businessObjectFormatEntity)));
    }

    // Retrieve and ensure that a business object data attribute exists with the specified key.
    BusinessObjectDataAttributeEntity businessObjectDataAttributeEntity =
        dmDaoHelper.getBusinessObjectDataAttributeEntity(businessObjectDataAttributeKey);

    // Delete the business object data attribute.
    BusinessObjectDataEntity businessObjectDataEntity =
        businessObjectDataAttributeEntity.getBusinessObjectData();
    businessObjectDataEntity.getAttributes().remove(businessObjectDataAttributeEntity);
    dmDao.saveAndRefresh(businessObjectDataEntity);

    // Create and return the business object data attribute object from the deleted entity.
    return createBusinessObjectDataAttributeFromEntity(businessObjectDataAttributeEntity);
  }
  /**
   * Creates a new business object data attribute.
   *
   * @param request the information needed to create a business object data attribute
   * @return the newly created business object data attribute
   */
  @Override
  public BusinessObjectDataAttribute createBusinessObjectDataAttribute(
      BusinessObjectDataAttributeCreateRequest request) {
    // Validate and trim the key.
    dmHelper.validateBusinessObjectDataAttributeKey(request.getBusinessObjectDataAttributeKey());

    // If namespace is not specified, get the namespace code by locating the legacy business object
    // definition.
    if (StringUtils.isBlank(request.getBusinessObjectDataAttributeKey().getNamespace())) {
      request
          .getBusinessObjectDataAttributeKey()
          .setNamespace(
              dmDaoHelper.getNamespaceCode(
                  request.getBusinessObjectDataAttributeKey().getBusinessObjectDefinitionName()));
    }

    // Get the business object format and ensure it exists.
    BusinessObjectFormatEntity businessObjectFormatEntity =
        dmDaoHelper.getBusinessObjectFormatEntity(
            new BusinessObjectFormatKey(
                request.getBusinessObjectDataAttributeKey().getNamespace(),
                request.getBusinessObjectDataAttributeKey().getBusinessObjectDefinitionName(),
                request.getBusinessObjectDataAttributeKey().getBusinessObjectFormatUsage(),
                request.getBusinessObjectDataAttributeKey().getBusinessObjectFormatFileType(),
                request.getBusinessObjectDataAttributeKey().getBusinessObjectFormatVersion()));

    // Validate the attribute value.
    if (dmDaoHelper.isBusinessObjectDataAttributeRequired(
        request.getBusinessObjectDataAttributeKey().getBusinessObjectDataAttributeName(),
        businessObjectFormatEntity)) {
      Assert.hasText(
          request.getBusinessObjectDataAttributeValue(),
          String.format(
              "A business object data attribute value must be specified since \"%s\" is a required attribute for business object format {%s}.",
              request.getBusinessObjectDataAttributeKey().getBusinessObjectDataAttributeName(),
              dmDaoHelper.businessObjectFormatEntityAltKeyToString(businessObjectFormatEntity)));
    }

    // Get the business object data and ensure it exists.
    BusinessObjectDataEntity businessObjectDataEntity =
        dmDaoHelper.getBusinessObjectDataEntity(
            new BusinessObjectDataKey(
                request.getBusinessObjectDataAttributeKey().getNamespace(),
                request.getBusinessObjectDataAttributeKey().getBusinessObjectDefinitionName(),
                request.getBusinessObjectDataAttributeKey().getBusinessObjectFormatUsage(),
                request.getBusinessObjectDataAttributeKey().getBusinessObjectFormatFileType(),
                request.getBusinessObjectDataAttributeKey().getBusinessObjectFormatVersion(),
                request.getBusinessObjectDataAttributeKey().getPartitionValue(),
                request.getBusinessObjectDataAttributeKey().getSubPartitionValues(),
                request.getBusinessObjectDataAttributeKey().getBusinessObjectDataVersion()));

    // Load all existing business object data attribute entities into a map for quick access using
    // lowercase attribute names.
    Map<String, BusinessObjectDataAttributeEntity> businessObjectDataAttributeEntityMap =
        dmDaoHelper.getBusinessObjectDataAttributeEntityMap(
            businessObjectDataEntity.getAttributes());

    // Ensure a business object data attribute with the specified name doesn't already exist for the
    // specified business object data.
    if (businessObjectDataAttributeEntityMap.containsKey(
        request
            .getBusinessObjectDataAttributeKey()
            .getBusinessObjectDataAttributeName()
            .toLowerCase())) {
      throw new AlreadyExistsException(
          String.format(
              "Unable to create business object data attribute with name \"%s\" because it already exists for the the business object data {%s}.",
              request.getBusinessObjectDataAttributeKey().getBusinessObjectDataAttributeName(),
              dmDaoHelper.businessObjectDataEntityAltKeyToString(businessObjectDataEntity)));
    }

    // Create a business object data attribute entity from the request information.
    BusinessObjectDataAttributeEntity businessObjectDataAttributeEntity =
        createBusinessObjectDataAttributeEntity(businessObjectDataEntity, request);

    // Persist the new entity.
    businessObjectDataAttributeEntity = dmDao.saveAndRefresh(businessObjectDataAttributeEntity);

    // Create and return the business object data attribute object from the persisted entity.
    return createBusinessObjectDataAttributeFromEntity(businessObjectDataAttributeEntity);
  }