/**
* Licensed to Apereo under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright ownership. Apereo
* licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use
* this file except in compliance with the License. You may obtain a copy of the License at the
* following location:
*
* <p>http://www.apache.org/licenses/LICENSE-2.0
*
* <p>Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apereo.portal.tools.dbloader;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.lang.ArrayUtils;
import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionOperations;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
/**
* Generates and executes SQL INSERT statements as the data XML document is parsed.
*
*/
public class DataXmlHandler extends BaseDbXmlHandler {
private final JdbcOperations jdbcOperations;
private final TransactionOperations transactionOperations;
private final Map<String, Map<String, Integer>> tableColumnInfo;
private final List<String> script = new LinkedList<String>();
public DataXmlHandler(
JdbcOperations jdbcOperations,
TransactionOperations transactionOperations,
Map<String, Map<String, Integer>> tableColumnTypes) {
this.jdbcOperations = jdbcOperations;
this.transactionOperations = transactionOperations;
this.tableColumnInfo = tableColumnTypes;
}
public List<String> getScript() {
return this.script;
}
private String currentTable = null;
private String currentColumn = null;
private String currentValue = null;
private Map<String, String> rowData;
/* (non-Javadoc)
* @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
*/
@Override
public void startElement(String uri, String localName, String name, Attributes attributes)
throws SAXException {
if ("row".equals(name)) {
this.rowData = new LinkedHashMap<String, String>();
}
this.chars = new StringBuilder();
}
/* (non-Javadoc)
* @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
*/
@Override
public void endElement(String uri, String localName, String name) throws SAXException {
if ("name".equals(name)) {
final String itemName = this.chars.toString().trim();
if (this.currentTable == null) {
this.currentTable = itemName;
} else if (this.currentColumn == null) {
this.currentColumn = itemName;
}
} else if ("value".equals(name)) {
this.currentValue = this.chars.toString().trim();
} else if ("column".equals(name)) {
this.rowData.put(this.currentColumn, this.currentValue);
this.currentColumn = null;
this.currentValue = null;
} else if ("row".equals(name)) {
this.doInsert();
this.rowData = null;
} else if ("table".equals(name)) {
this.currentTable = null;
}
this.chars = null;
}
protected final void doInsert() {
if (this.rowData.size() == 0) {
this.logger.warn(
"Found a row with no data for table "
+ this.currentTable
+ ", the row will be ignored");
return;
}
final Map<String, Integer> columnInfo = this.tableColumnInfo.get(this.currentTable);
final StringBuilder columns = new StringBuilder();
final StringBuilder parameters = new StringBuilder();
final Object[] values = new Object[this.rowData.size()];
final int[] types = new int[this.rowData.size()];
int index = 0;
for (final Iterator<Entry<String, String>> rowIterator = this.rowData.entrySet().iterator();
rowIterator.hasNext();
) {
final Entry<String, String> row = rowIterator.next();
final String columnName = row.getKey();
columns.append(columnName);
parameters.append("?");
values[index] = row.getValue();
types[index] = columnInfo.get(columnName);
if (rowIterator.hasNext()) {
columns.append(", ");
parameters.append(", ");
}
index++;
}
final String sql =
"INSERT INTO "
+ this.currentTable
+ " ("
+ columns
+ ") VALUES ("
+ parameters
+ ")";
if (this.logger.isInfoEnabled()) {
this.logger.info(
sql
+ "\t"
+ Arrays.asList(values)
+ "\t"
+ Arrays.asList(ArrayUtils.toObject(types)));
}
this.transactionOperations.execute(
new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
jdbcOperations.update(sql, values, types);
}
});
}
}