package org.exolab.castor.xml; import java.util.HashSet; import java.util.LinkedList; import java.util.Queue; import java.util.Set; import junit.framework.Assert; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; /** * This class is used to record the attribute values in every SAX startElement event. The * values are then get compared to the attribute values from the * SAXEventFromStaxProducer. * * <p> * If they are different then there an assertion is going fail * </p> * * @author <a href="mailto:philipp DOT erlacher AT gmail DOT com">Philipp * Erlacher</a> * */ public class AttributeRecorder extends DefaultHandler { /** * Logger from commons-logging. */ private static final Log LOG = LogFactory .getLog(BaseSax2EventFromStaxProducer.class); /** * a fifo to record attributes */ private Queue<Set<AttributeElement>> attributes = null; /** * indicates if we are in recordMode */ private Boolean recordMode; public AttributeRecorder() { super(); recordMode = true; attributes = new LinkedList<Set<AttributeElement>>(); } /** * calls {@link #handleEvent()} */ public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException { handleEvent(atts); } /** * if in recordMode then record current location otherwise compare current * location to expected location */ private void handleEvent(Attributes atts) { if (inRecordMode()) recordAttributes(getAttributeSet(atts)); else compareWithAttributes(getAttributeSet(atts)); } public void setReplayMode() { recordMode = false; } /** * are we in record mode ? * * @return true if we are, false otherwise */ private boolean inRecordMode() { return recordMode; } /** * record a location * * @param locationElement * location to record */ private void recordAttributes(Set<AttributeElement> attributeSet) { attributes.add(attributeSet); } private Set<AttributeElement> getAttributeSet(Attributes atts) { Set<AttributeElement> attSet = new HashSet<AttributeElement>(); for (int index = 0; index < atts.getLength(); index++) { attSet.add(new AttributeElement(atts, index)); } return attSet; } /** * compares the expected location with the current location. If they are not * equal then an Assertion fails * * @param currentLocator * the current location */ private void compareWithAttributes(Set<AttributeElement> attributeSet) { Assert.assertEquals(attributes.poll(), attributeSet); } /** * A Wrapper for a Attribute element. * * @author <a href="mailto:philipp DOT erlacher AT gmail DOT com">Philipp * Erlacher</a> * */ private class AttributeElement { private String localName, uri, type, value; public AttributeElement(Attributes att, int index) { super(); localName = att.getLocalName(index); uri = att.getURI(index); type = att.getType(index); value = att.getValue(index); } public String getLocalName() { return localName; } public String getUri() { return uri; } public String getType() { return type; } public String getValue() { return value; } @Override public boolean equals(Object that) { // check for self-comparison if (this == that) return true; if (!(that instanceof AttributeElement)) return false; AttributeElement attribute = (AttributeElement) that; if (!nonEmpty(localName).equals(nonEmpty(attribute.getLocalName()))) return false; if (!nonEmpty(uri).equals(nonEmpty(attribute.getUri()))) return false; if (!nonEmpty(type).equals(nonEmpty(attribute.getType()))) return false; if (!nonEmpty(value).equals(nonEmpty(attribute.getValue()))) return false; return true; } private String nonEmpty(String string) { return string == null ? "" : string; } }; }