diff --git a/example/src/com/example/AddNoteActivity.java b/example/src/com/example/AddNoteActivity.java index 06a6c62f..aba5e236 100755 --- a/example/src/com/example/AddNoteActivity.java +++ b/example/src/com/example/AddNoteActivity.java @@ -9,6 +9,8 @@ import android.widget.LinearLayout; import android.widget.TextView; +import static com.orm.SugarRecord.save; + public class AddNoteActivity extends Activity { public void onCreate(Bundle savedInstanceState) { @@ -39,8 +41,8 @@ public void onCreate(Bundle savedInstanceState) { save.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { Tag tag = new Tag(tagBox.getText().toString()); - tag.save(); - new Note( 10, titleBox.getText().toString(), descBox.getText().toString(),tag).save(); + save(tag); + save(new Note(10 + (int) (10 * Math.random()), titleBox.getText().toString(), descBox.getText().toString(), tag)); Intent intent = new Intent(AddNoteActivity.this, NoteListActivity.class); startActivity(intent); } diff --git a/example/src/com/example/NewNote.java b/example/src/com/example/NewNote.java new file mode 100644 index 00000000..a80e2d4a --- /dev/null +++ b/example/src/com/example/NewNote.java @@ -0,0 +1,11 @@ +package com.example; + +import com.orm.dsl.Table; + +@Table(name = "new_note") +public class NewNote { + + public long id; + public String name; + +} diff --git a/example/src/com/example/Note.java b/example/src/com/example/Note.java index 8e6308f9..b83f730f 100755 --- a/example/src/com/example/Note.java +++ b/example/src/com/example/Note.java @@ -1,9 +1,12 @@ package com.example; -import com.orm.SugarRecord; import com.orm.dsl.Column; +import com.orm.dsl.Table; -public class Note extends SugarRecord{ +@Table(name = "Note") +public class Note { + + private long id; @Column(name = "noteId", unique = true, notNull = true) private int noteId; @@ -42,25 +45,25 @@ public String getTitle() { return title; } - public String getDescription() { - return description; + public void setTitle(String title) { + this.title = title; } - public Tag getTag() { - return tag; + public String getDescription() { + return description; } public void setDescription(String description){ this.description = description; } - public void setTitle(String title) { - this.title = title; + public Tag getTag() { + return tag; } @Override public String toString() { - return title + "id: " + id + " - " + tag + " " + tag.getId(); + return title + "id: " + noteId; } } diff --git a/example/src/com/example/NoteListActivity.java b/example/src/com/example/NoteListActivity.java index a5d0399b..09877f2d 100755 --- a/example/src/com/example/NoteListActivity.java +++ b/example/src/com/example/NoteListActivity.java @@ -6,7 +6,7 @@ import android.util.Log; import android.view.View; import android.widget.ArrayAdapter; - +import com.orm.SugarRecord; import com.orm.query.Condition; import com.orm.query.Select; @@ -19,8 +19,9 @@ public void onCreate(Bundle savedInstanceState) { setContentView(R.layout.notelist); List notes = Select.from(Note.class).orderBy("title").list();//Note.listAll(Note.class); + List list = SugarRecord.listAll(NewNote.class); - setListAdapter(new ArrayAdapter(this,android.R.layout.simple_list_item_1, notes)); + setListAdapter(new ArrayAdapter(this, android.R.layout.simple_list_item_1, notes)); findViewById(R.id.Button01).setOnClickListener(new View.OnClickListener() { public void onClick(View view) { diff --git a/example/src/com/example/NoteRelation.java b/example/src/com/example/NoteRelation.java index 1a971d7d..a64d055a 100644 --- a/example/src/com/example/NoteRelation.java +++ b/example/src/com/example/NoteRelation.java @@ -1,9 +1,10 @@ package com.example; import android.content.Context; -import com.orm.SugarRecord; +import com.orm.dsl.Table; -public class NoteRelation extends SugarRecord { +@Table(name = "note_relation") +public class NoteRelation { String name; int noteId; diff --git a/example/src/com/example/SugarActivity.java b/example/src/com/example/SugarActivity.java index f5b8fe9f..b7130f86 100755 --- a/example/src/com/example/SugarActivity.java +++ b/example/src/com/example/SugarActivity.java @@ -2,11 +2,10 @@ import android.app.Activity; import android.content.Intent; -import android.database.sqlite.SQLiteDatabase; import android.os.Bundle; -import android.util.Log; -import com.orm.Database; -import com.orm.SugarApp; +import com.orm.SugarRecord; + +import static com.orm.SugarRecord.save; public class SugarActivity extends Activity { @@ -16,9 +15,10 @@ public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); - Note.deleteAll(Note.class); - TextNote.deleteAll(TextNote.class); - Tag.deleteAll(Tag.class); + SugarRecord.deleteAll(Note.class); + SugarRecord.deleteAll(TextNote.class); + SugarRecord.deleteAll(Tag.class); + SugarRecord.deleteAll(NewNote.class); initDb(); Intent intent = new Intent(this, NoteListActivity.class); startActivity(intent); @@ -28,8 +28,8 @@ private void initDb() { Tag t1 = new Tag("tag1"); Tag t2 = new Tag("tag2"); - t1.save(); - t2.save(); + save(t1); + save(t2); Note n1 = new Note( 10, "note1", "description1", t1); Note n2 = new Note(11, "note12", "description2", t1); @@ -39,23 +39,25 @@ private void initDb() { TextNote textNote = new TextNote(); textNote.desc = "Test"; - textNote.save(); - n1.save(); - n2.save(); - n3.save(); - n4.save(); + save(textNote); + save(n1); + save(n2); + save(n3); + save(n4); n1.setDescription("matrix"); n1.setTitle("atrix"); - n1.save(); + save(n1); n2.setDescription("matrix"); n2.setTitle("satrix"); - n2.save(); + save(n2); n3.setDescription("matrix"); n3.setTitle("batrix"); - n3.save(); - - + save(n3); - } + NewNote newNote = new NewNote(); + newNote.name = "name"; + save(newNote); + + } } diff --git a/example/src/com/example/Tag.java b/example/src/com/example/Tag.java index 24d8c145..6600c14a 100755 --- a/example/src/com/example/Tag.java +++ b/example/src/com/example/Tag.java @@ -1,9 +1,9 @@ package com.example; -import android.content.Context; -import com.orm.SugarRecord; +import com.orm.dsl.Table; -public class Tag extends SugarRecord{ +@Table(name = "tag") +public class Tag { private String name; public Tag(String name) { diff --git a/example/src/com/example/TextNote.java b/example/src/com/example/TextNote.java index c4025774..91b7a33c 100644 --- a/example/src/com/example/TextNote.java +++ b/example/src/com/example/TextNote.java @@ -1,5 +1,8 @@ package com.example; +import com.orm.dsl.Table; + +@Table(name = "text_note") public class TextNote extends Note { public String desc; diff --git a/library/src/com/orm/Database.java b/library/src/com/orm/Database.java deleted file mode 100644 index 0896ee1f..00000000 --- a/library/src/com/orm/Database.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.orm; - -import android.content.Context; -import android.database.sqlite.SQLiteDatabase; - - -public class Database { - private SugarDb sugarDb; - private SQLiteDatabase sqLiteDatabase; - - public Database(Context context){ - this.sugarDb = new SugarDb(context); - } - - - public synchronized SQLiteDatabase getDB() { - if (this.sqLiteDatabase == null) { - this.sqLiteDatabase = this.sugarDb.getWritableDatabase(); - } - - return this.sqLiteDatabase; - } - -} diff --git a/library/src/com/orm/SchemaGenerator.java b/library/src/com/orm/SchemaGenerator.java new file mode 100644 index 00000000..3dc1f72b --- /dev/null +++ b/library/src/com/orm/SchemaGenerator.java @@ -0,0 +1,173 @@ +package com.orm; + +import android.content.Context; +import android.database.SQLException; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteException; +import android.util.Log; +import com.orm.dsl.Column; +import com.orm.dsl.NotNull; +import com.orm.dsl.Unique; +import com.orm.util.NamingHelper; +import com.orm.util.NumberComparator; +import com.orm.util.QueryBuilder; +import com.orm.util.ReflectionUtil; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static com.orm.util.ReflectionUtil.getDomainClasses; + +public class SchemaGenerator { + + private Context context; + + public SchemaGenerator(Context context) { + this.context = context; + } + + public void createDatabase(SQLiteDatabase sqLiteDatabase) { + List domainClasses = getDomainClasses(context); + for (Class domain : domainClasses) { + createTable(domain, sqLiteDatabase); + } + } + + public void doUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) { + List domainClasses = getDomainClasses(context); + for (Class domain : domainClasses) { + try {// we try to do a select, if fails then (?) there isn't the table + sqLiteDatabase.query(NamingHelper.toSQLName(domain), null, null, null, null, null, null); + } catch (SQLiteException e) { + Log.i("Sugar", String.format("creating table on update (error was '%s')", e.getMessage())); + createTable(domain, sqLiteDatabase); + } + } + + executeSugarUpgrade(sqLiteDatabase, oldVersion, newVersion); + } + + public void deleteTables(SQLiteDatabase sqLiteDatabase) { + List tables = getDomainClasses(context); + for (Class table : tables) { + sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + NamingHelper.toSQLName(table)); + } + } + + private boolean executeSugarUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + + boolean isSuccess = false; + try { + List files = Arrays.asList(this.context.getAssets().list("sugar_upgrades")); + Collections.sort(files, new NumberComparator()); + + for (String file : files) { + Log.i("Sugar", "filename : " + file); + try { + int version = Integer.valueOf(file.replace(".sql", "")); + + if ((version > oldVersion) && (version <= newVersion)) { + executeScript(db, file); + isSuccess = true; + } + } catch (NumberFormatException e) { + Log.i("Sugar", "not a sugar script. ignored." + file); + } + } + } catch (IOException e) { + Log.e("Sugar", e.getMessage()); + } + + return isSuccess; + } + + private void executeScript(SQLiteDatabase db, String file) { + try { + InputStream is = this.context.getAssets().open("sugar_upgrades/" + file); + BufferedReader reader = new BufferedReader(new InputStreamReader(is)); + String line; + while ((line = reader.readLine()) != null) { + Log.i("Sugar script", line); + db.execSQL(line.toString()); + } + } catch (IOException e) { + Log.e("Sugar", e.getMessage()); + } + + Log.i("Sugar", "script executed"); + } + + private void createTable(Class table, SQLiteDatabase sqLiteDatabase) { + Log.i("Sugar", "create table"); + List fields = ReflectionUtil.getTableFields(table); + + String tableName = NamingHelper.toSQLName(table); + + StringBuilder sb = new StringBuilder("CREATE TABLE ").append(tableName).append( + " ( ID INTEGER PRIMARY KEY AUTOINCREMENT "); + + for (Field column : fields) { + String columnName = NamingHelper.toSQLName(column); + String columnType = QueryBuilder.getColumnType(column.getType()); + + if (columnType != null) { + + if (columnName.equalsIgnoreCase("Id")) { + continue; + } + + if (column.isAnnotationPresent(Column.class)) { + Column columnAnnotation = column.getAnnotation(Column.class); + columnName = columnAnnotation.name(); + + sb.append(", ").append(columnName).append(" ").append(columnType); + + if (columnAnnotation.notNull()) { + if (columnType.endsWith(" NULL")) { + sb.delete(sb.length() - 5, sb.length()); + } + sb.append(" NOT NULL"); + } + + if (columnAnnotation.unique()) { + sb.append(" UNIQUE"); + } + + } else { + + sb.append(", ").append(columnName).append(" ").append(columnType); + + if (column.isAnnotationPresent(NotNull.class)) { + if (columnType.endsWith(" NULL")) { + sb.delete(sb.length() - 5, sb.length()); + } + sb.append(" NOT NULL"); + } + + if (column.isAnnotationPresent(Unique.class)) { + sb.append(" UNIQUE"); + } + } + } + } + sb.append(" ) "); + + Log.i("Sugar", "creating table " + tableName); + + if (!"".equals(sb.toString())) { + try { + sqLiteDatabase.execSQL(sb.toString()); + } catch (SQLException e) { + e.printStackTrace(); + } + + } + } + +} diff --git a/library/src/com/orm/StringUtil.java b/library/src/com/orm/StringUtil.java deleted file mode 100644 index 4f837a1b..00000000 --- a/library/src/com/orm/StringUtil.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.orm; - -import com.orm.dsl.Column; - -import java.lang.reflect.Field; - -public class StringUtil { - public static String toSQLNameDefault(String javaNotation) { - if(javaNotation.equalsIgnoreCase("_id")) - return "_id"; - - StringBuilder sb = new StringBuilder(); - char[] buf = javaNotation.toCharArray(); - - for (int i = 0; i < buf.length; i++) { - char prevChar = (i > 0) ? buf[i - 1] : 0; - char c = buf[i]; - char nextChar = (i < buf.length - 1) ? buf[i + 1] : 0; - boolean isFirstChar = (i == 0); - - if (isFirstChar || Character.isLowerCase(c) || Character.isDigit(c)) { - sb.append(Character.toUpperCase(c)); - } else if (Character.isUpperCase(c)) { - if (Character.isLetterOrDigit(prevChar)) { - if (Character.isLowerCase(prevChar)) { - sb.append('_').append(Character.toUpperCase(c)); - } else if (nextChar > 0 && Character.isLowerCase(nextChar)) { - sb.append('_').append(Character.toUpperCase(c)); - } else { - sb.append(c); - } - } - else { - sb.append(c); - } - } - } - - return sb.toString(); - } - - public static String toSQLName(Field field){ - if(field.isAnnotationPresent(Column.class)){ - Column annotation = field.getAnnotation(Column.class); - return annotation.name(); - } - - return toSQLNameDefault(field.getName()); - } -} diff --git a/library/src/com/orm/SugarApp.java b/library/src/com/orm/SugarApp.java index ac7da99d..e2638a0e 100644 --- a/library/src/com/orm/SugarApp.java +++ b/library/src/com/orm/SugarApp.java @@ -2,13 +2,17 @@ public class SugarApp extends android.app.Application{ - private Database database; private static SugarApp sugarContext; + private SugarDb sugarDb; + + public static SugarApp getSugarContext() { + return sugarContext; + } public void onCreate(){ super.onCreate(); SugarApp.sugarContext = this; - this.database = new Database(this); + this.sugarDb = new SugarDb(this); } /* @@ -18,17 +22,13 @@ public void onCreate(){ * Robolectric Android mock. */ public void onTerminate(){ - if (this.database != null) { - this.database.getDB().close(); + if (this.sugarDb != null) { + this.sugarDb.getDB().close(); } super.onTerminate(); } - public static SugarApp getSugarContext(){ - return sugarContext; - } - - protected Database getDatabase() { - return database; + protected SugarDb getSugarDb() { + return sugarDb; } } diff --git a/library/src/com/orm/SugarDb.java b/library/src/com/orm/SugarDb.java index ceab2243..2d4dbfd3 100644 --- a/library/src/com/orm/SugarDb.java +++ b/library/src/com/orm/SugarDb.java @@ -1,296 +1,39 @@ package com.orm; -import static com.orm.SugarConfig.getDatabaseVersion; -import static com.orm.SugarConfig.getDebugEnabled; - -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Modifier; -import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Enumeration; -import java.util.List; - import android.content.Context; -import android.content.pm.PackageManager; import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteException; import android.database.sqlite.SQLiteOpenHelper; -import android.util.Log; +import com.orm.util.SugarConfig; +import com.orm.util.SugarCursorFactory; -import com.orm.dsl.Column; -import com.orm.dsl.NotNull; -import com.orm.dsl.Unique; - -import dalvik.system.DexFile; +import static com.orm.util.SugarConfig.getDatabaseVersion; +import static com.orm.util.SugarConfig.getDebugEnabled; public class SugarDb extends SQLiteOpenHelper { - private Context context; + private final SchemaGenerator schemaGenerator; + private SQLiteDatabase sqLiteDatabase; public SugarDb(Context context) { super(context, SugarConfig.getDatabaseName(context), new SugarCursorFactory(getDebugEnabled(context)), getDatabaseVersion(context)); - this.context = context; - - } - - private > List getDomainClasses(Context context) { - List domainClasses = new ArrayList(); - try { - for (String className : getAllClasses(context)) { - if (className.startsWith(SugarConfig.getDomainPackageName(context))) { - T domainClass = getDomainClass(className, context); - if (domainClass != null) domainClasses.add(domainClass); - } - } - - } catch (IOException e) { - Log.e("Sugar", e.getMessage()); - } catch (PackageManager.NameNotFoundException e) { - Log.e("Sugar", e.getMessage()); - } - - return domainClasses; - } - - @SuppressWarnings("unchecked") - private > T getDomainClass(String className, Context context) { - Class discoveredClass = null; - try { - discoveredClass = Class.forName(className, true, context.getClass().getClassLoader()); - } catch (ClassNotFoundException e) { - Log.e("Sugar", e.getMessage()); - } - - if ((discoveredClass == null) || - (!SugarRecord.class.isAssignableFrom(discoveredClass)) || - SugarRecord.class.equals(discoveredClass) || - Modifier.isAbstract(discoveredClass.getModifiers())) { - return null; - } else { - try { - Log.i("Sugar", "domain class : " + discoveredClass.getSimpleName()); - return (T) discoveredClass.getDeclaredConstructor().newInstance(); - - } catch (InstantiationException e) { - Log.e("Sugar", e.getMessage()); - } catch (IllegalAccessException e) { - Log.e("Sugar", e.getMessage()); - } catch (NoSuchMethodException e) { - Log.e("Sugar", e.getMessage()); - } catch (InvocationTargetException e) { - Log.e("Sugar", e.getMessage()); - } - } - - return null; - - } - - private List getAllClasses(Context context) throws PackageManager.NameNotFoundException, IOException { - String path = getSourcePath(context); - List classNames = new ArrayList(); - try { - DexFile dexfile = new DexFile(path); - Enumeration dexEntries = dexfile.entries(); - while (dexEntries.hasMoreElements()) { - classNames.add(dexEntries.nextElement()); - } - } catch (NullPointerException e) { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - Enumeration urls = classLoader.getResources(""); - List fileNames = new ArrayList(); - while (urls.hasMoreElements()) { - String classDirectoryName = urls.nextElement().getFile(); - if (classDirectoryName.contains("bin") || classDirectoryName.contains("classes")) { - File classDirectory = new File(classDirectoryName); - for (File filePath : classDirectory.listFiles()) { - populateFiles(filePath, fileNames, ""); - } - classNames.addAll(fileNames); - } - } - } - return classNames; - } - - private void populateFiles(File path, List fileNames, String parent) { - if (path.isDirectory()) { - for (File newPath : path.listFiles()) { - if ("".equals(parent)) { - populateFiles(newPath, fileNames, path.getName()); - } else { - populateFiles(newPath, fileNames, parent + "." + path.getName()); - } - } - } else { - String pathName = path.getName(); - String classSuffix = ".class"; - pathName = pathName.endsWith(classSuffix) ? - pathName.substring(0, pathName.length() - classSuffix.length()) : pathName; - if ("".equals(parent)) { - fileNames.add(pathName); - } else { - fileNames.add(parent + "." + pathName); - } - } - } - - private String getSourcePath(Context context) throws PackageManager.NameNotFoundException { - return context.getPackageManager().getApplicationInfo(context.getPackageName(), 0).sourceDir; + schemaGenerator = new SchemaGenerator(context); } @Override public void onCreate(SQLiteDatabase sqLiteDatabase) { - Log.i("Sugar", "on create"); - createDatabase(sqLiteDatabase); - } - - private > void createDatabase(SQLiteDatabase sqLiteDatabase) { - List domainClasses = getDomainClasses(context); - for (T domain : domainClasses) { - createTable(domain, sqLiteDatabase); - } - } - - private > void createTable(T table, SQLiteDatabase sqLiteDatabase) { - Log.i("Sugar", "create table"); - List fields = table.getTableFields(); - StringBuilder sb = new StringBuilder("CREATE TABLE ").append(table.getSqlName()).append( - " ( ID INTEGER PRIMARY KEY AUTOINCREMENT "); - - for (Field column : fields) { - String columnName = StringUtil.toSQLName(column); - String columnType = QueryBuilder.getColumnType(column.getType()); - - if (columnType != null) { - - if (columnName.equalsIgnoreCase("Id")) { - continue; - } - - if(column.isAnnotationPresent(Column.class)){ - Column columnAnnotation = column.getAnnotation(Column.class); - columnName = columnAnnotation.name(); - - sb.append(", ").append(columnName).append(" ").append(columnType); - - if (columnAnnotation.notNull()) { - if (columnType.endsWith(" NULL")) { - sb.delete(sb.length() - 5, sb.length()); - } - sb.append(" NOT NULL"); - } - - if (columnAnnotation.unique()) { - sb.append(" UNIQUE"); - } - - }else { - - sb.append(", ").append(columnName).append(" ").append(columnType); - - if (column.isAnnotationPresent(NotNull.class)) { - if (columnType.endsWith(" NULL")) { - sb.delete(sb.length() - 5, sb.length()); - } - sb.append(" NOT NULL"); - } - - if (column.isAnnotationPresent(Unique.class)) { - sb.append(" UNIQUE"); - } - } - } - } - sb.append(" ) "); - - Log.i("Sugar", "creating table " + table.getSqlName()); - - if (!"".equals(sb.toString())) - sqLiteDatabase.execSQL(sb.toString()); + schemaGenerator.createDatabase(sqLiteDatabase); } @Override public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) { - Log.i("Sugar", "upgrading sugar"); - // check if some tables are to be created - doUpgrade(sqLiteDatabase); - - if (!executeSugarUpgrade(sqLiteDatabase, oldVersion, newVersion)) { - deleteTables(sqLiteDatabase); - onCreate(sqLiteDatabase); - } - } - - /** - * Create the tables that do not exist. - */ - private > void doUpgrade(SQLiteDatabase sqLiteDatabase) { - List domainClasses = getDomainClasses(context); - for (T domain : domainClasses) { - try {// we try to do a select, if fails then (?) there isn't the table - sqLiteDatabase.query(domain.tableName, null, null, null, null, null, null); - } catch (SQLiteException e) { - Log.i("Sugar", String.format("creating table on update (error was '%s')", e.getMessage())); - createTable(domain, sqLiteDatabase); - } - } - } - - private > void deleteTables(SQLiteDatabase sqLiteDatabase) { - List tables = getDomainClasses(this.context); - for (T table : tables) { - sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + table.getSqlName()); - } + schemaGenerator.doUpgrade(sqLiteDatabase, oldVersion, newVersion); } - private boolean executeSugarUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - - boolean isSuccess = false; - try { - List files = Arrays.asList(this.context.getAssets().list("sugar_upgrades")); - Collections.sort(files, new NumberComparator()); - - for (String file : files){ - Log.i("Sugar", "filename : " + file); - try { - int version = Integer.valueOf(file.replace(".sql", "")); - - if ((version > oldVersion) && (version <= newVersion)) { - executeScript(db, file); - isSuccess = true; - } - } catch (NumberFormatException e) { - Log.i("Sugar", "not a sugar script. ignored." + file); - } - } - } catch (IOException e) { - Log.e("Sugar", e.getMessage()); + public synchronized SQLiteDatabase getDB() { + if (this.sqLiteDatabase == null) { + this.sqLiteDatabase = getWritableDatabase(); } - return isSuccess; + return this.sqLiteDatabase; } - private void executeScript(SQLiteDatabase db, String file) { - try { - InputStream is = this.context.getAssets().open("sugar_upgrades/" + file); - BufferedReader reader = new BufferedReader(new InputStreamReader(is)); - String line; - while ((line = reader.readLine()) != null) { - Log.i("Sugar script", line); - db.execSQL(line.toString()); - } - } catch (IOException e) { - Log.e("Sugar", e.getMessage()); - } - - Log.i("Sugar", "script executed"); - } } diff --git a/library/src/com/orm/SugarRecord.java b/library/src/com/orm/SugarRecord.java index 30eba6ee..07a64f5a 100644 --- a/library/src/com/orm/SugarRecord.java +++ b/library/src/com/orm/SugarRecord.java @@ -3,62 +3,48 @@ import android.content.ContentValues; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteException; import android.database.sqlite.SQLiteStatement; import android.text.TextUtils; import android.util.Log; -import com.orm.dsl.Ignore; +import com.orm.dsl.Table; +import com.orm.util.NamingHelper; +import com.orm.util.ReflectionUtil; import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.sql.Timestamp; import java.util.*; import static com.orm.SugarApp.getSugarContext; -public class SugarRecord{ - - @Ignore - String tableName = getSqlName(); +public class SugarRecord { protected Long id = null; - public void delete() { - SQLiteDatabase db = getSugarContext().getDatabase().getDB(); - db.delete(this.tableName, "Id=?", new String[]{getId().toString()}); - } - - public static > void deleteAll(Class type) { - Database db = getSugarContext().getDatabase(); + public static void deleteAll(Class type) { + SugarDb db = getSugarContext().getSugarDb(); SQLiteDatabase sqLiteDatabase = db.getDB(); - sqLiteDatabase.delete(getTableName(type), null, null); + sqLiteDatabase.delete(NamingHelper.toSQLName(type), null, null); } - public static > void deleteAll(Class type, String whereClause, String... whereArgs ) { - Database db = getSugarContext().getDatabase(); + public static void deleteAll(Class type, String whereClause, String... whereArgs) { + SugarDb db = getSugarContext().getSugarDb(); SQLiteDatabase sqLiteDatabase = db.getDB(); - sqLiteDatabase.delete(getTableName(type), whereClause, whereArgs); - } - - public long save() { - return save(getSugarContext().getDatabase().getDB()); + sqLiteDatabase.delete(NamingHelper.toSQLName(type), whereClause, whereArgs); } @SuppressWarnings("deprecation") - public static > void saveInTx(T... objects ) { + public static void saveInTx(T... objects) { saveInTx(Arrays.asList(objects)); } @SuppressWarnings("deprecation") - public static > void saveInTx(Collection objects ) { - SQLiteDatabase sqLiteDatabase = getSugarContext().getDatabase().getDB(); + public static void saveInTx(Collection objects) { + SQLiteDatabase sqLiteDatabase = getSugarContext().getSugarDb().getDB(); try{ sqLiteDatabase.beginTransaction(); sqLiteDatabase.setLockingEnabled(false); for(T object: objects){ - object.save(sqLiteDatabase); + SugarRecord.save(object); } sqLiteDatabase.setTransactionSuccessful(); }catch (Exception e){ @@ -70,115 +56,55 @@ public static > void saveInTx(Collection objects ) { } - long save(SQLiteDatabase db) { - - List columns = getTableFields(); - ContentValues values = new ContentValues(columns.size()); - for (Field column : columns) { - column.setAccessible(true); - Class columnType = column.getType(); - try { - String columnName = StringUtil.toSQLName(column); - Object columnValue = column.get(this); - if (SugarRecord.class.isAssignableFrom(columnType)) { - values.put(columnName, - (columnValue != null) - ? String.valueOf(((SugarRecord) columnValue).id) - : "0"); - } else { - if (columnType.equals(Short.class) || columnType.equals(short.class)) { - values.put(columnName, (Short) columnValue); - } else if (columnType.equals(Integer.class) || columnType.equals(int.class)) { - values.put(columnName, (Integer) columnValue); - } else if (columnType.equals(Long.class) || columnType.equals(long.class)) { - values.put(columnName, (Long) columnValue); - } else if (columnType.equals(Float.class) || columnType.equals(float.class)) { - values.put(columnName, (Float) columnValue); - } else if (columnType.equals(Double.class) || columnType.equals(double.class)) { - values.put(columnName, (Double) columnValue); - } else if (columnType.equals(Boolean.class) || columnType.equals(boolean.class)) { - values.put(columnName, (Boolean) columnValue); - } else if (Date.class.equals(columnType)) { - try { - values.put(columnName, ((Date) column.get(this)).getTime()); - } catch (NullPointerException e) { - values.put(columnName, (Long) null); - } - } else if (Calendar.class.equals(columnType)) { - try { - values.put(columnName, ((Calendar) column.get(this)).getTimeInMillis()); - } catch (NullPointerException e) { - values.put(columnName, (Long) null); - } - } else { - if (columnValue == null) { - values.putNull(columnName); - } else { - values.put(columnName, String.valueOf(columnValue)); - } - } - } - - } catch (IllegalAccessException e) { - Log.e("Sugar", e.getMessage()); - } - } - - id = db.insertWithOnConflict(getSqlName(), null, values, SQLiteDatabase.CONFLICT_REPLACE); - - Log.i("Sugar", getClass().getSimpleName() + " saved : " + id); - return id; - } - - public static > List listAll(Class type) { + public static List listAll(Class type) { return find(type, null, null, null, null, null); } - public static > T findById(Class type, Long id) { - List list = find( type, "id=?", new String[]{String.valueOf(id)}, null, null, "1"); + public static T findById(Class type, Long id) { + List list = find(type, "id=?", new String[]{String.valueOf(id)}, null, null, "1"); if (list.isEmpty()) return null; return list.get(0); } - public static > T findById(Class type, Integer id) { + public static T findById(Class type, Integer id) { return findById(type, Long.valueOf(id)); } - public static > Iterator findAll(Class type) { + public static Iterator findAll(Class type) { return findAsIterator(type, null, null, null, null, null); } - public static > Iterator findAsIterator(Class type, + public static Iterator findAsIterator(Class type, String whereClause, String... whereArgs) { return findAsIterator(type, whereClause, whereArgs, null, null, null); } - public static > Iterator findWithQueryAsIterator(Class type, String query, String... arguments) { - Database db = getSugarContext().getDatabase(); + public static Iterator findWithQueryAsIterator(Class type, String query, String... arguments) { + SugarDb db = getSugarContext().getSugarDb(); SQLiteDatabase sqLiteDatabase = db.getDB(); Cursor c = sqLiteDatabase.rawQuery(query, arguments); return new CursorIterator(type, c); } - public static > Iterator findAsIterator(Class type, + public static Iterator findAsIterator(Class type, String whereClause, String[] whereArgs, String groupBy, String orderBy, String limit) { - Database db = getSugarContext().getDatabase(); + SugarDb db = getSugarContext().getSugarDb(); SQLiteDatabase sqLiteDatabase = db.getDB(); - Cursor c = sqLiteDatabase.query(getTableName(type), null, + Cursor c = sqLiteDatabase.query(NamingHelper.toSQLName(type), null, whereClause, whereArgs, groupBy, null, orderBy, limit); return new CursorIterator(type, c); } - public static > List find(Class type, + public static List find(Class type, String whereClause, String... whereArgs) { return find(type, whereClause, whereArgs, null, null, null); } - public static > List findWithQuery(Class type, String query, String... arguments){ + public static List findWithQuery(Class type, String query, String... arguments) { - Database db = getSugarContext().getDatabase(); + SugarDb db = getSugarContext().getSugarDb(); SQLiteDatabase sqLiteDatabase = db.getDB(); T entity; List toRet = new ArrayList(); @@ -187,7 +113,7 @@ public static > List findWithQuery(Class type, St try { while (c.moveToNext()) { entity = type.getDeclaredConstructor().newInstance(); - entity.inflate(c); + SugarRecord.inflate(c, entity); toRet.add(entity); } } catch (Exception e) { @@ -199,22 +125,22 @@ public static > List findWithQuery(Class type, St } public static void executeQuery(String query, String... arguments){ - getSugarContext().getDatabase().getDB().execSQL(query, arguments); + getSugarContext().getSugarDb().getDB().execSQL(query, arguments); } - public static > List find(Class type, + public static List find(Class type, String whereClause, String[] whereArgs, String groupBy, String orderBy, String limit) { - Database db = getSugarContext().getDatabase(); + SugarDb db = getSugarContext().getSugarDb(); SQLiteDatabase sqLiteDatabase = db.getDB(); T entity; List toRet = new ArrayList(); - Cursor c = sqLiteDatabase.query(getTableName(type), null, + Cursor c = sqLiteDatabase.query(NamingHelper.toSQLName(type), null, whereClause, whereArgs, groupBy, null, orderBy, limit); try { while (c.moveToNext()) { entity = type.getDeclaredConstructor().newInstance(); - entity.inflate(c); + SugarRecord.inflate(c, entity); toRet.add(entity); } } catch (Exception e) { @@ -225,25 +151,25 @@ public static > List find(Class type, return toRet; } - public static > long count(Class type) { + public static long count(Class type) { return count(type, null, null, null, null, null); } - - public static > long count(Class type, + + public static long count(Class type, String whereClause, String[] whereArgs) { return count(type, whereClause, whereArgs, null, null, null); } - - public static > long count(Class type, + + public static long count(Class type, String whereClause, String[] whereArgs, String groupBy, String orderBy, String limit) { - - Database db = getSugarContext().getDatabase(); + + SugarDb db = getSugarContext().getSugarDb(); SQLiteDatabase sqLiteDatabase = db.getDB(); long toRet = -1; String filter = (!TextUtils.isEmpty(whereClause)) ? " where " + whereClause : ""; - SQLiteStatement sqLiteStatament = sqLiteDatabase.compileStatement("SELECT count(*) FROM " + getTableName(type) + filter); + SQLiteStatement sqLiteStatament = sqLiteDatabase.compileStatement("SELECT count(*) FROM " + NamingHelper.toSQLName(type) + filter); if (whereArgs != null) { for (int i = whereArgs.length; i != 0; i--) { @@ -258,137 +184,62 @@ public static > long count(Class type, } finally { sqLiteStatament.close(); } - - return toRet; + + return toRet; } - @SuppressWarnings("unchecked") - void inflate(Cursor cursor) { - Map entities = new HashMap(); - List columns = getTableFields(); - for (Field field : columns) { - field.setAccessible(true); - try { - Class fieldType = field.getType(); - String colName = StringUtil.toSQLName(field); + public static long save(Object object) { + return save(getSugarContext().getSugarDb().getDB(), object); + } - int columnIndex = cursor.getColumnIndex(colName); + static long save(SQLiteDatabase db, Object object) { - if (cursor.isNull(columnIndex)) { - continue; - } + List columns = ReflectionUtil.getTableFields(object.getClass()); + ContentValues values = new ContentValues(columns.size()); + for (Field column : columns) { + ReflectionUtil.addFieldValueToColumn(values, column, object); + } - if(colName.equalsIgnoreCase("id")){ - long cid = cursor.getLong(columnIndex); - field.set(this, Long.valueOf(cid)); - }else if (fieldType.equals(long.class) || fieldType.equals(Long.class)) { - field.set(this, - cursor.getLong(columnIndex)); - } else if (fieldType.equals(String.class)) { - String val = cursor.getString(columnIndex); - field.set(this, val != null && val.equals("null") ? null : val); - } else if (fieldType.equals(double.class) || fieldType.equals(Double.class)) { - field.set(this, - cursor.getDouble(columnIndex)); - } else if (fieldType.equals(boolean.class) || fieldType.equals(Boolean.class)) { - field.set(this, - cursor.getString(columnIndex).equals("1")); - } else if (field.getType().getName().equals("[B")) { - field.set(this, - cursor.getBlob(columnIndex)); - } else if (fieldType.equals(int.class) || fieldType.equals(Integer.class)) { - field.set(this, - cursor.getInt(columnIndex)); - } else if (fieldType.equals(float.class) || fieldType.equals(Float.class)) { - field.set(this, - cursor.getFloat(columnIndex)); - } else if (fieldType.equals(short.class) || fieldType.equals(Short.class)) { - field.set(this, - cursor.getShort(columnIndex)); - } else if (fieldType.equals(Timestamp.class)) { - long l = cursor.getLong(columnIndex); - field.set(this, new Timestamp(l)); - } else if (fieldType.equals(Date.class)) { - long l = cursor.getLong(columnIndex); - field.set(this, new Date(l)); - } else if (fieldType.equals(Calendar.class)) { - long l = cursor.getLong(columnIndex); - Calendar c = Calendar.getInstance(); - c.setTimeInMillis(l); - field.set(this, c); - } else if (Enum.class.isAssignableFrom(fieldType)) { - try { - Method valueOf = field.getType().getMethod("valueOf", String.class); - String strVal = cursor.getString(columnIndex); - Object enumVal = valueOf.invoke(field.getType(), strVal); - field.set(this, enumVal); - } catch (Exception e) { - Log.e("Sugar", "Enum cannot be read from Sqlite3 database. Please check the type of field " + field.getName()); - } - } else if (SugarRecord.class.isAssignableFrom(fieldType)) { - long id = cursor.getLong(columnIndex); - if (id > 0) - entities.put(field, id); - else - field.set(this, null); - } else - Log.e("Sugar", "Class cannot be read from Sqlite3 database. Please check the type of field " + field.getName() + "(" + field.getType().getName() + ")"); - } catch (IllegalArgumentException e) { - Log.e("field set error", e.getMessage()); - } catch (IllegalAccessException e) { - Log.e("field set error", e.getMessage()); - } + long id = db.insertWithOnConflict(NamingHelper.toSQLName(object.getClass()), null, values, SQLiteDatabase.CONFLICT_REPLACE); + if (SugarRecord.class.isAssignableFrom(object.getClass())) { + ReflectionUtil.setFieldValueForId(object, id); } - for (Field f : entities.keySet()) { - try { - f.set(this, findById((Class>) f.getType(), - entities.get(f))); - } catch (SQLiteException e) { - } catch (IllegalArgumentException e) { - } catch (IllegalAccessException e) { - } - } + Log.i("Sugar", object.getClass().getSimpleName() + " saved : " + id); + return id; } - public List getTableFields() { - List fieldList = SugarConfig.getFields(getClass()); - if(fieldList != null) return fieldList; + private static void inflate(Cursor cursor, Object object) { - Log.d("Sugar", "Fetching properties"); - List typeFields = new ArrayList(); + List columns = ReflectionUtil.getTableFields(object.getClass()); - getAllFields(typeFields, getClass()); - - List toStore = new ArrayList(); - for (Field field : typeFields) { - if (!field.isAnnotationPresent(Ignore.class) && !Modifier.isStatic(field.getModifiers())&& !Modifier.isTransient(field.getModifiers())) { - toStore.add(field); + for (Field field : columns) { + if (field.getClass().isAnnotationPresent(Table.class)) { + try { + long id = cursor.getLong(cursor.getColumnIndex(NamingHelper.toSQLName(field))); + field.set(object, (id > 0) ? findById(field.getType(), id) : null); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } else { + ReflectionUtil.setFieldValueFromCursor(cursor, field, object); } } - - SugarConfig.setFields(getClass(), toStore); - return toStore; } - private static List getAllFields(List fields, Class type) { - Collections.addAll(fields, type.getDeclaredFields()); - - if (type.getSuperclass() != null) { - fields = getAllFields(fields, type.getSuperclass()); - } - - return fields; + public void delete() { + SQLiteDatabase db = getSugarContext().getSugarDb().getDB(); + db.delete(NamingHelper.toSQLName(getClass()), "Id=?", new String[]{getId().toString()}); } - public String getSqlName() { - return getTableName(getClass()); + public long save() { + return save(getSugarContext().getSugarDb().getDB(), this); } - - public static String getTableName(Class type) { - return StringUtil.toSQLNameDefault(type.getSimpleName()); + @SuppressWarnings("unchecked") + void inflate(Cursor cursor) { + inflate(cursor, this); } public Long getId() { @@ -399,7 +250,7 @@ public void setId(Long id) { this.id = id; } - static class CursorIterator> implements Iterator { + static class CursorIterator implements Iterator { Class type; Cursor cursor; @@ -426,7 +277,7 @@ public E next() { try { entity = type.getDeclaredConstructor().newInstance(); - entity.inflate(cursor); + SugarRecord.inflate(cursor, entity); } catch (Exception e) { e.printStackTrace(); } finally { diff --git a/library/src/com/orm/SugarTransactionHelper.java b/library/src/com/orm/SugarTransactionHelper.java index 505547df..ef3bf5fe 100644 --- a/library/src/com/orm/SugarTransactionHelper.java +++ b/library/src/com/orm/SugarTransactionHelper.java @@ -7,7 +7,7 @@ public class SugarTransactionHelper { public static void doInTansaction(SugarTransactionHelper.Callback callback) { - SQLiteDatabase database = SugarApp.getSugarContext().getDatabase().getDB(); + SQLiteDatabase database = SugarApp.getSugarContext().getSugarDb().getDB(); database.beginTransaction(); diff --git a/library/src/com/orm/dsl/Table.java b/library/src/com/orm/dsl/Table.java new file mode 100644 index 00000000..0dfaa18b --- /dev/null +++ b/library/src/com/orm/dsl/Table.java @@ -0,0 +1,9 @@ +package com.orm.dsl; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface Table { + String name() default ""; +} diff --git a/library/src/com/orm/query/Select.java b/library/src/com/orm/query/Select.java index 95688297..0d148d46 100644 --- a/library/src/com/orm/query/Select.java +++ b/library/src/com/orm/query/Select.java @@ -1,12 +1,13 @@ package com.orm.query; import com.orm.SugarRecord; +import com.orm.util.NamingHelper; import java.util.ArrayList; import java.util.Iterator; import java.util.List; -public class Select> implements Iterable { +public class Select implements Iterable { private Class record; private String[] arguments; @@ -22,7 +23,7 @@ public Select(Class record) { this.record = record; } - public static > Select from(Class record) { + public static Select from(Class record) { return new Select(record); } @@ -106,7 +107,7 @@ public List list() { if(arguments == null) arguments = convertArgs(args); - return T.find(record, whereClause, arguments, groupBy, orderBy, limit); + return SugarRecord.find(record, whereClause, arguments, groupBy, orderBy, limit); } @@ -121,7 +122,7 @@ public T first() { if(arguments == null) arguments = convertArgs(args); - List list = T.find(record, whereClause, arguments, groupBy, orderBy, "1"); + List list = SugarRecord.find(record, whereClause, arguments, groupBy, orderBy, "1"); return list.size() > 0 ? list.get(0) : null; } @@ -130,7 +131,7 @@ String toSql() { sql.append("SELECT * FROM "); - sql.append(SugarRecord.getTableName(this.record) + " "); + sql.append(NamingHelper.toSQLName(this.record) + " "); if (whereClause != null) { sql.append("WHERE " + whereClause + " "); @@ -173,6 +174,6 @@ private String[] convertArgs(List argsList) { public Iterator iterator() { if(arguments == null) arguments = convertArgs(args); - return T.findAsIterator(record, whereClause, arguments, groupBy, orderBy, limit); + return SugarRecord.findAsIterator(record, whereClause, arguments, groupBy, orderBy, limit); } } diff --git a/library/src/com/orm/dsl/Collection.java b/library/src/com/orm/util/Collection.java similarity index 97% rename from library/src/com/orm/dsl/Collection.java rename to library/src/com/orm/util/Collection.java index 6f1b5075..596a3e22 100644 --- a/library/src/com/orm/dsl/Collection.java +++ b/library/src/com/orm/util/Collection.java @@ -1,4 +1,4 @@ -package com.orm.dsl; +package com.orm.util; import java.util.*; public class Collection { diff --git a/library/src/com/orm/util/NamingHelper.java b/library/src/com/orm/util/NamingHelper.java new file mode 100644 index 00000000..116ab25d --- /dev/null +++ b/library/src/com/orm/util/NamingHelper.java @@ -0,0 +1,62 @@ +package com.orm.util; + +import com.orm.dsl.Column; +import com.orm.dsl.Table; + +import java.lang.reflect.Field; + +public class NamingHelper { + public static String toSQLNameDefault(String javaNotation) { + if (javaNotation.equalsIgnoreCase("_id")) + return "_id"; + + StringBuilder sb = new StringBuilder(); + char[] buf = javaNotation.toCharArray(); + + for (int i = 0; i < buf.length; i++) { + char prevChar = (i > 0) ? buf[i - 1] : 0; + char c = buf[i]; + char nextChar = (i < buf.length - 1) ? buf[i + 1] : 0; + boolean isFirstChar = (i == 0); + + if (isFirstChar || Character.isLowerCase(c) || Character.isDigit(c)) { + sb.append(Character.toUpperCase(c)); + } else if (Character.isUpperCase(c)) { + if (Character.isLetterOrDigit(prevChar)) { + if (Character.isLowerCase(prevChar)) { + sb.append('_').append(Character.toUpperCase(c)); + } else if (nextChar > 0 && Character.isLowerCase(nextChar)) { + sb.append('_').append(Character.toUpperCase(c)); + } else { + sb.append(c); + } + } else { + sb.append(c); + } + } + } + + return sb.toString(); + } + + public static String toSQLName(Field field) { + if (field.isAnnotationPresent(Column.class)) { + Column annotation = field.getAnnotation(Column.class); + return annotation.name(); + } + + return toSQLNameDefault(field.getName()); + } + + public static String toSQLName(Class table) { + + if (table.isAnnotationPresent(Table.class)) { + Table annotation = table.getAnnotation(Table.class); + if ("".equals(annotation.name())) { + return NamingHelper.toSQLNameDefault(table.getSimpleName()); + } + return annotation.name(); + } + return NamingHelper.toSQLNameDefault(table.getSimpleName()); + } +} diff --git a/library/src/com/orm/NumberComparator.java b/library/src/com/orm/util/NumberComparator.java similarity index 99% rename from library/src/com/orm/NumberComparator.java rename to library/src/com/orm/util/NumberComparator.java index 244d3281..c4284721 100644 --- a/library/src/com/orm/NumberComparator.java +++ b/library/src/com/orm/util/NumberComparator.java @@ -1,9 +1,17 @@ -package com.orm; +package com.orm.util; import java.util.Comparator; public class NumberComparator implements Comparator { + static char charAt(String s, int i) { + if (i >= s.length()) { + return '\000'; + } + + return s.charAt(i); + } + int compareRight(String a, String b) { int bias = 0; int ia = 0; @@ -89,12 +97,4 @@ public int compare(Object o1, Object o2) { ib++; } } - - static char charAt(String s, int i) { - if (i >= s.length()) { - return '\000'; - } - - return s.charAt(i); - } } diff --git a/library/src/com/orm/QueryBuilder.java b/library/src/com/orm/util/QueryBuilder.java similarity index 95% rename from library/src/com/orm/QueryBuilder.java rename to library/src/com/orm/util/QueryBuilder.java index 6ca26fc9..77d6247e 100644 --- a/library/src/com/orm/QueryBuilder.java +++ b/library/src/com/orm/util/QueryBuilder.java @@ -1,4 +1,6 @@ -package com.orm; +package com.orm.util; + +import com.orm.SugarRecord; public class QueryBuilder { diff --git a/library/src/com/orm/util/ReflectionUtil.java b/library/src/com/orm/util/ReflectionUtil.java new file mode 100644 index 00000000..7a213cae --- /dev/null +++ b/library/src/com/orm/util/ReflectionUtil.java @@ -0,0 +1,281 @@ +package com.orm.util; + +import android.content.ContentValues; +import android.content.Context; +import android.content.pm.PackageManager; +import android.database.Cursor; +import android.util.Log; +import com.orm.SugarRecord; +import com.orm.dsl.Ignore; +import com.orm.dsl.Table; +import dalvik.system.DexFile; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.net.URL; +import java.sql.Timestamp; +import java.util.*; + +public class ReflectionUtil { + + public static List getTableFields(Class table) { + List fieldList = SugarConfig.getFields(table); + if (fieldList != null) return fieldList; + + Log.d("Sugar", "Fetching properties"); + List typeFields = new ArrayList(); + + getAllFields(typeFields, table); + + List toStore = new ArrayList(); + for (Field field : typeFields) { + if (!field.isAnnotationPresent(Ignore.class) && !Modifier.isStatic(field.getModifiers()) && !Modifier.isTransient(field.getModifiers())) { + toStore.add(field); + } + } + + SugarConfig.setFields(table, toStore); + return toStore; + } + + private static List getAllFields(List fields, Class type) { + Collections.addAll(fields, type.getDeclaredFields()); + + if (type.getSuperclass() != null) { + fields = getAllFields(fields, type.getSuperclass()); + } + + return fields; + } + + public static void addFieldValueToColumn(ContentValues values, Field column, Object object) { + column.setAccessible(true); + Class columnType = column.getType(); + try { + String columnName = NamingHelper.toSQLName(column); + Object columnValue = column.get(object); + + if (SugarRecord.class.isAssignableFrom(columnType)) { + values.put(columnName, + (columnValue != null) + ? String.valueOf(((SugarRecord) columnValue).getId()) + : "0"); + } else { + if (columnType.equals(Short.class) || columnType.equals(short.class)) { + values.put(columnName, (Short) columnValue); + } else if (columnType.equals(Integer.class) || columnType.equals(int.class)) { + values.put(columnName, (Integer) columnValue); + } else if (columnType.equals(Long.class) || columnType.equals(long.class)) { + values.put(columnName, (Long) columnValue); + } else if (columnType.equals(Float.class) || columnType.equals(float.class)) { + values.put(columnName, (Float) columnValue); + } else if (columnType.equals(Double.class) || columnType.equals(double.class)) { + values.put(columnName, (Double) columnValue); + } else if (columnType.equals(Boolean.class) || columnType.equals(boolean.class)) { + values.put(columnName, (Boolean) columnValue); + } else if (Date.class.equals(columnType)) { + try { + values.put(columnName, ((Date) column.get(object)).getTime()); + } catch (NullPointerException e) { + values.put(columnName, (Long) null); + } + } else if (Calendar.class.equals(columnType)) { + try { + values.put(columnName, ((Calendar) column.get(object)).getTimeInMillis()); + } catch (NullPointerException e) { + values.put(columnName, (Long) null); + } + } else { + if (columnValue == null) { + values.putNull(columnName); + } else { + values.put(columnName, String.valueOf(columnValue)); + } + } + } + + } catch (IllegalAccessException e) { + Log.e("Sugar", e.getMessage()); + } + } + + public static void setFieldValueFromCursor(Cursor cursor, Field field, Object object) { + field.setAccessible(true); + try { + Class fieldType = field.getType(); + String colName = NamingHelper.toSQLName(field); + + int columnIndex = cursor.getColumnIndex(colName); + + if (cursor.isNull(columnIndex)) { + return; + } + + if (colName.equalsIgnoreCase("id")) { + long cid = cursor.getLong(columnIndex); + field.set(object, Long.valueOf(cid)); + } else if (fieldType.equals(long.class) || fieldType.equals(Long.class)) { + field.set(object, + cursor.getLong(columnIndex)); + } else if (fieldType.equals(String.class)) { + String val = cursor.getString(columnIndex); + field.set(object, val != null && val.equals("null") ? null : val); + } else if (fieldType.equals(double.class) || fieldType.equals(Double.class)) { + field.set(object, + cursor.getDouble(columnIndex)); + } else if (fieldType.equals(boolean.class) || fieldType.equals(Boolean.class)) { + field.set(object, + cursor.getString(columnIndex).equals("1")); + } else if (field.getType().getName().equals("[B")) { + field.set(object, + cursor.getBlob(columnIndex)); + } else if (fieldType.equals(int.class) || fieldType.equals(Integer.class)) { + field.set(object, + cursor.getInt(columnIndex)); + } else if (fieldType.equals(float.class) || fieldType.equals(Float.class)) { + field.set(object, + cursor.getFloat(columnIndex)); + } else if (fieldType.equals(short.class) || fieldType.equals(Short.class)) { + field.set(object, + cursor.getShort(columnIndex)); + } else if (fieldType.equals(Timestamp.class)) { + long l = cursor.getLong(columnIndex); + field.set(object, new Timestamp(l)); + } else if (fieldType.equals(Date.class)) { + long l = cursor.getLong(columnIndex); + field.set(object, new Date(l)); + } else if (fieldType.equals(Calendar.class)) { + long l = cursor.getLong(columnIndex); + Calendar c = Calendar.getInstance(); + c.setTimeInMillis(l); + field.set(object, c); + } else if (Enum.class.isAssignableFrom(fieldType)) { + try { + Method valueOf = field.getType().getMethod("valueOf", String.class); + String strVal = cursor.getString(columnIndex); + Object enumVal = valueOf.invoke(field.getType(), strVal); + field.set(object, enumVal); + } catch (Exception e) { + Log.e("Sugar", "Enum cannot be read from Sqlite3 database. Please check the type of field " + field.getName()); + } + } else + Log.e("Sugar", "Class cannot be read from Sqlite3 database. Please check the type of field " + field.getName() + "(" + field.getType().getName() + ")"); + } catch (IllegalArgumentException e) { + Log.e("field set error", e.getMessage()); + } catch (IllegalAccessException e) { + Log.e("field set error", e.getMessage()); + } + } + + public static void setFieldValueForId(Object object, Long value) { + + try { + Field field = object.getClass().getField("id"); + + field.setAccessible(true); + field.set(object, value); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (NoSuchFieldException e) { + e.printStackTrace(); + } + } + + public static List getDomainClasses(Context context) { + List domainClasses = new ArrayList(); + try { + for (String className : getAllClasses(context)) { + if (className.startsWith(SugarConfig.getDomainPackageName(context))) { + Class domainClass = getDomainClass(className, context); + if (domainClass != null) domainClasses.add(domainClass); + } + } + } catch (IOException e) { + Log.e("Sugar", e.getMessage()); + } catch (PackageManager.NameNotFoundException e) { + Log.e("Sugar", e.getMessage()); + } + + return domainClasses; + } + + + private static Class getDomainClass(String className, Context context) { + Class discoveredClass = null; + try { + discoveredClass = Class.forName(className, true, context.getClass().getClassLoader()); + } catch (ClassNotFoundException e) { + Log.e("Sugar", e.getMessage()); + } + + if ((discoveredClass != null) && + ((SugarRecord.class.isAssignableFrom(discoveredClass) && + !SugarRecord.class.equals(discoveredClass)) || + discoveredClass.isAnnotationPresent(Table.class)) && + !Modifier.isAbstract(discoveredClass.getModifiers())) { + + Log.i("Sugar", "domain class : " + discoveredClass.getSimpleName()); + return discoveredClass; + + } else { + return null; + } + } + + + private static List getAllClasses(Context context) throws PackageManager.NameNotFoundException, IOException { + String path = getSourcePath(context); + List classNames = new ArrayList(); + try { + DexFile dexfile = new DexFile(path); + Enumeration dexEntries = dexfile.entries(); + while (dexEntries.hasMoreElements()) { + classNames.add(dexEntries.nextElement()); + } + } catch (NullPointerException e) { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + Enumeration urls = classLoader.getResources(""); + List fileNames = new ArrayList(); + while (urls.hasMoreElements()) { + String classDirectoryName = urls.nextElement().getFile(); + if (classDirectoryName.contains("bin") || classDirectoryName.contains("classes")) { + File classDirectory = new File(classDirectoryName); + for (File filePath : classDirectory.listFiles()) { + populateFiles(filePath, fileNames, ""); + } + classNames.addAll(fileNames); + } + } + } + return classNames; + } + + private static void populateFiles(File path, List fileNames, String parent) { + if (path.isDirectory()) { + for (File newPath : path.listFiles()) { + if ("".equals(parent)) { + populateFiles(newPath, fileNames, path.getName()); + } else { + populateFiles(newPath, fileNames, parent + "." + path.getName()); + } + } + } else { + String pathName = path.getName(); + String classSuffix = ".class"; + pathName = pathName.endsWith(classSuffix) ? + pathName.substring(0, pathName.length() - classSuffix.length()) : pathName; + if ("".equals(parent)) { + fileNames.add(pathName); + } else { + fileNames.add(parent + "." + pathName); + } + } + } + + private static String getSourcePath(Context context) throws PackageManager.NameNotFoundException { + return context.getPackageManager().getApplicationInfo(context.getPackageName(), 0).sourceDir; + } +} diff --git a/library/src/com/orm/SugarConfig.java b/library/src/com/orm/util/SugarConfig.java similarity index 99% rename from library/src/com/orm/SugarConfig.java rename to library/src/com/orm/util/SugarConfig.java index aaeb79b6..524adf29 100644 --- a/library/src/com/orm/SugarConfig.java +++ b/library/src/com/orm/util/SugarConfig.java @@ -1,4 +1,4 @@ -package com.orm; +package com.orm.util; import android.content.Context; import android.content.pm.ApplicationInfo; diff --git a/library/src/com/orm/SugarCursorFactory.java b/library/src/com/orm/util/SugarCursorFactory.java similarity index 97% rename from library/src/com/orm/SugarCursorFactory.java rename to library/src/com/orm/util/SugarCursorFactory.java index 17c60c59..538c8a9c 100644 --- a/library/src/com/orm/SugarCursorFactory.java +++ b/library/src/com/orm/util/SugarCursorFactory.java @@ -1,4 +1,4 @@ -package com.orm; +package com.orm.util; import android.database.Cursor; import android.database.sqlite.SQLiteCursor; diff --git a/library/test/com/orm/NamingHelperTest.java b/library/test/com/orm/NamingHelperTest.java new file mode 100644 index 00000000..d7c2e30e --- /dev/null +++ b/library/test/com/orm/NamingHelperTest.java @@ -0,0 +1,25 @@ +package com.orm; + +import com.orm.util.NamingHelper; +import org.junit.Test; + +import static junit.framework.Assert.assertEquals; + +public class NamingHelperTest { + @Test + public void testToSQLNameCaseConversion() throws Exception { + assertEquals("TESTLOWERCASE", NamingHelper.toSQLNameDefault("testlowercase")); + assertEquals("TESTUPPERCASE", NamingHelper.toSQLNameDefault("TESTUPPERCASE")); + } + + @Test + public void testToSQLNameUnderscore() { + assertEquals("TEST_UNDERSCORE", NamingHelper.toSQLNameDefault("testUnderscore")); + assertEquals("AB_CD", NamingHelper.toSQLNameDefault("AbCd")); + assertEquals("AB_CD", NamingHelper.toSQLNameDefault("ABCd")); + assertEquals("AB_CD", NamingHelper.toSQLNameDefault("AbCD")); + assertEquals("SOME_DETAILS_OBJECT", NamingHelper.toSQLNameDefault("SomeDetailsObject")); + } + + +} diff --git a/library/test/com/orm/StringUtilTest.java b/library/test/com/orm/StringUtilTest.java deleted file mode 100644 index 8f2b8786..00000000 --- a/library/test/com/orm/StringUtilTest.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.orm; - -import org.junit.Test; - -import static junit.framework.Assert.assertEquals; - -public class StringUtilTest { - @Test - public void testToSQLNameCaseConversion() throws Exception { - assertEquals("TESTLOWERCASE", StringUtil.toSQLNameDefault("testlowercase")); - assertEquals("TESTUPPERCASE", StringUtil.toSQLNameDefault("TESTUPPERCASE")); - } - - @Test - public void testToSQLNameUnderscore(){ - assertEquals("TEST_UNDERSCORE", StringUtil.toSQLNameDefault("testUnderscore")); - assertEquals("AB_CD", StringUtil.toSQLNameDefault("AbCd")); - assertEquals("AB_CD", StringUtil.toSQLNameDefault("ABCd")); - assertEquals("AB_CD", StringUtil.toSQLNameDefault("AbCD")); - assertEquals("SOME_DETAILS_OBJECT", StringUtil.toSQLNameDefault("SomeDetailsObject")); - } - - -} diff --git a/library/test/com/orm/query/TestRecord.java b/library/test/com/orm/query/TestRecord.java index 0751a936..50997205 100644 --- a/library/test/com/orm/query/TestRecord.java +++ b/library/test/com/orm/query/TestRecord.java @@ -1,10 +1,9 @@ package com.orm.query; import android.content.Context; -import com.orm.SugarApp; import com.orm.SugarRecord; -public class TestRecord extends SugarRecord{ +public class TestRecord extends SugarRecord { private String name;