001    /**
002     * Copyright 2010-2012 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;
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.lang3.StringUtils;
024    import org.springframework.util.Assert;
025    
026    public class DefaultSqlReader implements SqlReader {
027    
028            public static final String DEFAULT_DELIMITER = "/";
029            public static final DelimiterMode DEFAULT_DELIMITER_MODE = DelimiterMode.OWN_LINE;
030            public static final LineSeparator DEFAULT_LINE_SEPARATOR = LineSeparator.LF;
031            public static final List<String> DEFAULT_COMMENT_TOKENS = Arrays.asList(new String[] { "#", "--" });
032            public static final boolean DEFAULT_IS_TRIM = true;
033            public static final boolean DEFAULT_IS_IGNORE_COMMENTS = true;
034    
035            String delimiter = DEFAULT_DELIMITER;
036            DelimiterMode delimiterMode = DEFAULT_DELIMITER_MODE;
037            LineSeparator lineSeparator = DEFAULT_LINE_SEPARATOR;
038            boolean trim = DEFAULT_IS_TRIM;
039            boolean ignoreComments = DEFAULT_IS_IGNORE_COMMENTS;
040            List<String> commentTokens = DEFAULT_COMMENT_TOKENS;
041    
042            @Override
043            public String getSqlStatement(BufferedReader reader) throws IOException {
044                    Assert.notNull(delimiter, "delimiter is null");
045                    String line = reader.readLine();
046                    String trimmedLine = StringUtils.trimToNull(line);
047                    StringBuilder sb = new StringBuilder();
048                    while (proceed(line, trimmedLine, delimiter, delimiterMode)) {
049                            if (!ignore(ignoreComments, sb, trimmedLine, commentTokens)) {
050                                    sb.append(line + lineSeparator.getValue());
051                            }
052                            line = reader.readLine();
053                            trimmedLine = StringUtils.trimToNull(line);
054                    }
055                    return getReturnValue(sb.toString(), trim, lineSeparator);
056            }
057    
058            protected String getReturnValue(String sql, boolean trim, LineSeparator lineSeparator) {
059                    if (trim) {
060                            sql = StringUtils.trimToNull(sql);
061                    }
062                    if (sql == null) {
063                            return null;
064                    } else if (StringUtils.endsWith(sql, lineSeparator.getValue())) {
065                            int endIndex = sql.length() - lineSeparator.getValue().length();
066                            return StringUtils.substring(sql, 0, endIndex);
067                    } else {
068                            return sql;
069                    }
070            }
071    
072            protected boolean isEndOfSqlStatement(String trimmedLine, String delimiter, DelimiterMode delimiterMode) {
073                    switch (delimiterMode) {
074                    case END_OF_LINE:
075                            return StringUtils.endsWith(trimmedLine, delimiter);
076                    case OWN_LINE:
077                            return StringUtils.equals(trimmedLine, delimiter);
078                    default:
079                            throw new IllegalArgumentException("Delimiter mode '" + delimiterMode + "' is unknown");
080                    }
081            }
082    
083            protected boolean proceed(String line, String trimmedLine, String delimiter, DelimiterMode delimiterMode) {
084                    return line != null && !isEndOfSqlStatement(trimmedLine, delimiter, delimiterMode);
085            }
086    
087            protected boolean ignore(boolean ignoreComments, StringBuilder sql, String trimmedLine, List<String> commentTokens) {
088                    return ignoreComments && StringUtils.isBlank(sql.toString()) && isSqlComment(trimmedLine, commentTokens);
089            }
090    
091            protected boolean isSqlComment(String trimmedLine, List<String> commentTokens) {
092                    for (String commentToken : commentTokens) {
093                            if (StringUtils.startsWith(trimmedLine, commentToken)) {
094                                    return true;
095                            }
096                    }
097                    return false;
098            }
099    
100            public String getDelimiter() {
101                    return delimiter;
102            }
103    
104            public void setDelimiter(String delimiter) {
105                    this.delimiter = delimiter;
106            }
107    
108            public boolean isTrim() {
109                    return trim;
110            }
111    
112            public void setTrim(boolean trim) {
113                    this.trim = trim;
114            }
115    
116            public boolean isIgnoreComments() {
117                    return ignoreComments;
118            }
119    
120            public void setIgnoreComments(boolean ignoreComments) {
121                    this.ignoreComments = ignoreComments;
122            }
123    
124            public LineSeparator getLineSeparator() {
125                    return lineSeparator;
126            }
127    
128            public void setLineSeparator(LineSeparator lineSeparator) {
129                    this.lineSeparator = lineSeparator;
130            }
131    
132            public DelimiterMode getDelimiterMode() {
133                    return delimiterMode;
134            }
135    
136            public void setDelimiterMode(DelimiterMode delimiterMode) {
137                    this.delimiterMode = delimiterMode;
138            }
139    
140            public List<String> getCommentTokens() {
141                    return commentTokens;
142            }
143    
144            public void setCommentTokens(List<String> commentTokens) {
145                    this.commentTokens = commentTokens;
146            }
147    
148    }