cloud-notifications: update to api 2.15

Change-Id: I60a708e68be51f20a84fe94452d385122d84468a
Signed-off-by: Jorge Ruesga <j.ruesga.criado@gmail.com>
diff --git a/BUILD b/BUILD
index ab3b9b8..70dd404 100644
--- a/BUILD
+++ b/BUILD
@@ -29,11 +29,10 @@
   resources = RESOURCES,
   manifest_entries = [
     'Gerrit-PluginName: cloud-notifications',
-    'Gerrit-ApiVersion: 2.14-SNAPSHOT',
+    'Gerrit-ApiVersion: 2.15',
     'Gerrit-Module: com.ruesga.gerrit.plugins.fcm.ApiModule',
     'Implementation-Title: Firebase Cloud Notifications Plugin',
-    'Implementation-URL: https://gerrit.googlesource.com/plugins/cloud-notifications',
-    'Implementation-Version: 2.14-SNAPSHOT'
+    'Implementation-URL: https://gerrit.googlesource.com/plugins/cloud-notifications'
   ],
   deps = DEPS
 )
diff --git a/src/main/java/com/ruesga/gerrit/plugins/fcm/ApiModule.java b/src/main/java/com/ruesga/gerrit/plugins/fcm/ApiModule.java
index 9947f29..5ddff04 100644
--- a/src/main/java/com/ruesga/gerrit/plugins/fcm/ApiModule.java
+++ b/src/main/java/com/ruesga/gerrit/plugins/fcm/ApiModule.java
@@ -20,39 +20,12 @@
 import static com.ruesga.gerrit.plugins.fcm.server.DeviceResource.DEVICE_KIND;
 import static com.ruesga.gerrit.plugins.fcm.server.TokenResource.TOKEN_KIND;
 
-import com.google.gerrit.extensions.events.AssigneeChangedListener;
-import com.google.gerrit.extensions.events.ChangeAbandonedListener;
-import com.google.gerrit.extensions.events.ChangeMergedListener;
-import com.google.gerrit.extensions.events.ChangeRestoredListener;
-import com.google.gerrit.extensions.events.ChangeRevertedListener;
-import com.google.gerrit.extensions.events.CommentAddedListener;
-import com.google.gerrit.extensions.events.DraftPublishedListener;
-import com.google.gerrit.extensions.events.HashtagsEditedListener;
-import com.google.gerrit.extensions.events.LifecycleListener;
-import com.google.gerrit.extensions.events.ReviewerAddedListener;
-import com.google.gerrit.extensions.events.ReviewerDeletedListener;
-import com.google.gerrit.extensions.events.RevisionCreatedListener;
-import com.google.gerrit.extensions.events.TopicEditedListener;
-import com.google.gerrit.extensions.events.VoteDeletedListener;
+import com.google.gerrit.extensions.events.*;
 import com.google.gerrit.extensions.registration.DynamicMap;
 import com.google.gerrit.extensions.registration.DynamicSet;
 import com.google.gerrit.extensions.restapi.RestApiModule;
 import com.google.inject.Scopes;
-import com.ruesga.gerrit.plugins.fcm.DatabaseManager;
-import com.ruesga.gerrit.plugins.fcm.handlers.AssigneeChangedEventHandler;
-import com.ruesga.gerrit.plugins.fcm.handlers.ChangeAbandonedEventHandler;
-import com.ruesga.gerrit.plugins.fcm.handlers.ChangeMergedEventHandler;
-import com.ruesga.gerrit.plugins.fcm.handlers.ChangeRestoredEventHandler;
-import com.ruesga.gerrit.plugins.fcm.handlers.ChangeRevertedEventHandler;
-import com.ruesga.gerrit.plugins.fcm.handlers.CommentAddedEventHandler;
-import com.ruesga.gerrit.plugins.fcm.handlers.DraftPublishedEventHandler;
-import com.ruesga.gerrit.plugins.fcm.handlers.HashtagsEditedEventHandler;
-import com.ruesga.gerrit.plugins.fcm.handlers.LifeCycleHandler;
-import com.ruesga.gerrit.plugins.fcm.handlers.ReviewerAddedEventHandler;
-import com.ruesga.gerrit.plugins.fcm.handlers.ReviewerDeletedEventHandler;
-import com.ruesga.gerrit.plugins.fcm.handlers.RevisionCreatedEventHandler;
-import com.ruesga.gerrit.plugins.fcm.handlers.TopicEditedEventHandler;
-import com.ruesga.gerrit.plugins.fcm.handlers.VoteDeletedEventHandler;
+import com.ruesga.gerrit.plugins.fcm.handlers.*;
 import com.ruesga.gerrit.plugins.fcm.server.DeleteToken;
 import com.ruesga.gerrit.plugins.fcm.server.Devices;
 import com.ruesga.gerrit.plugins.fcm.server.GetCloudNotificationsConfigInfo;
@@ -89,8 +62,6 @@
                 .to(ChangeRevertedEventHandler.class);
         DynamicSet.bind(binder(), CommentAddedListener.class)
                 .to(CommentAddedEventHandler.class);
-        DynamicSet.bind(binder(), DraftPublishedListener.class)
-                .to(DraftPublishedEventHandler.class);
         DynamicSet.bind(binder(), HashtagsEditedListener.class)
                 .to(HashtagsEditedEventHandler.class);
         DynamicSet.bind(binder(), ReviewerDeletedListener.class)
@@ -103,6 +74,10 @@
                 .to(TopicEditedEventHandler.class);
         DynamicSet.bind(binder(), VoteDeletedListener.class)
                 .to(VoteDeletedEventHandler.class);
+        DynamicSet.bind(binder(), PrivateStateChangedListener.class)
+                .to(PrivateStateChangedEventHandler.class);
+        DynamicSet.bind(binder(), WorkInProgressStateChangedListener.class)
+                .to(WIPStateChangedEventHandler.class);
 
         // Configure the Rest API
         DynamicMap.mapOf(binder(), DEVICE_KIND);
diff --git a/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/AssigneeChangedEventHandler.java b/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/AssigneeChangedEventHandler.java
index fa050ea..af788c1 100644
--- a/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/AssigneeChangedEventHandler.java
+++ b/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/AssigneeChangedEventHandler.java
@@ -18,10 +18,12 @@
 import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.extensions.common.AccountInfo;
 import com.google.gerrit.extensions.events.AssigneeChangedListener;
+import com.google.gerrit.server.AnonymousUser;
 import com.google.gerrit.server.IdentifiedUser.GenericFactory;
-import com.google.gerrit.server.account.CapabilityControl;
-import com.google.gerrit.server.account.WatchConfig.NotifyType;
+import com.google.gerrit.server.account.GroupBackend;
+import com.google.gerrit.server.account.ProjectWatches.NotifyType;
 import com.google.gerrit.server.config.AllProjectsName;
+import com.google.gerrit.server.project.ProjectCache;
 import com.google.gerrit.server.query.account.InternalAccountQuery;
 import com.google.gerrit.server.query.change.ChangeQueryBuilder;
 import com.google.gerrit.server.query.change.ChangeQueryProcessor;
@@ -47,16 +49,20 @@
             AllProjectsName allProjectsName,
             ChangeQueryBuilder cqb,
             ChangeQueryProcessor cqp,
+            ProjectCache projectCache,
+            GroupBackend groupBackend,
             Provider<InternalAccountQuery> accountQueryProvider,
-            CapabilityControl.Factory capabilityControlFactory,
-            GenericFactory identifiedUserFactory) {
+            GenericFactory identifiedUserFactory,
+            Provider<AnonymousUser> anonymousProvider) {
         super(pluginName,
                 uploader,
                 allProjectsName,
                 cqb, cqp,
+                projectCache,
+                groupBackend,
                 accountQueryProvider,
-                capabilityControlFactory,
-                identifiedUserFactory);
+                identifiedUserFactory,
+                anonymousProvider);
     }
 
     protected int getEventType() {
diff --git a/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/ChangeAbandonedEventHandler.java b/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/ChangeAbandonedEventHandler.java
index 6a7a859..86c6bf6 100644
--- a/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/ChangeAbandonedEventHandler.java
+++ b/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/ChangeAbandonedEventHandler.java
@@ -17,10 +17,12 @@
 
 import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.extensions.events.ChangeAbandonedListener;
+import com.google.gerrit.server.AnonymousUser;
 import com.google.gerrit.server.IdentifiedUser.GenericFactory;
-import com.google.gerrit.server.account.CapabilityControl;
-import com.google.gerrit.server.account.WatchConfig.NotifyType;
+import com.google.gerrit.server.account.GroupBackend;
+import com.google.gerrit.server.account.ProjectWatches.NotifyType;
 import com.google.gerrit.server.config.AllProjectsName;
+import com.google.gerrit.server.project.ProjectCache;
 import com.google.gerrit.server.query.account.InternalAccountQuery;
 import com.google.gerrit.server.query.change.ChangeQueryBuilder;
 import com.google.gerrit.server.query.change.ChangeQueryProcessor;
@@ -35,21 +37,25 @@
 
     @Inject
     public ChangeAbandonedEventHandler(
-            @PluginName String pluginName,
+          @PluginName String pluginName,
             FcmUploaderWorker uploader,
             AllProjectsName allProjectsName,
             ChangeQueryBuilder cqb,
             ChangeQueryProcessor cqp,
+            ProjectCache projectCache,
+            GroupBackend groupBackend,
             Provider<InternalAccountQuery> accountQueryProvider,
-            CapabilityControl.Factory capabilityControlFactory,
-            GenericFactory identifiedUserFactory) {
+            GenericFactory identifiedUserFactory,
+            Provider<AnonymousUser> anonymousProvider) {
         super(pluginName,
                 uploader,
                 allProjectsName,
                 cqb, cqp,
+                projectCache,
+                groupBackend,
                 accountQueryProvider,
-                capabilityControlFactory,
-                identifiedUserFactory);
+                identifiedUserFactory,
+                anonymousProvider);
     }
 
     protected int getEventType() {
diff --git a/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/ChangeMergedEventHandler.java b/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/ChangeMergedEventHandler.java
index bf8bc5a..5570996 100644
--- a/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/ChangeMergedEventHandler.java
+++ b/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/ChangeMergedEventHandler.java
@@ -17,10 +17,12 @@
 
 import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.extensions.events.ChangeMergedListener;
+import com.google.gerrit.server.AnonymousUser;
 import com.google.gerrit.server.IdentifiedUser.GenericFactory;
-import com.google.gerrit.server.account.CapabilityControl;
-import com.google.gerrit.server.account.WatchConfig.NotifyType;
+import com.google.gerrit.server.account.GroupBackend;
+import com.google.gerrit.server.account.ProjectWatches.NotifyType;
 import com.google.gerrit.server.config.AllProjectsName;
+import com.google.gerrit.server.project.ProjectCache;
 import com.google.gerrit.server.query.account.InternalAccountQuery;
 import com.google.gerrit.server.query.change.ChangeQueryBuilder;
 import com.google.gerrit.server.query.change.ChangeQueryProcessor;
@@ -40,16 +42,20 @@
             AllProjectsName allProjectsName,
             ChangeQueryBuilder cqb,
             ChangeQueryProcessor cqp,
+            ProjectCache projectCache,
+            GroupBackend groupBackend,
             Provider<InternalAccountQuery> accountQueryProvider,
-            CapabilityControl.Factory capabilityControlFactory,
-            GenericFactory identifiedUserFactory) {
+            GenericFactory identifiedUserFactory,
+            Provider<AnonymousUser> anonymousProvider) {
         super(pluginName,
                 uploader,
                 allProjectsName,
                 cqb, cqp,
+                projectCache,
+                groupBackend,
                 accountQueryProvider,
-                capabilityControlFactory,
-                identifiedUserFactory);
+                identifiedUserFactory,
+                anonymousProvider);
     }
 
     protected int getEventType() {
diff --git a/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/ChangeRestoredEventHandler.java b/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/ChangeRestoredEventHandler.java
index a0976d9..2fa44aa 100644
--- a/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/ChangeRestoredEventHandler.java
+++ b/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/ChangeRestoredEventHandler.java
@@ -17,10 +17,12 @@
 
 import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.extensions.events.ChangeRestoredListener;
+import com.google.gerrit.server.AnonymousUser;
 import com.google.gerrit.server.IdentifiedUser.GenericFactory;
-import com.google.gerrit.server.account.CapabilityControl;
-import com.google.gerrit.server.account.WatchConfig.NotifyType;
+import com.google.gerrit.server.account.GroupBackend;
+import com.google.gerrit.server.account.ProjectWatches.NotifyType;
 import com.google.gerrit.server.config.AllProjectsName;
+import com.google.gerrit.server.project.ProjectCache;
 import com.google.gerrit.server.query.account.InternalAccountQuery;
 import com.google.gerrit.server.query.change.ChangeQueryBuilder;
 import com.google.gerrit.server.query.change.ChangeQueryProcessor;
@@ -40,16 +42,20 @@
             AllProjectsName allProjectsName,
             ChangeQueryBuilder cqb,
             ChangeQueryProcessor cqp,
+            ProjectCache projectCache,
+            GroupBackend groupBackend,
             Provider<InternalAccountQuery> accountQueryProvider,
-            CapabilityControl.Factory capabilityControlFactory,
-            GenericFactory identifiedUserFactory) {
+            GenericFactory identifiedUserFactory,
+            Provider<AnonymousUser> anonymousProvider) {
         super(pluginName,
                 uploader,
                 allProjectsName,
                 cqb, cqp,
+                projectCache,
+                groupBackend,
                 accountQueryProvider,
-                capabilityControlFactory,
-                identifiedUserFactory);
+                identifiedUserFactory,
+                anonymousProvider);
     }
 
     protected int getEventType() {
diff --git a/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/ChangeRevertedEventHandler.java b/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/ChangeRevertedEventHandler.java
index e859a17..c46aadd 100644
--- a/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/ChangeRevertedEventHandler.java
+++ b/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/ChangeRevertedEventHandler.java
@@ -17,10 +17,12 @@
 
 import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.extensions.events.ChangeRevertedListener;
+import com.google.gerrit.server.AnonymousUser;
 import com.google.gerrit.server.IdentifiedUser.GenericFactory;
-import com.google.gerrit.server.account.CapabilityControl;
-import com.google.gerrit.server.account.WatchConfig.NotifyType;
+import com.google.gerrit.server.account.GroupBackend;
+import com.google.gerrit.server.account.ProjectWatches.NotifyType;
 import com.google.gerrit.server.config.AllProjectsName;
+import com.google.gerrit.server.project.ProjectCache;
 import com.google.gerrit.server.query.account.InternalAccountQuery;
 import com.google.gerrit.server.query.change.ChangeQueryBuilder;
 import com.google.gerrit.server.query.change.ChangeQueryProcessor;
@@ -40,16 +42,20 @@
             AllProjectsName allProjectsName,
             ChangeQueryBuilder cqb,
             ChangeQueryProcessor cqp,
+            ProjectCache projectCache,
+            GroupBackend groupBackend,
             Provider<InternalAccountQuery> accountQueryProvider,
-            CapabilityControl.Factory capabilityControlFactory,
-            GenericFactory identifiedUserFactory) {
+            GenericFactory identifiedUserFactory,
+            Provider<AnonymousUser> anonymousProvider) {
         super(pluginName,
                 uploader,
                 allProjectsName,
                 cqb, cqp,
+                projectCache,
+                groupBackend,
                 accountQueryProvider,
-                capabilityControlFactory,
-                identifiedUserFactory);
+                identifiedUserFactory,
+                anonymousProvider);
     }
 
     protected int getEventType() {
diff --git a/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/CommentAddedEventHandler.java b/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/CommentAddedEventHandler.java
index 0ebe7dc..b047fc6 100644
--- a/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/CommentAddedEventHandler.java
+++ b/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/CommentAddedEventHandler.java
@@ -15,14 +15,14 @@
  */
 package com.ruesga.gerrit.plugins.fcm.handlers;
 
-import org.apache.commons.lang.StringUtils;
-
 import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.extensions.events.CommentAddedListener;
+import com.google.gerrit.server.AnonymousUser;
 import com.google.gerrit.server.IdentifiedUser.GenericFactory;
-import com.google.gerrit.server.account.CapabilityControl;
-import com.google.gerrit.server.account.WatchConfig.NotifyType;
+import com.google.gerrit.server.account.GroupBackend;
+import com.google.gerrit.server.account.ProjectWatches.NotifyType;
 import com.google.gerrit.server.config.AllProjectsName;
+import com.google.gerrit.server.project.ProjectCache;
 import com.google.gerrit.server.query.account.InternalAccountQuery;
 import com.google.gerrit.server.query.change.ChangeQueryBuilder;
 import com.google.gerrit.server.query.change.ChangeQueryProcessor;
@@ -32,6 +32,8 @@
 import com.ruesga.gerrit.plugins.fcm.rest.CloudNotificationEvents;
 import com.ruesga.gerrit.plugins.fcm.workers.FcmUploaderWorker;
 
+import org.apache.commons.lang.StringUtils;
+
 public class CommentAddedEventHandler extends EventHandler
         implements CommentAddedListener {
 
@@ -42,16 +44,20 @@
             AllProjectsName allProjectsName,
             ChangeQueryBuilder cqb,
             ChangeQueryProcessor cqp,
+            ProjectCache projectCache,
+            GroupBackend groupBackend,
             Provider<InternalAccountQuery> accountQueryProvider,
-            CapabilityControl.Factory capabilityControlFactory,
-            GenericFactory identifiedUserFactory) {
+            GenericFactory identifiedUserFactory,
+            Provider<AnonymousUser> anonymousProvider) {
         super(pluginName,
                 uploader,
                 allProjectsName,
                 cqb, cqp,
+                projectCache,
+                groupBackend,
                 accountQueryProvider,
-                capabilityControlFactory,
-                identifiedUserFactory);
+                identifiedUserFactory,
+                anonymousProvider);
     }
 
     protected int getEventType() {
@@ -66,11 +72,11 @@
     public void onCommentAdded(Event event) {
         Notification notification = createNotification(event);
         if (event.getComment() != null) {
-            notification.extra =
-                    StringUtils.abbreviate(event.getComment(), 250);
+          notification.extra =
+              StringUtils.abbreviate(event.getComment(), 250);
         }
         notification.body = formatAccount(event.getWho())
-                + " commented on this change";
+            + " commented on this change";
 
         notify(notification, event);
     }
diff --git a/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/EventHandler.java b/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/EventHandler.java
index 9c28cb2..99a8cdf 100644
--- a/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/EventHandler.java
+++ b/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/EventHandler.java
@@ -22,10 +22,9 @@
 import java.util.Map;
 import java.util.Set;
 
-import org.apache.commons.lang.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
+import com.google.common.collect.ImmutableSet;
+import com.google.gerrit.common.data.GroupDescription;
+import com.google.gerrit.common.data.GroupReference;
 import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.extensions.api.changes.NotifyHandling;
 import com.google.gerrit.extensions.client.ReviewerState;
@@ -33,22 +32,28 @@
 import com.google.gerrit.extensions.common.ChangeInfo;
 import com.google.gerrit.extensions.events.ChangeEvent;
 import com.google.gerrit.extensions.events.RevisionEvent;
+import com.google.gerrit.index.query.Predicate;
+import com.google.gerrit.index.query.QueryParseException;
+import com.google.gerrit.index.query.QueryResult;
 import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.server.AnonymousUser;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.IdentifiedUser.GenericFactory;
 import com.google.gerrit.server.account.AccountState;
-import com.google.gerrit.server.account.CapabilityControl;
-import com.google.gerrit.server.account.WatchConfig.NotifyType;
-import com.google.gerrit.server.account.WatchConfig.ProjectWatchKey;
+import com.google.gerrit.server.account.GroupBackend;
+import com.google.gerrit.server.account.ProjectWatches.NotifyType;
+import com.google.gerrit.server.account.ProjectWatches.ProjectWatchKey;
 import com.google.gerrit.server.config.AllProjectsName;
-import com.google.gerrit.server.query.Predicate;
-import com.google.gerrit.server.query.QueryParseException;
-import com.google.gerrit.server.query.QueryResult;
+import com.google.gerrit.server.git.NotifyConfig;
+import com.google.gerrit.server.project.ProjectCache;
+import com.google.gerrit.server.project.ProjectState;
 import com.google.gerrit.server.query.account.InternalAccountQuery;
 import com.google.gerrit.server.query.change.ChangeData;
 import com.google.gerrit.server.query.change.ChangeQueryBuilder;
 import com.google.gerrit.server.query.change.ChangeQueryProcessor;
+import com.google.gerrit.server.query.change.SingleGroupUser;
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
 import com.google.gwtorm.server.OrmException;
@@ -56,9 +61,13 @@
 import com.ruesga.gerrit.plugins.fcm.messaging.Notification;
 import com.ruesga.gerrit.plugins.fcm.workers.FcmUploaderWorker;
 
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 public abstract class EventHandler {
 
-    static final Logger log =
+    private static final Logger log =
             LoggerFactory.getLogger(EventHandler.class);
 
     private final String pluginName;
@@ -66,8 +75,11 @@
     private final AllProjectsName allProjectsName;
     private final ChangeQueryBuilder cqb;
     private final ChangeQueryProcessor cqp;
+    private final ProjectCache projectCache;
+    private final GroupBackend groupBackend;
     private final Provider<InternalAccountQuery> accountQueryProvider;
     private final GenericFactory identifiedUserFactory;
+    private final Provider<AnonymousUser> anonymousProvider;
     private final Gson gson;
 
     public EventHandler(
@@ -76,17 +88,22 @@
             AllProjectsName allProjectsName,
             ChangeQueryBuilder cqb,
             ChangeQueryProcessor cqp,
+            ProjectCache projectCache,
+            GroupBackend groupBackend,
             Provider<InternalAccountQuery> accountQueryProvider,
-            CapabilityControl.Factory capabilityControlFactory,
-            GenericFactory identifiedUserFactory) {
+            GenericFactory identifiedUserFactory,
+            Provider<AnonymousUser> anonymousProvider) {
         super();
         this.pluginName = pluginName;
         this.uploader = uploader;
         this.allProjectsName = allProjectsName;
         this.cqb = cqb;
         this.cqp = cqp;
+        this.projectCache = projectCache;
+        this.groupBackend = groupBackend;
         this.accountQueryProvider = accountQueryProvider;
         this.identifiedUserFactory = identifiedUserFactory;
+        this.anonymousProvider = anonymousProvider;
         this.gson = new GsonBuilder().create();
     }
 
@@ -94,7 +111,7 @@
 
     protected abstract NotifyType getNotifyType();
 
-    protected Gson getSerializer() {
+    Gson getSerializer() {
         return this.gson;
     }
 
@@ -169,7 +186,10 @@
 
         // 3.- Watchers
         ChangeData changeData = obtainChangeData(change);
-        notifiedUsers.addAll(getWatchers(getNotifyType(), changeData));
+        if (changeData != null) {
+            notifiedUsers.addAll(getWatchers(getNotifyType(), changeData,
+                    !safeBoolean(change.workInProgress) && !safeBoolean(change.isPrivate)));
+        }
 
         // 4.- Remove the author of this event (he doesn't need to get
         // the notification)
@@ -178,14 +198,14 @@
         return new ArrayList<>(notifiedUsers);
     }
 
-    public final Set<Integer> getWatchers(NotifyType type, ChangeData change) {
+    private Set<Integer> getWatchers(NotifyType type, ChangeData change, boolean includeWatchersFromNotifyConfig) {
         Set<Integer> watchers = new HashSet<>();
         try {
             Set<Account.Id> projectWatchers = new HashSet<>();
             for (AccountState a : accountQueryProvider.get().byWatchedProject(
                     change.project())) {
                 Account.Id accountId = a.getAccount().getId();
-                for (Map.Entry<ProjectWatchKey, Set<NotifyType>> e : a.getProjectWatches().entrySet()) {
+                for (Map.Entry<ProjectWatchKey, ImmutableSet<NotifyType>> e : a.getProjectWatches().entrySet()) {
                     if (change.project().equals(e.getKey().project())
                             && add(watchers, accountId, e.getKey(), e.getValue(), type, change)) {
                         // We only want to prevent matching All-Projects if this filter hits
@@ -194,16 +214,37 @@
                 }
             }
 
-            for (AccountState a : accountQueryProvider.get().byWatchedProject(
-                    allProjectsName)) {
-              for (Map.Entry<ProjectWatchKey, Set<NotifyType>> e : a.getProjectWatches().entrySet()) {
-                if (allProjectsName.equals(e.getKey().project())) {
-                  Account.Id accountId = a.getAccount().getId();
-                  if (!projectWatchers.contains(accountId)) {
-                    add(watchers, accountId, e.getKey(), e.getValue(), type, change);
-                  }
+            for (AccountState a : accountQueryProvider.get().byWatchedProject(allProjectsName)) {
+              for (Map.Entry<ProjectWatchKey, ImmutableSet<NotifyType>> e : a.getProjectWatches().entrySet()) {
+                    if (allProjectsName.equals(e.getKey().project())) {
+                        Account.Id accountId = a.getAccount().getId();
+                        if (!projectWatchers.contains(accountId)) {
+                            add(watchers, accountId, e.getKey(), e.getValue(), type, change);
+                        }
+                    }
                 }
-              }
+            }
+
+            if (includeWatchersFromNotifyConfig) {
+                ProjectState projectState = projectCache.get(change.project());
+                if (projectState != null) {
+                    for (ProjectState state : projectState.tree()) {
+                        for (NotifyConfig nc : state.getConfig().getNotifyConfigs()) {
+                            if (nc.isNotify(type)) {
+                                try {
+                                    add(watchers, nc, change);
+                                } catch (QueryParseException e) {
+                                    log.warn(
+                                        "Project {} has invalid notify {} filter \"{}\": {}",
+                                        state.getName(),
+                                        nc.getName(),
+                                        nc.getFilter(),
+                                        e.getMessage());
+                                }
+                            }
+                        }
+                    }
+                }
             }
 
         } catch (OrmException ex) {
@@ -233,11 +274,27 @@
         return false;
     }
 
+    private void add(Set<Integer> watchers, NotifyConfig nc, ChangeData change)
+            throws OrmException, QueryParseException {
+        for (GroupReference ref : nc.getGroups()) {
+            CurrentUser user = new SingleGroupUser(ref.getUUID());
+            if (filterMatch(user, nc.getFilter(), change)) {
+                deliverToMembers(watchers, ref.getUUID());
+            }
+        }
+    }
+
     private boolean filterMatch(
             CurrentUser user, String filter, ChangeData change)
             throws OrmException, QueryParseException {
-        ChangeQueryBuilder qb = cqb.asUser(user);
-        Predicate<ChangeData> p = qb.is_visible();
+        ChangeQueryBuilder qb;
+        Predicate<ChangeData> p = null;
+        if (user == null) {
+            qb = cqb.asUser(anonymousProvider.get());
+        } else {
+            qb = cqb.asUser(user);
+            p = qb.is_visible();
+        }
 
         if (filter != null) {
             Predicate<ChangeData> filterPredicate = qb.parse(filter);
@@ -269,6 +326,37 @@
         return null;
     }
 
+    private void deliverToMembers(Set<Integer> watchers, AccountGroup.UUID startUUID) {
+        Set<AccountGroup.UUID> seen = new HashSet<>();
+        List<AccountGroup.UUID> q = new ArrayList<>();
+
+        seen.add(startUUID);
+        q.add(startUUID);
+
+        while (!q.isEmpty()) {
+            AccountGroup.UUID uuid = q.remove(q.size() - 1);
+            GroupDescription.Basic group = groupBackend.get(uuid);
+            if (group == null) {
+                continue;
+            }
+
+            if (!(group instanceof GroupDescription.Internal)) {
+                // Non-internal groups cannot be expanded by the server.
+                continue;
+            }
+
+            GroupDescription.Internal ig = (GroupDescription.Internal) group;
+            for (Account.Id id : ig.getMembers()) {
+                watchers.add(id.get());
+            }
+            for (AccountGroup.UUID m : ig.getSubgroups()) {
+                if (seen.add(m)) {
+                    q.add(m);
+                }
+            }
+        }
+    }
+
     protected String formatAccount(AccountInfo account) {
         if (account.name != null) {
             return account.name;
@@ -278,4 +366,8 @@
         }
         return account.email;
     }
+
+    boolean safeBoolean(Boolean value) {
+        return value != null && value;
+    }
 }
diff --git a/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/HashtagsEditedEventHandler.java b/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/HashtagsEditedEventHandler.java
index 992fd5d..d112072 100644
--- a/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/HashtagsEditedEventHandler.java
+++ b/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/HashtagsEditedEventHandler.java
@@ -17,10 +17,12 @@
 
 import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.extensions.events.HashtagsEditedListener;
+import com.google.gerrit.server.AnonymousUser;
 import com.google.gerrit.server.IdentifiedUser.GenericFactory;
-import com.google.gerrit.server.account.CapabilityControl;
-import com.google.gerrit.server.account.WatchConfig.NotifyType;
+import com.google.gerrit.server.account.GroupBackend;
+import com.google.gerrit.server.account.ProjectWatches.NotifyType;
 import com.google.gerrit.server.config.AllProjectsName;
+import com.google.gerrit.server.project.ProjectCache;
 import com.google.gerrit.server.query.account.InternalAccountQuery;
 import com.google.gerrit.server.query.change.ChangeQueryBuilder;
 import com.google.gerrit.server.query.change.ChangeQueryProcessor;
@@ -46,16 +48,20 @@
             AllProjectsName allProjectsName,
             ChangeQueryBuilder cqb,
             ChangeQueryProcessor cqp,
+            ProjectCache projectCache,
+            GroupBackend groupBackend,
             Provider<InternalAccountQuery> accountQueryProvider,
-            CapabilityControl.Factory capabilityControlFactory,
-            GenericFactory identifiedUserFactory) {
+            GenericFactory identifiedUserFactory,
+            Provider<AnonymousUser> anonymousProvider) {
         super(pluginName,
                 uploader,
                 allProjectsName,
                 cqb, cqp,
+                projectCache,
+                groupBackend,
                 accountQueryProvider,
-                capabilityControlFactory,
-                identifiedUserFactory);
+                identifiedUserFactory,
+                anonymousProvider);
     }
 
     protected int getEventType() {
@@ -70,12 +76,10 @@
     public void onHashtagsEdited(Event event) {
         HashtagsInfo hashtags = new HashtagsInfo();
         if (event.getRemovedHashtags() != null) {
-            hashtags.removed = event.getRemovedHashtags().toArray(
-                    new String[event.getRemovedHashtags().size()]);
+            hashtags.removed = event.getRemovedHashtags().toArray(new String[0]);
         }
         if (event.getAddedHashtags() != null) {
-            hashtags.added = event.getAddedHashtags().toArray(
-                    new String[event.getAddedHashtags().size()]);
+            hashtags.added = event.getAddedHashtags().toArray(new String[0]);
         }
         Notification notification = createNotification(event);
         notification.extra = getSerializer().toJson(hashtags);
diff --git a/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/DraftPublishedEventHandler.java b/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/PrivateStateChangedEventHandler.java
similarity index 66%
rename from src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/DraftPublishedEventHandler.java
rename to src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/PrivateStateChangedEventHandler.java
index eaffee9..eb32e45 100644
--- a/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/DraftPublishedEventHandler.java
+++ b/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/PrivateStateChangedEventHandler.java
@@ -16,11 +16,13 @@
 package com.ruesga.gerrit.plugins.fcm.handlers;
 
 import com.google.gerrit.extensions.annotations.PluginName;
-import com.google.gerrit.extensions.events.DraftPublishedListener;
+import com.google.gerrit.extensions.events.PrivateStateChangedListener;
+import com.google.gerrit.server.AnonymousUser;
 import com.google.gerrit.server.IdentifiedUser.GenericFactory;
+import com.google.gerrit.server.account.GroupBackend;
+import com.google.gerrit.server.account.ProjectWatches.NotifyType;
 import com.google.gerrit.server.config.AllProjectsName;
-import com.google.gerrit.server.account.CapabilityControl;
-import com.google.gerrit.server.account.WatchConfig.NotifyType;
+import com.google.gerrit.server.project.ProjectCache;
 import com.google.gerrit.server.query.account.InternalAccountQuery;
 import com.google.gerrit.server.query.change.ChangeQueryBuilder;
 import com.google.gerrit.server.query.change.ChangeQueryProcessor;
@@ -30,30 +32,34 @@
 import com.ruesga.gerrit.plugins.fcm.rest.CloudNotificationEvents;
 import com.ruesga.gerrit.plugins.fcm.workers.FcmUploaderWorker;
 
-public class DraftPublishedEventHandler extends EventHandler
-        implements DraftPublishedListener {
+public class PrivateStateChangedEventHandler extends EventHandler
+        implements PrivateStateChangedListener {
 
     @Inject
-    public DraftPublishedEventHandler(
+    public PrivateStateChangedEventHandler(
             @PluginName String pluginName,
             FcmUploaderWorker uploader,
             AllProjectsName allProjectsName,
             ChangeQueryBuilder cqb,
             ChangeQueryProcessor cqp,
+            ProjectCache projectCache,
+            GroupBackend groupBackend,
             Provider<InternalAccountQuery> accountQueryProvider,
-            CapabilityControl.Factory capabilityControlFactory,
-            GenericFactory identifiedUserFactory) {
+            GenericFactory identifiedUserFactory,
+            Provider<AnonymousUser> anonymousProvider) {
         super(pluginName,
                 uploader,
                 allProjectsName,
                 cqb, cqp,
+                projectCache,
+                groupBackend,
                 accountQueryProvider,
-                capabilityControlFactory,
-                identifiedUserFactory);
+                identifiedUserFactory,
+                anonymousProvider);
     }
 
     protected int getEventType() {
-        return CloudNotificationEvents.DRAFT_PUBLISHED_EVENT;
+        return CloudNotificationEvents.PRIVATE_STATE_CHANGED_EVENT;
     }
 
     protected NotifyType getNotifyType() {
@@ -61,11 +67,11 @@
     }
 
     @Override
-    public void onDraftPublished(Event event) {
+    public void onPrivateStateChanged(Event event) {
         Notification notification = createNotification(event);
         notification.body = formatAccount(event.getWho())
-                + " published a draft on this change";
-
+                + " change state of this change to " +
+                      (safeBoolean(event.getChange().isPrivate) ? "private" : "public");
         notify(notification, event);
     }
 
diff --git a/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/ReviewerAddedEventHandler.java b/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/ReviewerAddedEventHandler.java
index bb4b561..49e66c1 100644
--- a/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/ReviewerAddedEventHandler.java
+++ b/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/ReviewerAddedEventHandler.java
@@ -20,10 +20,12 @@
 import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.extensions.common.AccountInfo;
 import com.google.gerrit.extensions.events.ReviewerAddedListener;
+import com.google.gerrit.server.AnonymousUser;
 import com.google.gerrit.server.IdentifiedUser.GenericFactory;
-import com.google.gerrit.server.account.CapabilityControl;
-import com.google.gerrit.server.account.WatchConfig.NotifyType;
+import com.google.gerrit.server.account.GroupBackend;
+import com.google.gerrit.server.account.ProjectWatches.NotifyType;
 import com.google.gerrit.server.config.AllProjectsName;
+import com.google.gerrit.server.project.ProjectCache;
 import com.google.gerrit.server.query.account.InternalAccountQuery;
 import com.google.gerrit.server.query.change.ChangeQueryBuilder;
 import com.google.gerrit.server.query.change.ChangeQueryProcessor;
@@ -43,16 +45,20 @@
             AllProjectsName allProjectsName,
             ChangeQueryBuilder cqb,
             ChangeQueryProcessor cqp,
+            ProjectCache projectCache,
+            GroupBackend groupBackend,
             Provider<InternalAccountQuery> accountQueryProvider,
-            CapabilityControl.Factory capabilityControlFactory,
-            GenericFactory identifiedUserFactory) {
+            GenericFactory identifiedUserFactory,
+            Provider<AnonymousUser> anonymousProvider) {
         super(pluginName,
                 uploader,
                 allProjectsName,
                 cqb, cqp,
+                projectCache,
+                groupBackend,
                 accountQueryProvider,
-                capabilityControlFactory,
-                identifiedUserFactory);
+                identifiedUserFactory,
+                anonymousProvider);
     }
 
     protected int getEventType() {
diff --git a/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/ReviewerDeletedEventHandler.java b/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/ReviewerDeletedEventHandler.java
index ffbabcf..1ea1258 100644
--- a/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/ReviewerDeletedEventHandler.java
+++ b/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/ReviewerDeletedEventHandler.java
@@ -17,10 +17,12 @@
 
 import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.extensions.events.ReviewerDeletedListener;
+import com.google.gerrit.server.AnonymousUser;
 import com.google.gerrit.server.IdentifiedUser.GenericFactory;
-import com.google.gerrit.server.account.CapabilityControl;
-import com.google.gerrit.server.account.WatchConfig.NotifyType;
+import com.google.gerrit.server.account.GroupBackend;
+import com.google.gerrit.server.account.ProjectWatches.NotifyType;
 import com.google.gerrit.server.config.AllProjectsName;
+import com.google.gerrit.server.project.ProjectCache;
 import com.google.gerrit.server.query.account.InternalAccountQuery;
 import com.google.gerrit.server.query.change.ChangeQueryBuilder;
 import com.google.gerrit.server.query.change.ChangeQueryProcessor;
@@ -40,16 +42,20 @@
             AllProjectsName allProjectsName,
             ChangeQueryBuilder cqb,
             ChangeQueryProcessor cqp,
+            ProjectCache projectCache,
+            GroupBackend groupBackend,
             Provider<InternalAccountQuery> accountQueryProvider,
-            CapabilityControl.Factory capabilityControlFactory,
-            GenericFactory identifiedUserFactory) {
+            GenericFactory identifiedUserFactory,
+            Provider<AnonymousUser> anonymousProvider) {
         super(pluginName,
                 uploader,
                 allProjectsName,
                 cqb, cqp,
+                projectCache,
+                groupBackend,
                 accountQueryProvider,
-                capabilityControlFactory,
-                identifiedUserFactory);
+                identifiedUserFactory,
+                anonymousProvider);
     }
 
     protected int getEventType() {
diff --git a/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/RevisionCreatedEventHandler.java b/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/RevisionCreatedEventHandler.java
index 946d113..e410510 100644
--- a/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/RevisionCreatedEventHandler.java
+++ b/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/RevisionCreatedEventHandler.java
@@ -17,10 +17,12 @@
 
 import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.extensions.events.RevisionCreatedListener;
+import com.google.gerrit.server.AnonymousUser;
 import com.google.gerrit.server.IdentifiedUser.GenericFactory;
-import com.google.gerrit.server.account.CapabilityControl;
-import com.google.gerrit.server.account.WatchConfig.NotifyType;
+import com.google.gerrit.server.account.GroupBackend;
+import com.google.gerrit.server.account.ProjectWatches.NotifyType;
 import com.google.gerrit.server.config.AllProjectsName;
+import com.google.gerrit.server.project.ProjectCache;
 import com.google.gerrit.server.query.account.InternalAccountQuery;
 import com.google.gerrit.server.query.change.ChangeQueryBuilder;
 import com.google.gerrit.server.query.change.ChangeQueryProcessor;
@@ -40,16 +42,20 @@
             AllProjectsName allProjectsName,
             ChangeQueryBuilder cqb,
             ChangeQueryProcessor cqp,
+            ProjectCache projectCache,
+            GroupBackend groupBackend,
             Provider<InternalAccountQuery> accountQueryProvider,
-            CapabilityControl.Factory capabilityControlFactory,
-            GenericFactory identifiedUserFactory) {
+            GenericFactory identifiedUserFactory,
+            Provider<AnonymousUser> anonymousProvider) {
         super(pluginName,
                 uploader,
                 allProjectsName,
                 cqb, cqp,
+                projectCache,
+                groupBackend,
                 accountQueryProvider,
-                capabilityControlFactory,
-                identifiedUserFactory);
+                identifiedUserFactory,
+                anonymousProvider);
     }
 
     protected int getEventType() {
diff --git a/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/TopicEditedEventHandler.java b/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/TopicEditedEventHandler.java
index e255b6b..24102b6 100644
--- a/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/TopicEditedEventHandler.java
+++ b/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/TopicEditedEventHandler.java
@@ -17,10 +17,12 @@
 
 import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.extensions.events.TopicEditedListener;
+import com.google.gerrit.server.AnonymousUser;
 import com.google.gerrit.server.IdentifiedUser.GenericFactory;
-import com.google.gerrit.server.account.CapabilityControl;
-import com.google.gerrit.server.account.WatchConfig.NotifyType;
+import com.google.gerrit.server.account.GroupBackend;
+import com.google.gerrit.server.account.ProjectWatches.NotifyType;
 import com.google.gerrit.server.config.AllProjectsName;
+import com.google.gerrit.server.project.ProjectCache;
 import com.google.gerrit.server.query.account.InternalAccountQuery;
 import com.google.gerrit.server.query.change.ChangeQueryBuilder;
 import com.google.gerrit.server.query.change.ChangeQueryProcessor;
@@ -45,16 +47,20 @@
             AllProjectsName allProjectsName,
             ChangeQueryBuilder cqb,
             ChangeQueryProcessor cqp,
+            ProjectCache projectCache,
+            GroupBackend groupBackend,
             Provider<InternalAccountQuery> accountQueryProvider,
-            CapabilityControl.Factory capabilityControlFactory,
-            GenericFactory identifiedUserFactory) {
+            GenericFactory identifiedUserFactory,
+            Provider<AnonymousUser> anonymousProvider) {
         super(pluginName,
                 uploader,
                 allProjectsName,
                 cqb, cqp,
+                projectCache,
+                groupBackend,
                 accountQueryProvider,
-                capabilityControlFactory,
-                identifiedUserFactory);
+                identifiedUserFactory,
+                anonymousProvider);
     }
 
     protected int getEventType() {
diff --git a/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/VoteDeletedEventHandler.java b/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/VoteDeletedEventHandler.java
index a54b3c9..3f639d8 100644
--- a/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/VoteDeletedEventHandler.java
+++ b/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/VoteDeletedEventHandler.java
@@ -20,10 +20,12 @@
 import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.extensions.common.ApprovalInfo;
 import com.google.gerrit.extensions.events.VoteDeletedListener;
+import com.google.gerrit.server.AnonymousUser;
 import com.google.gerrit.server.IdentifiedUser.GenericFactory;
-import com.google.gerrit.server.account.CapabilityControl;
-import com.google.gerrit.server.account.WatchConfig.NotifyType;
+import com.google.gerrit.server.account.GroupBackend;
+import com.google.gerrit.server.account.ProjectWatches.NotifyType;
 import com.google.gerrit.server.config.AllProjectsName;
+import com.google.gerrit.server.project.ProjectCache;
 import com.google.gerrit.server.query.account.InternalAccountQuery;
 import com.google.gerrit.server.query.change.ChangeQueryBuilder;
 import com.google.gerrit.server.query.change.ChangeQueryProcessor;
@@ -53,16 +55,20 @@
             AllProjectsName allProjectsName,
             ChangeQueryBuilder cqb,
             ChangeQueryProcessor cqp,
+            ProjectCache projectCache,
+            GroupBackend groupBackend,
             Provider<InternalAccountQuery> accountQueryProvider,
-            CapabilityControl.Factory capabilityControlFactory,
-            GenericFactory identifiedUserFactory) {
+            GenericFactory identifiedUserFactory,
+            Provider<AnonymousUser> anonymousProvider) {
         super(pluginName,
                 uploader,
                 allProjectsName,
                 cqb, cqp,
+                projectCache,
+                groupBackend,
                 accountQueryProvider,
-                capabilityControlFactory,
-                identifiedUserFactory);
+                identifiedUserFactory,
+                anonymousProvider);
     }
 
     protected int getEventType() {
@@ -91,11 +97,11 @@
 
     private VoteDeletedInfo toVoteDeletedInfo(Event event) {
         VoteDeletedInfo info = new VoteDeletedInfo();
-        Collection<ApprovalInfo> approvals = event.getRemoved().values();
+        Collection<ApprovalInfo> approvals = event.getOldApprovals().values();
         int count = approvals.size();
         info.votes = new VoteDeletedEntryInfo[count];
         for (int i = 0; i < count; i++)
-        for (ApprovalInfo approval : event.getRemoved().values()) {
+        for (ApprovalInfo approval : event.getOldApprovals().values()) {
             info.votes[i] = new VoteDeletedEntryInfo();
             info.votes[i].vote = approval.tag + + approval.value;
             info.votes[i].account = formatAccount(approval);
diff --git a/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/DraftPublishedEventHandler.java b/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/WIPStateChangedEventHandler.java
similarity index 66%
copy from src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/DraftPublishedEventHandler.java
copy to src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/WIPStateChangedEventHandler.java
index eaffee9..9179b1f 100644
--- a/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/DraftPublishedEventHandler.java
+++ b/src/main/java/com/ruesga/gerrit/plugins/fcm/handlers/WIPStateChangedEventHandler.java
@@ -16,11 +16,13 @@
 package com.ruesga.gerrit.plugins.fcm.handlers;
 
 import com.google.gerrit.extensions.annotations.PluginName;
-import com.google.gerrit.extensions.events.DraftPublishedListener;
+import com.google.gerrit.extensions.events.WorkInProgressStateChangedListener;
+import com.google.gerrit.server.AnonymousUser;
 import com.google.gerrit.server.IdentifiedUser.GenericFactory;
+import com.google.gerrit.server.account.GroupBackend;
+import com.google.gerrit.server.account.ProjectWatches.NotifyType;
 import com.google.gerrit.server.config.AllProjectsName;
-import com.google.gerrit.server.account.CapabilityControl;
-import com.google.gerrit.server.account.WatchConfig.NotifyType;
+import com.google.gerrit.server.project.ProjectCache;
 import com.google.gerrit.server.query.account.InternalAccountQuery;
 import com.google.gerrit.server.query.change.ChangeQueryBuilder;
 import com.google.gerrit.server.query.change.ChangeQueryProcessor;
@@ -30,30 +32,34 @@
 import com.ruesga.gerrit.plugins.fcm.rest.CloudNotificationEvents;
 import com.ruesga.gerrit.plugins.fcm.workers.FcmUploaderWorker;
 
-public class DraftPublishedEventHandler extends EventHandler
-        implements DraftPublishedListener {
+public class WIPStateChangedEventHandler extends EventHandler
+        implements WorkInProgressStateChangedListener {
 
     @Inject
-    public DraftPublishedEventHandler(
+    public WIPStateChangedEventHandler(
             @PluginName String pluginName,
             FcmUploaderWorker uploader,
             AllProjectsName allProjectsName,
             ChangeQueryBuilder cqb,
             ChangeQueryProcessor cqp,
+            ProjectCache projectCache,
+            GroupBackend groupBackend,
             Provider<InternalAccountQuery> accountQueryProvider,
-            CapabilityControl.Factory capabilityControlFactory,
-            GenericFactory identifiedUserFactory) {
+            GenericFactory identifiedUserFactory,
+            Provider<AnonymousUser> anonymousProvider) {
         super(pluginName,
                 uploader,
                 allProjectsName,
                 cqb, cqp,
+                projectCache,
+                groupBackend,
                 accountQueryProvider,
-                capabilityControlFactory,
-                identifiedUserFactory);
+                identifiedUserFactory,
+                anonymousProvider);
     }
 
     protected int getEventType() {
-        return CloudNotificationEvents.DRAFT_PUBLISHED_EVENT;
+        return CloudNotificationEvents.WIP_STATE_CHANGED_EVENT;
     }
 
     protected NotifyType getNotifyType() {
@@ -61,11 +67,11 @@
     }
 
     @Override
-    public void onDraftPublished(Event event) {
+    public void onWorkInProgressStateChanged(Event event) {
         Notification notification = createNotification(event);
         notification.body = formatAccount(event.getWho())
-                + " published a draft on this change";
-
+                + " change state of this change to " +
+                    (safeBoolean(event.getChange().isPrivate) ? "WIP" : "ready");
         notify(notification, event);
     }
 
diff --git a/src/main/java/com/ruesga/gerrit/plugins/fcm/messaging/Notification.java b/src/main/java/com/ruesga/gerrit/plugins/fcm/messaging/Notification.java
index cfe4a92..69a45ba 100644
--- a/src/main/java/com/ruesga/gerrit/plugins/fcm/messaging/Notification.java
+++ b/src/main/java/com/ruesga/gerrit/plugins/fcm/messaging/Notification.java
@@ -35,7 +35,7 @@
 
     @Override
     public Object clone() {
-        Notification other = new Notification();
+      Notification other = new Notification();
         other.when = when;
         other.who = who;
         other.token = token;
diff --git a/src/main/java/com/ruesga/gerrit/plugins/fcm/rest/CloudNotificationEvents.java b/src/main/java/com/ruesga/gerrit/plugins/fcm/rest/CloudNotificationEvents.java
index 0aa40b3..4fe7b0e 100644
--- a/src/main/java/com/ruesga/gerrit/plugins/fcm/rest/CloudNotificationEvents.java
+++ b/src/main/java/com/ruesga/gerrit/plugins/fcm/rest/CloudNotificationEvents.java
@@ -21,7 +21,7 @@
     public static final int CHANGE_RESTORED_EVENT = 0x04;
     public static final int CHANGE_REVERTED_EVENT = 0x08;
     public static final int COMMENT_ADDED_EVENT = 0x10;
-    public static final int DRAFT_PUBLISHED_EVENT = 0x20;
+    // removed => public static final int DRAFT_PUBLISHED_EVENT = 0x20;
     public static final int HASHTAG_CHANGED_EVENT = 0x40;
     public static final int REVIEWER_ADDED_EVENT = 0x80;
     public static final int REVIEWER_DELETED_EVENT = 0x100;
@@ -29,4 +29,6 @@
     public static final int TOPIC_CHANGED_EVENT = 0x400;
     public static final int ASSIGNEE_CHANGED_EVENT = 0x800;
     public static final int VOTE_DELETED_EVENT = 0x1000;
+    public static final int PRIVATE_STATE_CHANGED_EVENT = 0x2000;
+    public static final int WIP_STATE_CHANGED_EVENT = 0x4000;
 }
diff --git a/src/main/java/com/ruesga/gerrit/plugins/fcm/server/DeviceResource.java b/src/main/java/com/ruesga/gerrit/plugins/fcm/server/DeviceResource.java
index a6cd2e7..d090140 100644
--- a/src/main/java/com/ruesga/gerrit/plugins/fcm/server/DeviceResource.java
+++ b/src/main/java/com/ruesga/gerrit/plugins/fcm/server/DeviceResource.java
@@ -26,7 +26,7 @@
 
     private final String device;
 
-    public DeviceResource(IdentifiedUser user, String device) {
+    DeviceResource(IdentifiedUser user, String device) {
       super(user);
       this.device = device;
     }
diff --git a/src/main/java/com/ruesga/gerrit/plugins/fcm/server/TokenResource.java b/src/main/java/com/ruesga/gerrit/plugins/fcm/server/TokenResource.java
index 336343f..e91c3b6 100644
--- a/src/main/java/com/ruesga/gerrit/plugins/fcm/server/TokenResource.java
+++ b/src/main/java/com/ruesga/gerrit/plugins/fcm/server/TokenResource.java
@@ -24,7 +24,7 @@
 
     private final String token;
 
-    public TokenResource(DeviceResource rsrc, String token) {
+    TokenResource(DeviceResource rsrc, String token) {
       super(rsrc.getUser(), rsrc.getDevice());
       this.token = token;
     }
diff --git a/src/main/java/com/ruesga/gerrit/plugins/fcm/workers/FcmUploaderWorker.java b/src/main/java/com/ruesga/gerrit/plugins/fcm/workers/FcmUploaderWorker.java
index b03aa65..ee0b4de 100644
--- a/src/main/java/com/ruesga/gerrit/plugins/fcm/workers/FcmUploaderWorker.java
+++ b/src/main/java/com/ruesga/gerrit/plugins/fcm/workers/FcmUploaderWorker.java
@@ -17,7 +17,6 @@
 
 import java.io.BufferedReader;
 import java.io.DataOutputStream;
-import java.io.IOException;
 import java.io.InputStreamReader;
 import java.net.HttpURLConnection;
 import java.net.URL;
@@ -92,12 +91,7 @@
         }
 
         for (final Integer accountId : notifiedAccounts) {
-            this.executor.submit(new Runnable() {
-                @Override
-                public void run() {
-                    asyncNotify(accountId, notification);
-                }
-            });
+            this.executor.submit(() -> asyncNotify(accountId, notification));
         }
     }
 
@@ -133,34 +127,20 @@
             conn.setRequestProperty(
                     "Content-Length", Integer.toString(data.length()));
 
-            DataOutputStream os = new DataOutputStream(conn.getOutputStream());
-            try {
+            try (DataOutputStream os = new DataOutputStream(conn.getOutputStream())) {
                 os.write(data.getBytes());
                 os.flush();
-            } finally {
-                try {
-                    os.close();
-                } catch (IOException ex) {
-                    // Ignore
-                }
             }
 
             int responseCode = conn.getResponseCode();
             if (responseCode == 200) {
                 StringBuilder response = new StringBuilder();
-                BufferedReader in = new BufferedReader(
-                        new InputStreamReader(conn.getInputStream()));
-                try {
+                try (BufferedReader in = new BufferedReader(
+                        new InputStreamReader(conn.getInputStream()))) {
                     String inputLine;
                     while ((inputLine = in.readLine()) != null) {
                         response.append(inputLine);
                     }
-                } finally {
-                    try {
-                        in.close();
-                    } catch (IOException ex) {
-                        // Ignore
-                    }
                 }
 
                 // Process the server response
@@ -280,12 +260,8 @@
             log.debug("[%s] Retry fcm notification to %s after %d seconds",
                     pluginName, submit.request.to, retryAfter);
         }
-        this.delayedExecutor.schedule(new Runnable() {
-            @Override
-            public void run() {
-                sendNotification(submit);
-            }
-        }, retryAfter, TimeUnit.SECONDS);
+        this.delayedExecutor.schedule(() ->
+                sendNotification(submit), retryAfter, TimeUnit.SECONDS);
     }
 
 }
diff --git a/src/main/resources/Documentation/api.md b/src/main/resources/Documentation/api.md
index d61d4c1..feaf9d2 100644
--- a/src/main/resources/Documentation/api.md
+++ b/src/main/resources/Documentation/api.md
@@ -200,7 +200,7 @@
 
 `COMMENT_ADDED_EVENT = 0x08`
 
-`DRAFT_PUBLISHED_EVENT = 0x10`
+`DRAFT_PUBLISHED_EVENT = 0x10  (deprecated in 2.15)`
 
 `HASHTAG_CHANGED_EVENT = 0x20`
 
@@ -216,6 +216,10 @@
 
 `VOTE_DELETED_EVENT = 0x1000`
 
+`PRIVATE_STATE_CHANGED_EVENT = 0x2000`
+
+`WIP_STATE_CHANGED_EVENT = 0x4000`
+
 ***
 
 **CloudNotificationResponseMode**