org.jdom2.contrib.input.ResultSetBuilder Maven / Gradle / Ivy
Show all versions of jdom Show documentation
/*--
Copyright (C) 2000-2004 Jason Hunter & Brett McLaughlin.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions, and the disclaimer that follows
these conditions in the documentation and/or other materials
provided with the distribution.
3. The name "JDOM" must not be used to endorse or promote products
derived from this software without prior written permission. For
written permission, please contact .
4. Products derived from this software may not be called "JDOM", nor
may "JDOM" appear in their name, without prior written permission
from the JDOM Project Management .
In addition, we request (but do not require) that you include in the
end-user documentation provided with the redistribution and/or in the
software itself an acknowledgement equivalent to the following:
"This product includes software developed by the
JDOM Project (http://www.jdom.org/)."
Alternatively, the acknowledgment may be graphical using the logos
available at http://www.jdom.org/images/logos.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE JDOM AUTHORS OR THE PROJECT
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
This software consists of voluntary contributions made by many
individuals on behalf of the JDOM Project and was originally
created by Jason Hunter and
Brett McLaughlin . For more information
on the JDOM Project, please see .
*/
package org.jdom2.contrib.input;
import java.sql.*;
import java.text.*;
import java.util.*;
import org.jdom2.*;
/**
* ResultSetBuilder
builds a JDOM tree from a
* java.sql.ResultSet
. Many good ideas were leveraged from
* SQLBuilder written from Jon Baer.
*
* Notes:
* Uses name returned by rsmd.getColumnName(), not getColumnLabel()
* because that is less likely to be a valid XML element title.
* Null values are given empty bodies, but you can mark them as empty with
* an attribute using the setNullAttribute() method. Be aware that databases
* may change the case of column names. setAsXXX() methods are case
* insensitive on input column name. Assign each one a proper output name
* if you're worried. Only build() throws JDOMException. Any exceptions
* encountered in the set methods are thrown during the build().
* The setAsXXX(String columnName, ...) methods do not verify that a column
* with the given name actually exists.
*
* Still needs method-by-method Javadocs.
*
* Issues:
* Do attributes have to be added in a namespace?
*
* @author Jason Hunter
* @author Jon Baer
* @author David Bartle
* @author Robert J. Munro
* @version 0.5
*/
@SuppressWarnings("javadoc")
public class ResultSetBuilder {
/** The ResultSet that becomes a Document
*/
private ResultSet rs;
/** The meta data from the ResultSet */
private ResultSetMetaData rsmd;
/** Allows for throwing an exception whenever needed if caught early on */
private SQLException exception;
/** Map of original column names to display names */
private Map names = new HashMap();
/**
* Maps column data to be located either as an Attribute
of
* the row (if in the Map) or a child Element
of the row
* (if not in the Map)
*/
private Map attribs = new HashMap();
/** The Namespace
to use for each Element
*/
private Namespace ns = Namespace.NO_NAMESPACE;
/** The maximum rows to return from the result set */
int maxRows = Integer.MAX_VALUE; // default to all
/** Name for the root Element
of the Document
*/
private String rootName = "result";
/** Name for the each immediate child Element
of the root */
private String rowName = "entry";
/** Name for attribute to mark that a field was null */
private String nullAttribName = null;
/** Value for attribute to mark that a field was null */
private String nullAttribValue = null;
/**
*
* This sets up a java.sql.ResultSet
to be built
* as a Document
.
*
*
* @param rs java.sql.ResultSet
to build
*/
public ResultSetBuilder(ResultSet rs) {
this.rs = rs;
try {
rsmd = rs.getMetaData();
}
catch (SQLException e) {
// Hold the exception until build() is called
exception = e;
}
}
/**
*
* This sets up a java.sql.ResultSet
to be built
* as a Document
.
*
*
* @param rs java.sql.ResultSet
to build from
* @param rootName String
name for the root
* Element
* of the Document
* @param rowName String
name for the each immediate child
* Element
of the root
*/
public ResultSetBuilder(ResultSet rs, String rootName, String rowName) {
this(rs);
setRootName(rootName);
setRowName(rowName);
}
/**
*
* This sets up a java.sql.ResultSet
to be built
* as a Document
.
*
*
* @param rs java.sql.ResultSet
to build from
* @param rootName String
name for the root
* Element
* of the Document
* @param rowName String
name for the each immediate child
* Element
of the root
* @param ns Namespace
to use for each Element
*/
public ResultSetBuilder(ResultSet rs,
String rootName, String rowName, Namespace ns) {
this(rs, rootName, rowName);
setNamespace(ns);
}
/**
*
* This builds a Document
from the
* java.sql.ResultSet
.
*
*
* @return Document
- resultant Document object.
* @throws JDOMException
when there is a problem
* with the build.
*
*/
public Document build() throws JDOMException {
if (exception != null) {
throw new JDOMException("Database problem", exception);
}
try {
int colCount = rsmd.getColumnCount();
Element root = new Element(rootName, ns);
Document doc = new Document(root);
int rowCount = 0;
// get the column labels for this record set
String[] columnName = new String[colCount];
for (int index = 0; index < colCount; index++) {
columnName[index] = rsmd.getColumnName(index+1);
}
// build the org.jdom2.Document out of the result set
String name;
String value;
Element entry;
Element child;
while (rs.next() && (rowCount++ < maxRows)) {
entry = new Element(rowName, ns);
for (int col = 1; col <= colCount; col++) {
if (names.isEmpty()) {
name = columnName[col-1];
}
else {
name = lookupName(columnName[col-1]);
}
value = getString(rs, col, rsmd.getColumnType(col));
if (!attribs.isEmpty() && isAttribute(columnName[col-1])) {
if (!rs.wasNull()) {
entry.setAttribute(name, value);
}
}
else {
child = new Element(name, ns);
if (!rs.wasNull()) {
child.setText(value);
} else {
if (nullAttribName != null) {
child.setAttribute(nullAttribName, nullAttribValue);
}
}
entry.addContent(child);
}
}
root.addContent(entry);
}
return doc;
}
catch (SQLException e) {
throw new JDOMException("Database problem", e);
}
}
protected String getString(ResultSet prs, int column, int columnType)
throws SQLException {
if (columnType == Types.TIMESTAMP) {
Timestamp timeStamp = prs.getTimestamp(column);
if (timeStamp != null) {
return DateFormat.getDateTimeInstance(DateFormat.FULL,
DateFormat.FULL).format(timeStamp);
}
}
if (columnType == Types.DATE) {
java.sql.Date date = prs.getDate(column);
if (date != null) {
return DateFormat.getDateInstance(DateFormat.FULL).format(date);
}
}
if (columnType == Types.TIME) {
java.sql.Time time = prs.getTime(column);
if (time != null) {
return DateFormat.getTimeInstance(DateFormat.FULL).format(time);
}
}
return prs.getString(column);
}
private String lookupName(String origName) {
String name = names.get(origName.toLowerCase());
if (name != null) {
return name;
}
return origName;
}
private boolean isAttribute(String origName) {
Boolean val = attribs.get(origName.toLowerCase());
if (val == Boolean.TRUE) {
return true;
}
return false;
}
/**
* Set the name to use as the root element in
* the Document
.
*
* @param rootName String
the new name.
*
*/
public void setRootName(String rootName) {
this.rootName = rootName;
}
/**
* Set the name to use as the row element in
* the Document
.
*
* @param rowName String
the new name.
*
*/
public void setRowName(String rowName) {
this.rowName = rowName;
}
/**
*
* Set the Namespace
to use for
* each Element
in the Document
.
*
*
* @param ns String
the namespace to use.
*
*/
public void setNamespace(Namespace ns) {
this.ns = ns;
}
/**
*
* Set the maximum number of rows to add to your
* Document
.
*
*
* @param maxRows int
*
*/
public void setMaxRows(int maxRows) {
this.maxRows = maxRows;
}
/**
*
* Set a column as an Attribute
of a row using the
* original column name. The attribute will appear as the original
* column name.
*
*
* @param columnName String
the original column name
*
*/
public void setAsAttribute(String columnName) {
attribs.put(columnName.toLowerCase(), Boolean.TRUE);
}
/**
*
* Set a column as an Attribute
of a row using the
* column name. The attribute will appear as the new name provided.
*
*
* @param columnName String
original column name
* @param attribName String
new name to use for the attribute
*
*/
public void setAsAttribute(String columnName, String attribName) {
attribs.put(columnName.toLowerCase(), Boolean.TRUE);
names.put(columnName.toLowerCase(), attribName);
}
/**
*
* Set a column as an Attribute
of a row using the
* column number. The attribute will appear as the original column
* name.
*
*
* @param columnNum int
*
*/
public void setAsAttribute(int columnNum) {
try {
String name = rsmd.getColumnName(columnNum).toLowerCase();
attribs.put(name, Boolean.TRUE);
}
catch (SQLException e) {
exception = e;
}
}
/**
*
* Set a column as an Attribute
of a row using the
* column number. The attribute will appear as new name provided.
*
*
* @param columnNum int
* @param attribName String
new name to use for the attribute
*
*/
public void setAsAttribute(int columnNum, String attribName) {
try {
String name = rsmd.getColumnName(columnNum).toLowerCase();
attribs.put(name, Boolean.TRUE);
names.put(name, attribName);
}
catch (SQLException e) {
exception = e;
}
}
/**
*
* Set a column as an Element
of a row using the
* column name. The element name will appear as the new name provided.
*
*
* @param columnName String
original column name
* @param elemName String
new name to use for the element
*
*/
public void setAsElement(String columnName, String elemName) {
String name = columnName.toLowerCase();
attribs.put(name, Boolean.FALSE);
names.put(name, elemName);
}
/**
*
* Set a column as an Element
of a row using the
* column number. The element name will appear as new name provided.
*
*
* @param columnNum int
* @param elemName String
new name to use for the element
*
*/
public void setAsElement(int columnNum, String elemName) {
try {
String name = rsmd.getColumnName(columnNum).toLowerCase();
attribs.put(name, Boolean.FALSE);
names.put(name, elemName);
}
catch (SQLException e) {
exception = e;
}
}
/**
*
* Set a specific attribute to use to mark that a value in the
* database was null, not just an empty string. This is necessary
* because <foo/> semantically represents both null and empty.
* This method lets you have <foo null="true">.
*
*
* @param nullAttribName String
name of attribute to add
* @param nullAttribValue String
value to set it to.
*
*/
public void setNullAttribute(String nullAttribName,
String nullAttribValue) {
this.nullAttribName = nullAttribName;
this.nullAttribValue = nullAttribValue;
}
/*
public void setAsIngore(String columnName) {
}
public void setAsIngore(int columnNum) {
}
*/
}