/*
* Copyright (c) 2015 EMC Corporation
* All Rights Reserved
*/
package com.emc.apidocs.generating;
import com.emc.apidocs.KnownPaths;
import com.emc.apidocs.model.*;
import com.google.common.collect.Lists;
import org.apache.commons.io.IOUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.*;
/**
*/
public class PageGenerator {
private static final String TOC_TEMPLATE = "TableOfContents.html";
private static final String SERVICE_OVERVIEW_TEMPLATE = "Overview.html";
private static final String METHOD_DETAIL_TEMPLATE = "Details.html";
private static final String FOOTER_TEMPLATE = "Footer.html";
private static final String STATIC_PAGE_TEMPLATE = "Page.html";
private static final String SEARCH_TEMPLATE = "Search.html";
private static final String ERROR_CODES_TEMPLATE = "ErrorCodes.html";
private static final String API_DIFFERENCES = "API Differences";
private static final String ALL_NEW_SERVICES_OVERVIEW = "AllNewServicesOverview.html";
private static final String ALL_REMOVED_SERVICES_OVERVIEW = "AllRemovedServicesOverview.html";
private static final String ALL_MODIFIED_METHODS_OVERVIEW = "AllModifiedMethodsOverview.html";
private static final String ALL_REMOVED_METHODS_OVERVIEW = "AllRemovedMethodsOverview.html";
private static final String ALL_ADDED_METHODS_OVERVIEW = "AllAddedMethodsOverview.html";
private static final String ALL_DEPRECATED_METHODS_OVERVIEW = "AllDeprecatedMethodsOverview.html";
private static final String SERVICE_REMOVED_METHODS_OVERVIEW = "ServiceRemovedMethodsOverview.html";
private static final String SERVICE_NEW_METHODS_OVERVIEW = "ServiceNewMethodsOverview.html";
private static final String SERVICE_MODIFIED_METHODS_OVERVIEW = "ServiceModifiedMethodsOverview.html";
private static final String MODIFIED_METHOD_DETAIL = "ModifiedMethodDetail.html";
private final String buildNumber;
private static String generatedTableOfContents = "";
private static String generatedFooter = "";
public PageGenerator(String buildNumber) {
this.buildNumber = buildNumber;
}
public synchronized void generatePages(ApiDifferences apiDifferences, List<ApiService> apiServices, List<ApiErrorCode> errorCodes) {
StaticPageIndex staticPageIndex = new StaticPageIndex();
generatedFooter = generateFooter();
generatedTableOfContents = generateTableOfContents(apiServices, apiDifferences, staticPageIndex);
generateStaticPages(staticPageIndex);
generateSearchPage(apiServices);
generateErrorCodes(errorCodes);
generateChanges(apiDifferences, apiServices);
for (ApiService apiService : apiServices) {
generateServiceOverViewPage(apiService, apiDifferences.getChange(apiService.javaClassName));
for (ApiMethod apiMethod : apiService.methods) {
generateMethodDetailPage(apiMethod, apiDifferences.getChange(apiService.javaClassName, apiMethod.javaMethodName));
}
}
}
/** Generates all the static pages that just need formatting */
public void generateStaticPages(StaticPageIndex staticPageIndex) {
// Generate Static HTML pages
for (StaticPageIndex.PageFile file : staticPageIndex.getAllStaticPages()) {
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("content", file.content);
parameters.put("title", file.title);
parameters.put("folderId", file.parentFolder.getId());
parameters.put("pageFile", file.getGeneratedFileName());
addCommonTemplateParameters(parameters);
TemplateEngine.generateFileFromTemplate(KnownPaths.getTemplateFile(STATIC_PAGE_TEMPLATE),
KnownPaths.getHtmlOutputFile(file.getGeneratedFileName()),
parameters);
}
// Copy Artifacts
File artifactsDir = KnownPaths.getHtmlOutputFile(StaticPageIndex.ARTIFACTS_DIR);
artifactsDir.mkdir();
for (File artifact : staticPageIndex.getAllArtifacts()) {
try {
FileOutputStream outputFile = new FileOutputStream(artifactsDir.getAbsolutePath() + "/" + artifact.getName());
FileInputStream inputFile = new FileInputStream(artifact);
IOUtils.copy(inputFile, outputFile);
IOUtils.closeQuietly(inputFile);
} catch (Exception e) {
throw new RuntimeException("Error processing artifact " + artifact.getAbsolutePath(), e);
}
}
}
/** Generates the search page */
public void generateSearchPage(List<ApiService> services) {
List<ApiMethod> allMethods = new ArrayList<ApiMethod>();
for (ApiService service : services) {
allMethods.addAll(service.methods);
}
// Assign a unique Index Search Keys to all methods
int key = 0;
for (ApiMethod method : allMethods) {
method.indexKey = "" + key++;
}
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("apiMethods", allMethods);
parameters.put("title", "API Reference Search");
addCommonTemplateParameters(parameters);
TemplateEngine.generateFileFromTemplate(KnownPaths.getTemplateFile(SEARCH_TEMPLATE),
KnownPaths.getHtmlOutputFile(SEARCH_TEMPLATE),
parameters);
}
/** Generates the search page */
public void generateErrorCodes(List<ApiErrorCode> serviceCodes) {
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("errorCodes", serviceCodes);
parameters.put("title", "Error Codes");
addCommonTemplateParameters(parameters);
TemplateEngine.generateFileFromTemplate(KnownPaths.getTemplateFile(ERROR_CODES_TEMPLATE),
KnownPaths.getHtmlOutputFile(ERROR_CODES_TEMPLATE),
parameters);
}
public String generateFooter() {
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("buildNumber", buildNumber);
return TemplateEngine.generateStringFromTemplate(KnownPaths.getTemplateFile(FOOTER_TEMPLATE),
parameters);
}
public String generateTableOfContents(List<ApiService> services, ApiDifferences apiDifferences, StaticPageIndex staticPageIndex) {
ApiReferenceTocOrganizer grouping = new ApiReferenceTocOrganizer(KnownPaths.getReferenceFile("ApiReferenceGrouping.txt"));
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("services", services);
parameters.put("staticPageIndex", staticPageIndex);
parameters.put("serviceGrouping", grouping.organizeServices(services));
parameters.put("serviceDiff", getServiceDiff(grouping));
parameters.put("apiDifferences", apiDifferences);
// Sort Alphabetically Ascending
Collections.sort(services, new Comparator<ApiService>() {
@Override
public int compare(ApiService apiService, ApiService apiService1) {
return apiService.getTitle().compareTo(apiService1.getTitle());
}
});
return TemplateEngine.generateStringFromTemplate(KnownPaths.getTemplateFile(TOC_TEMPLATE),
parameters);
}
/**
* Gets map of API Differences
*
* @param grouping
* The instance of ApiReferenceTocOrganizer
* @return the API Differences map which exists
*/
private Map<String, String> getServiceDiff(ApiReferenceTocOrganizer grouping) {
List<String> allList = grouping.groups.get(API_DIFFERENCES);
if (allList == null || allList.isEmpty()) {
return null;
}
Map<String, String> diffMap = new HashMap<String, String>();
for (String item : allList) {
String pageLink = item.replaceAll(" ", "") + "_diff.html";
File file = KnownPaths.getApiDiffFile(pageLink);
if (file.exists()) {
diffMap.put(item, pageLink);
}
}
return diffMap;
}
public void generateServiceOverViewPage(ApiService apiService, ApiDifferences.Change change) {
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("apiService", apiService);
parameters.put("title", apiService.getTitle());
parameters.put("change", change);
addCommonTemplateParameters(parameters);
TemplateEngine.generateFileFromTemplate(KnownPaths.getTemplateFile(SERVICE_OVERVIEW_TEMPLATE),
KnownPaths.getHtmlOutputFile(apiService.getOverviewFileName()),
parameters);
}
public void generateMethodDetailPage(ApiMethod apiMethod, ApiDifferences.Change change) {
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("apiMethod", apiMethod);
parameters.put("title", apiMethod.apiService.getTitle() + ":" + apiMethod.getTitle());
parameters.put("change", change);
addCommonTemplateParameters(parameters);
try {
TemplateEngine.generateFileFromTemplate(KnownPaths.getTemplateFile(METHOD_DETAIL_TEMPLATE),
KnownPaths.getHtmlOutputFile(apiMethod.getDetailFileName()),
parameters);
} catch (Exception e) {
throw new RuntimeException("Error generating details for :" + apiMethod.getQualifiedName(), e);
}
}
public void generateChanges(ApiDifferences apiDifferences, List<ApiService> services) {
generateAllNewServicesOverview(apiDifferences);
generateAllRemovedServicesOverview(apiDifferences);
generateAllModifiedMethodsOverview(apiDifferences);
generateAllRemovedMethodsOverview(apiDifferences);
generateAllAddedMethodsOverview(apiDifferences);
generateAllDeprecatedMethodsOverview(services);
for (ApiServiceChanges apiServiceChanges : apiDifferences.modifiedServices) {
if (!apiServiceChanges.newMethods.isEmpty()) {
generateServiceNewMethods(apiServiceChanges.service, apiServiceChanges.newMethods);
}
if (!apiServiceChanges.removedMethods.isEmpty()) {
generateServiceRemovedMethods(apiServiceChanges.service, apiServiceChanges.removedMethods);
}
if (!apiServiceChanges.modifiedMethods.isEmpty()) {
generateServiceModifiedMethods(apiServiceChanges.service, apiServiceChanges.modifiedMethods);
for (ApiMethodChanges methodChanges : apiServiceChanges.modifiedMethods) {
generateModifiedMethodDetail(apiServiceChanges.service, methodChanges);
}
}
}
}
public void generateAllNewServicesOverview(ApiDifferences apiDifferences) {
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("apiDifferences", apiDifferences);
parameters.put("title", "New Services In the API");
addCommonTemplateParameters(parameters);
try {
TemplateEngine.generateFileFromTemplate(KnownPaths.getTemplateFile(ALL_NEW_SERVICES_OVERVIEW),
KnownPaths.getHtmlOutputFile(ALL_NEW_SERVICES_OVERVIEW),
parameters);
} catch (Exception e) {
throw new RuntimeException("Error generating all Changes File", e);
}
}
public void generateAllModifiedMethodsOverview(ApiDifferences apiDifferences) {
List<ApiMethodChanges> modifiedMethods = Lists.newArrayList();
for (ApiServiceChanges serviceChanges : apiDifferences.modifiedServices) {
modifiedMethods.addAll(serviceChanges.modifiedMethods);
}
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("modifiedMethods", modifiedMethods);
parameters.put("title", "Methods modified in the API");
addCommonTemplateParameters(parameters);
try {
TemplateEngine.generateFileFromTemplate(KnownPaths.getTemplateFile(ALL_MODIFIED_METHODS_OVERVIEW),
KnownPaths.getHtmlOutputFile(ALL_MODIFIED_METHODS_OVERVIEW),
parameters);
} catch (Exception e) {
throw new RuntimeException("Error generating all Changes File", e);
}
}
public void generateAllRemovedMethodsOverview(ApiDifferences apiDifferences) {
List<ApiMethod> removedMethods = Lists.newArrayList();
for (ApiServiceChanges serviceChanges : apiDifferences.modifiedServices) {
removedMethods.addAll(serviceChanges.removedMethods);
}
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("methods", removedMethods);
parameters.put("title", "Methods removed in the API");
addCommonTemplateParameters(parameters);
try {
TemplateEngine.generateFileFromTemplate(KnownPaths.getTemplateFile(ALL_REMOVED_METHODS_OVERVIEW),
KnownPaths.getHtmlOutputFile(ALL_REMOVED_METHODS_OVERVIEW),
parameters);
} catch (Exception e) {
throw new RuntimeException("Error generating all Changes File", e);
}
}
public void generateAllAddedMethodsOverview(ApiDifferences apiDifferences) {
List<ApiMethod> addedMethods = Lists.newArrayList();
for (ApiServiceChanges serviceChanges : apiDifferences.modifiedServices) {
addedMethods.addAll(serviceChanges.newMethods);
}
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("methods", addedMethods);
parameters.put("title", "Methods added in the API");
addCommonTemplateParameters(parameters);
try {
TemplateEngine.generateFileFromTemplate(KnownPaths.getTemplateFile(ALL_ADDED_METHODS_OVERVIEW),
KnownPaths.getHtmlOutputFile(ALL_ADDED_METHODS_OVERVIEW),
parameters);
} catch (Exception e) {
throw new RuntimeException("Error generating all Changes File", e);
}
}
public void generateAllDeprecatedMethodsOverview(List<ApiService> services) {
List<ApiMethod> deprecatedMethods = Lists.newArrayList();
for (ApiService service : services) {
if (service.isDeprecated) {
deprecatedMethods.addAll(service.methods);
}
else {
for (ApiMethod apiMethod : service.methods) {
if (apiMethod.isDeprecated) {
deprecatedMethods.add(apiMethod);
}
}
}
}
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("methods", deprecatedMethods);
parameters.put("title", "Methods deprecated in the API");
addCommonTemplateParameters(parameters);
try {
TemplateEngine.generateFileFromTemplate(KnownPaths.getTemplateFile(ALL_DEPRECATED_METHODS_OVERVIEW),
KnownPaths.getHtmlOutputFile(ALL_DEPRECATED_METHODS_OVERVIEW),
parameters);
} catch (Exception e) {
throw new RuntimeException("Error generating all Deprecated File", e);
}
}
public void generateAllRemovedServicesOverview(ApiDifferences apiDifferences) {
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("apiDifferences", apiDifferences);
parameters.put("title", "Services Removed From the API");
addCommonTemplateParameters(parameters);
try {
TemplateEngine.generateFileFromTemplate(KnownPaths.getTemplateFile(ALL_REMOVED_SERVICES_OVERVIEW),
KnownPaths.getHtmlOutputFile(ALL_REMOVED_SERVICES_OVERVIEW),
parameters);
} catch (Exception e) {
throw new RuntimeException("Error generating all Changes File", e);
}
}
public void generateServiceNewMethods(ApiService apiService, List<ApiMethod> newMethods) {
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("apiService", apiService);
parameters.put("apiMethods", newMethods);
parameters.put("title", "New Methods in " + apiService.getTitle());
addCommonTemplateParameters(parameters);
try {
TemplateEngine.generateFileFromTemplate(KnownPaths.getTemplateFile(SERVICE_NEW_METHODS_OVERVIEW),
KnownPaths.getHtmlOutputFile(apiService.getNewMethodsFileName()),
parameters);
} catch (Exception e) {
throw new RuntimeException("Error generating New Methods File", e);
}
}
public void generateServiceRemovedMethods(ApiService apiService, List<ApiMethod> removedMethods) {
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("apiService", apiService);
parameters.put("apiMethods", removedMethods);
parameters.put("title", "Methods Removed from " + apiService.getTitle());
addCommonTemplateParameters(parameters);
try {
TemplateEngine.generateFileFromTemplate(KnownPaths.getTemplateFile(SERVICE_REMOVED_METHODS_OVERVIEW),
KnownPaths.getHtmlOutputFile(apiService.getRemovedMethodsFileName()),
parameters);
} catch (Exception e) {
throw new RuntimeException("Error generating Removed Methods File", e);
}
}
public void generateServiceModifiedMethods(ApiService apiService, List<ApiMethodChanges> methodChanges) {
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("apiService", apiService);
parameters.put("methodChanges", methodChanges);
parameters.put("title", "Methods Changed in " + apiService.getTitle());
addCommonTemplateParameters(parameters);
try {
TemplateEngine.generateFileFromTemplate(KnownPaths.getTemplateFile(SERVICE_MODIFIED_METHODS_OVERVIEW),
KnownPaths.getHtmlOutputFile(apiService.getModifiedMethodsFileName()),
parameters);
} catch (Exception e) {
throw new RuntimeException("Error generating Removed Methods File", e);
}
}
public void generateModifiedMethodDetail(ApiService apiService, ApiMethodChanges methodChanges) {
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("apiService", apiService);
parameters.put("apiMethod", methodChanges.method);
parameters.put("methodChanges", methodChanges);
parameters.put("title", "Methods Changed in " + apiService.getTitle());
addCommonTemplateParameters(parameters);
try {
TemplateEngine.generateFileFromTemplate(KnownPaths.getTemplateFile(MODIFIED_METHOD_DETAIL),
KnownPaths.getHtmlOutputFile(apiService.getModifiedMethodFileName(methodChanges.method.javaMethodName)),
parameters);
} catch (Exception e) {
throw new RuntimeException("Error generating Removed Methods File", e);
}
}
private void addCommonTemplateParameters(Map<String, Object> parameters) {
parameters.put("tableOfContents", generatedTableOfContents);
parameters.put("footer", generatedFooter);
}
}