public Entity addEntity(Entity entity) throws ApplicationException {
    if (entity == null) {
      return null;
    }

    if (entity.getEntityVersionId() != null) {
      throw new ApplicationException(
          "This entity definition already exists so it can only be updated.");
    }

    validateNameUniqueness(entity);
    try {
      entity.setUserCreatedBy(Context.getUserContext().getUser());
      Date dateCreated = new Date();
      entity.setDateCreated(dateCreated);
      for (EntityAttribute attribute : entity.getAttributes()) {
        attribute.setDateCreated(dateCreated);
        attribute.setUserCreatedBy(Context.getUserContext().getUser());
        attribute.setEntity(entity);
      }
      entityDefinitionDao.addEntity(entity);
      addToCache(entity);
      Context.notifyObserver(ObservationEventType.ENTITY_ADD_EVENT, entity);
      return entity;
    } catch (DaoException e) {
      throw new ApplicationException(e.getMessage());
    }
  }
 public void deleteCustomField(CustomField field) throws ApplicationException {
   if (field == null
       || ConvertUtil.isNullOrEmpty(field.getEntityName())
       || ConvertUtil.isNullOrEmpty(field.getFieldName())) {
     log.warn("The custom field to be deleted is invalid: " + field);
     throw new ApplicationException("Unable to add invalid custom field definition.");
   }
   Entity entity = findLatestEntityVersionByName(field.getEntityName());
   EntityAttribute attrib = null;
   for (EntityAttribute item : entity.getAttributes()) {
     if (item.getName().equalsIgnoreCase(field.getFieldName()) && item.getDateVoided() == null) {
       attrib = item;
     }
   }
   if (attrib == null) {
     log.info("The user attempted to delete a custom field that does not exist.");
     throw new ApplicationException("Unable to delete an unknown custom field definition.");
   }
   attrib.setDateVoided(new Date());
   attrib.setUserVoidedBy(Context.getUserContext().getUser());
   try {
     entityDefinitionDao.updateEntity(entity);
     // Generate a notification event to inform interested listeners via the lightweight mechanism
     // that this event has occurred.
     Context.notifyObserver(ObservationEventType.CUSTOM_FIELD_DELETE_EVENT, field);
   } catch (DaoException e) {
     log.error("Failed while deleting a custom field: " + e, e);
     throw new ApplicationException("Failed while deleting the custom field: " + e.getMessage());
   }
 }
  public CustomField addCustomField(CustomField field) throws ApplicationException {
    if (field == null
        || ConvertUtil.isNullOrEmpty(field.getEntityName())
        || ConvertUtil.isNullOrEmpty(field.getFieldName())
        || ConvertUtil.isNullOrEmpty(field.getSourceFieldName())) {
      log.info("The custom field to be added is invalid: " + field);
      throw new ApplicationException("Unable to add invalid custom field definition.");
    }

    // Validate that a custom field by the same name does not already exist.
    List<CustomField> fields = loadCustomFields(field.getEntityName());
    for (CustomField custom : fields) {
      if (custom.getFieldName().equalsIgnoreCase(field.getFieldName())) {
        log.warn(
            "User attempted to add a custom field "
                + field
                + " that already exists in the system.");
        throw new ApplicationException(
            "Unable to add a custom field that already exists in the system.");
      }
    }

    Entity entity = findLatestEntityVersionByName(field.getEntityName());
    try {
      EntityAttribute attribute = buildAttributeFromCustomField(entity, field);
      entity.addAttribute(attribute);
      // TODO: Validate that the source field is known
      // TODO: Validate that the transformation function is known
      attribute = entityDefinitionDao.addCustomField(entity, attribute);
      // Generate a notification event to inform interested listeners via the lightweight mechanism
      // that this event has occurred.
      Context.notifyObserver(ObservationEventType.CUSTOM_FIELD_ADD_EVENT, field);
      Context.notifyObserver(ObservationEventType.ENTITY_ATTRIBUTE_UPDATE_EVENT, entity);
      return field;
    } catch (DaoException e) {
      log.error("Failed while saving a custom field: " + e, e);
      throw new ApplicationException("Failed while saving the custom field: " + e.getMessage());
    }
  }
  public Entity updateEntity(Entity entity) throws ApplicationException {
    if (entity == null) {
      return entity;
    }
    if (entity.getEntityVersionId() == null) {
      throw new ApplicationException(
          "An entity definition must first be created before it is updated.");
    }
    try {
      Date currentDate = new Date();
      entity.setDateChanged(currentDate);
      entity.setUserChangedBy(Context.getUserContext().getUser());
      for (EntityAttribute attrib : entity.getAttributes()) {
        if (attrib.getDateCreated() == null) {
          attrib.setDateCreated(currentDate);
          attrib.setUserCreatedBy(Context.getUserContext().getUser());
          // attrib.setEntity(entity);
        }
        attrib.setEntity(entity);
      }

      // Mark deletion attributes
      handleAttributeUpdates(entity);

      // remove validations for marked attribute
      for (EntityAttribute attrib : entity.getAttributes()) {
        if (attrib.getUserVoidedBy() != null) {

          // remove validations
          List<EntityAttributeValidation> existingValidations =
              loadEntityAttributeValidations(attrib);
          for (EntityAttributeValidation validation : existingValidations) {
            deleteEntityAttributeValidation(validation);
          }
        }
      }

      Entity updatedEntity = entityDefinitionDao.updateEntity(entity);
      updatedEntity = entityDefinitionDao.loadEntity(entity.getEntityVersionId());

      addToCache(updatedEntity);
      Context.notifyObserver(ObservationEventType.ENTITY_ATTRIBUTE_UPDATE_EVENT, entity);

      return updatedEntity;
    } catch (DaoException e) {
      throw new ApplicationException(e.getMessage());
    }
  }