code: private void upsertAttributes(EntityType entityType, EntityType existingEntityType) {
      // analyze both compound and atomic attributes owned by the entity
      Map<String, Attribute> attrsMap =
          stream(entityType.getOwnAllAttributes())
              .collect(toMap(Attribute::getName, Function.identity()));
      Map<String, Attribute> existingAttrsMap =
          stream(existingEntityType.getOwnAllAttributes())
              .collect(toMap(Attribute::getName, Function.identity()));
  
      // determine attributes to add, update and delete
      Set<String> addedAttrNames = Sets.difference(attrsMap.keySet(), existingAttrsMap.keySet());
      Set<String> sharedAttrNames = Sets.intersection(attrsMap.keySet(), existingAttrsMap.keySet());
      Set<String> deletedAttrNames = Sets.difference(existingAttrsMap.keySet(), attrsMap.keySet());
  
      // add new attributes
      if (!addedAttrNames.isEmpty()) {
        dataService.add(ATTRIBUTE_META_DATA, addedAttrNames.stream().map(attrsMap::get));
      }
  
      // update changed attributes
      List<String> updatedAttrNames =
          sharedAttrNames
              .stream()
              .filter(
                  attrName ->
                      !EntityUtils.equals(attrsMap.get(attrName), existingAttrsMap.get(attrName)))
              .collect(toList());
      if (!updatedAttrNames.isEmpty()) {
        dataService.update(ATTRIBUTE_META_DATA, updatedAttrNames.stream().map(attrsMap::get));
      }
  
      // delete removed attributes
      if (!deletedAttrNames.isEmpty()) {
        dataService.delete(ATTRIBUTE_META_DATA, deletedAttrNames.stream().map(existingAttrsMap::get));
      }
    }
docs: Add and update entity attributes
  
  @param entityType entity meta data
  @param existingEntityType existing entity meta data