Add attribute fillGaps to ParsingQueueTask

So we are able to differentiate between tasks to create new and create
missing events.

Solves: Jira GER-1545
Change-Id: If66746d02bc7e2045bc7ea15b3b38fc233d28303
diff --git a/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/parsing/EiffelEventParsingQueue.java b/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/parsing/EiffelEventParsingQueue.java
index 7fd9f25..db1b62b 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/parsing/EiffelEventParsingQueue.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/parsing/EiffelEventParsingQueue.java
@@ -70,6 +70,16 @@
   public void scheduleSccCreation(String repoName, String branchRef) {
     schedule(ParsingQueueTask.builder(SCC, repoName, branchRef));
   }
+  /**
+   * Schedules SCC creation for all commits with missing SCC-events where the commit is reachable
+   * from branchRef.
+   *
+   * @param repoName - the repository containing the commits to create events from.
+   * @param branchRef - create events for commits reachable from tip of branchRef.
+   */
+  public void scheduleMissingSccCreation(String repoName, String branchRef) {
+    schedule(ParsingQueueTask.builder(SCC, repoName, branchRef).fillGaps(true));
+  }
 
   /**
    * Schedule SCC creation for all commits reachable from commit.
@@ -82,6 +92,18 @@
     schedule(ParsingQueueTask.builder(SCC, repoName, branchRef).commit(commit));
   }
 
+  /**
+   * Schedules SCC creation for all commits with missing SCC-events where the commit is reachable
+   * from commit.
+   *
+   * @param repoName - the repository containing the commits to create events from.
+   * @param branchRef - used to populate data.gitIdentifier.branch.
+   * @param commit - create events from commits reachable from commit.
+   */
+  public void scheduleMissingSccCreation(String repoName, String branchRef, String commit) {
+    schedule(ParsingQueueTask.builder(SCC, repoName, branchRef).commit(commit).fillGaps(true));
+  }
+
   public void scheduleScsCreation(GitReferenceUpdatedListener.Event event) {
     schedule(
         ParsingQueueTask.builder(SCS, event.getProjectName(), event.getRefName())
@@ -95,6 +117,17 @@
     schedule(ParsingQueueTask.builder(SCS, repoName, branchRef));
   }
 
+  /**
+   * Schedules SCS creation for all commits with missing SCS-events where the commit is reachable
+   * from branchRef.
+   *
+   * @param repoName - the repository containing the commits to create events from.
+   * @param branchRef - create events for commits reachable from tip of branchRef.
+   */
+  public void scheduleMissingScsCreation(String repoName, String branchRef) {
+    schedule(ParsingQueueTask.builder(SCS, repoName, branchRef).fillGaps(true));
+  }
+
   public void scheduleArtcCreation(GitReferenceUpdatedListener.Event event) {
     schedule(
         ParsingQueueTask.builder(ARTC, event.getProjectName(), event.getRefName())
diff --git a/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/parsing/ParsingQueueTask.java b/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/parsing/ParsingQueueTask.java
index b35ff1b..3337888 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/parsing/ParsingQueueTask.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/parsing/ParsingQueueTask.java
@@ -47,6 +47,7 @@
     private Boolean _force = null;
     private String _previousTip = null;
     private PatchsetCreationData _patchsetCreationData;
+    private Boolean _fillGaps = false;
 
     private Builder(EiffelEventType type, String repoName, String branchRefOrTag) {
       this._type = type;
@@ -82,6 +83,14 @@
       this._previousTip = previousTip;
       return this;
     }
+    /**
+     * This attribute is specified when you want to create single SC eiffel-events that may be
+     * missing for a branch.
+     */
+    public Builder fillGaps(boolean fillGaps) {
+      this._fillGaps = fillGaps;
+      return this;
+    }
 
     public ParsingQueueTask build() {
       if (this._patchsetCreationData != null) {
@@ -95,7 +104,8 @@
           this._updater,
           this._updateTime,
           this._previousTip,
-          this._force);
+          this._force,
+          this._fillGaps);
     }
   }
 
@@ -108,6 +118,7 @@
   final Boolean force;
   final String previousTip;
   final PatchsetCreationData patchsetCreationData;
+  final Boolean fillGaps;
 
   private ParsingQueueTask(
       EiffelEventType type,
@@ -117,7 +128,8 @@
       AccountInfo updater,
       Long updateTime,
       String previousTip,
-      Boolean force) {
+      Boolean force,
+      Boolean fillGaps) {
     this.type = type;
     this.repoName = repoName;
     this.branchRefOrTag =
@@ -130,6 +142,7 @@
     this.previousTip = previousTip;
     this.force = force;
     this.patchsetCreationData = null;
+    this.fillGaps = fillGaps;
   }
 
   private ParsingQueueTask(PatchsetCreationData data) {
@@ -142,6 +155,7 @@
     this.previousTip = null;
     this.force = null;
     this.patchsetCreationData = data;
+    this.fillGaps = false;
   }
 
   @Override
@@ -151,9 +165,9 @@
             ? branchRefOrTag.substring(RefNames.REFS_HEADS.length())
             : branchRefOrTag;
     if (commitId != null) {
-      return String.format("%s[%s, %s, %s]", type.name(), repoName, target, commitId);
+      return String.format("%s[%s, %s, %s, %b]", type.name(), repoName, target, commitId, fillGaps);
     }
-    return String.format("%s[%s, %s]", type.name(), repoName, target);
+    return String.format("%s[%s, %s, %b]", type.name(), repoName, target, fillGaps);
   }
 
   @Override
@@ -166,7 +180,8 @@
           && Objects.equals(this.updater, that.updater)
           && Objects.equals(this.updateTime, that.updateTime)
           && Objects.equals(this.previousTip, that.previousTip)
-          && Objects.equals(this.force, that.force);
+          && Objects.equals(this.force, that.force)
+          && Objects.equals(this.fillGaps, that.fillGaps);
     }
     return false;
   }
diff --git a/src/test/java/com/googlesource/gerrit/plugins/eventseiffel/parsing/ParsingQueueTaskTest.java b/src/test/java/com/googlesource/gerrit/plugins/eventseiffel/parsing/ParsingQueueTaskTest.java
index 6c85763..c2fafdb 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/eventseiffel/parsing/ParsingQueueTaskTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/eventseiffel/parsing/ParsingQueueTaskTest.java
@@ -33,17 +33,18 @@
             .updateTime(0L)
             .previousTip("previous")
             .force(true)
+            .fillGaps(true)
             .build();
     String json = new Gson().toJson(task);
     String expected =
-        "{\"repoName\":\"repo\",\"branchRefOrTag\":\"branch\",\"commitId\":\"commit-sha1\",\"type\":\"EiffelSourceChangeCreatedEvent\",\"updater\":{\"_accountId\":1},\"updateTime\":0,\"force\":true,\"previousTip\":\"previous\"}";
+        "{\"repoName\":\"repo\",\"branchRefOrTag\":\"branch\",\"commitId\":\"commit-sha1\",\"type\":\"EiffelSourceChangeCreatedEvent\",\"updater\":{\"_accountId\":1},\"updateTime\":0,\"force\":true,\"previousTip\":\"previous\",\"fillGaps\":true}";
     assertEquals(json, expected);
   }
 
   @Test
   public void testParsingQueueTaskDeserializeable() {
     String json =
-        "{\"repoName\":\"repo\",\"branchRefOrTag\":\"branch\",\"commitId\":\"commit-sha1\",\"type\":\"EiffelSourceChangeCreatedEvent\",\"updater\":{\"_accountId\":1},\"updateTime\":0,\"force\":true,\"previousTip\":\"previous\"}";
+        "{\"repoName\":\"repo\",\"branchRefOrTag\":\"branch\",\"commitId\":\"commit-sha1\",\"type\":\"EiffelSourceChangeCreatedEvent\",\"updater\":{\"_accountId\":1},\"updateTime\":0,\"force\":true,\"previousTip\":\"previous\",\"fillGaps\":true}";
     ParsingQueueTask deSerialized = new Gson().fromJson(json, ParsingQueueTask.class);
     assertEquals(deSerialized.repoName, "repo");
     assertEquals(deSerialized.branchRefOrTag, "branch");
@@ -52,6 +53,7 @@
     assertEquals(deSerialized.updater._accountId, Integer.valueOf(1));
     assertEquals(deSerialized.updateTime, Long.valueOf(0));
     assertEquals(deSerialized.force, Boolean.TRUE);
+    assertEquals(deSerialized.fillGaps, Boolean.TRUE);
     assertEquals(deSerialized.previousTip, "previous");
   }