list, String delim) {
+ StringBuilder buf = new StringBuilder();
+ int num = list.size();
+ for (int i = 0; i < num; i++) {
+ if (i != 0)
+ buf.append(delim);
+ buf.append((String) list.get(i));
+ }
+ return buf.toString();
+ }
+}
diff --git a/src/com/perfectworldprogramming/mobile/orm/helper/DBHelper.java b/src/com/perfectworldprogramming/mobile/orm/helper/DBHelper.java
new file mode 100644
index 0000000..742bd81
--- /dev/null
+++ b/src/com/perfectworldprogramming/mobile/orm/helper/DBHelper.java
@@ -0,0 +1,38 @@
+package com.perfectworldprogramming.mobile.orm.helper;
+
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+
+/**
+ * This class might be deprecated if not needed
+ *
+ * User: Mark Spritzler
+ * Date: 3/10/11
+ * Time: 8:23 PM
+ */
+public class DBHelper {
+ private SQLiteDatabase sqlLiteDatabase;
+ private final AndroidSQLLiteOpenHelper openHelper;
+
+ public DBHelper(Context context, Class extends Object>[] classes, String dataBaseName, int dataBaseVersion) {
+ System.out.println(" " + context + " " + classes + " " + dataBaseName + " " + dataBaseVersion);
+ openHelper = new AndroidSQLLiteOpenHelper(context, classes, dataBaseName, dataBaseVersion);
+ establishDb();
+ }
+
+ private void establishDb() {
+ if (sqlLiteDatabase == null) {
+ sqlLiteDatabase = openHelper.getWritableDatabase();
+ }
+}
+ public void cleanup() {
+ if (sqlLiteDatabase != null) {
+ sqlLiteDatabase.close();
+ sqlLiteDatabase = null;
+ }
+ }
+
+ public SQLiteDatabase getSqlLiteDatabase() {
+ return sqlLiteDatabase;
+ }
+}
diff --git a/src/com/perfectworldprogramming/mobile/orm/interfaces/CursorExtractor.java b/src/com/perfectworldprogramming/mobile/orm/interfaces/CursorExtractor.java
new file mode 100644
index 0000000..6f824dd
--- /dev/null
+++ b/src/com/perfectworldprogramming/mobile/orm/interfaces/CursorExtractor.java
@@ -0,0 +1,31 @@
+package com.perfectworldprogramming.mobile.orm.interfaces;
+
+import android.database.Cursor;
+
+/**
+ * Callback interface used by {@link com.perfectworldprogramming.mobile.orm.AndroidSQLiteTemplate}'s query methods.
+ * Implementations of this interface perform the actual work of extracting
+ * results from a {@link java.sql.ResultSet}, but don't need to worry
+ * about exception handling. {@link java.sql.SQLException SQLExceptions}
+ * will be caught and handled by the calling AndroidSQLiteTemplate.
+ *
+ * This interface is mainly used within the SQLLite framework itself.
+ * A {@link CursorRowMapper} is usually a simpler choice for Cursor processing,
+ * mapping one result object per row instead of one result object for
+ * the entire ResultSet.
+ *
+ * @author Mark Spritzler
+ * @since 3/19/11
+ * @see com.perfectworldprogramming.mobile.orm.AndroidSQLiteTemplate
+ * @see CursorRowMapper
+ */
+public interface CursorExtractor {
+
+ /**
+ * Implementations must implement this method to process the entire Cursor.
+ * @param cursor Cursor to extract data from. Implementations should
+ * not close this: it will be closed by the calling AndroidSQLiteTemplate.
+ * @return an arbitrary result object, or null
if none
+ */
+ T extractData(Cursor cursor);
+}
diff --git a/src/com/perfectworldprogramming/mobile/orm/interfaces/CursorRowMapper.java b/src/com/perfectworldprogramming/mobile/orm/interfaces/CursorRowMapper.java
new file mode 100644
index 0000000..221b0ff
--- /dev/null
+++ b/src/com/perfectworldprogramming/mobile/orm/interfaces/CursorRowMapper.java
@@ -0,0 +1,13 @@
+package com.perfectworldprogramming.mobile.orm.interfaces;
+
+import android.database.Cursor;
+
+/**
+ * User: Mark Spritzler
+ * Date: 3/19/11
+ * Time: 2:35 PM
+ */
+public interface CursorRowMapper {
+
+ T mapRow(Cursor cursor, int rowNum);
+}
diff --git a/src/com/perfectworldprogramming/mobile/orm/interfaces/JdbcOperations.java b/src/com/perfectworldprogramming/mobile/orm/interfaces/JdbcOperations.java
new file mode 100644
index 0000000..86d37b7
--- /dev/null
+++ b/src/com/perfectworldprogramming/mobile/orm/interfaces/JdbcOperations.java
@@ -0,0 +1,219 @@
+package com.perfectworldprogramming.mobile.orm.interfaces;
+
+import java.util.List;
+
+import com.perfectworldprogramming.mobile.orm.exception.DataAccessException;
+import com.perfectworldprogramming.mobile.orm.exception.NoRowsReturnedException;
+
+/**
+ * Interface for the Android Template class. Since there is only one template
+ * class this interface isn't as necessary, but created to be as close a match to
+ * JDBCTemplate in Core Spring. So if you have used JDBCTemplate before, you will
+ * be completely familiar with the AndroidSQLiteTemplate class with same method
+ * names and functionality.
+ *
+ * User: Mark Spritzler
+ * Date: 3/19/11
+ * Time: 2:31 PM
+ */
+public interface JdbcOperations {
+
+ /**
+ * Creates an insert statement and inserts the data in the Domain object passed in
+ * as a parameter.
+ *
+ * The domain object passed in must mapped with the @PrimaryKey, @Column and @ForeignKey
+ * annotations. If your domain object is not mapped and you want to pass in an insert sql
+ * statement look at
+ * @param object domain object without an ID, and not inserted in the database yet
+ * @return long, number of rows inserted. Should return 1 if successful
+ */
+ public long insert(Object object) throws DataAccessException;
+
+ /**
+ * Handles insert SQL statement to the database.
+ * Use this method instead of insert(Object object
+ * if your domain objects are not mapped with the ORM Annotations.
+ *
+ * @param sql Insert sql statement
+ * @param args values to replace parameters within the insert statement
+ * @return long, number of rows inserted. Should return 1 if successful
+ */
+ public long insert(String sql, Object... args) throws DataAccessException;
+
+ /**
+ * Creates an update statement and updates the data in the Domain object passed in
+ * as a parameter.
+ *
+ * The domain object passed in must mapped with the @PrimaryKey, @Column and @ForeignKey
+ * annotations. If your domain object is not mapped and you want to update the data
+ * look at update(String sql, Object... args
+ *
+ * @param object domain object without an ID, and not inserted in the database yet
+ * @return long, number of rows updated. Should return 1 if successful
+ */
+ public long update(Object object) throws DataAccessException;
+
+ /**
+ * Handles updates to the database.
+ *
+ *
+ * Use this method instead of update(Object object)
+ * if your domain objects are not mapped with the ORM Annotations.
+ *
+ * @param sql update statement SQL
+ * @param args values to set the parameters in the update statement
+ */
+ public void update(String sql, Object... args) throws DataAccessException;
+
+ /**
+ *
+ * @param object
+ * @return
+ */
+ public long delete(Object object) throws DataAccessException;
+
+ /**
+ * Delete a single row in a table based on a single value for a single field.
+ *
+ * While this will call delete(table, whereClause, whereArgs) on the underlying SQLiteDatabase object, it will not allow an array of ids
+ * or a where clause. If you want that functionality use {@link #delete(String, Object...)} template method instead.
+ *
+ * @param table table to delete from
+ * @param columnName field to use in the where clause of the delete statement
+ * @param columnValue primary key value
+ * @return long should return 1 if successful
+ */
+ public long delete(String table, String columnName, String columnValue) throws DataAccessException;
+
+ /**
+ *
+ * @param sql
+ * @param args
+ */
+ public void delete(String sql, Object... args) throws DataAccessException;
+
+ /**
+ * Runs a query where one row with one field is expected in results, where
+ * the field value is an int.
+ *
+ * However, if the type of that field is not an int, then 0 will always be returned.
+ * This is because of the underlying Android SQLite implementation of running a simple
+ * query for int.
+ *
+ * If the result returns more than one row, the first row's data will be returned.
+ * If the result returned has zero rows, then a DataAccessException is thrown.
+ *
+ * @param sql select statement sql with one field in the select portion
+ * @param args values to set the parameters in the update statement
+ * @return int the value of the field. 0 if the field type is not a number
+ * @throws DataAccessException when the result set returned zero rows
+ */
+ public int queryForInt(String sql, Object... args) throws DataAccessException;
+
+ /**
+ * Runs a query where one row with one field is expected in results, where
+ * the field value is a long.
+ *
+ * However, if the type of that field is not an long, then 0 will always be returned.
+ * This is because of the underlying Android SQLite implementation of running a simple
+ * query for long.
+ *
+ * If the result returns more than one row, the first row's data will be returned.
+ * If the result set returned has zero rows, then a NoRowsReturnedException is thrown.
+ *
+ * @param sql select statement sql with one field in the select portion
+ * @param args values to set the parameters in the update statement
+ * @return long the value of the field. 0 if the field type is not a number
+ * @throws NoRowsReturnedException when the result set returned zero rows
+ */
+ public long queryForLong(String sql, Object... args) throws DataAccessException;
+
+ /**
+ * Runs a query where one row with one field is expected in results, where
+ * the field value is a String.
+ *
+ * However, if the type of that field is not an long, then SQLite will convert it to a String.
+ * This is because of the underlying Android SQLite implementation of running a simple
+ * query for String.
+ *
+ * If the result returns more than one row, the first row's data will be returned.
+ * If the result set returned has zero rows, then a NoRowsReturnedException is thrown.
+ *
+ * @param sql select statement sql with one field in the select portion
+ * @param args values to set the parameters in the update statement
+ * @return String the value of the field. if the field type is not a string the type is converted into a String
+ * @throws NoRowsReturnedException when the result set returned zero rows
+ */
+ public String queryForString(String sql, Object... args) throws DataAccessException, NoRowsReturnedException;
+
+ /**
+ *
+ * Runs a query where one row expected in results
+ *
+ * However, if the type of that field is not an long, then SQLite will convert it to a String.
+ * This is because of the underlying Android SQLite implementation of running a simple
+ * query for String.
+ *
+ * If the result returns more than one row, the first row's data will be returned.
+ * If the result set returned has zero rows, then a NoRowsReturnedException is thrown.
+ *
+ * @param sql select statement sql with one field in the select portion
+ * @param clazz Class of the domain object to create with the results from the Cursor
+ * @param args values to set the parameters in the update statement
+ * @param Type of the Domain object that is returned
+ * @return the domain object filled with the values from the first row of the Cursor
+ * @throws NoRowsReturnedException when the result set returned zero rows
+ */
+ public T queryForObject(String sql, Class clazz, Object... args) throws NoRowsReturnedException;
+
+ /**
+ *
+ * @param sql
+ * @param cursorRowMapper
+ * @param args
+ * @param
+ * @return
+ */
+ public T queryForObject(String sql, CursorRowMapper cursorRowMapper, Object... args) throws DataAccessException;
+
+ /**
+ *
+ * @param sql
+ * @param cursorExtractor
+ * @param args
+ * @param
+ * @return
+ */
+ public T queryForObject(String sql, CursorExtractor cursorExtractor, Object... args) throws DataAccessException;
+
+ /**
+ *
+ * @param clazz
+ * @param id
+ * @param
+ * @return
+ */
+ public T findById(Class clazz, Long id) throws DataAccessException;
+
+ /**
+ *
+ * @param sql
+ * @param clazz
+ * @param args
+ * @param
+ * @return
+ */
+ public List query(String sql, Class clazz, Object... args) throws DataAccessException;
+
+ /**
+ *
+ * @param sql
+ * @param cursorRowMapper
+ * @param args
+ * @param
+ * @return
+ */
+ public List query(String sql, CursorRowMapper cursorRowMapper, Object... args) throws DataAccessException;
+
+}
diff --git a/src/com/perfectworldprogramming/mobile/orm/reflection/DomainClassAnalyzer.java b/src/com/perfectworldprogramming/mobile/orm/reflection/DomainClassAnalyzer.java
new file mode 100644
index 0000000..aad7f89
--- /dev/null
+++ b/src/com/perfectworldprogramming/mobile/orm/reflection/DomainClassAnalyzer.java
@@ -0,0 +1,130 @@
+package com.perfectworldprogramming.mobile.orm.reflection;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.perfectworldprogramming.mobile.orm.annotations.Column;
+import com.perfectworldprogramming.mobile.orm.annotations.ForeignKey;
+import com.perfectworldprogramming.mobile.orm.annotations.PrimaryKey;
+import com.perfectworldprogramming.mobile.orm.exception.DataAccessException;
+import com.perfectworldprogramming.mobile.orm.exception.NoPrimaryKeyFieldException;
+
+import android.content.ContentValues;
+
+/**
+ * User: Mark Spritzler
+ * Date: 3/12/11
+ * Time: 9:48 PM
+ */
+public class DomainClassAnalyzer {
+
+ public Field getPrimaryKeyField(Class extends Object> clazz) {
+ Field primaryKeyField = null;
+ Field[] fields = clazz.getDeclaredFields();
+ for (Field field : fields) {
+ PrimaryKey primaryKey = field.getAnnotation(PrimaryKey.class);
+ if (primaryKey != null) {
+ primaryKeyField = field;
+ break;
+ }
+ }
+ if (primaryKeyField == null) {
+ throw new NoPrimaryKeyFieldException(clazz);
+ }
+ return primaryKeyField;
+ }
+
+ public String getPrimaryKeyFieldName(Class extends Object> clazz) {
+ PrimaryKey primaryKey = getPrimaryKey(clazz);
+ return primaryKey.value();
+ }
+
+ public PrimaryKey getPrimaryKey(Class extends Object> clazz) {
+ return getPrimaryKeyField(clazz).getAnnotation(PrimaryKey.class);
+ }
+
+ public Field[] getForeignKeyFields(Class extends Object> clazz) {
+ List foreignKeyFields = new ArrayList();
+ Field[] fields = clazz.getDeclaredFields();
+ for (Field field : fields) {
+ ForeignKey foreignKey = field.getAnnotation(ForeignKey.class);
+ if (foreignKey != null) {
+ foreignKeyFields.add(field);
+ break;
+ }
+ }
+ return foreignKeyFields.toArray(new Field[foreignKeyFields.size()]);
+ }
+
+ public long getIdFromObject(Object o) {
+ Long id = -1l;
+ Class extends Object> clazz = o.getClass();
+ Field primaryKeyField = getPrimaryKeyField(clazz);
+ primaryKeyField.setAccessible(true);
+ try {
+ id = (Long)primaryKeyField.get(o);
+ if (id == null) {
+ throw new DataAccessException("Domain classes must have an @PrimaryKey property in order to use the ORM functionality. Your " + o.getClass().getName() + " class is missing @PrimaryKey");
+ }
+ } catch (IllegalAccessException e) {
+ throw new DataAccessException(e.getMessage());
+ }
+ return id;
+ }
+
+ public void setIdToNewObject(Object object, long id) {
+ Field fieldToSet = this.getPrimaryKeyField(object.getClass());
+ fieldToSet.setAccessible(true);
+ try {
+ fieldToSet.set(object, id);
+ } catch (IllegalAccessException e) {
+ throw new DataAccessException(e.getMessage());
+ }
+ }
+
+ public ContentValues createContentValues(Object object) {
+ Class extends Object> clazz = object.getClass();
+ Field[] fields = clazz.getDeclaredFields();
+ ContentValues values = new ContentValues(fields.length);
+ for (Field field : fields) {
+ Column column = field.getAnnotation(Column.class);
+ if (column != null) {
+ addColumnValuesToContentValues(field, values, column.value(), object);
+ } else {
+ ForeignKey foreignKey = field.getAnnotation(ForeignKey.class);
+ if (foreignKey != null) {
+ addForeignKeyValuesToContentValues(field, foreignKey, values, object);
+ }
+ }
+ }
+ return values;
+ }
+
+ private void addColumnValuesToContentValues(Field field, ContentValues values, String fieldName, Object object) {
+ field.setAccessible(true);
+ try {
+ Object value = field.get(object);
+ if (value != null) {
+ values.put(fieldName, value.toString());
+ }
+ } catch (IllegalAccessException e) {
+ throw new DataAccessException("Unable to get the Column value from the domain object: " + object.getClass().getName() + " for Field: " + fieldName);
+ }
+ }
+
+ private void addForeignKeyValuesToContentValues(Field field, ForeignKey foreignKey, ContentValues values, Object domainObject) {
+ field.setAccessible(true);
+ try {
+ Object foreignDomainObject = field.get(domainObject);
+ if (foreignDomainObject != null) {
+ Object value = getIdFromObject(foreignDomainObject);
+ if (value != null) {
+ values.put(foreignKey.value(), value.toString());
+ }
+ }
+ } catch (IllegalAccessException e) {
+ throw new DataAccessException("Unable to get the Foreign Key value from the domain object: " + domainObject.getClass().getName());
+ }
+ }
+}
diff --git a/test/com/perfectworldprogramming/mobile/orm/test/AndroidSQLiteTemplateTests.java b/test/com/perfectworldprogramming/mobile/orm/test/AndroidSQLiteTemplateTests.java
new file mode 100644
index 0000000..a8f99ee
--- /dev/null
+++ b/test/com/perfectworldprogramming/mobile/orm/test/AndroidSQLiteTemplateTests.java
@@ -0,0 +1,886 @@
+package com.perfectworldprogramming.mobile.orm.test;
+
+import java.util.List;
+
+
+import com.perfectworldprogramming.mobile.orm.AndroidSQLiteTemplate;
+import com.perfectworldprogramming.mobile.orm.exception.DataAccessException;
+import com.perfectworldprogramming.mobile.orm.exception.EmptySQLStatementException;
+import com.perfectworldprogramming.mobile.orm.exception.InvalidCursorExtractorException;
+import com.perfectworldprogramming.mobile.orm.exception.InvalidCursorRowMapperException;
+import com.perfectworldprogramming.mobile.orm.helper.DBHelper;
+import com.perfectworldprogramming.mobile.orm.interfaces.CursorExtractor;
+import com.perfectworldprogramming.mobile.orm.interfaces.CursorRowMapper;
+import com.perfectworldprogramming.mobile.orm.reflection.DomainClassAnalyzer;
+import com.perfectworldprogramming.mobile.orm.test.domain.Account;
+import com.perfectworldprogramming.mobile.orm.test.domain.Address;
+import com.perfectworldprogramming.mobile.orm.test.domain.NoPKDomain;
+import com.perfectworldprogramming.mobile.orm.test.domain.Person;
+import com.perfectworldprogramming.mobile.orm.test.interfaces.AddressCursorExtractor;
+import com.perfectworldprogramming.mobile.orm.test.interfaces.AddressCursorRowMapper;
+import com.perfectworldprogramming.mobile.orm.test.interfaces.PersonCursorExtractor;
+import com.perfectworldprogramming.mobile.orm.test.interfaces.PersonCursorRowMapper;
+import com.perfectworldprogramming.mobile.orm.test.interfaces.SampleDataHelper;
+
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.test.ActivityInstrumentationTestCase2;
+import android.util.Log;
+
+/**
+ * User: Mark Spritzler
+ * Date: 4/7/11
+ * Time: 12:06 PM
+ */
+public class AndroidSQLiteTemplateTests extends ActivityInstrumentationTestCase2{
+
+ public AndroidSQLiteTemplateTests() {
+ super("org.springframework.mobile.orm.test", Main.class);
+ }
+
+ AndroidSQLiteTemplate template;
+ List sampleAccounts;
+
+ SQLiteDatabase dataBase;
+
+ @SuppressWarnings("unchecked")
+ public void setUp() {
+ try {
+ super.setUp();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ DBHelper helper = new DBHelper(this.getInstrumentation().getContext(), new Class[]{Person.class, Address.class, Account.class}, "ormtest", 3);
+ template = new AndroidSQLiteTemplate(helper.getSqlLiteDatabase());
+ SampleDataHelper.addDataToDatabase(template);
+ sampleAccounts = SampleDataHelper.getAccounts();
+ dataBase =helper.getSqlLiteDatabase();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+
+
+ // Currently passes
+ public void testSuccessInsertWithDomainObject() {
+ Person person = new Person();
+ person.setAge(5);
+ person.setFirstName("Ryan");
+ person.setLastName("Simpson");
+ person.setHeight(2.6);
+ long id = template.insert(person);
+
+ // Check out by using the api directly.
+ Cursor cursor = dataBase.rawQuery("Select * from Person where PERSON_ID = " + id, null);
+ assertNotNull(cursor);
+ assertEquals(1, cursor.getCount());
+ cursor.moveToFirst();
+ assertEquals("Ryan", cursor.getString(cursor.getColumnIndex("FIRST_NAME")));
+ assertEquals("Simpson", cursor.getString(cursor.getColumnIndex("LAST_NAME")));
+ }
+
+ //Currently passes but needs more code
+ /*
+ * Missing Mandatory/not Nullable Field
+ * Field that is set to unique is not unique (next version, but the code still should work in this scenario and would throw a DataAccessException)
+ */
+ public void testFailureInsertWithDomainObject() {
+ //missing mandatory field
+ Person person = new Person();
+ person.setAge(5);
+ person.setLastName("Simpson");
+ person.setHeight(2.6);
+ try {
+ template.insert(person);
+ fail("Exception should be thrown because a mandatory field is not set");
+ } catch (DataAccessException dae) {
+ } catch (Exception e) {
+ fail("This should throw a Spring DataAccessException not one from SQLite");
+ }
+ }
+
+ // Currently Passes
+ public void testSuccessInsertSQL() {
+ String sql = "INSERT INTO Person (FIRST_NAME, LAST_NAME, AGE) VALUES ('?', '?', ?)";
+ Object[] args = {"Bugs", "Bunny", 10};
+ long id = template.insert(sql, args);
+
+ Cursor cursor = dataBase.rawQuery("Select * from Person where PERSON_ID = " + id, null);
+ assertNotNull(cursor);
+ assertEquals(1, cursor.getCount());
+ cursor.moveToFirst();
+ assertEquals("Bugs", cursor.getString(cursor.getColumnIndex("FIRST_NAME")));
+ assertEquals("Bunny", cursor.getString(cursor.getColumnIndex("LAST_NAME")));
+ assertEquals(10, cursor.getInt(cursor.getColumnIndex("AGE")));
+ }
+
+ // Currently Passes
+ /*
+ * Invalid Insert statement string using FIELDS
+ * Using an update statement instead of an insert
+ */
+ public void testFailureInsertSQL() {
+ String sql = "INSERT INTO Person FIELDS (FIRST_NAME, LAST_NAME, AGE) VALUES ('?', '?', ?)";
+ Object[] args = {"Bugs", "Bunny", 10};
+ try {
+ template.insert(sql, args);
+ fail("Exception should be thrown because a insert statement is invalid");
+ } catch (DataAccessException de) {
+ } catch (Exception e) {
+ fail("This should throw a Spring DataAccessException not one from SQLite");
+ }
+
+ sql = "UPDATE Person (FIRST_NAME, LAST_NAME, AGE) VALUES ('?', '?', ?)";
+ try {
+ template.insert(sql, args);
+ fail("Exception should be thrown because it is an update statement");
+ } catch (DataAccessException de) {
+ } catch (Exception e) {
+ fail("This should throw a Spring DataAccessException not one from SQLite");
+ }
+ }
+
+ // Currently passes
+ public void testSuccessUpdateWithDomainObject() {
+ // Take the last account in collection and make changes
+ // First just a Real field
+ Account account = sampleAccounts.get(sampleAccounts.size()-1);
+ account.setAmount(42.00);
+ long numberOfAccountsUpdated = template.update(account);
+
+ assertEquals(1, numberOfAccountsUpdated);
+ assertAccount(account, "Select * from Account where YEAR_STARTED=2011");
+
+ // Now an Integer field
+ account.setYearAccountOpened(1900);
+ numberOfAccountsUpdated = template.update(account);
+ assertEquals(1, numberOfAccountsUpdated);
+ assertAccount(account, "Select * from Account where YEAR_STARTED=1900");
+
+ // Now a Text field
+ account.setAccountType("Invalid");
+ numberOfAccountsUpdated = template.update(account);
+ assertEquals(1, numberOfAccountsUpdated);
+ assertAccount(account, "Select * from Account where YEAR_STARTED=1900");
+
+ // Now all three field types in one update
+ account.setAccountType("Business Pro");
+ account.setYearAccountOpened(2011);
+ account.setAmount(4200.00);
+ numberOfAccountsUpdated = template.update(account);
+ assertEquals(1, numberOfAccountsUpdated);
+ assertAccount(account, "Select * from Account where YEAR_STARTED=2011");
+
+ }
+
+
+ // Currently Passes
+ public void testFailureUpdateWithDomainObject() {
+ //No Id set in domain object
+ Account account = new Account();
+ try {
+ template.update(account);
+ fail("Exception should be thrown because id is not set");
+ } catch (DataAccessException de) {
+ } catch (Exception e) {
+ Log.i("Template Test", Log.getStackTraceString(e));
+ fail("This should throw a Spring DataAccessException not one from SQLite " + e.getMessage());
+ }
+
+ // Use an object that is not mapped
+ Long longObject = new Long(5);
+ try {
+ template.update(longObject);
+ fail("Exception should be thrown because Long is not a domain object");
+ } catch (DataAccessException de) {
+ } catch (Exception e) {
+ fail("This should throw a Spring DataAccessException not one from SQLite " + e.getMessage());
+ }
+
+ // Object is mapped, but not a table in the database
+ NoPKDomain noPK = new NoPKDomain();
+ try {
+ template.update(noPK);
+ fail("Exception should be thrown because there isn't a table for this domain mapped object");
+ } catch (DataAccessException de) {
+ } catch (Exception e) {
+ fail("This should throw a Spring DataAccessException not one from SQLite " + e.getMessage());
+ }
+
+ }
+
+ // Currently passes
+ public void testSuccessUpdateSQL() {
+ // Update statement to one row
+ String sql = "UPDATE Account set AMOUNT = ? where ACCOUNT_TYPE = '?'";
+ Object[] args = {new Double(68.00), "Personal"};
+ template.update(sql, args);
+
+ Cursor cursor = dataBase.rawQuery("Select Amount from Account where ACCOUNT_TYPE='Personal'", null);
+ assertNotNull(cursor);
+ assertEquals(1, cursor.getCount());
+ cursor.moveToFirst();
+ Double results = cursor.getDouble(0);
+ assertEquals(new Double(68.00), results);
+
+ // Update statement to more than one row
+ sql = "UPDATE Account set AMOUNT = ? where ACCOUNT_TYPE = '?'";
+ args[0] = new Double(67.00);
+ args[1] = "Business";
+ template.update(sql, args);
+ cursor = dataBase.rawQuery("Select Amount from Account where ACCOUNT_TYPE='Business'", null);
+ assertNotNull(cursor);
+ assertEquals(3, cursor.getCount());
+ cursor.moveToFirst();
+ results = cursor.getDouble(0);
+ assertEquals(new Double(67.00), results);
+
+ // a delete statement
+ // This will work, because you can pass a delete statement to update
+ template.update("Delete from Account where ACCOUNT_ID = ?", new Object[]{1});
+
+ }
+
+
+ /* Currently passes
+ * Null sql,
+ * invalid update
+ * table doesn't exist
+ * set field doesn't exist
+ * set field to wrong type
+ * an insert statement,
+ * a select statement
+ *
+ */
+ public void testFailureUpdateSQL() {
+ String sql = "";
+ Object[] nullArgs = {};
+
+ // empty sql
+ try {
+ template.update(sql, nullArgs);
+ fail("Exception should be thrown because there isn't an update statement");
+ } catch (DataAccessException de) {
+ } catch (Exception e) {
+ fail("This should throw a Spring DataAccessException not one from SQLite " + e.getMessage());
+ }
+
+ // table doesn't exist
+ sql = "UPDATE NonExistingTable set AMOUNT = ? where ACCOUNT_TYPE = '?'";
+ Object[] validArgs = {new Double(67.00), "Business"};
+ try {
+ template.update(sql, validArgs);
+ fail("Exception should be thrown because the table doesn't exist in update statement");
+ } catch (DataAccessException de) {
+ } catch (Exception e) {
+ fail("This should throw a Spring DataAccessException not one from SQLite " + e.getMessage());
+ }
+
+ // set field doesn't exist
+ sql = "UPDATE Account set Non_Field = ? where ACCOUNT_TYPE = '?'";
+ try {
+ template.update(sql, validArgs);
+ fail("Exception should be thrown because the field doesn't exist update statement");
+ } catch (DataAccessException de) {
+ } catch (Exception e) {
+ fail("This should throw a Spring DataAccessException not one from SQLite " + e.getMessage());
+ }
+
+ // set field to wrong type
+ sql = "UPDATE Account set AMOUNT = ? where ACCOUNT_TYPE = '?'";
+ Object[] invalidArgs = {"Hello", "Business"};
+ try {
+ template.update(sql, invalidArgs);
+ fail("Exception should be thrown because the field value is the wrong type update statement");
+ } catch (DataAccessException de) {
+ } catch (Exception e) {
+ fail("This should throw a Spring DataAccessException not one from SQLite " + e.getMessage());
+ }
+
+ // an insert statement,
+ sql = "INSERT INTO Person FIELDS (FIRST_NAME, LAST_NAME, AGE) VALUES ('?', '?', ?)";
+ Object[] insertArgs = {"Bugs", "Bunny", 10};
+ try {
+ template.update(sql, insertArgs);
+ fail("Exception should be thrown because this is an insert statement not an update statement");
+ } catch (DataAccessException de) {
+ } catch (Exception e) {
+ fail("This should throw a Spring DataAccessException not one from SQLite " + e.getMessage());
+ }
+
+ // a select statement
+ sql = "Select * from Person";
+ try {
+ template.update(sql, new Object[]{});
+ fail("Exception should be thrown because this is a select statement not an update statement");
+ } catch (DataAccessException de) {
+ } catch (Exception e) {
+ fail("This should throw a Spring DataAccessException not one from SQLite " + e.getMessage());
+ }
+
+ }
+
+ // Currently passes
+ public void testSuccessDeleteWithDomainObject() {
+ Account account = sampleAccounts.get(5);
+ long results = template.delete(account);
+ assertEquals(1, results);
+ }
+
+ /*
+ * Currently passes
+ * null domain object
+ * domain object with invalid id
+ * domain object without an id
+ */
+ public void testFailureDeleteWithDomainObject() {
+ Account account = null;
+ try {
+ template.delete(account);
+ fail("Exception should be thrown because the domain object is null");
+ } catch (DataAccessException de) {
+ } catch (Exception e) {
+ fail("This should throw a Spring DataAccessException not one from SQLite " + e.getMessage());
+ }
+
+ account = new Account();
+ DomainClassAnalyzer analyzer = new DomainClassAnalyzer();
+ analyzer.setIdToNewObject(account, 42);
+ try {
+ template.delete(account);
+ fail("Exception should be thrown because this is an invalid id");
+ } catch (DataAccessException de) {
+ } catch (Exception e) {
+ fail("This should throw a Spring DataAccessException not one from SQLite " + e.getMessage());
+ }
+
+ account = new Account();
+ try {
+ template.delete(account);
+ fail("Exception should be thrown because the id in the domain object is null");
+ } catch (DataAccessException de) {
+ } catch (Exception e) {
+ fail("This should throw a Spring DataAccessException not one from SQLite " + e.getMessage());
+ }
+ }
+
+ // Currently Passes
+ public void testSuccessDeleteWithTableNameAndIdsToDelete() {
+ String table = "Account";
+ String keyColumnName = "ACCOUNT_ID";
+ String keyValue = "1";
+ long results = template.delete(table, keyColumnName, keyValue);
+ assertEquals(1, results);
+
+ keyValue = "2";
+ results = template.delete(table, keyColumnName, keyValue);
+ assertEquals(1, results);
+ }
+
+ /*
+ * Currently Passes
+ * empty strings and string array
+ * null table
+ * null keyColumnName
+ * null keyValues
+ * Wrong table name
+ * Wrong key column name
+ * Wrong id doesn't exist
+ */
+ public void testFailureDeleteWithTableNameAndIdsToDelete() {
+ // empty strings and string array
+ String table = "";
+ String keyColumnName = "";
+ String keyValue = "";
+ try {
+ template.delete(table, keyColumnName, keyValue);
+ fail("Exception should be thrown because there isn't a delete statement");
+ } catch (DataAccessException de) {
+ } catch (Exception e) {
+ fail("This should throw a Spring DataAccessException not one from SQLite " + e.getMessage());
+ }
+
+ //null table
+ table = null;
+ keyColumnName = "ACCOUNT_ID";
+ keyValue = "1";
+ try {
+ template.delete(table, keyColumnName, keyValue);
+ fail("Exception should be thrown because there isn't a delete statement");
+ } catch (DataAccessException de) {
+ } catch (Exception e) {
+ fail("This should throw a Spring DataAccessException not one from SQLite " + e.getMessage());
+ }
+
+ // null keyColumnName
+ table = "Account";
+ keyColumnName = null;
+ try {
+ template.delete(table, keyColumnName, keyValue);
+ fail("Exception should be thrown because there isn't a delete statement");
+ } catch (DataAccessException de) {
+ } catch (Exception e) {
+ fail("This should throw a Spring DataAccessException not one from SQLite " + e.getMessage());
+ }
+
+ // null keyValues
+ keyColumnName = "ACCOUNT_ID";
+ keyValue = null;
+ try {
+ template.delete(table, keyColumnName, keyValue);
+ fail("Exception should be thrown because there isn't a delete statement");
+ } catch (DataAccessException de) {
+ } catch (Exception e) {
+ fail("This should throw a Spring DataAccessException not one from SQLite " + e.getMessage());
+ }
+
+ // Fix the null from previous test
+ keyValue = "1";
+
+ // Wrong table name
+ table = "NonExistingTable";
+ try {
+ template.delete(table, keyColumnName, keyValue);
+ fail("Exception should be thrown because there isn't a delete statement");
+ } catch (DataAccessException de) {
+ } catch (Exception e) {
+ fail("This should throw a Spring DataAccessException not one from SQLite " + e.getMessage());
+ }
+
+ // Wrong key column name
+ table = "Account";
+ keyColumnName = "BAD_ID";
+ try {
+ template.delete(table, keyColumnName, keyValue);
+ fail("Exception should be thrown because there isn't a delete statement");
+ } catch (DataAccessException de) {
+ } catch (Exception e) {
+ fail("This should throw a Spring DataAccessException not one from SQLite " + e.getMessage());
+ }
+
+ // Wrong id doesn't exist
+ keyColumnName = "ACCOUNT_ID";
+ keyValue = "42";
+ long results = template.delete(table, keyColumnName, keyValue);
+ assertEquals(0, results);
+ }
+
+ // Currently Passes
+ public void testSuccessDeleteWithSQL() {
+ String sql = "Delete from Account where ACCOUNT_TYPE = '?'";
+ Object[] args = {"Personal"};
+ template.delete(sql, args);
+
+ sql = "Delete from Account where ACCOUNT_TYPE = '?'";
+ args[0] = "Business";
+ template.delete(sql, args);
+ }
+
+ // Currently Passes
+ public void testFailureDeleteWithSQL() {
+ String sql = "";
+ Object[] nullArgs = {};
+
+ // empty sql
+ try {
+ template.delete(sql, nullArgs);
+ fail("Exception should be thrown because there isn't a delete statement");
+ } catch (DataAccessException de) {
+ } catch (Exception e) {
+ fail("This should throw a Spring DataAccessException not one from SQLite " + e.getMessage());
+ }
+
+ // table doesn't exist
+ sql = "Delete from NonExistingTable where ACCOUNT_TYPE = '?'";
+ Object[] validArgs = {"Business"};
+ try {
+ template.delete(sql, validArgs);
+ fail("Exception should be thrown because the table doesn't exist in delete statement");
+ } catch (DataAccessException de) {
+ } catch (Exception e) {
+ fail("This should throw a Spring DataAccessException not one from SQLite " + e.getMessage());
+ }
+
+ // an insert statement,
+ sql = "INSERT INTO Person FIELDS (FIRST_NAME, LAST_NAME, AGE) VALUES ('?', '?', ?)";
+ Object[] insertArgs = {"Bugs", "Bunny", 10};
+ try {
+ template.delete(sql, insertArgs);
+ fail("Exception should be thrown because this is an insert statement not a delete statement");
+ } catch (DataAccessException de) {
+ } catch (Exception e) {
+ fail("This should throw a Spring DataAccessException not one from SQLite " + e.getMessage());
+ }
+
+ // a select statement
+ sql = "Select * from Person";
+ try {
+ template.delete(sql, new Object[]{});
+ fail("Exception should be thrown because this is a select statement not a delete statement");
+ } catch (DataAccessException de) {
+ } catch (Exception e) {
+ fail("This should throw a Spring DataAccessException not one from SQLite " + e.getMessage());
+ }
+ }
+
+
+ // Currently passes
+ public void testSuccessQueryForInt() {
+ String sql = "Select count(*) from Person";
+ String args = "";
+ Integer results = template.queryForInt(sql, args);
+
+ assertNotNull(results);
+ Cursor cursor = dataBase.rawQuery("Select count(*) from Person", null);
+ assertNotNull(cursor);
+ assertEquals(1, cursor.getCount());
+ cursor.moveToFirst();
+ Integer realCount = cursor.getInt(0);
+ assertEquals(realCount, results);
+ }
+
+ // Currently Passes
+ public void testFailureQueryForInt() {
+ String sql = "Select FIRST_NAME from Person Where FIRST_NAME='?'";
+ String args = "George";
+ try {
+ template.queryForInt(sql, args);
+ fail("DataAccessException should be thrown because query returns zero rows");
+ } catch (DataAccessException de) {
+ } catch (Exception e) {
+ fail("This should throw a Spring DataAccessException not one from SQLite " + e.getMessage());
+ }
+
+ // returns one row, but since it is a String the int is set to 0;
+ args = "John";
+ int zero = template.queryForInt(sql, args);
+ assertEquals(0, zero);
+
+ }
+
+ // Currently passes
+ public void testSuccessQueryForLong() {
+ String sql = "Select count(*) from Person";
+ String args = "";
+ Long results = template.queryForLong(sql, args);
+
+ assertNotNull(results);
+ Cursor cursor = dataBase.rawQuery("Select count(*) from Person", null);
+ assertNotNull(cursor);
+ assertEquals(1, cursor.getCount());
+ cursor.moveToFirst();
+ Long realCount = cursor.getLong(0);
+ assertEquals(realCount, results);
+ }
+
+ // Currently Passes
+ public void testFailureQueryForLong() {
+ String sql = "Select FIRST_NAME from Person Where FIRST_NAME='?'";
+ String args = "George";
+ try {
+ template.queryForLong(sql, args);
+ fail("DataAccessException should be thrown because query returns zero rows");
+ } catch (DataAccessException de) {
+ } catch (Exception e) {
+ fail("This should throw a Spring DataAccessException not one from SQLite " + e.getMessage());
+ }
+ args = "John";
+ long zero = template.queryForLong(sql, args);
+ assertEquals(0, zero);
+
+ }
+
+ // Currently passes
+ public void testSuccessQueryForString() {
+ String sql = "Select FIRST_NAME from Person Where FIRST_NAME='?'";
+ String args = "John";
+ String results = template.queryForString(sql, args);
+
+ assertNotNull(results);
+ assertEquals("John", results);
+
+ // Still will be successful and convert the int field to a String
+ sql = "Select AGE from Person Where FIRST_NAME='?'";
+ results = template.queryForString(sql, args);
+ assertNotNull(results);
+ assertEquals("42", results);
+
+ // Still will be successful with more than one row but return just the first row's value
+ sql = "Select age from Person";
+ args = null;
+ results = template.queryForString(sql, args);
+ assertNotNull(results);
+ assertEquals("42", results);
+
+ }
+
+ // Currently passes
+ public void testFailureQueryForString() {
+ String sql = "Select AGE from Person Where FIRST_NAME='?'";
+ String args = "George";
+ try {
+ template.queryForString(sql, args);
+ fail("DataAccessException should be thrown because it is returning 0 rows");
+ } catch (DataAccessException de) {
+ } catch (Exception e) {
+ fail("This should throw a Spring DataAccessException not one from SQLite " + e.getMessage());
+ }
+ }
+
+ // Currently passes
+ public void testSuccessQueryForObjectWithDomainClass() {
+ String sql="Select * from Person where FIRST_NAME='?'";
+ Class clazz = Person.class;
+ String args="John";
+ Person person = template.queryForObject(sql, clazz, args);
+ assertJohnThePerson(person);
+
+ // Still successful because SQLite returns the first row even if the query returns more than one row
+ sql="Select * from Person";
+ args = null;
+ person = template.queryForObject(sql, clazz, args);
+ assertJohnThePerson(person);
+ }
+
+ // Currently passes.
+ public void testFailureQueryForObjectWithDomainClass() {
+ String sql="Select * from Person where FIRST_NAME='?'";
+ Class clazz = Person.class;
+ String args="George";
+ try {
+ Object results = template.queryForObject(sql, clazz, args);
+ fail("DataAccessException should be thrown because results returned 0 rows but returns: " + results);
+ } catch (DataAccessException de) {
+ } catch (Exception e) {
+ fail("This should throw a Spring DataAccessException not one from SQLite " + e.getMessage());
+ }
+ }
+
+ // Currently passes
+ public void testSuccessQueryForObjectWithCursorRowMapper() {
+ String sql = "Select * from ADDRESS where ZIP_CODE='?'";
+ AddressCursorRowMapper addressCursorRowMapper = new AddressCursorRowMapper();
+ Address address = template.queryForObject(sql, addressCursorRowMapper, "12345");
+
+ assertNotNull(address);
+ assertEquals("Philadelphia", address.getCity());
+ assertEquals("PA", address.getState());
+ assertEquals("123 Broad Street", address.getStreet());
+ assertEquals("12345", address.getZipCode());
+ }
+
+ // Currently passes
+ public void testFailuresQueryForObjectWithCursorRowMapper() {
+ String sql="";
+ CursorRowMapper cursorRowMapper = null;
+ String args="";
+ try {
+ template.queryForObject(sql, cursorRowMapper, args);
+ fail("Should throw an IllegalArgumentException because the cursorRowMapper is null");
+ } catch (IllegalArgumentException ie) {
+ } catch (Exception e) {
+ fail("Only an IllegalArgumentException should be thrown");
+ }
+
+ cursorRowMapper = new AddressCursorRowMapper();
+ try {
+ template.queryForObject(sql, cursorRowMapper, args);
+ fail("Should throw an EmptySQLStatementException because the cursorRowMapper is null");
+ } catch (EmptySQLStatementException ie) {
+ } catch (Exception e) {
+ fail("Only an EmptySQLStatementException should be thrown " + e.getMessage());
+ }
+
+ sql = "Select * from Person Where FIRST_NAME = '?'";
+ args = "John";
+ try {
+ template.queryForObject(sql, cursorRowMapper, args);
+ fail("Should throw an InvalidCursorRowMapperException because the cursorRowMapper is of the wrong type. it is an Address Row mapper but the query is from Person");
+ } catch (InvalidCursorRowMapperException ie) {
+ } catch (Exception e) {
+ fail("Only an EmptySQLStatementException should be thrown: " + e.getMessage());
+ }
+ }
+
+ // Currently passes
+ public void testSuccessQueryForObjectWithCursorExtractor() {
+ String sql = "SELECT * from PERSON p, ADDRESS a where a.PERSON_ID = p.PERSON_ID and p.FIRST_NAME = '?'";
+ Person person = template.queryForObject(sql, new PersonCursorExtractor(), "John");
+
+ assertNotNull(person);
+ assertEquals(new Integer(42), person.getAge());
+ assertEquals("John", person.getFirstName());
+ assertEquals("Doe", person.getLastName());
+ assertEquals(new Double("5.1d"), person.getHeight());
+ List addresses = person.getAddresses();
+ assertNotNull(addresses);
+ assertEquals(2, addresses.size());
+ }
+
+ // Currently passes
+ public void testFailureQueryForObjectWithCursorExtractor() {
+ String sql="";
+ CursorExtractor cursorExtractor = null;
+ String args="";
+ try {
+ template.queryForObject(sql, cursorExtractor, args);
+ fail("Should throw an IllegalArgumentException because the cursorExtractor is null");
+ } catch (IllegalArgumentException ie) {
+ } catch (Exception e) {
+ fail("Only an IllegalArgumentException should be thrown");
+ }
+
+ cursorExtractor = new AddressCursorExtractor();
+ try {
+ template.queryForObject(sql, cursorExtractor, args);
+ fail("Should throw an EmptySQLStatementException because the cursorExtractor is null");
+ } catch (EmptySQLStatementException ie) {
+ } catch (Exception e) {
+ fail("Only an EmptySQLStatementException should be thrown " + e.getMessage());
+ }
+
+ sql = "Select * from Person";
+ try {
+ template.queryForObject(sql, cursorExtractor, args);
+ fail("Should throw an InvalidCursorExtractorException because the query does not return enough fields or from the Address table in a join clause");
+ } catch (InvalidCursorExtractorException ie) {
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ }
+
+ // Currently passes
+ public void testSuccessFindById() {
+ Person person = template.findById(Person.class, 1l);
+ assertJohnThePerson(person);
+ }
+
+ // Currently passes
+ public void testFailedFindById() {
+ Person person = template.findById(Person.class, 50l);
+ assertNull(person);
+ }
+
+ // Currently passes
+ public void testSuccessQueryWithDomainClass() {
+ List people = template.query("Select * from Person Where FIRST_NAME='?'", Person.class, "John");
+
+ assertNotNull(people);
+ assertEquals(1, people.size());
+ Person person = people.get(0);
+ assertJohnThePerson(person);
+ }
+
+ // Currently passes but needs more code, null sql, empty sql
+ public void testFailureQueryWithDomainClass() {
+ List people = template.query("Select * from Person Where FIRST_NAME='?'", Person.class, "Jonathon");
+ assertNotNull(people);
+ assertEquals(0, people.size());
+
+ // Null sql
+ String sql = null;
+ try {
+ template.query(sql, Person.class, "Jonathon");
+ fail("Should throw an EmptySQLStatementException because the query does not return enough fields or from the Address table in a join clause");
+ } catch (EmptySQLStatementException esse) {
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ // Empty String sql
+ sql = "";
+ try {
+ template.query(sql, Person.class, "Jonathon");
+ fail("Should throw an EmptySQLStatementException because the query does not return enough fields or from the Address table in a join clause");
+ } catch (EmptySQLStatementException esse) {
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ // Empty args
+ sql = "Select * from Person Where FIRST_NAME='?'";
+ try {
+ template.query(sql, Person.class, (Object[])null);
+ fail("A DataAccessException should be thrown because the arguments for the where clause is null");
+ } catch (DataAccessException dae) {
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+ }
+
+ // Currently passes
+ public void testSuccessQueryWithCursorRowMapper() {
+ String sqlStart = "Select * from Person Where";
+ CursorRowMapper personCursorRowMapper = new PersonCursorRowMapper();
+ String sql = sqlStart + " FIRST_NAME='?'";
+ List people = template.query(sql, personCursorRowMapper, "John");
+
+ assertNotNull(people);
+ assertEquals(1, people.size());
+ Person person = people.get(0);
+ assertJohnThePerson(person);
+
+ List everyone = template.query("Select * from Person", personCursorRowMapper);
+ assertNotNull(everyone);
+ Cursor cursor = dataBase.rawQuery("Select count(*) from Person", null);
+ assertNotNull(cursor);
+ assertEquals(1, cursor.getCount());
+ cursor.moveToFirst();
+ int realCount = cursor.getInt(0);
+ assertEquals(realCount, everyone.size());
+ }
+
+ // Currently passes add null sql or null rowmapper tests
+ public void testFailuresQueryWithCursorRowMapper() {
+ String sqlStart = "Select * from Person Where";
+ CursorRowMapper personCursorRowMapper = new PersonCursorRowMapper();
+ String sql = sqlStart + " FIRST_NAME=?";
+ try {
+ template.query(sql, personCursorRowMapper, "John");
+ fail("A DataAccessException should be thrown because the String parameter is not quoted");
+ } catch (DataAccessException dae) {
+ } catch (Exception e) {
+ fail("This should throw a Spring DataAccessException not one from SQLite " + e.getMessage());
+ }
+
+
+ try {
+ template.query("", personCursorRowMapper);
+ fail("A DataAccessException should be thrown because there is no query string");
+ } catch (DataAccessException dae) {
+ } catch (Exception e) {
+ fail("This should throw a Spring DataAccessException not one from SQLite " + e.getMessage());
+ }
+
+ try {
+ template.query("Select * from Address", personCursorRowMapper);
+ fail("A DataAccessException should be thrown because they are Addresses not People");
+ } catch (DataAccessException dae) {
+ } catch (Exception e) {
+ fail("This should throw a Spring DataAccessException not one from SQLite " + e.getMessage());
+ }
+ }
+
+ private void assertJohnThePerson(Person john) {
+ assertEquals(new Integer(42), john.getAge());
+ assertEquals("John", john.getFirstName());
+ assertEquals("Doe", john.getLastName());
+ assertEquals(new Double("5.1d"), john.getHeight());
+ }
+
+ private void assertAccount(Account account, String sql) {
+ Cursor cursor = dataBase.rawQuery(sql, null);
+ assertNotNull(cursor);
+ assertEquals(1, cursor.getCount());
+ cursor.moveToFirst();
+ Account checkAccount = new Account();
+ checkAccount.setAccountType(cursor.getString(cursor.getColumnIndex("ACCOUNT_TYPE")));
+ checkAccount.setAmount(cursor.getDouble(cursor.getColumnIndex("AMOUNT")));
+ checkAccount.setYearAccountOpened(cursor.getInt(cursor.getColumnIndex("YEAR_STARTED")));
+ assertEquals(account, checkAccount);
+ }
+}
diff --git a/test/com/perfectworldprogramming/mobile/orm/test/Main.java b/test/com/perfectworldprogramming/mobile/orm/test/Main.java
new file mode 100644
index 0000000..e4fdaee
--- /dev/null
+++ b/test/com/perfectworldprogramming/mobile/orm/test/Main.java
@@ -0,0 +1,17 @@
+package com.perfectworldprogramming.mobile.orm.test;
+
+import com.perfectworldprogramming.mobile.orm.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class Main extends Activity {
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+ //AndroidSQLLiteOpenHelper dbHelper = new AndroidSQLLiteOpenHelper(this.getApplicationContext(), new Class[]{Person.class, Address.class}, "ormtest", 1);
+ //dbHelper.getWritableDatabase();
+ }
+}
diff --git a/test/com/perfectworldprogramming/mobile/orm/test/MyInstrumentationTestRunner.java b/test/com/perfectworldprogramming/mobile/orm/test/MyInstrumentationTestRunner.java
new file mode 100644
index 0000000..5e45cca
--- /dev/null
+++ b/test/com/perfectworldprogramming/mobile/orm/test/MyInstrumentationTestRunner.java
@@ -0,0 +1,38 @@
+package com.perfectworldprogramming.mobile.orm.test;
+
+import junit.framework.TestSuite;
+
+import com.perfectworldprogramming.mobile.orm.test.creator.TableCreatorTest;
+import com.perfectworldprogramming.mobile.orm.test.helper.DBHelperTests;
+import com.perfectworldprogramming.mobile.orm.test.interfaces.CursorExtractorTests;
+import com.perfectworldprogramming.mobile.orm.test.interfaces.CursorRowMapperTests;
+import com.perfectworldprogramming.mobile.orm.test.reflection.DomainClassAnalyzerTests;
+
+import android.test.InstrumentationTestRunner;
+import android.test.InstrumentationTestSuite;
+
+/**
+ * User: Mark Spritzler
+ * Date: 3/30/11
+ * Time: 5:03 PM
+ */
+public class MyInstrumentationTestRunner extends InstrumentationTestRunner {
+ @Override
+ public TestSuite getAllTests() {
+ InstrumentationTestSuite suite = new InstrumentationTestSuite(this);
+ suite.addTestSuite(DomainClassAnalyzerTests.class);
+ suite.addTestSuite(DBHelperTests.class);
+ //suite.addTestSuite(AndroidSQLiteTemplateTests.class);
+ suite.addTestSuite(TableCreatorTest.class);
+ suite.addTestSuite(CursorExtractorTests.class);
+ suite.addTestSuite(CursorRowMapperTests.class);
+
+ return suite;
+ }
+
+ @Override
+ public ClassLoader getLoader() {
+ return MyInstrumentationTestRunner.class.getClassLoader();
+ }
+
+}
diff --git a/test/com/perfectworldprogramming/mobile/orm/test/creator/TableCreatorTest.java b/test/com/perfectworldprogramming/mobile/orm/test/creator/TableCreatorTest.java
new file mode 100644
index 0000000..2921cd5
--- /dev/null
+++ b/test/com/perfectworldprogramming/mobile/orm/test/creator/TableCreatorTest.java
@@ -0,0 +1,50 @@
+package com.perfectworldprogramming.mobile.orm.test.creator;
+
+import java.util.List;
+
+
+import com.perfectworldprogramming.mobile.orm.creator.SQLLiteCreateStatementGenerator;
+import com.perfectworldprogramming.mobile.orm.test.Main;
+import com.perfectworldprogramming.mobile.orm.test.domain.Address;
+import com.perfectworldprogramming.mobile.orm.test.domain.Person;
+
+import android.test.ActivityInstrumentationTestCase2;
+
+/**
+ * User: Mark Spritzler
+ * Date: 3/14/11
+ * Time: 2:40 PM
+ */
+public class TableCreatorTest extends ActivityInstrumentationTestCase2 {
+
+ // TODO need more tests
+ private SQLLiteCreateStatementGenerator SQLLiteCreateStatementGenerator = new SQLLiteCreateStatementGenerator();
+
+ public TableCreatorTest() {
+ super("org.springframework.mobile.orm.test", Main.class);
+ }
+
+ public void setUp() {
+ try {
+ super.setUp();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public void testGenerateTables() {
+ String statement = SQLLiteCreateStatementGenerator.createCreateStatement(Person.class);
+ assertNotNull("Statement should not be null", statement);
+ System.out.println(statement);
+
+ SQLLiteCreateStatementGenerator.setClasses(new Class[]{Person.class, Address.class});
+ List createStatements = SQLLiteCreateStatementGenerator.getCreateStatements();
+ assertNotNull("Should return a list", createStatements);
+ assertEquals("Should return two statements", 2, createStatements.size());
+ for (String aStatement : createStatements) {
+ System.out.println(aStatement);
+ }
+ }
+
+}
diff --git a/test/com/perfectworldprogramming/mobile/orm/test/domain/Account.java b/test/com/perfectworldprogramming/mobile/orm/test/domain/Account.java
new file mode 100644
index 0000000..1e03d79
--- /dev/null
+++ b/test/com/perfectworldprogramming/mobile/orm/test/domain/Account.java
@@ -0,0 +1,91 @@
+package com.perfectworldprogramming.mobile.orm.test.domain;
+
+import com.perfectworldprogramming.mobile.orm.annotations.Column;
+import com.perfectworldprogramming.mobile.orm.annotations.ColumnType;
+import com.perfectworldprogramming.mobile.orm.annotations.PrimaryKey;
+
+public class Account {
+
+ @PrimaryKey("ACCOUNT_ID")
+ private Long id;
+
+ @Column(value="ACCOUNT_TYPE", nullable=false, type=ColumnType.TEXT)
+ private String accountType;
+
+ @Column(value="AMOUNT", type=ColumnType.REAL)
+ private double amount;
+
+ @Column(value="YEAR_STARTED", type=ColumnType.INTEGER)
+ private int yearAccountOpened;
+
+ public Long getId() {
+ return id;
+ }
+
+ public String getAccountType() {
+ return accountType;
+ }
+
+ public void setAccountType(String accountType) {
+ this.accountType = accountType;
+ }
+
+ public double getAmount() {
+ return amount;
+ }
+
+ public void setAmount(double amount) {
+ this.amount = amount;
+ }
+
+ public int getYearAccountOpened() {
+ return yearAccountOpened;
+ }
+
+ public void setYearAccountOpened(int yearStarted) {
+ this.yearAccountOpened = yearStarted;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result
+ + ((accountType == null) ? 0 : accountType.hashCode());
+ long temp;
+ temp = Double.doubleToLongBits(amount);
+ result = prime * result + (int) (temp ^ (temp >>> 32));
+ result = prime * result + yearAccountOpened;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Account other = (Account) obj;
+ if (accountType == null) {
+ if (other.accountType != null)
+ return false;
+ } else if (!accountType.equals(other.accountType))
+ return false;
+ if (Double.doubleToLongBits(amount) != Double
+ .doubleToLongBits(other.amount))
+ return false;
+ if (yearAccountOpened != other.yearAccountOpened)
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "Account [id=" + id + ", accountType=" + accountType
+ + ", amount=" + amount + ", yearStarted=" + yearAccountOpened + "]";
+ }
+
+
+}
diff --git a/test/com/perfectworldprogramming/mobile/orm/test/domain/Address.java b/test/com/perfectworldprogramming/mobile/orm/test/domain/Address.java
new file mode 100644
index 0000000..2de31f1
--- /dev/null
+++ b/test/com/perfectworldprogramming/mobile/orm/test/domain/Address.java
@@ -0,0 +1,124 @@
+package com.perfectworldprogramming.mobile.orm.test.domain;
+
+import com.perfectworldprogramming.mobile.orm.annotations.Column;
+import com.perfectworldprogramming.mobile.orm.annotations.ColumnType;
+import com.perfectworldprogramming.mobile.orm.annotations.ForeignKey;
+import com.perfectworldprogramming.mobile.orm.annotations.PrimaryKey;
+
+/**
+ * User: Mark Spritzler
+ * Date: 3/14/11
+ * Time: 2:42 PM
+ */
+public class Address {
+
+ @PrimaryKey(value = "ADDRESS_ID")
+ private Long id;
+
+ @Column(value = "STREET", type = ColumnType.TEXT, nullable = false)
+ private String street;
+
+ @Column(value = "CITY", type = ColumnType.TEXT, nullable = false)
+ private String city;
+
+ @Column(value = "STATE", type = ColumnType.TEXT, nullable = false)
+ private String state;
+
+ @Column(value = "ZIP_CODE", type = ColumnType.TEXT, nullable = false)
+ private String zipCode;
+
+ @ForeignKey(value = "PERSON_ID")
+ private Person person;
+
+ public Address() {}
+
+ public Address(Long id) {
+ this.id = id;
+ }
+
+ public Address(String street, String city, String state, String zipCode, Person person) {
+ this.street = street;
+ this.city = city;
+ this.state = state;
+ this.zipCode = zipCode;
+ this.person = person;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public String getStreet() {
+ return street;
+ }
+
+ public void setStreet(String street) {
+ this.street = street;
+ }
+
+ public String getCity() {
+ return city;
+ }
+
+ public void setCity(String city) {
+ this.city = city;
+ }
+
+ public String getState() {
+ return state;
+ }
+
+ public void setState(String state) {
+ this.state = state;
+ }
+
+ public String getZipCode() {
+ return zipCode;
+ }
+
+ public void setZipCode(String zipCode) {
+ this.zipCode = zipCode;
+ }
+
+ public Person getPerson() {
+ return person;
+ }
+
+ public void setPerson(Person person) {
+ this.person = person;
+ }
+
+ @Override
+ public String toString() {
+ String address = "Id: " + id +
+ " Street: " + street +
+ " City: " + city +
+ " State: " + state +
+ " Zip Code: " + zipCode;
+ return address;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ Address address = (Address) o;
+
+ if (city != null ? !city.equals(address.city) : address.city != null) return false;
+ if (state != null ? !state.equals(address.state) : address.state != null) return false;
+ if (street != null ? !street.equals(address.street) : address.street != null) return false;
+ if (zipCode != null ? !zipCode.equals(address.zipCode) : address.zipCode != null) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = street != null ? street.hashCode() : 0;
+ result = 31 * result + (city != null ? city.hashCode() : 0);
+ result = 31 * result + (state != null ? state.hashCode() : 0);
+ result = 31 * result + (zipCode != null ? zipCode.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/test/com/perfectworldprogramming/mobile/orm/test/domain/NoPKDomain.java b/test/com/perfectworldprogramming/mobile/orm/test/domain/NoPKDomain.java
new file mode 100644
index 0000000..c49a8f3
--- /dev/null
+++ b/test/com/perfectworldprogramming/mobile/orm/test/domain/NoPKDomain.java
@@ -0,0 +1,43 @@
+package com.perfectworldprogramming.mobile.orm.test.domain;
+
+import com.perfectworldprogramming.mobile.orm.annotations.Column;
+import com.perfectworldprogramming.mobile.orm.annotations.ColumnType;
+import com.perfectworldprogramming.mobile.orm.annotations.ForeignKey;
+
+public class NoPKDomain {
+
+ @Column(value="value1", type=ColumnType.TEXT)
+ private String value1;
+
+ @Column(value="value1", type=ColumnType.TEXT)
+ private String value2;
+
+ @ForeignKey(value="PERSON_ID")
+ private Person person;
+
+ public String getValue1() {
+ return value1;
+ }
+
+ public void setValue1(String value1) {
+ this.value1 = value1;
+ }
+
+ public String getValue2() {
+ return value2;
+ }
+
+ public void setValue2(String value2) {
+ this.value2 = value2;
+ }
+
+ public Person getPerson() {
+ return person;
+ }
+
+ public void setPerson(Person person) {
+ this.person = person;
+ }
+
+
+}
diff --git a/test/com/perfectworldprogramming/mobile/orm/test/domain/Person.java b/test/com/perfectworldprogramming/mobile/orm/test/domain/Person.java
new file mode 100644
index 0000000..b3e21fd
--- /dev/null
+++ b/test/com/perfectworldprogramming/mobile/orm/test/domain/Person.java
@@ -0,0 +1,191 @@
+package com.perfectworldprogramming.mobile.orm.test.domain;
+
+import com.perfectworldprogramming.mobile.orm.annotations.Column;
+import com.perfectworldprogramming.mobile.orm.annotations.ColumnType;
+import com.perfectworldprogramming.mobile.orm.annotations.PrimaryKey;
+import com.perfectworldprogramming.mobile.orm.annotations.Transient;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * User: Mark Spritzler
+ * Date: 3/14/11
+ * Time: 2:42 PM
+ */
+public class Person {
+
+ @PrimaryKey(value = "PERSON_ID")
+ private Long id;
+
+ @Column(value = "FIRST_NAME", type = ColumnType.TEXT, nullable = false)
+ private String firstName;
+
+ @Column(value = "LAST_NAME", type = ColumnType.TEXT, nullable = false)
+ private String lastName;
+
+ @Column(value = "AGE", type = ColumnType.INTEGER, nullable = false)
+ private Integer age;
+
+ @Column(value = "HEIGHT", type = ColumnType.REAL)
+ private Double height;
+
+ @Column(value = "WEIGHT", type = ColumnType.REAL)
+ private Float weight;
+
+ @Column(value = "JACKET_SIZE", type = ColumnType.INTEGER)
+ private int jacketSize;
+
+ @Column(value = "SHOE_SIZE", type = ColumnType.REAL)
+ private float shoeSize;
+
+ @Column(value = "WEALTH", type = ColumnType.REAL)
+ private double wealth;
+
+
+
+ @Transient
+ private List addresses;
+
+ public Person() {}
+
+ public Person(Long id) {
+ this.id = id;
+ }
+
+ public Person(String firstName, String lastName, int age, Double height) {
+ this.firstName = firstName;
+ this.lastName = lastName;
+ this.age = age;
+ this.height = height;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public String getFirstName() {
+ return firstName;
+ }
+
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+
+ public String getLastName() {
+ return lastName;
+ }
+
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
+ }
+
+ public Integer getAge() {
+ return age;
+ }
+
+ public void setAge(Integer age) {
+ this.age = age;
+ }
+
+ public Double getHeight() {
+ return height;
+ }
+
+ public void setHeight(Double height) {
+ this.height = height;
+ }
+
+ public Float getWeight() {
+ return weight;
+ }
+
+ public void setWeight(Float weight) {
+ this.weight = weight;
+ }
+
+ public int getJacketSize() {
+ return jacketSize;
+ }
+
+ public void setJacketSize(int jacketSize) {
+ this.jacketSize = jacketSize;
+ }
+
+ public float getShoeSize() {
+ return shoeSize;
+ }
+
+ public void setShoeSize(float shoeSize) {
+ this.shoeSize = shoeSize;
+ }
+
+ public double getWealth() {
+ return wealth;
+ }
+
+ public void setWealth(double wealth) {
+ this.wealth = wealth;
+ }
+
+ public List getAddresses() {
+ return addresses;
+ }
+
+ public void setAddresses(List addresses) {
+ this.addresses = addresses;
+ }
+
+ public void addAddress(Address address) {
+ if (addresses == null) {
+ this.addresses = new ArrayList();
+ }
+ this.addresses.add(address);
+ address.setPerson(this);
+ }
+
+ @Override
+ public String toString() {
+ String person = "Id: " + id +
+ " First Name: " + firstName +
+ " Last Name: " + lastName +
+ " Age: " + age +
+ " Height: " + height +
+ " Weight: " + weight +
+ " Jacket Size: " + jacketSize +
+ " Shoe Size: " + shoeSize +
+ " Wealth: " + wealth;
+ if (addresses != null && addresses.size() > 0) {
+ String stringOfAddresses = "\t Addresses: \n";
+ for (Address address : addresses) {
+ stringOfAddresses += "\tt " + address;
+ }
+ person += stringOfAddresses;
+ }
+ return person;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ Person person = (Person) o;
+
+ if (age != person.age) return false;
+ if (firstName != null ? !firstName.equals(person.firstName) : person.firstName != null) return false;
+ if (height != null ? !height.equals(person.height) : person.height != null) return false;
+ if (lastName != null ? !lastName.equals(person.lastName) : person.lastName != null) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = firstName != null ? firstName.hashCode() : 0;
+ result = 31 * result + (lastName != null ? lastName.hashCode() : 0);
+ result = 31 * result + age;
+ result = 31 * result + (height != null ? height.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/test/com/perfectworldprogramming/mobile/orm/test/domain/WrongTypeMappedDomain.java b/test/com/perfectworldprogramming/mobile/orm/test/domain/WrongTypeMappedDomain.java
new file mode 100644
index 0000000..1dfb715
--- /dev/null
+++ b/test/com/perfectworldprogramming/mobile/orm/test/domain/WrongTypeMappedDomain.java
@@ -0,0 +1,5 @@
+package com.perfectworldprogramming.mobile.orm.test.domain;
+
+public class WrongTypeMappedDomain {
+
+}
diff --git a/test/com/perfectworldprogramming/mobile/orm/test/helper/AndroidSQLLiteOpenHelperTest.java b/test/com/perfectworldprogramming/mobile/orm/test/helper/AndroidSQLLiteOpenHelperTest.java
new file mode 100644
index 0000000..3ebd499
--- /dev/null
+++ b/test/com/perfectworldprogramming/mobile/orm/test/helper/AndroidSQLLiteOpenHelperTest.java
@@ -0,0 +1,48 @@
+package com.perfectworldprogramming.mobile.orm.test.helper;
+
+
+import com.perfectworldprogramming.mobile.orm.helper.AndroidSQLLiteOpenHelper;
+import com.perfectworldprogramming.mobile.orm.test.Main;
+import com.perfectworldprogramming.mobile.orm.test.domain.Account;
+import com.perfectworldprogramming.mobile.orm.test.domain.Address;
+import com.perfectworldprogramming.mobile.orm.test.domain.Person;
+
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+import android.test.ActivityInstrumentationTestCase2;
+
+/**
+ * User: Mark Spritzler
+ * Date: 5/4/11
+ * Time: 6:22 PM
+ */
+public class AndroidSQLLiteOpenHelperTest extends ActivityInstrumentationTestCase2 {
+ AndroidSQLLiteOpenHelper helper;
+
+ public AndroidSQLLiteOpenHelperTest() {
+ super("org.springframework.mobile.orm.test", Main.class);
+ }
+
+ @SuppressWarnings("unchecked")
+ public void setUp() {
+ try {
+ super.setUp();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ Context ctx = this.getInstrumentation().getContext();
+ helper = new AndroidSQLLiteOpenHelper(ctx, new Class[]{Person.class, Address.class, Account.class}, "ormtest", 3);
+ }
+
+ public void testGetWritableDatabase() {
+ SQLiteDatabase db = helper.getWritableDatabase();
+ assertNotNull(db);
+ int version = db.getVersion();
+ assertEquals("", 3, version);
+ }
+
+ public void tearDown() {
+ helper.close();
+ }
+
+}
diff --git a/test/com/perfectworldprogramming/mobile/orm/test/helper/DBHelperTests.java b/test/com/perfectworldprogramming/mobile/orm/test/helper/DBHelperTests.java
new file mode 100644
index 0000000..89f433d
--- /dev/null
+++ b/test/com/perfectworldprogramming/mobile/orm/test/helper/DBHelperTests.java
@@ -0,0 +1,42 @@
+package com.perfectworldprogramming.mobile.orm.test.helper;
+
+
+import com.perfectworldprogramming.mobile.orm.helper.DBHelper;
+import com.perfectworldprogramming.mobile.orm.test.Main;
+import com.perfectworldprogramming.mobile.orm.test.domain.Account;
+import com.perfectworldprogramming.mobile.orm.test.domain.Address;
+import com.perfectworldprogramming.mobile.orm.test.domain.Person;
+
+import android.database.sqlite.SQLiteDatabase;
+import android.test.ActivityInstrumentationTestCase2;
+
+/**
+ * User: Mark Spritzler
+ * Date: 3/14/11
+ * Time: 9:24 PM
+ */
+public class DBHelperTests extends ActivityInstrumentationTestCase2 {
+ DBHelper helper;
+
+ public DBHelperTests() {
+ super("org.springframework.mobile.orm.test", Main.class);
+ }
+
+ @SuppressWarnings("unchecked")
+ public void setUp() {
+ try {
+ super.setUp();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ helper = new DBHelper(this.getInstrumentation().getContext(), new Class[]{Person.class, Address.class, Account.class}, "ormtest", 3);
+ }
+
+ //@Test
+ public void testStartDBTests() {
+ SQLiteDatabase db = helper.getSqlLiteDatabase();
+ assertNotNull(db);
+ int version = db.getVersion();
+ assertEquals("", 3, version);
+ }
+}
diff --git a/test/com/perfectworldprogramming/mobile/orm/test/interfaces/AddressCursorExtractor.java b/test/com/perfectworldprogramming/mobile/orm/test/interfaces/AddressCursorExtractor.java
new file mode 100644
index 0000000..61c5ae1
--- /dev/null
+++ b/test/com/perfectworldprogramming/mobile/orm/test/interfaces/AddressCursorExtractor.java
@@ -0,0 +1,49 @@
+package com.perfectworldprogramming.mobile.orm.test.interfaces;
+
+
+import com.perfectworldprogramming.mobile.orm.interfaces.CursorExtractor;
+import com.perfectworldprogramming.mobile.orm.test.domain.Address;
+import com.perfectworldprogramming.mobile.orm.test.domain.Person;
+
+import android.database.Cursor;
+
+/**
+ * User: Mark Spritzler
+ * Date: 4/7/11
+ * Time: 11:47 AM
+ */
+public class AddressCursorExtractor implements CursorExtractor {
+
+ private static final String PERSON_ID = "PERSON_ID";
+ private static final String FIRST_NAME = "FIRST_NAME";
+ private static final String LAST_NAME = "LAST_NAME";
+ private static final String HEIGHT = "HEIGHT";
+ private static final String AGE = "AGE";
+ private static final String ADDRESS_ID = "ADDRESS_ID";
+ private static final String STREET = "STREET";
+ private static final String CITY = "CITY";
+ private static final String STATE = "STATE";
+ private static final String ZIP_CODE = "ZIP_CODE";
+
+ @Override
+ public Address extractData(Cursor cursor) {
+ Address address = null;
+ if (cursor != null) {
+ if (cursor.moveToFirst()) {
+ address = new Address(cursor.getLong(cursor.getColumnIndex(ADDRESS_ID)));
+ address.setCity(cursor.getString(cursor.getColumnIndex(CITY)));
+ address.setState(cursor.getString(cursor.getColumnIndex(STATE)));
+ address.setStreet(cursor.getString(cursor.getColumnIndex(STREET)));
+ address.setZipCode(cursor.getString(cursor.getColumnIndex(ZIP_CODE)));
+ Person person = new Person(cursor.getLong(cursor.getColumnIndex(PERSON_ID)));
+ person.setFirstName(cursor.getString(cursor.getColumnIndex(FIRST_NAME)));
+ person.setLastName(cursor.getString(cursor.getColumnIndex(LAST_NAME)));
+ person.setHeight(cursor.getDouble(cursor.getColumnIndex(HEIGHT)));
+ person.setAge(cursor.getInt(cursor.getColumnIndex(AGE)));
+ address.setPerson(person);
+ }
+ }
+
+ return address;
+ }
+}
diff --git a/test/com/perfectworldprogramming/mobile/orm/test/interfaces/AddressCursorRowMapper.java b/test/com/perfectworldprogramming/mobile/orm/test/interfaces/AddressCursorRowMapper.java
new file mode 100644
index 0000000..eb64184
--- /dev/null
+++ b/test/com/perfectworldprogramming/mobile/orm/test/interfaces/AddressCursorRowMapper.java
@@ -0,0 +1,31 @@
+package com.perfectworldprogramming.mobile.orm.test.interfaces;
+
+
+import com.perfectworldprogramming.mobile.orm.interfaces.CursorRowMapper;
+import com.perfectworldprogramming.mobile.orm.test.domain.Address;
+
+import android.database.Cursor;
+
+/**
+ * User: Mark Spritzler
+ * Date: 4/6/11
+ * Time: 10:55 AM
+ */
+public class AddressCursorRowMapper implements CursorRowMapper {
+
+ private static final String ID = "ADDRESS_ID";
+ private static final String STREET = "STREET";
+ private static final String CITY = "CITY";
+ private static final String STATE = "STATE";
+ private static final String ZIP_CODE = "ZIP_CODE";
+
+ @Override
+ public Address mapRow(Cursor cursor, int rowNum) {
+ Address address = new Address(cursor.getLong(cursor.getColumnIndex(ID)));
+ address.setCity(cursor.getString(cursor.getColumnIndex(CITY)));
+ address.setState(cursor.getString(cursor.getColumnIndex(STATE)));
+ address.setStreet(cursor.getString(cursor.getColumnIndex(STREET)));
+ address.setZipCode(cursor.getString(cursor.getColumnIndex(ZIP_CODE)));
+ return address;
+ }
+}
diff --git a/test/com/perfectworldprogramming/mobile/orm/test/interfaces/CursorExtractorTests.java b/test/com/perfectworldprogramming/mobile/orm/test/interfaces/CursorExtractorTests.java
new file mode 100644
index 0000000..33aeb43
--- /dev/null
+++ b/test/com/perfectworldprogramming/mobile/orm/test/interfaces/CursorExtractorTests.java
@@ -0,0 +1,73 @@
+package com.perfectworldprogramming.mobile.orm.test.interfaces;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+import com.perfectworldprogramming.mobile.orm.AndroidSQLiteTemplate;
+import com.perfectworldprogramming.mobile.orm.helper.DBHelper;
+import com.perfectworldprogramming.mobile.orm.test.Main;
+import com.perfectworldprogramming.mobile.orm.test.domain.Account;
+import com.perfectworldprogramming.mobile.orm.test.domain.Address;
+import com.perfectworldprogramming.mobile.orm.test.domain.Person;
+
+import android.test.ActivityInstrumentationTestCase2;
+
+/**
+ * User: Mark Spritzler
+ * Date: 4/6/11
+ * Time: 10:50 AM
+ */
+// TODO need negative path tests
+public class CursorExtractorTests extends ActivityInstrumentationTestCase2 {
+
+ AndroidSQLiteTemplate template;
+ List samplePeople = new ArrayList();
+ List sampleAddress = new ArrayList();
+ DBHelper helper;
+
+ public CursorExtractorTests() {
+ super("org.springframework.mobile.orm.test", Main.class);
+ }
+
+ @SuppressWarnings("unchecked")
+ public void setUp() {
+ try {
+ super.setUp();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ helper = new DBHelper(this.getInstrumentation().getContext(), new Class[]{Person.class, Address.class, Account.class}, "ormtest", 3);
+ template = new AndroidSQLiteTemplate(helper.getSqlLiteDatabase());
+ SampleDataHelper.addDataToDatabase(template);
+ }
+
+ public void testSuccessfulPersonExtractor() {
+ String sql = "SELECT * from PERSON p, ADDRESS a where a.PERSON_ID = p.PERSON_ID and p.FIRST_NAME = '?'";
+ Person person = template.queryForObject(sql, new PersonCursorExtractor(), "John");
+ assertNotNull(person);
+ assertEquals(new Integer(42), person.getAge());
+ assertEquals("John", person.getFirstName());
+ assertEquals("Doe", person.getLastName());
+ assertEquals(new Double("5.1d"), person.getHeight());
+ List addresses = person.getAddresses();
+ assertNotNull(addresses);
+ assertEquals(2, addresses.size());
+ }
+
+ public void testSuccessfulAddressExtractor() {
+ String sql = "SELECT * from ADDRESS a, PERSON p where a.PERSON_ID = p.PERSON_ID and a.ZIP_CODE='?'";
+ Address address = template.queryForObject(sql, new AddressCursorExtractor(), "12345");
+ assertNotNull(address);
+ assertEquals("Philadelphia", address.getCity());
+ assertEquals("PA", address.getState());
+ assertEquals("123 Broad Street", address.getStreet());
+ assertEquals("12345", address.getZipCode());
+ Person person = address.getPerson();
+ assertNotNull(person);
+ assertEquals(new Integer(42), person.getAge());
+ assertEquals("John", person.getFirstName());
+ assertEquals("Doe", person.getLastName());
+ assertEquals(new Double("5.1d"), person.getHeight());
+ }
+}
diff --git a/test/com/perfectworldprogramming/mobile/orm/test/interfaces/CursorRowMapperTests.java b/test/com/perfectworldprogramming/mobile/orm/test/interfaces/CursorRowMapperTests.java
new file mode 100644
index 0000000..564e3a8
--- /dev/null
+++ b/test/com/perfectworldprogramming/mobile/orm/test/interfaces/CursorRowMapperTests.java
@@ -0,0 +1,135 @@
+package com.perfectworldprogramming.mobile.orm.test.interfaces;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+import com.perfectworldprogramming.mobile.orm.AndroidSQLiteTemplate;
+import com.perfectworldprogramming.mobile.orm.exception.ExtraResultsException;
+import com.perfectworldprogramming.mobile.orm.helper.DBHelper;
+import com.perfectworldprogramming.mobile.orm.test.Main;
+import com.perfectworldprogramming.mobile.orm.test.domain.Account;
+import com.perfectworldprogramming.mobile.orm.test.domain.Address;
+import com.perfectworldprogramming.mobile.orm.test.domain.Person;
+
+import android.test.ActivityInstrumentationTestCase2;
+
+/**
+ * User: Mark Spritzler
+ * Date: 4/6/11
+ * Time: 10:50 AM
+ */
+public class CursorRowMapperTests extends ActivityInstrumentationTestCase2 {
+
+
+ public CursorRowMapperTests() {
+ super("org.springframework.mobile.orm.test", Main.class);
+ }
+
+ AndroidSQLiteTemplate template;
+ List samplePeople = new ArrayList();
+ List sampleAddress = new ArrayList();
+
+ @SuppressWarnings("unchecked")
+ public void setUp() {
+ try {
+ super.setUp();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ DBHelper helper = new DBHelper(this.getInstrumentation().getContext(), new Class[]{Person.class, Address.class, Account.class}, "ormtest", 3);
+ template = new AndroidSQLiteTemplate(helper.getSqlLiteDatabase());
+ SampleDataHelper.addDataToDatabase(template);
+ }
+
+ // Address tests first
+ public void testSuccessfulAddressMapperTest() {
+ List addresses = template.query("Select * from ADDRESS", new AddressCursorRowMapper());
+ assertNotNull(addresses);
+ assertEquals(2, addresses.size());
+ for (Address address : sampleAddress) {
+ assertTrue(addresses.contains(address));
+ }
+ }
+
+ public void testAddressQueryWithNoResultsTest () {
+ List addresses = template.query("Select * from ADDRESS where 1=2", new AddressCursorRowMapper());
+ assertNotNull(addresses);
+ assertEquals(0, addresses.size());
+ }
+
+ public void testAddressSingleObjectSuccessTest () {
+ Address address = template.queryForObject("Select * from ADDRESS where ZIP_CODE='?'", new AddressCursorRowMapper(), "12345");
+ assertNotNull(address);
+ assertEquals("Philadelphia", address.getCity());
+ assertEquals("PA", address.getState());
+ assertEquals("123 Broad Street", address.getStreet());
+ assertEquals("12345", address.getZipCode());
+ }
+
+ //@Test(expected = ExtraResultsException.class)
+ public void testAddressSingleObjectReturnsNoResultsTest() {
+ try {
+ template.queryForObject("Select * from ADDRESS where ZIP_CODE='?'", new AddressCursorRowMapper(), "98765");
+ fail("This test should have thrown an ExtraResultsException stating that 0 rows were returned when expecting 1");
+ } catch (ExtraResultsException ere) {
+ String numberOfResults = "0";
+ assertEquals("Expected one row returned by query but received " + numberOfResults, ere.getMessage());
+ }
+ }
+
+ //@Test(expected = ExtraResultsException.class)
+ public void testAddressSingleObjectReturnsTwoRowsTest() {
+ try {
+ template.queryForObject("Select * from ADDRESS", new AddressCursorRowMapper());
+ } catch (ExtraResultsException ere) {
+ String numberOfResults = "2";
+ assertEquals("Expected one row returned by query but received " + numberOfResults, ere.getMessage());
+ }
+ }
+
+ // Person tests second
+ public void testSuccessfulPersonMapperTest() {
+ List persons = template.query("Select * from PERSON", new PersonCursorRowMapper());
+ assertNotNull(persons);
+ assertEquals(2, persons.size());
+ for (Person person : samplePeople) {
+ assertTrue(persons.contains(person));
+ }
+ }
+
+ public void testPersonQueryWithNoResultsTest () {
+ List persons = template.query("Select * from ADDRESS where 1=2", new PersonCursorRowMapper());
+ assertNotNull(persons);
+ assertEquals(0, persons.size());
+ }
+
+ public void testPersonSingleObjectSuccessTest () {
+ Person person = template.queryForObject("Select * from PERSON where FIRST_NAME='?'", new PersonCursorRowMapper(), "John");
+ assertNotNull(person);
+ assertEquals(new Integer(42), person.getAge());
+ assertEquals("John", person.getFirstName());
+ assertEquals("Doe", person.getLastName());
+ assertEquals(new Double("5.1d"), person.getHeight());
+ }
+
+ //@Test(expected = ExtraResultsException.class)
+ public void testPersonSingleObjectReturnsNoResultsTest() {
+ try {
+ template.queryForObject("Select * from PERSON where FIRST_NAME='?' and AGE=?", new PersonCursorRowMapper(), "George", 37);
+ } catch (ExtraResultsException ere) {
+ String numberOfResults = "0";
+ assertEquals("Expected one row returned by query but received " + numberOfResults, ere.getMessage());
+ }
+ }
+
+ //@Test(expected = ExtraResultsException.class)
+ public void testPersonSingleObjectReturnsTwoRowsTest() {
+ try {
+ template.queryForObject("Select * from PERSON", new PersonCursorRowMapper());
+ } catch (ExtraResultsException ere) {
+ String numberOfResults = "2";
+ assertEquals("Expected one row returned by query but received " + numberOfResults, ere.getMessage());
+ }
+ }
+}
diff --git a/test/com/perfectworldprogramming/mobile/orm/test/interfaces/PersonCursorExtractor.java b/test/com/perfectworldprogramming/mobile/orm/test/interfaces/PersonCursorExtractor.java
new file mode 100644
index 0000000..fa75cea
--- /dev/null
+++ b/test/com/perfectworldprogramming/mobile/orm/test/interfaces/PersonCursorExtractor.java
@@ -0,0 +1,50 @@
+package com.perfectworldprogramming.mobile.orm.test.interfaces;
+
+import android.database.Cursor;
+
+
+import com.perfectworldprogramming.mobile.orm.interfaces.CursorExtractor;
+import com.perfectworldprogramming.mobile.orm.test.domain.Address;
+import com.perfectworldprogramming.mobile.orm.test.domain.Person;
+
+/**
+ * User: Mark Spritzler
+ * Date: 4/6/11
+ * Time: 4:21 PM
+ */
+public class PersonCursorExtractor implements CursorExtractor {
+
+ private static final String PERSON_ID = "PERSON_ID";
+ private static final String FIRST_NAME = "FIRST_NAME";
+ private static final String LAST_NAME = "LAST_NAME";
+ private static final String HEIGHT = "HEIGHT";
+ private static final String AGE = "AGE";
+ private static final String ADDRESS_ID = "ADDRESS_ID";
+ private static final String STREET = "STREET";
+ private static final String CITY = "CITY";
+ private static final String STATE = "STATE";
+ private static final String ZIP_CODE = "ZIP_CODE";
+
+ @Override
+ public Person extractData(Cursor cursor) {
+ Person person = null;
+ if (cursor != null) {
+ if (cursor.moveToFirst()) {
+ person = new Person(cursor.getLong(cursor.getColumnIndex(PERSON_ID)));
+ person.setFirstName(cursor.getString(cursor.getColumnIndex(FIRST_NAME)));
+ person.setLastName(cursor.getString(cursor.getColumnIndex(LAST_NAME)));
+ person.setHeight(cursor.getDouble(cursor.getColumnIndex(HEIGHT)));
+ person.setAge(cursor.getInt(cursor.getColumnIndex(AGE)));
+ do {
+ Address address = new Address(cursor.getLong(cursor.getColumnIndex(ADDRESS_ID)));
+ address.setCity(cursor.getString(cursor.getColumnIndex(CITY)));
+ address.setState(cursor.getString(cursor.getColumnIndex(STATE)));
+ address.setStreet(cursor.getString(cursor.getColumnIndex(STREET)));
+ address.setZipCode(cursor.getString(cursor.getColumnIndex(ZIP_CODE)));
+ person.addAddress(address);
+ } while (cursor.moveToNext());
+ }
+ }
+ return person;
+ }
+}
diff --git a/test/com/perfectworldprogramming/mobile/orm/test/interfaces/PersonCursorRowMapper.java b/test/com/perfectworldprogramming/mobile/orm/test/interfaces/PersonCursorRowMapper.java
new file mode 100644
index 0000000..be9e21a
--- /dev/null
+++ b/test/com/perfectworldprogramming/mobile/orm/test/interfaces/PersonCursorRowMapper.java
@@ -0,0 +1,31 @@
+package com.perfectworldprogramming.mobile.orm.test.interfaces;
+
+
+import com.perfectworldprogramming.mobile.orm.interfaces.CursorRowMapper;
+import com.perfectworldprogramming.mobile.orm.test.domain.Person;
+
+import android.database.Cursor;
+
+/**
+ * User: Mark Spritzler
+ * Date: 4/6/11
+ * Time: 10:50 AM
+ */
+public class PersonCursorRowMapper implements CursorRowMapper {
+
+ private static final String ID = "PERSON_ID";
+ private static final String FIRST_NAME = "FIRST_NAME";
+ private static final String LAST_NAME = "LAST_NAME";
+ private static final String HEIGHT = "HEIGHT";
+ private static final String AGE = "AGE";
+
+ @Override
+ public Person mapRow(Cursor cursor, int rowNum) {
+ Person person = new Person(cursor.getLong(cursor.getColumnIndex(ID)));
+ person.setFirstName(cursor.getString(cursor.getColumnIndex(FIRST_NAME)));
+ person.setLastName(cursor.getString(cursor.getColumnIndex(LAST_NAME)));
+ person.setHeight(cursor.getDouble(cursor.getColumnIndex(HEIGHT)));
+ person.setAge(cursor.getInt(cursor.getColumnIndex(AGE)));
+ return person;
+ }
+}
diff --git a/test/com/perfectworldprogramming/mobile/orm/test/interfaces/SampleDataHelper.java b/test/com/perfectworldprogramming/mobile/orm/test/interfaces/SampleDataHelper.java
new file mode 100644
index 0000000..08c1f24
--- /dev/null
+++ b/test/com/perfectworldprogramming/mobile/orm/test/interfaces/SampleDataHelper.java
@@ -0,0 +1,167 @@
+package com.perfectworldprogramming.mobile.orm.test.interfaces;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+import com.perfectworldprogramming.mobile.orm.AndroidSQLiteTemplate;
+import com.perfectworldprogramming.mobile.orm.test.domain.Account;
+import com.perfectworldprogramming.mobile.orm.test.domain.Address;
+import com.perfectworldprogramming.mobile.orm.test.domain.Person;
+
+/**
+ * User: Mark Spritzler
+ * Date: 4/6/11
+ * Time: 11:11 AM
+ */
+public class SampleDataHelper {
+
+ private static List sampleAccounts;
+
+ public static void addDataToDatabase(AndroidSQLiteTemplate template) {
+ int addressCount = template.queryForInt("Select count(*) from Address");
+ int personCount = template.queryForInt("Select count(*) from Person");
+ int accountCount = template.queryForInt("Select count(*) from Account");
+ if (addressCount > 0) {
+ template.delete("DELETE FROM Address", (Object[])null);
+ }
+ if (personCount > 0) {
+ template.delete("DELETE FROM Person", (Object[])null);
+ }
+ if (accountCount > 0) {
+ template.delete("DELETE FROM Account", (Object[])null);
+ }
+ List sampleAddress = createAddresses();
+ List samplePeople = createPeople();
+ sampleAccounts = createAccounts();
+
+ Person person1 = samplePeople.get(0);
+ for (Address address : sampleAddress) {
+ person1.addAddress(address);
+ }
+
+ for (Person person : samplePeople) {
+ template.insert(person);
+ }
+
+ for (Address address : sampleAddress) {
+ template.insert(address);
+ }
+
+ for (Account account : sampleAccounts) {
+ template.insert(account);
+ }
+
+ }
+
+ public static List getAccounts() {
+ return sampleAccounts;
+ }
+
+ private static List createAddresses() {
+ List sampleAddress = new ArrayList();
+ Address address1 = new Address();
+ address1.setZipCode("90808");
+ address1.setCity("Long Beach");
+ address1.setState("CA");
+ address1.setStreet("123 Elm Street");
+ sampleAddress.add(address1);
+
+ Address address2 = new Address();
+ address2.setZipCode("12345");
+ address2.setCity("Philadelphia");
+ address2.setState("PA");
+ address2.setStreet("123 Broad Street");
+ sampleAddress.add(address2);
+ return sampleAddress;
+ }
+
+ private static List createPeople() {
+ List samplePeople = new ArrayList();
+ Person person1 = new Person();
+ person1.setAge(42);
+ person1.setFirstName("John");
+ person1.setLastName("Doe");
+ person1.setHeight(5.1d);
+ person1.setWeight(175.6f);
+ person1.setJacketSize(43);
+ person1.setShoeSize(9.5f);
+ person1.setWealth(210000.00d);
+ samplePeople.add(person1);
+
+ Person person2 = new Person();
+ person2.setAge(21);
+ person2.setHeight(6.2d);
+ person2.setFirstName("Bill");
+ person2.setLastName("Smith");
+ person1.setWeight(225.6f);
+ person1.setJacketSize(48);
+ person1.setShoeSize(12.5f);
+ person1.setWealth(10000.00d);
+ samplePeople.add(person2);
+
+ return samplePeople;
+ }
+
+ private static List createAccounts() {
+ List accounts = new ArrayList();
+ //For successful delete
+ Account account1 = new Account();
+ account1.setAccountType("Personal");
+ account1.setAmount(23.00d);
+ account1.setYearAccountOpened(1989);
+ accounts.add(account1);
+
+ //For successful delete
+ Account account2 = new Account();
+ account2.setAccountType("Business");
+ account2.setAmount(560000.00d);
+ account2.setYearAccountOpened(1990);
+ accounts.add(account2);
+
+ // for successful delete
+ Account account3 = new Account();
+ account3.setAccountType("Business");
+ account3.setAmount(475.60d);
+ account3.setYearAccountOpened(1991);
+ accounts.add(account3);
+
+ // for successful delete
+ Account account4 = new Account();
+ account4.setAccountType("Business");
+ account4.setAmount(4200.00d);
+ account4.setYearAccountOpened(2000);
+ accounts.add(account4);
+
+ // for successful update
+ Account account5 = new Account();
+ account5.setAccountType("Business Plus");
+ account5.setAmount(4200.00d);
+ account5.setYearAccountOpened(2001);
+ accounts.add(account5);
+
+ // for successful update
+ Account account6 = new Account();
+ account6.setAccountType("Personal Plus");
+ account6.setAmount(4200.00d);
+ account6.setYearAccountOpened(2002);
+ accounts.add(account6);
+
+ // for successful update
+ Account account7 = new Account();
+ account7.setAccountType("Personal Plus");
+ account7.setAmount(4200.00d);
+ account7.setYearAccountOpened(2003);
+ accounts.add(account7);
+
+ // for successful update
+ Account account8 = new Account();
+ account8.setAccountType("Business Plus");
+ account8.setAmount(4200.00d);
+ account8.setYearAccountOpened(2011);
+ accounts.add(account8);
+
+ return accounts;
+ }
+
+}
diff --git a/test/com/perfectworldprogramming/mobile/orm/test/reflection/DomainClassAnalyzerTests.java b/test/com/perfectworldprogramming/mobile/orm/test/reflection/DomainClassAnalyzerTests.java
new file mode 100644
index 0000000..b325059
--- /dev/null
+++ b/test/com/perfectworldprogramming/mobile/orm/test/reflection/DomainClassAnalyzerTests.java
@@ -0,0 +1,136 @@
+package com.perfectworldprogramming.mobile.orm.test.reflection;
+
+import java.lang.reflect.Field;
+
+
+import com.perfectworldprogramming.mobile.orm.annotations.PrimaryKey;
+import com.perfectworldprogramming.mobile.orm.reflection.DomainClassAnalyzer;
+import com.perfectworldprogramming.mobile.orm.test.Main;
+import com.perfectworldprogramming.mobile.orm.test.domain.Address;
+import com.perfectworldprogramming.mobile.orm.test.domain.Person;
+
+import android.content.ContentValues;
+import android.test.ActivityInstrumentationTestCase2;
+
+/**
+ * User: Mark Spritzler
+ * Date: 3/14/11
+ * Time: 5:57 PM
+ */
+public class DomainClassAnalyzerTests extends ActivityInstrumentationTestCase2 {
+ DomainClassAnalyzer domainClassAnalyzer = new DomainClassAnalyzer();
+
+ public DomainClassAnalyzerTests() {
+ super("org.springframework.mobile.orm.test", Main.class);
+ }
+
+ public void setUp() {
+ try {
+ super.setUp();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void testGetPrimaryKeyFieldTest() {
+ Field field = domainClassAnalyzer.getPrimaryKeyField(Person.class);
+ assertNotNull("primary key field should not be null", field);
+ assertEquals("", Long.class, field.getType());
+ }
+
+ public void testGetPrimaryKeyNameTest() {
+ String primaryKeyName = domainClassAnalyzer.getPrimaryKeyFieldName(Person.class);
+ assertEquals("primary key name should be PERSON_ID", "PERSON_ID", primaryKeyName);
+ primaryKeyName = domainClassAnalyzer.getPrimaryKeyFieldName(Address.class);
+ assertEquals("primary key name should be ADDRESS_ID", "ADDRESS_ID", primaryKeyName);
+ }
+
+ public void testGetPrimaryKeyTest() {
+ PrimaryKey primaryKey = domainClassAnalyzer.getPrimaryKey(Person.class);
+ assertNotNull("primary key annotation should be found", primaryKey);
+ }
+
+ public void testGetForeignKeyFieldsTest() {
+ Field[] personForeignKeyFields = domainClassAnalyzer.getForeignKeyFields(Person.class);
+ assertEquals("", 0, personForeignKeyFields.length);
+ Field[] addressForeignKeyFields = domainClassAnalyzer.getForeignKeyFields(Address.class);
+ assertEquals("", 1, addressForeignKeyFields.length);
+ }
+
+ public void testGetIdFromObjectTest() {
+ Address address = getTestAddress();
+ Long id = domainClassAnalyzer.getIdFromObject(address);
+ assertNotNull("id should not be null", id);
+ assertEquals("id for address should be 15", new Long(15), id);
+ Person person = getTestPerson();
+ id = domainClassAnalyzer.getIdFromObject(person);
+ assertNotNull("id should not be null", id);
+ assertEquals("id for person should be 100", new Long(100), id);
+ }
+
+ public void testCreateContentValuesTest() {
+ ContentValues personValues = domainClassAnalyzer.createContentValues(getTestPerson());
+ assertNotNull(personValues);
+ ContentValues addressValues = domainClassAnalyzer.createContentValues(getTestAddress());
+ assertNotNull(addressValues);
+ }
+
+ private Person getTestPerson() {
+ Person person = new Person();
+ person.setAge(42);
+ person.setFirstName("George");
+ person.setHeight(5.10);
+ person.setLastName("Jetson");
+ person.addAddress(getTestAddressForPerson(person));
+ try {
+ Field field = person.getClass().getDeclaredField("id");
+ field.setAccessible(true);
+ field.set(person, new Long(100));
+ } catch (NoSuchFieldException e) {
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ return person;
+ }
+
+ private Address getTestAddress() {
+ Address address = new Address();
+ address.setCity("Long Beach");
+ Person person = getTestPerson();
+ person.addAddress(address);
+ address.setPerson(person);
+ address.setState("CA");
+ address.setStreet("123 Elm Street");
+ address.setZipCode("90808");
+ try {
+ Field field = address.getClass().getDeclaredField("id");
+ field.setAccessible(true);
+ field.set(address, 15l);
+ } catch (NoSuchFieldException e) {
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ return address;
+ }
+
+ private Address getTestAddressForPerson(Person person) {
+ Address address = new Address();
+ address.setCity("Long Beach");
+ address.setPerson(person);
+ address.setState("CA");
+ address.setStreet("123 Elm Street");
+ address.setZipCode("90808");
+ try {
+ Field field = address.getClass().getDeclaredField("id");
+ field.setAccessible(true);
+ field.set(address, 16l);
+ } catch (NoSuchFieldException e) {
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ return address;
+ }
+}