/** * 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); } }); } }