/* * This software is distributed under the terms of the FSF * Gnu Lesser General Public License (see lgpl.txt). * * This program is distributed WITHOUT ANY WARRANTY. See the * GNU General Public License for more details. */ package com.scooterframework.orm.sqldataexpress.parser; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.StringTokenizer; import com.scooterframework.common.logging.LogUtil; import com.scooterframework.common.util.StringUtil; import com.scooterframework.orm.sqldataexpress.object.Parameter; import com.scooterframework.orm.sqldataexpress.util.SqlUtil; /** * JdbcStatementHelper class has helper methods that are used by parser classes. * * @author (Fei) John Chen */ public class JdbcStatementHelper { // reset all the alias to original table name protected String resetAlias(String message) { // return if there is no alias if ( message.indexOf('.') == -1 ) return message; //message = message.toUpperCase(); message = resetSpace(message) + " "; List<String> aliasList = new ArrayList<String>(); Map<String, String> aliasMap = new HashMap<String, String>(); List<String> asList = new ArrayList<String>(); /* * Note: I cannot add '()' to the tokenizer list, because inner view may * cause some problems. But I need to allow space around '()'. */ message = StringUtil.replace(message, "(", " ( "); message = StringUtil.replace(message, ")", " ) "); message = StringUtil.replace(message, ",", " , "); StringTokenizer sti = new StringTokenizer(message, " |><={}+-*/"); int totalTokens = sti.countTokens(); String[] tokens = new String[totalTokens]; int i = 0; while(sti.hasMoreTokens()) { tokens[i] = sti.nextToken(); if (!tokens[i].startsWith("?")) { int dotIndex = tokens[i].indexOf('.'); if (dotIndex != -1) { // get the alias before dot String alias = tokens[i].substring(0, dotIndex); if ( !aliasList.contains(alias) ) aliasList.add(alias); } } i = i + 1; } //log.debug("aliasList: " + aliasList); // find the alias ref for ( int j = 1; j < totalTokens; j++ ) { String token = tokens[j]; if ( aliasList.contains(token) && !aliasMap.containsKey(token)) { if ( !",".equals(tokens[j-1]) && !"UPDATE".equalsIgnoreCase(tokens[j-1]) && !"FROM".equalsIgnoreCase(tokens[j-1]) && !"AS".equalsIgnoreCase(tokens[j-1]) && !"JOIN".equalsIgnoreCase(tokens[j-1]) && //e.g. SELECT USERS.* FROM USERS INNER JOIN PROJECTS_USERS ON USERS.ID=PROJECTS_USERS.USER_ID !")".equals(tokens[j-1])) { aliasMap.put(token, tokens[j-1]); } else if ("AS".equalsIgnoreCase(tokens[j-1])) { aliasMap.put(token, tokens[j-2]); asList.add(token); } } } //log.debug("aliasMap: " + aliasMap); //log.debug("asList: " + asList); // replace all occurrences of alias in the message string with its ref for (Map.Entry<String, String> entry : aliasMap.entrySet()) { String alias = entry.getKey(); String aliasRef = entry.getValue(); if (aliasRef == null) continue; message = replaceWords(message, alias+".", aliasRef+"."); message = replaceWords(message, aliasRef + " " + alias, aliasRef); } //log.debug("asList: " + asList); // replace all occurrences of alias in the message string with its ref for (String alias : asList) { message = replaceWords(message, "AS " + alias, ""); } return message; } //allow only one space between words in the message protected String resetSpace(String message) { StringTokenizer sti = new StringTokenizer(message, " "); StringBuilder sb = new StringBuilder(); while(sti.hasMoreTokens()) { sb.append(sti.nextToken()).append(' '); } return sb.toString(); } //replace all occurrences of oldWord with newWord. protected String replaceWords(String message, String oldWord, String newWord) { String validChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_1234567890"; if (message != null && !(oldWord.toUpperCase().endsWith("A") && (message .toUpperCase().indexOf((oldWord.toUpperCase() + "S")) != -1))) { int strSize = message.length(); int checkLength = oldWord.length(); int checkIndex = 0; int k = 0; while(k<strSize) { checkIndex = message.toUpperCase().indexOf(oldWord.toUpperCase(), k); if (checkIndex == -1) break; k = checkIndex + checkLength; if (k >= strSize) break; if (checkIndex == 0) { message = newWord + message.substring(k); } else { char c = message.charAt(checkIndex-1); if (validChars.indexOf(c) == -1) { message = message.substring(0, checkIndex) + newWord + message.substring(k); } } strSize = message.length(); } } return message; } //token must a string that starts with ? protected String getNameFromToken(int positionIndex, String token) { if (token == null || !token.startsWith("?")) return ""; String name = ""; if ("?".equals(token)) { name = String.valueOf(positionIndex); } else if (token.length() > 1) { if (token.indexOf(':') != -1) { name = token.substring(1, token.indexOf(':')); } else { name = token.substring(1); } } return name; } //token must a string that starts with ? protected int getInlineSqlDataTypeFromToken(String token) { int sqlDataType = Parameter.UNKNOWN_SQL_DATA_TYPE; if (token.length() > 1 && token.indexOf(':') != -1) { String typeName = token.substring(token.indexOf(':') + 1); sqlDataType = SqlUtil.getSqlDataTypeFromDataTypeName(typeName); } return sqlDataType; } protected LogUtil log = LogUtil.getLogger(this.getClass().getName()); }