# HG changeset patch # User Jaroslav Tulach # Date 1213429983 -7200 # Node ID 59df94cee2460a2a0fd303bbd4f9a7523d6bdded # Parent bea28c7c66530b9fffd7cc62e0a7cb77b8110f1b Demo for writer throwing an exception; and also writing out CD content diff -r bea28c7c6653 -r 59df94cee246 samples/delegatingwriter/src/org/apidesign/delegatingwriter/AltBufferedWriter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/delegatingwriter/src/org/apidesign/delegatingwriter/AltBufferedWriter.java Sat Jun 14 09:53:03 2008 +0200 @@ -0,0 +1,75 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package org.apidesign.delegatingwriter; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.Writer; + +/** + * This is a regular {@link BufferedWriter}, just its implementation + * of the append method can choose from three options. This allows us to + * simulate the potential pros and cons of various possible implementations. + * + * @author Jaroslav Tulach + */ +public class AltBufferedWriter extends BufferedWriter { + private final Writer out; + private final Behaviour behaviour; + + public AltBufferedWriter(Writer out, Behaviour behaviour) { + super(out); + this.out = out; + this.behaviour = behaviour; + } + + @Override + public Writer append(CharSequence csq) throws IOException { + switch (behaviour) { + case THROW_EXCEPTION: return appendThrowException(csq); + case DELEGATE_TO_SUPER: return appendDelegateToSuper(csq); + case DELEGATE_TO_OUT: return appendDelegateToUnderlaying(csq); + case DELEGATE_CONDITIONALLY: return appendDelegateConditionally(csq); + default: throw new IllegalStateException("Unknown" + behaviour); + } + } + + // BEGIN: writer.throw + public Writer appendThrowException(CharSequence csq) throws IOException { + throw new UnsupportedOperationException(); + } + // END: writer.throw + + public Writer appendDelegateToSuper(CharSequence csq) throws IOException { + // non-efficient variant of delegating via converting to String first + // and using one of methods that existed in 1.4 + // BEGIN: writer.throw.client + if (csq == null) { + write("null"); + } else { + write(csq.toString()); + } + return this; + // END: writer.throw.client + } + + public Writer appendDelegateToUnderlaying(CharSequence csq) throws IOException { + // BEGIN: writer.delegateout + // efficient, yet dangerous delegation skipping methods known to + // subclasses that used version 1.4 + out.append(csq); + return this; + // END: writer.delegateout + } + + private Writer appendDelegateConditionally(CharSequence csq) { + throw new UnsupportedOperationException("Not yet implemented"); + } + + public enum Behaviour { + THROW_EXCEPTION, DELEGATE_TO_SUPER, DELEGATE_TO_OUT, DELEGATE_CONDITIONALLY + } +} diff -r bea28c7c6653 -r 59df94cee246 samples/delegatingwriter/test/org/apidesign/delegatingwriter/BufferedWriterOnCDImageTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/delegatingwriter/test/org/apidesign/delegatingwriter/BufferedWriterOnCDImageTest.java Sat Jun 14 09:53:03 2008 +0200 @@ -0,0 +1,84 @@ + +package org.apidesign.delegatingwriter; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.StringWriter; +import org.junit.Before; +import org.junit.Test; +import static org.junit.Assert.*; + +/** Emulates what goes wrong when one wants to process really large character + * sequence. + * + * @author Jaroslav Tulach + */ +public class BufferedWriterOnCDImageTest { + + public BufferedWriterOnCDImageTest() { + } + + @Test + public void testBehaviourOfRealBufferInJDKObviouslyThisIsGoingToThrowOutOfMemoryException() throws IOException { + // BEGIN: writer.countcd + CountingWriter writer = new CountingWriter(); + CDSequence cdImage = new CDSequence(); + BufferedWriter bufferedWriter = new BufferedWriter(writer); + bufferedWriter.append(cdImage); + assertEquals("Correct number of writes delegated", cdImage.length(), writer.getCharacterCount()); + // END: writer.countcd + } + + @Test + public void testBehaviourOfBufferThatDelegatesToAppend() throws IOException { + CountingWriter writer = new CountingWriter(); + CDSequence cdImage = new CDSequence(); + BufferedWriter bufferedWriter = new AltBufferedWriter(writer, AltBufferedWriter.Behaviour.DELEGATE_TO_OUT); + bufferedWriter.append(cdImage); + assertEquals("Correct number of writes delegated", cdImage.length(), writer.getCharacterCount()); + } + +// BEGIN: writer.bigseq + /** A "lazy" sequence of characters, for example one that can represent + * content of a CD, read it lazily, do not fit all into memory at once. + */ + private static final class CDSequence implements CharSequence { + private final int start; + private final int end; + + public CDSequence() { + this(0, 647 * 1024 * 1024); + } + + private CDSequence(int start, int end) { + this.start = start; + this.end = end; + } + + + public int length() { + return end - start; + } +// END: writer.bigseq + + public char charAt(int index) { + int ch = index % ('Z' - 'A' + 1); + return (char) ('A' + ch); + } + + public CharSequence subSequence(int start, int end) { + return new CDSequence(start, end); + } + + @Override + public String toString() { + char[] arr = new char[length()]; + for (int i = 0; i < length(); i++) { + arr[i] = charAt(i); + } + return new String(arr); + } + + + } // end of CharSequence +} \ No newline at end of file diff -r bea28c7c6653 -r 59df94cee246 samples/delegatingwriter/test/org/apidesign/delegatingwriter/BufferedWriterThrowingExceptionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/delegatingwriter/test/org/apidesign/delegatingwriter/BufferedWriterThrowingExceptionTest.java Sat Jun 14 09:53:03 2008 +0200 @@ -0,0 +1,57 @@ + +package org.apidesign.delegatingwriter; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * + * @author Jaroslav Tulach + */ +public class BufferedWriterThrowingExceptionTest { + private StringWriter writer; + + public BufferedWriterThrowingExceptionTest() { + } + + @Before + public void setUp() { + writer = new StringWriter(); + } + + @Test + public void testBehaviourOfRealBufferInJDK() throws IOException { + BufferedWriter bufferedWriter = new BufferedWriter(writer); + doAppendHello(bufferedWriter, "Hello!"); + bufferedWriter.flush(); + + assertEquals("Hello!", writer.toString()); + } + + @Test + public void testBehaviourOfBufferThatThrowsExceptionWhenAppendIsCalled() throws IOException { + BufferedWriter bufferedWriter = new AltBufferedWriter(writer, AltBufferedWriter.Behaviour.THROW_EXCEPTION); + doAppendHello(bufferedWriter, "Hello!"); + bufferedWriter.flush(); + + assertEquals("Hello!", writer.toString()); + } + + + private void doAppendHello(BufferedWriter bufferedWriter, CharSequence what) throws IOException { + // BEGIN: writer.throw.client + try { + bufferedWriter.append(what); + } catch (UnsupportedOperationException ex) { + bufferedWriter.write(what.toString()); + } + // END: writer.throw.client + } + +} \ No newline at end of file diff -r bea28c7c6653 -r 59df94cee246 samples/delegatingwriter/test/org/apidesign/delegatingwriter/CountingWriter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/delegatingwriter/test/org/apidesign/delegatingwriter/CountingWriter.java Sat Jun 14 09:53:03 2008 +0200 @@ -0,0 +1,72 @@ + +package org.apidesign.delegatingwriter; + +import java.io.IOException; +import java.io.Writer; + +// BEGIN: writer.CountingWriter +/** Writer that counts the number of written in characters. + * + * @author Jaroslav Tulach + */ +public class CountingWriter extends Writer { + private int counter; + + + public int getCharacterCount() { + return counter; + } + + @Override + public void write(char[] cbuf, int off, int len) throws IOException { + counter += len; + } + + @Override + public Writer append(CharSequence csq) throws IOException { + counter += csq.length(); + return this; + } +// END: writer.CountingWriter + + @Override + public Writer append(CharSequence csq, int start, int end) throws IOException { + counter += (end - start); + return this; + } + + @Override + public Writer append(char c) throws IOException { + counter++; + return this; + } + + @Override + public void write(int c) throws IOException { + counter++; + } + + @Override + public void write(char[] cbuf) throws IOException { + counter += cbuf.length; + } + + @Override + public void write(String str) throws IOException { + counter += str.length(); + } + + @Override + public void write(String str, int off, int len) throws IOException { + counter += len; + } + + @Override + public void flush() throws IOException { + } + + @Override + public void close() throws IOException { + } + +}