package fr.eyal.datalib.sample.netflix.data.model.cast; import java.util.ArrayList; import java.util.Calendar; import android.content.ContentProviderOperation; import android.content.ContentProviderResult; import android.content.ContentResolver; import android.content.ContentValues; import android.content.OperationApplicationException; import android.database.Cursor; import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; import android.os.RemoteException; import fr.eyal.lib.data.model.BusinessObjectDAO; import fr.eyal.datalib.sample.netflix.data.model.NetflixProvider; public class CastPersonBase extends BusinessObjectDAO { protected long _parentId = ID_INVALID; //list of content public String id; public String name; public String bio; //list of childs public ArrayList<CastLink> castLink; public CastPersonBase() { super(); } public CastPersonBase(final long id) { super(id); } @Override protected void initialize() { super.initialize(); } /** * DATABASE MANAGEMENT */ /** * Constants used with a ContentProvider's access */ public static final String CONTENT_PATH = "castperson"; public static final String CONTENT_URL = NetflixProvider.PROVIDER_PREFIX + NetflixProvider.AUTHORITY + "/" + CONTENT_PATH; public static final Uri CONTENT_URI = Uri.parse(CONTENT_URL); /** * SQL databases table's name */ public static String DATABASE_TABLE_NAME = "castperson"; /** * SQL database table's fields names */ public static final String FIELD__ID = BusinessObjectDAO.FIELD_ID; public static final String FIELD__UPDATED_AT = BusinessObjectDAO.FIELD_UPDATED_AT; public static final String FIELD__PARENT_ID = "_parent_id"; //list of content public static final String FIELD_ID = "id"; public static final String FIELD_NAME = "name"; public static final String FIELD_BIO = "bio"; /** * List of SQL database fields' names */ public static String[] DATABASE_TABLE_FIELDS_NAMES = { // header FIELD__ID, // _id FIELD__UPDATED_AT, // updated_at FIELD__PARENT_ID, // sensors_id //list of content FIELD_ID, //id; FIELD_NAME, //name; FIELD_BIO, //bio; }; /** * SQL fields' types in the table */ static String[] DATABASE_TABLE_FIELDS_TYPES = { // prevision_meteo_meteo_weather // header "integer", "integer", "integer", //list of content "text", "text", "text", }; /** * SQLite scripts to create the table */ public static String CREATE_TABLE = "CREATE TABLE " + DATABASE_TABLE_NAME + " (" + DATABASE_TABLE_FIELDS_NAMES[0] + " " + DATABASE_TABLE_FIELDS_TYPES[0] + " PRIMARY KEY AUTOINCREMENT" + ", " + DATABASE_TABLE_FIELDS_NAMES[1] + " " + DATABASE_TABLE_FIELDS_TYPES[1] + ", " + DATABASE_TABLE_FIELDS_NAMES[2] + " " + DATABASE_TABLE_FIELDS_TYPES[2] + " REFERENCES " + Cast.DATABASE_TABLE_NAME + "(" + Cast.DATABASE_TABLE_FIELDS_NAMES[0] + ") ON DELETE CASCADE" + ", " //list of content + DATABASE_TABLE_FIELDS_NAMES[3] + " " + DATABASE_TABLE_FIELDS_TYPES[3] + ", " + DATABASE_TABLE_FIELDS_NAMES[4] + " " + DATABASE_TABLE_FIELDS_TYPES[4] + ", " + DATABASE_TABLE_FIELDS_NAMES[5] + " " + DATABASE_TABLE_FIELDS_TYPES[5] + "); " + "CREATE INDEX " + DATABASE_TABLE_NAME + "_" + DATABASE_TABLE_FIELDS_NAMES[0] + " ON " + DATABASE_TABLE_NAME + " (" + DATABASE_TABLE_FIELDS_NAMES[0] + ");"; @Override protected ContentResolver getContentResolver() { try { return NetflixProvider.getContentResolver(); } catch (InstantiationException e) { e.printStackTrace(); } return null; } @Override public ContentValues getContentValues() { // we create the values to add final ContentValues values = new ContentValues(); if (_id != ID_INVALID) values.put(FIELD__ID, _id); if (_parentId != ID_INVALID) values.put(FIELD__PARENT_ID, _parentId); values.put(FIELD__UPDATED_AT, _updatedAt.getTimeInMillis() / 1000); //list of content values.put(FIELD_ID, id); values.put(FIELD_NAME, name); values.put(FIELD_BIO, bio); return values; } @Override protected void fillFromDatabaseById(final long id) { // we define the access condition to the object final String[] columns = new String[DATABASE_TABLE_FIELDS_NAMES.length]; for (int i = 0; i < DATABASE_TABLE_FIELDS_NAMES.length; i++) { columns[i] = DATABASE_TABLE_FIELDS_NAMES[i]; } final String where = FIELD__ID + "=?"; final String[] args = { id + "" }; // we check the existence inside the database final Cursor cursor = mResolver.query(CONTENT_URI, // CastPerson columns, // id where, // id=? args, // id FIELD__UPDATED_AT + " DESC"); // ORDER BY updated_at DESC // we fill the object thanks to the Cursor recieved if (cursor.moveToFirst()) { fillObjectFromCursor(cursor); } if (!cursor.isClosed()) { cursor.close(); } // we get the childs content fillChildrenFromDatabase(); } @Override protected void fillObjectFromCursor(final Cursor cursor) { // we initialize the childs tabs castLink = new ArrayList<CastLink>(); // if we have a content if (!cursor.isClosed() && !cursor.isAfterLast()) { int i = 0; // header _id = cursor.getLong(i++); _updatedAt = Calendar.getInstance(); _updatedAt.setTimeInMillis(cursor.getLong(i++) * 1000); _parentId = cursor.getLong(i++); //list of content id = cursor.getString(i++); name = cursor.getString(i++); bio = cursor.getString(i++); } else { _id = ID_INVALID; } } @Override public ContentProviderResult[] save() throws OperationApplicationException, RemoteException { // we define the access conditions to the object final String[] columns = { FIELD__ID }; final String where = FIELD__ID + " LIKE ?"; // id LIKE {this.id} final String[] args = { _id + "" }; return save(columns, where, args, CONTENT_URI, NetflixProvider.AUTHORITY); } @Override protected int updateChildrenId(long[] ids, int index, int parentIndex) { for (final CastLink castLinkElement : castLink) { index = castLinkElement.updateId(ids, index, parentIndex); } return index; } @Override public int updateId(long[] ids, int index, int parentIndex) { if(parentIndex >= 0) _parentId = ids[parentIndex]; return super.updateId(ids, index); } @Override protected void updateIntoTheDatabase(final ArrayList<ContentProviderOperation> batch) { updateIntoTheDatabase(batch, CONTENT_URI); } @Override public ContentProviderResult[] delete() throws OperationApplicationException, RemoteException { // we define the access conditions to the object final String[] columns = { FIELD__ID }; final String where = FIELD__ID + "=?"; // _url LIKE {this.url} final String[] args = { _id + "" }; return delete(columns, where, args, CONTENT_URI, NetflixProvider.AUTHORITY); } @Override public boolean deleteFromDatabase(final ArrayList<ContentProviderOperation> batch) { return deleteFromDatabase(batch, CONTENT_URI); } @Override public void deleteChildsFromDatabase(final ArrayList<ContentProviderOperation> batch) { // we first remove all the childs of the childs of the object for (final CastLink castLinkElement : castLink) { castLinkElement.deleteChildsFromDatabase(batch); } String whereClause = ""; final String[] argsClause = { _id + "" }; // we delete all the child entries whereClause = CastLink.FIELD__PARENT_ID + "=?"; // castperson_id=? batch.add(ContentProviderOperation.newDelete(CastLink.CONTENT_URI) .withSelection(whereClause, argsClause) .build()); } @Override public void addChildsIntoDatabase(final ArrayList<ContentProviderOperation> batch, final int previousResult) { for (final CastLink castLinkElement : castLink) { castLinkElement.addIntoDatabase(batch, CastLink.CONTENT_URI, CastLink.FIELD__PARENT_ID, previousResult); } } @Override public void addChildsIntoDatabase(final ArrayList<ContentProviderOperation> batch) { for (final CastLink castLinkElement : castLink) { castLinkElement._parentId = _id; castLinkElement.addIntoDatabase(batch, CastLink.CONTENT_URI); } } @Override protected void fillChildrenFromDatabase() { String[] columns; String where; String[] args; Cursor cursor; // we define the access conditions to the objects columns = new String[CastLink.DATABASE_TABLE_FIELDS_NAMES.length]; for (int i = 0; i < CastLink.DATABASE_TABLE_FIELDS_NAMES.length; i++) { columns[i] = CastLink.DATABASE_TABLE_FIELDS_NAMES[i]; } where = CastLink.FIELD__PARENT_ID + "=?"; args = new String[1]; args[0] = _id + ""; // we check the existence of the entry inside the database cursor = mResolver.query(CastLink.CONTENT_URI, columns, // all the columns of the object where, // castperson_id=? args, // id of the object null); // if we get a result if (cursor.moveToFirst()) { do { // we create and then fill the item with the Cursor final CastLink itemCastLink = new CastLink(); itemCastLink.fillObjectFromCursor(cursor); castLink.add(itemCastLink); // we add a new object to the list } while (cursor.moveToNext()); } cursor.close(); } /** * This function build an array of {@link CastPersonBase} thanks to a Cursor * object received from the database. * * @param c The cursor object. * @param join Tells if the child of the objects have to be recursively * filled from the database. * @return Returns an {@link ArrayList} of the result fill with the content * of the Cursor. If the Cursor is empty, it returns an empty array. * <b>The result of this function is return as ArrayList<?>. It has * to be casted into the expected class to be useful.</b> * Ex: Cast to ArrayList<{@link CastPerson}> if you want it as {@link CastPerson} */ public static ArrayList<?> buildArrayFromCursor(final Cursor c, final boolean join) { final ArrayList<CastPersonBase> result = new ArrayList<CastPersonBase>(); if (c.moveToFirst()) { do { // we create and fill the item final CastPersonBase newObject = new CastPersonBase(); newObject.fillObjectFromCursor(c); // if it's asked we fill the childs of the item if (join) { newObject.fillChildrenFromDatabase(); } // we add the element to the result result.add(newObject); } while (c.moveToNext()); } return result; } /** * PARCELABLE MANAGMENT */ public static final Parcelable.Creator<CastPersonBase> CREATOR = new Parcelable.Creator<CastPersonBase>() { @Override public CastPersonBase createFromParcel(final Parcel in) { return new CastPersonBase(in); } @Override public CastPersonBase[] newArray(final int size) { return new CastPersonBase[size]; } }; @Override public int describeContents() { return 0; } @Override public void writeToParcel(final Parcel dest, final int flags) { // Business Object DAO dest.writeLong(_id); dest.writeLong(_updatedAt.getTimeInMillis()); //list of content dest.writeString(id); dest.writeString(name); dest.writeString(bio); //list of childs dest.writeParcelableArray(castLink.toArray(new CastLink[castLink.size()]), 0); } public CastPersonBase(final Parcel in) { // Business Object DAO _id = in.readLong(); _updatedAt = Calendar.getInstance(); _updatedAt.setTimeInMillis(in.readLong()); //list of content id = in.readString(); name = in.readString(); bio = in.readString(); //list of children Parcelable[] items; items = in.readParcelableArray(CastLink.class.getClassLoader()); castLink = new ArrayList<CastLink>(); for (final Parcelable parcelable : items) { castLink.add((CastLink) parcelable); } } }