DataAccessObject.java :  » Map » androdb » org » androdb » access » Android Open Source

Android Open Source » Map » androdb 
androdb » org » androdb » access » DataAccessObject.java
package org.androdb.access;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import org.androdb.AndroDBException;
import org.androdb.Const;
import org.androdb.metadata.EntityDescriptor;
import org.androdb.metadata.FieldDescriptor;
import org.androdb.util.StringUtils;

import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

/**
 * provides data access functionality for the given type <code>T</code>
 * 
 * @author martin.s.schumacher
 * @since 08.01.2010 18:48:12
 * 
 * @param <T>
 *          the type to create a DataAccessObject for
 * 
 */
public class DataAccessObject<T> {

  /**
   * 
   */
  private static final String GETTER_PREFIX = "get";
  private EntityDescriptor descriptor;
  private String entityName;
  private SQLiteDatabase db;

  /**
   * @param type
   *          the type to create a DataAccessObejct for
   */
  public DataAccessObject(EntityDescriptor entityDescriptor, SQLiteDatabase db) {
    this.descriptor = entityDescriptor;
    this.entityName = this.descriptor.getTheEntity().getName();
    this.db = db;
  }

  /**
   * copies a given DAO for handling overriding
   * 
   * @param copy
   *          the dao to copy
   */
  protected DataAccessObject(DataAccessObject<T> copy) {
    this.db = copy.db;
    this.descriptor = copy.descriptor;
    this.entityName = this.descriptor.getTheEntity().getName();
  }

  /**
   * saves the given entity. decides with the value of the PrimaryKey, if the
   * entity should be inserted or updated.
   * 
   * @param entity
   *          the entity to save
   */
  public void save(T entity) {
    try {
      // looking if we have to update or to insert
      T old = null;
      FieldDescriptor pk = this.descriptor.getPrimaryKey();
      Class<T> clazz = this.getEntity();
      Method pkGetter = clazz.getMethod(GETTER_PREFIX + StringUtils.firstCharToUpper(pk.getField().getName()));

      Object key = pkGetter.invoke(entity);

      if (key != null) {
        old = this.findByPrimaryKey(key);
      }

      ContentValues values = new ContentValues();
      for (FieldDescriptor field : this.descriptor.getAllFieldDescriptors()) {
        if (field.isPersistent()) {
          String prefix = GETTER_PREFIX;
          if ((field.getField().getType() == Boolean.class) || (field.getField().getType() == boolean.class)) {
            prefix = "is";
          }
          Method m = clazz.getMethod(prefix + StringUtils.firstCharToUpper(field.getField().getName()));
          this.addToContentValues(values, field.getColumn(), m.invoke(entity));
        }
      }

      long l = 0;
      if (old == null) {
        l = this.db.insert(this.descriptor.getTablename(), null, values);
      } else {
        String whereClause = pk.getColumn() + " = ?";
        String[] whereArgs = { key.toString() };
        l = this.db.update(this.descriptor.getTablename(), values, whereClause, whereArgs);
      }
      if (l == 0) {
        throw new AndroDBException("could not insert values for " + this.entityName + ".");
      }
    } catch (SecurityException e) {
      throw new AndroDBException("Could not save " + this.entityName + ".", e);
    } catch (NoSuchMethodException e) {
      throw new AndroDBException("Could not save " + this.entityName + ".", e);
    } catch (IllegalArgumentException e) {
      throw new AndroDBException("Could not save " + this.entityName + ".", e);
    } catch (IllegalAccessException e) {
      throw new AndroDBException("Could not save " + this.entityName + ".", e);
    } catch (InvocationTargetException e) {
      throw new AndroDBException("Could not save " + this.entityName + ".", e);
    }
  }

  public T findByPrimaryKey(Object key) {

    try {
      FieldDescriptor primaryKey = this.descriptor.getPrimaryKey();
      if (primaryKey == null) {
        throw new AndroDBException("the primary key of " + this.entityName + " cannot be null!");
      }
      if (key.getClass() != this.descriptor.getPrimaryKey().getField().getType()) {
        throw new AndroDBException("the configured key for " + this.entityName + " is " + primaryKey.getField().getName() + " which type is "
            + primaryKey.getField().getType().getName() + ". But you passed " + key.getClass().getName() + ".");
      }

      String tablename = this.descriptor.getTablename();
      String[] columns = this.descriptor.getColumns();
      String selection = this.descriptor.getPrimaryKey().getColumn() + " = ?";
      String[] selectionargs = { String.valueOf(key) };
      String orderBy = this.descriptor.getPrimaryKey().getColumn();
      Cursor result = this.db.query(tablename, columns, selection, selectionargs, null, null, orderBy);
      if (result.getCount() > 1) {
        throw new AndroDBException("there can just be one result, while finding by primary key.");
      }
      // nothing found
      if (result.getCount() == 0) {
        return null;
      }
      result.moveToFirst();

      return this.makeInstance(result);

    } catch (SecurityException e) {
      throw new AndroDBException("Could not find " + this.entityName + " by primary key.", e);
    } catch (IllegalArgumentException e) {
      throw new AndroDBException("Could not find " + this.entityName + " by primary key.", e);
    }
  }

  /**
   * finds all Entitys of type <code>T</code>
   * 
   * @return a list with all entities
   */
  public List<T> findAll() {
    return this.find(null, null, null, null, this.descriptor.getPrimaryKey().getColumn());
  }

  public List<T> find(String selection, String[] selectionargs, String groupBy, String having, String orderBy) {
    String tablename = this.descriptor.getTablename();
    String[] columns = this.descriptor.getColumns();
    Cursor result = this.db.query(tablename, columns, selection, selectionargs, null, null, orderBy);
    if (result.getCount() == 0) {
      return new ArrayList<T>();
    }

    return this.makeInstanceOfList(result);
  }

  public List<T> findByExample(T example) {
    try {
      String tablename = this.descriptor.getTablename();
      String[] columns = this.descriptor.getColumns();

      String selection = null;
      ArrayList<String> selectionArgList = new ArrayList<String>();

      Class<T> clazz = this.getEntity();

      for (FieldDescriptor field : this.descriptor.getAllFieldDescriptors()) {
        if (field.isPersistent()) {
          String prefix = GETTER_PREFIX;
          Log.d(Const.LOG_CAT, field.getField().getName() + "::" + field.getField().getType());
          if ((field.getField().getType() == Boolean.class) || (field.getField().getType() == boolean.class)) {
            prefix = "is";
          }
          Method m = clazz.getMethod(prefix + StringUtils.firstCharToUpper(field.getField().getName()));

          Object val = m.invoke(example);
          if (val != null) {
            selection = (selection == null ? "" : selection + " and ");
            selection = selection + field.getColumn() + " = ?";
            selectionArgList.add(val.toString());
          }
        }
      }

      String[] selectionargs = (selectionArgList.size() > 0 ? selectionArgList.toArray(new String[0]) : null);
      Cursor result = this.db.query(tablename, columns, selection, selectionargs, null, null, null);

      return this.makeInstanceOfList(result);

    } catch (SecurityException e) {
      throw new AndroDBException("Could not save " + this.entityName + ".", e);
    } catch (NoSuchMethodException e) {
      throw new AndroDBException("Could not save " + this.entityName + ".", e);
    } catch (IllegalArgumentException e) {
      throw new AndroDBException("Could not save " + this.entityName + ".", e);
    } catch (IllegalAccessException e) {
      throw new AndroDBException("Could not save " + this.entityName + ".", e);
    } catch (InvocationTargetException e) {
      throw new AndroDBException("Could not save " + this.entityName + ".", e);
    }
  }

  /**
   * deletes the given entity
   * 
   * @param entity
   *          the entity to delete
   */
  public void delete(T entity) {
    try {
      FieldDescriptor primaryKey = this.descriptor.getPrimaryKey();
      if (primaryKey == null) {
        throw new AndroDBException("the primary key of " + this.entityName + " cannot be null!");
      }

      String tablename = this.descriptor.getTablename();
      String selection = this.descriptor.getPrimaryKey().getColumn() + " = ?";

      Method m = this.getEntity().getMethod(GETTER_PREFIX + StringUtils.firstCharToUpper(this.descriptor.getPrimaryKey().getField().getName()));

      Object key = m.invoke(entity);
      if (key == null) {
        throw new IllegalArgumentException("The primary key field '" + this.descriptor.getPrimaryKey().getField().getName()
            + "' of the given entity was null!");
      }

      String[] selectionargs = { String.valueOf(key) };
      this.db.delete(tablename, selection, selectionargs);

    } catch (SecurityException e) {
      throw new AndroDBException("Could not delete " + this.entityName + " by primary key.", e);
    } catch (IllegalArgumentException e) {
      throw new AndroDBException("Could not delete " + this.entityName + " by primary key.", e);
    } catch (NoSuchMethodException e) {
      throw new AndroDBException("Could not delete " + this.entityName + " by primary key.", e);
    } catch (IllegalAccessException e) {
      throw new AndroDBException("Could not delete " + this.entityName + " by primary key.", e);
    } catch (InvocationTargetException e) {
      throw new AndroDBException("Could not delete " + this.entityName + " by primary key.", e);
    }
  }

  private List<T> makeInstanceOfList(Cursor result) {
    ArrayList<T> list = new ArrayList<T>();
    result.moveToFirst();
    if (result.getCount() > 0) {
      do {
        T instance = this.makeInstanceInternal(result);
        list.add(instance);
      } while (result.moveToNext());
      result.close();
    }
    return list;
  }

  protected T makeInstance(Cursor result) {
    T instance = this.makeInstanceInternal(result);
    result.close();
    return instance;
  }

  private T makeInstanceInternal(Cursor result) {
    try {
      Class<T> clazz = this.getEntity();
      T instance = clazz.newInstance();

      for (FieldDescriptor field : this.descriptor.getAllFieldDescriptors()) {
        if (field.isPersistent()) {
          String setterName = "set" + StringUtils.firstCharToUpper(field.getField().getName());
          Method m = clazz.getMethod(setterName, field.getField().getType());
          Object args = this.getResultValue(result, result.getColumnIndex(field.getColumn()), field.getField().getType());
          m.invoke(instance, args);
        }
      }

      return instance;
    } catch (InstantiationException e) {
      throw new AndroDBException("Could not create instance of " + this.entityName + ".", e);
    } catch (IllegalAccessException e) {
      throw new AndroDBException("Could not create instance of " + this.entityName + ".", e);
    } catch (SecurityException e) {
      throw new AndroDBException("Could not create instance of " + this.entityName + ".", e);
    } catch (NoSuchMethodException e) {
      throw new AndroDBException("Could not create instance of " + this.entityName + ".", e);
    } catch (IllegalArgumentException e) {
      throw new AndroDBException("Could not create instance of " + this.entityName + ".", e);
    } catch (InvocationTargetException e) {
      throw new AndroDBException("Could not create instance of " + this.entityName + ".", e);
    }
  }

  @SuppressWarnings("unchecked")
  private Class<T> getEntity() {
    return (Class<T>) this.descriptor.getTheEntity();
  }

  private Object getResultValue(Cursor result, int columnIndex, Class<?> type) {

    if (type == String.class) {
      return result.getString(columnIndex);
    }
    if ((type == Long.class) || (type == long.class)) {
      return result.getLong(columnIndex);
    }
    if ((type == Integer.class) || (type == int.class)) {
      return result.getInt(columnIndex);
    }
    if ((type == Short.class) || (type == short.class)) {
      return result.getShort(columnIndex);
    }
    if ((type == Boolean.class) || (type == boolean.class)) {
      return result.getInt(columnIndex) == 1;
    }
    if ((type == Double.class) || (type == double.class)) {
      return result.getDouble(columnIndex);
    }
    if ((type == Float.class) || (type == float.class)) {
      return result.getFloat(columnIndex);
    }
    return null;
  }

  private void addToContentValues(ContentValues values, String key, Object value) {
    if (value instanceof String) {
      values.put(key, (String) value);
    }
    if ((value instanceof Long) || ((value != null) && (value.getClass() == long.class))) {
      values.put(key, (Long) value);
    }
    if ((value instanceof Integer) || ((value != null) && (value.getClass() == int.class))) {
      values.put(key, (Integer) value);
    }
    if ((value instanceof Short) || ((value != null) && (value.getClass() == short.class))) {
      values.put(key, (Short) value);
    }
    if ((value instanceof Boolean) || ((value != null) && (value.getClass() == boolean.class))) {
      values.put(key, (Boolean) value);
    }
    if ((value instanceof Double) || ((value != null) && (value.getClass() == double.class))) {
      values.put(key, (Double) value);
    }
    if ((value instanceof Float) || ((value != null) && (value.getClass() == float.class))) {
      values.put(key, (Float) value);
    }
    if ((value instanceof Byte) || ((value != null) && (value.getClass() == byte.class))) {
      values.put(key, (Byte) value);
    }

  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.