/*
 * The contents of this file are subject to the Mozilla Public License Version 1.1
 * (the "License"); you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at <http://www.mozilla.org/MPL/>.
 * 
 * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
 * WARRANTY OF ANY KIND, either express or implied. See the License for the specific
 * language governing rights and limitations under the License.
 * 
 * The Original Code is the Venice Web Communities System.
 * 
 * The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
 * for Silverwrist Design Studios.  Portions created by Eric J. Bowersox are
 * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios.  All Rights Reserved.
 * 
 * Contributor(s): 
 */
package com.silverwrist.dynamo.db;

import java.lang.reflect.*;
import java.sql.*;
import com.silverwrist.util.*;
import com.silverwrist.dynamo.iface.DBUtilities;

abstract class DBUtilitiesImpl implements DBUtilities
{
  /*--------------------------------------------------------------------------------
   * Static data members
   *--------------------------------------------------------------------------------
   */

  private static final Class[] ARGS_TYPE = new Class[0];
  private static final Object[] ARGS = new Object[0];

  private static final String SQL_WILDCARD_CHARS = "%_'";

  /*--------------------------------------------------------------------------------
   * Constructor
   *--------------------------------------------------------------------------------
   */

  protected DBUtilitiesImpl()
  { // do nothing
  } // end constructor

  /*--------------------------------------------------------------------------------
   * Implementations from interface DBUtilities
   *--------------------------------------------------------------------------------
   */

  public String encodeString(String data)
  {
    if (data==null)
      return null;  // safety feature
    int ndx = data.indexOf('\'');
    if (ndx<0)
      return data;
    StringBuffer buf = new StringBuffer();
    while (ndx>=0)
    { // convert each single quote mark to a pair of them
      if (ndx>0)
	buf.append(data.substring(0,ndx));
      buf.append("''");
      data = data.substring(ndx+1);
      ndx = data.indexOf('\'');

    } // end while

    buf.append(data);
    return buf.toString();

  } // end encodeString

  public String encodeStringWildcards(String data)
  {
    if (data==null)
      return null;  // safety feature
    AnyCharMatcher nhc = new AnyCharMatcher(SQL_WILDCARD_CHARS);
    int ndx = nhc.get(data);
    if (ndx<0)
      return data;   // trivial short-circuit case
    StringBuffer buf = new StringBuffer();
    while (ndx>=0)
    { // append the matched "head" and then the encoded character
      if (ndx>0)
	buf.append(data.substring(0,ndx));
      switch (data.charAt(ndx++))
      {
	case '%':
	  buf.append("\\%");
	  break;

	case '_':
	  buf.append("\\_");
	  break;

	case '\'':
	  buf.append("\'\'");
	  break;

      } // end switch

      if (ndx==data.length())
	return buf.toString();  // munched the entire string - all done!
      data = data.substring(ndx);
      ndx = nhc.get(data);

    } // end while

    buf.append(data);  // append the unmatched tail
    return buf.toString();

  } // end encodeStringWildcards

  /*--------------------------------------------------------------------------------
   * Abstract declarations from interface DBUtilities
   *--------------------------------------------------------------------------------
   */

  public abstract java.util.Date getDateTime(ResultSet rs, String column) throws SQLException;

  public abstract java.util.Date getDateTime(ResultSet rs, int column) throws SQLException;

  public abstract void setDateTime(PreparedStatement stmt, int index, java.util.Date date) throws SQLException;

  public abstract void testDatabase(Connection conn) throws SQLException;

  /*--------------------------------------------------------------------------------
   * External static operations
   *--------------------------------------------------------------------------------
   */

  public static DBUtilities get(String type) throws Exception
  {
    String impl_class_name = DBUtilitiesImpl.class.getName() + "_" + type.toLowerCase();
    Method m = Class.forName(impl_class_name).getMethod("get",ARGS_TYPE);
    return (DBUtilities)(m.invoke(null,ARGS));
    
  } // end get

} // end class DBUtilitiesImpl
