private void populateEntity(AlertDefinitionEntity entity,
      Map<String, Object> requestMap) throws AmbariException, AuthorizationException {

    // some fields are required on creation; on update we keep what's there
    boolean bCreate = true;
    if (null != entity.getDefinitionId()) {
      bCreate = false;
    }

    String clusterName = (String) requestMap.get(ALERT_DEF_CLUSTER_NAME);
    String definitionName = (String) requestMap.get(ALERT_DEF_NAME);
    String serviceName = (String) requestMap.get(ALERT_DEF_SERVICE_NAME);
    String componentName = (String) requestMap.get(ALERT_DEF_COMPONENT_NAME);
    String type = (String) requestMap.get(ALERT_DEF_SOURCE_TYPE);
    String label = (String) requestMap.get(ALERT_DEF_LABEL);
    String helpURL = (String) requestMap.get(ALERT_DEF_HELP_URL);
    String description = (String) requestMap.get(ALERT_DEF_DESCRIPTION);
    String desiredScope = (String) requestMap.get(ALERT_DEF_SCOPE);

    Integer interval = null;
    if (requestMap.containsKey(ALERT_DEF_INTERVAL)) {
      interval = Integer.valueOf((String) requestMap.get(ALERT_DEF_INTERVAL));
    }

    Boolean enabled = null;
    if (requestMap.containsKey(ALERT_DEF_ENABLED)) {
      enabled = Boolean.parseBoolean((String) requestMap.get(ALERT_DEF_ENABLED));
    } else if (bCreate) {
      enabled = Boolean.TRUE;
    }

    Boolean ignoreHost = null;
    if (requestMap.containsKey(ALERT_DEF_IGNORE_HOST)) {
      ignoreHost = Boolean.parseBoolean((String) requestMap.get(ALERT_DEF_IGNORE_HOST));
    } else if (bCreate) {
      ignoreHost = Boolean.FALSE;
    }

    Scope scope = null;
    if (null != desiredScope && desiredScope.length() > 0) {
      scope = Scope.valueOf(desiredScope);
    }

    SourceType sourceType = null;
    if (null != type && type.length() > 0) {
      sourceType = SourceType.valueOf(type);
    }

    // if not specified when creating an alert definition, the scope is
    // assumed to be ANY
    if (null == scope && bCreate) {
      scope = Scope.ANY;
    }

    Integer repeatTolerance = null;
    if (requestMap.containsKey(ALERT_DEF_REPEAT_TOLERANCE)) {
      repeatTolerance = Integer.valueOf((String) requestMap.get(ALERT_DEF_REPEAT_TOLERANCE));
    }

    Boolean repeatToleranceEnabled = null;
    if (requestMap.containsKey(ALERT_DEF_REPEAT_TOLERANCE_ENABLED)) {
      repeatToleranceEnabled = Boolean.valueOf(
          requestMap.get(ALERT_DEF_REPEAT_TOLERANCE_ENABLED).toString());
    }

    if (StringUtils.isEmpty(clusterName)) {
      throw new IllegalArgumentException(
          "Invalid argument, cluster name is required");
    }

    if (bCreate && !requestMap.containsKey(ALERT_DEF_INTERVAL)) {
      throw new IllegalArgumentException("Check interval must be specified");
    }

    if (bCreate && StringUtils.isEmpty(definitionName)) {
      throw new IllegalArgumentException("Definition name must be specified");
    }

    if (bCreate && StringUtils.isEmpty(serviceName)) {
      throw new IllegalArgumentException("Service name must be specified");
    }

    // on creation, source type is required
    if (bCreate && null == sourceType) {
      throw new IllegalArgumentException(String.format(
          "Source type must be specified and one of %s",
          EnumSet.allOf(SourceType.class)));
    }

    // !!! The AlertDefinition "source" field is a nested JSON object;
    // build a JSON representation from the flat properties and then
    // serialize that JSON object as a string
    Map<String,JsonObject> jsonObjectMapping = new HashMap<>();

    // for every property in the request, if it's a source property, then
    // add it to the JSON model
    for (Entry<String, Object> entry : requestMap.entrySet()) {
      String propertyKey = entry.getKey();

      // only handle "source" subproperties
      if (!propertyKey.startsWith(ALERT_DEF_SOURCE)) {
        continue;
      }

      // gets a JSON object to add the property to; this will create the
      // property and all of its parent properties recursively if necessary
      JsonObject jsonObject = getJsonObjectMapping(ALERT_DEF_SOURCE,
          jsonObjectMapping, propertyKey);

      String propertyName = PropertyHelper.getPropertyName(propertyKey);
      Object entryValue = entry.getValue();

      // determine if the object is a collection, a number, or a string
      if( entryValue instanceof Collection<?> ){
        // add it as a tree (collection)
        JsonElement jsonElement = gson.toJsonTree(entryValue);
        jsonObject.add(propertyName, jsonElement);
      } else if (entryValue instanceof Number) {
        // add it as a number
        jsonObject.addProperty(propertyName, (Number) entryValue);
      } else {
        // it's a string, but it could still be a Number since Ambari's higher
        // level JSON processor converts all JSON bodies into Map<String,String>
        // instead of Map<String,Object>
        String value = entryValue.toString();
        if (StringUtils.isNotEmpty(value) && NumberUtils.isNumber(value)) {
          Number number = NumberUtils.createNumber(value);
          jsonObject.addProperty(propertyName, number);
        } else {
          jsonObject.addProperty(propertyName, value);
        }
      }
    }

    // "source" must be filled in when creating
    JsonObject source = jsonObjectMapping.get(ALERT_DEF_SOURCE);
    if (bCreate && (null == source || 0 == source.entrySet().size())) {
      throw new IllegalArgumentException("Source must be specified");
    }

    Clusters clusters = getManagementController().getClusters();
    Cluster cluster = clusters.getCluster(clusterName);
    Long clusterId = cluster.getClusterId();

    boolean managed = false;
    boolean toggled = false;

    // at this point, we have either validated all required properties or
    // we are using the exiting entity properties where not defined, so we
    // can do simply null checks
    if (!clusterId.equals(entity.getClusterId())) {
      entity.setClusterId(clusterId);
      managed = true;
    }

    if ((null != componentName) && !componentName.equals(entity.getComponentName())) {
      entity.setComponentName(componentName);
      managed = true;
    }

    if ((null != definitionName) && !definitionName.equals(entity.getDefinitionName())) {
      entity.setDefinitionName(definitionName);
      managed = true;
    }

    if ((null != label) && !label.equals(entity.getLabel())) {
      entity.setLabel(label);
      managed = true;
    }

    if ((null != helpURL) && !helpURL.equals(entity.getHelpURL())) {
      entity.setHelpURL(helpURL);
      managed = true;
    }

    if ((null != description) && !description.equals(entity.getDescription())) {
      entity.setDescription(description);
      managed = true;
    }

    if ((null != enabled) && !enabled.equals(entity.getEnabled())) {
      entity.setEnabled(enabled);
      toggled = true;
    }

    if ((null != ignoreHost) && !ignoreHost.equals(entity.isHostIgnored())) {
      entity.setHostIgnored(ignoreHost);
      managed = true;
    }

    if ((null != interval) && !interval.equals(entity.getScheduleInterval())) {
      entity.setScheduleInterval(interval);
      managed = true;
    }

    if ((null != serviceName) && !serviceName.equals(entity.getServiceName())) {
      entity.setServiceName(serviceName);
      managed = true;
    }

    if ((null != sourceType) && !sourceType.equals(entity.getSourceType())) {
      entity.setSourceType(sourceType);
      managed = true;
    }

    if (null != source) {
      entity.setSource(source.toString());
      managed = true;
    }

    if ((null != scope) && !scope.equals(entity.getScope())) {
      entity.setScope(scope);
      managed = true;
    }

    // repeat tolerance is only for non-AGGREGATE alerts
    if (entity.getSourceType() != SourceType.AGGREGATE) {
      if (null != repeatTolerance) {
        entity.setRepeatTolerance(repeatTolerance);
        managed = true;
      }

      if (null != repeatToleranceEnabled) {
        entity.setRepeatToleranceEnabled(repeatToleranceEnabled);
        managed = true;
      }
    }

    if (managed) {
      AlertResourceProviderUtils.verifyManageAuthorization(entity);
    } else if (toggled) {
      AlertResourceProviderUtils.verifyToggleAuthorization(entity);
    }

    entity.setHash(UUID.randomUUID().toString());
  }
Merges the map of properties into the specified entity. If the entity is
being created, an {@link IllegalArgumentException} is thrown when a
required property is absent. When updating, missing properties are assume
to not have changed.

@param entity
         the entity to merge the properties into (not {@code null}).
@param requestMap
         the map of properties (not {@code null}).
@throws AmbariException
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertDefinitionResourceProvider.java