public void copySubscribers(AEntity from, AEntity to) {
   Subscription fromSubscription = subscriptionDao.getSubscriptionBySubject(from);
   if (fromSubscription == null || fromSubscription.isSubscribersEmailsEmpty()) return;
   Subscription toSubscription = subscriptionDao.getSubscriptionBySubject(to);
   if (toSubscription == null) toSubscription = subscriptionDao.postSubscription(to);
   toSubscription.addSubscribersEmails(fromSubscription.getSubscribersEmails());
 }
 public void subscribe(String email, AEntity subject) {
   if (!Str.isEmail(email)) throw new RuntimeException("Invalid email: " + email);
   email = email.toLowerCase();
   Subscription subscription = subscriptionDao.getSubscriptionBySubject(subject);
   if (subscription == null) subscription = subscriptionDao.postSubscription(subject);
   subscription.addSubscribersEmail(email);
   log.info(email, "subscribed to", subject);
 }
 public void unsubscribe(String email, AEntity subject, String key) throws InvalidKeyException {
   email = email.toLowerCase();
   if (!createKey(email).equals(key)) throw new InvalidKeyException(email);
   if (subject == null) {
     unsubscribeAll(email, key);
     return;
   }
   Subscription subscription = subscriptionDao.getSubscriptionBySubject(subject);
   if (subscription == null || !subscription.containsSubscribersEmail(email)) {
     log.debug(email, "is not subscribed to", subject);
     return;
   }
   subscription.removeSubscribersEmail(email);
   log.info(email, "unsubscribed from", subject);
 }
  public void notifySubscribers(
      AEntity subject, String message, Project project, String exceptionEmail) {
    Subscription subscription = subscriptionDao.getSubscriptionBySubject(subject);
    if (subscription == null || subscription.isSubscribersEmailsEmpty()) {
      log.debug("No subscribers for", subject);
      return;
    }

    Set<String> subscribersEmails = subscription.getSubscribersEmails();
    if (exceptionEmail != null) subscribersEmails.remove(exceptionEmail.toLowerCase());
    if (subscribersEmails.isEmpty()) {
      log.debug("No subscribers for", subject);
      return;
    }

    synchronized (notifications) {
      for (Notification notification : notifications) {
        if (!notification.subject.equals(subject)) continue;
        notification.merge(message, subscribersEmails);
        return;
      }
      notifications.add(new Notification(subject, message, project, subscribersEmails));
    }
  }