001 /**
002 * Copyright 2010-2013 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.kuali.common.jdbc.suppliers;
017
018 import java.io.BufferedReader;
019 import java.io.IOException;
020 import java.util.Arrays;
021 import java.util.List;
022
023 import org.apache.commons.io.IOUtils;
024 import org.kuali.common.jdbc.reader.SqlReader;
025 import org.kuali.common.jdbc.service.MetaDataUtils;
026 import org.kuali.common.jdbc.sql.model.SqlMetaData;
027 import org.kuali.common.util.Assert;
028 import org.kuali.common.util.CollectionUtils;
029 import org.kuali.common.util.ListUtils;
030 import org.kuali.common.util.LocationUtils;
031
032 /**
033 * Supply SQL from strings that may have more than one SQL statement each
034 */
035 public final class ComplexStringSupplier extends AbstractSupplier {
036
037 private int index = 0;
038 private BufferedReader in;
039
040 private final List<String> strings;
041 private final SqlReader reader;
042 private final SqlMetaData metaData;
043 private boolean open = false;
044 private boolean done = false;
045
046 public ComplexStringSupplier(String sql, SqlReader reader) {
047 this(CollectionUtils.singletonList(sql), reader);
048 }
049
050 public ComplexStringSupplier(List<String> strings, SqlReader reader) {
051 Assert.noNulls(strings, reader);
052 this.strings = ListUtils.newImmutableArrayList(strings);
053 this.reader = reader;
054 this.metaData = MetaDataUtils.getSqlMetaData(this);
055 }
056
057 @Override
058 public synchronized void open() {
059 Assert.isFalse(open, "Already open");
060 this.open = true;
061 this.done = false;
062
063 // Reset index to zero
064 this.index = 0;
065
066 // Open a reader to the first string in the list
067 this.in = getBufferedReader(strings, index);
068 }
069
070 @Override
071 public synchronized List<String> getSql() {
072 Assert.isTrue(open, "Not open");
073 if (done) {
074 return null;
075 }
076 try {
077 // Have the reader produce a SQL statement
078 String sql = reader.getSql(in);
079
080 if (sql != null) {
081 // We got SQL we are done
082 return Arrays.asList(sql);
083 } else {
084 // We've exhausted the current string, move to the next one
085 this.index++;
086 }
087
088 // We've exhausted all of the strings, we are done
089 if (index == strings.size()) {
090 this.done = true;
091 return null;
092 }
093
094 // Open a reader to the new string
095 this.in = getBufferedReader(strings, index);
096
097 // Get SQL from the new string
098 return getSql();
099 } catch (IOException e) {
100 throw new IllegalStateException(e);
101 }
102 }
103
104 @Override
105 public synchronized void close() {
106 Assert.isTrue(open, "Not open");
107 this.open = false;
108
109 // Make sure the BufferedReader is closed
110 IOUtils.closeQuietly(in);
111 }
112
113 /**
114 * Extract a String from the list and open a BufferedReader that can read from it
115 */
116 protected BufferedReader getBufferedReader(List<String> strings, int index) {
117 String string = strings.get(index);
118 return LocationUtils.getBufferedReaderFromString(string);
119 }
120
121 @Override
122 public SqlMetaData getMetaData() {
123 return metaData;
124 }
125
126 public List<String> getStrings() {
127 return strings;
128 }
129
130 public SqlReader getReader() {
131 return reader;
132 }
133
134 }