/** * Filename: EntityHome.java (in org.repin.android.db) * This file is part of the Redpin project. * * Redpin is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 3 of the License, or * any later version. * * Redpin is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Redpin. If not, see <http://www.gnu.org/licenses/>. * * (c) Copyright ETH Zurich, Pascal Brogle, Philipp Bolliger, 2010, ALL RIGHTS RESERVED. * * www.redpin.org */ package org.redpin.android.db; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import org.redpin.android.ApplicationContext; import android.content.ContentProvider; import android.content.ContentResolver; import android.content.ContentUris; import android.content.ContentValues; import android.database.Cursor; import android.database.SQLException; import android.net.Uri; import android.provider.BaseColumns; /** * Abstract class which provides an partial implementation of all function * needed to add, get, update and remove entities to/from database. * EntityHomes are used to encapsulate androids {@link ContentProvider} * * @author Pascal Brogle (broglep@student.ethz.ch) * * @param <T> * entity which implements the interface {@link LocalEntity} */ public abstract class EntityHome<T extends LocalEntity> implements IEntityHome<T, Long> { protected ContentResolver resolver; /** * Transforms an entity to a set of values * * @param e * Entity * @return Set of entity values */ abstract protected ContentValues toContentValues(T e); /** * Transforms an database row to an entity * * @param cursor * @return Entity */ abstract public T fromCursorRow(Cursor cursor); /** * * @return {@link ContentProvider} URI of entities handled by this * {@link EntityHome} */ abstract protected Uri contentUri(); /** * Creates an {@link EntityHome} with the {@link ContentResolver} obtained * from {@link ApplicationContext} */ public EntityHome() { this.resolver = ApplicationContext.get().getContentResolver(); } /** * * @param resolver * {@link ContentResolver} */ public EntityHome(ContentResolver resolver) { this.resolver = resolver; } /* add */ /** * Add an entity to the database. * * @param e * Entity * @return Entity with its generated primary key */ public T add(T e) { ContentValues values = toContentValues(e); Uri res = resolver.insert(contentUri(), values); e.setLocalId(getId(res)); return e; } /** * Add a list of entities * * @param list * {@link List} of entities * @return {@link List} of entities with their generated primary keys */ public List<T> add(List<T> list) { T el; List<T> res = new ArrayList<T>(list.size()); for (T e : list) { el = add(e); if (el == null) { break; } else { res.add(el); } } return res; } /* get */ /** * Get an entity by it's primary key * * @param id * Primary Key * @return Entity */ public T getById(Long id) { Uri uri = ContentUris.withAppendedId(contentUri(), id); List<T> res = fromCursor(resolver.query(uri, null, null, null, null)); if (res.size() < 1) { return null; } return res.get(0); } /** * Get all entities * * @return {@link List} of all entities */ public List<T> getAll() { return fromCursor(resolver.query(contentUri(), null, null, null, null)); } /** * Get an entity * * @param e * Entity * @return Entity with all fields filled from database */ public T get(T e) { return getById(e.getLocalId()); } /** * Get a {@link List} of entities * * @param list * {@link List} of primary keys * @return {@link List} of entities */ public List<T> get(List<T> list) { List<T> res = new ArrayList<T>(list.size()); for (T e : list) { res.add(get(e)); } return res; } /** * Get a {@link List} of entities by their primary keys * * @param ids * {@link List} of primary keys * @return {@link List} of entities */ public List<T> getById(List<Long> ids) { List<T> res = new ArrayList<T>(ids.size()); for (Long id : ids) { res.add(getById(id)); } return res; } /* remove */ /** * Removes an entity by it's primary key * * @param id * Primary Key * @return True if successful */ public boolean removeById(Long id) { Uri uri = ContentUris.withAppendedId(contentUri(), id); return resolver.delete(uri, null, null) == 1; } /** * Removes an entity * * @param e * Entity * @return True if successful */ public boolean remove(T e) { return removeById(e.getLocalId()); } /** * Removes a {@link List} of entities * * @param list * {@link List} of entities * @return True if removal of all entities was successful */ public boolean remove(List<T> list) { boolean ok = true; for (T e : list) { if (!remove(e)) break; } return ok; } /** * Removes a list of entities by their primary keys * * @param ids * List of primary keys * @return True if removal of all entities was successful */ public boolean removeById(List<Long> ids) { boolean ok = true; for (Long id : ids) { if (!removeById(id)) { ok = false; break; } } return ok; } /** * Removes all entities from database * * @return True if removal was successful */ public boolean removeAll() { resolver.delete(contentUri(), null, null); return true; } /* update */ /** * Updates an entity * * @param e * Entity * @return <code>true</code> if successful */ public boolean update(T e) { if (e.getLocalId() < 0) { return false; } Uri uri = ContentUris.withAppendedId(contentUri(), e.getLocalId()); return resolver.update(uri, toContentValues(e), null, null) == 1; } /** * Updates a {@link List} of entities * * @param list * {@link List} of entities to be updated * @return <code>true</code> if all entities were updated successfully */ public boolean update(List<T> list) { boolean ok = true; for (T e : list) { if (!update(e)) { ok = false; break; } } return ok; } private static final String[] idProjection = new String[] { BaseColumns._ID }; /** * Gets the database id of an entity-URI * * @param uri * URI of an entity * @return Database id for entity with specified URI */ protected long getId(Uri uri) { Cursor cursor = resolver.query(uri, idProjection, null, null, null); if (cursor.moveToFirst()) { long id = cursor.getLong(cursor.getColumnIndex(BaseColumns._ID)); cursor.close(); return id; } cursor.close(); throw new SQLException("no first row"); } /** * Creates entities from cursor * * @param cursor * @return {@link List} of entities */ protected List<T> fromCursor(Cursor cursor) { List<T> res = new LinkedList<T>(); if (cursor == null) { return res; } while (cursor.moveToNext()) { int pos = cursor.getPosition(); res.add(fromCursorRow(cursor)); int new_pos = cursor.getPosition(); if (pos != new_pos) { cursor.moveToPosition(pos); } } cursor.close(); return res; } }