001: /*
002: *
003: * The DbUnit Database Testing Framework
004: * Copyright (C)2002-2004, DbUnit.org
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or (at your option) any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: */
021: package org.dbunit.dataset.xml;
022:
023: import org.slf4j.Logger;
024: import org.slf4j.LoggerFactory;
025:
026: import org.dbunit.dataset.*;
027: import org.dbunit.dataset.datatype.DataType;
028: import org.dbunit.dataset.stream.DefaultConsumer;
029: import org.dbunit.dataset.stream.IDataSetConsumer;
030: import org.dbunit.dataset.stream.IDataSetProducer;
031: import org.xml.sax.*;
032: import org.xml.sax.helpers.DefaultHandler;
033:
034: import javax.xml.parsers.ParserConfigurationException;
035: import javax.xml.parsers.SAXParserFactory;
036: import java.io.IOException;
037: import java.io.InputStream;
038: import java.util.LinkedList;
039: import java.util.List;
040:
041: /**
042: * @author Manuel Laflamme
043: * @since Apr 30, 2003
044: * @version $Revision: 558 $
045: */
046: public class XmlProducer extends DefaultHandler implements
047: IDataSetProducer, ContentHandler, ErrorHandler {
048:
049: /**
050: * Logger for this class
051: */
052: private static final Logger logger = LoggerFactory
053: .getLogger(XmlProducer.class);
054:
055: private static final IDataSetConsumer EMPTY_CONSUMER = new DefaultConsumer();
056:
057: private static final String DATASET = "dataset";
058: private static final String TABLE = "table";
059: private static final String NAME = "name";
060: private static final String COLUMN = "column";
061: private static final String ROW = "row";
062: private static final String VALUE = "value";
063: private static final String NULL = "null";
064: private static final String NONE = "none";
065:
066: private final InputSource _inputSource;
067: private boolean _validating = false;
068:
069: private IDataSetConsumer _consumer = EMPTY_CONSUMER;
070:
071: private String _activeTableName;
072: private ITableMetaData _activeMetaData;
073:
074: private List _activeColumnNames;
075: private StringBuffer _activeCharacters;
076: private List _activeRowValues;
077:
078: public XmlProducer(InputSource inputSource) {
079: _inputSource = inputSource;
080: }
081:
082: private ITableMetaData createMetaData(String tableName,
083: List _columnNames) {
084: logger.debug("createMetaData(tableName=" + tableName
085: + ", _columnNames=" + _columnNames + ") - start");
086:
087: Column[] columns = new Column[_columnNames.size()];
088: for (int i = 0; i < columns.length; i++) {
089: String columnName = (String) _columnNames.get(i);
090: columns[i] = new Column(columnName, DataType.UNKNOWN);
091: }
092: DefaultTableMetaData metaData = new DefaultTableMetaData(
093: tableName, columns);
094: return metaData;
095: }
096:
097: public void setValidating(boolean validating) {
098: logger.debug("setValidating(validating=" + validating
099: + ") - start");
100:
101: _validating = validating;
102: }
103:
104: ////////////////////////////////////////////////////////////////////////////
105: // IDataSetProducer interface
106:
107: public void setConsumer(IDataSetConsumer consumer)
108: throws DataSetException {
109: logger.debug("setConsumer(consumer) - start");
110:
111: _consumer = consumer;
112: }
113:
114: public void produce() throws DataSetException {
115: logger.debug("produce() - start");
116:
117: try {
118: SAXParserFactory saxParserFactory = SAXParserFactory
119: .newInstance();
120: saxParserFactory.setValidating(_validating);
121: XMLReader xmlReader = saxParserFactory.newSAXParser()
122: .getXMLReader();
123:
124: xmlReader.setContentHandler(this );
125: xmlReader.setEntityResolver(this );
126: xmlReader.setErrorHandler(this );
127: xmlReader.parse(_inputSource);
128: } catch (ParserConfigurationException e) {
129: logger.error("produce()", e);
130:
131: throw new DataSetException(e);
132: } catch (SAXException e) {
133: logger.error("produce()", e);
134:
135: Exception exception = e.getException() == null ? e : e
136: .getException();
137: throw new DataSetException(exception);
138: } catch (IOException e) {
139: logger.error("produce()", e);
140:
141: throw new DataSetException(e);
142: }
143: }
144:
145: ////////////////////////////////////////////////////////////////////////////
146: // EntityResolver interface
147:
148: public InputSource resolveEntity(String publicId, String systemId)
149: throws SAXException {
150: logger.debug("resolveEntity(publicId=" + publicId
151: + ", systemId=" + systemId + ") - start");
152:
153: InputStream in = getClass().getClassLoader()
154: .getResourceAsStream(
155: "org/dbunit/dataset/xml/dataset.dtd");
156: return (new InputSource(in));
157: }
158:
159: ////////////////////////////////////////////////////////////////////////
160: // ContentHandler interface
161:
162: public void startElement(String uri, String localName,
163: String qName, Attributes attributes) throws SAXException {
164: logger.debug("startElement(uri=" + uri + ", localName="
165: + localName + ", qName=" + qName + ", attributes="
166: + attributes + ") - start");
167:
168: try {
169: // dataset
170: if (qName.equals(DATASET)) {
171: _consumer.startDataSet();
172: return;
173: }
174:
175: // table
176: if (qName.equals(TABLE)) {
177: _activeTableName = attributes.getValue(NAME);
178: _activeColumnNames = new LinkedList();
179: return;
180: }
181:
182: // column
183: if (qName.equals(COLUMN)) {
184: _activeCharacters = new StringBuffer();
185: return;
186: }
187:
188: // row
189: if (qName.equals(ROW)) {
190: // End of metadata at first row
191: if (_activeColumnNames != null) {
192: _activeMetaData = createMetaData(_activeTableName,
193: _activeColumnNames);
194: _consumer.startTable(_activeMetaData);
195: _activeColumnNames = null;
196:
197: }
198:
199: _activeRowValues = new LinkedList();
200: return;
201: }
202:
203: // value
204: if (qName.equals(VALUE)) {
205: _activeCharacters = new StringBuffer();
206: return;
207: }
208:
209: // null
210: if (qName.equals(NULL)) {
211: _activeRowValues.add(null);
212: return;
213: }
214:
215: // none
216: if (qName.equals(NONE)) {
217: _activeRowValues.add(ITable.NO_VALUE);
218: return;
219: }
220: } catch (DataSetException e) {
221: logger.error("startElement()", e);
222:
223: throw new SAXException(e);
224: }
225: }
226:
227: public void endElement(String uri, String localName, String qName)
228: throws SAXException {
229: logger.debug("endElement(uri=" + uri + ", localName="
230: + localName + ", qName=" + qName + ") - start");
231:
232: try {
233: // dataset
234: if (qName.equals(DATASET)) {
235: _consumer.endDataSet();
236: return;
237: }
238:
239: // table
240: if (qName.equals(TABLE)) {
241: // End of metadata
242: if (_activeColumnNames != null) {
243: _activeMetaData = createMetaData(_activeTableName,
244: _activeColumnNames);
245: _consumer.startTable(_activeMetaData);
246: _activeColumnNames = null;
247: }
248:
249: _consumer.endTable();
250: _activeTableName = null;
251: _activeMetaData = null;
252: return;
253: }
254:
255: // column
256: if (qName.equals(COLUMN)) {
257: _activeColumnNames.add(_activeCharacters.toString());
258: _activeCharacters = null;
259: return;
260: }
261:
262: // row
263: if (qName.equals(ROW)) {
264: final int length = Math.max(_activeRowValues.size(),
265: _activeMetaData.getColumns().length);
266: Object[] values = new Object[length];
267: for (int i = 0; i < values.length; i++) {
268: values[i] = (i >= _activeRowValues.size()) ? ITable.NO_VALUE
269: : _activeRowValues.get(i);
270: }
271: _consumer.row(values);
272: _activeRowValues = null;
273: return;
274: }
275:
276: // value
277: if (qName.equals(VALUE)) {
278: _activeRowValues.add(_activeCharacters.toString());
279: _activeCharacters = null;
280: return;
281: }
282:
283: // null
284: if (qName.equals(NULL)) {
285: // Nothing to do, already processed in startElement()
286: return;
287: }
288:
289: // none
290: if (qName.equals(NONE)) {
291: // Nothing to do, already processed in startElement()
292: return;
293: }
294: } catch (DataSetException e) {
295: logger.error("endElement()", e);
296:
297: throw new SAXException(e);
298: }
299: }
300:
301: public void characters(char ch[], int start, int length)
302: throws SAXException {
303: logger.debug("characters(ch=" + ch + ", start=" + start
304: + ", length=" + length + ") - start");
305:
306: if (_activeCharacters != null) {
307: _activeCharacters.append(ch, start, length);
308: }
309: }
310:
311: ////////////////////////////////////////////////////////////////////////////
312: // ErrorHandler interface
313:
314: // public void warning(SAXParseException e)
315: // throws SAXException
316: // {
317: // throw e;
318: // }
319:
320: public void error(SAXParseException e) throws SAXException {
321: logger.debug("error(e=" + e + ") - start");
322:
323: throw e;
324: }
325:
326: // public void fatalError(SAXParseException e)
327: // throws SAXException
328: // {
329: // throw e;
330: // }
331:
332: }
|