All Downloads are FREE. Search and download functionalities are using the official Maven repository.

tbrugz.sqldump.datadump.XMLDataDump Maven / Gradle / Ivy

There is a newer version: 0.9.17
Show newest version
package tbrugz.sqldump.datadump;

import java.io.IOException;
import java.io.Writer;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.List;
import java.util.Properties;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import tbrugz.sqldump.util.SQLUtils;
import tbrugz.sqldump.util.Utils;

enum HeaderFooterDump {
	ALWAYS, IFHASDATA, NEVER;
}
//XXX: option to define per-column 'row' xml-element? cursors already have "table-name"...
//XXX: option to dump columns as XML atributes. maybe for columns with name like '@'?
//XXX: 'alwaysDumpHeaderAndFooter': prop for setting for main dumper & inner (ResultSet) dumpers (using prop per table name?)
//XXX: XMLDataDump to extend AbstractXMLDataDump ? so HTMLDataDump and XMLDataDump would have a common ancestor
public class XMLDataDump extends AbstractDumpSyntax {
	
	static final Log log = LogFactory.getLog(XMLDataDump.class);
	
	static final String XML_SYNTAX_ID = "xml";
	static final String DEFAULT_ROW_ELEMENT = "row";
	
	static final String PROP_ROWELEMENT = "sqldump.datadump.xml.rowelement";
	static final String PROP_DUMPROWELEMENT = "sqldump.datadump.xml.dumprowelement";
	static final String PROP_DUMPNULLVALUES = "sqldump.datadump.xml.dumpnullvalues";
	
	static final String PREFIX_ROWELEMENT4TABLE = "sqldump.datadump.xml.rowelement4table@";
	static final String PREFIX_DUMPROWELEMENT4TABLE = "sqldump.datadump.xml.dumprowelement4table@";
	static final String PROP_DUMPHEADER4INNERTABLES = "sqldump.datadump.xml.dumpheader4innertables";
	static final String PROP_DUMPTABLENAMEASROWTAG = "sqldump.datadump.xml.dumptablenameasrowtag";

	static final String PROP_XML_ESCAPE = "sqldump.datadump.xml.escape";
	static final String PREFIX_ESCAPE4TABLE = "sqldump.datadump.xml.escape4table@";
	static final String PREFIX_ESCAPECOLS_4TABLE = "sqldump.datadump.xml.escapecols4table@";
	static final String PREFIX_NO_ESCAPECOLS_4TABLE = "sqldump.datadump.xml.noescapecols4table@";
	
	//static final String PREFIX_ROWELEMENT4COLUMN = "sqldump.datadump.xml.rowelement4column@";
	//static final String PREFIX_DUMPROWELEMENT4COLUMN = "sqldump.datadump.xml.dumprowelement4column@";

	public XMLDataDump() {
		this("", HeaderFooterDump.ALWAYS);
	}

	public XMLDataDump(String padding, HeaderFooterDump dumpHeaderFooter) {
		this.padding = padding;
		this.dumpHeaderFooter = dumpHeaderFooter;
	}
	
	final String padding;
	final HeaderFooterDump dumpHeaderFooter;
	
	//definitions from properties
	protected Properties prop = null;
	String defaultRowElement = DEFAULT_ROW_ELEMENT;
	boolean defaultDumpRowElement = true;
	boolean dumpNullValues = true;
	HeaderFooterDump dumpHeader4InnerTables = HeaderFooterDump.ALWAYS;
	boolean dumpTableNameAsRowTag = false;
	protected boolean escape = false;
	protected boolean escape4table = false;
	List cols2Escape = null;
	List colsNot2Escape = null;

	//dumper properties
	String rowElement = defaultRowElement;
	boolean dumpRowElement = defaultDumpRowElement;
	
	@Override
	public void procProperties(Properties prop) {
		procStandardProperties(prop);
		defaultRowElement = prop.getProperty(PROP_ROWELEMENT, defaultRowElement);
		defaultDumpRowElement = Utils.getPropBool(prop, PROP_DUMPROWELEMENT, defaultDumpRowElement);
		dumpNullValues = Utils.getPropBool(prop, PROP_DUMPNULLVALUES, dumpNullValues);
		try {
			dumpHeader4InnerTables = HeaderFooterDump.valueOf(prop.getProperty(PROP_DUMPHEADER4INNERTABLES, dumpHeader4InnerTables.name()));
		}
		catch(IllegalArgumentException e) {
			log.warn("invalid argument for '"+PROP_DUMPHEADER4INNERTABLES+"': "+e);
		}
		dumpTableNameAsRowTag = Utils.getPropBool(prop, PROP_DUMPTABLENAMEASROWTAG, dumpTableNameAsRowTag);
		escape = Utils.getPropBool(prop, PROP_XML_ESCAPE, escape);
		this.prop = prop;
		postProcProperties();
	}

	@Override
	public void initDump(String schema, String tableName, List pkCols, ResultSetMetaData md) throws SQLException {
		super.initDump(schema, tableName, pkCols, md);
		
		rowElement = prop.getProperty(PREFIX_ROWELEMENT4TABLE+tableName, dumpTableNameAsRowTag?tableName:defaultRowElement);
		dumpRowElement = Utils.getPropBool(prop, PREFIX_DUMPROWELEMENT4TABLE+tableName, defaultDumpRowElement);
		escape4table = Utils.getPropBool(prop, PREFIX_ESCAPE4TABLE+tableName, escape);
		cols2Escape = Utils.getStringListFromProp(prop, PREFIX_ESCAPECOLS_4TABLE+tableName, ",");
		colsNot2Escape = Utils.getStringListFromProp(prop, PREFIX_NO_ESCAPECOLS_4TABLE+tableName, ",");
	}
	
	@Override
	public void dumpHeader(Writer fos) throws IOException {
		//XXX: add xml declaration? optional? e.g.: 
		//see http://www.w3.org/TR/REC-xml/#NT-XMLDecl
		//    http://www.ibm.com/developerworks/xml/library/x-tipdecl/index.html
		if(dumpHeaderFooter.equals(HeaderFooterDump.ALWAYS)) {
			out("<"+tableName+">\n", fos);
		}
	}

	@Override
	public void dumpRow(ResultSet rs, long count, Writer fos) throws IOException, SQLException {
		if(count==0 && dumpHeaderFooter.equals(HeaderFooterDump.IFHASDATA)) {
			out("<"+tableName+">\n", fos);
		}
		if(dumpRowElement) {
			out("\t<"+rowElement+">\n",fos);
		}
		StringBuilder sb = new StringBuilder();
		sb.append("\t\t");
		List vals = SQLUtils.getRowObjectListFromRS(rs, lsColTypes, numCol, true);
		for(int i=0;i"+ nullValueStr +"" );
					}
				}
				else {
					sb.append( "<"+lsColNames.get(i)+">"+ value +"" );
				}
			}
		}
		dumpAndClearBuffer(sb, fos);
		
		if(dumpRowElement) {
			out("\t\n", fos);
		}
	}
	
	public boolean doEscape(final int i) {
		return escape4table?
				(colsNot2Escape==null || !colsNot2Escape.contains(lsColNames.get(i))):
				(cols2Escape!=null && cols2Escape.contains(lsColNames.get(i)));
	}
	
	void dumpAndClearBuffer(StringBuilder sb, Writer fos) throws IOException {
		String sbuff = sb.toString(); sb.setLength(0);
		if("".equals(sbuff.trim())) {
			return;
		}
		out(sbuff+"\n", fos);
	}

	@Override
	public void dumpFooter(long count, Writer fos) throws IOException {
		if(dumpHeaderFooter.equals(HeaderFooterDump.ALWAYS)
				|| (dumpHeaderFooter.equals(HeaderFooterDump.IFHASDATA) && count>0)) {
			out("\n", fos);
		}
	}

	protected void out(String s, Writer pw) throws IOException {
		pw.write(padding+s);
	}
	
	@Override
	public String getSyntaxId() {
		return XML_SYNTAX_ID;
	}

	// http://annevankesteren.nl/2004/08/mime-types
	@Override
	public String getMimeType() {
		return "application/xml";
	}
}