package org.exolab.castor.xml;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.easymock.EasyMock;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
/**
* This class gets called by a SAX parser and is used for recording invocations
* on an EasyMock object.
* <p>
* Every method that gets called by the parser and is used in UnmarshalHandler
* will be recorded. Method invocations that don't get recorded are for example
* processingInstruction() or skippedEntities().
* </p>
*
* @author <a href="mailto:philipp DOT erlacher AT gmail DOT com">Philipp
* Erlacher</a>
*
*/
public class Sax2MethodRecorder implements ContentHandler {
/**
* Logger from commons-logging.
*/
private static final Log LOG = LogFactory.getLog(Sax2MethodRecorder.class);
private ContentHandler contentMock;
/**
* charactersBuffer is used to save characters events that came in as chunks
*/
StringBuffer charactersBuffer = null;
public Sax2MethodRecorder(ContentHandler contentMock) {
super();
this.contentMock = contentMock;
}
/*
* from here ContentHandler Methods
*/
public void startDocument() {
LOG.debug("< Start Document >");
try {
contentMock.startDocument();
} catch (SAXException e) {
e.printStackTrace();
}
}
public void endDocument() {
LOG.debug("< End Document >");
try {
contentMock.endDocument();
} catch (SAXException e) {
e.printStackTrace();
}
}
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
LOG.debug("< Start Element >");
contentMock.startElement(EasyMock.eq(uri), EasyMock.eq(localName),
EasyMock.eq(qName), (Attributes) EasyMock.anyObject());
return;
}
/**
* receives notification of an endElement. This element will be recorded. If
* there is a characters event pending, then this will be recorded first.
*/
public void endElement(String uri, String localName, String qName)
throws SAXException {
LOG.debug("< End Element >");
if (isCharBufferSendable())
sentCharacters();
contentMock.endElement(EasyMock.eq(uri), EasyMock.eq(localName),
EasyMock.eq(qName));
return;
}
/**
* fills a buffer with the characters in ch
*/
public void characters(char[] ch, int start, int length) {
LOG.debug("< characters >");
if (charactersBuffer != null) {
LOG.debug(" second characters event");
charactersBuffer.append(ch, start, length);
} else {
charactersBuffer = new StringBuffer(length);
charactersBuffer.append(ch, start, length);
}
}
/**
* if charactersBuffer is not null it is sendable
*
* @return true if it is sendable, otherwise false
*/
private boolean isCharBufferSendable() {
return charactersBuffer != null;
}
/**
* sets charactersBuffer back to null and therefore it's no longer sendable
*/
private void resetCharBuffer() {
charactersBuffer = null;
}
/**
* takes charactersBuffer and sends it as a single event to the
* contentHandler. Afterwards it resets charactersBuffer
*/
private void sentCharacters() {
try {
String string = new String(charactersBuffer);
char[] chars;
chars = new char[charactersBuffer.length()];
chars = string.toCharArray();
contentMock.characters(EasyMock.aryEq(chars), EasyMock.eq(0),
EasyMock.eq(charactersBuffer.length()));
resetCharBuffer();
} catch (SAXException e) {
e.printStackTrace();
}
}
public void startPrefixMapping(String prefix, String uri)
throws SAXException {
LOG.debug("< startPrefixMapping >");
contentMock.startPrefixMapping(EasyMock.eq(prefix), EasyMock.eq(uri));
}
public void endPrefixMapping(String prefix) throws SAXException {
LOG.debug("< endPrefixMapping >");
contentMock.endPrefixMapping(EasyMock.eq(prefix));
}
public void ignorableWhitespace(char[] ch, int start, int length)
throws SAXException {
LOG.debug("< ignorableWhitespace >");
StringBuffer buffer = new StringBuffer(length);
buffer.append(ch, start, length);
String string = new String(buffer);
char[] chars;
chars = new char[length];
chars = string.toCharArray();
contentMock.ignorableWhitespace(EasyMock.aryEq(chars), EasyMock.eq(0),
EasyMock.eq(length));
}
/**
* processInstructions won't be recorded unless
* {@link UnmarshalHandler.processingInstruction} does something
*/
public void processingInstruction(String target, String data)
throws SAXException {
return;
}
public void setDocumentLocator(Locator locator) {
LOG.debug("< setDocumentLocator >");
contentMock.setDocumentLocator((Locator) EasyMock.anyObject());
}
/**
* skippedEntities won't be recorded unless
* {@link UnmarshalHandler.skippedEntity} does something
*/
public void skippedEntity(String name) throws SAXException {
return;
}
}