1920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson/*
2920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson * Copyright (C) 2010 Google Inc.
3920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson *
4920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson * Licensed under the Apache License, Version 2.0 (the "License");
5920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson * you may not use this file except in compliance with the License.
6920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson * You may obtain a copy of the License at
7920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson *
8920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson * http://www.apache.org/licenses/LICENSE-2.0
9920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson *
10920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson * Unless required by applicable law or agreed to in writing, software
11920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson * distributed under the License is distributed on an "AS IS" BASIS,
12920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson * See the License for the specific language governing permissions and
14920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson * limitations under the License.
15920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson */
16920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
17920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodsonpackage com.google.doclava;
18920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
19920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodsonimport com.google.clearsilver.jsilver.JSilver;
20920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodsonimport com.google.clearsilver.jsilver.data.Data;
21920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodsonimport com.google.clearsilver.jsilver.resourceloader.CompositeResourceLoader;
22920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodsonimport com.google.clearsilver.jsilver.resourceloader.FileSystemResourceLoader;
23920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodsonimport com.google.clearsilver.jsilver.resourceloader.ResourceLoader;
24920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodsonimport java.io.File;
25920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodsonimport java.io.FileOutputStream;
26920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodsonimport java.io.IOException;
27920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodsonimport java.io.OutputStreamWriter;
28920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodsonimport java.net.URL;
29920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodsonimport java.util.ArrayList;
30920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodsonimport java.util.Collections;
31920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodsonimport java.util.HashMap;
32920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodsonimport java.util.LinkedHashSet;
33920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodsonimport java.util.List;
34920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodsonimport java.util.Map;
35920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodsonimport java.util.Set;
36920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
37920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson/**
38920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson * This class is used to generate a web page highlighting the differences and
39920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson * similarities among various Java libraries.
40920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson *
41920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson */
42920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodsonpublic final class DoclavaDiff {
43920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  private final String outputDir;
44920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  private final JSilver jSilver;
45920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  private final List<FederatedSite> sites = new ArrayList<FederatedSite>();
46920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
47920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  public static void main(String[] args) {
48920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    new DoclavaDiff(args).generateSite();
49920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
50920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
51920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  public DoclavaDiff(String[] args) {
52920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // TODO: options parsing
53920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    try {
54920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      sites.add(new FederatedSite("Android", new URL("http://manatee/doclava/android")));
55920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      sites.add(new FederatedSite("GWT", new URL("http://manatee/doclava/gwt")));
56920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      //sites.add(new FederatedSite("Crore", new URL("http://manatee/doclava/crore")));
57920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      outputDir = "build";
58920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    } catch (Exception e) {
59920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      throw new AssertionError(e);
60920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
61920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
62920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // TODO: accept external templates
63920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    List<ResourceLoader> resourceLoaders = new ArrayList<ResourceLoader>();
64920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    resourceLoaders.add(new FileSystemResourceLoader("assets/templates"));
65920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
66920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    ResourceLoader compositeResourceLoader = new CompositeResourceLoader(resourceLoaders);
67920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    jSilver = new JSilver(compositeResourceLoader);
68920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
69920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
70920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  public void generateSite() {
71920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    Data data = generateHdf();
72920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    generateHtml("diff.cs", data, new File(outputDir + "/diff.html"));
73920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
74920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
75920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  /**
76920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson   * Creates an HDF with this structure:
77920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson   * <pre>
7841d8656cf17e04b25a058d0874e401654ea547b4Dirk Dougherty   * sites.0.name = projectA
7941d8656cf17e04b25a058d0874e401654ea547b4Dirk Dougherty   * sites.0.url = http://proja.domain.com/reference
8041d8656cf17e04b25a058d0874e401654ea547b4Dirk Dougherty   * sites.1.name = projectB
8141d8656cf17e04b25a058d0874e401654ea547b4Dirk Dougherty   * sites.1.url = http://projb.domain.com
82920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson   * packages.0.name = java.lang
83920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson   * packages.0.sites.0.hasPackage = 1
8441d8656cf17e04b25a058d0874e401654ea547b4Dirk Dougherty   * packages.0.sites.0.link = http://proja.domain.com/reference/java/lang
85920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson   * packages.0.sites.1.hasPackage = 0
86920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson   * packages.0.classes.0.qualifiedName = java.lang.Object
87920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson   * packages.0.classes.0.sites.0.hasClass = 1
8841d8656cf17e04b25a058d0874e401654ea547b4Dirk Dougherty   * packages.0.classes.0.sites.0.link = http://proja.domain.com/reference/java/lang/Object
89920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson   * packages.0.classes.0.sites.1.hasClass = 0
90920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson   * packages.0.classes.0.methods.0.signature = wait()
91920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson   * packages.0.classes.0.methods.0.sites.0.hasMethod = 1
9241d8656cf17e04b25a058d0874e401654ea547b4Dirk Dougherty   * packages.0.classes.0.methods.0.sites.0.link = http://proja.domain.com/reference/java/lang/Object#wait
93920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson   * packages.0.classes.0.methods.0.sites.1.hasMethod = 0
94920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson   * </pre>
95920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson   */
96920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  private Data generateHdf() {
97920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    Data data = jSilver.createData();
98920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
99920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    data.setValue("triangle.opened", "../assets/templates/assets/images/triangle-opened.png");
100920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    data.setValue("triangle.closed", "../assets/templates/assets/images/triangle-closed.png");
101920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
102920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    int i = 0;
103920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (FederatedSite site : sites) {
104920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      String base = "sites." + (i++);
105920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      data.setValue(base + ".name", site.name());
106920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      data.setValue(base + ".url", site.baseUrl().toString());
107920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
108920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
109920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    List<String> allPackages = knownPackages(sites);
110920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
111920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    int p = 0;
112920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (String pkg : allPackages) {
113920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      PackageInfo packageInfo = new PackageInfo(pkg);
114920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      String packageBase = "packages." + (p++);
115920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      data.setValue(packageBase + ".name", pkg);
116920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
117920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      int s = 0;
118920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      for (FederatedSite site : sites) {
119920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        String siteBase = packageBase + ".sites." + (s++);
120920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        if (site.apiInfo().getPackages().containsKey(pkg)) {
121920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          data.setValue(siteBase + ".hasPackage", "1");
122920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          data.setValue(siteBase + ".link", site.linkFor(packageInfo.htmlPage()));
123920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        } else {
124920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          data.setValue(siteBase + ".hasPackage", "0");
125920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
126920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
127920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
128920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (packageUniqueToSite(pkg, sites)) {
129920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        continue;
130920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
131920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
132920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      List<String> packageClasses = knownClassesForPackage(pkg, sites);
133920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      int c = 0;
134920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      for (String qualifiedClassName : packageClasses) {
135920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        String classBase = packageBase + ".classes." + (c++);
136920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        data.setValue(classBase + ".qualifiedName", qualifiedClassName);
137920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
138920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        s = 0;
139920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        for (FederatedSite site : sites) {
140920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          String siteBase = classBase + ".sites." + (s++);
141920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          ClassInfo classInfo = site.apiInfo().findClass(qualifiedClassName);
142920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          if (classInfo != null) {
143920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            data.setValue(siteBase + ".hasClass", "1");
144920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            data.setValue(siteBase + ".link", site.linkFor(classInfo.htmlPage()));
145920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          } else {
146920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            data.setValue(siteBase + ".hasClass", "0");
147920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          }
148920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
149920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
150920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        if (agreeOnClass(qualifiedClassName, sites)) {
151920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          continue;
152920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
153920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
154920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        if (classUniqueToSite(qualifiedClassName, sites)) {
155920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          continue;
156920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
157920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
158920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        int m = 0;
159920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        List<MethodInfo> methods = knownMethodsForClass(qualifiedClassName, sites);
160920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        for (MethodInfo method : methods) {
161920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          if (agreeOnMethod(qualifiedClassName, method, sites)) {
162920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            continue;
163920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          }
164920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
165920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          String methodBase = classBase + ".methods." + (m++);
166920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          data.setValue(methodBase + ".signature", method.prettySignature());
167920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          int k = 0;
168920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          for (FederatedSite site : sites) {
169920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            String siteBase = methodBase + ".sites." + (k++);
170920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            if (site.apiInfo().findClass(qualifiedClassName) == null) {
171920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              data.setValue(siteBase + ".hasMethod", "0");
172920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              continue;
173920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            }
174920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            Map<String,MethodInfo> siteMethods
175920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                = site.apiInfo().findClass(qualifiedClassName).allMethods();
176920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            if (siteMethods.containsKey(method.getHashableName())) {
177920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              data.setValue(siteBase + ".hasMethod", "1");
178920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              data.setValue(siteBase + ".link", site.linkFor(method.htmlPage()));
179920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            } else {
180920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              data.setValue(siteBase + ".hasMethod", "0");
181920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            }
182920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          }
183920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
184920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
185920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
186920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
187920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    return data;
188920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
189920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
190920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  /**
191920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson   * Returns a list of all known packages from all sites.
192920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson   */
193920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  private List<String> knownPackages(List<FederatedSite> sites) {
194920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    Set<String> allPackages = new LinkedHashSet<String>();
195920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (FederatedSite site : sites) {
196920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      Map<String, PackageInfo> packages = site.apiInfo().getPackages();
197920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      for (String pkg : packages.keySet()) {
198920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        allPackages.add(pkg);
199920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
200920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
201920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
202920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    List<String> packages = new ArrayList<String>(allPackages);
203920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    Collections.sort(packages);
204920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    return packages;
205920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
206920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
207920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  /**
208920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson   * Returns all known classes from all sites for a given package.
209920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson   */
210920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  private List<String> knownClassesForPackage(String pkg, List<FederatedSite> sites) {
211920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    Set<String> allClasses = new LinkedHashSet<String>();
212920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (FederatedSite site : sites) {
213920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      PackageInfo packageInfo = site.apiInfo().getPackages().get(pkg);
214920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (packageInfo == null) {
215920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        continue;
216920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
217920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      HashMap<String, ClassInfo> classes = packageInfo.allClasses();
218920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      for (Map.Entry<String, ClassInfo> entry : classes.entrySet()) {
219920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        allClasses.add(entry.getValue().qualifiedName());
220920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
221920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
222920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
223920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    List<String> classes = new ArrayList<String>(allClasses);
224920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    Collections.sort(classes);
225920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    return classes;
226920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
227920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
228920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  /**
229920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson   * Returns all known methods from all sites for a given class.
230920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson   */
231920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  private List<MethodInfo> knownMethodsForClass(String qualifiedClassName,
232920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      List<FederatedSite> sites) {
233920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
234920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    Map<String, MethodInfo> allMethods = new HashMap<String, MethodInfo>();
235920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (FederatedSite site : sites) {
236920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      ClassInfo classInfo = site.apiInfo().findClass(qualifiedClassName);
237920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (classInfo == null) {
238920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        continue;
239920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
240920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
241920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      for (Map.Entry<String, MethodInfo> entry: classInfo.allMethods().entrySet()) {
242920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        allMethods.put(entry.getKey(), entry.getValue());
243920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
244920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
245920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
246920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    List<MethodInfo> methods = new ArrayList<MethodInfo>();
247920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    methods.addAll(allMethods.values());
248920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    return methods;
249920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
250920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
251920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  /**
252920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson   * Returns true if the list of sites all completely agree on the given
253920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson   * package. All sites must possess the package, all classes it contains, and
254920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson   * all methods of each class.
255920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson   */
256920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  private boolean agreeOnPackage(String pkg, List<FederatedSite> sites) {
257920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (FederatedSite site : sites) {
258920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (site.apiInfo().getPackages().get(pkg) == null) {
259920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        return false;
260920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
261920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
262920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
263920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    List<String> classes = knownClassesForPackage(pkg, sites);
264920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (String clazz : classes) {
265920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (!agreeOnClass(clazz, sites)) {
266920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        return false;
267920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
268920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
269920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    return true;
270920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
271920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
272920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  /**
273920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson   * Returns true if the list of sites all agree on the given class. Each site
274920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson   * must have the class and agree on its methods.
275920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson   */
276920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  private boolean agreeOnClass(String qualifiedClassName, List<FederatedSite> sites) {
277920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    List<MethodInfo> methods = knownMethodsForClass(qualifiedClassName, sites);
278920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (MethodInfo method : methods) {
279920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (!agreeOnMethod(qualifiedClassName, method, sites)) {
280920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        return false;
281920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
282920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
283920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    return true;
284920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
285920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
286920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  /**
287920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson   * Returns true if the list of sites all contain the given method.
288920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson   */
289920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  private boolean agreeOnMethod(String qualifiedClassName, MethodInfo method,
290920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      List<FederatedSite> sites) {
291920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
292920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (FederatedSite site : sites) {
293920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      ClassInfo siteClass = site.apiInfo().findClass(qualifiedClassName);
294920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (siteClass == null) {
295920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        return false;
296920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
297920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
298920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (!siteClass.supportsMethod(method)) {
299920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        return false;
300920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
301920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
302920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    return true;
303920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
304920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
305920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  /**
306920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson   * Returns true if the given package is known to exactly one of the given sites.
307920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson   */
308920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  private boolean packageUniqueToSite(String pkg, List<FederatedSite> sites) {
309920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    int numSites = 0;
310920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (FederatedSite site : sites) {
311920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (site.apiInfo().getPackages().containsKey(pkg)) {
312920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        numSites++;
313920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
314920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
315920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    return numSites == 1;
316920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
317920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
318920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  /**
319920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson   * Returns true if the given class is known to exactly one of the given sites.
320920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson   */
321920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  private boolean classUniqueToSite(String qualifiedClassName, List<FederatedSite> sites) {
322920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    int numSites = 0;
323920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (FederatedSite site : sites) {
324920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (site.apiInfo().findClass(qualifiedClassName) != null) {
325920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        numSites++;
326920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
327920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
328920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    return numSites == 1;
329920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
330920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
331920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  private void generateHtml(String template, Data data, File file) {
332920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    ClearPage.ensureDirectory(file);
333920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
334920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    OutputStreamWriter stream = null;
335920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    try {
336920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream = new OutputStreamWriter(new FileOutputStream(file), "UTF-8");
337920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      String rendered = jSilver.render(template, data);
338920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.write(rendered, 0, rendered.length());
339920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    } catch (IOException e) {
340920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      System.out.println("error: " + e.getMessage() + "; when writing file: " + file.getAbsolutePath());
341920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    } finally {
342920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (stream != null) {
343920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        try {
344920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          stream.close();
345920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        } catch (IOException ignored) {}
346920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
347920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
348920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
349ed8f79791885c3ac15401d88a147aee551e1039eBrian Carlstrom}
350