Refactor DownloadCommandLink types into DownloadCommandLink class

Defining custom DownloadCommandLink types for the changes screen
is cumbersome and defining them as default types makes them
easily available for other uses, for example: to potentially
download branches, the project dashboards, or even the meta
config branch.  It also keeps some of the special wiring between
the DownloadCommandLink and some of the other download classes
such as the DownloadCommandPanel internal to the download
package.

Change-Id: Ia29f82c78d65d1311e09e0cdedc1e0ce78e7c759
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchSetComplexDisclosurePanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchSetComplexDisclosurePanel.java
index 3b85dfb..77cada9 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchSetComplexDisclosurePanel.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchSetComplexDisclosurePanel.java
@@ -212,80 +212,39 @@
     final DownloadUrlPanel urls = new DownloadUrlPanel(commands);
     final Set<DownloadScheme> allowedSchemes = Gerrit.getConfig().getDownloadSchemes();
     final Set<DownloadCommand> allowedCommands = Gerrit.getConfig().getDownloadCommands();
+    DownloadCommandLink.CopyableCommandLinkFactory cmdLinkfactory =
+        new DownloadCommandLink.CopyableCommandLinkFactory(copyLabel, urls);
 
     copyLabel.setStyleName(Gerrit.RESOURCES.css().downloadLinkCopyLabel());
 
     urls.add(DownloadUrlLink.createDownloadUrlLinks(projectName,
         patchSet.getRefName(), changeDetail.isAllowsAnonymous()));
 
+    // This site prefers usage of the 'repo' tool, so suggest
+    // that for easy fetch.
+    //
     if (allowedSchemes.contains(DownloadScheme.REPO_DOWNLOAD)) {
-      // This site prefers usage of the 'repo' tool, so suggest
-      // that for easy fetch.
-      //
-      final StringBuilder r = new StringBuilder();
-      r.append("repo download ");
-      r.append(projectName);
-      r.append(" ");
-      r.append(changeDetail.getChange().getChangeId());
-      r.append("/");
-      r.append(patchSet.getPatchSetId());
-      final String cmd = r.toString();
-      commands.add(new DownloadCommandLink(DownloadCommand.REPO_DOWNLOAD,
-          "repo download") {
-        @Override
-        protected void setCurrentUrl(DownloadUrlLink link) {
-          urls.setVisible(false);
-          copyLabel.setText(cmd);
-        }
-      });
+      commands.add(cmdLinkfactory.new RepoCommandLink(projectName,
+          changeDetail.getChange().getChangeId() + "/"
+          + patchSet.getPatchSetId()));
     }
 
     if (!urls.isEmpty()) {
       if (allowedCommands.contains(DownloadCommand.CHECKOUT)
           || allowedCommands.contains(DownloadCommand.DEFAULT_DOWNLOADS)) {
-        commands.add(new DownloadCommandLink(DownloadCommand.CHECKOUT,
-            "checkout") {
-          @Override
-          protected void setCurrentUrl(DownloadUrlLink link) {
-            urls.setVisible(true);
-            copyLabel.setText("git fetch " + link.getUrlData()
-                + " && git checkout FETCH_HEAD");
-          }
-        });
+        commands.add(cmdLinkfactory.new CheckoutCommandLink());
       }
       if (allowedCommands.contains(DownloadCommand.PULL)
           || allowedCommands.contains(DownloadCommand.DEFAULT_DOWNLOADS)) {
-        commands.add(new DownloadCommandLink(DownloadCommand.PULL, "pull") {
-          @Override
-          protected void setCurrentUrl(DownloadUrlLink link) {
-            urls.setVisible(true);
-            copyLabel.setText("git pull " + link.getUrlData());
-          }
-        });
+        commands.add(cmdLinkfactory.new PullCommandLink());
       }
       if (allowedCommands.contains(DownloadCommand.CHERRY_PICK)
           || allowedCommands.contains(DownloadCommand.DEFAULT_DOWNLOADS)) {
-        commands.add(new DownloadCommandLink(DownloadCommand.CHERRY_PICK,
-            "cherry-pick") {
-          @Override
-          protected void setCurrentUrl(DownloadUrlLink link) {
-            urls.setVisible(true);
-            copyLabel.setText("git fetch " + link.getUrlData()
-                + " && git cherry-pick FETCH_HEAD");
-          }
-        });
+        commands.add(cmdLinkfactory.new CherryPickCommandLink());
       }
       if (allowedCommands.contains(DownloadCommand.FORMAT_PATCH)
           || allowedCommands.contains(DownloadCommand.DEFAULT_DOWNLOADS)) {
-        commands.add(new DownloadCommandLink(DownloadCommand.FORMAT_PATCH,
-            "patch") {
-          @Override
-          protected void setCurrentUrl(DownloadUrlLink link) {
-            urls.setVisible(true);
-            copyLabel.setText("git fetch " + link.getUrlData()
-                + " && git format-patch -1 --stdout FETCH_HEAD");
-          }
-        });
+        commands.add(cmdLinkfactory.new FormatPatchCommandLink());
       }
     }
 
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/download/DownloadCommandLink.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/download/DownloadCommandLink.java
index f257acc..a79c7de 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/download/DownloadCommandLink.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/download/DownloadCommandLink.java
@@ -16,18 +16,114 @@
 
 import com.google.gerrit.client.Gerrit;
 import com.google.gerrit.reviewdb.client.AccountGeneralPreferences;
+import com.google.gerrit.reviewdb.client.AccountGeneralPreferences.DownloadCommand;
 import com.google.gwt.aria.client.Roles;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.user.client.ui.Anchor;
 import com.google.gwt.user.client.ui.Widget;
+import com.google.gwtexpui.clippy.client.CopyableLabel;
 import com.google.gwtjsonrpc.common.AsyncCallback;
 import com.google.gwtjsonrpc.common.VoidResult;
 
 public abstract class DownloadCommandLink extends Anchor implements ClickHandler {
-  final AccountGeneralPreferences.DownloadCommand cmdType;
+  public static class CopyableCommandLinkFactory {
+    protected CopyableLabel copyLabel = null;
+    protected Widget widget;
 
-  public DownloadCommandLink(AccountGeneralPreferences.DownloadCommand cmdType,
+    public class CheckoutCommandLink extends DownloadCommandLink {
+      public CheckoutCommandLink () {
+        super(DownloadCommand.CHECKOUT, "checkout");
+      }
+
+      @Override
+      protected void setCurrentUrl(DownloadUrlLink link) {
+        widget.setVisible(true);
+        copyLabel.setText("git fetch " + link.urlData
+            + " && git checkout FETCH_HEAD");
+      }
+    }
+
+    public class PullCommandLink extends DownloadCommandLink {
+      public PullCommandLink() {
+        super(DownloadCommand.PULL, "pull");
+      }
+
+      @Override
+      protected void setCurrentUrl(DownloadUrlLink link) {
+        widget.setVisible(true);
+        copyLabel.setText("git pull " + link.urlData);
+      }
+    }
+
+    public class CherryPickCommandLink extends DownloadCommandLink {
+      public CherryPickCommandLink() {
+        super(DownloadCommand.CHERRY_PICK, "cherry-pick");
+      }
+
+      @Override
+      protected void setCurrentUrl(DownloadUrlLink link) {
+        widget.setVisible(true);
+        copyLabel.setText("git fetch " + link.urlData
+            + " && git cherry-pick FETCH_HEAD");
+      }
+    }
+
+    public class FormatPatchCommandLink extends DownloadCommandLink {
+      public FormatPatchCommandLink() {
+        super(DownloadCommand.FORMAT_PATCH, "patch");
+      }
+
+      @Override
+      protected void setCurrentUrl(DownloadUrlLink link) {
+        widget.setVisible(true);
+        copyLabel.setText("git fetch " + link.urlData
+            + " && git format-patch -1 --stdout FETCH_HEAD");
+      }
+    }
+
+    public class RepoCommandLink extends DownloadCommandLink {
+      String projectName;
+      String ref;
+      public RepoCommandLink(String project, String ref) {
+        super(DownloadCommand.REPO_DOWNLOAD, "checkout");
+        this.projectName = project;
+        this.ref = ref;
+      }
+
+      @Override
+      protected void setCurrentUrl(DownloadUrlLink link) {
+        widget.setVisible(false);
+        final StringBuilder r = new StringBuilder();
+        r.append("repo download ");
+        r.append(projectName);
+        r.append(" ");
+        r.append(ref);
+        copyLabel.setText(r.toString());
+      }
+    }
+
+    public class CloneCommandLink extends DownloadCommandLink {
+      public CloneCommandLink() {
+        super(DownloadCommand.CHECKOUT, "clone");
+      }
+
+      @Override
+      protected void setCurrentUrl(DownloadUrlLink link) {
+        widget.setVisible(true);
+        copyLabel.setText("git clone " + link.getUrlData());
+      }
+    }
+
+    public CopyableCommandLinkFactory(CopyableLabel label, Widget widget) {
+      copyLabel = label;
+      this.widget = widget;
+    }
+  }
+
+  final DownloadCommand cmdType;
+
+  public DownloadCommandLink(DownloadCommand cmdType,
       String text) {
     super(text);
     this.cmdType = cmdType;
@@ -62,7 +158,7 @@
     }
   }
 
-  public AccountGeneralPreferences.DownloadCommand getCmdType() {
+  public DownloadCommand getCmdType() {
     return cmdType;
   }