Provide selected formatter to XDocLoader

By looking at the mime type we know which formatter should be used to
render the project documentation file. This formatter must be provided
to the XDocLoader which does the actual formatting. This change is a
preparation to support different formatters and not only a Markdown
formatter.

Change-Id: I9c240fdd60097254cbcf54182628d832a0b3b125
Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
diff --git a/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocLoader.java b/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocLoader.java
index 76cfe34..1461186 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocLoader.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocLoader.java
@@ -89,9 +89,10 @@
           }
           ObjectId objectId = tw.getObjectId(0);
           ObjectLoader loader = repo.open(objectId);
-          byte[] md = loader.getBytes(Integer.MAX_VALUE);
-          return getMarkdownAsHtmlResource(cfg, key.getProject(),
-              new String(md, UTF_8), commit.getCommitTime());
+          byte[] raw = loader.getBytes(Integer.MAX_VALUE);
+          byte[] html = formatAsHtml(cfg, key.getFormatter(),
+              replaceMacros(key.getProject(), new String(raw, UTF_8)));
+          return getAsHtmlResource(html, commit.getCommitTime());
         } finally {
           tw.release();
         }
@@ -103,21 +104,7 @@
     }
   }
 
-  private Resource getMarkdownAsHtmlResource(XDocGlobalConfig cfg,
-      Project.NameKey project, String md, int lastModified)
-      throws IOException {
-    MarkdownFormatter f = new MarkdownFormatter();
-    if (!cfg.isHtmlAllowed(Formatter.MARKDOWN)) {
-      f.suppressHtml();
-    }
-    byte[] html = f.markdownToDocHtml(replaceMacros(project, md), UTF_8.name());
-    return new SmallResource(html)
-        .setContentType("text/html")
-        .setCharacterEncoding(UTF_8.name())
-        .setLastModified(lastModified);
-  }
-
-  private String replaceMacros(Project.NameKey project, String md) {
+  private String replaceMacros(Project.NameKey project, String raw) {
     Map<String, String> macros = Maps.newHashMap();
 
     String url = webUrl.get();
@@ -129,7 +116,7 @@
     macros.put("PROJECT", project.get());
     macros.put("PROJECT_URL", url + "#/admin/projects/" + project.get());
 
-    Matcher m = Pattern.compile("(\\\\)?@([A-Z_]+)@").matcher(md);
+    Matcher m = Pattern.compile("(\\\\)?@([A-Z_]+)@").matcher(raw);
     StringBuffer sb = new StringBuffer();
     while (m.find()) {
       String key = m.group(2);
@@ -144,6 +131,33 @@
     return sb.toString();
   }
 
+  private byte[] formatAsHtml(XDocGlobalConfig cfg, Formatter formatter,
+      String raw) throws IOException {
+    switch (formatter) {
+      case MARKDOWN:
+        return formatMarkdownAsHtml(cfg, raw);
+      default:
+        throw new IllegalStateException("Unsupported formatter: "
+            + formatter.name());
+    }
+  }
+
+  private byte[] formatMarkdownAsHtml(XDocGlobalConfig cfg, String md)
+      throws IOException {
+    MarkdownFormatter f = new MarkdownFormatter();
+    if (!cfg.isHtmlAllowed(Formatter.MARKDOWN)) {
+      f.suppressHtml();
+    }
+    return f.markdownToDocHtml(md, UTF_8.name());
+  }
+
+  private Resource getAsHtmlResource(byte[] html, int lastModified) {
+    return new SmallResource(html)
+        .setContentType("text/html")
+        .setCharacterEncoding(UTF_8.name())
+        .setLastModified(lastModified);
+  }
+
   public static class Module extends CacheModule {
     static final String X_DOC_RESOURCES = "x_doc_resources";
 
diff --git a/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocResourceKey.java b/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocResourceKey.java
index 54ff737..09bc287 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocResourceKey.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocResourceKey.java
@@ -18,19 +18,28 @@
 import com.google.gerrit.extensions.restapi.IdString;
 import com.google.gerrit.reviewdb.client.Project;
 
+import com.googlesource.gerrit.plugins.xdocs.XDocGlobalConfig.Formatter;
+
 import org.eclipse.jgit.lib.ObjectId;
 
 public class XDocResourceKey {
+  private final Formatter formatter;
   private final Project.NameKey project;
   private final String resource;
   private final ObjectId revId;
 
-  XDocResourceKey(Project.NameKey project, String r, ObjectId revId) {
+  XDocResourceKey(Formatter formatter, Project.NameKey project, String r,
+      ObjectId revId) {
+    this.formatter = formatter;
     this.project = project;
     this.resource = r;
     this.revId = revId;
   }
 
+  public Formatter getFormatter() {
+    return formatter;
+  }
+
   public Project.NameKey getProject() {
     return project;
   }
@@ -45,21 +54,23 @@
 
   @Override
   public int hashCode() {
-    return Objects.hashCode(project, resource, revId);
+    return Objects.hashCode(formatter, project, resource, revId);
   }
 
   @Override
   public boolean equals(Object other) {
     if (other instanceof XDocResourceKey) {
       XDocResourceKey rk = (XDocResourceKey) other;
-      return project.equals(rk.project) && resource.equals(rk.resource)
-          && revId.equals(rk.revId);
+      return formatter.equals(rk.formatter) && project.equals(rk.project)
+          && resource.equals(rk.resource) && revId.equals(rk.revId);
     }
     return false;
   }
 
   public String asString() {
     StringBuilder b = new StringBuilder();
+    b.append(formatter.name());
+    b.append("/");
     b.append(IdString.fromDecoded(project.get()).encoded());
     b.append("/");
     b.append(resource != null ? IdString.fromDecoded(resource).encoded() : "");
@@ -70,19 +81,23 @@
 
   public static XDocResourceKey fromString(String str) {
     String[] s = str.split("/");
+    Formatter formatter = null;
     String project = null;
     String file = null;
     String revision = null;
     if (s.length > 0) {
-      project = IdString.fromUrl(s[0]).get();
+      formatter = Formatter.valueOf(s[0]);
     }
     if (s.length > 1) {
-      file = IdString.fromUrl(s[1]).get();
+      project = IdString.fromUrl(s[1]).get();
     }
     if (s.length > 2) {
-      revision = s[2];
+      file = IdString.fromUrl(s[2]).get();
     }
-    return new XDocResourceKey(new Project.NameKey(project), file,
+    if (s.length > 3) {
+      revision = s[3];
+    }
+    return new XDocResourceKey(formatter, new Project.NameKey(project), file,
         ObjectId.fromString(revision));
   }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocServlet.java b/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocServlet.java
index c01cd8b..2befa05 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocServlet.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocServlet.java
@@ -191,9 +191,10 @@
         }
 
         Resource rsc;
-        if (mimeTypes.get(mimeType) != null) {
+        Formatter formatter = mimeTypes.get(mimeType);
+        if (formatter != null) {
           rsc = docCache.getUnchecked(
-              (new XDocResourceKey(key.project, key.file, revId)).asString());
+              (new XDocResourceKey(formatter, key.project, key.file, revId)).asString());
         } else if ("image".equals(mimeType.getMediaType())) {
           rsc = getImageResource(repo, revId, key.file);
         } else {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocWebLink.java b/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocWebLink.java
index e347516..2c25095 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocWebLink.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocWebLink.java
@@ -30,6 +30,8 @@
 import com.google.inject.Singleton;
 import com.google.inject.name.Named;
 
+import com.googlesource.gerrit.plugins.xdocs.XDocGlobalConfig.Formatter;
+
 import eu.medsea.mimeutil.MimeType;
 
 import org.eclipse.jgit.lib.Constants;
@@ -97,7 +99,8 @@
     XDocGlobalConfig pluginCfg =
         new XDocGlobalConfig(pluginCfgFactory.getGlobalPluginConfig(pluginName));
     MimeType mimeType = fileTypeRegistry.getMimeType(fileName, null);
-    if (!pluginCfg.getMimeTypes().keySet().contains(mimeType)) {
+    Formatter formatter = pluginCfg.getMimeTypes().get(mimeType);
+    if (formatter == null) {
       return null;
     }
 
@@ -110,7 +113,7 @@
           return null;
         }
         Resource rsc = docCache.getUnchecked(
-           (new XDocResourceKey(p, fileName, revId)).asString());
+           (new XDocResourceKey(formatter, p, fileName, revId)).asString());
         if (rsc != Resource.NOT_FOUND) {
           StringBuilder url = new StringBuilder();
           url.append("plugins/");