View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.doxia.util;
20  
21  import java.io.BufferedWriter;
22  import java.io.IOException;
23  import java.io.Writer;
24  
25  /**
26   * Allows to specify the line-length of an output writer.
27   */
28  public class LineBreaker {
29      /** The default maximal line length. */
30      public static final int DEFAULT_MAX_LINE_LENGTH = 78;
31  
32      /** The system dependent EOL. */
33      private static final String EOL = System.getProperty("line.separator");
34  
35      /** The destination writer. */
36      private Writer destination;
37  
38      /** The writer to use. */
39      private BufferedWriter writer;
40  
41      /** The maximal line length. */
42      private int maxLineLength;
43  
44      /** The current line length. */
45      private int lineLength = 0;
46  
47      /** The string buffer to store the current text. */
48      private StringBuilder word = new StringBuilder(1024);
49  
50      /**
51       * Constructs a new LineBreaker with DEFAULT_MAX_LINE_LENGTH.
52       *
53       * @param out The writer to use.
54       */
55      public LineBreaker(Writer out) {
56          this(out, DEFAULT_MAX_LINE_LENGTH);
57      }
58  
59      /**
60       * Constructs a new LineBreaker with the given max line length.
61       *
62       * @param out The writer to use.
63       * @param max The maximal line length.
64       */
65      public LineBreaker(Writer out, int max) {
66          if (max <= 0) {
67              throw new IllegalArgumentException("max must be a positive integer");
68          }
69  
70          destination = out;
71          this.maxLineLength = max;
72          writer = new BufferedWriter(out);
73      }
74  
75      /**
76       * Returns the current destination writer.
77       *
78       * @return The destination.
79       */
80      public Writer getDestination() {
81          return destination;
82      }
83  
84      /**
85       * Writes the given text to the writer. White space is not preserved.
86       *
87       * @param text The text to write.
88       * @throws java.io.IOException if there's a problem writing the text.
89       */
90      public void write(String text) throws IOException {
91          write(text, /*preserveSpace*/ false);
92      }
93  
94      /**
95       * Writes the given text to the writer.
96       *
97       * @param text The text to write.
98       * @param preserveSpace True to preserve white space.
99       */
100     public void write(String text, boolean preserveSpace) {
101         int length = text.length();
102 
103         try {
104             for (int i = 0; i < length; ++i) {
105                 char c = text.charAt(i);
106 
107                 switch (c) {
108                     case ' ':
109                         if (preserveSpace) {
110                             word.append(c);
111                         } else {
112                             writeWord();
113                         }
114                         break;
115 
116                     case '\r':
117                         // if \r\n (windows) then just pass along \n
118                         if (i + 1 < length && text.charAt(i + 1) == '\n') {
119                             break;
120                         }
121 
122                     case '\n':
123                         writeWord();
124                         writer.write(EOL);
125                         lineLength = 0;
126                         break;
127 
128                     default:
129                         word.append(c);
130                 }
131             }
132         } catch (Exception e) {
133             // TODO: log
134         }
135     }
136 
137     /**
138      * Write out the current StringBuilder and flush the writer.
139      * Any IOException will be swallowed.
140      */
141     public void flush() {
142         try {
143             writeWord();
144             writer.flush();
145         } catch (IOException e) {
146             // TODO: log
147         }
148     }
149 
150     /**
151      * Writes the current StringBuilder to the writer.
152      *
153      * @throws IOException if an exception occurs during writing.
154      */
155     private void writeWord() throws IOException {
156         int length = word.length();
157         if (length > 0) {
158             if (lineLength > 0) {
159                 if (lineLength + 1 + length > maxLineLength) {
160                     writer.write(EOL);
161                     lineLength = 0;
162                 } else {
163                     writer.write(' ');
164                     ++lineLength;
165                 }
166             }
167 
168             writer.write(word.toString());
169             word.setLength(0);
170 
171             lineLength += length;
172         }
173     }
174 
175     /**
176      * Close the writer.
177      */
178     public void close() {
179         if (writer == null) {
180             return;
181         }
182 
183         try {
184             writer.close();
185         } catch (IOException ex) {
186             // ignore
187         }
188     }
189 }