1 /* 2 * The contents of this file are subject to the terms of the Common Development and 3 * Distribution License (the License). You may not use this file except in compliance with the 4 * License. 5 * 6 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 7 * specific language governing permission and limitations under the License. 8 * 9 * When distributing Covered Software, include this CDDL Header Notice in each file and include 10 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 11 * Header, with the fields enclosed by brackets [] replaced by your own identifying 12 * information: "Portions copyright [year] [name of copyright owner]". 13 * 14 * Copyright 2012-2015 ForgeRock AS. 15 */ 16 17 package org.forgerock.doc.maven.utils; 18 19 import java.io.File; 20 import java.io.FileFilter; 21 import java.io.FilenameFilter; 22 import java.io.IOException; 23 import java.util.Set; 24 import java.util.TreeSet; 25 import java.util.regex.Pattern; 26 27 import org.apache.commons.io.FileUtils; 28 import org.apache.commons.io.FilenameUtils; 29 import org.codehaus.plexus.util.StringUtils; 30 31 /** 32 * Utility methods to work with documents. 33 */ 34 public final class NameUtils { 35 /** 36 * Pattern to validate the document names. 37 * 38 * <br> 39 * 40 * project-doc-version names are not expected in published docs, 41 * @see #renameDoc(String, String, String, String) 42 * 43 * <br> 44 * 45 * When published, documentation file names 46 * should include the version before the document name: 47 * Project-Version-Doc-Name.ext 48 * 49 * @deprecated since 3.0.0 50 * 51 * <p>Valid names:</p> 52 * <ul> 53 * <li>guide</li> 54 * <li>admin-quide</li> 55 * <li>OpenTEST-guide</li> 56 * <li>OpenTEST-admin-guide</li> 57 * <li>OpenTEST-admin-guide-1.1.1.0</li> 58 * <li>OpenTEST-admin-guide-1.1.1.0-SNAPSHOT</li> 59 * <li>OpenTEST-admin-guide-1.1.1.0-express</li> 60 * <li>OpenTEST-admin-guide-1.1.1.0-Xpress</li> 61 * <li>OpenTEST-admin-guide-1.1.1.0-Xpress1</li> 62 * <li>OpenTEST-10.1.0-admin-guide</li> 63 * <li>OpenTEST-10.1.0-SNAPSHOT-admin-guide</li> 64 * <li>OpenTEST-10.1.0-Xpress2-admin-guide</li> 65 * <li>db2-connector-1.1.0.0-SNAPSHOT</li> 66 * </ul> 67 * 68 * <p>Invalid names:</p> 69 * <ul> 70 * <li>guide.</li> 71 * <li>guide-1</li> 72 * <li>guide-.</li> 73 * </ul> 74 */ 75 @Deprecated 76 public static final Pattern DOCUMENT_FILE_PATTERN = Pattern 77 .compile("^([a-zA-Z0-9]+)(-?[0-9].[0-9\\.]*[0-9])?(-SNAPSHOT|(-Ex|-ex|-X)press[0-9])" 78 + "?([a-zA-Z-]*)((-?[0-9].[0-9\\.]*[0-9])?-?(SNAPSHOT|(Ex|ex|X)press[0-9]?)?)$"); 79 80 /** 81 * Rename document to reflect project and document name. For example, 82 * index.pdf could be renamed OpenAM-Admin-Guide.pdf. 83 * 84 * @param projectName 85 * Short name of the project, such as OpenAM, OpenDJ, OpenIDM 86 * @param docName 87 * Short name for the document, such as admin-guide, 88 * release-notes, reference 89 * @param extension 90 * File name extension not including dot, e.g. pdf 91 * @return New name for document. Can be "" if rename failed. 92 */ 93 public static String renameDoc(final String projectName, 94 final String docName, 95 final String extension) { 96 return renameDoc(projectName, docName, "", extension); 97 } 98 99 /** 100 * Rename document to reflect project and document name. For example, 101 * index.pdf could be renamed OpenAM-10.0.0-Admin-Guide.pdf. 102 * 103 * @param projectName 104 * Short name of the project, such as OpenAM, OpenDJ, OpenIDM 105 * @param docName 106 * Short name for the document, such as admin-guide, 107 * release-notes, reference 108 * @param version 109 * Document version such as 10.0.0, 2.5.0, 2.0.2 110 * @param extension 111 * File name extension not including dot, e.g. pdf 112 * @return New name for document. Can be "" if rename failed. 113 */ 114 public static String renameDoc(final String projectName, 115 final String docName, 116 final String version, 117 final String extension) { 118 119 // Doc name must be non-empty. 120 if (!StringUtils.isNotBlank(docName)) { 121 return ""; 122 } 123 124 StringBuilder sb = new StringBuilder(); 125 126 // If project name exists, capitalize it, replace spaces with hyphens, 127 // and follow the result with a hyphen. 128 if (StringUtils.isNotBlank(projectName)) { 129 sb.append(spacesToHyphens(capitalize(projectName))).append('-'); 130 131 // Version precedes the document name. 132 // It only makes sense to use a version if a project name is defined. 133 // If version exists, follow it with a hyphen. 134 if (StringUtils.isNotBlank(version)) { 135 sb.append(version).append('-'); 136 } 137 } 138 139 // Capitalize the doc name. 140 sb.append(capitalize(docName)); 141 142 // If extension exists, precede it with a . 143 if (StringUtils.isNotBlank(extension)) { 144 sb.append('.').append(extension); 145 } 146 147 return sb.toString(); 148 } 149 150 /** 151 * Capitalize initial letters in a document name. 152 * 153 * @param docName 154 * Name of the document such as reference or admin-guide 155 * @return Capitalized name such as Reference or Admin-Guide 156 */ 157 protected static String capitalize(final String docName) { 158 char[] chars = docName.toCharArray(); 159 160 boolean isInitial = true; 161 for (int i = 0; i < chars.length; i++) { 162 if (isInitial && Character.isLetter(chars[i])) { 163 chars[i] = Character.toUpperCase(chars[i]); 164 isInitial = false; 165 } else { 166 isInitial = !Character.isLetter(chars[i]); 167 } 168 } 169 170 return String.valueOf(chars); 171 } 172 173 /** 174 * Replace spaces with hyphens. 175 * 176 * @param string String in which to replace spaces with hyphens 177 * @return String with spaces replaced by hyphens. 178 */ 179 protected static String spacesToHyphens(final String string) { 180 return string.replaceAll(" ", "-"); 181 } 182 183 /** 184 * Returns names of directories that mirror the document names and contain 185 * DocBook XML documents to build. 186 * 187 * @param srcDir 188 * Directory containing DocBook XML sources. Document directories 189 * like admin-guide or reference are one level below this 190 * directory. 191 * @param docFile 192 * Name of a file common to all documents to build, such as 193 * index.xml. 194 * @return Document names, as in admin-guide or reference 195 */ 196 public static Set<String> getDocumentNames(final File srcDir, 197 final String docFile) { 198 Set<String> documentDirectories = new TreeSet<String>(); 199 200 // Match directories containing DocBook document entry point files, 201 // and ignore everything else. 202 FileFilter filter = new FileFilter() { 203 @Override 204 public boolean accept(final File file) { 205 return file.isDirectory(); 206 } 207 }; 208 209 File[] directories = srcDir.listFiles(filter); 210 if (directories != null && directories.length > 0) { 211 212 FilenameFilter nameFilter = new FilenameFilter() { 213 @Override 214 public boolean accept(final File file, final String name) { 215 return name.equalsIgnoreCase(docFile); 216 } 217 }; 218 219 for (File dir : directories) { 220 String[] found = dir.list(nameFilter); 221 if (found.length > 0) { 222 documentDirectories.add(dir.getName()); 223 } 224 } 225 } 226 227 return documentDirectories; 228 } 229 230 /** 231 * Rename a single built document. 232 * For example, rename {@code index.pdf} to {@code OpenAM-Admin-Guide.pdf}. 233 * 234 * @param builtDocument File to rename, such as {@code index.pdf}. 235 * @param docName Simple document name such as {@code admin-guide}. 236 * @param projectName Project name, such as {@code OpenAM}. 237 * @throws IOException Something went wrong renaming the file. 238 */ 239 public static void renameDocument(final File builtDocument, 240 final String docName, 241 final String projectName) 242 throws IOException { 243 String ext = FilenameUtils.getExtension(builtDocument.getName()); 244 File newFile = new File(builtDocument.getParent(), renameDoc(projectName, docName, ext)); 245 if (!newFile.exists()) { 246 FileUtils.moveFile(builtDocument, newFile); 247 } 248 } 249 250 /** 251 * Not used. 252 */ 253 private NameUtils() { 254 } 255 }