001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU General
007: * Public License Version 2 only ("GPL") or the Common Development and Distribution
008: * License("CDDL") (collectively, the "License"). You may not use this file except in
009: * compliance with the License. You can obtain a copy of the License at
010: * http://www.netbeans.org/cddl-gplv2.html or nbbuild/licenses/CDDL-GPL-2-CP. See the
011: * License for the specific language governing permissions and limitations under the
012: * License. When distributing the software, include this License Header Notice in
013: * each file and include the License file at nbbuild/licenses/CDDL-GPL-2-CP. Sun
014: * designates this particular file as subject to the "Classpath" exception as
015: * provided by Sun in the GPL Version 2 section of the License file that
016: * accompanied this code. If applicable, add the following below the License Header,
017: * with the fields enclosed by brackets [] replaced by your own identifying
018: * information: "Portions Copyrighted [year] [name of copyright owner]"
019: *
020: * Contributor(s):
021: *
022: * The Original Software is NetBeans. The Initial Developer of the Original Software
023: * is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun Microsystems, Inc. All
024: * Rights Reserved.
025: *
026: * If you wish your version of this file to be governed by only the CDDL or only the
027: * GPL Version 2, indicate your decision by adding "[Contributor] elects to include
028: * this software in this distribution under the [CDDL or GPL Version 2] license." If
029: * you do not indicate a single choice of license, a recipient has the option to
030: * distribute your version of this file under either the CDDL, the GPL Version 2 or
031: * to extend the choice of license to its licensees as provided above. However, if
032: * you add GPL Version 2 code and therefore, elected the GPL Version 2 license, then
033: * the option applies only if the new code is made subject to such option by the
034: * copyright holder.
035: */
036:
037: package org.netbeans.installer.infra.utils.comment.utils;
038:
039: import java.io.BufferedReader;
040: import java.io.File;
041: import java.io.FileReader;
042: import java.io.FileWriter;
043: import java.io.IOException;
044: import java.io.PrintWriter;
045: import java.io.StringReader;
046: import java.util.Arrays;
047: import java.util.LinkedList;
048: import java.util.List;
049:
050: /**
051: * This is the helper utility methods class for the initial comment correcter
052: * utility.
053: *
054: * It provides means to read a text file into a string, write a string to a file and
055: * to reformat a given text to the given line length. It also holds several
056: * constants that are used elsewhere.
057: *
058: * @author Kirill Sorokin
059: */
060: public final class Utils {
061: /////////////////////////////////////////////////////////////////////////////////
062: // Static
063: /**
064: * Reads the given text file into a string.
065: *
066: * @param file The file to read.
067: * @return Contents of the file as a string.
068: * @throws java.io.IOException if an I/O error occurs of there are problems
069: * with validating the supplied file.
070: * @throws java.lang.IllegalArgumentException if the parameter is null.
071: */
072: public static String readFile(final File file) throws IOException {
073: // basic validation
074: if (file == null) {
075: throw new IllegalArgumentException(
076: "The 'file' parameter cannot be null."); // NOI18N
077: }
078:
079: // file validation
080: if (!file.exists()) {
081: throw new IOException("The given file '" + file + // NOI18N
082: "' does not exist."); // NOI18N
083: }
084: if (!file.isFile()) {
085: throw new IOException("The given file '" + file + // NOI18N
086: "' exists but is a directory."); // NOI18N
087: }
088:
089: // read the file
090: final StringBuilder string = new StringBuilder();
091:
092: BufferedReader reader = null;
093: try {
094: reader = new BufferedReader(new FileReader(file));
095:
096: String line = null;
097: while ((line = reader.readLine()) != null) {
098: string.append(line + NL);
099: }
100: } finally {
101: if (reader != null) {
102: reader.close();
103: }
104: }
105:
106: return string.toString();
107: }
108:
109: /**
110: * Writes the given string to a file. The file contents are overwritten be the
111: * string.
112: *
113: * @param file The file to which the string should be written.
114: * @param string
115: * @throws java.io.IOException if an I/O errors occurs of there are problems
116: * with validating the supplied file.
117: * @throws java.lang.IllegalArgumentException if either of the parameters is
118: * null.
119: */
120: public static void writeFile(final File file, final String string)
121: throws IOException {
122: // basic validation
123: if (file == null) {
124: throw new IllegalArgumentException(
125: "The 'file' parameter cannot be null."); // NOI18N
126: }
127: if (string == null) {
128: throw new IllegalArgumentException(
129: "The 'string' parameter cannot be null."); // NOI18N
130: }
131:
132: // file validation
133: final File parent = file.getParentFile();
134: if (file.exists() && !file.isFile()) {
135: throw new IOException("The given file '" + file + // NOI18N
136: "' exists and is not a file."); // NOI18N
137: }
138: if (parent.exists() && !parent.isDirectory()) {
139: throw new IOException("The parent of the given file '"
140: + parent + // NOI18N
141: "' exists and is not a directory."); // NOI18N
142: }
143: if (!parent.exists() && !parent.mkdirs()) {
144: throw new IOException("The parent of the given file '"
145: + parent + // NOI18N
146: "' does not exist and could not be created."); // NOI18N
147: }
148:
149: // write the file
150: final BufferedReader reader = new BufferedReader(
151: new StringReader(string));
152:
153: PrintWriter writer = null;
154: try {
155: writer = new PrintWriter(new FileWriter(file));
156:
157: String line = null;
158: while ((line = reader.readLine()) != null) {
159: writer.println(line);
160: }
161: } finally {
162: if (writer != null) {
163: writer.close();
164: }
165: }
166: }
167:
168: /**
169: * Reformats the given text to the given line length.
170: *
171: * <p>
172: * Optinally the caller may specify a prefix which will be prepended to every
173: * string in the reformatted file.
174: *
175: * @param string The text to reformat.
176: * @param prefix The prefix to attach to the lines of the reformatted text.
177: * @param length The desired line length.
178: * @return The reformatted as a string.
179: * @throws java.lang.IllegalArgumentException if either of the parameters is
180: * null or if the line length is negative or zero.
181: */
182: public static String reformat(final String string,
183: final String prefix, final int length) {
184: // basic validation
185: if (string == null) {
186: throw new IllegalArgumentException(
187: "The 'string' parameter cannot be null."); // NOI18N
188: }
189: if (prefix == null) {
190: throw new IllegalArgumentException(
191: "The 'prefix' parameter cannot be null."); // NOI18N
192: }
193: if (length <= 0) {
194: throw new IllegalArgumentException(
195: "The 'length' parameter should be positive."); // NOI18N
196: }
197:
198: final List<String> lines = new LinkedList<String>();
199: lines.addAll(Arrays.asList(string.split(NL_PATTERN)));
200:
201: final int realLength = length - prefix.length();
202:
203: for (int i = 0; i < lines.size(); i++) {
204: String line = lines.get(i);
205:
206: // if the current line's length is greater than the required one, we
207: // find the space character which will allow us to wrap the line
208: // satisfying the required length (the new line will be inserted into
209: // the list and processed at the next iteration); if the line cannot be
210: // wrapped - it is NOT modified
211: // if the line's length is less than the required one, and the line is
212: // not empty (which would the end of a paragraph), and is not the last
213: // line in the text, we try to attach the next line to it and wrap the
214: // sum if it's required
215: if (line.length() > realLength) {
216: final int index = findPrevious(line, ' ', realLength);
217:
218: if (index != -1) {
219: lines.add(i, line.substring(0, index));
220: lines.set(i + 1, line.substring(index + 1));
221: }
222: } else if (!line.trim().equals(EL)
223: && (i < lines.size() - 1)) {
224: final String next = lines.get(i + 1);
225:
226: if (!next.trim().equals(EL)) {
227: if (!line.endsWith(SP)) {
228: line = line + SP + next;
229: } else {
230: line = line + next;
231: }
232:
233: if (line.length() > realLength) {
234: int index = findPrevious(line, ' ', realLength);
235:
236: if (index != -1) {
237: lines.set(i, line.substring(0, index));
238: lines.set(i + 1, line.substring(index + 1));
239: }
240: } else {
241: lines.set(i, line);
242: lines.remove(i + 1);
243: }
244: }
245: }
246: }
247:
248: // concatenate the lines and return the result
249: final StringBuilder builder = new StringBuilder();
250: for (String line : lines) {
251: builder.append(prefix).append(line).append(NL);
252: }
253:
254: return builder.toString();
255: }
256:
257: // private //////////////////////////////////////////////////////////////////////
258: /**
259: * Finds the previous entry of the given character in the given string, starting
260: * at the given offset.
261: *
262: * @param string The string in which to perform the search.
263: * @param ch The character to look for.
264: * @param offset The offset from which to start searching.
265: * @return The previous index of the given character of <code>-1</code> if the
266: * character cannot be found.
267: * @throws java.lang.IllegalArgumentException if the string parameter is null.
268: */
269: private static int findPrevious(final String string, final char ch,
270: final int offset) {
271: // basic validation
272: if (string == null) {
273: throw new IllegalArgumentException(
274: "The 'string' parameter cannot be null."); // NOI18N
275: }
276:
277: for (int i = offset; i > 0; i--) {
278: if (string.charAt(i) == ch) {
279: return i;
280: }
281: }
282:
283: return -1;
284: }
285:
286: /////////////////////////////////////////////////////////////////////////////////
287: // Instance
288: /**
289: * A dummy <code>private</code> default constructor, which prevents the class
290: * from being instantiated.
291: */
292: private Utils() {
293: // does nothing
294: }
295:
296: /////////////////////////////////////////////////////////////////////////////////
297: // Constants
298: /**
299: * Newline character combination for the current platform. This would be
300: * equal to \r\n on windows, \n on unices and \r on mac.
301: */
302: public static final String NL = System
303: .getProperty("line.separator"); // NOI18N
304:
305: /**
306: * Empty line constant.
307: */
308: public static final String EL = ""; // NOI18N
309:
310: /**
311: * Space character constant.
312: */
313: public static final String SP = " "; // NOI18N
314:
315: /**
316: * A platform-agnostic pattern which will match the end of the line.
317: */
318: public static final String NL_PATTERN = "\r\n|\n|\r"; // NOI18N
319: }
|