/*
* The Kuali Financial System, a comprehensive financial management system for higher education.
*
* Copyright 2005-2014 The Kuali Foundation
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.kuali.kfs.module.bc.batch.dataaccess.impl;
import java.util.ArrayList;
/**
*
* implements a type to hold the raw SQL for each step in a process. allows us to have an insertion point for system parameters which can only be
* incorporated into the SQL at run-time. provides a method to insert the parameter string and return the finished SQL as a string,
* and another to just return SQL as a string without inserting anything, therefore permitting most of the SQL to be built in a constructor and finished at run time.
*/
public class SQLForStep {
// locations in the StringBuilder in which a run-time parameter string is to be incorporated
// (maybe an int[] will be faster when a user is waiting for the SQL to be built
private int[] insertionPoints = {};
// string buffers are thread-safe, while string builders are not
// string builders are more efficient, so use one here and never modify it in our public methods
private StringBuilder sqlBuilder;
public SQLForStep(StringBuilder sqlBuilder)
{
// use this constructor when the SQL needs no insertions
// make a copy of the static SQL, so this type acts as a container for SQL to be passed ot other methods and used repeatedly.
this.sqlBuilder = new StringBuilder(sqlBuilder);
}
public SQLForStep(StringBuilder sqlBuilder, ArrayList<Integer> insertionPoints)
{
// use this constructor when there are run-time strings to be inserted into the SQL
this.sqlBuilder = new StringBuilder(sqlBuilder);
int pointCount = insertionPoints.size();
this.insertionPoints = new int[pointCount];
for (int idx = 0; idx < pointCount; idx++)
{
this.insertionPoints[idx] = (int) insertionPoints.get(idx);
}
}
public String getSQL(ArrayList<String> parameterToInsert)
{
// make a copy of the SQL, so this routine is thread-safe, and evey caller gets her own copy of the static SQL to change.
// string buffers are thread-safe, while string builders are not, but making a copy puts everything on the stack of the local thread anyway,
// so we don't need the string buffer synchronization and can use the more efficient StringBuilder.
if (parameterToInsert.size() != insertionPoints.length) {
// throw an out of bounds exception if there is a mismatch
// we can't build the SQL
throw(new IndexOutOfBoundsException("the number of strings to be inserted into SQL does not match the number of insertion points"));
}
StringBuilder unfinishedSQL = new StringBuilder(sqlBuilder);
// insertions will add to the length of the String
// we need to increase the value of the insertion point based on the leghtns
int lengthSoFar = 0;
for (int idx = 0; idx < insertionPoints.length; idx++)
{
String parameterString = parameterToInsert.get(idx);
unfinishedSQL.insert(insertionPoints[idx]+lengthSoFar,parameterString);
lengthSoFar = lengthSoFar+parameterString.length();
}
return(unfinishedSQL.toString());
}
public String getSQL()
{
// no changes needed to the StringBuilder. just return a string built from the SQL StringBuilder.
return(sqlBuilder.toString());
}
}