Align Project.NameKey serialization to gerrit core

Since I96dbb4c38f2 Project.NameKey is serialized in stream events as:

  "project": "project-name"

However high-availability plugin missed this feature and doesn't use
custom JsonSerializer, so that the Project.NameKey is serialized in
legacy form:

  "project": { "name" : "project-name" }

Starting from gerrit release 3.1 this plugin migrated to custom
ProjectNameKeyAdapter that was added in I242b51530a3. As a side effect,
project name serialization was implicitly changed to new serialization
form.

This incompatibility can cause a problem in zero-downtime upgrade
scenario, where the events created by gerrit 3.0 cannot be de-serialized
by second node running gerrit 3.1.

To rectify, install custom ProjectNameKeyAdapter, that is aware of skew
of project name representation and could also understand legacy and new
form of project name.

Note, that the plugin own ProjectNameKeyAdapter class should be removed
when this change is merged to stable-3.1 branch. The test class could be
removed as well, because similar round trip serialization tests exist
in gerrit core.

Bug: Issue 13825
Change-Id: I73bd4df898d8b978f67e9ab27fe5bb5461a951fd
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/event/ProjectNameKeyAdapter.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/event/ProjectNameKeyAdapter.java
new file mode 100644
index 0000000..8c00282
--- /dev/null
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/event/ProjectNameKeyAdapter.java
@@ -0,0 +1,44 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.ericsson.gerrit.plugins.highavailability.event;
+
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParseException;
+import com.google.gson.JsonPrimitive;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+import java.lang.reflect.Type;
+
+public class ProjectNameKeyAdapter
+    implements JsonSerializer<Project.NameKey>, JsonDeserializer<Project.NameKey> {
+  @Override
+  public JsonElement serialize(
+      Project.NameKey project, Type typeOfSrc, JsonSerializationContext context) {
+    return new JsonPrimitive(project.get());
+  }
+
+  @Override
+  public Project.NameKey deserialize(
+      JsonElement json, Type typeOfT, JsonDeserializationContext context)
+      throws JsonParseException {
+    if (json.isJsonObject()) {
+      return Project.nameKey(json.getAsJsonObject().get("name").getAsJsonPrimitive().getAsString());
+    }
+    return Project.nameKey(json.getAsString());
+  }
+}
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/GsonProvider.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/GsonProvider.java
index e62cec2..36f0029 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/GsonProvider.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/GsonProvider.java
@@ -14,7 +14,9 @@
 
 package com.ericsson.gerrit.plugins.highavailability.forwarder.rest;
 
+import com.ericsson.gerrit.plugins.highavailability.event.ProjectNameKeyAdapter;
 import com.google.common.base.Supplier;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.events.Event;
 import com.google.gerrit.server.events.EventDeserializer;
 import com.google.gerrit.server.events.SupplierDeserializer;
@@ -28,6 +30,7 @@
   public Gson get() {
     return new GsonBuilder()
         .registerTypeAdapter(Event.class, new EventDeserializer())
+        .registerTypeAdapter(Project.NameKey.class, new ProjectNameKeyAdapter())
         .registerTypeAdapter(Supplier.class, new SupplierDeserializer())
         .create();
   }
diff --git a/src/test/java/com/ericsson/gerrit/plugins/highavailability/event/EventDeserializerTest.java b/src/test/java/com/ericsson/gerrit/plugins/highavailability/event/EventDeserializerTest.java
new file mode 100644
index 0000000..8e1b5eb
--- /dev/null
+++ b/src/test/java/com/ericsson/gerrit/plugins/highavailability/event/EventDeserializerTest.java
@@ -0,0 +1,42 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.ericsson.gerrit.plugins.highavailability.event;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.ericsson.gerrit.plugins.highavailability.forwarder.rest.GsonProvider;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gson.Gson;
+import org.junit.Test;
+
+public class EventDeserializerTest {
+  private static final String LEGACY_PROJECT_KEY = "{\"name\": \"project\"}";
+
+  private static final String NEW_PROJECT_KEY = "\"project\"";
+
+  private final Gson gson = new GsonProvider().get();
+
+  @Test
+  public void deserializePatchSetCreatedEventLegacyProjectKey() {
+    Project.NameKey n = gson.fromJson(LEGACY_PROJECT_KEY, Project.NameKey.class);
+    assertThat(n.get()).isEqualTo("project");
+  }
+
+  @Test
+  public void deserializePatchSetCreatedEventNewProjectKey() {
+    Project.NameKey n = gson.fromJson(NEW_PROJECT_KEY, Project.NameKey.class);
+    assertThat(n.get()).isEqualTo("project");
+  }
+}