Allow to specify which comment link should be used to extract issue ids

This configuration option is useful when reusing the same comment
link for different its plugins.

Change-Id: I6e32ca274c36cc56ca56e4d795229a5b35a7311c
diff --git a/src/main/java/com/googlesource/gerrit/plugins/hooks/its/ItsConfig.java b/src/main/java/com/googlesource/gerrit/plugins/hooks/its/ItsConfig.java
index 4955f8e..2be5be8 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/hooks/its/ItsConfig.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/hooks/its/ItsConfig.java
@@ -130,13 +130,30 @@
   // Issue association --------------------------------------------------------
 
   /**
+   * Gets the name of the comment link that should be used
+   *
+   * @return name of the comment link that should be used
+   */
+  public String getCommentLinkName() {
+    String ret;
+
+    ret = gerritConfig.getString(pluginName, null, "commentlink");
+    if (ret == null) {
+      ret = pluginName;
+    }
+
+    return ret;
+  }
+
+  /**
    * Gets the regular expression used to identify issue ids.
    * @return the regular expression, or {@code null}, if there is no pattern
    *    to match issue ids.
    */
   public Pattern getIssuePattern() {
     Pattern ret = null;
-    String match = gerritConfig.getString("commentlink", pluginName, "match");
+    String match = gerritConfig.getString("commentlink",
+        getCommentLinkName(), "match");
     if (match != null) {
       ret = Pattern.compile(match);
     }
@@ -148,7 +165,7 @@
    * @return policy on how necessary association with issues is
    */
   public ItsAssociationPolicy getItsAssociationPolicy() {
-    return gerritConfig.getEnum("commentlink", pluginName, "association",
-        ItsAssociationPolicy.OPTIONAL);
+    return gerritConfig.getEnum("commentlink", getCommentLinkName(),
+        "association", ItsAssociationPolicy.OPTIONAL);
   }
 }
diff --git a/src/main/resources/Documentation/config-common.md b/src/main/resources/Documentation/config-common.md
index 6ae1b4e..26da3ca 100644
--- a/src/main/resources/Documentation/config-common.md
+++ b/src/main/resources/Documentation/config-common.md
@@ -5,6 +5,7 @@
 * [Identifying ITS ids][identifying-its-ids]
 * [Enabling ITS integration][enabling-its-integration]
 * [Configuring rules of when to take which actions in the ITS][configure-rules]
+* [Further common configuration details][config-common-detail]
 
 
 
@@ -13,7 +14,8 @@
 -----------------------------------------------------
 
 In order to extract ITS ids from commit messages, @PLUGIN@ uses
-[commentlink][upstream-comment-link-doc]s of name "`@PLUGIN@`".
+[commentlink][upstream-comment-link-doc]s of
+([per default][common-config-commentlink]) name "`@PLUGIN@`".
 
 The first group of `commentlink.@PLUGIN@.match` is considered the
 issue id.
@@ -139,6 +141,24 @@
 by going to the Gerrit UI under menu Plugins -> Installed.  Now you
 just need to use the appropriate name to configure each plugin.
 
+
+
+[config-common-detail]: #config-common-detail
+<a name="config-common-detail">Further common configuration details</a>
+-----------------------------------------------------------------------
+
+[common-config-commentlink]: #common-config-commentlink
+
+<a name="common-config-commentlink">`@PLUGIN@.commentlink`
+:   The name of the comment link to use to extract issue ids.
+
+    This setting is useful to reuse the same comment link from different Its
+    plugins. For example, if you set `@PLUGIN@.commentlink` to `foo`, then the
+    comment link `foo` is used (instead of the comment link `@PLUGIN@`) to
+    extract issue ids.
+
+    Default is `@PLUGIN@`
+
 [Back to @PLUGIN@ documentation index][index]
 
 [index]: index.html
diff --git a/src/test/java/com/googlesource/gerrit/plugins/hooks/its/ItsConfigTest.java b/src/test/java/com/googlesource/gerrit/plugins/hooks/its/ItsConfigTest.java
index 9848c52..0417c55 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/hooks/its/ItsConfigTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/hooks/its/ItsConfigTest.java
@@ -411,6 +411,8 @@
   public void testPatternNullMatch() {
     ItsConfig itsConfig = createItsConfig();
 
+    expect(serverConfig.getString("ItsTestName", null, "commentlink"))
+        .andReturn(null).atLeastOnce();
     expect(serverConfig.getString("commentlink", "ItsTestName", "match"))
         .andReturn(null).atLeastOnce();
 
@@ -420,9 +422,25 @@
         itsConfig.getIssuePattern());
   }
 
+  public void testPatternNullMatchWCommentLink() {
+    ItsConfig itsConfig = createItsConfig();
+
+    expect(serverConfig.getString("ItsTestName", null, "commentlink"))
+        .andReturn("foo").atLeastOnce();
+    expect(serverConfig.getString("commentlink", "foo", "match"))
+        .andReturn(null).atLeastOnce();
+
+    replayMocks();
+
+    assertNull("Pattern for null match is not null",
+        itsConfig.getIssuePattern());
+  }
+
   public void testPattern() {
     ItsConfig itsConfig = createItsConfig();
 
+    expect(serverConfig.getString("ItsTestName", null, "commentlink"))
+        .andReturn(null).atLeastOnce();
     expect(serverConfig.getString("commentlink", "ItsTestName", "match"))
         .andReturn("TestPattern").atLeastOnce();
 
@@ -432,9 +450,26 @@
         "TestPattern", itsConfig.getIssuePattern().pattern());
   }
 
+  public void testPatternWCommentLink() {
+    ItsConfig itsConfig = createItsConfig();
+
+    expect(serverConfig.getString("ItsTestName", null, "commentlink"))
+        .andReturn("foo").atLeastOnce();
+    expect(serverConfig.getString("commentlink", "foo", "match"))
+        .andReturn("TestPattern").atLeastOnce();
+
+    replayMocks();
+
+    assertEquals("Expected and generated pattern are not equal",
+        "TestPattern", itsConfig.getIssuePattern().pattern());
+
+  }
+
   public void testItsAssociationPolicyOptional() {
     ItsConfig itsConfig = createItsConfig();
 
+    expect(serverConfig.getString("ItsTestName", null, "commentlink"))
+        .andReturn(null).atLeastOnce();
     expect(serverConfig.getEnum("commentlink", "ItsTestName", "association",
         ItsAssociationPolicy.OPTIONAL))
         .andReturn(ItsAssociationPolicy.OPTIONAL)
@@ -446,9 +481,27 @@
         ItsAssociationPolicy.OPTIONAL, itsConfig.getItsAssociationPolicy());
   }
 
+  public void testItsAssociationPolicyOptionalWCommentLink() {
+    ItsConfig itsConfig = createItsConfig();
+
+    expect(serverConfig.getString("ItsTestName", null, "commentlink"))
+        .andReturn("foo").atLeastOnce();
+    expect(serverConfig.getEnum("commentlink", "foo", "association",
+        ItsAssociationPolicy.OPTIONAL))
+        .andReturn(ItsAssociationPolicy.OPTIONAL)
+        .atLeastOnce();
+
+    replayMocks();
+
+    assertEquals("Expected and generated associated policy do not match",
+        ItsAssociationPolicy.OPTIONAL, itsConfig.getItsAssociationPolicy());
+  }
+
   public void testItsAssociationPolicySuggested() {
     ItsConfig itsConfig = createItsConfig();
 
+    expect(serverConfig.getString("ItsTestName", null, "commentlink"))
+        .andReturn(null).atLeastOnce();
     expect(serverConfig.getEnum("commentlink", "ItsTestName", "association",
         ItsAssociationPolicy.OPTIONAL))
         .andReturn(ItsAssociationPolicy.SUGGESTED)
@@ -460,9 +513,27 @@
         ItsAssociationPolicy.SUGGESTED, itsConfig.getItsAssociationPolicy());
   }
 
+  public void testItsAssociationPolicySuggestedWCommentLink() {
+    ItsConfig itsConfig = createItsConfig();
+
+    expect(serverConfig.getString("ItsTestName", null, "commentlink"))
+        .andReturn("foo").atLeastOnce();
+    expect(serverConfig.getEnum("commentlink", "foo", "association",
+        ItsAssociationPolicy.OPTIONAL))
+        .andReturn(ItsAssociationPolicy.SUGGESTED)
+        .atLeastOnce();
+
+    replayMocks();
+
+    assertEquals("Expected and generated associated policy do not match",
+        ItsAssociationPolicy.SUGGESTED, itsConfig.getItsAssociationPolicy());
+  }
+
   public void testItsAssociationPolicyMandatory() {
     ItsConfig itsConfig = createItsConfig();
 
+    expect(serverConfig.getString("ItsTestName", null, "commentlink"))
+        .andReturn(null).atLeastOnce();
     expect(serverConfig.getEnum("commentlink", "ItsTestName", "association",
         ItsAssociationPolicy.OPTIONAL))
         .andReturn(ItsAssociationPolicy.MANDATORY)
@@ -474,6 +545,22 @@
         ItsAssociationPolicy.MANDATORY, itsConfig.getItsAssociationPolicy());
   }
 
+  public void testItsAssociationPolicyMandatoryWCommentLink() {
+    ItsConfig itsConfig = createItsConfig();
+
+    expect(serverConfig.getString("ItsTestName", null, "commentlink"))
+        .andReturn("foo").atLeastOnce();
+    expect(serverConfig.getEnum("commentlink", "foo", "association",
+        ItsAssociationPolicy.OPTIONAL))
+        .andReturn(ItsAssociationPolicy.MANDATORY)
+        .atLeastOnce();
+
+    replayMocks();
+
+    assertEquals("Expected and generated associated policy do not match",
+        ItsAssociationPolicy.MANDATORY, itsConfig.getItsAssociationPolicy());
+  }
+
   private ItsConfig createItsConfig() {
     return injector.getInstance(ItsConfig.class);
   }