Package org.cruxframework.crux.core.client.db

Source Code of org.cruxframework.crux.core.client.db.WSQLAbstractObjectStore$EncodeCallback

/*
* Copyright 2013 cruxframework.org.
*
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.cruxframework.crux.core.client.db;

import java.util.logging.Level;

import org.cruxframework.crux.core.client.collection.Array;
import org.cruxframework.crux.core.client.collection.CollectionFactory;
import org.cruxframework.crux.core.client.db.Cursor.CursorDirection;
import org.cruxframework.crux.core.client.db.Transaction.Mode;
import org.cruxframework.crux.core.client.db.websql.SQLError;
import org.cruxframework.crux.core.client.db.websql.SQLResultSet;
import org.cruxframework.crux.core.client.db.websql.SQLTransaction;
import org.cruxframework.crux.core.client.db.websql.SQLTransaction.SQLStatementErrorCallback;
import org.cruxframework.crux.core.client.utils.JsUtils;
import org.cruxframework.crux.core.client.utils.StringUtils;

import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArrayMixed;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.logging.client.LogConfiguration;

/**
* @author Thiago da Rosa de Bustamante
*
*/
public abstract class WSQLAbstractObjectStore<K, V> extends AbstractObjectStore<K, V>
{
  protected final String name;
  protected final WSQLTransaction transaction;
  protected final WSQLAbstractDatabase db;
  protected Array<String> indexAndKeyColumnNames;
  protected Array<String> keyPath;
  protected Array<String> indexColumnNames;

  protected WSQLAbstractObjectStore(WSQLAbstractDatabase db, String name, WSQLTransaction transaction)
  {
    super(db);
    this.db = db;
    this.name = name;
    this.transaction = transaction;
    this.keyPath = getKeyPath();
    this.indexColumnNames = getIndexedColumnNames();
    this.indexAndKeyColumnNames = getIndexAndKeyColumnNames();
  }
 
  @Override
  public String getObjectStoreName()
  {
      return name;
  }
 
  @Override
  public void add(final V object, final DatabaseWriteCallback<K> callback)
  {
      transaction.addRequest(new WSQLTransaction.RequestOperation()
      {
        @Override
        public void doOperation(final SQLTransaction tx)
        {
        insertObject(object, tx, callback, getKey(object));
        }
      }, new Mode[]{Mode.readWrite});
  }
 
  @Override
  public void put(final V object, final DatabaseWriteCallback<K> callback)
  {
      transaction.addRequest(new WSQLTransaction.RequestOperation()
      {
        @Override
        public void doOperation(final SQLTransaction tx)
        {
        updateObject(object, tx, callback, getKey(object));
        }
      }, new Mode[]{Mode.readWrite});
  }

  @Override
  public void get(final K key, final DatabaseRetrieveCallback<V> callback)
  {
      transaction.addRequest(new WSQLTransaction.RequestOperation()
    {
      @Override
      public void doOperation(final SQLTransaction tx)
      {
        StringBuilder sql = new StringBuilder("SELECT * FROM \"").append(name).append("\"");
        final JsArrayMixed args = JsArrayMixed.createArray().cast();
        if (key != null)
        {
          sql.append(" WHERE ");
          addKeyToQuery(key, sql, args);
        }
        runSelectSQL(callback, tx, args, sql.toString(), key);
      }
    }, new Mode[]{Mode.readOnly, Mode.readWrite});
    }
 
  @Override
  public void delete(final KeyRange<K> range, final DatabaseDeleteCallback callback)
  {
    if (callback != null)
    {
      callback.setDb(db);
    }
      transaction.addRequest(new WSQLTransaction.RequestOperation()
      {
        @Override
        public void doOperation(final SQLTransaction tx)
        {
          StringBuilder sql = new StringBuilder("DELETE FROM \"").append(name).append("\"");
        JsArrayMixed args = JsArrayMixed.createArray().cast();
        if (range != null)
        {
          addKeyRangeToQuery(range, sql, args);
        }
        String sqlStatement = sql.toString();
        runDeleteSQL(callback, tx, args, sqlStatement);
        }
      }, new Mode[]{Mode.readWrite});
  }
 
  @Override
  public void delete(final K key, final DatabaseDeleteCallback callback)
  {
    if (callback != null)
    {
      callback.setDb(db);
    }
      transaction.addRequest(new WSQLTransaction.RequestOperation()
      {
        @Override
        public void doOperation(final SQLTransaction tx)
        {
          StringBuilder sql = new StringBuilder("DELETE FROM \"").append(name).append("\"");
        JsArrayMixed args = JsArrayMixed.createArray().cast();
        if (key != null)
        {
          sql.append(" WHERE ");
          addKeyToQuery(key, sql, args);
        }
        String sqlStatement = sql.toString();
        runDeleteSQL(callback, tx, args, sqlStatement);
        }
      }, new Mode[]{Mode.readWrite});
  }
 
  @Override
  public void clear(final DatabaseCallback callback)
  {
    if (callback != null)
    {
      callback.setDb(db);
    }
      transaction.addRequest(new WSQLTransaction.RequestOperation()
    {
      @Override
      public void doOperation(final SQLTransaction tx)
      {
        String sql = "DELETE FROM __sys__ WHERE name = ?";
        JsArrayMixed args = JsArrayMixed.createArray().cast();
        args.push(name);
        if (LogConfiguration.loggingIsEnabled())
        {
          logger.log(Level.FINE, "Running SQL ["+sql+"]");
        }
        tx.executeSQL(sql, args, null, getErrorHandler(callback));
      }
    }, new Mode[]{Mode.readWrite});
      transaction.addRequest(new WSQLTransaction.RequestOperation()
    {
      @Override
      public void doOperation(final SQLTransaction tx)
      {
        String sql = "DELETE FROM \"" + name + "\"";
        JsArrayMixed args = JsArrayMixed.createArray().cast();
        runDatabaseSQL(callback, tx, args, sql);
      }
    }, new Mode[]{Mode.readWrite});
  }
 
  public void createTable(SQLTransaction tx, final DatabaseCallback callback)
  {
    if (callback != null)
    {
      callback.setDb(db);
    }
    String sql = "INSERT INTO __sys__(name) VALUES (?)";
    JsArrayMixed args = JsArrayMixed.createArray().cast();
    args.push(name);
    if (LogConfiguration.loggingIsEnabled())
    {
      logger.log(Level.FINE, "Running SQL ["+sql+"]");
    }
    tx.executeSQL(sql, args, new SQLTransaction.SQLStatementCallback()
    {
      @Override
      public void onSuccess(SQLTransaction tx, SQLResultSet rs)
      {
        String sql = getCreateTableSQL();
        JsArrayMixed args = JsArrayMixed.createArray().cast();
        runDatabaseSQL(callback, tx, args, sql);
      }
    }, getErrorHandler(callback));
  }
 
  @Override
  public void count(final DatabaseCountCallback callback)
  {
    count(null, callback);
  }

  @Override
  public void count(final KeyRange<K> range, final DatabaseCountCallback callback)
  {
    if (callback != null)
    {
      callback.setDb(db);
    }
      transaction.addRequest(new WSQLTransaction.RequestOperation()
    {
      @Override
      public void doOperation(final SQLTransaction tx)
      {
        StringBuilder sql = new StringBuilder("SELECT COUNT(*) AS total FROM \"").append(name).append("\"");
        JsArrayMixed args = JsArrayMixed.createArray().cast();
        if (range != null)
        {
          addKeyRangeToQuery(range, sql, args);
        }
        String sqlStatement = sql.toString();
        if (LogConfiguration.loggingIsEnabled())
        {
          logger.log(Level.FINE, "Running SQL ["+sqlStatement+"]");
        }
        tx.executeSQL(sqlStatement, args, new SQLTransaction.SQLStatementCallback()
        {
          @Override
          public void onSuccess(SQLTransaction tx, SQLResultSet rs)
          {
            if (callback != null)
            {
              try
              {
                int count;
                if (rs.getRows().length() > 0)
                {
                  count = JsUtils.readIntPropertyValue(rs.getRows().itemObject(0), "total");
                }
                else
                {
                  String message = db.messages.objectStoreCountError("No rows returned");
                  if (LogConfiguration.loggingIsEnabled())
                  {
                    logger.log(Level.SEVERE, message);
                  }
                  callback.onError(message);
                  callback.setDb(null);
                  return;
                }
                if (LogConfiguration.loggingIsEnabled())
                {
                  logger.log(Level.FINE, "There are ["+count+"] records on object store ["+name+"].");
                }
                callback.onSuccess(count);
                callback.setDb(null);
              }
              catch (Exception e)
              {
                if (LogConfiguration.loggingIsEnabled())
                {
                  logger.log(Level.SEVERE, db.messages.objectStoreOperationError(e.getMessage()), e);
                }
              }
            }
          }
        }, getErrorHandler(callback));
      }
    }, new Mode[]{Mode.readOnly, Mode.readWrite});
    }

  @Override
  public void openCursor(DatabaseCursorCallback<K, V> callback)
  {
    openCursor(null, CursorDirection.next, callback);
  }
 
  @Override
  public void openCursor(KeyRange<K> keyRange, DatabaseCursorCallback<K, V> callback)
  {
    openCursor(keyRange, CursorDirection.next, callback);
  }
 
  protected void insertObject(final V object, final SQLTransaction tx, final DatabaseWriteCallback<K> callback, final K key)
    {
    encodeObject(object, new EncodeCallback()
    {
      @Override
      public void onEncode(JSONObject encoded)
      {
          insertObject(tx, callback, key, encoded);
      }
    });
    }

  protected void insertObject(final SQLTransaction tx, final DatabaseWriteCallback<K> callback, final K key, JSONObject encoded)
  {
    StringBuilder sqlStart = new StringBuilder("INSERT INTO ").append("\""+ name +"\" (");
    StringBuilder sqlEnd = new StringBuilder(" VALUES(");
    JavaScriptObject encodedObject = encoded.getJavaScriptObject();
   
      JsArrayMixed sqlValues = JsArrayMixed.createArray().cast();
     
      if (!isAutoIncrement() || key != null)
      {
        getIndexesValuesForObject(encodedObject, indexAndKeyColumnNames, sqlValues);
       
        for (int i=0; i< indexAndKeyColumnNames.size(); i++)
        {
          String k = indexAndKeyColumnNames.get(i);
          sqlStart.append("\""+k +"\",");
          sqlEnd.append("?,");
        }
      }
      else
      {
        getIndexesValuesForObject(encodedObject, indexColumnNames, sqlValues);
       
        for (int i=0; i< indexColumnNames.size(); i++)
        {
          String k = indexColumnNames.get(i);
          sqlStart.append("\""+k +"\",");
          sqlEnd.append("?,");
        }
      }
   
    sqlStart.append("value)");
    sqlEnd.append("?)");
    sqlValues.push(encoded.toString());
    String sqlStatement = sqlStart.toString()+" "+sqlEnd.toString() ;
    runInsertQL(callback, tx, sqlValues, sqlStatement, key);
  }

  protected void updateObject(final V object, final SQLTransaction tx, final DatabaseWriteCallback<K> callback, final K key)
    {
    encodeObject(object, new EncodeCallback()
    {
      @Override
      public void onEncode(JSONObject encoded)
      {
          StringBuilder sql = new StringBuilder("UPDATE ").append("\""+ name +"\" SET ");
         
          JsArrayMixed sqlValues = JsArrayMixed.createArray().cast();
          getIndexesValuesForObject(encoded.getJavaScriptObject(), indexColumnNames, sqlValues);
          for (int i=0; i< indexColumnNames.size(); i++)
          {
            String key = indexColumnNames.get(i);
            sql.append("\""+key +"\" = ?, ");
          }
         
        sql.append("value = ?");
        sqlValues.push(encoded.toString());
        sql.append(" WHERE ");
        addKeyToQuery(key, sql, sqlValues);
       
            String sqlStatement = sql.toString();
        runUpdateSQL(callback, tx, sqlValues, sqlStatement, key, encoded);
      }
    });
    }
 
  protected Array<String> getIndexAndKeyColumnNames()
  {
    Array<String> indexAndKeys = CollectionFactory.createArray();
    for (int i=0; i< keyPath.size(); i++)
    {
      String k = keyPath.get(i);
      indexAndKeys.add(k);
    }
    for (int i=0; i< indexColumnNames.size(); i++)
    {
      String k = indexColumnNames.get(i);
      if (indexAndKeys.indexOf(k) == -1)
      {
        indexAndKeys.add(k);
      }
    }
    return indexAndKeys;
  }

  protected void getIndexesValuesForObject(JavaScriptObject object, Array<String> columnNames, JsArrayMixed output)
  {
    for (int i=0; i<columnNames.size(); i++)
    {
      JsUtils.readPropertyValue(object, columnNames.get(i), output, true);
    }
  }

  protected void runUpdateSQL(final DatabaseWriteCallback<K> callback, final SQLTransaction tx, JsArrayMixed args, String sqlStatement,
                final K key, final JSONObject encodedObject)
    {
    if (LogConfiguration.loggingIsEnabled())
    {
      logger.log(Level.FINE, "Running SQL ["+sqlStatement+"]");
    }
        tx.executeSQL(sqlStatement, args, new SQLTransaction.SQLStatementCallback()
    {
      @Override
      public void onSuccess(SQLTransaction tx, SQLResultSet rs)
      {
        if (rs.getRowsAffected() == 0)
        {
          insertObject(tx, callback, key, encodedObject);
        }
        else
        {
          if (LogConfiguration.loggingIsEnabled())
          {
            logger.log(Level.FINE, "Operation executed on database. Table ["+name+"]");
          }
          if (callback != null)
          {
            try
            {
              callback.onSuccess(key);
              callback.setDb(null);
            }
            catch (Exception e)
            {
              if (LogConfiguration.loggingIsEnabled())
              {
                logger.log(Level.SEVERE, db.messages.objectStoreOperationError(e.getMessage()), e);
              }
            }
          }
        }
      }
    }, getErrorHandler(callback));
    }
 
  protected void runInsertQL(final DatabaseWriteCallback<K> callback, final SQLTransaction tx, JsArrayMixed args, String sqlStatement, final K key)
    {
    if (LogConfiguration.loggingIsEnabled())
    {
      logger.log(Level.FINE, "Running SQL ["+sqlStatement+"]");
    }
        tx.executeSQL(sqlStatement, args, new SQLTransaction.SQLStatementCallback()
    {
      @SuppressWarnings("unchecked")
            @Override
      public void onSuccess(SQLTransaction tx, SQLResultSet rs)
      {
        if (LogConfiguration.loggingIsEnabled())
        {
          logger.log(Level.FINE, "Operation executed on database. Table ["+name+"]");
        }
        if (callback != null)
        {
          try
          {
            if (isAutoIncrement())
            {   // Only integer keys can be auto incremented.
              callback.onSuccess((K) new Integer(rs.getInsertId()));
            }
            else
            {
              callback.onSuccess(key);
            }
            callback.setDb(null);
          }
          catch (Exception e)
          {
            if (LogConfiguration.loggingIsEnabled())
            {
              logger.log(Level.SEVERE, db.messages.objectStoreOperationError(e.getMessage()), e);
            }
          }
        }
      }
    }, getErrorHandler(callback));
    }
 
  protected void runDeleteSQL(final DatabaseDeleteCallback callback, final SQLTransaction tx, JsArrayMixed args, String sqlStatement)
    {
    if (LogConfiguration.loggingIsEnabled())
    {
      logger.log(Level.FINE, "Running SQL ["+sqlStatement+"]");
    }
        tx.executeSQL(sqlStatement, args, new SQLTransaction.SQLStatementCallback()
    {
      @Override
      public void onSuccess(SQLTransaction tx, SQLResultSet rs)
      {
        if (LogConfiguration.loggingIsEnabled())
        {
          logger.log(Level.FINE, "Operation executed on database. Table ["+name+"]");
        }
        if (callback != null)
        {
          try
          {
            callback.onSuccess();
            callback.setDb(null);
          }
          catch (Exception e)
          {
            if (LogConfiguration.loggingIsEnabled())
            {
              logger.log(Level.SEVERE, db.messages.objectStoreOperationError(e.getMessage()), e);
            }
          }
        }
      }
    }, getErrorHandler(callback));
    }

  protected void runSelectSQL(final DatabaseRetrieveCallback<V> callback, final SQLTransaction tx, JsArrayMixed args, String sqlStatement, final K key)
    {
    if (LogConfiguration.loggingIsEnabled())
    {
      logger.log(Level.FINE, "Running SQL ["+sqlStatement+"]");
    }
        tx.executeSQL(sqlStatement, args, new SQLTransaction.SQLStatementCallback()
    {
      @Override
      public void onSuccess(SQLTransaction tx, SQLResultSet rs)
      {
        if (LogConfiguration.loggingIsEnabled())
        {
          logger.log(Level.FINE, "Operation executed on database. Table ["+name+"]");
        }
        if (callback != null)
        {
          try
          {
            if (rs.getRows().length() > 0)
            {
              String encodedObject = JsUtils.readStringPropertyValue(rs.getRows().itemObject(0), "value");
              if (!StringUtils.isEmpty(encodedObject))
              {
                V object = decodeObject(encodedObject);
                if (isAutoIncrement() && key != null)
                {
                  setObjectKey(object, key);
                }
                callback.onSuccess(object);
              }
              else
              {
                callback.onError(db.messages.objectStoreOperationError("Read error"));
                return;
              }
            }
            else
            {
              callback.onSuccess(null);
            }
            callback.setDb(null);
          }
          catch (Exception e)
          {
            if (LogConfiguration.loggingIsEnabled())
            {
              logger.log(Level.SEVERE, db.messages.objectStoreOperationError(e.getMessage()), e);
            }
          }
        }
      }
    }, getErrorHandler(callback));
    }
 
  protected void runDatabaseSQL(final DatabaseCallback callback, final SQLTransaction tx, JsArrayMixed args, String sqlStatement)
    {
    if (LogConfiguration.loggingIsEnabled())
    {
      logger.log(Level.FINE, "Running SQL ["+sqlStatement+"]");
    }
        tx.executeSQL(sqlStatement, args, new SQLTransaction.SQLStatementCallback()
    {
      @Override
      public void onSuccess(SQLTransaction tx, SQLResultSet rs)
      {
        if (LogConfiguration.loggingIsEnabled())
        {
          logger.log(Level.FINE, "Operation executed on database. Table ["+name+"]");
        }
        if (callback != null)
        {
          try
          {
            callback.onSuccess();
            callback.setDb(null);
          }
          catch (Exception e)
          {
            if (LogConfiguration.loggingIsEnabled())
            {
              logger.log(Level.SEVERE, db.messages.objectStoreOperationError(e.getMessage()), e);
            }
          }
        }
      }
    }, getErrorHandler(callback));
    }

  protected SQLStatementErrorCallback getErrorHandler(final Callback callback)
    {
      return new SQLTransaction.SQLStatementErrorCallback()
    {
      @Override
      public boolean onError(SQLTransaction tx, SQLError error)
      {
        String message = db.messages.objectStoreOperationError(error.getName() + " - " + error.getMessage());
        if (LogConfiguration.loggingIsEnabled())
        {
          logger.log(Level.SEVERE, message);
        }
        if (callback != null)
        {
          callback.onError(message);
          callback.setDb(null);
        }
        else if (db.errorHandler != null)
        {
          db.errorHandler.onError(message);
        }
        return true;
      }
    };
   
 
  protected void reportError(String message)
  {
    if (LogConfiguration.loggingIsEnabled())
    {
      logger.log(Level.SEVERE, message);
    }
    if (db.errorHandler != null)
    {
      db.errorHandler.onError(message);
    }
  }
 
  protected abstract Array<String> getIndexedColumnNames();
  protected abstract Array<String> getKeyPath();
  protected abstract void addKeyRangeToQuery(final KeyRange<K> range, StringBuilder sql, JsArrayMixed args);
  protected abstract void addKeyToQuery(final K key, StringBuilder sql, JsArrayMixed args);
  protected abstract K getKey(V object);
  protected abstract void setObjectKey(V object, K key);
  protected abstract V decodeObject(String encodedObject);
  protected abstract void encodeObject(V object, EncodeCallback callback);
  protected abstract String getCreateTableSQL();
   
  public static interface EncodeCallback
  {
    void onEncode(JSONObject encoded);
  }
}
TOP

Related Classes of org.cruxframework.crux.core.client.db.WSQLAbstractObjectStore$EncodeCallback

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.