sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1403036 - in /sis/branches/JDK7/sis-utility/src: main/java/org/apache/sis/io/ main/java/org/apache/sis/util/ test/java/org/apache/sis/io/
Date Sun, 28 Oct 2012 16:32:27 GMT
Author: desruisseaux
Date: Sun Oct 28 16:32:27 2012
New Revision: 1403036

URL: http://svn.apache.org/viewvc?rev=1403036&view=rev
Log:
Merged ExpandedTabFormatter with LineWrapFormatter. The reason is that LineWrapFormatter needs
to take tabulation in account for correct line length calculation, and ExpandedTabFormatter
would be better to use the same line-detection and X.364 escape sequences handling than
LineWrapFormatter for consistency. This would lead to large duplication between those two
classes both in term of code and in term of processing power.

We should probably merge the other line-related formatters for the same reasons,
and rename as LineFormatter. This will be the subject of another commit.

Removed:
    sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/io/ExpandedTabFormatter.java
Modified:
    sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/io/LineWrapFormatter.java
    sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/io/TableFormatter.java
    sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java
    sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/io/ExpandedTabFormatterTest.java
    sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/io/LineWrapFormatterTest.java

Modified: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/io/LineWrapFormatter.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/io/LineWrapFormatter.java?rev=1403036&r1=1403035&r2=1403036&view=diff
==============================================================================
--- sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/io/LineWrapFormatter.java (original)
+++ sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/io/LineWrapFormatter.java Sun
Oct 28 16:32:27 2012
@@ -19,6 +19,7 @@ package org.apache.sis.io;
 import java.io.Flushable;
 import java.io.IOException;
 import org.apache.sis.util.Decorator;
+import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.ArgumentChecks;
 
 import static org.apache.sis.io.X364.ESCAPE;
@@ -30,8 +31,19 @@ import static org.apache.sis.util.Charac
 
 /**
  * An {@link Appendable} which wraps the lines to some maximal line length.
- * The default line length is 80 characters, but can be changed by a call to
- * {@link #setMaximalLineLength(int)}.
+ * The default line length is 80 Unicode characters (code points), but can
+ * be changed by a call to {@link #setMaximalLineLength(int)}.
+ *
+ * <p>The characters given to this filter can contain {@linkplain X364 X.364} escape
sequences,
+ * as this class will not count the space used by those escape sequences in the calculation
of
+ * line length.</p>
+ *
+ * {@section Tabulations}
+ * For proper calculation of line lengths in presence of tabulation characters ({@code '\t'}),
+ * this class needs to known the tabulation width. The default value is 8, but this can be
changed
+ * by a call to {@link #setTabulationWidth(int)}. By default tabulation characters are sent
to the
+ * {@linkplain #out underlying appendable} <i>as-is</i>, but this class can optionally
be instructed
+ * to expand tabulations by a call to {@link #setTabulationExpanded(boolean)}.
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3 (derived from geotk-3.00)
@@ -41,13 +53,17 @@ import static org.apache.sis.util.Charac
 @Decorator(Appendable.class)
 public class LineWrapFormatter extends FilteredAppendable implements Flushable {
     /**
-     * The line separator. We will use the first line separator found in the
-     * text to write, or the system default if none.
+     * The line separator to use when this class inserts some (line separators found in the
+     * texts given by the user will be passed "as is"). We will use the first line separator
+     * found in the given texts, or the system default if none.
      */
     private String lineSeparator;
 
     /**
      * The maximal line length, in units of <em>code points</em> (not {@code
char}).
+     * Can be set to {@link Integer#MAX_VALUE} if there is no limit.
+     *
+     * @see #setMaximalLineLength(int)
      */
     private int maximalLineLength;
 
@@ -59,6 +75,20 @@ public class LineWrapFormatter extends F
     private int codePointCount;
 
     /**
+     * The tabulation width, in number of code points.
+     *
+     * @see #setTabulationWidth(int)
+     */
+    private int tabulationWidth = 8;
+
+    /**
+     * {@code true} if this formatter shall expands tabulations into spaces.
+     *
+     * @see #setTabulationExpanded(boolean)
+     */
+    private boolean isTabulationExpanded;
+
+    /**
      * {@code true} if an escape sequence is in progress. The escape sequence will stop
      * after the first non-digit character other than {@link #IGNORE_AFTER_ESCAPE}.
      */
@@ -70,7 +100,7 @@ public class LineWrapFormatter extends F
     private final StringBuilder buffer = new StringBuilder(16);
 
     /**
-     * Constructs a formatter which will wrap the lines at a maximum of 80 characters.
+     * Constructs a formatter which will wrap the lines at a maximum of 80 Unicode characters.
      * The maximal line length can be changed by a call to {@link #setMaximalLineLength(int)}.
      *
      * @param out The underlying stream or buffer to write to.
@@ -83,28 +113,35 @@ public class LineWrapFormatter extends F
     /**
      * Constructs a formatter which will wrap the lines at a given maximal length.
      *
-     * @param out The underlying stream or buffer to write to.
-     * @param length The maximal line length.
+     * @param out                   The underlying stream or buffer to write to.
+     * @param maximalLineLength     The maximal number of Unicode characters per line,
+     *                              or {@link Integer#MAX_VALUE} if there is no limit.
+     * @param isTabulationExpanded  {@code true} for expanding tabulations into spaces,
+     *                              or {@code false} for sending {@code '\t'} characters
as-is.
      */
-    public LineWrapFormatter(final Appendable out, final int length) {
+    public LineWrapFormatter(final Appendable out, final int maximalLineLength, final boolean
isTabulationExpanded) {
         super(out);
-        ArgumentChecks.ensureStrictlyPositive("length", length);
-        maximalLineLength = length;
+        ArgumentChecks.ensureStrictlyPositive("maximalLineLength", maximalLineLength);
+        this.maximalLineLength    = maximalLineLength;
+        this.isTabulationExpanded = isTabulationExpanded;
     }
 
     /**
-     * Returns the maximal line length. The default value is 80.
+     * Returns the maximal line length, in unit of Unicode characters (code point count).
+     * The default value is 80.
      *
-     * @return The current maximal line length.
+     * @return The current maximal number of Unicode characters per line,
+     *         or {@link Integer#MAX_VALUE} if there is no limit.
      */
     public int getMaximalLineLength() {
         return maximalLineLength;
     }
 
     /**
-     * Sets the maximal line length.
+     * Sets the maximal line length, in units of Unicode characters (code point count).
      *
-     * @param length The new maximal line length.
+     * @param length The new maximal number of Unicode characters per line,
+     *               or {@link Integer#MAX_VALUE} if there is no limit.
      */
     public void setMaximalLineLength(final int length) {
         ArgumentChecks.ensureStrictlyPositive("length", length);
@@ -112,6 +149,62 @@ public class LineWrapFormatter extends F
     }
 
     /**
+     * Returns the current tabulation width, in unit of Unicode characters (code point count).
+     * The default value is 8.
+     *
+     * @return The current tabulation width in number of Unicode characters.
+     */
+    public int getTabulationWidth() {
+        return tabulationWidth;
+    }
+
+    /**
+     * Sets the tabulation width, in unit of Unicode characters (code point count).
+     *
+     * @param  width The new tabulation width. Must be greater than 0.
+     * @throws IllegalArgumentException if {@code tabWidth} is not greater than 0.
+     */
+    public void setTabulationWidth(final int width) {
+        ArgumentChecks.ensureStrictlyPositive("width", width);
+        tabulationWidth = width;
+    }
+
+    /**
+     * Returns {@code true} if this formatter expands tabulations into spaces.
+     * The default value is {@code false}, which means that {@code '\t'} characters
+     * are sent to the {@linkplain #out underlying appendable} <i>as-is</i>.
+     *
+     * @return {@code true} if this formatter expands tabulations into spaces,
+     *         or {@code false} if {@code '\t'} characters are sent <i>as-is</i>.
+     */
+    public boolean isTabulationExpanded() {
+        return isTabulationExpanded;
+    }
+
+    /**
+     * Sets whether this class formatter expands tabulations into spaces.
+     *
+     * @param expanded {@code true} if this class shall expands tabulations into spaces,
+     *                 or {@code false} for sending {@code '\t'} characters as-is.
+     */
+    public void setTabulationExpanded(final boolean expanded) {
+        isTabulationExpanded = expanded;
+    }
+
+    /**
+     * Writes a line separator to {@link #out}. This method is invoked only for new line
separators
+     * generated by this class, not for the line separators found in the texts supplied by
the user.
+     * The {@link #append(CharSequence,int,int)} method tries to detect the line separator
used in
+     * the text, but if no line separator has been found we have to use some fallback.
+     */
+    private void lineSeparator() throws IOException {
+        if (lineSeparator == null) {
+            lineSeparator = System.lineSeparator();
+        }
+        out.append(lineSeparator);
+    }
+
+    /**
      * Removes the soft hyphen characters from the given buffer. This is invoked
      * when the buffer is about to be written without being split on two lines.
      */
@@ -145,12 +238,36 @@ public class LineWrapFormatter extends F
             isEscapeSequence = true;
             return;
         }
-        if (Character.isSpaceChar(c)) {
+        /*
+         * Use Character.isWhitespace(…) instead of Character.isSpaceChar(…)
+         * because the former accepts tabulations (which we want), and does
+         * not returns 'true' for non-breaking spaces (which we also want).
+         */
+        if (Character.isWhitespace(c)) {
             deleteSoftHyphen(buffer);
             out.append(buffer);
             buffer.setLength(0);
             isEscapeSequence = false; // Handle spaces as "end of escape sequence".
         }
+        /*
+         * If the character is the tabulation, compute the number of spaces and optionally
replace
+         * the tabulation by spaces. Note that in such case, the buffer is empty (because
of the
+         * above block) so we don't need to bother about the buffer when writing to 'out'.
+         */
+        if (c == '\t') {
+            final int width = tabulationWidth - (codePointCount % tabulationWidth);
+            if ((codePointCount += width) > maximalLineLength) {
+                lineSeparator();
+                codePointCount = 0;
+            } else {
+                if (isTabulationExpanded) {
+                    buffer.append(CharSequences.spaces(width));
+                } else {
+                    buffer.append('\t');
+                }
+            }
+            return;
+        }
         buffer.appendCodePoint(c);
         /*
          * Special handling of ANSI X3.64 escape sequences. Since they are not visible
@@ -198,20 +315,12 @@ searchHyp:  for (int i=buffer.length(); 
                     }
                 }
             }
-            /*
-             * The append(CharSequence,int,int) method tries to detect the line separator
-             * used in the document to be formatted. But if no line separator can be found,
-             * then fallback on the system default.
-             */
-            if (lineSeparator == null) {
-                lineSeparator = System.lineSeparator();
-            }
-            out.append(lineSeparator);
+            lineSeparator();
             final int length = buffer.length();
             codePointCount = buffer.codePointCount(0, length);
             for (int i=0; i<length;) {
                 final int s = buffer.codePointAt(i);
-                if (!Character.isSpaceChar(s)) {
+                if (!Character.isWhitespace(s)) {
                     buffer.delete(0, i);
                     return;
                 }

Modified: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/io/TableFormatter.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/io/TableFormatter.java?rev=1403036&r1=1403035&r2=1403036&view=diff
==============================================================================
--- sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/io/TableFormatter.java (original)
+++ sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/io/TableFormatter.java Sun
Oct 28 16:32:27 2012
@@ -125,7 +125,7 @@ public class TableFormatter extends Filt
     };
 
     /**
-     * Default character for space.
+     * The character for empty spaces to insert between columns.
      */
     private static final char SPACE = ' ';
 
@@ -249,6 +249,15 @@ public class TableFormatter extends Filt
      */
     public TableFormatter(final Appendable out, final String separator) {
         super(out);
+        /*
+         * Use Character.isSpaceChar(…) instead of Character.isWhitespace(…) because
the former
+         * does not consider control characters (tabulation, group separator, etc.) as spaces.
+         * We presume that if the user wants to put such characters in the border, he has
reasons.
+         *
+         * If this policy is changed, search for other occurrences of 'isSpaceChar' in this
class
+         * for ensuring consistency. Note however that the same policy is not necessarily
applied
+         * everywhere.
+         */
         final int length = separator.length();
         int lower = 0;
         int upper = length;
@@ -302,8 +311,10 @@ public class TableFormatter extends Filt
         }
         assert (verticalBorder >= -1) && (verticalBorder <= +1) : verticalBorder;
         /*
-         * Remplaces spaces by the horizontal lines,
-         * and vertical lines by an intersection.
+         * Remplaces spaces by the horizontal lines, and vertical lines by an intersection.
+         * Use Character.isSpaceChar(…) instead of Character.isWhitespace(…) for
consistency
+         * with the policy used in the constructor, since we work on the same object (namely
+         * the border strings).
          */
         final int index = (horizontalBorder+1) + (verticalBorder+1)*3;
         final int borderLength = border.length();
@@ -619,7 +630,7 @@ public class TableFormatter extends Filt
             nextColumn(fill);
         }
         assert buffer.length() == 0;
-        cells.add(!Character.isSpaceChar(fill) ? new Cell(null, alignment, fill) : null);
+        cells.add((fill != SPACE) ? new Cell(null, alignment, fill) : null);
         currentColumn = 0;
         currentRow++;
     }
@@ -743,8 +754,14 @@ public class TableFormatter extends Filt
                             if (c == '\r' && (next < textLength) && cellText.charAt(next)
== '\n') {
                                 next++;
                             }
-                            // Verify if the remaining contains only whitespaces, but do
not skip
-                            // those whitespaces if there is at least one non-white character.
+                            /*
+                             * Verify if the remaining contains only white spaces. If so,
those spaces
+                             * will be ignored. But if there is at least one non-white character,
then
+                             * we will not skip those spaces. We use Character.isWhitespace(…)
instead
+                             * of Character.isSpaceChar(…) in order to consider non-breaking
spaces as
+                             * non-white characters. This is similar to the use of &nbsp;
in HTML tables,
+                             * which can be used for forcing the insertion of an otherwise
ignored space.
+                             */
                             for (int i=next; i<textLength; i += Character.charCount(c))
{
                                 c = cellText.codePointAt(i);
                                 if (!Character.isWhitespace(c)) {
@@ -783,7 +800,8 @@ public class TableFormatter extends Filt
                     if (isFirstColumn) {
                         out.append(leftBorder);
                     }
-                    final Appendable tabExpander = (cellText.indexOf('\t') >= 0) ? new
ExpandedTabFormatter(out) : out;
+                    final Appendable tabExpander = (cellText.indexOf('\t') >= 0)
+                            ? new LineWrapFormatter(out, Integer.MAX_VALUE, true) : out;
                     switch (cell.alignment) {
                         default: {
                             throw new AssertionError(cell.alignment);

Modified: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java?rev=1403036&r1=1403035&r2=1403036&view=diff
==============================================================================
--- sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java (original)
+++ sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java Sun
Oct 28 16:32:27 2012
@@ -1050,7 +1050,7 @@ searchWordBreak:    while (true) {
         final int lg = buffer.length();
         if (lg != 0) {
             final int cp = buffer.codePointBefore(lg);
-            if (isSpaceChar(cp)) {
+            if (isWhitespace(cp)) {
                 buffer.setLength(lg - charCount(cp));
             }
         }

Modified: sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/io/ExpandedTabFormatterTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/io/ExpandedTabFormatterTest.java?rev=1403036&r1=1403035&r2=1403036&view=diff
==============================================================================
--- sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/io/ExpandedTabFormatterTest.java
(original)
+++ sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/io/ExpandedTabFormatterTest.java
Sun Oct 28 16:32:27 2012
@@ -24,7 +24,8 @@ import static org.junit.Assert.*;
 
 
 /**
- * Tests the {@link ExpandedTabFormatter} implementation.
+ * Tests the {@link LineWrapFormatter} implementation
+ * when used for expanding tabulations to spaces.
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3 (derived from geotk-3.00)
@@ -37,7 +38,7 @@ public final strictfp class ExpandedTabF
      * Creates a new test case.
      */
     public ExpandedTabFormatterTest() {
-        formatter = new ExpandedTabFormatter(formatter);
+        formatter = new LineWrapFormatter(formatter, Integer.MAX_VALUE, true);
     }
 
     /**
@@ -46,8 +47,8 @@ public final strictfp class ExpandedTabF
     @Override
     void run(final String lineSeparator) throws IOException {
         final Appendable out = formatter;
-        if (out instanceof ExpandedTabFormatter) {
-            assertEquals("getTabWidth", 8, ((ExpandedTabFormatter) out).getTabWidth());
+        if (out instanceof LineWrapFormatter) {
+            assertEquals("getTabWidth", 8, ((LineWrapFormatter) out).getTabulationWidth());
         }
         assertSame(out, out.append("12\t8"   + lineSeparator));
         assertSame(out, out.append("1234\t8" + lineSeparator));

Modified: sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/io/LineWrapFormatterTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/io/LineWrapFormatterTest.java?rev=1403036&r1=1403035&r2=1403036&view=diff
==============================================================================
--- sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/io/LineWrapFormatterTest.java
(original)
+++ sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/io/LineWrapFormatterTest.java
Sun Oct 28 16:32:27 2012
@@ -25,7 +25,8 @@ import static org.apache.sis.util.Charac
 
 
 /**
- * Tests the {@link LineWrapFormatter} implementations.
+ * Tests the {@link LineWrapFormatter} implementation
+ * when used for wrapping lines to 80 characters.
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3 (derived from geotk-3.00)
@@ -38,7 +39,7 @@ public final strictfp class LineWrapForm
      * Creates a new test case.
      */
     public LineWrapFormatterTest() {
-        formatter = new LineWrapFormatter(formatter, 10);
+        formatter = new LineWrapFormatter(formatter, 10, false);
     }
 
     /**



Mime
View raw message