From 7b20733f1d992a278a4ed6d3864d9690e589cc7e Mon Sep 17 00:00:00 2001 From: Mark Spritzler Date: Thu, 27 Oct 2011 20:47:35 -0500 Subject: [PATCH] Get all the files commited --- .classpath | 2 +- .gitignore | 18 + AndroidManifest.xml | 10 +- README | 15 + bin/classes.dex | Bin 0 -> 70888 bytes .../mobile/orm/AndroidSQLiteTemplate.class | Bin 0 -> 13904 bytes .../mobile/orm/CursorAdapter.class | Bin 0 -> 8990 bytes .../mobile/orm/Main.class | Bin 0 -> 966 bytes .../mobile/orm/R$attr.class | Bin 0 -> 400 bytes .../mobile/orm/R$drawable.class | Bin 0 -> 460 bytes .../mobile/orm/R$layout.class | Bin 0 -> 454 bytes .../mobile/orm/R$string.class | Bin 0 -> 487 bytes .../mobile/orm/R.class | Bin 0 -> 609 bytes .../mobile/orm/annotations/Column.class | Bin 0 -> 827 bytes .../mobile/orm/annotations/ColumnSetter.class | Bin 0 -> 489 bytes .../mobile/orm/annotations/ColumnType.class | Bin 0 -> 1315 bytes .../mobile/orm/annotations/ForeignKey.class | Bin 0 -> 598 bytes .../mobile/orm/annotations/PrimaryKey.class | Bin 0 -> 598 bytes .../mobile/orm/annotations/Transient.class | Bin 0 -> 461 bytes .../creator/CreateStatementGenerator.class | Bin 0 -> 480 bytes .../SQLLiteCreateStatementGenerator.class | Bin 0 -> 6959 bytes .../orm/exception/DataAccessException.class | Bin 0 -> 514 bytes .../EmptySQLStatementException.class | Bin 0 -> 600 bytes .../orm/exception/ExtraResultsException.class | Bin 0 -> 761 bytes .../InvalidCursorExtractorException.class | Bin 0 -> 1226 bytes .../InvalidCursorRowMapperException.class | Bin 0 -> 1226 bytes .../exception/InvalidQueryTypeException.class | Bin 0 -> 880 bytes .../NoPrimaryKeyFieldException.class | Bin 0 -> 1001 bytes .../exception/NoRowsReturnedException.class | Bin 0 -> 761 bytes .../orm/helper/AndroidSQLLiteOpenHelper.class | Bin 0 -> 5177 bytes .../mobile/orm/helper/DBHelper.class | Bin 0 -> 1889 bytes .../orm/interfaces/CursorExtractor.class | Bin 0 -> 335 bytes .../orm/interfaces/CursorRowMapper.class | Bin 0 -> 332 bytes .../orm/interfaces/JdbcOperations.class | Bin 0 -> 2342 bytes .../orm/reflection/DomainClassAnalyzer.class | Bin 0 -> 6317 bytes .../orm/test/AndroidSQLiteTemplateTests.class | Bin 0 -> 25999 bytes .../mobile/orm/test/Main.class | Bin 0 -> 543 bytes .../test/MyInstrumentationTestRunner.class | Bin 0 -> 1320 bytes .../orm/test/creator/TableCreatorTest.class | Bin 0 -> 2462 bytes .../mobile/orm/test/domain/Account.class | Bin 0 -> 2850 bytes .../mobile/orm/test/domain/Address.class | Bin 0 -> 3763 bytes .../mobile/orm/test/domain/NoPKDomain.class | Bin 0 -> 1501 bytes .../mobile/orm/test/domain/Person.class | Bin 0 -> 6305 bytes .../test/domain/WrongTypeMappedDomain.class | Bin 0 -> 390 bytes .../helper/AndroidSQLLiteOpenHelperTest.class | Bin 0 -> 2218 bytes .../orm/test/helper/DBHelperTests.class | Bin 0 -> 1986 bytes .../interfaces/AddressCursorExtractor.class | Bin 0 -> 2674 bytes .../interfaces/AddressCursorRowMapper.class | Bin 0 -> 1790 bytes .../interfaces/CursorExtractorTests.class | Bin 0 -> 4507 bytes .../interfaces/CursorRowMapperTests.class | Bin 0 -> 6895 bytes .../interfaces/PersonCursorExtractor.class | Bin 0 -> 2714 bytes .../interfaces/PersonCursorRowMapper.class | Bin 0 -> 2014 bytes .../test/interfaces/SampleDataHelper.class | Bin 0 -> 5528 bytes .../reflection/DomainClassAnalyzerTests.class | Bin 0 -> 6174 bytes .../mobile/orm/AndroidSQLiteTemplate.class | Bin 0 -> 13656 bytes .../mobile/orm/CursorAdapter.class | Bin 0 -> 8798 bytes bin/org/springframework/mobile/orm/Main.class | Bin 0 -> 934 bytes .../springframework/mobile/orm/R$attr.class | Bin 0 -> 376 bytes .../mobile/orm/R$drawable.class | Bin 0 -> 436 bytes .../springframework/mobile/orm/R$layout.class | Bin 0 -> 430 bytes .../springframework/mobile/orm/R$string.class | Bin 0 -> 463 bytes bin/org/springframework/mobile/orm/R.class | Bin 0 -> 561 bytes .../mobile/orm/annotations/Column.class | Bin 0 -> 795 bytes .../mobile/orm/annotations/ColumnSetter.class | Bin 0 -> 481 bytes .../mobile/orm/annotations/ColumnType.class | Bin 0 -> 1267 bytes .../mobile/orm/annotations/ForeignKey.class | Bin 0 -> 582 bytes .../mobile/orm/annotations/PrimaryKey.class | Bin 0 -> 582 bytes .../mobile/orm/annotations/Transient.class | Bin 0 -> 453 bytes .../creator/CreateStatementGenerator.class | Bin 0 -> 472 bytes .../SQLLiteCreateStatementGenerator.class | Bin 0 -> 6823 bytes .../orm/exception/DataAccessException.class | Bin 0 -> 498 bytes .../EmptySQLStatementException.class | Bin 0 -> 576 bytes .../orm/exception/ExtraResultsException.class | Bin 0 -> 737 bytes .../InvalidCursorExtractorException.class | Bin 0 -> 1202 bytes .../InvalidCursorRowMapperException.class | Bin 0 -> 1202 bytes .../exception/InvalidQueryTypeException.class | Bin 0 -> 856 bytes .../NoPrimaryKeyFieldException.class | Bin 0 -> 977 bytes .../exception/NoRowsReturnedException.class | Bin 0 -> 737 bytes .../orm/helper/AndroidSQLLiteOpenHelper.class | Bin 0 -> 5137 bytes .../mobile/orm/helper/DBHelper.class | Bin 0 -> 1857 bytes .../orm/interfaces/CursorExtractor.class | Bin 0 -> 327 bytes .../orm/interfaces/CursorRowMapper.class | Bin 0 -> 324 bytes .../orm/interfaces/JdbcOperations.class | Bin 0 -> 2270 bytes .../orm/reflection/DomainClassAnalyzer.class | Bin 0 -> 6213 bytes .../orm/test/AndroidSQLiteTemplateTests.class | Bin 0 -> 25615 bytes .../mobile/orm/test/Main.class | Bin 0 -> 527 bytes .../test/MyInstrumentationTestRunner.class | Bin 0 -> 1264 bytes .../orm/test/creator/TableCreatorTest.class | Bin 0 -> 2398 bytes .../mobile/orm/test/domain/Account.class | Bin 0 -> 2810 bytes .../mobile/orm/test/domain/Address.class | Bin 0 -> 3683 bytes .../mobile/orm/test/domain/NoPKDomain.class | Bin 0 -> 1437 bytes .../mobile/orm/test/domain/Person.class | Bin 0 -> 6201 bytes .../test/domain/WrongTypeMappedDomain.class | Bin 0 -> 374 bytes .../helper/AndroidSQLLiteOpenHelperTest.class | Bin 0 -> 2146 bytes .../orm/test/helper/DBHelperTests.class | Bin 0 -> 1914 bytes .../interfaces/AddressCursorExtractor.class | Bin 0 -> 2586 bytes .../interfaces/AddressCursorRowMapper.class | Bin 0 -> 1726 bytes .../interfaces/CursorExtractorTests.class | Bin 0 -> 4339 bytes .../interfaces/CursorRowMapperTests.class | Bin 0 -> 6711 bytes .../interfaces/PersonCursorExtractor.class | Bin 0 -> 2626 bytes .../interfaces/PersonCursorRowMapper.class | Bin 0 -> 1950 bytes .../test/interfaces/SampleDataHelper.class | Bin 0 -> 5384 bytes .../reflection/DomainClassAnalyzerTests.class | Bin 0 -> 6030 bytes bin/resources.ap_ | Bin 0 -> 10588 bytes .../mobile/orm/R.java | 2 +- proguard.cfg | 36 + project.properties | 11 + res/drawable-hdpi/icon.png | Bin 0 -> 4147 bytes res/drawable-ldpi/icon.png | Bin 0 -> 1723 bytes res/drawable-mdpi/icon.png | Bin 0 -> 2574 bytes res/layout/main.xml | 12 + res/values/strings.xml | 5 + .../mobile/orm/AndroidSQLiteTemplate.java | 327 +++++++ .../mobile/orm/CursorAdapter.java | 231 +++++ .../mobile/orm/Main.java | 19 + .../mobile/orm/annotations/Column.java | 54 ++ .../mobile/orm/annotations/ColumnSetter.java | 17 + .../mobile/orm/annotations/ColumnType.java | 13 + .../mobile/orm/annotations/ForeignKey.java | 22 + .../mobile/orm/annotations/PrimaryKey.java | 26 + .../mobile/orm/annotations/Transient.java | 18 + .../orm/creator/CreateStatementGenerator.java | 47 + .../SQLLiteCreateStatementGenerator.java | 177 ++++ .../orm/exception/DataAccessException.java | 18 + .../exception/EmptySQLStatementException.java | 10 + .../orm/exception/ExtraResultsException.java | 15 + .../InvalidCursorExtractorException.java | 11 + .../InvalidCursorRowMapperException.java | 10 + .../exception/InvalidQueryTypeException.java | 13 + .../exception/NoPrimaryKeyFieldException.java | 13 + .../exception/NoRowsReturnedException.java | 13 + .../orm/helper/AndroidSQLLiteOpenHelper.java | 105 +++ .../mobile/orm/helper/DBHelper.java | 38 + .../orm/interfaces/CursorExtractor.java | 31 + .../orm/interfaces/CursorRowMapper.java | 13 + .../mobile/orm/interfaces/JdbcOperations.java | 219 +++++ .../orm/reflection/DomainClassAnalyzer.java | 130 +++ .../orm/test/AndroidSQLiteTemplateTests.java | 886 ++++++++++++++++++ .../mobile/orm/test/Main.java | 17 + .../orm/test/MyInstrumentationTestRunner.java | 38 + .../orm/test/creator/TableCreatorTest.java | 50 + .../mobile/orm/test/domain/Account.java | 91 ++ .../mobile/orm/test/domain/Address.java | 124 +++ .../mobile/orm/test/domain/NoPKDomain.java | 43 + .../mobile/orm/test/domain/Person.java | 191 ++++ .../test/domain/WrongTypeMappedDomain.java | 5 + .../helper/AndroidSQLLiteOpenHelperTest.java | 48 + .../mobile/orm/test/helper/DBHelperTests.java | 42 + .../interfaces/AddressCursorExtractor.java | 49 + .../interfaces/AddressCursorRowMapper.java | 31 + .../test/interfaces/CursorExtractorTests.java | 73 ++ .../test/interfaces/CursorRowMapperTests.java | 135 +++ .../interfaces/PersonCursorExtractor.java | 50 + .../interfaces/PersonCursorRowMapper.java | 31 + .../orm/test/interfaces/SampleDataHelper.java | 167 ++++ .../reflection/DomainClassAnalyzerTests.java | 136 +++ 156 files changed, 3901 insertions(+), 7 deletions(-) create mode 100644 .gitignore create mode 100644 bin/classes.dex create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/AndroidSQLiteTemplate.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/CursorAdapter.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/Main.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/R$attr.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/R$drawable.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/R$layout.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/R$string.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/R.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/annotations/Column.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/annotations/ColumnSetter.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/annotations/ColumnType.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/annotations/ForeignKey.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/annotations/PrimaryKey.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/annotations/Transient.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/creator/CreateStatementGenerator.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/creator/SQLLiteCreateStatementGenerator.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/exception/DataAccessException.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/exception/EmptySQLStatementException.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/exception/ExtraResultsException.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/exception/InvalidCursorExtractorException.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/exception/InvalidCursorRowMapperException.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/exception/InvalidQueryTypeException.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/exception/NoPrimaryKeyFieldException.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/exception/NoRowsReturnedException.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/helper/AndroidSQLLiteOpenHelper.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/helper/DBHelper.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/interfaces/CursorExtractor.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/interfaces/CursorRowMapper.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/interfaces/JdbcOperations.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/reflection/DomainClassAnalyzer.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/test/AndroidSQLiteTemplateTests.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/test/Main.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/test/MyInstrumentationTestRunner.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/test/creator/TableCreatorTest.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/test/domain/Account.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/test/domain/Address.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/test/domain/NoPKDomain.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/test/domain/Person.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/test/domain/WrongTypeMappedDomain.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/test/helper/AndroidSQLLiteOpenHelperTest.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/test/helper/DBHelperTests.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/test/interfaces/AddressCursorExtractor.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/test/interfaces/AddressCursorRowMapper.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/test/interfaces/CursorExtractorTests.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/test/interfaces/CursorRowMapperTests.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/test/interfaces/PersonCursorExtractor.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/test/interfaces/PersonCursorRowMapper.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/test/interfaces/SampleDataHelper.class create mode 100644 bin/classes/com/perfectworldprogramming/mobile/orm/test/reflection/DomainClassAnalyzerTests.class create mode 100644 bin/org/springframework/mobile/orm/AndroidSQLiteTemplate.class create mode 100644 bin/org/springframework/mobile/orm/CursorAdapter.class create mode 100644 bin/org/springframework/mobile/orm/Main.class create mode 100644 bin/org/springframework/mobile/orm/R$attr.class create mode 100644 bin/org/springframework/mobile/orm/R$drawable.class create mode 100644 bin/org/springframework/mobile/orm/R$layout.class create mode 100644 bin/org/springframework/mobile/orm/R$string.class create mode 100644 bin/org/springframework/mobile/orm/R.class create mode 100644 bin/org/springframework/mobile/orm/annotations/Column.class create mode 100644 bin/org/springframework/mobile/orm/annotations/ColumnSetter.class create mode 100644 bin/org/springframework/mobile/orm/annotations/ColumnType.class create mode 100644 bin/org/springframework/mobile/orm/annotations/ForeignKey.class create mode 100644 bin/org/springframework/mobile/orm/annotations/PrimaryKey.class create mode 100644 bin/org/springframework/mobile/orm/annotations/Transient.class create mode 100644 bin/org/springframework/mobile/orm/creator/CreateStatementGenerator.class create mode 100644 bin/org/springframework/mobile/orm/creator/SQLLiteCreateStatementGenerator.class create mode 100644 bin/org/springframework/mobile/orm/exception/DataAccessException.class create mode 100644 bin/org/springframework/mobile/orm/exception/EmptySQLStatementException.class create mode 100644 bin/org/springframework/mobile/orm/exception/ExtraResultsException.class create mode 100644 bin/org/springframework/mobile/orm/exception/InvalidCursorExtractorException.class create mode 100644 bin/org/springframework/mobile/orm/exception/InvalidCursorRowMapperException.class create mode 100644 bin/org/springframework/mobile/orm/exception/InvalidQueryTypeException.class create mode 100644 bin/org/springframework/mobile/orm/exception/NoPrimaryKeyFieldException.class create mode 100644 bin/org/springframework/mobile/orm/exception/NoRowsReturnedException.class create mode 100644 bin/org/springframework/mobile/orm/helper/AndroidSQLLiteOpenHelper.class create mode 100644 bin/org/springframework/mobile/orm/helper/DBHelper.class create mode 100644 bin/org/springframework/mobile/orm/interfaces/CursorExtractor.class create mode 100644 bin/org/springframework/mobile/orm/interfaces/CursorRowMapper.class create mode 100644 bin/org/springframework/mobile/orm/interfaces/JdbcOperations.class create mode 100644 bin/org/springframework/mobile/orm/reflection/DomainClassAnalyzer.class create mode 100644 bin/org/springframework/mobile/orm/test/AndroidSQLiteTemplateTests.class create mode 100644 bin/org/springframework/mobile/orm/test/Main.class create mode 100644 bin/org/springframework/mobile/orm/test/MyInstrumentationTestRunner.class create mode 100644 bin/org/springframework/mobile/orm/test/creator/TableCreatorTest.class create mode 100644 bin/org/springframework/mobile/orm/test/domain/Account.class create mode 100644 bin/org/springframework/mobile/orm/test/domain/Address.class create mode 100644 bin/org/springframework/mobile/orm/test/domain/NoPKDomain.class create mode 100644 bin/org/springframework/mobile/orm/test/domain/Person.class create mode 100644 bin/org/springframework/mobile/orm/test/domain/WrongTypeMappedDomain.class create mode 100644 bin/org/springframework/mobile/orm/test/helper/AndroidSQLLiteOpenHelperTest.class create mode 100644 bin/org/springframework/mobile/orm/test/helper/DBHelperTests.class create mode 100644 bin/org/springframework/mobile/orm/test/interfaces/AddressCursorExtractor.class create mode 100644 bin/org/springframework/mobile/orm/test/interfaces/AddressCursorRowMapper.class create mode 100644 bin/org/springframework/mobile/orm/test/interfaces/CursorExtractorTests.class create mode 100644 bin/org/springframework/mobile/orm/test/interfaces/CursorRowMapperTests.class create mode 100644 bin/org/springframework/mobile/orm/test/interfaces/PersonCursorExtractor.class create mode 100644 bin/org/springframework/mobile/orm/test/interfaces/PersonCursorRowMapper.class create mode 100644 bin/org/springframework/mobile/orm/test/interfaces/SampleDataHelper.class create mode 100644 bin/org/springframework/mobile/orm/test/reflection/DomainClassAnalyzerTests.class create mode 100644 bin/resources.ap_ rename gen/{org/springframework => com/perfectworldprogramming}/mobile/orm/R.java (92%) create mode 100644 proguard.cfg create mode 100644 project.properties create mode 100644 res/drawable-hdpi/icon.png create mode 100644 res/drawable-ldpi/icon.png create mode 100644 res/drawable-mdpi/icon.png create mode 100644 res/layout/main.xml create mode 100644 res/values/strings.xml create mode 100644 src/com/perfectworldprogramming/mobile/orm/AndroidSQLiteTemplate.java create mode 100644 src/com/perfectworldprogramming/mobile/orm/CursorAdapter.java create mode 100644 src/com/perfectworldprogramming/mobile/orm/Main.java create mode 100644 src/com/perfectworldprogramming/mobile/orm/annotations/Column.java create mode 100644 src/com/perfectworldprogramming/mobile/orm/annotations/ColumnSetter.java create mode 100644 src/com/perfectworldprogramming/mobile/orm/annotations/ColumnType.java create mode 100644 src/com/perfectworldprogramming/mobile/orm/annotations/ForeignKey.java create mode 100644 src/com/perfectworldprogramming/mobile/orm/annotations/PrimaryKey.java create mode 100644 src/com/perfectworldprogramming/mobile/orm/annotations/Transient.java create mode 100644 src/com/perfectworldprogramming/mobile/orm/creator/CreateStatementGenerator.java create mode 100644 src/com/perfectworldprogramming/mobile/orm/creator/SQLLiteCreateStatementGenerator.java create mode 100644 src/com/perfectworldprogramming/mobile/orm/exception/DataAccessException.java create mode 100644 src/com/perfectworldprogramming/mobile/orm/exception/EmptySQLStatementException.java create mode 100644 src/com/perfectworldprogramming/mobile/orm/exception/ExtraResultsException.java create mode 100644 src/com/perfectworldprogramming/mobile/orm/exception/InvalidCursorExtractorException.java create mode 100644 src/com/perfectworldprogramming/mobile/orm/exception/InvalidCursorRowMapperException.java create mode 100644 src/com/perfectworldprogramming/mobile/orm/exception/InvalidQueryTypeException.java create mode 100644 src/com/perfectworldprogramming/mobile/orm/exception/NoPrimaryKeyFieldException.java create mode 100644 src/com/perfectworldprogramming/mobile/orm/exception/NoRowsReturnedException.java create mode 100644 src/com/perfectworldprogramming/mobile/orm/helper/AndroidSQLLiteOpenHelper.java create mode 100644 src/com/perfectworldprogramming/mobile/orm/helper/DBHelper.java create mode 100644 src/com/perfectworldprogramming/mobile/orm/interfaces/CursorExtractor.java create mode 100644 src/com/perfectworldprogramming/mobile/orm/interfaces/CursorRowMapper.java create mode 100644 src/com/perfectworldprogramming/mobile/orm/interfaces/JdbcOperations.java create mode 100644 src/com/perfectworldprogramming/mobile/orm/reflection/DomainClassAnalyzer.java create mode 100644 test/com/perfectworldprogramming/mobile/orm/test/AndroidSQLiteTemplateTests.java create mode 100644 test/com/perfectworldprogramming/mobile/orm/test/Main.java create mode 100644 test/com/perfectworldprogramming/mobile/orm/test/MyInstrumentationTestRunner.java create mode 100644 test/com/perfectworldprogramming/mobile/orm/test/creator/TableCreatorTest.java create mode 100644 test/com/perfectworldprogramming/mobile/orm/test/domain/Account.java create mode 100644 test/com/perfectworldprogramming/mobile/orm/test/domain/Address.java create mode 100644 test/com/perfectworldprogramming/mobile/orm/test/domain/NoPKDomain.java create mode 100644 test/com/perfectworldprogramming/mobile/orm/test/domain/Person.java create mode 100644 test/com/perfectworldprogramming/mobile/orm/test/domain/WrongTypeMappedDomain.java create mode 100644 test/com/perfectworldprogramming/mobile/orm/test/helper/AndroidSQLLiteOpenHelperTest.java create mode 100644 test/com/perfectworldprogramming/mobile/orm/test/helper/DBHelperTests.java create mode 100644 test/com/perfectworldprogramming/mobile/orm/test/interfaces/AddressCursorExtractor.java create mode 100644 test/com/perfectworldprogramming/mobile/orm/test/interfaces/AddressCursorRowMapper.java create mode 100644 test/com/perfectworldprogramming/mobile/orm/test/interfaces/CursorExtractorTests.java create mode 100644 test/com/perfectworldprogramming/mobile/orm/test/interfaces/CursorRowMapperTests.java create mode 100644 test/com/perfectworldprogramming/mobile/orm/test/interfaces/PersonCursorExtractor.java create mode 100644 test/com/perfectworldprogramming/mobile/orm/test/interfaces/PersonCursorRowMapper.java create mode 100644 test/com/perfectworldprogramming/mobile/orm/test/interfaces/SampleDataHelper.java create mode 100644 test/com/perfectworldprogramming/mobile/orm/test/reflection/DomainClassAnalyzerTests.java diff --git a/.classpath b/.classpath index 24761b6..f66896c 100644 --- a/.classpath +++ b/.classpath @@ -4,5 +4,5 @@ - + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0008167 --- /dev/null +++ b/.gitignore @@ -0,0 +1,18 @@ +# osx noise +.DS_Store +profile + +# xcode noise +build/* +*.mode1 +*.mode1v3 +*.mode2v3 +*.perspective +*.perspectivev3 +*.pbxuser +*.xcworkspace +xcuserdata + +# svn & cvs +.svn +CVS diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 0a7d842..868f338 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1,11 +1,11 @@ - + - @@ -25,8 +25,8 @@ + android:targetPackage="com.perfectworldprogramming.mobile.orm.test" + android:name="android.test.InstrumentationTestRunner" /--> diff --git a/README b/README index e69de29..283c987 100644 --- a/README +++ b/README @@ -0,0 +1,15 @@ +Welcome to AndroidSQLLiteOrm. + +The purpose of this project is to simplify the Android SQLLite apis. I found the apis to be un-intuitive. Now un-intuitive to one person is different to another. So to many out there the Android SQLLite apis are perfectly fine. Not to me, so I thought about projects that are already out there that simplify Data Access. And since I do a lot of work with the Spring Framework, I thought I could match Spring's JdbcTemplate api and make it run on Android. And that is exactly what I have done. + +So, if you have used Spring's JdbcTemplate before, then you know how to use AndroidSQLLiteOrm. + +I have added a couple of features above the JdbcTemplate. I have added basic ORM support. Very generic and basic. So I do not do associations. I do Foreign Key Associations of ManyToOne, simple for saving Child records to have the FK stored in its table. But I do not retrieve any associations when querying. The ORM support works really well with Creating and Android database, where Create Table scripts can be automatically generated, as well as Alter Table scripts for updates to your database version. + +For the best documentation on how to use this project. Check out the full set of Unit and Integration tests. You can even run the tests if you like to prove that it works. + +Thank you for looking at my project + +Mark Spritzler + +Please raise issues/Feedback and comments on GitHub to this project. \ No newline at end of file diff --git a/bin/classes.dex b/bin/classes.dex new file mode 100644 index 0000000000000000000000000000000000000000..369885c60ab171c622fbe60345d85e908c2de594 GIT binary patch literal 70888 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 X&qS0@nma36ssE-kjhFCYNFD!QwZ$Om literal 0 HcmV?d00001 diff --git a/bin/classes/com/perfectworldprogramming/mobile/orm/Main.class b/bin/classes/com/perfectworldprogramming/mobile/orm/Main.class new file mode 100644 index 0000000000000000000000000000000000000000..245b4b51da66a68b62f9227e5f7a5818518466bf GIT binary patch literal 966 zcmb7CTW=CU6#j-wp%hCCma2FGuUx8=_=+(>Ow%S?jls|upN8F$j#+lr-GS{krakt%XR0B zp^o{Bap3u~-RN5`+j(rFko=kia-dG~*g=_LGnS^S10w^|SMrp|*AE;046ZTkUy{a& z^l65?vlvb9jpHaIUxzX{mrT4POS^ zS=?sGkPJq~CWl>A?Nn zH&{%E;o!1z|6|TXAlK95$d&uFw+!ocYoFLTphgmq?(`+-k5-awhEAM3BcE>0ko`6f z=g8Wy-I5Km`9%WxD|DiLL4mA&tSQfe)|#yuwwlG_6r~^7eb=1gIxF5v&2Z;vZ;HFe tE8sHK20^3=WCL5Y6WgewI4@LPfGrCVEFR(!m8wvgIvR84O?sU`>krCp`6&PZ literal 0 HcmV?d00001 diff --git a/bin/classes/com/perfectworldprogramming/mobile/orm/R$attr.class b/bin/classes/com/perfectworldprogramming/mobile/orm/R$attr.class new file mode 100644 index 0000000000000000000000000000000000000000..3a7b47c6138d5d1286c905a6cbb5271110110d00 GIT binary patch literal 400 zcmb7A%}N6?7@V)&?drPPTD^GpPz4Qot#~OEghioB@7ZmvDaoc}Q++N^f(IYKhbn%% z_y9^^CiDG-nS5_QzW`k0I6;SSQ93Ku%0H_zyg6?cYwwm`TC1z2u&&TX3Fobtoyrh= zf`~9!$yX_iq5c$7MjS1Nspv680%xSxRh$Ec*0OY!0 A!TU;`dCUPw$xh$d*bZ_A2Hw!36o-_`35XS*(gh6VvcqQGVOpA?mdcJaY;Y5}xvxqaBC@o{_vUqwj zcVZ(FEd%(3&Qd&!SPK^2B}?ul_$sxAKx0B{WKCWOQ_O^3OYfxy5E@s?sN$O7^-pIk zAKAGK;h_~_3n8IBQAXabvqZXw@*hHXVpE}K!l{z~6#e2!<%EmLzZbtGg!gvsQhCF! zc%kWe>4FfAjgfAoMV`w%z#*ak*WrZb?_DrplOCUz&_f*!jsde8nw(MTk#U=0Rq6F`oP;PbMDx06)su zyZQlosqX5ju5``k*ZT*6a~y@J5#rRDcqRRVO!Ft_^?c>s!V6=RUBt#EO3T=J6Hkw| zcy>h|qE6^8#ahH#u;eyb@+P5fgt7!06WSwZvs~DGCUhZ#mjEC%FO^mK6(Ja$%ve5h zbJ;?Gc7#o|2%U+t@}@9}^!FmslF*yDROp%Ts^q`Jdj6;~!f^7>vo8p(J6HHrUUMQo zXL?pKB&ROVyc;z?X_pmF+! i=(Un;GnNZL7ahi^>Kn{*6bZC9NF8w>>XPAnXF7K`~ZF^ zi49||gmsCS z9A~-XS^%HWS;{9VwB(lCaLF$Tb(y9QMkb0tBSLFvO_ocOPo-Wd@5KiZstcvHEdYet zWo+X7is1E6rUZXzXQ}}Y?It$SB(%q|Q8%k3RPJ7enti)t8%aHtE-v_|=;w<#BMip> z%yB_z+}V|j)HO%s?@Z2$P=w~l80CgqW|_(Y91{9}wPu&~k}%+a9&fpV9;&D@1try) zH-2%0Z>Y%2+TspTGEhBz!`5s0q{CVm06W-bEn2w&UFKrIZmE0N=W}g$z(ac9JH~KT literal 0 HcmV?d00001 diff --git a/bin/classes/com/perfectworldprogramming/mobile/orm/R.class b/bin/classes/com/perfectworldprogramming/mobile/orm/R.class new file mode 100644 index 0000000000000000000000000000000000000000..b5a952b6eaeb85639b75b5ef3eff4f7c07cdced4 GIT binary patch literal 609 zcmb7BO-lnY5PfO4O|8||`dL3N;-MBa)T`p9AP7aFO7GcitSQ+|$?jVGS)K$B{s4cJ zIJ?#RO5nXWGt4lP_x1hp3E%=p93_TsU_&ui?nwp7!a6gVJ3DnU40SXWq4l*_pX3#!3SfR2iB>9jUuC^p$&*zEKSA zp$()NOQ*B=H|ZtMI%en%i|%vDP=Bzg3)BtmNPCRVv*j2Xw^5|rz{ogOF-M!>tmw=W znIw*G$cST`p@kSK6O4SdY4)K@!Ex}P?l^Je7p3>jB0h$P4XSUVgDv76;$7kny?x?C GbbbKsaG{g{ literal 0 HcmV?d00001 diff --git a/bin/classes/com/perfectworldprogramming/mobile/orm/annotations/Column.class b/bin/classes/com/perfectworldprogramming/mobile/orm/annotations/Column.class new file mode 100644 index 0000000000000000000000000000000000000000..847472838856b807ad9e9ae3e0c8f787adfe9e41 GIT binary patch literal 827 zcmbu7Pfy!G5XIjl4yHg`p!_KXN(&N#OD%D$IG~6G2?;1lT!iRpV}{6Ry&E=b5MQl_ zegHlcVl4hRhe$~DU|IA0o4503eRu!&AAl{ags2dHCN_(D>@GO*H`eL%p0i!2vMe>- zD6^eZb7Wl>DPycxKDDMF?OL5@CPYA(yj0gJ(n{c8olEfuF+x}=)v_pjBAdKWDy(-$O8=GfUNg>*($+cD;%|%Uwz~A3DMW2=zj@Fgd>an8*b6JyDt_y)Ajejx$*q84>-SN-f7m2^AKuci zNnXsr=R()tzQ#6t&u)92`RziCO7%{vY9C`FjAPae1eg~f`~zZq#sa<+6=M-gSQg+b@Bp|9?;-#I literal 0 HcmV?d00001 diff --git a/bin/classes/com/perfectworldprogramming/mobile/orm/annotations/ColumnSetter.class b/bin/classes/com/perfectworldprogramming/mobile/orm/annotations/ColumnSetter.class new file mode 100644 index 0000000000000000000000000000000000000000..9acf53184e718ff8dfd6b096a7b3b5c7d335e98a GIT binary patch literal 489 zcmaix$w~u35QhKG;%M9w%|%2M4?!KTJ@X&NEU;R~G{r&U#1>hX*2o-_L#2J~9A5juMoY(J}cVn-NN$pq~H%v82=Z#d> zx}ZYpY%Z^zE{q*e2;?Kw1ey~yRZ=T1c^XbwDZ+}tVHqu}<<*~%Kz*uoK?3cQ)B6%0 z1kcSc1X?9~LnBq_AOL~Jz!g5BTON&>#bM6oA_9B;!iLn)OPZ%cO{GdMaIny5VX9d9 zF$L~__fy+I9ks3DKN^LVzToO(sMdZW(-FC=g0W&q1zGs!YZFS rf0E$cMp$KUjlF7)1}a!*vw{t5^1aX27N?^(2*Ng+Xw5ys4t9S5qyCOk literal 0 HcmV?d00001 diff --git a/bin/classes/com/perfectworldprogramming/mobile/orm/annotations/ColumnType.class b/bin/classes/com/perfectworldprogramming/mobile/orm/annotations/ColumnType.class new file mode 100644 index 0000000000000000000000000000000000000000..bee0f0cb747851f2a11ed4d9a69796b07ab8524f GIT binary patch literal 1315 zcmbtUO;giQ6g`i$OiLe!UDpeEV0ms!-SOGpxKOg(ur1dLHW;LQ zp-P2zykj$ocp3~73NpCGkSO;;vU$DVvJv<+s?u(unxfd-3gSp4Aq#Lvfh<5$fEfiz z0a60oRggkL?CvQ@W0+w~w_J0-?bJ=b!t1ulkkP#cx2xQ@1P&jjAz^~V1s|;z={e_i z+oa8QzA)$r(#WGIqrfm8X|2-=Oh>^ImKjpq_j#w`H9HK&=l~AtXXKsIZe%8ZAJI_g z5JQ;IbStTL=c`FCvIYLz0Q{uS&uDC|l$OB-I>ZvRx( zcdv*@>fEqST^_W3diyRyD6-1~%HJq$u96ER`Xb|-)51Fdtz?^UCC7v-nFScn39C?K zjGUxkgz`oSeI_if%6G6@W=y)o_ys0Ikd1|4Dg@K<5adEIn+U<2{DYFDE+&mytcxk5 z7Vjcw)Dm6H85fxUO1wk3PxmZo1DSS&G~`IdA}M%5Iv#`(B8t9|o}yLiM|30?mu4^V zuuqbp0Q8cSa4%y)v_`~_@VJ-0PNhV8wu|}NTd81)XaPs0i8cvurS&Tg|>zws+0P@GAfl0fb9 zs++-mXSsDz*_c2%vvR$V5IF3mu~QMfszePnWg3aV(Ndcw zPXlQ~a@_H3b-tx3qSy`QQ(~yt?zFm1fs@s6j~ui7OpIRqfjk?nf;od;@8xmOd1wio zt}bbsAYFK%5z~$CKW27kbQ;Bda*k~MLhwW8c@_C52p*w_b&fVT$|ooxhfO}_u!U{j a&r!e*r@c1_LKziQ7ZG6>d#Ew65Bva8ShIfs literal 0 HcmV?d00001 diff --git a/bin/classes/com/perfectworldprogramming/mobile/orm/annotations/PrimaryKey.class b/bin/classes/com/perfectworldprogramming/mobile/orm/annotations/PrimaryKey.class new file mode 100644 index 0000000000000000000000000000000000000000..02a77746a78d4b0d1792125f0bc05d5b529b2e80 GIT binary patch literal 598 zcmbV~O-}+b5Qg9K;VOOriY6Y6UkTBRn|LK2h(JO_C4gQ$m1Q7H+AZmJG5j?T{s4cJ zak#h~NK8C5?R1`b=S`r5dro$x53Q zPXlQuihX30{Ju8&_pGl9FCXr-R|uT=)P!l<|xU z*i7Q0ZQAqwUr*ETpU*DV2s6S&K~l}ifml*JDp%xoF_JSc0mn@j7b+K}|YO68o7 zDr)a?nFi%@O)e(b6=*HgN=c)bf1EB@lVDGvy*=GVWp85vjYLc6ikJSAZIlzj+@AytcX0;M(CE R1mOtBXqG#|30gP>egWU^iZ=iN literal 0 HcmV?d00001 diff --git a/bin/classes/com/perfectworldprogramming/mobile/orm/creator/CreateStatementGenerator.class b/bin/classes/com/perfectworldprogramming/mobile/orm/creator/CreateStatementGenerator.class new file mode 100644 index 0000000000000000000000000000000000000000..e0efa64f62ca0e3f968537ff8599c8571d30eed7 GIT binary patch literal 480 zcmZuuO-sW-5Pj2XW9ui1N5P9y5nS+SikG5AD0;{**v4r{$!5!Dqy9Dz{s4cJI7y|1 z)XNT!d2im#+wY&xF95eV4A3D=Vr$fr-JE0pZe8}ebT)C?m^4q6v9mN|Wt~y6W9_X| zCfOP^+Hnif7J^rJM% zwJ#kLE;k6Hm7pFTc_-_I_aZv27vq)%;bPd}k275q;h$x50^x3hH@a>pS7(URzvArC7&97(}*oF+WO-27_FnR<+SN;a*N|@W|2@V8xup_vS!5Z%h M-fLp%?AOeLUn`-E>;M1& literal 0 HcmV?d00001 diff --git a/bin/classes/com/perfectworldprogramming/mobile/orm/creator/SQLLiteCreateStatementGenerator.class b/bin/classes/com/perfectworldprogramming/mobile/orm/creator/SQLLiteCreateStatementGenerator.class new file mode 100644 index 0000000000000000000000000000000000000000..cd0b79770934012c6951d7fe6292070a8ea2ab29 GIT binary patch literal 6959 zcmb_hd3;pW75?sIX5KJ)2n+@o5IS0vBtwWrOC*VjAxvN-3?T`Ds5KpumoP9(oJ9nw zR7Ih-Me7c(v?}gZt4V>1cEeV?uXeB9?Y{m;OTT;H%gmc3DCXynUuNFD@7}X~=R4=z zJG}b8!$$!u#(y+81R}kuMD?JN?l*d~TT|(H-(Wg5kd7u2vE)E?BDFCVH>y+VM0Ic4 zh-Opi>W;Oot+A}pEQdx%mLCZtnO$KdjkJ8P!6`6xbM(q+bv#N5Yc_7CU=41874J~f z$y5mF&F!J4&QMQh)3Vl(fUmWnuOpkL;dKI&n^Vb5Hk!Z_[=kC(B_VDVa_U@ilp>7YR6($0l5OA-H zgx9VMdEgW9NWqbHt*su+Fh>D75}4kyracs15s@-_Lam|Ip-86(et~oA`(sADuOSeQ zbcR-h+5_#OmQZ^r(j4jt)c2>-Mr z$ru^JbEyrVW;siECUsCkG@DBs0t?10s1MqLdo0W9P?@PDPjW=X@P=F;BpoF|sO5k^$2PI4Dk7$&2y|Gs?MaEMDCj%VcTBIb$a4 zZB($btD#Oqt-x7@v_Ml#1Yj-LaNaQlv0J%rn1+trr zfXSqQ#nM1FrDorzx|quY8x5HPfdRAVFyGZ)g|!i2(wj9YH#E zZyOxp_WV(D#tl3fGFs;NbY!`uk-b}1M+a5zXp)t+V-OmD^Ej}{09>NuQe4Jl9R-3w z%^1OTHZv{c$B`-!um>~TA4!qC3`Qo8ut4h=;p1Cub4=To<=-{A{q`)e> zCnrV4GN#Uhgn%PZE}>897{nE16xrDnk9VeQ_>3cUM1&0zD4ml%8?D5 zHkxq|@Z0tjfy3&wY^?n!(=>jF%tYR%V>_;*0q4E-Im<}en7RJlHQ!XBOuuG1+pnT zs^c*{&Kk_JwcO~9N7F{1S-u3$D6e=c2|Mwmj;HW6Pdl+pp$xR8jSP=#vW3_xhE+o@ zktdaBbUcgacnHeGwzJjnTppIw&+B*rL%d~VQ|inlP+oLS9XYYsZL;QgQ8L-2YOa8F z)yN-0?Z=K{)-=?WVh0ZEI3jz8>q_%t_o4v2cnP1^@N&`B(=1myz93IkZsUqvG@kL` zOJsI<`6L{}S2Vmbu`D+E(#fNfj<4cX!eCv~CP$t)wsye#mpks4J(0 z`$sx{jGr)N(#Bvs+H3GoAaH@5My7dnV+^hv=N#t2&uFZ5=`F=x9QNRsWSzX*@12&NRZ5T zo%wg`IM>B@Gf^__1m?i4L1--Sf}iVw>0HP=Z{FJt%G-z)EKg<7=N(43G`2(;>*jh; zwG6r$6HgvLk1|ClQzWTC`mMz}J_&r_Ep<#DM@Q#7)Zvg<$GjhxD?j$qYRRYhN6^!~ za2U}@Rd5I!hp=gVl`k&8DyxFSNLCFYUGQ-R83Ib1M0q}1?#Jb%a*wj7(v+9?dA{W{ zbs$H79o#jCd#|Ks84?o*xk}>Tkaw)Sja#LS;%-WmC17_Y4ZJE+b#yic( znR9Wi%kT2-7{WC#V@Ivq?>+`^Wzg>)#xBn9QS*ChHNR%gYs0vS^Ly3&-dc~}a|}Ay zyZoME+*0POI_m6u0F#5h+okgd;SKuklux^yLcTn3;%1qOCNCo-2Y4!R!$2u7raEGT zV>4!93!ROl0tse&3iWiViEgb#2A#b2brXn7cf2aX0o6zA4y>{kVtL%t9aT#eEFRd~Cq|cz~P} znkV)_U+8yQ6~QISTxIS9Cth2)@DM&N@FI2|!e<#@cNG56xF*wBk zv#9cYZU{&B!R`BEB*^UCv_9yYqrRTQmxu6Le(0MjXC-OP`eXvNm$bN3xzKK^&b!c*c?q}NJ;ssj|6M_b>NnDrLTotmTRHQlZIW|; z7R={qLErS^>Awr6H>b;N(}h4TV$A^=REmdLbsk{=50a~oG9Zu9*2js!lWbg1A%drw i>CY%M%r4oLN24o`MwhA;CX?w;!wh=!FUoh|-~R{iP7DbE literal 0 HcmV?d00001 diff --git a/bin/classes/com/perfectworldprogramming/mobile/orm/exception/DataAccessException.class b/bin/classes/com/perfectworldprogramming/mobile/orm/exception/DataAccessException.class new file mode 100644 index 0000000000000000000000000000000000000000..51e23d30dc40c6b0da6f14755db42272e3bde159 GIT binary patch literal 514 zcmb_Y$xZ@65PdalW&lAHG~B$oBu?TLLt;P@&BTK!_hx9Z&GahN4 z;C9fXeW2T1M{P*m$OPtd3`=8KErBx!HNSm_8)#;ExXN3B| zB&idLn}|4*C7vsPL?|DrM7chpy%YZEj-BPPdb<-sabRZBM**uf_^1*Zp-SX=rl-maz5oCK literal 0 HcmV?d00001 diff --git a/bin/classes/com/perfectworldprogramming/mobile/orm/exception/EmptySQLStatementException.class b/bin/classes/com/perfectworldprogramming/mobile/orm/exception/EmptySQLStatementException.class new file mode 100644 index 0000000000000000000000000000000000000000..e0b2e23a744d137ab2ee0afc476538ac238f74f0 GIT binary patch literal 600 zcmb7BO-~y!5PcIuLPIE!mKJegxzQf75)!9Wl_~-fbXye#a(6ZZxboVI?M<7X)l;P& z`UCo-P-pqNalnW1%$uj@ndg5ufBpj4!)6-|!spx-Y03VA^Z3JgGcCQl^r|Sdy-W)? z(S}p!i0nJ8%@IS*@8nA)u%k?5FV8XYk|F1X3Rdw zqvyv%0-X?64x9~9**I3F;ze1cK167J&{oHfgoWLAV?y)5O?e3~3F)z&DWj)}jNDJY z8CHRlP?e>bC(71na$T{XCn0*-x!=J8*1G6mov^W+eOEJ;8YO0oZu^5;eKpgTzgESB z{h68=CiF6w%d|>nmiiuS#w#5NU$SRg^0dbTLTBVEpYxG?4PpCfYQLTxI}lH5kFbSB zwB&9})xeTuqJ?FNT|xE*Be~n}dn>=O`s>`u;c0)8iD@1O)^OnLap2e&&Ik~l1YZkwCqYzrL1WfOg4WPLvyK{W655^N z|JvQ{(KMr7$12vOE0twz#)M7j>O%6ok?xdnyN-2i5USpucS&ea}-8k&UVp*H-k zNF#P1Rg^HHIkd6NOUcwEo`Yq7sB^;W;gy$i>4Ljb*vyK)-=8mE)-oW}_H5x|-jyGP zuzo4`$#hh>4-x~iF>$+qMY$^yl~9$J$l$u1bwS>uEGW=^`~!{8&E+%P*f>S&6t~W> l`E5qIBWG=v)IbYMxGVAMISKa=NF;PA_+TdeP@)pH{s1iu&rARS literal 0 HcmV?d00001 diff --git a/bin/classes/com/perfectworldprogramming/mobile/orm/exception/InvalidCursorExtractorException.class b/bin/classes/com/perfectworldprogramming/mobile/orm/exception/InvalidCursorExtractorException.class new file mode 100644 index 0000000000000000000000000000000000000000..14476586ba7c933e2c1f6ae51471578e36513c8c GIT binary patch literal 1226 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 ZkVOb6qe2|pbT{doc&cOGr(~tD^9RWG6M+B# literal 0 HcmV?d00001 diff --git a/bin/classes/com/perfectworldprogramming/mobile/orm/exception/NoRowsReturnedException.class b/bin/classes/com/perfectworldprogramming/mobile/orm/exception/NoRowsReturnedException.class new file mode 100644 index 0000000000000000000000000000000000000000..0329342029d1712a9fa678d29fc493a4ad73e23f GIT binary patch literal 761 zcmb7CT~8B16g{^T+Vn%PwxEEzpbwytO?<5}QL0f=`vBU6$La2+j@jK=XJ=9^((A+jj=2YT_D$03Qswh4p%)QcycCQJYjs7=vsQgGt_Iu7s5#7xpp}cKE zuHX(~>FW90Tt^|>Di#PU1LIjK&a>0%yaQvs?>XC_UJXsO8mOUO?Ai@G#U>Q4xq+u+LjX=_fkpzY| zP1@2neWdi=(xwmka#Gq9+Qc?-18I}eH0kT7-(9PpUHRxo`E1;MXC!(2faR_gEqmrZ z&b{ZHefBx`&fD+3dL2Lu{;HrvU|-Zo2GY7Yrbn}93^Nf+o5r}QC6n>gcpzzv#uIwL zFq47fdV*4c&Q#1a;<3n~-rjgt?@#Ng{nms6mq49n&jw;zRvXnadLVNuL9qbE7f1^z z(S(-C=ox|PqrE4z(^?>*QDK)H4GL65;^QeTn=^HR+9d+J8XZgeM^Di7Ud5pXB$ZzY)nHj^}r$w`dc~*K<0fDhZKR@Wo9*;9Z`+MIXjxa)s6^@ClfUoGt;s^<-(zm_jPgqM@w#^eH zA0fI>kQvg=Ox#Ebh>(EWNOhUImgTC(c~tKVRj__Y!DfN*3cZX<1%@d}Em>{ri)5)Z zNuoWXr*u=!d$0*xWQ4a0l-AV`$^JGKHP|lTwf0!NRG_BL5pX*f>K!9_=RK%HgMxa2 z?FE+K*+UhLXd?LfgdU~U)bG@j-&Jycb>@_GsXI?1W^^%1chX)7NTnK>0k>TsI%F-C?p zuNa*W^G`;tT}4pxVa=#M9#0LLS}MZ?C3__~9#+vI$>DdBBQzE^vON>=Og2-bmH{Bo?)z03*o&i4(jD+s@AcU|?nkLygsNxU? zSl6{Q51N>T_~NaCOI^$F9&}@n%%dVi#+x2J1RcE?O3 z>9-uL$tZ}EWb;tjXQT%wkyJp_9aFXj6)6}5dW=WC#_GItnF8TFIrE3^QtS!(DT3ZT z(0?!=QX6y+GRP_5)*F}9ES996iKw2I=&3j@10o68r)M(SI8Vw6oKtX?Ru@*Eo1OfXdNSi$4%pm#7*x*xTC@8Hc_TG&7t`Sn|{um#O{ zfV$nB3E)9mxQQO^phPJ?KuMKz_DCy7KFARtO6IT*iUOgaPT{OzqYb!=q7UIiwj(9| zbaxfSZ{;0ncQsC7r|pgVdYe+(Rz8V$d~R=fOM98mhnZKTs}22QYIhe?9SkX+`>|mE~=T|d=i`6D}5ecRS zZ=5d|-g2*UX|9znKEwY{UL^>vcmp?i?AtLJAmWlA6~u5A(b`6!nz553L9}BR_TpiT z@dA7byYVzHxX+>!FLLxIue5KW8-GU+{>gRkVn6=PWd08xwc?pZr3ASc&s+I;%CS$A zU6OIP@ENvBsry|k#x82VZpFBa(yvgLk8`bf37=)lL#^lWIeeZwKTC_gz%i9JtjBZs zBF7{v)^cBa56O62{sQMDKZf9%Bb_U3en@T<88U|#Q0W*~u*c$#f|LA{e9Fwx(&d(x z&@SH9sn<@@FUf2XCy8!3b(*42gd42*eVOrN2>PqPYI8$O;p^e%o7gvtizCg~@Ew5} zT$;vY-y~W{N}p>AKl8a{P-XKM6s@7y6@f`?XfI>8!tVOYZp?R@uFw(}F?)!Ii3Tgsmt7M17ej2lV4cG7+fex!y zZSlG;qM}JgW4Nio>$-;5OYk~Q%Dz>%HeQ?b>b{`V1|_c9JeFZFx8Z^1vj-O^G=?AX4Cmm*)>#G~_L_{IJU%XBPe?zEl~Kwvuj z!KvGkT(=^tWrb3pRJXiN;M*Oulg3QuFvV;<8qTZ=3QqPwY;qstV$|g1B*P=YZsuJ8!C;?+RQhZN8eKtfPW?f$_*sfCUPr zlUpcf5vGP)0{PgSqqgaIPnn^0m6MLA;f_G<&0NeJZsV>pJ2wILp$-k>InF-R@sT?6 zGcsfkId-_W-eP0bZBK6Z+?EU;Gs??n)cv;QG_Al^>ok~&_Uw=tr)-`i7~{JeXY>eG}NqjiHC7!qa^1r)9DcS?%v1Sl!eo>X(++>*lb7M;aaq+14jHI6@dxrW~h+Oo#CQ($u7?Jea2=2+n<-`^4bSSDwNI(Uv5e&Jk=nq0FcAIL`X|Kj)*{@c;k- literal 0 HcmV?d00001 diff --git a/bin/classes/com/perfectworldprogramming/mobile/orm/interfaces/CursorExtractor.class b/bin/classes/com/perfectworldprogramming/mobile/orm/interfaces/CursorExtractor.class new file mode 100644 index 0000000000000000000000000000000000000000..6f59a0fd5f267565cf4b509c2491dd1296f8b346 GIT binary patch literal 335 zcmaJ-yG{c^3>+tr%Yz~Xb?Q*SN|Xd4Ap%t-irf$Q_LkE|x3`gR5BN3;K7fxx7)X^! zDJub>axKBicMy@^~FPvF=I363+MXUH!Tf=C}FH;i9`kXh0zJ^+f>bWv3YEoaxlV MP;2zpjd#f82Q{W*2LJ#7 literal 0 HcmV?d00001 diff --git a/bin/classes/com/perfectworldprogramming/mobile/orm/interfaces/CursorRowMapper.class b/bin/classes/com/perfectworldprogramming/mobile/orm/interfaces/CursorRowMapper.class new file mode 100644 index 0000000000000000000000000000000000000000..b48415ff52a9aa20c621f09e7afb84e6aac4052b GIT binary patch literal 332 zcmaJ-!AiqW5S(o_X{!eh-o4gKA9%DPh#&}+g3S+Xl4p1&FB>+A{WlMOfFC8U(o+i_ z7Iuf3+1dU2{`drNgYy(4!b2g^wO-$R(eFg-vQ?>+V+>8@qU53WPBgmE^hV;sckXe} zPV`lFFWj0k#R=hJ%kS)JHqkoYninC7+!~3nn6J1gRYK`X?m6eq?>&~!*Q-O}k}%zb zs^NZ6Pq_L|oMpzIZDi2GKUq@30dY7BWFKe9$;Aj literal 0 HcmV?d00001 diff --git a/bin/classes/com/perfectworldprogramming/mobile/orm/interfaces/JdbcOperations.class b/bin/classes/com/perfectworldprogramming/mobile/orm/interfaces/JdbcOperations.class new file mode 100644 index 0000000000000000000000000000000000000000..bc23a22111c8f70a0149a534a153125028b23e88 GIT binary patch literal 2342 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 A#{d8T literal 0 HcmV?d00001 diff --git a/bin/classes/com/perfectworldprogramming/mobile/orm/test/AndroidSQLiteTemplateTests.class b/bin/classes/com/perfectworldprogramming/mobile/orm/test/AndroidSQLiteTemplateTests.class new file mode 100644 index 0000000000000000000000000000000000000000..7ac727a88b716a096235ff93e3b865c93e36c6e4 GIT binary patch literal 25999 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 literal 0 HcmV?d00001 diff --git a/bin/classes/com/perfectworldprogramming/mobile/orm/test/MyInstrumentationTestRunner.class b/bin/classes/com/perfectworldprogramming/mobile/orm/test/MyInstrumentationTestRunner.class new file mode 100644 index 0000000000000000000000000000000000000000..ecf0a66dcdac5bc711974fc9611a0d4cbb4af207 GIT binary patch literal 1320 zcmb_cYfscb6g|UZ>n^L{@_q`UunWo~5q z^nfR7FN!5sI^jlUhHsucOEaVMM5acVNToaUbt_L(sXg>DEQvJKDhi9}-^MbO?nP;2 z?lbh(8@mjBEfvZNdQq;TA0>uCKT73`JlT_aN9@Itq2{YV#JfUA*6)1mGlx;e@XY^D zBAN^X2hyy^u@y$hv-O65loM6HPj@2ef?jjGwVg*sHa%QrxcN8DF1CUp3|ny{4D)sW z?2Kr)`Gsq0Hg-LXF}&0z2p$WnxjX4d%rHFYhQy(asgd}`!>8`WW%V$}u+a@lprtTMb64V4;aDgS z^9;|sL5fmCeJui+@m8)gr60XDS_A~%p?3XW0k_ogCY7*r!wmhI?F)wG^8y=UezC$f zd(l7)WokEHiBM{WN!x6{)}h#HR#3-^hXxJCg@7tnvBYqNU|iwOuqxXs*MWRY<4X7@f1W@x=Yon(aU#(3$JL~KGrjf)_hr%7_6X6;=#qtmQLcror0!rrsZaEgWzXLWwcANkJ literal 0 HcmV?d00001 diff --git a/bin/classes/com/perfectworldprogramming/mobile/orm/test/creator/TableCreatorTest.class b/bin/classes/com/perfectworldprogramming/mobile/orm/test/creator/TableCreatorTest.class new file mode 100644 index 0000000000000000000000000000000000000000..d0a7454e52b87cc9a27c1b6f5bf9a7b7318940a8 GIT binary patch literal 2462 zcmbVOYgZdp6x}z3P6$H_;niwef-MCCBv|XC4OWo?q9FxCQCfUVCbuwUGLz0sYVoJ| z2l}}#g;tj?Kl?}g7uJ1elJIEPlKLU@xaZt+&p!K{J^AaOU;hAb6@iABz%A3Q=4#Tr zFU{b4*Rv}%&)xEjYSnVKa#go%*)r#P)m$L`AZL2g2wX3>W|VC?7rm^}pdl_WWjGbj zwJMS8tQlC3tYCM^@dK}3l}=y;mg^|*Im4G%1%^tig@P4Cab$^hsoWN&BRzGBz)InS z$u;x(kBE7JQ!|!h1vdrS#>UqL;&X0ACeSHx$@R9fe$6B7`-Cr9i=AwQKTG^sgu*^bVBe+ z^q^0rk?4THfR1*Y5;#+^99gVa%hC%;6-X6a)3DbK&r&2e7URLTuVOT?2p!c9Y^N&qgQ%$4eEhLz$Vkcmum^*8pVM+nPU;m-{ zwRZ4`uF!GWs5Nn^oEps)!SXeX30yy6nL|hww@OBHE7J2_65E4}jtNXMixBMbUKSWR zOn8IdLkTxpAc3sF`PK-e{cX2ySJI9fq{}kx)NMOS&Zc#|4GvBhn?!m+(G7~U2#g*+ zEjPCk6`X@!%_ngKGa6Xg zh@zur9Up>IrG*sP4uiZRDb?5?lgES8!-{D5MBv8%pkcOB@ucr79&YKF$AUnTjTHu! zY}fv=dxvV>94_Vlsg5OlMkrf!S2}i}KiroZ8;|zY1Ix}8EI-I6P!Q-VMZ9=2sC!P@ zNZT|eP*mII3zY-B3ZlA?KC$Cvm@K#ypi ze^@tcCN=nqf-WtMudC>Hb=pnU5nM zvkm&15kj$QbdiS2(e?>7Ohvt~V+-4Cfo;Pth5-oZu0Tht5K3DPsBbhXqeY|B>V9JF zK3;wjYqT7wUPm=*x7O6D%f~j(ynNtIc5t%f);&`$@Z-iVIj&Dxl_V1{SzC@lrs-oA zUhCsF^IAHoJ`(wxc?^^MHh!7~VoIF()W&BDHm@CgTL|BQzDz2a()V#X^Ba0L_R;$b z`k&Gs!yvDx!x(3|s~^2MhqGMM8G-xw_6F}lDQ+WXnfDmix-$DX{{)G`#2zj_4c+5B zdWgYP&=lglUf{|_ZXII4;V|$(w7C&DL9a`=%-tjO=HH7&Mu_wEO7lF?MP%(XI+>r* zpBml6cp)`4@eH}2@D7i@u9n+>$447&snOC#JT+U|!<<^&!{T!4^GSN9mfI(v#v z+~LCpwIlun{paG(@wLF8FpG>e#aL>E-2M3CZ&jUm2qcS6K93;DoVqc}wQ)=$LuH(x zzD=^mQ`kfnCht{DhafW{c&7m}i3%({AgXKJu>+eW*d*90*V^DPx~g_$b7@nh7)0y^ bR?)6OXfQQStj39<4#iNTIfjSu!n^-3f6bqP literal 0 HcmV?d00001 diff --git a/bin/classes/com/perfectworldprogramming/mobile/orm/test/domain/Account.class b/bin/classes/com/perfectworldprogramming/mobile/orm/test/domain/Account.class new file mode 100644 index 0000000000000000000000000000000000000000..a01462178fc2c45c4fbb8f2d6113841742eae67d GIT binary patch literal 2850 zcmbVOTT>Hf7=FGSA*_fIwJH|0tw2yxkEkJN2tlJ96e5aNWs|J1m}KK-V~2}g^`<|d zH|S^ZNERmous*D+r%J z-=_LRjTTgDFJ?FCM8Koxc|X?>%o(Nin85xe8tFxCMX%`Df|e+i3`@0iqf`;NIQNb? z)P_~`x~UgcbL*P6MeqJ6YN4tLgc8Z*;?0H3gY=9*kLp0pY?UbrH(^?~OlC;C*!x6I z8ii`HL~CU`T4wcnN}#J$EfiEH=Ox7u@L6`?_sY(RA(1nVFO#~R5eTS7$-IDIa)HFW zOq9ZxN+nUI=r+1iL)V0VK0SJeV-TR3wDJvMqrHp`-d>$pMe zq$62SD^%XyQWE*Tc^?WNN|R=p_%k%8BV%EtP1RFyd}=l$3wV{d$N7Uk0Nq%rF@z)pILG07D7 zBpH^1TZr(1TsEp^PMhV+-XL#WGK|CQTQ46jA3So}cnb2=!?lZl-4%o=;83}OeO!0Y zfP!A^yn{aM(h$aODsgCBrLe8!kxF|V`98`y8n4R_IP!ybM7}`O_>l3VTm@Hu8iGNxL;^9tG@C+w@YRlqCMu^ zS2YkBevT9EK#mf~@Ed?QRTMabvvnZbwRnb!r)@wY9f6$3g*uRJMh-s5L_3gi0*Sr> zNX%{*eq-uD{vl6(#-HjNob<)}1_w4s&Dh@vdVfSnZfl6I#U)+8A~7xHhY$A+eeva2 zYum~bYw-b@f!FS)qv+=T6i=t=_Y6;GagggFoMShg=kKKpj2^S`MK~ag>{iUn+sigS zKlQF~=b^=Zq;Zwru2J(4Jg+zr-XMe^ec~0dy9bZFkguXk(M!6P6PS&R{Q$r3DKqkW zpGIm}U_uMu%fr~85c5v5$}uMT7xqwt8+oW<>08^vNt{M)-#;Z6b@jPZF-sGbOpzmQj|%>nbbvMo+avet~aoNWh~-8KLl$$ z$$=blvZyz878%@Rj)U~Q!Xfq8#PlK<^eZpXPiA)RmP5=J%4Nc!2ifxR-*J02eCGu| zV~)c$+z)4K$jf}Wgx8(@i5m29!P!sLPzpchzJ^L;W_xWwEBrFtVwF~!IyGK@HL48f H!IS?1l(0pB literal 0 HcmV?d00001 diff --git a/bin/classes/com/perfectworldprogramming/mobile/orm/test/domain/Address.class b/bin/classes/com/perfectworldprogramming/mobile/orm/test/domain/Address.class new file mode 100644 index 0000000000000000000000000000000000000000..48cc6f8769a796078c2b6eaf61aa1c2d72801c6d GIT binary patch literal 3763 zcmbtWT~iZR7=8}qix@>gp;WC=TZM!eQQIm|3i45-C`eK&ScHYFu$b)PCeh+mulxa> zUiGfywBC5p&J>(!XF9#&qJN`*qto^|dls^Zi=%Xg>^b}H`@ZLS-mk--|NQzpfD0&v z(IC*fWEInEx_w_?DnGXDLVnG*mTj$AG|c66(ONVLdfKv!>9Srbr}I`(GtBf*K5y$K z+6M#MWBbvq~N%dA;T zT47qV4f*a01LYNi71RHw$@4OEE0@$-J3STQ6lm9U6NB9qLl7Z>r{3>w#ds{m8vR7e8M1;7p9wGr!2$NR=bGf+9}S6^)8b67#mNfzJQoN|K9|EftI~J`-rK4l*UZS}_WF-Hsr`BF^M{<57&^hAiS_L4rv3rry9HvT!8OPpjY$=Mo0gKT!bh55FRYlOe15~BRT zmUBO}bKOq^emH<;9S3m;EwgB)61(wLr6YApY}8kk+Uu0q!>=lJ)G4vOT_p+j7=Ofc zoN$DkpnS&3Bh6KC4JKaVqR;546-CP@8#KIKtVzy~=s-7Vrks-pl+T@$<8H=yj*}M2A})udgE}sUB>hR5 zjA9T1AL1iE2z+UgCO!CBKRBmdQ;_ai8SU^10flf>_2$o=nCH%2q|W89Pz@oocyJnF{zc4m6VgID?eH#*v1+I z9&rXg<`n)4!&t{%Jn>|8&L!1~>m_XgV*mgE literal 0 HcmV?d00001 diff --git a/bin/classes/com/perfectworldprogramming/mobile/orm/test/domain/NoPKDomain.class b/bin/classes/com/perfectworldprogramming/mobile/orm/test/domain/NoPKDomain.class new file mode 100644 index 0000000000000000000000000000000000000000..2ec760185bba8f7cd57f74d21e095b8dd837eca1 GIT binary patch literal 1501 zcmbtT*>2N76upy`q=uHHE2VS;;-r8@UJF5}i-a1bQ4>YHAtxEaRJJFwoud8~NFXF0 z_y9f%al90#sf$8+@Qm-wJ?Eag%+Fune-KfXo@Ob*=w(lu+K}7tdC&bQZKFT5<-pcW zQ&gBa>v#B($s~eHDvQ>-~Y{0iqYJuex_@N4#08u6g-SFXSy-s&lwf! z(PhiELAuLm$vgm%|1lE z5SDOjjFM`(1I>G~&-0X|MTH7fWHehB7H^EqF1On{3huQ<_H?78+rqQM!<73$paWBD z8_z5n2~XRAyPa?V=GF4m5y%mv2MVPr17|04UQn<4dKvv8ta`|8g>GL$qA#9DP+g2P zLQXkE<0*vA@gk@S-J#h)+XZV){SQ(viF`|r>>fYFi$Y7Hf<5zI2yG&467Moe39l}& zvakx+Z{Z~8;4sf=h7?%H{;&7Y9^TJjpTh_IT@a%2RKz+DY7INXp00eOh0pj&&=OXU znc%vNRS6tuh3>&(v`Y7}UIu@mwNJPl2Nz?(>$DMqYw%70ld0@{rL`z@-alPJrprFV zV&D~q_oM}dVJKFdkgZ7}tFb~J#tYe+6ta$R8`lU4I>6`=J&vhJX;R2`tdKHQ;wn;_ T6jFi^^%@~Ts~PS1J$UjPF4aaJ literal 0 HcmV?d00001 diff --git a/bin/classes/com/perfectworldprogramming/mobile/orm/test/domain/Person.class b/bin/classes/com/perfectworldprogramming/mobile/orm/test/domain/Person.class new file mode 100644 index 0000000000000000000000000000000000000000..2358e41b1965d4350ed31739bfd6a19b4ff16e6e GIT binary patch literal 6305 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 lb+rg(QqfOr-a5(N+7Q7CJR zl9Fb2XI8tK+3%mvF92tl#0UsCxwEQa|HOIw>U>o+-j!ZkYwA*2mzj!{^H#OIYE|K^ zHnn>6t}f?q4bODbaBKfcr=&474fIrIPGn)`{@Cev1J3BLX?tSiapF8u{-*5f|a2r1w=n`0S!QPvYoLbEbs&*~h_IzoFQO#B|R`yfr)6^~ol_>No<@Hj@Q*x~?gQa9+gEj_I z0+UYDqIs(5DsRVAKP?BbiW)T;C`Wl=psi<}Sl$-sZ8{cMDxDI}2}la`IpYPMx-Zb3 z9p4m4&4v|e;vIpJFskO`dc*{uFj2{@pXZyI=9y_;XKLV#z^zkaNvK(IydaHkoV8%! zJ%Q0|>6x?R*uFy^%SuNpbgaz!P8=6Bu(KsEkgJW_wv0BMZC?sxN}=ocn@;5Ed22DH zo_evs`e_MDK%Kynt^k?piKTj2*Wd>%T!5LzAg&m=EO72Hh521q)^*t|T!l&4nm|=n zj{AHga$K2)z;z2lxWNRfQXMI_z)*I)bRY|-Ubl}J6wFjT{mn5$^_fbpzJlYG{*3W*6*hR#caD;M>&1`FCBL*w4}Z~ zzS&1bOk3zduYjPeFLYS7)kOJqyJ}Zp@IS)|oJnN1;?!HcFrdLMO7$r6lx~qZhXZdC zjsJ5CU!X|oQXxn81#%ryskBbn@e7~Vn9b{q!+|gAQDD}>9Oemt%_<|c8miTX?=zLo z=3d)=#=DcfoW>%S4J@(w4-|ZS3=3c3>!z4DsRlMza$7B%SP_5*ux8-_)&;C4fcX~< z$LB3D&>8=LaZ)bORoNCeEZy<(Nxrdj5Lhe=m`Xa)T=eoZb31b(`UFtFXy>`7X|*!&ZkPv9+D1$&34c!&NRzrGw7qk7)_EVi8bFrvf1+6h3|N(3y<-AGXC%nXDVGz literal 0 HcmV?d00001 diff --git a/bin/classes/com/perfectworldprogramming/mobile/orm/test/helper/DBHelperTests.class b/bin/classes/com/perfectworldprogramming/mobile/orm/test/helper/DBHelperTests.class new file mode 100644 index 0000000000000000000000000000000000000000..d3a58191226fce69d6f7ff51d4547dabf289ff1b GIT binary patch literal 1986 zcmbVN?Q+vb6g}%WmhFl{Oi4)jN}&YXDHf#=J{(dKCzP~KfI6hj^p`9zMj%U$v`*h!GaIIfvVUH(Yg)zv-co;~;KufKnP3*b7wH;@px?*uKYEyHKh zQ9lNu*Jy`9GqhVR*Kb;_pzeCo3c{A9WTdR;(qpK#vivZ9*yLVhASrOw_8Vc~Ho9R; zj&gTh_0yUksj$HB1`dN(OxCsL%1ZMNq7xu1g zc{YWrDUDVh*r|AS6qPlx<5ky}8=Y2NhMRWXlLEPF;Mm@l9lCnm+f1tGZX~cgsvt3` zAyu@(5v3WAq#JL3~ICJ`=bzVx6(-ji5y{SdV2G1-^ljz}@%we5uh0 zWyJou_MYE6PSEjH8tf;7zSh*TIENeBpf?4U@_mJeb@<^OqYiBJyu4P}%J39#nHWb( zK+w0R2BP}zq1}$frdhY!Ju9EkRJa$amF3uyn$|rNi}oSUQ8HnOH`J!0a&@s*ONxbUcp)2Yd2S{RL+lTQG}Nd}ZJPd-lLf zM`M_Hh_$Y*ws^*Dk$A|grSXjbG=X&!8+asOb_uNRbZn2!J2i-Zpd*D8NHppKhX-;r zJ|#7F4}gVcQVTkvBOh=WQ^0?X-;#E-K&Iw4eOq-x1~~n5kKOuT(|F;3O&mQ2%Zp{U zHZ|dYgo0>;@H)n418H6}T-}P-K&F_>=FEM3_?nvuOz@iJ9hhY36monr<0KiJ#7A85 z6#Gej=97-SS=`6uFGyGC_HerR2hMF5_i$kkmr{SCusxQWt8FK9S8LnjIjffYJhhK6 ze#89hIBk-grpZMEPm(D(>>E@M3-01x=BKm7yh1K{oJJwWo#`g&<4)i) Yo)Bn)(chv*RtanpCV{8eitpe30~7=!=Kufz literal 0 HcmV?d00001 diff --git a/bin/classes/com/perfectworldprogramming/mobile/orm/test/interfaces/AddressCursorExtractor.class b/bin/classes/com/perfectworldprogramming/mobile/orm/test/interfaces/AddressCursorExtractor.class new file mode 100644 index 0000000000000000000000000000000000000000..4fb6508777e2887c4353ea9ded630f3867a4e993 GIT binary patch literal 2674 zcmbtVT~ixn6n@?S*$}qnqXi07Eq*2hh~L_#QezTIYWOgTR8WgcvV^6{E^aoo_50iD zwO5Y6!5O`wVrRVY!V9mwbDZh;OB~1N-QCI-#i2M1yLp~--gD0ToU`xy^Pk`U0N`q*OQBpto!Bn{J{r&iIM$#k`9 z>&<4SWj8H5ch#}AieuRd+68(xv@I=J*BD@ab%Svggay(EOccnmC%8c8LatbvpIgai z1^NoRX-baGa#I3FGM3qNG}Bqs>McD2MIbtzFP6$HbLrV!1YL|#NdFCw2!v;H`SUa7 z2)YH@(&y>Z%Qfk2wwNoGm?(l{bSjmLxg4GP1==(D@=^qY0v)Aty37Sb0+HqX!b)a7 zOEg0FvxaFnQw$i3FUl2GRga<#qblyfy#n0@!_?MEkIE|EoGmN!6a?-BiES{tLmK?VE zHGyNX3-Lg3>640L66a*&pO^N%*7%}K{DO)MIMba>?9H+)GaroQkGPCBt>Qdpn77HD z8P2tRwzMdHFQ|A?`bOwmax{l?IEh&mbCT?INn6()$u6jPNwQJ0%f_Z0S_LJ6(}(E8 zg3e>XjG~Bh^0BDmq71DvwAYp4P7)8w5B6@DadOoUdJU*kgU~mzY*Ds zY!q)`RRPB~aLRZdvKtktMK-9LXJZ$N&{eE~O_kf8(T&zz*1le^zP0A&3a9@WdWN419vvgH@X$jr3r=#vx0Pu-~B*vAZ~lc-Og>P zxB`x=tk#oLU@CT)57Jwml1EXv;-1$6L;HU7oGZ;c+Xc=ZCY^sX@SF+rUf~!Bqz)6u zFPn!t2e)#0R@?N?#fkqquy(uR-96M@;3E|e;}MQ_$!ggZeVUh=z{tN}VUscfWiJ^u zQ*&B2J--NiwSLrtZphfZG56eN|4ZAc6h^tPHvV@YieV^-@OLLK_K=Ia0$8Q}NB|!t z?hfD{;@$x6BR&?u$BFv`cz}2?fKLz)1@JKONC2O7>*USH3h!fuNxlW&9b-3e>RY$u z`}qvJWH%n*Z`E_agLsHY$nNpU#iGs)x0Cx_%qD)qZ;2hm1ir*CH!-=CNc0`w!J{GU z;K>la!?QOqH9JoBgwLi!*hWq=!$Br5nSmfvkj%*-Gk+6BnIP(uw-c1-CdjHm*Ow)8 zG|0RnnI4~cRhG80jjAO3d~#iq^=-U4KCz9~_&3~P8>A{zY!xV7h`SHt6wxSRw49+% z1?qE&3T;xK>s06~TE6D#`6I^gD-yUxsim4@o?^b5)DGA17WE9#<88dd_jQ!;F5Y9# z_vz13`UAHVO!lN1`2$aR{tEGreHu$_<3m|t$gR-pn{YEpdk7!9&rk5F`~K`Ne6Owd literal 0 HcmV?d00001 diff --git a/bin/classes/com/perfectworldprogramming/mobile/orm/test/interfaces/AddressCursorRowMapper.class b/bin/classes/com/perfectworldprogramming/mobile/orm/test/interfaces/AddressCursorRowMapper.class new file mode 100644 index 0000000000000000000000000000000000000000..2e78a9382f8471d220ce07a241804cdcb77ec3c2 GIT binary patch literal 1790 zcmbtUX>Zd&5Pj>kb(*?21zL_$&ZMC=_mxrzNeV7$Q<^9OzMxIK4MwpY*-i_;gFgaa zI3@Vbk3!5kK`}>BD-^}+c{}sw&Fpx;egE_Yz$I*|P#D(guC2F(wNpvs$V5yuciBAd@|7Ru#k zGH9S&*(?+)acB&EIivC6 zJWdw5V|uP->Lw3(jr&6Hv@K(#_LbIjZEiU~&o!gs1jDWU=>C;p2q$q`#VLkEy9m^9 z24@*Y8Y0NK&9?0rjwxO;OeOz3;FKZxk{VK&XHY4m=sFELn52vv$!OW^|IXmeK%E=iLYw7hU*N2l(;i;QYJOHm#;gC zlI^C3TcATyeX7g~UhPs+Rr=o6uq=J!@t>pD>rCekpgz-Oqv05iQwe3a z?bXE!T`mkq{(hA#N(Smd*=jgEXnW-OI@0eh>t0LP{Z{#}E-Ys-M|H*M-%r08sEE`1 zAYHHu5@c%;dzkEzh&@X7Si~MDdm>^_hP-s&5aU5&)M;h3_Rqh^p|@d*X?hNX;0OhS z(uEE5t;IAaFkJkEU%sxq{ClVhqr{E*bDfoc&dt6*!Aat~gUQzH4HzYD1 zMV2Ho97XO(WHO4}TX;ih6i8_^Bn~)C@6$+=b(@5hNE#<$Qto_5QdcgCLjfyc33c4Z wgOFtv238Rp%Tmn4ZZYSmGck%+=hH{uq1a2<=>-eP6>?Cp9zILh2-inH0Q)J*g8%>k literal 0 HcmV?d00001 diff --git a/bin/classes/com/perfectworldprogramming/mobile/orm/test/interfaces/CursorExtractorTests.class b/bin/classes/com/perfectworldprogramming/mobile/orm/test/interfaces/CursorExtractorTests.class new file mode 100644 index 0000000000000000000000000000000000000000..12123b132ceda41ae8396f95d53e99eb8ed83ab7 GIT binary patch literal 4507 zcmb_gdw&~86+L4sUPalquF?k5rm>)q*s?9<(S$UzlPZ!NJCzkDQcRsf-L~LjRVqexE?zNbjItg#txDX{Z6|J29q!bM zx*bo|E!(s*R~$<#I;K_NYg<7;U{I@;EYm1?Cz3_SxMVnsV^!O+>J`1}XpUi4<@S_j z>jwmaj$WyiHAfdXmTl9Rq^BZ(CTlo)!9Sl6P;HH}^ayA;5XARro zj;(oPuBth8i?7F9UJtda-sPfXRy3m;pU}xeHF1ox@A9-KOC?LUZGqhXL%uJ~RnRrB zm+2~jBkfx19f+q-jJhXjWY>^UHJoDtoxOdN0)doS(u3G8@UUsk#q63zzt7VDI)mY2 z%nN`R10W_rE4W`^Uz<*HSsEutA#~zxD(=DC1@`oMq?9#=SKg7@5=|?qvS!XUedC(Md`v2c4C*5)x8x0yHzL%%27ncHUtIk$r@EXSFg+a$Tg!68zyPsM&PvBGn@(~@=qJ-vO|wFK2_wRp>hLs2R+69Nh|Lz))CAks1{GXlxp2E(m9Jh>^xYb4MdXZ^w~^4AJHP0=XFbuXff~I^jJDF9H}+Un3kN6 zjGfIFrgO>h3}5d(zE{E10(V-?JWE?{^bn@8OF@y>=z8Lwp1Ht2AqcV(IAzYWw2xv= z#XJmwyBF%ZwK!s0-X?)(Z&vHu^vHj&wTb2=@>C`Inmpt$$x3)pMHv-3ikFIRIXTnG z)yri%wArvV5e!R{akP$gj5Tadw?e35K?XhV-9Rt1GlT>j6?I(VZORImoRcxaEZTIG z2_tYt#Uh?zZ{it|S*UAeUOjtnVndUJhE-DAvnoD_4^afQjTn~g|+_yoeUp}PD z=cURIx9He>+4?JelR;c%Kae(csqCXFJ|>lIqq3~#=~D3V4PlTr>%2>Y_#`Pg6x&}4 z;YEB}a`c%NavLh7fSLrlk2Q?vP)R^o^Le0 z%Vvwsoj~HYGHYXJNW82~vLlrC@7UOlEY{XKlHD7NhYz`_db}i1*jPOpHDjPrNZP6% zTI~GT#B}O(Iy3B6j-Rm+YBMcctFdq9rqb~;b_MYZlDz-G!AA}S@hduVV%{igCHA57 zh8Dswey!q~3^aw|km4so5Wf}Zm`KWZ*HtXZcR{{mm30_vD~v!&i=41btrVe;be-4k zFy2tHD!0n0T3@}P;!U|KTa@!gO?J6*^IIzZfIoVhy{acL%#gYr_^s|$eE0IAz7sh< zg}hHfd9!X6^$~t@3G8g)w7|Q?j>#YuC^i}l*B`g~#=1STWXI004ZMT7(#a3S0RMP% z^9k8(b9F069SHHsmb)=mIcLYhXMk&L(D}TVvvZUp_}dc=hr{V5UB?LbjZQ^h!^jd&EhBdwXE-^t zg8VgCUx1+d2tiu5n`2PBLft{^p+&uHm-{e+D8|w6TDils#J4g?EK@j7Nl)@5Ke$g) zn&jtw4degGWy!G-et%YK?q9_;>Cpl=FhiS5`6bN0g~a&43NEaoI@L{(wSgtrE4Umk zaqxi^JQsd}gO6~qiWjHCpIFAHIR7kn@aK!UK_1;Q_&UBSu!3((rae3{IuM9)7AMF1 zX!Cv?CL3G*1g(vFje$2dyjBu=oG zPGJIRJWY}eI^W{z3v7gBkb3l7ZP4?4gPs!pgg=v>EXkBab#nX{p6I||{fzqCe*o{g BChPzJ literal 0 HcmV?d00001 diff --git a/bin/classes/com/perfectworldprogramming/mobile/orm/test/interfaces/CursorRowMapperTests.class b/bin/classes/com/perfectworldprogramming/mobile/orm/test/interfaces/CursorRowMapperTests.class new file mode 100644 index 0000000000000000000000000000000000000000..ce0b1f77e234d4e4beefcfeeca2049d21465d383 GIT binary patch literal 6895 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 literal 0 HcmV?d00001 diff --git a/bin/classes/com/perfectworldprogramming/mobile/orm/test/interfaces/PersonCursorRowMapper.class b/bin/classes/com/perfectworldprogramming/mobile/orm/test/interfaces/PersonCursorRowMapper.class new file mode 100644 index 0000000000000000000000000000000000000000..7e9b9203e4ca0cd8fea648b605492c48476e6565 GIT binary patch literal 2014 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 NkQoX8;WdDF{tM`|+|B?1 literal 0 HcmV?d00001 diff --git a/bin/classes/com/perfectworldprogramming/mobile/orm/test/reflection/DomainClassAnalyzerTests.class b/bin/classes/com/perfectworldprogramming/mobile/orm/test/reflection/DomainClassAnalyzerTests.class new file mode 100644 index 0000000000000000000000000000000000000000..46356f2db891f6e58b78d00f04a8159d48a1257b GIT binary patch literal 6174 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 NW;2af@L@=;{0|Dc(JBA{ literal 0 HcmV?d00001 diff --git a/bin/org/springframework/mobile/orm/Main.class b/bin/org/springframework/mobile/orm/Main.class new file mode 100644 index 0000000000000000000000000000000000000000..8e21a27fa58906c85c55af2bb02b5e3428495f2b GIT binary patch literal 934 zcma)4U2hUW6g|U7p>!=3ELHIXtW}_mllY2hM2xY?R%0+U#;1WD>F6@M?haI+{7t?< zqKQAiA7#7)v^2ipKHR(WbCnL_YZ~3FJT(IM_ysVKbJd9cUx9=_+|fqH9O>ZU)yG4p-2hNw-~ku(zL?RSAAg=$+d)E3`4nAzYyG?tKf^nW)^oCGGx1v zvB_Zv73*S^p|vdX-#72wk76viFZ6)7eG$jaOB)?y8{4GvEZVMv``BYBlC+aZ8SDRZ zK}p19WaE-BZ?Vhc&puVisZvVkcc}q|Sd682q+=s=Uv|u_6~&9fmYtwpdA+$i3{O|J zcZI)1oa+Rms4rj8d@`)t>3n4CN0qFnKGT<=KN>xX8Cr45jB>g$MfUsbI7iVQ16gcP zbmkW*U!fJv2l5o{gKgCa?;&W<-@a*n)^)@c<8rs!TLB)Mv^Y^g4n4zsG*-)c^nh literal 0 HcmV?d00001 diff --git a/bin/org/springframework/mobile/orm/R$attr.class b/bin/org/springframework/mobile/orm/R$attr.class new file mode 100644 index 0000000000000000000000000000000000000000..403bf6ac7bedb076809f9ca21085acf8473c1c12 GIT binary patch literal 376 zcma)&PfNrw5XIl@wp*>$T~{yOJShG-7}l%eWkC>%!YX@DYphw@MAEK)E>D67KY$-f zoCNPm;Jv&VCj2H}-yfdHbQ%=Tp0xdahm zw2&`S)Y4SqrdX)5BMi>9(cJ~1e|R(}L{odOQuMK!A;y3(%(YS1%cfB7P8PKyjB{Jc zdM=&z`L`H#kGdrsBc!)>=}L9UlngOD@nnST${6LQwQO6}CKwZT|9X&_{eGB$ xci?XUJ9&22gp&vvh>zc~^2UW8QdZvv*7yKfxX0}4p}!Gyh!J}l#y7ErogZ_gR?GkZ literal 0 HcmV?d00001 diff --git a/bin/org/springframework/mobile/orm/R$drawable.class b/bin/org/springframework/mobile/orm/R$drawable.class new file mode 100644 index 0000000000000000000000000000000000000000..2d54064ce01e3be21d34fed13c56dde54577b2a3 GIT binary patch literal 436 zcma)2O;5r=5Pd@n#aaaMlbZ(*qKO;5YP^t`kPuDKaNm{{7u#L3EpqfXc{1_f5Aa7B zr;VQV@@C%b%*;3)>vaHH01Pq4y0F!ehVy literal 0 HcmV?d00001 diff --git a/bin/org/springframework/mobile/orm/R$layout.class b/bin/org/springframework/mobile/orm/R$layout.class new file mode 100644 index 0000000000000000000000000000000000000000..2f07745732667af0b915251993da26f15cd84092 GIT binary patch literal 430 zcma)2yH3ME5S)#Z7=lAWc&4L3f>3aR7DQtSDN+PdKXWHugoDdugCOjUyTh&5< zc7$cL2%V9(>as`^yrN#>-oLT2!qi-<(?8+*RJqWb-_+p#`vhz zPKbuqDjyq}Whx7?McDo8Bya!x0LN^IT`~62K$Bz0tcE4dsPx0Q!WB_*pmF$y=(QSI eWh@tfE;@`+l{c8JRsCLt>)7B}o*`^v8~tzJong)Z literal 0 HcmV?d00001 diff --git a/bin/org/springframework/mobile/orm/R$string.class b/bin/org/springframework/mobile/orm/R$string.class new file mode 100644 index 0000000000000000000000000000000000000000..4fd1766dd64adc7b4cd5ab4e7805f452f4a95dd2 GIT binary patch literal 463 zcma)&y-or_6ot=q7Zwo&@fRx#6UD-fwi+7}6B42c8d@`pBP`C&keNkGpUKL^!Uyo7 zjCU3bJ8jP7oBMn2=hyoOfK%*7SRx!4JC5DVrh5EfMJAt(eT*}cq)NudX7OO(NLL~ z1c#j=A?%uaSw(iOq0%qOWMbo&3?|BO(* zF>^bTmu!vK7#w>ugj!E)X}d}|CtZXc!roskxq5LFoUoyQuepRaN+>f$1yz`re{q!~ u_0F^|dHzvib(VI@VZyDkq@D><4TVx`{1*7wxurNc$V;3@@3?e0_g>0yx92z#L)Ex{-{Zory*dPKA1E-IENhZvri?3uRBhBh<(0 zMae)#BYEqO^&laXE=**SOG4qO-6wb*JJb~vFkeLxB|@!hB7HLneeLd*A810OYX>Um zD`(R9H|ZshCMLAHd3~G{DtC6`2KtJ73)Sl>el_CgCvG8K_q~Ne4C)0^9#_#YwsncFhD%!IS2_ftk_?GYXDm z76ZlOca+~aF^39cS_Z2H#%iXE%!^rlDZ?7-%q@6W=K2bnSY=*k-e7L>*<#*7^9PGU Bji>+s literal 0 HcmV?d00001 diff --git a/bin/org/springframework/mobile/orm/annotations/Column.class b/bin/org/springframework/mobile/orm/annotations/Column.class new file mode 100644 index 0000000000000000000000000000000000000000..d832ca2b61d1973329e4674ea092f4a1f910ecbd GIT binary patch literal 795 zcmbV~$xh=y5QhIs9L&HB`!dW7yM*9^1s8-kArd4cHYJ|XD4aT>hz#v+u-hPBZ4NvD z4}~a;#W_Sm%%Nq~@9(d!r5~UEJpkCmypIxL!zP^|y-p(2xkyyZcQ&~SV%v%|2R4ZV zWsG&oMb@Ojp4C}we0YSBOLeOPtxP94XvbOZB4ln@nrf(wxUc@Z9~i5ZjXY(=CN!mD{)e z+v$b1zae3uVY8&o`!YPj;LEty^EL@H^~|^^=08yyNzp~0DPgv26kT%*RnlQ6buIP& zU(+13aj(T!_77@@Rl-7VxXw;kS)=4z`2ab!I%?kw=+}QAhX+SB!eVbr)wZ*|20j;h z`}5;#uydU3tdK0UETjVG%|!`btz7V;DyX h6XGvn5>xVBhKFeZ{4)^aJ7(}Bj~GAk3$p^u0nZzR;o1NI literal 0 HcmV?d00001 diff --git a/bin/org/springframework/mobile/orm/annotations/ColumnSetter.class b/bin/org/springframework/mobile/orm/annotations/ColumnSetter.class new file mode 100644 index 0000000000000000000000000000000000000000..579918d8098cc73bb64caea4d61b989c1cf42353 GIT binary patch literal 481 zcmaixO-lnY5Qg9M!`1rLYA+(9cqn=?;KhR{(F%eeWxEREDJ|0_HJg-dw$i`m!5`p{ z5~mlphk}QYc{5LD-b}uKKED8*qaC3laN&F^^NH6s9eI_}hx6|;a|3NiI-f~ptqUq> zXLEV&Op)0>g+M++O`theQzebEseBrYX&54`2ppEDjW z^LTl_YbYZdlG%h9swJJjM*|hCb6CL!HhJIYXp7U)8w6n+O|<5Uu!G%SZ(oZ5 literal 0 HcmV?d00001 diff --git a/bin/org/springframework/mobile/orm/annotations/ColumnType.class b/bin/org/springframework/mobile/orm/annotations/ColumnType.class new file mode 100644 index 0000000000000000000000000000000000000000..db560fc4c406177426f1abea1472318a9b4ac0d8 GIT binary patch literal 1267 zcmbVMO;giQ6g`i$OhNDIGhmUTdhqG-1*dr+a^p zmIaKCjB9_C<9(shY}_=9+;@_D?>pzdll=bk{R+S{tjic;SaZFG+B)?tr*Z7@ruo_R zKB-N&X4$6ddQFu(j_Y&Za-EjC$c@s{sx1T%~fcF z9ruG7M>GkB2?Z(KVu%%cDe0`63Lc#=*^FLZG;&aCBwn>ZE z+1#MglgJ`3BgZfvlGJJWW>diumKhS<^LVH3o^}}WVc`e06SM9YN}*Z&dql&aLks8~ z95d{O%X;(54R}^!1Wy$_!76z)+;_+3tyUpK=4PY5FkwfsQ_^tTUfp~{UZ%nK-Mb<( zNwHxy9PYP0dK*?Js*3~C-Y9IY(rHWdg+(`~g+~C2WRD<{GlEE_0LC-I5|kMs$0!(~ zx=})32#c%y1FV`FlP)lRj>!O|BLSESz;rYKnE=ej0x&24q#~({NuwI+V#=sSyT};T zSQm4~Ip)7n-yz(mdz!d`%sE0FGQ?t$7`z}J4}uJlMc+b?(JJW?isby#>;)e7o5Uyq zy&@%8%UBT7sPQ8_?v=08R-!!J#e8*F%3oEBg5{nxbBV>}uk_}c(seg>Lm@$@ztZcG cryQ|YGR5+jP=A5_zix%Sr=55Jhk2;b?p$(I~hOUm&`1KyV>hiAf+BA0*L@t4^#89cQ{jPfsMj=E4u~ zqr{qxlSM#WG~KuBRMn;G>-*yqzy)?Z^IBxuYb!36sIywNT7Cl*2&3Bf zVUl{FSEjEz|Jc=y36n_o$T_n06Tt(_^C|M?1+UJ-GOHC<`4}bSu*%OI*09d^F$&n= Vu=fH%D5HXEstB9dLXClK;0HT+tlIzp literal 0 HcmV?d00001 diff --git a/bin/org/springframework/mobile/orm/annotations/PrimaryKey.class b/bin/org/springframework/mobile/orm/annotations/PrimaryKey.class new file mode 100644 index 0000000000000000000000000000000000000000..c02d36d3cf8e4e5e848a2a7c57453253540776d4 GIT binary patch literal 582 zcmb7>O-sW-5Qg9Fhtc}cR;%Da{DPtv7X%N|lh_uDRZCmFc-q!!NKLY3v#I2-dGH7L zqr}O@^iU8F%kI1L%*@No*Z0RKfJ^K-$O&9&}n%zm?6dGlLFpg324OaisD^KJ$Y zZ0eyQP|esTO;qe#0SJ@^IyPf!voV2kX5}I+A+X<%L+b_f>_y(lr>sUKaIny3!P8I~ zmn?TYSsris6i{e~$&45(wmYqEQ{ZSh+$YN{kBQOxA4pI8-Z){<=|4RTJNGSt7f!x6b8cI6~ReKiIifQLd{ z7}_NggKgd2@B4hG`~La-0&tC!01d*8^NGqA-q_^L>x@5~e^;5CnUt0DnbOv}LKnu_ zTt!~n+^{VIY!fy#5d7V{*ps&_m6p`@UqFll O9HL!Cj3ab#4EzEJeum`$ literal 0 HcmV?d00001 diff --git a/bin/org/springframework/mobile/orm/creator/CreateStatementGenerator.class b/bin/org/springframework/mobile/orm/creator/CreateStatementGenerator.class new file mode 100644 index 0000000000000000000000000000000000000000..3fb563dafbc97da830a41dcf2394ca3dcc018cfe GIT binary patch literal 472 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 ZG&=HVbf{WkF`53gpnMnp`Cm;g(}(~7 literal 0 HcmV?d00001 diff --git a/bin/org/springframework/mobile/orm/exception/DataAccessException.class b/bin/org/springframework/mobile/orm/exception/DataAccessException.class new file mode 100644 index 0000000000000000000000000000000000000000..dfdf19038dbe3494f15b9134387988d3ecd6af50 GIT binary patch literal 498 zcmbtQxlY4C5Pg#qISC1Y1eA`BL&6emqDUwK31m?aNWU?QS+IAbT^sl|?!(0%2fml`iYsTSo+2$zI+JfJXJ>f zW08u3FqF<6esNWl2)!F|C;V9G$Un<;suKDAPiQ%5m58U(I@Y*29uw$<&=?u*QlZnS zh%;H{dGbeu%0OwA4hfyD;750o=JWNpr-ahTTuKi`EZ57US+m7Na&J&c`a&7Fr!f1$5s5 Dq{4j~ literal 0 HcmV?d00001 diff --git a/bin/org/springframework/mobile/orm/exception/EmptySQLStatementException.class b/bin/org/springframework/mobile/orm/exception/EmptySQLStatementException.class new file mode 100644 index 0000000000000000000000000000000000000000..595886c082bf49688c4bf78c1c2765916e269fc9 GIT binary patch literal 576 zcma)3%T60X5Ue)F2FJY2E6RoC1{}OnBu*eCWQ;_#LPSn{A1{p=*qzzT%#!%CI3aQ1 z1NbOJFOS@im_t9ROFcC;k5Bgx0KVgE6E#B5x^e6ar_K1nshs~>cOB<;q%)4K%VYkR zauKvOaX&A@WbiW?1Qj@E6Z-F?ChCO!PcJ%BK^>+kd;fm}VbQbGDjTx%a@p^bBLe*( z%=N7CL76aAS;^BPygEc^>}#XL0by!udq}AF>^aY1o)Djy8Yx15PcKUCJISgLefH8VEK|#4lLrDssh>|1qF~OMB?b(OoL%#FJ5n({wyx7 z1QI`hABC7rgOF$s^}+T$&3p4a<6pnO{{-+94=X4UcB~tRS?aVIA2>DPBkR6|6C3G- zL+d6XPh(EKwkGUNy;JWv%M+jV{-PC>3EP*}*i&9Tk7LgMDG*jNc3LGvcA3=q(BC7_ zD?($}n#?QXhbqZ=K|B|W2#ed=Xum@!clujHId<)cD_A0|eO8AmOq3ai`@VS6i(Dro zc2%qpp7f?E$DT)lH5@p56gc*|GXg}%!PlJKaS-KR(3th1pfxnmtfPkOgm!1}zjk+P zSY)*8SjC#SQfbO&MA#Hp=aT0}x&`BA9qZU2RJ}cONoaM>QzZ8anuO(nHvA@^MC{(H zC}Bc#U}Nc*lCDWS2h0AG&Ir#2mmbE21MNydGb{G?U_NXaN1ssJx4Db?rF;y+`i0!b zMT>A3B*tY@^2!A)%2|=9gsR*`23KXT3-TIeL4o$8A834RE}!Ds#tB*{xN(ZjZ!^j* g*=w_;23lCcZHZUUNVtPQBB4vcdo$_#5|!}a4-4YORsaA1 literal 0 HcmV?d00001 diff --git a/bin/org/springframework/mobile/orm/exception/InvalidCursorExtractorException.class b/bin/org/springframework/mobile/orm/exception/InvalidCursorExtractorException.class new file mode 100644 index 0000000000000000000000000000000000000000..68ee643af07707038910e4c5b0312bf9b4f581fa GIT binary patch literal 1202 zcma)5T~8B16g>mQmRbZVAEKaxB2qqD!8c1tv}lAhXo8aXINc80!R=0+nFac@e1Sw0 ze}I3$e`CD6EmDC5_F?DVnKS3yIdkXNpYJ~btl@bYeGKok@k_R4ROs&;(UeEpd?__` zO$D-~O|vAAJ=tLE| zC=u*QV@dJT)+PhnW*DmI&^i&iJrP85fU1u_#&Bz0h01L(j4f0T#Gxn!BJ@j@Kv-KY z>@f`PDnAr1GLoTi39`P_v*~^9Kzgpck?c!VbX}$~!Z3MGyX#_;UPmgZOOrvKVXA8h zzu?JBp2aZ6a>!zwVZ2wkLqZ~1OkygHdkn+p5=rGb+{Xikv@hKbT}XVmLQkPxhFD=H zhlhAXHi%YBhINLOtE4XN?H-|=!7Rh?BLASRRkc8JBZVcWxiFHi7Wmglnl`U%X?ds} z_jKrl3b_aZ?i!NsD;d=7GG9AGD$65F7A31kM#qsLUc$U6@ExKE#i8tKwI{6>Q9 z*hd1!&>aNrWiAyd7+z~9>t51wocLw4llmRbZVAEKaxB2qrOf^R}dv}lA>G@>LvPPaolxZSBUvtWOgFOX>B z5AYB8Z;W@hMJkZMKJ45(bMHBK&b{;N&-b4IR`Dc_9){Q2)I8fXDy;1r(U3>leD)f; zq5|n@)9~b1UpAf6p|=$tia=FMk+Ism*GF$evnkEX)AKY^4C~iM+Z0Yb_kC&YKLmzh zD~%Gto-~#iKW=R@ux*CHk`ApCq1zKdB>SlP_+t$H>nc=kgJE>Od>{^m7l^Rtl>%Yy zT49f2U{}>b;UXg$3Kv4w7rT<)Rt}`^);5y7R7qE58p8||XRy027U@N#f~qtbp2Hp7Wk}bg+o6WUmn(D?+ChjJ zrgON5`y@l$iLlDBd>Pe++|Cu&GMHibUF7eywW<+|~Nz>w0EiDhV z7WfW9gyK-ugloqb9o6bd zY+F7eFot>%w3fJ3#9(-(m7M#@$Z^7#ji#exZFpT+-W1j)0d#q;_Y>1d8wJi5V|^ax zFdIvmak{Nq7QGlH#mg#`J5i$|&4;)^hJ0E3GD12bN*{|0-I|(@N&f2VXwA4B1^B8DGAl*UK<_MLETI@Gt{Ls?c+yvFk%W zt!eUlkRgizaf9q!vNMRAwAPTK9bkIl2Zlc7M^12S@fhRBn96hd9pk|X9(|*LUd+)y nn*?Vtg#kP!f4rTHc@)Sa7%X6sh?dCC(c0cwPRNVo^}zcJTCiBn literal 0 HcmV?d00001 diff --git a/bin/org/springframework/mobile/orm/exception/InvalidQueryTypeException.class b/bin/org/springframework/mobile/orm/exception/InvalidQueryTypeException.class new file mode 100644 index 0000000000000000000000000000000000000000..70d233ef7365154548664d8eb0a3021246d23468 GIT binary patch literal 856 zcma)4U2oG+3_UL0T0+Z4*cc4f1sJU5W0836gv3^mhAJeqQN$a!i76M-B)YjN+t1=< zlR)AJ@S_k;TX`Q^Vq6_g3v7slx*t6l^FXW4%Q!eYiotEk5& zlUncgIs|%6sP86mW>su^D$03I`YsL;=C^gM?Q_Crv-?Gjlpm>h;P2alM|;-O>JiGj zNyrskC9Isz*vWMivZ-Q`urcN7jfr|zm~MIRRp#+w%7GPpPk9dNaBFaIov?gH2d!Qa zv0TFqtVpveO*sw;PtOXS>2}&pyNX*f7_XmO&v3wc#No8`?HcZ2jZn48gfd~N*_r`r zJGcawu+Y^pzsZMvHV3L7F~RL7flOP;%*CEM%l5O*2%YYQpYq(5XcKCad2v|mN>TCj z&?V;bKuE=t0B1kRO~9{Y@d%A`k+%vM+yx0W*#xX&4)gM@h*d&WG?HhzBC;l)k0_7h z8jpUW{=r>1!L`T7SaNTQcp~>0t0!oDALp)%bOfW2Yl7g3=1sDt-aWB^2JT}+unX;h MXeH4fidDkqUlStf%>V!Z literal 0 HcmV?d00001 diff --git a/bin/org/springframework/mobile/orm/exception/NoPrimaryKeyFieldException.class b/bin/org/springframework/mobile/orm/exception/NoPrimaryKeyFieldException.class new file mode 100644 index 0000000000000000000000000000000000000000..510f4a9204e193562ad9d7362ef24a3202770ef3 GIT binary patch literal 977 zcma)4T~8B16g^W~T9?H_Ed@VWK151|O?+)bq6HGQDJIn>K2EpOI(zw)Id zn)n0!QO3J%kt&d|4?A=3+YbJz*MqlWa3qD>J-m3zBF#{{HP8W%_)EtTVfYt;VIdS+aql#7-nnIm(e~$al3KCKXcpVe&4RUJPfPlHp88k z?E5^5wO}Y;38_`4l8!qk!ilQ;qr7xobww5n49l0Wttjcwt5~{Sp>rrOY&MleO-tHg zor;0gOB!PJRP1*x>03^s!!nRZ(S(5|hNWo@V?5$Bu#EdztT5y+*+xZ}cz}mge_uo` z=>@K6(r}V$%TvlHI0?^V6Hl;8ec?eM{4T@pb%a-PCpA?Qh&2=I31==+V_*X_D3Y{> z^hGoFIzqqa9hX!T8p@$rahe#}6K6X5BtwS7#;q6O=8dW{WT=N{XAFx|n#bd1DE-Sn z2re{i{U3b&pc#yoinSw-Xw4Z`Zx*tbj0J08)C$@=8cGJUbY{s)AxAgD!W`Yrk!K!v z>Fgj)9$;nX2l5{ai|4pk8KN}AqamzwY<#1)8En$u7{$%e8kl%Wc4?f4Ej%NO5U`Ch TaqQ6Dq;u@4jCh}umBQ{H$#Dsb literal 0 HcmV?d00001 diff --git a/bin/org/springframework/mobile/orm/exception/NoRowsReturnedException.class b/bin/org/springframework/mobile/orm/exception/NoRowsReturnedException.class new file mode 100644 index 0000000000000000000000000000000000000000..f8c8ebcfbb8a86dd44f7ce911b661704b6e952bf GIT binary patch literal 737 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 Zk>Al|Ad)*21uyoYq!Sc@$5Gak{{X`g&Zz(Z literal 0 HcmV?d00001 diff --git a/bin/org/springframework/mobile/orm/interfaces/CursorExtractor.class b/bin/org/springframework/mobile/orm/interfaces/CursorExtractor.class new file mode 100644 index 0000000000000000000000000000000000000000..8abc4e9452a384b0091f7ab9a13effe702f21f9d GIT binary patch literal 327 zcmaJ-Jx>Bb5PgHn@l{w@TVsKn*eQfYu_CeH{=nSba9QMb&DVxFeg6P>z#u`3@aVNP^@mzlE|n|!^!jcppV_q-ua&Vbh%Pyo+B`Q}d!2m+ zs I>m8B)9ssFcwEzGB literal 0 HcmV?d00001 diff --git a/bin/org/springframework/mobile/orm/interfaces/CursorRowMapper.class b/bin/org/springframework/mobile/orm/interfaces/CursorRowMapper.class new file mode 100644 index 0000000000000000000000000000000000000000..b80fba0fda3d0dcff71c5926658413b15b115aab GIT binary patch literal 324 zcmaJ-!AiqW5S(o_X{rYg-g~W=KJca$FM?306x#g2CfS5noA<&dvH#}559mjUPwA-z z4-31)%%hES%T6L{Ys54bvnj=>xh|>AZI%+6Y68F zT%SfO>otPn_KC^*qZso9)dU4>>~6fHl5UzxiW`O?C`V};a+pZvqnT*R`D*u;`m~nI~{`M@iAc2i_#?@mzBpF z!JE{j|G*FUv3tOzCmd!)${$J^_rG?2owmBvb+rwOXbfUi2<97h$DxW;HQ=z?d>!}M zNI_R^HY*!iP6ZH1U5JFrM8;yv6D}93JbSdSrbEjU*G=#(eLgdb`4^dQpGZMX$^VPY zLoo@N7uvRCy*=Hv2wp_nA3V=UyM}{TS&taPx4D_zKR;TaBoZMA=|8WL% zN|J`glXlmr+pbiv`BSp2GYHNuSs*@S2^K9{E02e^!tkxvd86tJ2d;0ms)@3HDtTvPfpxb7o2B1mC`-1L!K h8sxUB!5!SyAotXr`*@&19{R{54e}TSPkb#;{{U>5rNICI literal 0 HcmV?d00001 diff --git a/bin/org/springframework/mobile/orm/reflection/DomainClassAnalyzer.class b/bin/org/springframework/mobile/orm/reflection/DomainClassAnalyzer.class new file mode 100644 index 0000000000000000000000000000000000000000..1db3573a4c216f6b9386752fcfc1240ed37b990e GIT binary patch literal 6213 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 literal 0 HcmV?d00001 diff --git a/bin/org/springframework/mobile/orm/test/AndroidSQLiteTemplateTests.class b/bin/org/springframework/mobile/orm/test/AndroidSQLiteTemplateTests.class new file mode 100644 index 0000000000000000000000000000000000000000..f91967690c6e1bb0bcf34dcf6971f4ef0abca80c GIT binary patch literal 25615 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 literal 0 HcmV?d00001 diff --git a/bin/org/springframework/mobile/orm/test/Main.class b/bin/org/springframework/mobile/orm/test/Main.class new file mode 100644 index 0000000000000000000000000000000000000000..0f6acc1abceb7adbecd4fac37f19c127f8dd3a0e GIT binary patch literal 527 zcma)&%T7Wu5QhJ9=g3V^ysg|FF|mnTjERyMNze_3ec@EBLQ8rI#FfwFMiLi3fDdJy z0>+ICyO`;8rr-QCpI`4E08Vj`MS>wTcF5z2ReE@D#aPabed1%&S0l-d9djpR$8Utv zS)>@YgpRCH5f_sQzZf_*Q|_4|bEdR%=M2g4sK=0MnMejmB40on8HRF4X?Z&x_oclP z{gGs-cFaJGdcrCnuOCzHLB$M>&VMyE8FEIqtQ3xz^|13J&&2$4s-ux?9`(GC%>qg& zCts3402-r!ZPXb`v2-n?oz$+Uu-H#!Nr(H6*NDdOZA`E+A}-0LzOko9RGhYhlYRRQ@TMWhmCvi|cm s!4kfralAmKQLVnA_RAZ|%S%d>Z|OEiW(;v}&D4MBZwSpWb4 literal 0 HcmV?d00001 diff --git a/bin/org/springframework/mobile/orm/test/MyInstrumentationTestRunner.class b/bin/org/springframework/mobile/orm/test/MyInstrumentationTestRunner.class new file mode 100644 index 0000000000000000000000000000000000000000..091461c012ca830d7a7dee450336cf27ea496ed9 GIT binary patch literal 1264 zcmbtTTTc@~6#j-w*On?+?pHw+T2RLLWKyER;)P`K0SJkYLpzkk?MyQ}E8?%x7fdwq z2l%6mXJ!j1iP~s3IWuSHobR0PT)ut({1w1MtOe*{c%n^{Cv6j{=AjWSd7{l5-qHtA zEV(uNtVvr^Sz#ls_UP|Us+2SV`WTjkY8V|gGV9;kGUV1H71_rOz2(Y2 zLtjldWC6X%7txO#!(bRG`6_K4NV6vnV#!bnbzQ{!!bDE*{Oq$wQNpkh{%7)4hJmKE z8*%Ii5#nsQ5+0|NBEKw#d)iGSE2{x+GTi+eS8rRu5QZJ85r+A4c3b@fBjF-X6fub@hN5URF4AWhDTl}6t>Cdx zP3}E?@EL|j-2^|9aa$U``Shi~_-Fy<7}mS-t{W+=Hr%(cmMIP*z&t~(8-z$%X%0nQ zCcKuKM4M;ttPynr?WA)1Ux9Y?$u_m7Q$dFQ#PyqD`J!=_GQHY47d0CUhCGc?s6|5> zhDkR>zt%Z>suobjN`MLt`W1sBRi8tAILZhFy{frkjFT|O<)vLn5J(5Gg!u)4?LEEcLL`zk44;} i(6nk;>ZI_%>y&VboniSBKO?aC6M@_XfqOoS`#%6i^Iu*7 literal 0 HcmV?d00001 diff --git a/bin/org/springframework/mobile/orm/test/creator/TableCreatorTest.class b/bin/org/springframework/mobile/orm/test/creator/TableCreatorTest.class new file mode 100644 index 0000000000000000000000000000000000000000..c6e86553855c67952e3eb77a99df0571c3d7b5cf GIT binary patch literal 2398 zcmb7GYgZFj6x}xoP6z`+l?m73Iv-dvtO#b=r_rCyKLZBfgFztHlhQH-m z&iY-?Y{-YMw`nxos%1;V^%_PX{lKVs(hOYBSTd`&oQqzTXwZ-lm@=KZ=UVm1b+#5* z53FFj#Uov4Rsb*94ow5QbIyWG@6pb@bqfz|peh z$i-%(D!ouVfppoenf9{jSxU^-Vj|eEe1Vz6h!4TG3+nC$(%s|B;P#ec;)ITOkWAqe zPHV^r9NXjL>Z6+6Qca=bT_jnf>b`)DP}^Mc%$gJs{2$rJS7!%P^oNcM=2jbzs;SjH z5gcDbR^Z|xw1!aXZiC7hH>Kyh6mST69TS*j_7G%uj|!aIFKkQ3eTBB9PNE<%-f8WO zzu`9Rdd6{sOjTx_rfsLF(R(^Bf(N3X%^BWVtrb$kk*8ZDH@b{OOp zMX3h*gs*VblI9z<|XErV;O-aeStm9jJC!k02UcKKmZ5B253L;CT+_H*( zN5?AG1d<$&tywsF07I#@UhKmU_({W$1i4pB+p5DvmGwCC5#=9lM+k>et9vxm54KG> zqg2$pI@Ym4={HP&F$_RJcLaJnM5r0ECwZ$u87(?8ovtU=!EX8~tl4qklsY(zwzt~z z=xo=<>6a7Euya!tx9Qd7JU>?KlJ0p_P(`xvinZ>TRGL1kdpW=MxK<2fVZ}Z_hFq}`P()un2@_%4xWf#YO!^jibV;JLgAdE4_UBftr zxA+I>jKF<3j<QfA+f~Jw+b(||Fxb-9h zX2QUu(dJg*B)!hyEO(!yH-8>nV}t}>&$si5ej@9k(aAr>NczGKa^>{Y#4{Mb;(ez6 zL@oFHiO*Kz=?j&WM0&QegE_UhgKG=vuP5o5Ug(*8jvE5caGMV+0#_1`F>*Zd9N!E4 zjoKn(O)-{Qp=Q6l_*b!$2!RyP$LF(1vBW{vHHIuEk>e!HbDm9*<4LSx3N_vvFhY>| z5WLd@nL-^F?h(~x?%0G)3f2g=!L>LXMptY{HkUR<#Ta5Qa0@*egoc{NldAEgaQ?)w MMRN@I;e~hqe{Kqd-v9sr literal 0 HcmV?d00001 diff --git a/bin/org/springframework/mobile/orm/test/domain/Account.class b/bin/org/springframework/mobile/orm/test/domain/Account.class new file mode 100644 index 0000000000000000000000000000000000000000..32bd3acd207b5182aaae4786739bf412611f4f95 GIT binary patch literal 2810 zcmb7GT~iZR7=BJZA*_fIwJH|0tw2yxKciyM5Q0V_C`1&k$|kI^nC#+aqr*k7dea}! zoA$=5wl~hSozd87XF9!Vr~OS%?Q?b)@?q5R0`{Eqew^od-uFH5?|;Aj0pK{Egy9o7 zZdxnx%DSZ+D-SHStUWQUhw-vm&`Vm}w90W?tJv{nv#jbyJXI{3Rl^P=Aked>K33x; z)mVwo7S^<)E#T9ac|Kh?Oq<5an84mS2I*yOL9ghAl9nG#~P*1hA` zEWNB+8&|arW(_`8OI1xEl1is%Z{+g#vy%c{stYl{u})L80n5BCDKhTFhuoMpOVzT$ zC}s1O{NlBYK!;H+l~j`PQ%VQ~Z0EucV&mqPNSQy7&)mujgw(QBSU`|WC^aLA(Kwe$ zO$+SU&{WH-!R)$bXp~!IiES~Hn!7)rPtD~s3=3y-`OKxv921<^4c#6W@DB|yFiqNA z)*|p@KtUf42yCC$4J}tK7c?s`$w@1N+ zhlU%<;j~64l^aqJL`a~UZXP$cc)d;jUioCi5d~dP7*T17*frE}ffpcocgobBu2f=D zCONL47rSVaNjzI%Xi~cO(tYtwr5Tx(k!KWqguQfQWE;1@P*x`ClC_$*Rm+xD>R44P ztFHRvxERKTrulK9DmahR5lmn*jC7NI(yX!=3No1D`LeUin^M6E-DY7V?kg0ULtJJJ zLzY&lme@l9TPv@#MQGbbD8+{}>bh6bkoKsmmKfWlnLEg1!?$IV%qqBs>%>ku(j~P* z=bcR@aSq2K7{|PVY0R+A%)(mp)Oi^R&a_uGi`i_`r5nbgz@GYB;hs)Z_0qCtb>NO1 zId_%^?&!*}ro8rq|7jIN5jDzf3KOd?9d~({j3v<`SZwG%mD~Qm*q4ErS_}#_;8oIIl zHhQo_Llisd#G&z=qK=bKI_-AtduZoqylLO(+V?v*^5vn&$Gktzui!Trdx`#ExbP7u z9C#qWLtINlbigP0lwX0*aG1ZFgP&vYXBr!Wcef25MyyTnNNe!Ew!ud+>IIMUDjzQl z#YSFWq>fu^2x1GO-^sAs_42SwUarD|#6RBx;^Rt6@Epf}YGHAxEszs9xdp`UR5cVE ze1T)FKn@eg;9G#WRTMad(_26`Yw;Y3XDvWtZGoJ{xh)`@itK-ZL@SU{0*Su`$e7bE zLOy+7u79XgkoS-G^q&tTd;0rUDb2{=2>X9TL@sMcE+wU0zalju?FSF`41D?3*Grqu ziKS$pWZ-wY=`cFEKEd5d<~_yTY3%3s0M4+R&hr1DbG&`b!58Cz@Mf=Kex6=(@CE62 znJXV7_9BZb%yyNY2jF|niSUOZ1mzR2iQU`yE{J;6uJ4^5&@l~N~rk6NQmvNMo;v|(MsSCtBMbtC=UPlh|n8iK*Az0#04&;E# zVymeO$m0e%_A~baht%f?(~WRAsJucimD#>i4l!RSPYIJ5WXmUi$F0Ta?U(q190zN- z7cJDVEcx;iU2)gPYS5!4cb%xgh(6-FhDv>AyB$Ca{L65YRa$81)a2HyQRQ_$JpLa5 Cb~NSy literal 0 HcmV?d00001 diff --git a/bin/org/springframework/mobile/orm/test/domain/Address.class b/bin/org/springframework/mobile/orm/test/domain/Address.class new file mode 100644 index 0000000000000000000000000000000000000000..c59208007b51d40467c209ca7a81e0d1079c5117 GIT binary patch literal 3683 zcmbVNT~iZR7=8}qix@>gq13OatwKVKDD?v<1^K8^6eKAXEW$$8u$b)PCeh+Wr&s*} zonG~>`9$T#gk|RX1v;k7X2~e%Ge*%^%Im|XX_d5+VVOmND-&zT8>%`LHfsrmrb~L%Pm&-=1 ze7RuKDv-`hkBwyne5Lg@UbrX7%1efZ^yJHo-J_q7SlQ)jhv~X z-ZV8fou0g-f<0iEMrlx>v9oJN;wQ>58gV*;6F4c*JYksnopNDGw=}${fhk zoWQ;)BOjGbrf&Hxf-zjBiKfOf8R(D8TAsaBmGx}~bFw$J2$rx+*E0Wktw`n8sw#4X z{bA_H1@W+I&MO8HJivm0u&RfwdyBw+VqSi9TU&G6JG7z|SJVLGoJdK}W(1FrCtiL{ z%6U#}!OVoyR@q+G$NAwAh`0@YUgi>~*gA4n2GAgznx`O7`?!YqZz>|p7i=;2MLXC1 zG~kN^Xx4EMhtM*IRw}XkUROF&qr}F1U8%iBi9P$eQb&yv+u2o;V2|-nOvedF$O*}3 zlsuAL1y_IU6;A!cO#{yGDQSY#-{VtWMFqT%vs|U|IXC(;1zyc^Tau@ z!#3cu73i-EBvA`wpe~Ss`alx3K!ylpco!h52LwK>3nW;xdHsO>cIbLtx;ejHyh6lY0&m44dL96TWY!m%JkK(ufFsK<|-o5nw>E7LeH z32b4%TsBd70bk?5!IMWXoX-KYYce88T^z} z_;ZY49ry9flht{bR4Z2N76o$`aX-H~lNxD)>Hy}<5SOftVph~EVgc_w$6Ghx1Cmq5R+Y{MNQQrzA z5E2(W01t)u$974Yx`cA!SUo-3U0JJ+=NN9ler zY}pnTH>7JDKKFd%NZO`wjGC|ZJPm!6e?;bV|YHwff0OF-^ zgulfosh3({+?Gc?M@gE~C{G1OQ&r*cTHkJSw`syqWxMQ{R?BpSnn#N%|Gj|2W0{6; zGAOlT>TpH zk7F1;DuPnhHM&7lA=8=KGyOlr6m+g3`)-Ht;m?5e1A`u^mriRqE{XptNeSfxW*N-# z=&xZV>tQj+X_7R|aNED`gE`utL_duW`8Oem0#gC)45SV841K!%jb=Y%kf3?AN|_M4 zfL03wXpwGV#%PIdqdlMeg_b{Ib2zyWo4i7+QSug|6Udn;Z+@la!O^*3bsjfe2o&bR zsOWfw78=7~RvgIsD9BPQ$lZ95^-+)&9JhK2NLT?z_vn6%BgIjWjaZNpmE#;Kj)D{c QqF(|MmYUIKP=g1*0WCu-jsO4v literal 0 HcmV?d00001 diff --git a/bin/org/springframework/mobile/orm/test/domain/Person.class b/bin/org/springframework/mobile/orm/test/domain/Person.class new file mode 100644 index 0000000000000000000000000000000000000000..a123127f10b795fdf7755ee40f9672c1851c2d4c GIT binary patch literal 6201 zcmbVQiGLL38GdH7$tIiO3YUPXTd)`sFcqj45+jjh$-tQd<%2ZCh*UZSVdK{gpoNe6zc=n@tgaKa%;5_jum(d&ArR zJ^31dh4^;>J`GnTlKu6mp`;b>-9WNk#O@>Q+fo4X<#sk}TjkTBiLFayxl*3s%-QN9tg2gt?9P+oJiyNwh^UtiKprA!9j z&6Tum#plycH4RM^di8}Ey-C)cG~y}Cj5}Uv zwBnZCL{HbuTT90+PxP5VlwgsLdVE~Ngs2ra+tY(RX0lsCDV|UC8nLxT(vrP<=(h(f zntQ?I^Ws;fM(~qsJmGOFYTnuk=F3tYr6}Xqd+#Q?hr>OIc#hnRP-3ptQ3+iHUZ-OU z^dOqCJb>#pOv)9qn{ql@z?cV|%InywVOmXOo=0#dGez189n&yfRuLUDF^dJ;Z`u)d zh^iVdkJ}@3UWRkUJ0*`MTfTZKk7{ZW(fT?|BIFWUw;HABv*FLyHIuw8V}JJWLl(PW*`cErbyQ679>tkL z%BpA(bP?B^+0zfHSY%DhFMhUrw*ds%^jsu-IchG{j=X)qWh2%AKF@C86r}^UIhize zOWO?M7A&g7ZMZ#vFKQT{BavGjci>KTFhY=|_mr!8w;Sed3}O%N4&W{g3oq~*7eS`u z9(-8^UiB>Y+l#W$?R4V6071&*pkeWc@ez}}%Vr6zHilfsm)i-|JOX$?!}MH7Q>WLb ztyrI#EXUW_+#`KULqXh+2c@}p$m(GokKj?Z1Y>B(jMIG!in-6@(LAXQ<#>#ULQY!? z$xx!?KOs_|ED+|lIB#bx6!tVTIwXzEl~s;!5L$@6YH6q(-((0vs^!S`IoYa?A=_^; zEkdgLL-JZHB+mI!2qQQyd1C4l!}mB7G{cKh3GXM-^FRpBbIF@4LgyP$H~>;R7=D? zZ>YrU_(1^QXD7-PO6FF_8#qH%adQ{PsQl*cmP-(4@pb@j<&D6~W%54$P{Z60lqF1$ zAG0hg?2sV(sg9rF=d6GMBh~IGXJ_5W_zpQEH(%qFGsAXl&05Y&^TxChOUXp?u8v>h zJ=)J^yPT6GODO+MaSj^<{5c)J#GOI>4(9^+eV!TWb>hU9kVz(2Ew1SlPj~}r3ObAT zb^Hm23=DtO@iz%kxfQq9%2+Pa-zPv8b2>&(2D=jJWUm?K9~FF5RK;H@^7%H=2^@ff z@X0*GU4Xkve#`k&k#a6Lp|}^*`5i|FUW~^C6B98BRU0vx+#Fs;6HP53;!HA{=n_RV zBO{69ic3`GsPl=sOBGQyHStLveILr*^SvE?KPRKaCr|6>`?)!OzNDk?=jHDCx)H^E z`pJg{j=#ijS8_j-Urwg{eHC~0{A&D`)*i#cBM$ju{uW~S`|lI{EiNMguEsU|3iBuV zTbRQX?&CKo%(ZpHSdx=4-U-=a_$i};ydr6uqIM-oKvg(JW`is9cG8rRwmKuTv3CA2 znrf?$W7#mmwKM#~Xv?XYNvI$oKbBC0$EQW8^!>lidw^3tSbVftq{njqCnPDyvqE%(0I~Og=PzZ7-IlY zjYGpme7XpbO@%=EiURp8HWvf3sn8<>1Y(T=M0F?)TL`tV7aT>;!GcVW6$R1Fe?=|eiH6VNX4mW? zN)zdG=(F^j7+-q|w`@3uFAO6sCv_)qs}JkyYDe&;oa$**3f#+w>ONF)s;lOBHyaOl zV9d$3w>hM{kIKH{0N3RGM?wsN|%h_p{ji&c%17-eyW~Q z>n2%0qt;=ec~-64WW8UlH_7^dTKA0L+f@hEdSC=ERUJ|5_z1o;f|01$cLrPJa{|XT zJc;hAQ>)eXRsJ`O{{ZIB@Sniw2;=xDmSG>Fcns_DIQsAehDc)*%pN?&Kg6EK zvv>xl_7ViSa#X$1k|@k@gbD@g{N!MZcdjS>8+jz9ZRT5_=NG&FHmcs_re z6K)#MV2XTr#>o9;I1Vd^;4M;0p>!%U$H`{|e?9|s;Nz1hJ dnCb+R1bUJx;c9KHy7$hO z^Vf#2b<=QhIk+)G!fdIZwW_o&)or%qyd#WHj5XaUVYIiuAcPmL-~=PAPY_{Dn5M?^ z&8p7W&vjNYVLNrXt`^#xUjLe5_h?$edHUa+$Ask0t$fZ`(v7h5XPd*m2zDW{-QC{qv(G-edj00r-vE~JlY$t-mLD{YupKyF z^XI^7@#lW<)M)v2$K{3}v<$&RVLaw;n+HbGYXrX2s5~%DNATS?_wGdpdt{>^!LVd? zExNagwr~y{@k`kYMbK$+Pguh7J!xICLcYw9>^f$+V~&6^0zrX%tvQ|})*0fNY?UEV z@*7;mI}CH=I)5s|d^f{9Wtf*4DmcfG8G#|9V%u^&4RM^;q2N7+`HcC*I^(`nUtuxHg>&X6*F+j6T`;K+4vGa(*3Awzi-ArY7ntVpJb znX!f23bG&aY|Bkg7`?-S zf(*m@h{BDaNkNYCJ)t71nSz@Pw?;UQiqP;|qzU6b4?^ElkY`wai)+P3Bj91E;G?&^ zXWM?q6Dp{U6q2!oqG17_NL_x)P|OUfahkLJf9Z2*qbK2VwmMD~U)3>&Bm*P4UK+9* zsDy zG~n{=_(Z;P&=1VY465K(u;D+a3AKRlbkt-gkJ+vtQvI}w-wAAfmnJ*IZ1Id)o|nDA zFkW$*o+UZ~+3yb^MVcQq+SmTq_>!}Q?d?AOC@s7m?!xp-K}P8Tv|ubeeXqk?ZRe zdWM3|Vuc2sgfbK5wAzEBQcj=YbMkT#bNB)U`dT9^`U!85Pnq!T0oEp6m4u{ozhmVH z>*nH1d_{Qg-cFgx>6h3!Az+di0}V|T^Mqi5kY#Wg*&zh!0fGs9iwXsrAnQFmBsv(X ngP<$4k}Rv;ppQ;sbVU6K?6|$S~Xvqox(NBQIz^ zjd)AE45JrTE3A9Iu)?TiNfArynef{pvR0PwCm)++i#22!uJE7{gmB(V9A(uvCxM~l<9e}LR-32f3gt%ePe#}S4L6skOs zLOD&LOevIA3L1_w6o+6Yxvq0B&@qDJ1~i;tm?_%N`3|>y9yBdSszO!zELES!aYYe2 zZhL{)=(Or0+T?X#Fqn4ea=*qSPo2BQtbFFh40nbVAR#kQ1y#wIN--J>`M9lEo;Gj_ zc^wm&)bJ(4$pfyduUyeq^*3-9dE%#1xg@*GCRG>rKKR`eS!?b~~@HJ)E z6mp=`3{%BfdtVd0-L?iCDmpG=M#CkB$wS->Tt<;WCxmJkNbyRNe_v!*83So`f2?RI zQGN%hCr#1t4a2n|`6X3uge_{i^-x4{7-%Rn%zwtUrA8wXG0nr(&%EclVJDDz&|GMw zQ${W6w-zT34u+Pxd=-O8S@sHZdn$O6=|5OMi40?{xw}w1D z3v{}boPk2g)J7w;MiQiellX#8)V*Gi-|0*F-YD&1{14>q zxm}zo{e^Q|rCm(z;zI6k%x;aCbIw-Qyy9$)nwDc;%kAOYx48Kx37aKO6U0RUj}ud1 zk}R~yNQwrga2?YLiSZPuOCpafZsR+OaEETt9~|jsB1^|gk6V+1ssc=u{>05)EZB4J z@B{H%xoiHEJNpjyLBc8SMY?*4FlUI%Wt>4V!JSTn^l-=U5RV9GjJ$t=L##5`B$x~y Jqn5mX{SOFR1^EB~ literal 0 HcmV?d00001 diff --git a/bin/org/springframework/mobile/orm/test/interfaces/AddressCursorExtractor.class b/bin/org/springframework/mobile/orm/test/interfaces/AddressCursorExtractor.class new file mode 100644 index 0000000000000000000000000000000000000000..31557f3c7f91fe68238996569de8e37c058ad76c GIT binary patch literal 2586 zcmb7FTXWk~5dMynT8^XU);7HYEmu1?(+h>xCB?)};^JJeO`ri96#K+gYfC|r)0SI- za+&@FhTp&pyrh)Q@W2BPJn_ab)8Use4BwGdq7+J+@mSJ+yJvULw|n;d^4AYP0yu^* zHN*r8w$sSCtBz?kRve=xuh`DzOv_$2n=)fNt&AsKFJoGsbXJU-bThen-I1<4(RN(h zDO~j&qvqL;hE9RLOU9a!X&P1|Gq-$6);tYyfm2%qi1@zGsX*6!p71a{G=QY{w>G}>hPhhXWj!HFG<%0bJiN)gl(!^Yz(m|S^ zF)h;@r^8fwL9MXsGKmfx(eVf#73eLQmYi+3mZeiQmYY&-#;zI71;a6w9D<$RMbj0S zDs92o!&(sMl8?MX*jAzpi6|!!(4AZ*T0oiV(F|1)o zVDAI`>KMT&(`eaivT9G7j_dgxEo#UJ9DA5;ZjPx!9@W{q#|3&C(wnfG?Uq%v>hh|< zp47iPBwbWXp3`v>&kJZ=QnIZEOOz_6&n0mRSq-P@YooQ4UdI`{Nb@z-RC6l=yHe-U z5$DP#o5UE-ssg{H^!IDi3o7u-Iwrv0?PB1dXH}ZTsIRbDLsYG>v&b6NurD9s%lOR6@jDM;D287xLZk- zaaKJRbiA%y>U8Osb(WJuDbDLyRElmYN`~txToLh>j<<0kAR=$K{WG9ykWbX1v;`{hSaeF7E^6^TAGcE?5<5s5ZVT{Fm+tQWgb@6qG-`n#V;n& zf~~<4=-=o8s%1kuDuGpj!OaB=m3{^^aY0vcW{_*}Tn|PY;htsMuh^Q7D`1`lhX;1w#w{VWbO{iDnK#>?**vNjuO?Qrmrca zCyKnGkiHOkQ>C`Fj=BN|Lhzyjo9lRYWON^ZH8R*4fq*(mZ z)RxHA1#+}XmTr=xugTIk)c(ZD_#1|Bms47?ITSD!vPtf64eyc97%kq%2YlZ|1s~!g z#=K5@w$h)tt6{7!N3S0T%=0V8AL}$UypB&)hA}_Gpl-sCr1UY|@SmUIbN~It-(HA` AVE_OC literal 0 HcmV?d00001 diff --git a/bin/org/springframework/mobile/orm/test/interfaces/AddressCursorRowMapper.class b/bin/org/springframework/mobile/orm/test/interfaces/AddressCursorRowMapper.class new file mode 100644 index 0000000000000000000000000000000000000000..2ced2dda022661e7c2a5c19404bd3a5f9ac074dd GIT binary patch literal 1726 zcmbVMTXWJt6#h1}4aM|st@nB_6x(RMORXYMO{Jw4h8cb7EU?8WB+MpQefAIOi`N-_ z_eVLN4LHPVZO38A=6pH(o$p+BzyJ9B6~F>EbZ87YSJq9hC2gm^C3#b9yYhwEbSrj4 zn67M^zVLk0c6=eXcvX02x>l3I^D=GexpKqZUgfQpkUIJpMxXPS+-z{CZWb!fMb+0a zz;J7i03q%jqzsysWf;%*c#FOgnqnBrxQ^#@$1n3nTSReyA(qZ&H*&?|rrI=6EN$d+ zr6>%BzKm6R62&k>f3cJ<<)Rp6h(5K}H#3DSS>xosXgjvQ#1M%m%4&yO6EQ?^*uX(d zGK}PHN36A*6(LK!(hy3OTjh;1m$tIIV4wfY_81=I_sDsFMWr+cn!H6tW>}Bsxl@y_ zT{COk=N0Y=vs12=mDpFfn%m^I^Q(U;9j6!;_M`LnjR$ZB=X9K9nA$~P7R1#iIo^GVqV7_arGuZeK%m@61l%r zy)SGrOvG0bA#&xDieVZHs(n|~_nlu8Wfl0Ef$O-zFi3$rqorh0L3{DK6Q|g28MqB< zitbTnw*PvUl*-EYj)5iR8ztYO&wZMvY1}iAR^VU&N+EoOW(;H%8YA?n-BP1Rjjsj= zjN!s6$4wyC}hs|HTsBuOv2ZCMq|bZIag z`}-9!uNWxzqFr~m-t51#zbzK`+8P|X--kK1l)`DsBSQav`W=OiD7_ET z1*suMwh^+2$Q};aBV><;>@l*(L-s_#OZNvc9wJ7QRz_?8><3J}3ql;B=Rg1|a!|Oy z0mpEhET*bUPqq0Q$?K!F`UTTZlF9MdC!E&s2{Rf#BKZNA*X9Tv>7rLPyvI$2jD?X! zg$#v}y9${IBlqXtQWy_nzXjluL1*`|_Ruj~K- literal 0 HcmV?d00001 diff --git a/bin/org/springframework/mobile/orm/test/interfaces/CursorExtractorTests.class b/bin/org/springframework/mobile/orm/test/interfaces/CursorExtractorTests.class new file mode 100644 index 0000000000000000000000000000000000000000..c22ab63fa98c209ac451aefa5e98d843fb4aeee7 GIT binary patch literal 4339 zcmbtX30oW26+I7RMwTZDkrO9wY@;@95Hd*Ka2gBj$dWL)0%J?20kXeP5C`ZBw@~kWi=TntuH&{SR%=n;C=~Cmfy=gnfIy#CDOsjb@=m0Rj&a#=mPRVJW7QV)ilaG(S&`e*nynua2s-*g zwX8Y1z|mX_BT}B|{Mnr0=mq~=Qb4se%FxGklTU%p+(qrOmZ&*KIgvALhdZ|Cjk${E z)GRJ%o0bP!sdcfJ%mvM;B*t~(t|X6B=3SoFRHFxPm+8^>S6W1P-*a z%-fjAoE&yf(5Q|9qhdJ61=^!M69R#>S<-{pDey44jW; zR_AsI>{Fp2C`S<$I}jAOCudajvD(6nZWXi{>Ev+EENbNm%`)V>KN)c54SFKmiZ>TS zi)bd9+icxAUzIq!RlEnCA@pFsg4j9+7j5=xQLoCNR?&-2nktjX$vax{Qh~{#D~Jn_ z;luRw?z z(k65Js>A&al8bV(;w1dVq=I9_=eo~@?z&aMfWW~P__n5y0tV@!J2>WNh=RxO@LaKI z)+$aACj}Hnx-=z(K4fILWd%~vI+M+KFKh|nh6z8)M|vh?pq^537w%RtB5*s$LC&Pa6Q0{b`6wK(PB zIHzJ8IzlLb$$DPkL<=y@nUr@cu{6aiNh;otCj{=*N+mg2FxRaVcr4l~O>fB*%ZPv= zBlkBrqn?DaF1xums#X1>uvglcuN8T1*|W8>SHbHyR}fDMJdw}lvgtx37MZoog~)jJ zT>i{hq}m%vWisco`Fuo+T$$G`J)*_Ewds*eWH3@~cw?IJeQ4xdzA!zO8qIRK`$V^b zrvx&0$f0Lp(+wNKH1;Sc@_O4yz%w%!^&&%?Yy?i5^DN23m{TziL*VYknr6r-P z8t?6lsY_*_RPiaPYzLL)G*6d;Pj7O6#;oz~3*xh+q(6SJ6vA`(yyWN$P2|>9NXgHu zcmZExPejSXx-mD;s=pb7CzrG(@f8(c#n(K{eg)P^TX-GwMw7Jz-@vyNe3OyqdZ50d z;@kKREwqiN$rk&P5lPPXBst&b9UC2?Gda&%CU5l(@A*d4yKIKobO{`8RWP<*Gpq;O zS$kxMChgv}xocReu6GXmHWvvWYD1NHQJ}E7O4MsZZ@pmLR+Z4=QzPTk=`)$^pj#n+ z!G@(p8a7v1-@Gj);w9_};#VZ~;Gx4u`h)ll9XCF2l(iE3!+ApsVGzGnaa{(MLieZH zng{WFfwu9KT)UxSS*``S#wzMCwpJN&lomN@nOZ4ApXfTT&q2JdVoh$9QM568Q^gx{ zR<;yVMpbs7a`T%i{)9h!o4x8L(9aOM9oU;2Z`$p+dSx*8D%{L+YU0=m3+}p;vvDgY8c@e?f{$)fdyKgeKjKneycihBd zlkMSTelidq%uj9$pU8((9VCQ4Dd%C}OUayF5#LD}%%`i786Dz?1xtJw<7fpAXcH{}-nv$42;r zIjMR78m38)7PyHS+FZ&nWA;rXM|)RsaSfHpPJ*oVF2i2Mm2ioJ53S;3;b%Gc1P5z) zZZiCt6?~5GU*rz{e0i*oN4NF8hOY~(;=7V*4^Ny91pB&n#L|A5Y>auk1%%d@;{hA749W@dNyjfVyxRKf;fReu~cj3HfQqPbpn`&6`mqX6K(jrpHXl97n%Uz{{R30 literal 0 HcmV?d00001 diff --git a/bin/org/springframework/mobile/orm/test/interfaces/CursorRowMapperTests.class b/bin/org/springframework/mobile/orm/test/interfaces/CursorRowMapperTests.class new file mode 100644 index 0000000000000000000000000000000000000000..e7b4025d5c67555431b5970e406caafdd139299e GIT binary patch literal 6711 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 bfkL~HLc7Ta@}z}UB4qO~5%b-nfKdMfffPR) literal 0 HcmV?d00001 diff --git a/bin/org/springframework/mobile/orm/test/interfaces/PersonCursorExtractor.class b/bin/org/springframework/mobile/orm/test/interfaces/PersonCursorExtractor.class new file mode 100644 index 0000000000000000000000000000000000000000..c8115e3a8173da7dce6cc93dfd8db8f71ad7faba GIT binary patch literal 2626 zcmb7FTXPd-7=FIAbklU{2`Erd!DG_2jT{sq2*xC(!8EN+j8YGEn{2~EvRijI1w4Ux z_J$j8^v-{v<4h5m@lG%N1CBFZG2{3nbkyhD-P$dRrIX3-zR&j_pZEQ~@5evC{SLrE ze4-#CkhAPY%2~1vv$1GvE&YOJpHH={1*55_EW4F*b;nH^rmNeFT1|ISGrH|qX12|z zoxkYXTFtd=1)T!@=d@)l)zr*JYI@X@RX-%XD1LbgNpktw*5<#3l-}<;r|1GnJ2`hdzp#f5fcoIg-zlwWsuRveXF!fTqwV>M-ZK0{lVyv3htZKF)$k5asxt7?Dzf07p%NsQdPz;#PAAURWL6wu*Nu-^@eWC z1UREZ>*)y=y$ot9>L4Lq%plX?$55E|Rn0_I0Xuwf6T_9M*KOT#VpzmU`8cQIyyR73 zpse9ul2}WHDX}QAva7k=-HTXK@tOoBCv2pyyApL&xDt&KoimpFqhK7%DlUL?8q@0a zAfmvL_+~a3}^d8x2!)+cp)ihPG?qbfZFywd?P;JL>pGrru$_?i@>>NMk>%=-__~Vi<;kD8IXT zDMviHCnT#}-x`v8Dfflse#!$Od64q9ki4Dpj*vV=d1px8MR|8f9;Un}B=7a|#T6FZN$fWk~a_+ z_zXYa#Q2$HaxiuSk4A6m~Ph7`|sZpY8fMz0CL0%%gVWc3D{s1XT%b68CC&9r0 zJR`xESFmssi!#ji0ACGrwlqd`SJN1Xl*mvRu_UrLjM$@ND`>N-O9G$&_37xB zEVToYo(c8{ye=Z-v5QpnVISh0f@54Qk~EEEEt9Bgr0NTGB=HOH(OabQ zS8^}u9q}m)=p~tW6K|2=2sPfuWxlUr3RmzBV_&6y4DZF5EJ%SIs=ZE;ndw={lH$9bz literal 0 HcmV?d00001 diff --git a/bin/org/springframework/mobile/orm/test/interfaces/PersonCursorRowMapper.class b/bin/org/springframework/mobile/orm/test/interfaces/PersonCursorRowMapper.class new file mode 100644 index 0000000000000000000000000000000000000000..2970350b9cd9cb0ce58e60a92d51c855b06f584d GIT binary patch literal 1950 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 literal 0 HcmV?d00001 diff --git a/bin/org/springframework/mobile/orm/test/reflection/DomainClassAnalyzerTests.class b/bin/org/springframework/mobile/orm/test/reflection/DomainClassAnalyzerTests.class new file mode 100644 index 0000000000000000000000000000000000000000..da5ad7573587d06df9055236ebb9f91722c9ce5e GIT binary patch literal 6030 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 literal 0 HcmV?d00001 diff --git a/bin/resources.ap_ b/bin/resources.ap_ new file mode 100644 index 0000000000000000000000000000000000000000..52fde5efa347e8a9b6540c383f89f8ff990ea6dc GIT binary patch literal 10588 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 literal 0 HcmV?d00001 diff --git a/gen/org/springframework/mobile/orm/R.java b/gen/com/perfectworldprogramming/mobile/orm/R.java similarity index 92% rename from gen/org/springframework/mobile/orm/R.java rename to gen/com/perfectworldprogramming/mobile/orm/R.java index 133ec9f..3e1d7d0 100644 --- a/gen/org/springframework/mobile/orm/R.java +++ b/gen/com/perfectworldprogramming/mobile/orm/R.java @@ -5,7 +5,7 @@ * should not be modified by hand. */ -package org.springframework.mobile.orm; +package com.perfectworldprogramming.mobile.orm; public final class R { public static final class attr { diff --git a/proguard.cfg b/proguard.cfg new file mode 100644 index 0000000..12dd039 --- /dev/null +++ b/proguard.cfg @@ -0,0 +1,36 @@ +-optimizationpasses 5 +-dontusemixedcaseclassnames +-dontskipnonpubliclibraryclasses +-dontpreverify +-verbose +-optimizations !code/simplification/arithmetic,!field/*,!class/merging/* + +-keep public class * extends android.app.Activity +-keep public class * extends android.app.Application +-keep public class * extends android.app.Service +-keep public class * extends android.content.BroadcastReceiver +-keep public class * extends android.content.ContentProvider +-keep public class * extends android.app.backup.BackupAgentHelper +-keep public class * extends android.preference.Preference +-keep public class com.android.vending.licensing.ILicensingService + +-keepclasseswithmembernames class * { + native ; +} + +-keepclasseswithmembernames class * { + public (android.content.Context, android.util.AttributeSet); +} + +-keepclasseswithmembernames class * { + public (android.content.Context, android.util.AttributeSet, int); +} + +-keepclassmembers enum * { + public static **[] values(); + public static ** valueOf(java.lang.String); +} + +-keep class * implements android.os.Parcelable { + public static final android.os.Parcelable$Creator *; +} diff --git a/project.properties b/project.properties new file mode 100644 index 0000000..ea89160 --- /dev/null +++ b/project.properties @@ -0,0 +1,11 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system use, +# "ant.properties", and override values to adapt the script to your +# project structure. + +# Project target. +target=android-8 diff --git a/res/drawable-hdpi/icon.png b/res/drawable-hdpi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..8074c4c571b8cd19e27f4ee5545df367420686d7 GIT binary patch literal 4147 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 literal 0 HcmV?d00001 diff --git a/res/drawable-ldpi/icon.png b/res/drawable-ldpi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..1095584ec21f71cd0afc9e0993aa2209671b590c GIT binary patch literal 1723 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 + + + diff --git a/res/values/strings.xml b/res/values/strings.xml new file mode 100644 index 0000000..631af88 --- /dev/null +++ b/res/values/strings.xml @@ -0,0 +1,5 @@ + + + Hello World, Main! + AndroidSQLLiteOrm + diff --git a/src/com/perfectworldprogramming/mobile/orm/AndroidSQLiteTemplate.java b/src/com/perfectworldprogramming/mobile/orm/AndroidSQLiteTemplate.java new file mode 100644 index 0000000..1a39051 --- /dev/null +++ b/src/com/perfectworldprogramming/mobile/orm/AndroidSQLiteTemplate.java @@ -0,0 +1,327 @@ +package com.perfectworldprogramming.mobile.orm; + +import java.util.List; + +import com.perfectworldprogramming.mobile.orm.exception.DataAccessException; +import com.perfectworldprogramming.mobile.orm.exception.EmptySQLStatementException; +import com.perfectworldprogramming.mobile.orm.exception.NoRowsReturnedException; +import com.perfectworldprogramming.mobile.orm.interfaces.CursorExtractor; +import com.perfectworldprogramming.mobile.orm.interfaces.CursorRowMapper; +import com.perfectworldprogramming.mobile.orm.interfaces.JdbcOperations; +import com.perfectworldprogramming.mobile.orm.reflection.DomainClassAnalyzer; + +import android.content.ContentValues; +import android.database.Cursor; +import android.database.SQLException; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteDoneException; +import android.database.sqlite.SQLiteException; +import android.database.sqlite.SQLiteStatement; + +/** + * For queries that return Cursors will use the CursorAdapter class to convert the Cursor into your Domain object, either via + * Annotations you put in your domain objects to map to the tables, or via CursorRowMapper or CursorExtractor implementations. + * Either approach, the CursorAdapter will close the Cursor after it has completed conversion. No need to close Cursors yourself. + * + * User: Mark Spritzler + * Date: 3/10/11 + * Time: 10:07 PM + */ +public class AndroidSQLiteTemplate implements JdbcOperations { + private SQLiteDatabase sqLiteDatabase; + private DomainClassAnalyzer domainClassAnalyzer = new DomainClassAnalyzer(); + private CursorAdapter cursorAdapter = new CursorAdapter(); + + public AndroidSQLiteTemplate(SQLiteDatabase sqLiteDatabase) { + this.sqLiteDatabase = sqLiteDatabase; + } + + @Override + public long insert(Object object) { + ContentValues values = domainClassAnalyzer.createContentValues(object); + long id = sqLiteDatabase.insert(object.getClass().getSimpleName(), + null, values); + // the insert method used above doesn't through an exception if it can't insert, but returns -1 as the result. + if (id != -1) { + domainClassAnalyzer.setIdToNewObject(object, id); + } else { + throw new DataAccessException("Unable to insert new record for object: " + object); + } + return id; + } + + @Override + public long insert(String sql, Object... args) { + sql = replaceParametersInStatement(sql, args); + SQLiteStatement statement = null; + Long results; + try { + statement = sqLiteDatabase.compileStatement(sql); + results = statement.executeInsert(); + } catch (SQLException se) { + throw new DataAccessException(se.getMessage()); + } finally { + if (statement != null) { + statement.close(); + } + } + return results; + } + + @Override + public long update(Object object) { + ContentValues values = domainClassAnalyzer.createContentValues(object); + String whereClause = domainClassAnalyzer.getPrimaryKeyFieldName(object.getClass()) + " = ?"; + String[] whereArgs = {String.valueOf(domainClassAnalyzer.getIdFromObject(object))}; + + return sqLiteDatabase.update(object.getClass().getSimpleName(), + values, whereClause, whereArgs); + } + + @Override + public void update(String sql, Object... args) { + sql = replaceParametersInStatement(sql, args); + SQLiteStatement statement = null; + try { + statement = sqLiteDatabase.compileStatement(sql); + statement.execute(); + } catch (SQLException se) { + throw new DataAccessException(se.getMessage()); + } finally { + if (statement != null) { + statement.close(); + } + } + } + + @Override + public long delete(Object object) { + if (object == null) { + throw new DataAccessException("Please supply a non null domain object to delete(Object) method"); + } + String whereClause = domainClassAnalyzer.getPrimaryKeyFieldName(object.getClass()) + " = ?"; + String[] whereArgs = {String.valueOf(domainClassAnalyzer.getIdFromObject(object))}; + long results = -1; + try { + results = sqLiteDatabase.delete(object.getClass().getSimpleName(), + whereClause, whereArgs); + if (results == 0) { + throw new DataAccessException("unable to delete " + object.getClass().getName() + ". Most likely the Primary Key id value does not exist in the database."); + } + } catch (SQLiteException sle) { + + } + return results; + } + + @Override + public long delete(String table, String columnName, String columnValue) { + if (table == null || columnName == null || columnValue == null || "".equals(table)|| "".equals(columnName)|| "".equals(table)) { + throw new DataAccessException("Please supply tableName, columnName and columnValue in order to delete any data"); + } + String[] args = {columnValue}; + long results = -1; + try { + results = sqLiteDatabase.delete(table, "" + columnName + "=?", args); + } catch (SQLiteException sle) { + throw new DataAccessException("Call to delete(String, String, String) failed. Please check you are passing in correct tableName, columnName and value to this method"); + } + return results; + } + + @Override + public void delete(String sql, Object... args) { + update(sql, args); + } + + @Override + public int queryForInt(String sql, Object... args) { + return (int)queryForLong(sql, args); + } + + @Override + public long queryForLong(String sql, Object... args) { + sql = replaceParametersInStatement(sql, args); + SQLiteStatement statement = null; + long results; + try { + statement = sqLiteDatabase.compileStatement(sql); + results = statement.simpleQueryForLong(); + } catch (SQLiteDoneException se) { + throw new NoRowsReturnedException("Query For Long/Int did not return any rows for sql: " + sql); + } finally { + if (statement != null) { + statement.close(); + } + } + return results; + } + + @Override + public String queryForString(String sql, Object... args) { + sql = replaceParametersInStatement(sql, args); + SQLiteStatement statement = null; + String results; + try { + statement = sqLiteDatabase.compileStatement(sql); + results = statement.simpleQueryForString(); + } catch (SQLiteDoneException se) { + throw new NoRowsReturnedException("Query For String did not return any rows for sql: " + sql); + } catch (SQLException e) { + throw new DataAccessException(e.getMessage()); + } finally { + if (statement != null) { + statement.close(); + } + } + return results; + } + + //** All Implementations below call their corresponding executeFor* private methods for a more central exception handling + @Override + public T queryForObject(String sql, CursorRowMapper cursorRowMapper, Object... args) { + if (cursorRowMapper == null) { + throw new IllegalArgumentException(); + } + sql = replaceParametersInStatement(sql, args); + return executeForSingleObject(sql, cursorRowMapper); + } + + @Override + public T queryForObject(String sql, Class clazz, Object... args) { + sql = replaceParametersInStatement(sql, args); + T t = executeForSingleObject(sql, clazz); + if (t == null) { + throw new DataAccessException("QueryForObject returned no results for query: " + sql); + } + return t; + } + + @Override + public T queryForObject(String sql, CursorExtractor cursorExtractor, Object... args) { + if (cursorExtractor == null) { + throw new IllegalArgumentException(); + } + sql = replaceParametersInStatement(sql, args); + return executeForSingleObject(sql, cursorExtractor); + } + + @Override + public T findById(Class clazz, Long id) { + String sql = generateStatementById(clazz, id); + return executeForSingleObject(sql, clazz); + } + + @Override + public List query(String sql, Class clazz, Object... args) { + sql = replaceParametersInStatement(sql, args); + return executeForList(sql, clazz); + } + + @Override + public List query(String sql, CursorRowMapper cursorRowMapper, Object... args) { + if (cursorRowMapper == null) { + throw new IllegalArgumentException(); + } + sql = replaceParametersInStatement(sql, args); + return executeForList(sql, cursorRowMapper); + } + + private T executeForSingleObject(String sql, CursorExtractor cursorExtractor) { + if (sql == null || "".equals(sql)) { + throw new EmptySQLStatementException(); + } + + if (cursorExtractor == null) { + throw new IllegalArgumentException(); + } + + Cursor cursor = null; + try { + cursor = sqLiteDatabase.rawQuery(sql, null); + return cursorAdapter.adaptFromCursor(cursor, cursorExtractor); + } catch (SQLiteException se) { + throw new DataAccessException(se.getMessage()); + } + } + + private T executeForSingleObject(String sql, CursorRowMapper cursorRowMapper) { + if (cursorRowMapper == null) { + throw new IllegalArgumentException(); + } + Cursor cursor = null; + try { + cursor = sqLiteDatabase.rawQuery(sql, null); + return cursorAdapter.adaptFromCursor(cursor, cursorRowMapper); + } catch (SQLiteException se) { + throw new DataAccessException(se.getMessage()); + } + } + + private T executeForSingleObject(String sql, Class clazz) { + Cursor cursor = null; + try { + cursor = sqLiteDatabase.rawQuery(sql, null); + return cursorAdapter.adaptFromCursor(cursor, clazz); + } catch (SQLiteException se) { + throw new DataAccessException(se.getMessage()); + } + } + + private List executeForList(String sql, CursorRowMapper cursorRowMapper) { + if (cursorRowMapper == null) { + throw new IllegalArgumentException(); + } + Cursor cursor = null; + try { + cursor = sqLiteDatabase.rawQuery(sql, null); + return cursorAdapter.adaptListFromCursor(cursor, cursorRowMapper); + } catch (SQLiteException se) { + throw new DataAccessException(se.getMessage()); + } catch (Exception e) { + throw new DataAccessException("Unable to execute query. Please check your sql for incorrect sql grammer."); + } + } + + private List executeForList(String sql, Class clazz) { + Cursor cursor = null; + try { + cursor = sqLiteDatabase.rawQuery(sql, null); + return cursorAdapter.adaptListFromCursor(cursor, clazz); + } catch (SQLiteException se) { + throw new DataAccessException(se.getMessage()); + } + } + + private String generateStatementById(Class clazz, Long id) { + StringBuilder selectStatement = new StringBuilder("SELECT * FROM "); + selectStatement.append(clazz.getSimpleName()); + selectStatement.append(" WHERE "); + selectStatement.append(domainClassAnalyzer.getPrimaryKeyFieldName(clazz)); + selectStatement.append(" = "); + selectStatement.append(id); + + return selectStatement.toString(); + } + + private String replaceParametersInStatement(String sql, Object... args) { + if (sql == null || "".equals(sql)) { + throw new EmptySQLStatementException(); + } + + if (args != null) { + for (Object arg: args) { + if (arg != null) { + String replaceMe = "[/?]"; + sql = sql.replaceFirst(replaceMe, arg.toString()); + } + } + } + if (sql.contains("?")) { + throw new DataAccessException("Not all Query parameters have been set, please set all values for query to execute"); + } + + return sql; + } + +} diff --git a/src/com/perfectworldprogramming/mobile/orm/CursorAdapter.java b/src/com/perfectworldprogramming/mobile/orm/CursorAdapter.java new file mode 100644 index 0000000..65c599a --- /dev/null +++ b/src/com/perfectworldprogramming/mobile/orm/CursorAdapter.java @@ -0,0 +1,231 @@ +package com.perfectworldprogramming.mobile.orm; + +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.annotations.Transient; +import com.perfectworldprogramming.mobile.orm.exception.DataAccessException; +import com.perfectworldprogramming.mobile.orm.exception.ExtraResultsException; +import com.perfectworldprogramming.mobile.orm.exception.InvalidCursorExtractorException; +import com.perfectworldprogramming.mobile.orm.exception.InvalidCursorRowMapperException; +import com.perfectworldprogramming.mobile.orm.interfaces.CursorExtractor; +import com.perfectworldprogramming.mobile.orm.interfaces.CursorRowMapper; + +import android.database.Cursor; + +/** + * User: Mark Spritzler + * Date: 3/12/11 + * Time: 9:45 PM + */ +public class CursorAdapter { + + /** + * convert a Cursor with a multitude of date rows and return a List of instances of Class + * That is mapped to the corresponding database table that the Cursor has data from + * + * @param cursor returned data from the database query + * @param clazz Domain object Class to put all the data from the cursor + * @param Domain Object type + * @return List returns a list of populated domain objects based on the cursor data. + */ + public List adaptListFromCursor(Cursor cursor, Class clazz) { + List results = new ArrayList(); + if (cursor.getCount() > 0) { + results = getValuesFromCursor(cursor, clazz); + cursor.close(); + } + return results; + } + + /** + * convert a Cursor with a multitude of data rows and return a List of instances by calling + * the CursorRowMapper passed in. This will loop through all the rows of the Cursor and pass + * each row to the CursorRowMapper. + * + * @param cursor returned data from the database query. + * @param cursorRowMapper CursorRowMapper that implements mapRow to convert a row in the cursor to a instance + * @param Domain Object type the CursorRowMapper maps + * @return List returns a list of populated domain objects based on the cursor data. + */ + public List adaptListFromCursor(Cursor cursor, CursorRowMapper cursorRowMapper) { + List values = new ArrayList(); + if (cursor != null) { + if (cursor.moveToFirst()) { + do { + try { + T newInstance = cursorRowMapper.mapRow(cursor, cursor.getPosition()); + values.add(newInstance); + } catch (IllegalStateException ise) { + if (!cursor.isClosed()) { + cursor.close(); + } + throw new InvalidCursorRowMapperException(cursorRowMapper.getClass()); + } + } while (cursor.moveToNext()); + } + if (!cursor.isClosed()) { + cursor.close(); + } + } + return values; + } + + /** + * Returns a Single Domain Object from the Cursor's first row. All other rows will be ignored. + * @param cursor returned data from the database query. + * @param clazz Domain object Class to put all the data from the cursor + * @param Domain Object type of the Class + * @return T domain object populated with data from the first row in the Cursor + */ + public T adaptFromCursor(Cursor cursor, Class clazz) { + T newInstance = null; + if (cursor != null) { + if (cursor.moveToFirst()) { + newInstance = getSingleObjectValuesFromCursor(cursor, clazz); + cursor.close(); + } + } + return newInstance; + } + + public T adaptFromCursor(Cursor cursor, CursorRowMapper cursorRowMapper) { + T newInstance = null; + if (cursor != null) { + if(cursor.getCount() != 1) { + throw new ExtraResultsException(cursor.getCount()); + } + + if (cursor.moveToFirst()) { + try { + newInstance = cursorRowMapper.mapRow(cursor, 1); + } catch (IllegalStateException ise) { + throw new InvalidCursorRowMapperException(cursorRowMapper.getClass()); + } finally { + if (!cursor.isClosed()) { + cursor.close(); + } + } + } + } + return newInstance; + } + + /** + * Converts the data from the Cursor into a Domain object based on the CursorExtractor callback. + * + * A CursorExtractor receives the entire Cursor, and is responsible for looping through the + * dataset and created the more complex domain object tree graph. + * + * @param cursor returned data from the database query. + * @param cursorExtractor Callback interface that receives the entire Cursor + * @param Domain Object type of the Class + * @return T Domain Object fully populated with data from the Cursor + */ + public T adaptFromCursor(Cursor cursor, CursorExtractor cursorExtractor) { + T result = null; + try { + result = cursorExtractor.extractData(cursor); + } catch (IllegalStateException ise) { + throw new InvalidCursorExtractorException(cursorExtractor.getClass()); + } finally { + if (!cursor.isClosed()) { + cursor.close(); + } + } + return result; + } + + private List getValuesFromCursor(Cursor cursor, Class clazz) { + List values = new ArrayList(); + if (cursor != null) { + if (cursor.moveToFirst()) { + do { + T newInstance = getSingleObjectValuesFromCursor(cursor, clazz); + values.add(newInstance); + } while (cursor.moveToNext()); + } + cursor.close(); + } + return values; + } + + private T getSingleObjectValuesFromCursor(Cursor cursor, Class clazz) { + T newInstance = null; + try { + newInstance = clazz.newInstance(); + setFieldValues(clazz, newInstance, cursor); + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + + return newInstance; + } + + private void setFieldValues(Class clazz, T object, Cursor cursor) { + Field[] fields = clazz.getDeclaredFields(); + for (Field field : fields) { + setFieldValue(field, object, cursor); + } + } + + private void setFieldValue(Field fieldToSet, T object, Cursor cursor) { + + //Skip over @Transient and @ForeignKey fields + if (fieldToSet.isAnnotationPresent(Transient.class) || + fieldToSet.isAnnotationPresent(ForeignKey.class)) { + return; + } + String columnName = getColumnName(fieldToSet); + + int columnIndex = cursor.getColumnIndex(columnName); + + fieldToSet.setAccessible(true); + Class clazz = fieldToSet.getType(); + Object value = getValue(clazz, cursor, columnIndex); + if (value != null) { + try { + fieldToSet.set(object, value); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + } + + private String getColumnName(Field field) { + String columnName; + Column column = field.getAnnotation(Column.class); + if (column == null) { + PrimaryKey key = field.getAnnotation(PrimaryKey.class); + columnName = key.value(); + } else { + columnName = column.value(); + } + return columnName; + } + + private Object getValue(Class clazz, Cursor cursor, int columnIndex) { + if (cursor.getColumnCount() <= columnIndex || columnIndex < 0) { + throw new DataAccessException("Column index " + columnIndex + " does not exist"); + } + if (clazz.getName().endsWith("Integer") || clazz.getName().endsWith("int")) { + return cursor.getInt(columnIndex); + } else if (clazz.getName().endsWith("Long") || clazz.getName().endsWith("long")) { + return cursor.getLong(columnIndex); + } else if (clazz.getName().endsWith("Double") || clazz.getName().endsWith("double")) { + return cursor.getDouble(columnIndex); + } else if (clazz.getName().endsWith("Float") || clazz.getName().endsWith("float")) { + return cursor.getFloat(columnIndex); + } else if (clazz.getName().endsWith("String")) { + return cursor.getString(columnIndex); + } + return null; + } + +} diff --git a/src/com/perfectworldprogramming/mobile/orm/Main.java b/src/com/perfectworldprogramming/mobile/orm/Main.java new file mode 100644 index 0000000..170d393 --- /dev/null +++ b/src/com/perfectworldprogramming/mobile/orm/Main.java @@ -0,0 +1,19 @@ +package com.perfectworldprogramming.mobile.orm; + +import com.perfectworldprogramming.mobile.orm.R; + +import com.perfectworldprogramming.mobile.orm.helper.AndroidSQLLiteOpenHelper; + +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(), null, "ormtest", 1); + dbHelper.getWritableDatabase(); + } +} \ No newline at end of file diff --git a/src/com/perfectworldprogramming/mobile/orm/annotations/Column.java b/src/com/perfectworldprogramming/mobile/orm/annotations/Column.java new file mode 100644 index 0000000..a14c96d --- /dev/null +++ b/src/com/perfectworldprogramming/mobile/orm/annotations/Column.java @@ -0,0 +1,54 @@ +package com.perfectworldprogramming.mobile.orm.annotations; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation to place of Domain object properties to map them to a field + * in a database table. + * + * User: Mark Spritzler + * Date: 3/10/11 + * Time: 8:36 PM + */ +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@ColumnSetter() +public @interface Column { + /** + * Column name in the database. This will be used in the CREATE statements + * and for setting the domain property to the value of the column in the database. + * + * @return String field name in the database + */ + public String value() default ""; + + /** + * Should the column be unique and not allow duplicates. + * + * default value is false, allowing for duplicates in the database. + * + * @return boolean + */ + public boolean unique() default false; + + /** + * Should the column allow nulls. True allows nulls, False does not allow nulls + * + * default value is true, allowing for nulls. + * + * @return boolean + */ + public boolean nullable() default true; + + /** + * Used to determine the field type to use in the CREATE statement. + * + * @return ColumnType + */ + public ColumnType type() default ColumnType.TEXT; +} diff --git a/src/com/perfectworldprogramming/mobile/orm/annotations/ColumnSetter.java b/src/com/perfectworldprogramming/mobile/orm/annotations/ColumnSetter.java new file mode 100644 index 0000000..e3ea34a --- /dev/null +++ b/src/com/perfectworldprogramming/mobile/orm/annotations/ColumnSetter.java @@ -0,0 +1,17 @@ +package com.perfectworldprogramming.mobile.orm.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * User: Mark Spritzler + * Date: 3/23/11 + * Time: 6:33 PM + */ +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface ColumnSetter { + public String value() default ""; +} diff --git a/src/com/perfectworldprogramming/mobile/orm/annotations/ColumnType.java b/src/com/perfectworldprogramming/mobile/orm/annotations/ColumnType.java new file mode 100644 index 0000000..9493397 --- /dev/null +++ b/src/com/perfectworldprogramming/mobile/orm/annotations/ColumnType.java @@ -0,0 +1,13 @@ +package com.perfectworldprogramming.mobile.orm.annotations; + +/** + * User: Mark Spritzler + * Date: 3/10/11 + * Time: 8:42 PM + */ +public enum ColumnType { + TEXT, + INTEGER, + REAL, + BLOB +} diff --git a/src/com/perfectworldprogramming/mobile/orm/annotations/ForeignKey.java b/src/com/perfectworldprogramming/mobile/orm/annotations/ForeignKey.java new file mode 100644 index 0000000..97a8eed --- /dev/null +++ b/src/com/perfectworldprogramming/mobile/orm/annotations/ForeignKey.java @@ -0,0 +1,22 @@ +package com.perfectworldprogramming.mobile.orm.annotations; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation to put on a ManyToOne association between domain objects. + * + * User: Mark Spritzler + * Date: 3/10/11 + * Time: 9:21 PM + */ +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@ColumnSetter +public @interface ForeignKey { + public String value() default ""; +} diff --git a/src/com/perfectworldprogramming/mobile/orm/annotations/PrimaryKey.java b/src/com/perfectworldprogramming/mobile/orm/annotations/PrimaryKey.java new file mode 100644 index 0000000..d6e4fda --- /dev/null +++ b/src/com/perfectworldprogramming/mobile/orm/annotations/PrimaryKey.java @@ -0,0 +1,26 @@ +package com.perfectworldprogramming.mobile.orm.annotations; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation to put on the Primary Key field of a domain object. + * + * It is best to make the property to be a Long. + * + * The generated Primary Key field in the database will be an auto-increment field. + * + * User: Mark Spritzler + * Date: 3/10/11 + * Time: 9:44 PM + */ +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@ColumnSetter +public @interface PrimaryKey { + public String value() default ""; +} diff --git a/src/com/perfectworldprogramming/mobile/orm/annotations/Transient.java b/src/com/perfectworldprogramming/mobile/orm/annotations/Transient.java new file mode 100644 index 0000000..7fb5856 --- /dev/null +++ b/src/com/perfectworldprogramming/mobile/orm/annotations/Transient.java @@ -0,0 +1,18 @@ +package com.perfectworldprogramming.mobile.orm.annotations; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * User: Mark Spritzler + * Date: 3/17/11 + * Time: 4:30 PM + */ +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Transient { +} diff --git a/src/com/perfectworldprogramming/mobile/orm/creator/CreateStatementGenerator.java b/src/com/perfectworldprogramming/mobile/orm/creator/CreateStatementGenerator.java new file mode 100644 index 0000000..b731882 --- /dev/null +++ b/src/com/perfectworldprogramming/mobile/orm/creator/CreateStatementGenerator.java @@ -0,0 +1,47 @@ +package com.perfectworldprogramming.mobile.orm.creator; + +import java.util.List; + +/** + * User: Mark Spritzler + * Date: 3/19/11 + * Time: 2:53 PM + */ +public interface CreateStatementGenerator { + + /** + * List of Create statements to run on the database to create tables + * + * @return List List of Create statements to run on the database to create tables. + */ + public List getCreateStatements(); + + /** + * Creates a CREATE SQL Statement for the Class that is passed in as a parameter. + * The Class is mapped with the Spring Mobile ORM annotations. Without those + * annotations this method should return + * + * The returned CREATE statement can be run by an Android SQLLiteDatabaseHelper class to create + * the tables when the SQLLiteDatabaseHelper class' onCreate method is called. + * + * @param clazz domain class + * @return String Create SQL Statement to run on the database to create a database table. + */ + public String createCreateStatement(Class clazz); + + /** + * * Creates a CREATE SQL Statement with 'IF NOT EXISTS' for the Class that is passed in as a parameter. + * The Class is mapped with the Spring Mobile ORM annotations. Without those + * annotations this method should return + * + * The returned CREATE statement can be run by an Android SQLLiteDatabaseHelper class to create + * the tables when the SQLLiteDatabaseHelper class' onUpdate method is called. + * + * This will create new tables added in the update and also let us know what already exists to update the fields + * + * @param clazz domain class + * @return String Create SQL Statement to run on the database to create a database table. + */ + public String createCreateIfNotExistsStatement(Class clazz); + +} diff --git a/src/com/perfectworldprogramming/mobile/orm/creator/SQLLiteCreateStatementGenerator.java b/src/com/perfectworldprogramming/mobile/orm/creator/SQLLiteCreateStatementGenerator.java new file mode 100644 index 0000000..ba19f00 --- /dev/null +++ b/src/com/perfectworldprogramming/mobile/orm/creator/SQLLiteCreateStatementGenerator.java @@ -0,0 +1,177 @@ +package com.perfectworldprogramming.mobile.orm.creator; + +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; +import com.perfectworldprogramming.mobile.orm.reflection.DomainClassAnalyzer; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + +/** + * This class generates CREATE SQL statements for mapped Domain objects. + * + * There are two approaches to use this class. + *
  • Assign the classes property to an array of Class objects for each domain + * object you want create statements for. Then call the getCreateStatements method to return + * a List of Strings. Each string is a create statement for one table
  • + *
  • just call the createCreateStatement method passing in a single Class which + * returns a single Create String SQL statement
  • + *
+ * + * User: Mark Spritzler + * Date: 3/10/11 + * Time: 8:55 PM + */ +public class SQLLiteCreateStatementGenerator implements CreateStatementGenerator { + + private static final String CREATE_TABLE = "CREATE TABLE "; + private static final String CREATE_TABLE_IF_NOT_EXISTS = "CREATE TABLE IF NOT EXISTS "; + private static final String PRIMARY_KEY = "PRIMARY KEY"; + private static final String UNIQUE = "UNIQUE"; + private static final String NOT_NULL = "NOT NULL"; + private static final String FOREIGN_KEY_ELEMENT = " INTEGER REFERENCES ()"; //" FOREIGN KEY() REFERENCES ()"; + private static final String SPACE = " "; + + private Class[] classes; + private DomainClassAnalyzer domainClassAnalyzer = new DomainClassAnalyzer(); + + /** + * Creates a SQLLiteCreateStatementGenerator without the Classes to make create SQL statements for + * Call the setClasses method to set the classes so that we can create the create statements + * or call the createCreateStatement + */ + public SQLLiteCreateStatementGenerator() {} + + /** + * Constructor that takes an array of domain {@link Class}es to create tables + * for in SQLLite create statements + * @param classes array of classes to create tables for + */ + public SQLLiteCreateStatementGenerator(Class[] classes) { + this.classes = classes; + } + + /** + * Setter method for classes property + * + * @param classes Array of Class objects for all the Domain objects to create tables for + */ + public void setClasses(Class[] classes) { + this.classes = classes; + } + + @Override + public List getCreateStatements() { + if (classes == null) { + throw new IllegalArgumentException("You must assign the domain classes to the SQLLiteCreateStatementGenerator class before generating the create statements"); + } + List createStatements = new ArrayList(classes.length); + for (Class clazz : classes) { + createStatements.add(createCreateStatement(clazz)); + } + return createStatements; + } + + @Override + public String createCreateStatement(Class clazz) { + return createStatement(clazz, CREATE_TABLE); + } + + public String createCreateIfNotExistsStatement(Class clazz) { + return createStatement(clazz, CREATE_TABLE_IF_NOT_EXISTS); + } + + /** + * Always the same code to create a create table statement. Only differences is if it needs to include IF NOT EXISTS. + */ + private String createStatement(Class clazz, String create) { + StringBuilder createStatement = new StringBuilder(create); + createStatement.append(clazz.getSimpleName()); + createStatement.append(" ("); + addAllToStatement(createStatement, clazz); + return createStatement.toString(); + } + + private void addAllToStatement(StringBuilder createStatement, Class clazz) { + Field[] fields = getFieldsToAddToStatement(clazz); + + if (fields.length == 0) { + return; + } + + for (int i = 0; i< fields.length; i++ ) { + Field field = fields[i]; + PrimaryKey primaryKey = field.getAnnotation(PrimaryKey.class); + if (primaryKey != null) { + addPrimaryKeyToStatement(createStatement, primaryKey); + } + Column column = field.getAnnotation(Column.class); + if (column != null) { + addColumnsToStatement(createStatement, column); + } + ForeignKey foreignKey = field.getAnnotation(ForeignKey.class); + if (foreignKey != null) { + addForeignKeyToStatement(createStatement, field, foreignKey); + } + + if (i != (fields.length-1)) { + createStatement.append(", "); + } else { + createStatement.append(")"); + } + } + } + + private Field[] getFieldsToAddToStatement(Class clazz) { + List fieldsToAdd = new ArrayList(); + Field[] fields = clazz.getDeclaredFields(); + for (Field field : fields) { + if (field.isAnnotationPresent(PrimaryKey.class) || + field.isAnnotationPresent(Column.class) || + field.isAnnotationPresent(ForeignKey.class)) { + fieldsToAdd.add(field); + } + } + return fieldsToAdd.toArray(new Field[fieldsToAdd.size()]); + } + + private void addPrimaryKeyToStatement(StringBuilder createStatement, PrimaryKey primaryKey) { + String pkName = primaryKey.value(); + if (pkName.equals("")) { + pkName = "ID"; + } + createStatement.append(pkName); + createStatement.append(SPACE); + createStatement.append(ColumnType.INTEGER); + createStatement.append(SPACE); + createStatement.append(PRIMARY_KEY); + } + + private void addForeignKeyToStatement(StringBuilder createStatement, Field field, ForeignKey foreignKey) { + Class clazz = field.getType(); + String fkField = domainClassAnalyzer.getPrimaryKeyFieldName(clazz); + String foreignTable = field.getType().getSimpleName(); + String s = FOREIGN_KEY_ELEMENT.replaceAll("", foreignTable) + .replaceAll("", foreignKey.value()) + .replaceAll("", fkField); + createStatement.append(s); + } + + private void addColumnsToStatement(StringBuilder createStatement, Column column) { + createStatement.append(column.value()); + createStatement.append(SPACE); + createStatement.append(column.type().name()); + createStatement.append(SPACE); + if (column.unique()) { + createStatement.append(UNIQUE); + createStatement.append(SPACE); + } + if (!column.nullable()){ + createStatement.append(NOT_NULL); + createStatement.append(SPACE); + } + } +} diff --git a/src/com/perfectworldprogramming/mobile/orm/exception/DataAccessException.java b/src/com/perfectworldprogramming/mobile/orm/exception/DataAccessException.java new file mode 100644 index 0000000..dee4efd --- /dev/null +++ b/src/com/perfectworldprogramming/mobile/orm/exception/DataAccessException.java @@ -0,0 +1,18 @@ +package com.perfectworldprogramming.mobile.orm.exception; + +/** + * User: Mark Spritzler + * Date: 4/6/11 + * Time: 11:26 AM + */ +public class DataAccessException extends RuntimeException { + + /** + * + */ + private static final long serialVersionUID = 1L; + + public DataAccessException(String msg) { + super(msg); + } +} diff --git a/src/com/perfectworldprogramming/mobile/orm/exception/EmptySQLStatementException.java b/src/com/perfectworldprogramming/mobile/orm/exception/EmptySQLStatementException.java new file mode 100644 index 0000000..e36321d --- /dev/null +++ b/src/com/perfectworldprogramming/mobile/orm/exception/EmptySQLStatementException.java @@ -0,0 +1,10 @@ +package com.perfectworldprogramming.mobile.orm.exception; + +public class EmptySQLStatementException extends DataAccessException { + + private static final long serialVersionUID = 1L; + + public EmptySQLStatementException() { + super("Invalid SQL. Please supply an SQL query string."); + } +} diff --git a/src/com/perfectworldprogramming/mobile/orm/exception/ExtraResultsException.java b/src/com/perfectworldprogramming/mobile/orm/exception/ExtraResultsException.java new file mode 100644 index 0000000..c394570 --- /dev/null +++ b/src/com/perfectworldprogramming/mobile/orm/exception/ExtraResultsException.java @@ -0,0 +1,15 @@ +package com.perfectworldprogramming.mobile.orm.exception; + +/** + * User: Mark Spritzler + * Date: 4/6/11 + * Time: 11:27 AM + */ +public class ExtraResultsException extends DataAccessException { + + private static final long serialVersionUID = 1L; + + public ExtraResultsException(int numberOfResults) { + super("Expected one row returned by query but received " + numberOfResults); + } +} diff --git a/src/com/perfectworldprogramming/mobile/orm/exception/InvalidCursorExtractorException.java b/src/com/perfectworldprogramming/mobile/orm/exception/InvalidCursorExtractorException.java new file mode 100644 index 0000000..58f7967 --- /dev/null +++ b/src/com/perfectworldprogramming/mobile/orm/exception/InvalidCursorExtractorException.java @@ -0,0 +1,11 @@ +package com.perfectworldprogramming.mobile.orm.exception; + +public class InvalidCursorExtractorException extends DataAccessException { + + private static final long serialVersionUID = 1L; + + public InvalidCursorExtractorException(Class class1) { + super("Invalid CursorExtractor: " + class1.getName() + ". Possible reasons are 1) query does not contain all the fields, 2) query is using the wrong tables, 3) Not navigating through the Cursor correctly, either by the cursor is empty, or has past the end of the results."); + } + +} diff --git a/src/com/perfectworldprogramming/mobile/orm/exception/InvalidCursorRowMapperException.java b/src/com/perfectworldprogramming/mobile/orm/exception/InvalidCursorRowMapperException.java new file mode 100644 index 0000000..66188ef --- /dev/null +++ b/src/com/perfectworldprogramming/mobile/orm/exception/InvalidCursorRowMapperException.java @@ -0,0 +1,10 @@ +package com.perfectworldprogramming.mobile.orm.exception; + +public class InvalidCursorRowMapperException extends DataAccessException { + + private static final long serialVersionUID = 1L; + + public InvalidCursorRowMapperException(Class class1) { + super("Invalid CursorRowMapper: " + class1.getName() + ". Possible reasons are 1) query does not contain all the fields, 2) query is using the wrong tables, 3) Not navigating through the Cursor correctly, either by the cursor is empty, or has past the end of the results."); + } +} \ No newline at end of file diff --git a/src/com/perfectworldprogramming/mobile/orm/exception/InvalidQueryTypeException.java b/src/com/perfectworldprogramming/mobile/orm/exception/InvalidQueryTypeException.java new file mode 100644 index 0000000..86b01be --- /dev/null +++ b/src/com/perfectworldprogramming/mobile/orm/exception/InvalidQueryTypeException.java @@ -0,0 +1,13 @@ +package com.perfectworldprogramming.mobile.orm.exception; + +public class InvalidQueryTypeException extends DataAccessException { + /** + * + */ + private static final long serialVersionUID = 1L; + + public InvalidQueryTypeException(String expectedType, String givenType) { + super("Invalid Query type. Was expecting a " + expectedType + " but received a " + givenType); + } + +} diff --git a/src/com/perfectworldprogramming/mobile/orm/exception/NoPrimaryKeyFieldException.java b/src/com/perfectworldprogramming/mobile/orm/exception/NoPrimaryKeyFieldException.java new file mode 100644 index 0000000..8768bee --- /dev/null +++ b/src/com/perfectworldprogramming/mobile/orm/exception/NoPrimaryKeyFieldException.java @@ -0,0 +1,13 @@ +package com.perfectworldprogramming.mobile.orm.exception; + +public class NoPrimaryKeyFieldException extends DataAccessException { + + /** + * + */ + private static final long serialVersionUID = 1L; + + public NoPrimaryKeyFieldException(Class clazz) { + super("No primary key field found in class " + clazz.getSimpleName()); + } +} \ No newline at end of file diff --git a/src/com/perfectworldprogramming/mobile/orm/exception/NoRowsReturnedException.java b/src/com/perfectworldprogramming/mobile/orm/exception/NoRowsReturnedException.java new file mode 100644 index 0000000..8c39a99 --- /dev/null +++ b/src/com/perfectworldprogramming/mobile/orm/exception/NoRowsReturnedException.java @@ -0,0 +1,13 @@ +package com.perfectworldprogramming.mobile.orm.exception; + +public class NoRowsReturnedException extends DataAccessException { + + /** + * + */ + private static final long serialVersionUID = 1L; + + public NoRowsReturnedException(String msg) { + super("No rows returned for query " + msg); + } +} diff --git a/src/com/perfectworldprogramming/mobile/orm/helper/AndroidSQLLiteOpenHelper.java b/src/com/perfectworldprogramming/mobile/orm/helper/AndroidSQLLiteOpenHelper.java new file mode 100644 index 0000000..fcf7e6e --- /dev/null +++ b/src/com/perfectworldprogramming/mobile/orm/helper/AndroidSQLLiteOpenHelper.java @@ -0,0 +1,105 @@ +package com.perfectworldprogramming.mobile.orm.helper; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import com.perfectworldprogramming.mobile.orm.creator.SQLLiteCreateStatementGenerator; +import com.perfectworldprogramming.mobile.orm.exception.DataAccessException; + +import android.content.Context; +import android.database.Cursor; +import android.database.SQLException; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import android.util.Log; + +/** + * User: Mark Spritzler + * Date: 3/10/11 + * Time: 7:51 PM + */ +public class AndroidSQLLiteOpenHelper extends SQLiteOpenHelper { + + protected Class[] classes; + + public AndroidSQLLiteOpenHelper(Context context, Class[] classes, String dataBaseName, int dataBaseVersion) { + super(context, dataBaseName, null, dataBaseVersion); + this.classes = classes; + } + + @Override + public void onCreate(SQLiteDatabase sqLiteDatabase) { + SQLLiteCreateStatementGenerator sqlLiteCreateStatementGenerator = new SQLLiteCreateStatementGenerator(); + for (Class clazz : classes) { + sqLiteDatabase.execSQL(sqlLiteCreateStatementGenerator.createCreateStatement(clazz)); + } + } + + /* + * beginTransaction + run a table creation with if not exists (we are doing an upgrade, so the table might not exists yet, it will fail alter and drop) + put in a list the existing columns List columns = DBUtils.GetColumns(db, TableName); + backup table (ALTER table " + TableName + " RENAME TO 'temp_" + TableName) + create new table (the newest table creation schema) + get the intersection with the new columns, this time columns taken from the upgraded table (columns.retainAll(DBUtils.GetColumns(db, TableName));) + restore data (String cols = StringUtils.join(columns, ","); db.execSQL(String.format( "INSERT INTO %s (%s) SELECT %s from temp_%s", TableName, cols, cols, TableName)); ) + remove backup table (DROP table 'temp_" + TableName) + setTransactionSuccessful + */ + @Override + public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) { + SQLLiteCreateStatementGenerator sqlLiteCreateStatementGenerator = new SQLLiteCreateStatementGenerator(); + sqLiteDatabase.beginTransaction(); + for (Class clazz : classes) { + // Thanks to Pentium10 at Stack Overflow for this solution. + String createStatementIfNotExists = sqlLiteCreateStatementGenerator.createCreateIfNotExistsStatement(clazz); + String tableName = clazz.getSimpleName(); + try { + sqLiteDatabase.execSQL(createStatementIfNotExists); + List columns = getColumns(sqLiteDatabase, tableName); + sqLiteDatabase.execSQL("ALTER table " + tableName + " RENAME TO 'temp_" + tableName + "'"); + sqLiteDatabase.execSQL(sqlLiteCreateStatementGenerator.createCreateStatement(clazz)); + columns.retainAll(getColumns(sqLiteDatabase, tableName)); + String cols = join(columns, ","); + sqLiteDatabase.execSQL(String.format( "INSERT INTO %s (%s) SELECT %s from temp_%s", tableName, cols, cols, tableName)); + sqLiteDatabase.execSQL("DROP table 'temp_" + tableName +"'"); + } catch (SQLException e) { + Log.v(tableName, e.getMessage(), e); + throw new DataAccessException(e.getMessage()); + } + } + sqLiteDatabase.setTransactionSuccessful(); + sqLiteDatabase.endTransaction(); + + } + + private static List getColumns(SQLiteDatabase db, String tableName) { + List ar = null; + Cursor c = null; + try { + c = db.rawQuery("select * from " + tableName + " limit 1", null); + if (c != null) { + ar = new ArrayList(Arrays.asList(c.getColumnNames())); + } + } catch (Exception e) { + Log.v(tableName, e.getMessage(), e); + e.printStackTrace(); + } finally { + if (c != null) + c.close(); + } + return ar; + } + + private static String join(List 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[] 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 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 clazz) { + PrimaryKey primaryKey = getPrimaryKey(clazz); + return primaryKey.value(); + } + + public PrimaryKey getPrimaryKey(Class clazz) { + return getPrimaryKeyField(clazz).getAnnotation(PrimaryKey.class); + } + + public Field[] getForeignKeyFields(Class 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 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 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; + } +}