csv.impl.XmlReader Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of csv Show documentation
Show all versions of csv Show documentation
A library for easily accessing CSV, Excel and and other table-like data from Java
/*
* This file is part of CSV package.
*
* CSV is free software: you can redistribute it
* and/or modify it under the terms of version 3 of the GNU
* Lesser General Public License as published by the Free Software
* Foundation.
*
* CSV is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with CSV. If not, see
* .
*/
package csv.impl;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.ext.DefaultHandler2;
import csv.CsvException;
/**
* Reads from a XML file.
* @author ralph
*
*/
public class XmlReader extends AbstractStreamTableReader {
protected static final int END_OF_FILE_INDEX = -1;
private ParserThread parserThread = null;
private Object nextRow[] = null;
private String rowTagName = "record";
private String columnTagName = "column";
private boolean useColumnNameTags = false;
private String columnNameAttribute = "name";
private String columnTypeAttribute = "type";
/**
* Constructor.
*/
public XmlReader() {
setHasHeaderRow(true);
}
/**
* Constructor.
* @param in stream to read
*/
public XmlReader(InputStream in) {
super(in);
setHasHeaderRow(true);
}
/**
* Constructor.
* @param file fiel to read
* @throws FileNotFoundException when the file cannot be found
*/
public XmlReader(File file) throws FileNotFoundException {
super(file);
setHasHeaderRow(true);
}
/**
* Constructor.
* @param file file to read
* @throws FileNotFoundException when the file cannot be found
*/
public XmlReader(String file) throws FileNotFoundException {
super(file);
setHasHeaderRow(true);
}
/**
* Closes the stream.
* @see csv.impl.AbstractStreamTableReader#close()
*/
@Override
public void close() {
// deliver remaining comments
if (parserThread != null) {
deliverComments(END_OF_FILE_INDEX);
}
super.close();
}
/**
* Resets the reader.
* @see csv.impl.AbstractStreamTableReader#reset()
*/
@Override
public void reset() {
if (parserThread != null) {
parserThread.stopParsing();
parserThread = null;
}
super.reset();
}
/**
* Returns true if there are more rows.
* @see java.util.Iterator#hasNext()
*/
@Override
public boolean hasNext() {
if (nextRow == null) readNextRow();
return nextRow != null;
}
/**
* Returns the next row.
* @see java.util.Iterator#next()
*/
@Override
public Object[] next() {
if (nextRow == null) readNextRow();
if (nextRow == null) throw new CsvException("End of XML stream reached");
// Before delivering make sure that comments are delivered
deliverComments();
// Deliver current row
Object rc[] = nextRow;
nextRow = null;
incrementRowCount();
return rc;
}
/**
* Reads the next row.
*/
protected void readNextRow() {
if (nextRow != null) return;
// Initialize parser
if (parserThread == null) initParser();
// Read the next row
nextRow = parserThread.next();
}
/**
* Reads the header row.
* @see csv.impl.AbstractTableReader#readHeaderRow()
*/
@Override
protected void readHeaderRow() {
if (parserThread == null) initParser();
if (isHeaderRowRead()) return;
// Parsing thread has information about column names
setHeaderRow(parserThread.getColumnNames());
return;
}
/**
* Initializes the XML parser thread.
*/
protected void initParser() {
if (parserThread == null) {
parserThread = new ParserThread();
parserThread.start();
}
}
/**
* Handles all comments that were registered for current row.
*/
protected void deliverComments() {
deliverComments(getRowCount());
}
/**
* Handles all comments that were registered for current row.
* @param rowIndex the index of the row to be processed
*/
protected void deliverComments(int rowIndex) {
List comments = parserThread.deliverComments(rowIndex);
if (comments != null) {
for (String comment : comments) {
notifyComment(comment, rowIndex, 0);
}
}
}
/**
* Returns the row tag name.
* @return the rowTagName
*/
public String getRowTagName() {
return rowTagName;
}
/**
* Sets the row tag name.
* @param rowTagName the rowTagName to set
*/
public void setRowTagName(String rowTagName) {
this.rowTagName = rowTagName;
}
/**
* Returns the column tag name.
* @return the columnTagName
*/
public String getColumnTagName() {
return columnTagName;
}
/**
* Sets the column tag name.
* @param columnTagName the columnTagName to set
*/
public void setColumnTagName(String columnTagName) {
this.columnTagName = columnTagName;
}
/**
* Returns whether column names will be used as column tag names.
* @return the useColumnNameTags
*/
public boolean isUseColumnNameTags() {
return useColumnNameTags;
}
/**
* Sets whether column names will be used as column tag names.
* @param useColumnNameTags the useColumnNameTags to set
*/
public void setUseColumnNameTags(boolean useColumnNameTags) {
this.useColumnNameTags = useColumnNameTags;
}
/**
* Returns the attribute name of column tag that will contain the attribute name.
* This information is required only when {@link #isUseColumnNameTags()} returns false.
* @return the columnNameAttribute
*/
public String getColumnNameAttribute() {
return columnNameAttribute;
}
/**
* Sets the attribute name of column tag that will contain the attribute name.
* This information is required only when {@link #isUseColumnNameTags()} returns false.
* @param columnNameAttribute the columnNameAttribute to set
*/
public void setColumnNameAttribute(String columnNameAttribute) {
this.columnNameAttribute = columnNameAttribute;
}
/**
* Returns the attribute name of column tag that contains the type of value.
* The type is the value class and usually being used for type conversion.
* @return the columnTypeAttribute
*/
public String getColumnTypeAttribute() {
return columnTypeAttribute;
}
/**
* Sets the attribute name of column tag that contains the type of value.
* The type is the value class and usually being used for type conversion.
* @param columnTypeAttribute the columnTypeAttribute to set
*/
public void setColumnTypeAttribute(String columnTypeAttribute) {
this.columnTypeAttribute = columnTypeAttribute;
}
/**
* The thread doing the XML parse (pushes the handler).
* We use reader/writer synchronization pattern to enable pull pattern
* for main class.
* @author ralph
*
*/
private class ParserThread extends Thread {
private SAXParser parser = null;
private CsvException parsingError = null;
private List