func SendNotifications(notifications []common.NotificationInfo) common.SyncServiceError {
	for _, notification := range notifications {
		if err := Comm.SendNotificationMessage(notification.NotificationTopic, notification.DestType, notification.DestID,
			notification.InstanceID, notification.DataID, notification.MetaData); err != nil {
			return &Error{err.Error()}
		}
	}
	return nil
}
SendNotifications calls the communication to send the notification messages
package communications
import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"github.com/open-horizon/edge-sync-service/common"
	"github.com/open-horizon/edge-sync-service/core/leader"
	"github.com/open-horizon/edge-utilities/logger"
	"github.com/open-horizon/edge-utilities/logger/log"
	"github.com/open-horizon/edge-utilities/logger/trace"
)
type invalidNotification struct {
	message string
}
func (e *invalidNotification) Error() string {
	return e.message
}
func PrepareObjectNotifications(metaData common.MetaData) ([]common.NotificationInfo, common.SyncServiceError) {
	lockIndex := common.HashStrings(metaData.DestOrgID, metaData.ObjectType, metaData.ObjectID)
	common.ObjectLocks.Lock(lockIndex)
	destinations, err := Store.GetObjectDestinations(metaData)
	if err == nil {
		err = Store.UpdateObjectDelivering(metaData.DestOrgID, metaData.ObjectType, metaData.ObjectID)
		if err != nil && log.IsLogging(logger.ERROR) {
			log.Error("Failed to update object's delivery status. Error: " + err.Error())
		}
		common.ObjectLocks.Unlock(lockIndex)
		return PrepareUpdateNotification(metaData, destinations)
	}
	common.ObjectLocks.Unlock(lockIndex)
	return nil, nil
}
func PrepareDeleteNotifications(metaData common.MetaData) ([]common.NotificationInfo, common.SyncServiceError) {
	lockIndex := common.HashStrings(metaData.DestOrgID, metaData.ObjectType, metaData.ObjectID)
	common.ObjectLocks.Lock(lockIndex)
	destinations, err := Store.GetObjectDestinations(metaData)
	if err != nil {
		common.ObjectLocks.Unlock(lockIndex)
		return nil, err
	}
	common.ObjectLocks.Unlock(lockIndex)
	return prepareNotifications(common.Delete, metaData, destinations)
}
func PrepareNotificationsForDestinations(metaData common.MetaData, destinations []common.StoreDestinationStatus, topic string) ([]common.NotificationInfo,
	common.SyncServiceError) {
	dests := make([]common.Destination, 0)
	for _, dest := range destinations {
		lockIndex := common.HashStrings(metaData.DestOrgID, metaData.ObjectType, metaData.ObjectID)
		common.ObjectLocks.Lock(lockIndex)
		if topic != common.Delete || (dest.Status == common.Delivering || dest.Status == common.Delivered || dest.Status == common.Consumed ||
			dest.Status == common.Error) {
			dests = append(dests, dest.Destination)
		}
		common.ObjectLocks.Unlock(lockIndex)
	}
	return prepareNotifications(topic, metaData, dests)
}
func prepareNotifications(topic string, metaData common.MetaData, destinations []common.Destination) ([]common.NotificationInfo, common.SyncServiceError) {
	result := make([]common.NotificationInfo, 0)
	for _, destination := range destinations {
		lockIndex := common.HashStrings(metaData.DestOrgID, metaData.ObjectType, metaData.ObjectID)
		common.ObjectLocks.Lock(lockIndex)
		notification := common.Notification{ObjectID: metaData.ObjectID, ObjectType: metaData.ObjectType,
			DestOrgID: metaData.DestOrgID, DestID: destination.DestID, DestType: destination.DestType,
			Status: topic, InstanceID: metaData.InstanceID, DataID: metaData.DataID}
		if trace.IsLogging(logger.DEBUG) {
			trace.Debug("In notification.go, prepareNotifications update notification for %s %s %s %s with status %s\n", metaData.ObjectType, metaData.ObjectID, destination.DestType, destination.DestID, topic)
		}
		if err := Store.UpdateNotificationRecord(notification); err != nil {
			common.ObjectLocks.Unlock(lockIndex)
			return nil, err
		}
		if trace.IsLogging(logger.DEBUG) {
			trace.Debug("In notification.go, prepareNotifications, update notification for %s %s %s %s with status %s is done\n", metaData.ObjectType, metaData.ObjectID, destination.DestType, destination.DestID, topic)
		}
		metaData.DestType = destination.DestType
		metaData.DestID = destination.DestID
		notificationInfo := common.NotificationInfo{NotificationTopic: topic, DestType: metaData.DestType, DestID: metaData.DestID,
			InstanceID: metaData.InstanceID, DataID: metaData.DataID, MetaData: &metaData}
		result = append(result, notificationInfo)
		common.ObjectLocks.Unlock(lockIndex)
	}
	return result, nil
}
func PrepareUpdateNotification(metaData common.MetaData, destinations []common.Destination) ([]common.NotificationInfo, common.SyncServiceError) {
	return prepareNotifications(common.Update, metaData, destinations)
}
func PrepareObjectStatusNotification(metaData common.MetaData, status string) ([]common.NotificationInfo, common.SyncServiceError) {
	lockIndex := common.HashStrings(metaData.DestOrgID, metaData.ObjectType, metaData.ObjectID)
	common.ObjectLocks.Lock(lockIndex)
	notification := common.Notification{ObjectID: metaData.ObjectID, ObjectType: metaData.ObjectType,
		DestOrgID: metaData.DestOrgID, DestID: metaData.OriginID, DestType: metaData.OriginType,
		Status: status, InstanceID: metaData.InstanceID, DataID: metaData.DataID}
	if trace.IsLogging(logger.DEBUG) {
		trace.Debug("In notification.go, PrepareObjectStatusNotification, update notification for %s %s %s %s with status %s\n", metaData.ObjectType, metaData.ObjectID, notification.DestType, notification.DestID, notification.Status)
	}
	if err := Store.UpdateNotificationRecord(notification); err != nil {
		common.ObjectLocks.Unlock(lockIndex)
		return nil, err
	}
	if trace.IsLogging(logger.DEBUG) {
		trace.Debug("In notification.go, PrepareObjectStatusNotification, update notification for %s %s %s %s with status %s is done\n", metaData.ObjectType, metaData.ObjectID, notification.DestType, notification.DestID, notification.Status)
	}
	notificationInfo := common.NotificationInfo{NotificationTopic: status, DestType: metaData.OriginType, DestID: metaData.OriginID,
		InstanceID: metaData.InstanceID, DataID: metaData.DataID, MetaData: &metaData}
	common.ObjectLocks.Unlock(lockIndex)
	return []common.NotificationInfo{notificationInfo}, nil
}