package org.jboss.cache.loader;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.cache.config.CacheLoaderConfig.IndividualCacheLoaderConfig;

import java.util.Properties;

/**
 * Builds the different SQLs needed by <tt>JDBCCacheLoader</tt>.
 *
 * @author Mircea.Markus@iquestint.com
 * @author <a href="mailto:galder.zamarreno@jboss.com">Galder Zamarreno</a>
 * @version 1.0
 */
public class JDBCCacheLoaderConfig extends AdjListJDBCCacheLoaderConfig
{

   private static final long serialVersionUID = -8371846151643130271L;

   private static final Log log = LogFactory.getLog(JDBCCacheLoaderConfig.class);

   private String deleteNodeSql;
   private String recursiveChildrenSql;
   private String nodeCountSql;
   private String sqlConcat;

   private String startingWith;
   private String appendSepparator;

   public JDBCCacheLoaderConfig(IndividualCacheLoaderConfig base)
   {
      super(base);
      setClassName(JDBCCacheLoader.class.getName());
   }

   public JDBCCacheLoaderConfig()
   {
      setClassName(JDBCCacheLoader.class.getName());
   }

   @Override
   public void setProperties(Properties props)
   {
      super.setProperties(props);
      sqlConcat = props.getProperty("cache.jdbc.sql-concat");

      disectSqlConcat();
      
      deleteNodeSql = constructDeleteNodeSql();
      recursiveChildrenSql = constructRecursiveChildrenSql();
      nodeCountSql = constructNodeCountSql();
   }

   /**
    * Returns the sql string for removing a node and all its children.
    */
   @Override
   public String getDeleteNodeSql()
   {
      if (startingWith == null || appendSepparator == null || deleteNodeSql == null)
      {
         disectSqlConcat();
         setDeleteNodeSql(constructDeleteNodeSql());
      }

      return deleteNodeSql;
   }

   /**
    * Returns an sql that will return a node and all its children.
    */
   public String getRecursiveChildrenSql()
   {
      if (startingWith == null || appendSepparator == null || recursiveChildrenSql == null)
      {
         disectSqlConcat();
         setRecursiveChildrenSql(constructRecursiveChildrenSql());
      }

      return recursiveChildrenSql;
   }

   public void setRecursiveChildrenSql(String recursiveChildrenSql)
   {
      this.recursiveChildrenSql = recursiveChildrenSql;
   }

   /**
    * Returns an sql that will count all the persisted node.
    */
   public String getNodeCountSql()
   {
      if (startingWith == null || appendSepparator == null || nodeCountSql == null)
      {
         disectSqlConcat();
         setNodeCountSql(constructNodeCountSql());
      }

      return nodeCountSql;
   }

   public void setNodeCountSql(String nodeCountSql)
   {
      this.nodeCountSql = nodeCountSql;
   }

   public String getSqlConcat()
   {
      return sqlConcat;
   }

   public void setSqlConcat(String sqlConcat)
   {
      testImmutability("sqlConcat");
      this.sqlConcat = sqlConcat;
   }

   public String getStartingWith()
   {
      return startingWith;
   }

   public void setStartingWith(String startingWith)
   {
      this.startingWith = startingWith;
   }

   public String getAppendSepparator()
   {
      return appendSepparator;
   }

   public void setAppendSepparator(String appendSepparator)
   {
      this.appendSepparator = appendSepparator;
   }

   private void disectSqlConcat()
   {
      if (sqlConcat == null)
      {
         log.info("Missiing JDBCCacheLoader config 'cache.jdbc.sql-concat', using default value:'concat(1,2)'");
         sqlConcat = "concat(1,2)";
      }
      startingWith = sqlConcat.replace('1', '?').replace("2", "'%'"); //concat(?, '%')
      appendSepparator = sqlConcat.replace("1", fqnColumn).replace("2", "'/'"); //concat(fqnColumn, '/')      
   }

   private String constructNodeCountSql()
   {
      return "select count(*) from " + table;
   }

   private String constructRecursiveChildrenSql()
   {
      return "select " + fqnColumn + "," + nodeColumn + " from " + table + " where " + appendSepparator + " like " + startingWith;
   }

   private String constructDeleteNodeSql()
   {
      return "delete from " + table + " where " + appendSepparator + " like " + startingWith;
   }   
}