|
Red Squirrel Reflections
Dave Hoover explores the psychology of software development
|
|
Mon, 07 Feb 2005Quotes Manager Project -- Day 13 An ongoing pet project blog...As I explore my solution, I see that subsequent calls to add a new quote actually append the entire document to the previous document. That's obviously not what I want.
Ah, solved the problem I found yesterday.
The
Now for the second problem...
Before the XML output is generated from the I'm feeling stuck, so I'll write a failing test...
public void testShouldWriteDocumentToFileWhenUpdatedMultipleTimes() throws Exception {
Document document = parseStub();
ByteArrayOutputStream output = new ByteArrayOutputStream();
QuoteListener listener = new XmlQuoteListener(document, output);
assertEquals("", output.toString());
listener.update();
listener.update();
String expectedOutput = documentToText(document);
assertEquals(expectedOutput, output.toString());
}
OK, this test fails and identifies the problem.
If I can get it to pass, I'll be in good shape.
Maybe I'll have more clarity on the way home...we're pulling into Chicago...
How about a factory to provide
public void testShouldWriteDocumentToFileWhenUpdatedMultipleTimes() throws Exception {
Document document = parseStub();
ByteArrayOutputStream output = new ByteArrayOutputStream();
Mock factory = mock(OutputFactory.class);
OutputStream ignored = new ByteArrayOutputStream();
factory.expects(atLeastOnce()).method("newOutput")
.will(onConsecutiveCalls(returnValue(ignored), returnValue(output)));
QuoteListener listener = new XmlQuoteListener(document, (OutputFactory) factory.proxy());
assertEquals("", output.toString());
listener.update();
listener.update();
String expectedOutput = documentToText(document);
assertEquals(expectedOutput, output.toString());
}
This won't compile and I'll take a couple biggish steps to make it pass...
public class XmlQuoteListener implements QuoteListener {
private final Document document;
private final OutputFactory factory;
public XmlQuoteListener(Document document, OutputFactory factory) {
this.document = document;
this.factory = factory;
}
public void update() {
try {
Transformer transformer = TransformerFactory.newInstance().newTransformer();
Source source = new DOMSource(document);
Result result = new StreamResult(factory.newOutput());
transformer.transform(source, result);
} catch (Exception e) {
e.printStackTrace();
}
}
}
OK, I've pushed the responsibility down.
I have yet another anonoymous class (this time an OutputFactory) in my
main method...
public static void main(String[] args) throws Exception {
JFrame frame = new JFrame(TITLE);
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
final String xmlFile = "play.xml";
Document document = builder.parse(xmlFile);
QuoteListener listener = new XmlQuoteListener(document, new OutputFactory() {
public OutputStream newOutput() throws IOException {
return new FileOutputStream(xmlFile);
}
});
QuoteManager manager = new XmlQuoteManager(document);
manager.addListener(listener);
QuoteManagerPanel quoterManager = new QuoteManagerPanel(manager);
frame.getContentPane().add(quoterManager);
frame.pack();
frame.setVisible(true);
}
I'll run the app and to see if that fixes my problem.
I have an uneasy feeling about creating a new OutputStream every time...
But hey, it worked like a charm!
Time for a check in.
So let's look back at the initial goals and see where we are...
If anyone is interested, I'll post the final source code when I'm finished. |