001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2003-2006, GeoTools Project Managment Committee (PMC)
005: * (C) 2001, Institut de Recherche pour le Développement
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation;
010: * version 2.1 of the License.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: */
017: package org.geotools.io;
018:
019: // Standard I/O
020: import java.io.FilterWriter;
021: import java.io.IOException;
022: import java.io.Writer;
023:
024: // Geotools dependencies
025: import org.geotools.resources.Utilities;
026:
027: /**
028: * Writes characters to a stream while expanding
029: * tabs (<code>'\t'</code>) into spaces.
030: *
031: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/metadata/src/main/java/org/geotools/io/ExpandedTabWriter.java $
032: * @version $Id: ExpandedTabWriter.java 22443 2006-10-27 20:47:22Z desruisseaux $
033: * @author Martin Desruisseaux
034: *
035: * @since 2.0
036: */
037: public class ExpandedTabWriter extends FilterWriter {
038: /**
039: * Tab width (in number of spaces).
040: */
041: private int tabWidth = 8;
042:
043: /**
044: * Current column position.
045: * Columns are numbered from 0.
046: */
047: private int column = 0;
048:
049: /**
050: * Constructs a filter which replaces tab characters (<code>'\t'</code>)
051: * with spaces. Tab widths default to 8 characters.
052: *
053: * @param out a Writer object to provide the underlying stream.
054: */
055: public ExpandedTabWriter(final Writer out) {
056: super (out);
057: }
058:
059: /**
060: * Constructs a filter which replaces tab characters (<code>'\t'</code>)
061: * with spaces, using the specified tab width.
062: *
063: * @param out a Writer object to provide the underlying stream.
064: * @param tabWidth The tab width. Must be greater than 0.
065: * @throws IllegalArgumentException if {@code tabWidth}
066: * is not greater than 0.
067: */
068: public ExpandedTabWriter(Writer out, int tabWidth)
069: throws IllegalArgumentException {
070: super (out);
071: setTabWidth(tabWidth);
072: }
073:
074: /**
075: * Sets the tab width.
076: *
077: * @param tabWidth The tab width. Must be greater than 0.
078: * @throws IllegalArgumentException if {@code tabWidth}
079: * is not greater than 0.
080: */
081: public void setTabWidth(final int tabWidth)
082: throws IllegalArgumentException {
083: synchronized (lock) {
084: if (tabWidth > 0) {
085: this .tabWidth = tabWidth;
086: } else {
087: throw new IllegalArgumentException(Integer
088: .toString(tabWidth));
089: }
090: }
091: }
092:
093: /**
094: * Returns the tab width.
095: */
096: public int getTabWidth() {
097: return tabWidth;
098: }
099:
100: /**
101: * Writes spaces for a tab character.
102: *
103: * @throws IOException If an I/O error occurs
104: */
105: private void expand() throws IOException {
106: final int width = tabWidth - (column % tabWidth);
107: out.write(Utilities.spaces(width));
108: column += width;
109: }
110:
111: /**
112: * Writes a single character.
113: *
114: * @throws IOException If an I/O error occurs
115: */
116: public void write(final int c) throws IOException {
117: synchronized (lock) {
118: switch (c) {
119: case '\r': // fall through
120: case '\n':
121: column = 0;
122: break;
123: case '\t':
124: expand();
125: return;
126: default:
127: column++;
128: break;
129: }
130: out.write(c);
131: }
132: }
133:
134: /**
135: * Writes a portion of an array of characters.
136: *
137: * @param buffer Buffer of characters to be written
138: * @param offset Offset from which to start reading characters
139: * @param length Number of characters to be written
140: * @throws IOException If an I/O error occurs
141: */
142: public void write(final char[] buffer, final int offset, int length)
143: throws IOException {
144: synchronized (lock) {
145: int start = offset;
146: length += offset;
147: for (int end = offset; end < length; end++) {
148: final char c = buffer[end];
149: switch (c) {
150: case '\r': // fall through
151: case '\n':
152: column = 0;
153: break;
154:
155: case '\t':
156: out.write(buffer, start, end - start);
157: start = end + 1;
158: expand();
159: break;
160:
161: default:
162: column++;
163: break;
164: }
165: }
166: out.write(buffer, start, length - start);
167: }
168: }
169:
170: /**
171: * Writes a portion of a string.
172: *
173: * @param string String to be written
174: * @param offset Offset from which to start reading characters
175: * @param length Number of characters to be written
176: * @throws IOException If an I/O error occurs
177: */
178: public void write(final String string, final int offset, int length)
179: throws IOException {
180: synchronized (lock) {
181: int start = offset;
182: length += offset;
183: for (int end = offset; end < length; end++) {
184: final char c = string.charAt(end);
185: switch (c) {
186: case '\r': // fall through
187: case '\n':
188: column = 0;
189: break;
190:
191: case '\t':
192: out.write(string, start, end - start);
193: start = end + 1;
194: expand();
195: break;
196:
197: default:
198: column++;
199: break;
200: }
201: }
202: out.write(string, start, length - start);
203: }
204: }
205: }
|