As the purpose of buffer is to "buffer", let's modify our example to delegate to appendable methods directly only if the appendable is too big
1.1 --- a/samples/delegatingwriter/src/org/apidesign/delegatingwriter/AltBufferedWriter.java Sat Jun 14 09:53:06 2008 +0200
1.2 +++ b/samples/delegatingwriter/src/org/apidesign/delegatingwriter/AltBufferedWriter.java Sat Jun 14 09:53:07 2008 +0200
1.3 @@ -66,7 +66,12 @@
1.4 // BEGIN: writer.delegateout
1.5 // efficient, yet dangerous delegation skipping methods unknown to
1.6 // subclasses that used version 1.4
1.7 - out.append(csq);
1.8 + if (csq != null && csq.length() < 1024) {
1.9 + write(csq.toString());
1.10 + } else {
1.11 + flush();
1.12 + out.append(csq);
1.13 + }
1.14 return this;
1.15 // END: writer.delegateout
1.16 }
1.17 @@ -83,13 +88,10 @@
1.18 throw new IOException(ex);
1.19 }
1.20
1.21 - if (isOverriden) {
1.22 - if (csq == null) {
1.23 - write("null");
1.24 - } else {
1.25 - write(csq.toString());
1.26 - }
1.27 + if (isOverriden || (csq != null && csq.length() < 1024)) {
1.28 + write(csq.toString());
1.29 } else {
1.30 + flush();
1.31 out.append(csq);
1.32 }
1.33 return this;
2.1 --- a/samples/delegatingwriter/test/org/apidesign/delegatingwriter/BufferedWriterCryptoTest.java Sat Jun 14 09:53:06 2008 +0200
2.2 +++ b/samples/delegatingwriter/test/org/apidesign/delegatingwriter/BufferedWriterCryptoTest.java Sat Jun 14 09:53:07 2008 +0200
2.3 @@ -14,7 +14,8 @@
2.4 */
2.5 public class BufferedWriterCryptoTest {
2.6 private StringWriter writer;
2.7 -
2.8 + private String fromCode;
2.9 + private String toCode;
2.10
2.11 public BufferedWriterCryptoTest() {
2.12 }
2.13 @@ -22,6 +23,14 @@
2.14 @Before
2.15 public void setUp() {
2.16 writer = new StringWriter();
2.17 + StringBuffer f = new StringBuffer();
2.18 + StringBuffer t = new StringBuffer();
2.19 + for (int i = 0; i < 500; i++) {
2.20 + f.append("VMS");
2.21 + t.append("WNT");
2.22 + }
2.23 + fromCode = f.toString();
2.24 + toCode = t.toString();
2.25 }
2.26
2.27 @Test
2.28 @@ -35,13 +44,21 @@
2.29 }
2.30
2.31 @Test
2.32 + public void testBehaviourOfRealBufferInJDKWorksFineOnLongSentences() throws IOException {
2.33 + CryptoWriter bufferedWriter = new CryptoWriter(writer);
2.34 + bufferedWriter.append(fromCode);
2.35 + bufferedWriter.flush();
2.36 + assertEquals("Converted", toCode, writer.toString());
2.37 + }
2.38 +
2.39 + @Test
2.40 public void testBehaviourOfBufferThatDelegatesToAppendFails() throws IOException {
2.41 CryptoWriter bufferedWriter = new CryptoWriter(writer, CryptoWriter.Behaviour.DELEGATE_TO_OUT);
2.42 - bufferedWriter.append("VMS");
2.43 + bufferedWriter.append(fromCode);
2.44 bufferedWriter.flush();
2.45 assertEquals("This will fail, as the direct delegation from append to " +
2.46 "the underlaying writer will skip all the crypto methods",
2.47 - "WNT", writer.toString()
2.48 + toCode, writer.toString()
2.49 );
2.50 }
2.51
3.1 --- a/samples/delegatingwriter/test/org/apidesign/delegatingwriter/BufferedWriterThrowingExceptionTest.java Sat Jun 14 09:53:06 2008 +0200
3.2 +++ b/samples/delegatingwriter/test/org/apidesign/delegatingwriter/BufferedWriterThrowingExceptionTest.java Sat Jun 14 09:53:07 2008 +0200
3.3 @@ -4,8 +4,6 @@
3.4 import java.io.BufferedWriter;
3.5 import java.io.IOException;
3.6 import java.io.StringWriter;
3.7 -import java.io.Writer;
3.8 -import org.junit.After;
3.9 import org.junit.Before;
3.10 import org.junit.Test;
3.11 import static org.junit.Assert.*;
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/samples/delegatingwriterfinal/src-api1.0/api/SimpleBuffer.java Sat Jun 14 09:53:07 2008 +0200
4.3 @@ -0,0 +1,36 @@
4.4 +package api;
4.5 +
4.6 +import java.io.IOException;
4.7 +
4.8 +/**
4.9 + *
4.10 + * @author Jaroslav Tulach
4.11 + */
4.12 +final class SimpleBuffer implements Writer.Impl {
4.13 + private final Writer out;
4.14 + private final StringBuffer sb = new StringBuffer();
4.15 +
4.16 + public SimpleBuffer(Writer out) {
4.17 + this.out = out;
4.18 + }
4.19 +
4.20 + public void close() throws IOException {
4.21 + flush();
4.22 + out.close();
4.23 + }
4.24 +
4.25 + public void flush() throws IOException {
4.26 + out.write(sb.toString());
4.27 + sb.setLength(0);
4.28 + out.flush();
4.29 + }
4.30 +
4.31 + public void write(String str, int off, int len) throws IOException {
4.32 + sb.append(str, len, len);
4.33 + }
4.34 +
4.35 + public void write(char[] arr, int off, int len) throws IOException {
4.36 + sb.append(arr, len, len);
4.37 + }
4.38 +
4.39 +}
5.1 --- a/samples/delegatingwriterfinal/src-api1.0/api/Writer.java Sat Jun 14 09:53:06 2008 +0200
5.2 +++ b/samples/delegatingwriterfinal/src-api1.0/api/Writer.java Sat Jun 14 09:53:07 2008 +0200
5.3 @@ -1,6 +1,5 @@
5.4 package api;
5.5
5.6 -import java.io.BufferedWriter;
5.7 import java.io.IOException;
5.8
5.9 /** Fixing the problem caused by mixing subclassing and delegation in
5.10 @@ -63,24 +62,7 @@
5.11 }
5.12
5.13 public static Writer createBuffered(final Writer out) {
5.14 - class Delegate extends java.io.Writer {
5.15 - @Override
5.16 - public void write(char[] cbuf, int off, int len) throws IOException {
5.17 - out.write(cbuf, off, len);
5.18 - }
5.19 -
5.20 - @Override
5.21 - public void flush() throws IOException {
5.22 - out.flush();
5.23 - }
5.24 -
5.25 - @Override
5.26 - public void close() throws IOException {
5.27 - out.close();
5.28 - }
5.29 -
5.30 - }
5.31 - return create(new BufferedWriter(new Delegate()));
5.32 + return create(new SimpleBuffer(out));
5.33 }
5.34
5.35
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/samples/delegatingwriterfinal/src-api2.0/api/SimpleBuffer.java Sat Jun 14 09:53:07 2008 +0200
6.3 @@ -0,0 +1,39 @@
6.4 +package api;
6.5 +
6.6 +import java.io.IOException;
6.7 +
6.8 +/**
6.9 + *
6.10 + * @author Jaroslav Tulach
6.11 + */
6.12 +final class SimpleBuffer implements Writer.ImplSeq {
6.13 + private final Writer out;
6.14 + private final StringBuffer sb = new StringBuffer();
6.15 +
6.16 + public SimpleBuffer(Writer out) {
6.17 + this.out = out;
6.18 + }
6.19 +
6.20 + public void close() throws IOException {
6.21 + flush();
6.22 + out.close();
6.23 + }
6.24 +
6.25 + public void flush() throws IOException {
6.26 + if (sb.length() > 0) {
6.27 + out.write(sb.toString());
6.28 + sb.setLength(0);
6.29 + out.flush();
6.30 + }
6.31 + }
6.32 +
6.33 + public void write(CharSequence seq) throws IOException {
6.34 + if (seq.length() < 1024) {
6.35 + sb.append(seq);
6.36 + } else {
6.37 + flush();
6.38 + out.append(seq);
6.39 + }
6.40 + }
6.41 +
6.42 +}
7.1 --- a/samples/delegatingwriterfinal/src-api2.0/api/Writer.java Sat Jun 14 09:53:06 2008 +0200
7.2 +++ b/samples/delegatingwriterfinal/src-api2.0/api/Writer.java Sat Jun 14 09:53:07 2008 +0200
7.3 @@ -8,7 +8,7 @@
7.4 *
7.5 * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
7.6 */
7.7 -public final class Writer {
7.8 +public final class Writer implements Appendable {
7.9 private final Impl impl;
7.10 private final ImplSeq seq;
7.11
7.12 @@ -69,6 +69,27 @@
7.13 }
7.14 }
7.15
7.16 +
7.17 +
7.18 + public final Writer append(CharSequence csq) throws IOException {
7.19 + if (impl != null) {
7.20 + String s = csq == null ? "null" : csq.toString();
7.21 + impl.write(s, 0, s.length());
7.22 + } else {
7.23 + seq.write(csq);
7.24 + }
7.25 + return this;
7.26 + }
7.27 +
7.28 + public final Writer append(CharSequence csq, int start, int end) throws IOException {
7.29 + return append(csq.subSequence(start, end));
7.30 + }
7.31 +
7.32 + public final Writer append(char c) throws IOException {
7.33 + write(c);
7.34 + return this;
7.35 + }
7.36 +
7.37 public static Writer create(Impl impl) {
7.38 return new Writer(impl, null);
7.39 }
7.40 @@ -78,13 +99,9 @@
7.41 }
7.42
7.43 public static Writer create(final java.io.Writer w) {
7.44 - return new Writer(new Impl() {
7.45 - public void write(String str, int off, int len) throws IOException {
7.46 - w.write(str, off, len);
7.47 - }
7.48 -
7.49 - public void write(char[] arr, int off, int len) throws IOException {
7.50 - w.write(arr, off, len);
7.51 + return new Writer(null, new ImplSeq() {
7.52 + public void write(CharSequence seq) throws IOException {
7.53 + w.append(seq);
7.54 }
7.55
7.56 public void close() throws IOException {
7.57 @@ -94,28 +111,11 @@
7.58 public void flush() throws IOException {
7.59 w.flush();
7.60 }
7.61 - }, null);
7.62 + });
7.63 }
7.64
7.65 public static Writer createBuffered(final Writer out) {
7.66 - class Delegate extends java.io.Writer {
7.67 - @Override
7.68 - public void write(char[] cbuf, int off, int len) throws IOException {
7.69 - out.write(cbuf, off, len);
7.70 - }
7.71 -
7.72 - @Override
7.73 - public void flush() throws IOException {
7.74 - out.flush();
7.75 - }
7.76 -
7.77 - @Override
7.78 - public void close() throws IOException {
7.79 - out.close();
7.80 - }
7.81 -
7.82 - }
7.83 - return create(new BufferedWriter(new Delegate()));
7.84 + return create(new SimpleBuffer(out));
7.85 }
7.86
7.87
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/samples/delegatingwriterfinal/src-test1.0/api/usage/CryptoWriter.java Sat Jun 14 09:53:07 2008 +0200
8.3 @@ -0,0 +1,60 @@
8.4 +
8.5 +package api.usage;
8.6 +
8.7 +import api.Writer;
8.8 +import java.io.IOException;
8.9 +
8.10 +
8.11 +/** Writer alters each char from 'A' to 'Z' range with next one just like
8.12 + * old Romans did.
8.13 + *
8.14 + * @author Jaroslav Tulach
8.15 + */
8.16 +public class CryptoWriter implements Writer.Impl {
8.17 + private Writer out;
8.18 +
8.19 + private CryptoWriter(Writer out) {
8.20 + this.out = out;
8.21 + }
8.22 +
8.23 +
8.24 + public static Writer create(Writer out) {
8.25 + return Writer.create(new CryptoWriter(out));
8.26 + }
8.27 +
8.28 + @Override
8.29 + public void write(char[] cbuf, int off, int len) throws IOException {
8.30 + char[] arr = new char[len];
8.31 + for (int i = 0; i < len; i++) {
8.32 + arr[i] = convertChar(cbuf[off + i]);
8.33 + }
8.34 + out.write(arr, 0, len);
8.35 + }
8.36 +
8.37 + @Override
8.38 + public void write(String str, int off, int len) throws IOException {
8.39 + StringBuffer sb = new StringBuffer();
8.40 + for (int i = 0; i < len; i++) {
8.41 + sb.append(convertChar(str.charAt(off + i)));
8.42 + }
8.43 + out.write(sb.toString(), 0, len);
8.44 + }
8.45 +
8.46 + private char convertChar(int c) {
8.47 + if (c == 'Z') {
8.48 + return 'A';
8.49 + }
8.50 + if (c == 'z') {
8.51 + return 'a';
8.52 + }
8.53 + return (char)(c + 1);
8.54 + }
8.55 +
8.56 + public void close() throws IOException {
8.57 + out.close();
8.58 + }
8.59 +
8.60 + public void flush() throws IOException {
8.61 + out.flush();
8.62 + }
8.63 +}