This is an automated email from the ASF dual-hosted git repository. ddekany pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/freemarker-docgen.git
commit 633349d589bd4cff58ea5ed72f06ea9d6b75eded Author: ddekany <[email protected]> AuthorDate: Sun Jun 8 01:56:55 2025 +0200 Some code cleanup (mostly just put parts of execute() into smaller methods) --- .../java/org/freemarker/docgen/core/Transform.java | 740 ++++++++++----------- 1 file changed, 370 insertions(+), 370 deletions(-) diff --git a/freemarker-docgen-core/src/main/java/org/freemarker/docgen/core/Transform.java b/freemarker-docgen-core/src/main/java/org/freemarker/docgen/core/Transform.java index f860012..a7f6f61 100644 --- a/freemarker-docgen-core/src/main/java/org/freemarker/docgen/core/Transform.java +++ b/freemarker-docgen-core/src/main/java/org/freemarker/docgen/core/Transform.java @@ -72,6 +72,7 @@ import freemarker.template.SimpleHash; import freemarker.template.SimpleScalar; import freemarker.template.Template; import freemarker.template.TemplateException; +import freemarker.template.TemplateExceptionHandler; import freemarker.template.TemplateMethodModelEx; import freemarker.template.TemplateModel; import freemarker.template.TemplateModelException; @@ -523,33 +524,83 @@ public final class Transform { */ public void execute() throws DocgenException, IOException, SAXException { + checkNotYetExecuted(); + validateJavaBeanProperties(); + loadConfigurationFile(); + validateAndDefaultSettings(); + initializeStateFields(); + configureFreeMarker(); + + // - Load and validate the book XML + final File docFile = findDocFile(); + Document doc = XMLUtil.loadDocBook5XML(docFile, validate, validationOps, logger); + ignoredFilePathPatterns.add(FileUtil.globToRegexp(docFile.getName())); + + preprocessDOM(doc); + + resolveDocgenUrlsInSettings(); + + // - Create destination directory: + if (!destDir.isDirectory() && !destDir.mkdirs()) { + throw new IOException("Failed to create destination directory: " + destDir.getAbsolutePath()); + } + logger.info("Output directory: " + destDir.getAbsolutePath()); + + checkInternalBookmarks(); + + insertableFiles = computeInsertableFiles(); + + setFreeMarkerSharedVariables(doc); + + generateToJsons(doc); + + generateSiteMapXML(doc); + + int htmlFileCounter = generateBookContentHTMLFiles(); + + if (!offline && searchKey != null) { + generateSearchResultsHtmlFile(doc); + htmlFileCounter++; + } + + copyStandardStatics(); + + int bookSpecStaticFileCounter = copyCustomStatics(); + + if (generateEclipseTOC) { + generateEclipseTOC(doc); + } + + logger.info( + "Done: " + + htmlFileCounter + " HTML-s + " + + bookSpecStaticFileCounter + " custom statics + commons" + + (generateEclipseTOC ? " + Eclipse ToC" : "")); + } + + private void checkNotYetExecuted() { if (executed) { throw new DocgenException( - "This transformation was alrady executed; " - + "use a new " + Transform.class.getName() + "."); + "This transformation was already executed; use a new " + Transform.class.getName() + "."); } executed = true; + } - // Check Java Bean properties: - + private void validateJavaBeanProperties() throws IOException { if (srcDir == null) { - throw new DocgenException( - "The source directory (the DocBook XML) wasn't specified."); + throw new DocgenException("The source directory (the DocBook XML) wasn't specified."); } if (!srcDir.isDirectory()) { - throw new IOException( - "Source directory doesn't exist: " - + srcDir.getAbsolutePath()); + throw new IOException("Source directory doesn't exist: " + srcDir.getAbsolutePath()); } if (destDir == null) { - throw new DocgenException( - "The destination directory wasn't specified."); + throw new DocgenException("The destination directory wasn't specified."); } // Note: This directory will be created automatically if missing. + } - // Load configuration file: - + private void loadConfigurationFile() throws IOException { File templatesDir = null; cfgFile = new File(srcDir, FILE_SETTINGS); @@ -802,10 +853,10 @@ public final class Transform { String msg; if (strRank.equalsIgnoreCase("article")) { msg = "\"article\" is not a rank, since articles " - + "can have various ranks depending on their " - + "context. (Hint: if the article is the " - + "top-level element then it has \"chapter\" " - + "rank.)"; + + "can have various ranks depending on their " + + "context. (Hint: if the article is the " + + "top-level element then it has \"chapter\" " + + "rank.)"; } else { msg = "Unknown rank: " + strRank; } @@ -835,33 +886,35 @@ public final class Transform { throw newCfgFileException(settingName, "Unknown setting name."); } } // for each cfg settings + } + } - if (deployUrl == null) { - throw new DocgenException( - "The \"" + SETTING_DEPLOY_URL + "\" setting wasn't specified"); - } - if (offline == null) { - throw new DocgenException( - "The \"" + SETTING_OFFLINE - + "\" setting wasn't specified; it must be set to true or false"); - } - if (logo == null) { - throw new DocgenException( - "The \"" + SETTING_LOGO - + "\" setting wasn't specified; it must be set currently, as the layout reserves space for it."); - } - if (copyrightHolder == null) { - throw new DocgenException( - "The \"" + SETTING_COPYRIGHT_HOLDER + "\" setting wasn't specified."); - } - if (copyrightHolderSite == null) { - throw new DocgenException( - "The \"" + SETTING_COPYRIGHT_HOLDER_SITE + "\" setting wasn't specified."); - } - if (copyrightStartYear == null) { - throw new DocgenException( - "The \"" + SETTING_COPYRIGHT_START_YEAR + "\" setting wasn't specified."); - } + private void validateAndDefaultSettings() { + if (deployUrl == null) { + throw new DocgenException( + "The \"" + SETTING_DEPLOY_URL + "\" setting wasn't specified"); + } + if (offline == null) { + throw new DocgenException( + "The \"" + SETTING_OFFLINE + + "\" setting wasn't specified; it must be set to true or false"); + } + if (logo == null) { + throw new DocgenException( + "The \"" + SETTING_LOGO + + "\" setting wasn't specified; it must be set currently, as the layout reserves space for it."); + } + if (copyrightHolder == null) { + throw new DocgenException( + "The \"" + SETTING_COPYRIGHT_HOLDER + "\" setting wasn't specified."); + } + if (copyrightHolderSite == null) { + throw new DocgenException( + "The \"" + SETTING_COPYRIGHT_HOLDER_SITE + "\" setting wasn't specified."); + } + if (copyrightStartYear == null) { + throw new DocgenException( + "The \"" + SETTING_COPYRIGHT_START_YEAR + "\" setting wasn't specified."); } // Ensure proper rank relations: @@ -874,25 +927,20 @@ public final class Transform { maxMainTOFDisplayDepth = maxTOFDisplayDepth; } - templatesDir = new File(srcDir, DIR_TEMPLATES); - if (!templatesDir.exists()) { - templatesDir = null; - } - if (contentDir == null) { contentDir = srcDir; } + } - // Initialize state fields - + private void initializeStateFields() { primaryIndexTermLookup = new HashMap<>(); secondaryIndexTermLookup = new HashMap<>(); elementsById = new HashMap<>(); tocNodes = new ArrayList<>(); indexEntries = new ArrayList<>(); + } - // Setup FreeMarker: - + private void configureFreeMarker() throws IOException { try { Logger.selectLoggerLibrary(Logger.LIBRARY_NONE); } catch (ClassNotFoundException e) { @@ -900,11 +948,12 @@ public final class Transform { } logger.info("Using FreeMarker " + Configuration.getVersion()); - fmConfig = new Configuration(Configuration.VERSION_2_3_25); + fmConfig = new Configuration(Configuration.VERSION_2_3_34); TemplateLoader templateLoader = new ClassTemplateLoader( Transform.class, "templates"); - if (templatesDir != null) { + File templatesDir = new File(srcDir, DIR_TEMPLATES); + if (!templatesDir.exists()) { templateLoader = new MultiTemplateLoader( new TemplateLoader[] { new FileTemplateLoader(templatesDir), templateLoader }); } @@ -916,9 +965,14 @@ public final class Transform { fmConfig.setDefaultEncoding(UTF_8.name()); fmConfig.setOutputEncoding(UTF_8.name()); - // Do the actual job: + fmConfig.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); + fmConfig.setLogTemplateExceptions(false); + fmConfig.setWrapUncheckedExceptions(true); - // - Load and validate the book XML + fmConfig.setFallbackOnNullLoopVariable(false); + } + + private File findDocFile() { final File docFile; { final File docFile1 = new File(contentDir, FILE_BOOK); @@ -934,14 +988,24 @@ public final class Transform { } } } - Document doc = XMLUtil.loadDocBook5XML( - docFile, validate, validationOps, logger); - ignoredFilePathPatterns.add(FileUtil.globToRegexp(docFile.getName())); + return docFile; + } - // - Post-edit and examine the DOM: - preprocessDOM(doc); + /** + * Adds attribute <tt>id</tt> to elements that are in + * <code>idAttrElements</code>, but has no id attribute yet. + * Adding id-s is useful to create more precise HTML cross-links later. + */ + private void preprocessDOM(Document doc) + throws SAXException, DocgenException { + NodeModel.simplify(doc); + preprocessDOM_applyRemoveNodesWhenOnlineSetting(doc); + preprocessDOM_addRanks(doc); + preprocessDOM_misc(doc); + preprocessDOM_buildTOC(doc); + } - // Resolve Docgen URL schemes in setting values: + private void resolveDocgenUrlsInSettings() { // Olinks must come first: if (olinks != null) { for (Entry<String, String> olinkEnt : olinks.entrySet()) { @@ -965,7 +1029,7 @@ public final class Transform { tab.put("href", resolveDocgenURL(SETTING_SOCIAL_LINKS, tab.get("href"))); } for (Map<String, String> links : footerSiteMap.values()) { - for (Map.Entry<String, String> link : links.entrySet()) { + for (Entry<String, String> link : links.entrySet()) { link.setValue(resolveDocgenURL(SETTING_FOOTER_SITEMAP, link.getValue())); } } @@ -975,14 +1039,9 @@ public final class Transform { for (Logo logo : sideTOCLogos) { resolveLogoHref(logo); } + } - // - Create destination directory: - if (!destDir.isDirectory() && !destDir.mkdirs()) { - throw new IOException("Failed to create destination directory: " - + destDir.getAbsolutePath()); - } - logger.info("Output directory: " + destDir.getAbsolutePath()); - + private void checkInternalBookmarks() { // - Check internal book-marks: for (Entry<String, String> ent : internalBookmarks.entrySet()) { String id = ent.getValue(); @@ -992,73 +1051,99 @@ public final class Transform { "No element with id \"" + id + "\" exists in the book."); } } + } - insertableFiles = computeInsertableFiles(); + private Map<String, Path> computeInsertableFiles() throws DocgenException { + for (String varName : insertableFilesOverrides.keySet()) { + if (!insertableFilesFromSettingsFile.containsKey(varName)) { + throw new DocgenException("Attempt to set insertable path with symbolic name " + + StringUtil.jQuote(varName) + + ", when same was not set in the settings file (" + FILE_SETTINGS + ")."); + } + } + + Map<String, String> unresolvedInsertableFiles = new HashMap<>(); + unresolvedInsertableFiles.putAll(insertableFilesFromSettingsFile); + unresolvedInsertableFiles.putAll(insertableFilesOverrides); - // - Setup common data-model variables: + for (Entry<String, String> entry : unresolvedInsertableFiles.entrySet()) { + if (entry.getValue() == null) { + throw new DocgenException("The insertable path with symbolic name " + + StringUtil.jQuote(entry.getKey()) + " was set to path null, which is not allowed. " + + "Probably you are supposed to override its path."); + } + } + + Map<String, Path> insertableFiles = new HashMap<>(); + for (Entry<String, String> entry : unresolvedInsertableFiles.entrySet()) { + String symbolicName = entry.getKey(); + String unresolvedPath = entry.getValue(); + + Path path; + if (unresolvedPath.endsWith("/**") || unresolvedPath.endsWith("\\**")) { + path = srcDir.toPath().resolve(unresolvedPath.substring(0, unresolvedPath.length() - 3)); + if (!Files.isDirectory(path)) { + throw new DocgenException( + "Insertable file with symbolic name " + StringUtil.jQuote(symbolicName) + + " points to a directory that doesn't exist: " + StringUtil.jQuote(path)); + } + } else { + path = srcDir.toPath().resolve(unresolvedPath); + if (!Files.isRegularFile(path)) { + if (Files.isDirectory(path)) { + throw new DocgenException( + "Insertable file with symbolic name " + StringUtil.jQuote(symbolicName) + + " points to a directory, not a file: " + StringUtil.jQuote(path) + "." + + " If you want to point to a directory, end the path with \"/**\"."); + } else { + throw new DocgenException( + "Insertable file with symbolic name " + StringUtil.jQuote(symbolicName) + + " points to a file that doesn't exist: " + StringUtil.jQuote(path)); + } + } + } + + insertableFiles.put(symbolicName, path); + } + + return insertableFiles; + } + + private void setFreeMarkerSharedVariables(Document doc) { try { // Settings: - fmConfig.setSharedVariable( - VAR_OFFLINE, offline); - fmConfig.setSharedVariable( - VAR_SIMPLE_NAVIGATION_MODE, simpleNavigationMode); - fmConfig.setSharedVariable( - VAR_DEPLOY_URL, deployUrl); - fmConfig.setSharedVariable( - VAR_ONLINE_TRACKER_HTML, onlineTrackerHTML); - fmConfig.setSharedVariable( - VAR_COOKIE_CONSENT_SCRIPT_URL, cookieConstentScriptURL); - fmConfig.setSharedVariable( - VAR_SHOW_EDITORAL_NOTES, showEditoralNotes); - fmConfig.setSharedVariable( - VAR_SHOW_XXE_LOGO, showXXELogo); - fmConfig.setSharedVariable( - VAR_SEARCH_KEY, searchKey); - fmConfig.setSharedVariable( - VAR_DISABLE_JAVASCRIPT, disableJavaScript); - fmConfig.setSharedVariable( - VAR_OLINKS, olinks); - fmConfig.setSharedVariable( - VAR_NUMBERED_SECTIONS, numberedSections); - fmConfig.setSharedVariable( - VAR_LOGO, logo); - fmConfig.setSharedVariable( - VAR_SIDE_TOC_LOGOS, sideTOCLogos); - fmConfig.setSharedVariable( - VAR_COPYRIGHT_HOLDER, copyrightHolder); - fmConfig.setSharedVariable( - VAR_COPYRIGHT_HOLDER_SITE, copyrightHolderSite); - fmConfig.setSharedVariable( - VAR_COPYRIGHT_SUFFIX, copyrightSuffix); - fmConfig.setSharedVariable( - VAR_COPYRIGHT_START_YEAR, copyrightStartYear); - fmConfig.setSharedVariable( - VAR_COPYRIGHT_COMMENT, copyrightComment); - fmConfig.setSharedVariable( - VAR_COPYRIGHT_JAVA_COMMENT, copyrightJavaComment); - fmConfig.setSharedVariable( - VAR_TABS, tabs); - fmConfig.setSharedVariable( - VAR_SECONDARY_TABS, secondaryTabs); - fmConfig.setSharedVariable( - VAR_SOCIAL_LINKS, socialLinks); - fmConfig.setSharedVariable( - VAR_FOOTER_SITEMAP, footerSiteMap); - fmConfig.setSharedVariable( - VAR_EXTERNAL_BOOKMARDS, externalBookmarks); - fmConfig.setSharedVariable( - VAR_INTERNAL_BOOKMARDS, internalBookmarks); - fmConfig.setSharedVariable( - VAR_ROOT_ELEMENT, doc.getDocumentElement()); - fmConfig.setSharedVariable( - VAR_CUSTOM_VARIABLES, computeCustomVariables()); + fmConfig.setSharedVariable(VAR_OFFLINE, offline); + fmConfig.setSharedVariable(VAR_SIMPLE_NAVIGATION_MODE, simpleNavigationMode); + fmConfig.setSharedVariable(VAR_DEPLOY_URL, deployUrl); + fmConfig.setSharedVariable(VAR_ONLINE_TRACKER_HTML, onlineTrackerHTML); + fmConfig.setSharedVariable(VAR_COOKIE_CONSENT_SCRIPT_URL, cookieConstentScriptURL); + fmConfig.setSharedVariable(VAR_SHOW_EDITORAL_NOTES, showEditoralNotes); + fmConfig.setSharedVariable(VAR_SHOW_XXE_LOGO, showXXELogo); + fmConfig.setSharedVariable(VAR_SEARCH_KEY, searchKey); + fmConfig.setSharedVariable(VAR_DISABLE_JAVASCRIPT, disableJavaScript); + fmConfig.setSharedVariable(VAR_OLINKS, olinks); + fmConfig.setSharedVariable(VAR_NUMBERED_SECTIONS, numberedSections); + fmConfig.setSharedVariable(VAR_LOGO, logo); + fmConfig.setSharedVariable(VAR_SIDE_TOC_LOGOS, sideTOCLogos); + fmConfig.setSharedVariable(VAR_COPYRIGHT_HOLDER, copyrightHolder); + fmConfig.setSharedVariable(VAR_COPYRIGHT_HOLDER_SITE, copyrightHolderSite); + fmConfig.setSharedVariable(VAR_COPYRIGHT_SUFFIX, copyrightSuffix); + fmConfig.setSharedVariable(VAR_COPYRIGHT_START_YEAR, copyrightStartYear); + fmConfig.setSharedVariable(VAR_COPYRIGHT_COMMENT, copyrightComment); + fmConfig.setSharedVariable(VAR_COPYRIGHT_JAVA_COMMENT, copyrightJavaComment); + fmConfig.setSharedVariable(VAR_TABS, tabs); + fmConfig.setSharedVariable(VAR_SECONDARY_TABS, secondaryTabs); + fmConfig.setSharedVariable(VAR_SOCIAL_LINKS, socialLinks); + fmConfig.setSharedVariable(VAR_FOOTER_SITEMAP, footerSiteMap); + fmConfig.setSharedVariable(VAR_EXTERNAL_BOOKMARDS, externalBookmarks); + fmConfig.setSharedVariable(VAR_INTERNAL_BOOKMARDS, internalBookmarks); + fmConfig.setSharedVariable(VAR_ROOT_ELEMENT, doc.getDocumentElement()); + fmConfig.setSharedVariable(VAR_CUSTOM_VARIABLES, computeCustomVariables()); fmConfig.setSharedVariable( "printTextWithDocgenSubstitutions", new PrintTextWithDocgenSubstitutionsDirective(this)); - fmConfig.setSharedVariable( - "chopLinebreak", - ChopLinebreakDirective.INSTANCE); + fmConfig.setSharedVariable("chopLinebreak", ChopLinebreakDirective.INSTANCE); // Calculated data: { @@ -1072,74 +1157,86 @@ public final class Transform { new DateUtil.TrivialCalendarFieldsToDateConverter()); } catch (DateParseException e) { throw new DocgenException( - "Malformed \"" + SYSPROP_GENERATION_TIME - + "\" system property value: " + generationTimeStr, e); + "Malformed \"" + SYSPROP_GENERATION_TIME + "\" system property value: " + generationTimeStr, + e); } } fmConfig.setSharedVariable(VAR_TRANSFORM_START_TIME, generationTime); } - fmConfig.setSharedVariable( - VAR_INDEX_ENTRIES, indexEntries); + fmConfig.setSharedVariable(VAR_INDEX_ENTRIES, indexEntries); int tofCntLv1 = countTOFEntries(tocNodes.get(0), 1); int tofCntLv2 = countTOFEntries(tocNodes.get(0), 2); fmConfig.setSharedVariable( VAR_SHOW_NAVIGATION_BAR, - tofCntLv1 != 0 - || internalBookmarks.size() != 0 - || externalBookmarks.size() != 0); - fmConfig.setSharedVariable( - VAR_SHOW_BREADCRUMB, tofCntLv1 != tofCntLv2); + tofCntLv1 != 0 || !internalBookmarks.isEmpty() || !externalBookmarks.isEmpty()); + fmConfig.setSharedVariable(VAR_SHOW_BREADCRUMB, tofCntLv1 != tofCntLv2); // Helper methods and directives: - fmConfig.setSharedVariable( - "NodeFromID", nodeFromID); - fmConfig.setSharedVariable( - "CreateLinkFromID", createLinkFromID); - fmConfig.setSharedVariable( - "primaryIndexTermLookup", primaryIndexTermLookup); - fmConfig.setSharedVariable( - "secondaryIndexTermLookup", secondaryIndexTermLookup); - fmConfig.setSharedVariable( - "CreateLinkFromNode", createLinkFromNode); + fmConfig.setSharedVariable("NodeFromID", nodeFromID); + fmConfig.setSharedVariable("CreateLinkFromID", createLinkFromID); + fmConfig.setSharedVariable("primaryIndexTermLookup", primaryIndexTermLookup); + fmConfig.setSharedVariable("secondaryIndexTermLookup", secondaryIndexTermLookup); + fmConfig.setSharedVariable("CreateLinkFromNode", createLinkFromNode); } catch (TemplateModelException e) { throw new BugException(e); } + } - // - Generate ToC JSON-s: - { - logger.info("Generating ToC JSON..."); - Template template = fmConfig.getTemplate(FILE_TOC_JSON_TEMPLATE); - try (Writer wr = FileUtil.newFileWriter(new File(destDir, FILE_TOC_JSON_OUTPUT))) { - try { - SimpleHash dataModel = new SimpleHash(fmConfig.getObjectWrapper()); - dataModel.put(VAR_JSON_TOC_ROOT, tocNodes.get(0)); - template.process(dataModel, wr, null, NodeModel.wrap(doc)); - } catch (TemplateException e) { - throw new BugException("Failed to generate ToC JSON " - + "(see cause exception).", e); - } + private Map<String, Object> computeCustomVariables() throws DocgenException { + for (String varName : customVariableOverrides.keySet()) { + if (!customVariablesFromSettingsFile.containsKey(varName)) { + throw new DocgenException("Attempt to override custom variable " + StringUtil.jQuote(varName) + + ", when it was not set in the settings file (" + cfgFile + ")."); } } - // - Generate Sitemap XML: - { - logger.info("Generating Sitemap XML..."); - Template template = fmConfig.getTemplate(FILE_SITEMAP_XML_TEMPLATE); - try (Writer wr = FileUtil.newFileWriter(new File(destDir, FILE_SITEMAP_XML_OUTPUT))) { - try { - SimpleHash dataModel = new SimpleHash(fmConfig.getObjectWrapper()); - dataModel.put(VAR_JSON_TOC_ROOT, tocNodes.get(0)); - template.process(dataModel, wr, null, NodeModel.wrap(doc)); - } catch (TemplateException e) { - throw new BugException("Failed to generate Sitemap XML" - + "(see cause exception).", e); - } + Map<String, Object> customVariables = new HashMap<>(); + customVariables.putAll(customVariablesFromSettingsFile); + customVariables.putAll(customVariableOverrides); + + for (Entry<String, Object> entry : customVariables.entrySet()) { + if (entry.getValue() == null) { + throw new DocgenException("The custom variable " + StringUtil.jQuote(entry.getKey()) + + " was set to null, which is not allowed. Probably you are supposed to override its value."); } } + return customVariables; + } - // - Generate the HTML-s: + private void generateToJsons(Document doc) throws IOException { + logger.info("Generating ToC JSON..."); + Template template = fmConfig.getTemplate(FILE_TOC_JSON_TEMPLATE); + try (Writer wr = FileUtil.newFileWriter(new File(destDir, FILE_TOC_JSON_OUTPUT))) { + try { + SimpleHash dataModel = new SimpleHash(fmConfig.getObjectWrapper()); + dataModel.put(VAR_JSON_TOC_ROOT, tocNodes.get(0)); + template.process(dataModel, wr, null, NodeModel.wrap(doc)); + } catch (TemplateException e) { + throw new BugException("Failed to generate ToC JSON " + + "(see cause exception).", e); + } + } + } + + private void generateSiteMapXML(Document doc) throws IOException { + logger.info("Generating Sitemap XML..."); + Template template = fmConfig.getTemplate(FILE_SITEMAP_XML_TEMPLATE); + try (Writer wr = FileUtil.newFileWriter(new File(destDir, FILE_SITEMAP_XML_OUTPUT))) { + try { + SimpleHash dataModel = new SimpleHash(fmConfig.getObjectWrapper()); + dataModel.put(VAR_JSON_TOC_ROOT, tocNodes.get(0)); + template.process(dataModel, wr, null, NodeModel.wrap(doc)); + } catch (TemplateException e) { + throw new BugException("Failed to generate Sitemap XML" + + "(see cause exception).", e); + } + } + } + + private int generateBookContentHTMLFiles() throws IOException { logger.info("Generating HTML files..."); + int htmlFileCounter = 0; for (TOCNode tocNode : tocNodes) { if (tocNode.getOutputFileName() != null) { @@ -1160,19 +1257,20 @@ public final class Transform { } } } + return htmlFileCounter; + } - if (!offline && searchKey != null) { - try { - generateSearchResultsHTMLFile(doc); - htmlFileCounter++; - } catch (freemarker.core.StopException e) { - throw new DocgenException(e.getMessage()); - } catch (TemplateException e) { - throw new BugException(e); - } + private void generateSearchResultsHtmlFile(Document doc) throws IOException { + try { + generateSearchResultsHtmlFileInner(doc); + } catch (freemarker.core.StopException e) { + throw new DocgenException(e.getMessage()); + } catch (TemplateException e) { + throw new BugException(e); } + } - // - Copy the standard statics: + private void copyStandardStatics() throws IOException { logger.info("Copying common static files..."); copyCommonStatic("docgen.min.css"); copyCommonStatic("img/patterned-bg.png"); @@ -1187,125 +1285,103 @@ public final class Transform { copyCommonStatic("img/xxe.png"); } if (!disableJavaScript) { - copyCommonStatic("main.min.js"); + copyCommonStatic("main.min.js"); } + } - // - Copy the custom statics: - logger.info("Copying custom static files..."); - int bookSpecStaticFileCounter = FileUtil.copyDir(contentDir, destDir, ignoredFilePathPatterns); - - // - Eclipse ToC: - if (generateEclipseTOC) { - if (simpleNavigationMode) { - throw new DocgenException("Eclipse ToC generation is untested/unsupported with simpleNavigationMode=true."); + private void copyCommonStatic(String staticFileName) throws IOException { + String resourcePath = "statics/" + staticFileName; + try (InputStream in = Transform.class.getResourceAsStream(resourcePath)) { + if (in == null) { + throw new IOException("Failed to open class-loader resource: " + resourcePath + " relatively to " + + Transform.class.getPackage().getName()); } - logger.info("Generating Eclipse ToC..."); - Template template = fmConfig.getTemplate(FILE_ECLIPSE_TOC_TEMPLATE); - try (Writer wr = FileUtil.newFileWriter(new File(destDir, FILE_ECLIPSE_TOC_OUTPUT))) { - try { - SimpleHash dataModel = new SimpleHash(fmConfig.getObjectWrapper()); - if (eclipseLinkTo != null) { - dataModel.put(VAR_ECLIPSE_LINK_TO, eclipseLinkTo); + if (staticFileName.endsWith(".css") || staticFileName.endsWith(".js")) { + // ISO-8859-1 will be good enough as far as the resource isn't UTF-16 or EBCDIC: + final Charset fileCharset = StandardCharsets.ISO_8859_1; + String content = FileUtil.loadString(in, fileCharset); + final String eol = TextUtil.detectEOL(content, "\n"); + + // If we have an initial comment, then that must be a copyright header, which we will remove. + if (content.startsWith("/*")) { + int commentEnd = content.indexOf("*/"); + if (commentEnd == -1) { + throw new BugException("Unclosed initial \"/*\" in resource " + resourcePath); + } + commentEnd += 2; + String comment = content.substring(0, commentEnd); + if (!comment.contains("Copyright") && !comment.contains("copyright") + && !comment.contains("License") && !comment.contains("license")) { + throw new BugException("The initial /*...*/ comments doesn't look like a copyright header " + + "in resource " + resourcePath); } - template.process(dataModel, wr, null, NodeModel.wrap(doc)); - } catch (TemplateException e) { - throw new BugException("Failed to generate Eclipse ToC " - + "(see cause exception).", e); - } - } - } - // - Report summary: - logger.info( - "Done: " - + htmlFileCounter + " HTML-s + " - + bookSpecStaticFileCounter + " custom statics + commons" - + (generateEclipseTOC ? " + Eclipse ToC" : "")); - } + // Include an EOL after the comment, if there's any. + for (int i = 0; i < 2; i++) { + if (commentEnd < content.length()) { + char c = content.charAt(commentEnd); + if (c == '\n') { + commentEnd++; + } else if (c == '\r') { + commentEnd++; + if (commentEnd < content.length() && content.charAt(commentEnd) == '\n') { + commentEnd++; + } + } + } + } - private Map<String, Object> computeCustomVariables() throws DocgenException { - for (String varName : customVariableOverrides.keySet()) { - if (!customVariablesFromSettingsFile.containsKey(varName)) { - throw new DocgenException("Attempt to override custom variable " + StringUtil.jQuote(varName) - + ", when it was not set in the settings file (" + cfgFile + ")."); - } - } + // Remove existing copyright header: + content = content.substring(commentEnd); + } - Map<String, Object> customVariables = new HashMap<>(); - customVariables.putAll(customVariablesFromSettingsFile); - customVariables.putAll(customVariableOverrides); + if (offline && copyrightComment != null) { + // Add copyright comment: + StringBuilder sb = new StringBuilder(TextUtil.normalizeEOL(copyrightJavaComment, eol)); + sb.append(eol); + if (content.length() > 0 && content.charAt(0) != '\n' && content.charAt(0) != '\r') { + sb.append(eol); + } + sb.append(content); + content = sb.toString(); + } - for (Entry<String, Object> entry : customVariables.entrySet()) { - if (entry.getValue() == null) { - throw new DocgenException("The custom variable " + StringUtil.jQuote(entry.getKey()) - + " was set to null, which is not allowed. Probably you are supposed to override its value."); + Path destSubdir = destDir.toPath().resolve("docgen-resources"); + Files.createDirectories(destSubdir); + Files.write(destSubdir.resolve(staticFileName), content.getBytes(fileCharset)); + } else { + FileUtil.copyResourceIntoFile( + Transform.class, "statics", staticFileName, + new File(destDir, "docgen-resources")); } } - - return customVariables; } - private Map<String, Path> computeInsertableFiles() throws DocgenException { - for (String varName : insertableFilesOverrides.keySet()) { - if (!insertableFilesFromSettingsFile.containsKey(varName)) { - throw new DocgenException("Attempt to set insertable path with symbolic name " - + StringUtil.jQuote(varName) - + ", when same was not set in the settings file (" + FILE_SETTINGS + ")."); - } - } - - Map<String, String> unresolvedInsertableFiles = new HashMap<>(); - unresolvedInsertableFiles.putAll(insertableFilesFromSettingsFile); - unresolvedInsertableFiles.putAll(insertableFilesOverrides); + private int copyCustomStatics() throws IOException { + logger.info("Copying custom static files..."); + int bookSpecStaticFileCounter = FileUtil.copyDir(contentDir, destDir, ignoredFilePathPatterns); + return bookSpecStaticFileCounter; + } - for (Entry<String, String> entry : unresolvedInsertableFiles.entrySet()) { - if (entry.getValue() == null) { - throw new DocgenException("The insertable path with symbolic name " - + StringUtil.jQuote(entry.getKey()) + " was set to path null, which is not allowed. " - + "Probably you are supposed to override its path."); - } + private void generateEclipseTOC(Document doc) throws IOException { + if (simpleNavigationMode) { + throw new DocgenException("Eclipse ToC generation is untested/unsupported with simpleNavigationMode=true."); } - Map<String, Path> insertableFiles = new HashMap<>(); - for (Entry<String, String> entry : unresolvedInsertableFiles.entrySet()) { - String symbolicName = entry.getKey(); - String unresolvedPath = entry.getValue(); - - Path path; - if (unresolvedPath.endsWith("/**") || unresolvedPath.endsWith("\\**")) { - path = srcDir.toPath().resolve(unresolvedPath.substring(0, unresolvedPath.length() - 3)); - if (!Files.isDirectory(path)) { - throw new DocgenException( - "Insertable file with symbolic name " + StringUtil.jQuote(symbolicName) - + " points to a directory that doesn't exist: " + StringUtil.jQuote(path)); - } - } else { - path = srcDir.toPath().resolve(unresolvedPath); - if (!Files.isRegularFile(path)) { - if (Files.isDirectory(path)) { - throw new DocgenException( - "Insertable file with symbolic name " + StringUtil.jQuote(symbolicName) - + " points to a directory, not a file: " + StringUtil.jQuote(path) + "." - + " If you want to point to a directory, end the path with \"/**\"."); - } else { - throw new DocgenException( - "Insertable file with symbolic name " + StringUtil.jQuote(symbolicName) - + " points to a file that doesn't exist: " + StringUtil.jQuote(path)); - } + logger.info("Generating Eclipse ToC..."); + Template template = fmConfig.getTemplate(FILE_ECLIPSE_TOC_TEMPLATE); + try (Writer wr = FileUtil.newFileWriter(new File(destDir, FILE_ECLIPSE_TOC_OUTPUT))) { + try { + SimpleHash dataModel = new SimpleHash(fmConfig.getObjectWrapper()); + if (eclipseLinkTo != null) { + dataModel.put(VAR_ECLIPSE_LINK_TO, eclipseLinkTo); } + template.process(dataModel, wr, null, NodeModel.wrap(doc)); + } catch (TemplateException e) { + throw new BugException("Failed to generate Eclipse ToC " + + "(see cause exception).", e); } - - insertableFiles.put(symbolicName, path); - } - - return insertableFiles; - } - - private void resolveLogoHref(Logo logo) throws DocgenException { - String logoHref = logo.getHref(); - if (logoHref != null) { - logo.setHref(resolveDocgenURL(SETTING_LOGO, logoHref)); } } @@ -1337,6 +1413,13 @@ public final class Transform { } } + private void resolveLogoHref(Logo logo) throws DocgenException { + String logoHref = logo.getHref(); + if (logoHref != null) { + logo.setHref(resolveDocgenURL(SETTING_LOGO, logoHref)); + } + } + private static Logo castMapToLogo(SettingName settingName, Object settingValue) { Map<String, String> logoMap = castSetting( settingName, @@ -1367,89 +1450,6 @@ public final class Transform { } } - private void copyCommonStatic(String staticFileName) throws IOException { - String resourcePath = "statics/" + staticFileName; - try (InputStream in = Transform.class.getResourceAsStream(resourcePath)) { - if (in == null) { - throw new IOException("Failed to open class-loader resource: " + resourcePath + " relatively to " - + Transform.class.getPackage().getName()); - } - - if (staticFileName.endsWith(".css") || staticFileName.endsWith(".js")) { - // ISO-8859-1 will be good enough as far as the resource isn't UTF-16 or EBCDIC: - final Charset fileCharset = StandardCharsets.ISO_8859_1; - String content = FileUtil.loadString(in, fileCharset); - final String eol = TextUtil.detectEOL(content, "\n"); - - // If we have an initial comment, then that must be a copyright header, which we will remove. - if (content.startsWith("/*")) { - int commentEnd = content.indexOf("*/"); - if (commentEnd == -1) { - throw new BugException("Unclosed initial \"/*\" in resource " + resourcePath); - } - commentEnd += 2; - String comment = content.substring(0, commentEnd); - if (!comment.contains("Copyright") && !comment.contains("copyright") - && !comment.contains("License") && !comment.contains("license")) { - throw new BugException("The initial /*...*/ comments doesn't look like a copyright header " - + "in resource " + resourcePath); - } - - // Include an EOL after the comment, if there's any. - for (int i = 0; i < 2; i++) { - if (commentEnd < content.length()) { - char c = content.charAt(commentEnd); - if (c == '\n') { - commentEnd++; - } else if (c == '\r') { - commentEnd++; - if (commentEnd < content.length() && content.charAt(commentEnd) == '\n') { - commentEnd++; - } - } - } - } - - // Remove existing copyright header: - content = content.substring(commentEnd); - } - - if (offline && copyrightComment != null) { - // Add copyright comment: - StringBuilder sb = new StringBuilder(TextUtil.normalizeEOL(copyrightJavaComment, eol)); - sb.append(eol); - if (content.length() > 0 && content.charAt(0) != '\n' && content.charAt(0) != '\r') { - sb.append(eol); - } - sb.append(content); - content = sb.toString(); - } - - Path destSubdir = destDir.toPath().resolve("docgen-resources"); - Files.createDirectories(destSubdir); - Files.write(destSubdir.resolve(staticFileName), content.getBytes(fileCharset)); - } else { - FileUtil.copyResourceIntoFile( - Transform.class, "statics", staticFileName, - new File(destDir, "docgen-resources")); - } - } - } - - /** - * Adds attribute <tt>id</tt> to elements that are in - * <code>idAttrElements</code>, but has no id attribute yet. - * Adding id-s is useful to create more precise HTML cross-links later. - */ - private void preprocessDOM(Document doc) - throws SAXException, DocgenException { - NodeModel.simplify(doc); - preprocessDOM_applyRemoveNodesWhenOnlineSetting(doc); - preprocessDOM_addRanks(doc); - preprocessDOM_misc(doc); - preprocessDOM_buildTOC(doc); - } - private static final class PreprocessDOMMisc_GlobalState { private int lastId; @@ -2328,7 +2328,7 @@ public final class Transform { } } - private void generateSearchResultsHTMLFile(Document doc) throws TemplateException, IOException, DocgenException { + private void generateSearchResultsHtmlFileInner(Document doc) throws TemplateException, IOException, DocgenException { SimpleHash dataModel = new SimpleHash(fmConfig.getObjectWrapper()); dataModel.put(VAR_PAGE_TYPE, PAGE_TYPE_SEARCH_RESULTS);
