Main Page | Packages | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages

PatternRewritingRule.java

00001 /**
00002  * C-JDBC: Clustered JDBC.
00003  * Copyright (C) 2002-2004 French National Institute For Research In Computer
00004  * Science And Control (INRIA).
00005  * Contact: c-jdbc@objectweb.org
00006  * 
00007  * This library is free software; you can redistribute it and/or modify it
00008  * under the terms of the GNU Lesser General Public License as published by the
00009  * Free Software Foundation; either version 2.1 of the License, or any later
00010  * version.
00011  * 
00012  * This library is distributed in the hope that it will be useful, but WITHOUT
00013  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
00015  * for more details.
00016  * 
00017  * You should have received a copy of the GNU Lesser General Public License
00018  * along with this library; if not, write to the Free Software Foundation,
00019  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00020  *
00021  * Initial developer(s): Emmanuel Cecchet.
00022  * Contributor(s): ______________________.
00023  */
00024 
00025 package org.objectweb.cjdbc.controller.backend.rewriting;
00026 
00027 import java.util.Hashtable;
00028 import java.util.StringTokenizer;
00029 
00030 /**
00031  * This class defines a PatternRewritingRule
00032  * 
00033  * @author <a href="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
00034  * @version 1.0
00035  */
00036 public class PatternRewritingRule extends AbstractRewritingRule
00037 {
00038   private char     tokenDelimiter = '?';
00039   private String[] patternArray;
00040   private String[] rewriteArray;
00041 
00042   /**
00043    * Creates a new <code>PatternRewritingRule.java</code> object
00044    * 
00045    * @param queryPattern SQL pattern to match
00046    * @param rewrite rewritten SQL query
00047    * @param caseSensitive true if matching is case sensitive
00048    * @param stopOnMatch true if rewriting must stop after this rule if it
00049    *          matches.
00050    */
00051   public PatternRewritingRule(String queryPattern, String rewrite,
00052       boolean caseSensitive, boolean stopOnMatch)
00053   {
00054     super(queryPattern, rewrite, caseSensitive, stopOnMatch);
00055 
00056     // Parse queryPattern and rewrite to extract the parameters ?1 ?2 ...
00057     StringTokenizer patternTokenizer = new StringTokenizer(queryPattern, String
00058         .valueOf(tokenDelimiter), true);
00059     patternArray = new String[patternTokenizer.countTokens()];
00060     int i = 0;
00061     try
00062     {
00063       do
00064       {
00065         patternArray[i] = patternTokenizer.nextToken();
00066         if (patternArray[i].charAt(0) == tokenDelimiter)
00067         { // We found a delimiter (?)
00068           String nextToken = patternTokenizer.nextToken();
00069           // Add the parameter number (only works with 1 digit parameters)
00070           //For example ?124 will be recognized as ?1
00071           patternArray[i] += nextToken.charAt(0);
00072           i++;
00073           if (nextToken.length() > 1)
00074             // This is the next token
00075             patternArray[i] = nextToken.substring(1);
00076         }
00077         i++;
00078       }
00079       while (patternTokenizer.hasMoreTokens());
00080     }
00081     catch (RuntimeException e)
00082     {
00083       throw new RuntimeException("Malformed query pattern: " + queryPattern);
00084     }
00085     StringTokenizer rewriteTokenizer = new StringTokenizer(rewrite, String
00086         .valueOf(tokenDelimiter), true);
00087     rewriteArray = new String[rewriteTokenizer.countTokens()];
00088     i = 0;
00089     try
00090     {
00091       do
00092       {
00093         rewriteArray[i] = rewriteTokenizer.nextToken();
00094         if (rewriteArray[i].charAt(0) == tokenDelimiter)
00095         { // We found a delimiter (?)
00096           String nextToken = rewriteTokenizer.nextToken();
00097           // Add the parameter number (only works with 1 digit parameters)
00098           //For example ?124 will be recognized as ?1
00099           rewriteArray[i] += nextToken.charAt(0);
00100           i++;
00101           if (nextToken.length() > 1)
00102             // This is the next token
00103             rewriteArray[i] = nextToken.substring(1);
00104         }
00105         i++;
00106       }
00107       while (rewriteTokenizer.hasMoreTokens());
00108     }
00109     catch (RuntimeException e1)
00110     {
00111       throw new RuntimeException("Malformed rewrite element: " + rewrite);
00112     }
00113   }
00114 
00115   /**
00116    * @see org.objectweb.cjdbc.controller.backend.rewriting.AbstractRewritingRule#rewrite(java.lang.String)
00117    */
00118   public String rewrite(String sqlQuery)
00119   {
00120     Hashtable tokens = null; // Parameters value in the query
00121     String lastParameter = null;
00122     String currentToken;
00123     int oldIndex = 0;
00124     int newIndex = 0;
00125 
00126     // Check for match and collect parameters into tokens
00127     for (int i = 0; i < patternArray.length; i++)
00128     {
00129       currentToken = patternArray[i];
00130       if (currentToken == null)
00131         break; // Last token was a parameter
00132       if (currentToken.charAt(0) == tokenDelimiter)
00133       { // A new parameter is expected
00134         lastParameter = currentToken;
00135         continue;
00136       }
00137       // Here is the value of the parameter
00138       newIndex = sqlQuery.indexOf(currentToken, oldIndex);
00139       if (newIndex == -1)
00140       { // No match
00141         hasMatched = false;
00142         return sqlQuery;
00143       }
00144 
00145       if (lastParameter != null)
00146       { // Add the parameter value
00147         if (tokens == null)
00148           tokens = new Hashtable();
00149         tokens.put(lastParameter, sqlQuery.substring(oldIndex, newIndex));
00150       }
00151       oldIndex = newIndex + currentToken.length();
00152     }
00153     // Last parameter
00154     if (newIndex < sqlQuery.length())
00155     {
00156       if (tokens != null)
00157       {
00158         if (tokens.containsKey(lastParameter))
00159         { // No match on the end of the pattern
00160           hasMatched = false;
00161           return sqlQuery;
00162         }
00163         else
00164           tokens.put(lastParameter, sqlQuery.substring(oldIndex));
00165       }
00166       // Here, we probably had a match without parameters. What's the point?
00167     }
00168 
00169     hasMatched = true;
00170 
00171     StringBuffer rewrittenQuery = new StringBuffer();
00172     for (int i = 0; i < rewriteArray.length; i++)
00173     {
00174       currentToken = rewriteArray[i];
00175       if (currentToken == null)
00176         break; // Last token was a parameter
00177       if (currentToken.charAt(0) != tokenDelimiter)
00178         rewrittenQuery.append(currentToken);
00179       else
00180         rewrittenQuery.append(tokens.get(currentToken));
00181     }
00182     return rewrittenQuery.toString();
00183   }
00184 }

Generated on Mon Apr 11 22:01:33 2005 for C-JDBC by  doxygen 1.3.9.1