#557 - showoff of possible refactorings - see REFACTOR.md for additonal details

This commit is contained in:
Markus M. May 2018-01-04 22:22:08 +01:00
parent 9255b93800
commit 9cb019f5ca
7 changed files with 249 additions and 216 deletions

View file

@ -12,6 +12,8 @@ import org.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.sql.SQLException;
import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
@ -518,7 +520,12 @@ public class DataService extends IntentService {
} }
private void handleRemovedFoodRecord(String _id) { private void handleRemovedFoodRecord(String _id) {
MainApp.getDbHelper().foodHelper.deleteFoodById(_id);
try {
MainApp.getDbHelper().foodHelper.getDao().deleteByNSId(_id);
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
} }
public void handleAddChangeFoodRecord(JSONObject trJson) throws JSONException { public void handleAddChangeFoodRecord(JSONObject trJson) throws JSONException {

View file

@ -68,7 +68,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public static final String DATABASE_DBREQUESTS = "DBRequests"; public static final String DATABASE_DBREQUESTS = "DBRequests";
public static final String DATABASE_CAREPORTALEVENTS = "CareportalEvents"; public static final String DATABASE_CAREPORTALEVENTS = "CareportalEvents";
public static final String DATABASE_PROFILESWITCHES = "ProfileSwitches"; public static final String DATABASE_PROFILESWITCHES = "ProfileSwitches";
public static final String DATABASE_FOODS = "Foods";
private static final int DATABASE_VERSION = 8; private static final int DATABASE_VERSION = 8;
@ -95,11 +94,12 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
private static final ScheduledExecutorService profileSwitchEventWorker = Executors.newSingleThreadScheduledExecutor(); private static final ScheduledExecutorService profileSwitchEventWorker = Executors.newSingleThreadScheduledExecutor();
private static ScheduledFuture<?> scheduledProfileSwitchEventPost = null; private static ScheduledFuture<?> scheduledProfileSwitchEventPost = null;
public FoodHelper foodHelper = new FoodHelper(this); public FoodHelper foodHelper;
public DatabaseHelper(Context context) { public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION); super(context, DATABASE_NAME, null, DATABASE_VERSION);
onCreate(getWritableDatabase(), getConnectionSource()); onCreate(getWritableDatabase(), getConnectionSource());
foodHelper = new FoodHelper(getConnectionSource());
//onUpgrade(getWritableDatabase(), getConnectionSource(), 1,1); //onUpgrade(getWritableDatabase(), getConnectionSource(), 1,1);
} }

View file

@ -3,20 +3,25 @@ package info.nightscout.androidaps.db;
import com.j256.ormlite.field.DatabaseField; import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable; import com.j256.ormlite.table.DatabaseTable;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.Objects; import java.util.Objects;
import info.nightscout.utils.JsonHelper;
/** /**
* Created by mike on 20.09.2017. * Created by mike on 20.09.2017.
*/ */
@DatabaseTable(tableName = Food.TABLE_FOODS)
@DatabaseTable(tableName = DatabaseHelper.DATABASE_FOODS)
public class Food { public class Food {
private static Logger log = LoggerFactory.getLogger(Food.class); private static Logger log = LoggerFactory.getLogger(Food.class);
public static final String TABLE_FOODS = "Foods";
@DatabaseField(id = true) @DatabaseField(id = true)
public long key; public long key;
@ -64,6 +69,25 @@ public class Food {
key = System.currentTimeMillis(); key = System.currentTimeMillis();
} }
public static Food createFromJson(JSONObject json) throws JSONException {
Food food = new Food();
if ("food".equals(JsonHelper.safeGetString(json, "type"))) {
food._id = JsonHelper.safeGetString(json, "_id");
food.category = JsonHelper.safeGetString(json, "category");
food.subcategory = JsonHelper.safeGetString(json, "subcategory");
food.name = JsonHelper.safeGetString(json, "name");
food.units = JsonHelper.safeGetString(json, "unit");
food.portion = JsonHelper.safeGetDouble(json, "portion");
food.carbs = JsonHelper.safeGetInt(json, "carbs");
food.gi = JsonHelper.safeGetInt(json, "gi");
food.energy = JsonHelper.safeGetInt(json, "energy");
food.protein = JsonHelper.safeGetInt(json, "protein");
food.fat = JsonHelper.safeGetInt(json, "fat");
}
return food;
}
public boolean isEqual(Food other) { public boolean isEqual(Food other) {
if (portion != other.portion) if (portion != other.portion)
return false; return false;

View file

@ -0,0 +1,161 @@
package info.nightscout.androidaps.db;
import android.content.Context;
import com.j256.ormlite.android.apptools.OpenHelperManager;
import com.j256.ormlite.dao.BaseDaoImpl;
import com.j256.ormlite.dao.DaoManager;
import com.j256.ormlite.stmt.PreparedQuery;
import com.j256.ormlite.stmt.QueryBuilder;
import com.j256.ormlite.support.ConnectionSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
* Created by triplem on 04.01.18.
*/
public class FoodDao extends BaseDaoImpl<Food, Long> {
private static final Logger log = LoggerFactory.getLogger(FoodDao.class);
public FoodDao(ConnectionSource source) throws SQLException {
super(source, Food.class);
}
/**
* Static instantiation methods. The database connection is accessed via
* the OpenHelperManager which keeps a count of the number of objects
* using the connection. Thus every call to connect() must be matched by
* a call to release() once the session is done.
*/
public static FoodDao connect(Context context) {
return with(OpenHelperManager.getHelper(context, DatabaseHelper.class)
.getConnectionSource());
}
public static FoodDao with(ConnectionSource connection) {
try {
return (FoodDao) DaoManager.createDao(connection, Food.class);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
/**
* Releasing the DAO flags the connection manager that the DAO is no
* longer using the connection. When the connection count is zero, the
* connection manager will close the database.
*/
public void release() {
OpenHelperManager.releaseHelper();
}
/**
*
* @return
*
* @deprecated should use queryForAll instead, which is a standard method of the ORMLite DAO
*/
public List<Food> getFoodData() {
try {
QueryBuilder<Food, Long> queryBuilder = this.queryBuilder();
PreparedQuery<Food> preparedQuery = queryBuilder.prepare();
return this.query(preparedQuery);
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
return new ArrayList<>();
}
public boolean createOrUpdateByNS(Food food) {
try {
// find by NS _id
if (food._id != null) {
Food old = this.findByNSId(food._id);
if (old != null) {
if (!old.isEqual(food)) {
this.delete(old); // need to delete/create because date may change too
old.copyFrom(food);
this.create(old);
log.debug("FOOD: Updating record by _id: " + old.toString());
FoodHelper.scheduleFoodChange();
return true;
} else {
return false;
}
}
}
this.createOrUpdate(food);
log.debug("FOOD: New record: " + food.toString());
FoodHelper.scheduleFoodChange();
return true;
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
return false;
}
/**
* deletes an entry by its NS Id.
*
* Basically a convenience method for findByNSId and deleteFood.
*
* should be moved to a Service
*
* @param _id
*/
public void deleteByNSId(String _id) throws SQLException {
Food stored = findByNSId(_id);
if (stored != null) {
log.debug("FOOD: Removing Food record from database: " + stored.toString());
this.deleteFood(stored);
}
}
/**
* deletes the food and sends the foodChange Event
*
* should be moved ot a Service
*
* @param food
*/
public void deleteFood(Food food) {
try {
this.delete(food);
FoodHelper.scheduleFoodChange();
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
}
/**
* finds food by its NS Id.
*
* @param _id
* @return
*/
public Food findByNSId(String _id) {
try {
List<Food> list = this.queryForEq("_id", _id);
if (list.size() == 1) { // really? if there are more then one result, then we do not return anything...
return list.get(0);
}
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
return null;
}
}

View file

@ -1,208 +0,0 @@
package info.nightscout.androidaps.db;
import com.j256.ormlite.android.AndroidConnectionSource;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.stmt.PreparedQuery;
import com.j256.ormlite.stmt.QueryBuilder;
import com.j256.ormlite.stmt.Where;
import com.j256.ormlite.table.TableUtils;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.events.EventFoodDatabaseChanged;
/**
* Created by mike on 24.09.2017.
*/
public class FoodHelper {
private static Logger log = LoggerFactory.getLogger(FoodHelper.class);
DatabaseHelper databaseHelper;
private static final ScheduledExecutorService foodEventWorker = Executors.newSingleThreadScheduledExecutor();
private static ScheduledFuture<?> scheduledFoodEventPost = null;
public FoodHelper(DatabaseHelper databaseHelper) {
this.databaseHelper = databaseHelper;
}
private Dao<Food, Long> getDaoFood() throws SQLException {
return databaseHelper.getDao(Food.class);
}
public void resetFood() {
try {
TableUtils.dropTable(databaseHelper.getConnectionSource(), Food.class, true);
TableUtils.createTableIfNotExists(databaseHelper.getConnectionSource(), Food.class);
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
scheduleFoodChange();
}
public List<Food> getFoodData() {
try {
Dao<Food, Long> daoFood = getDaoFood();
List<Food> foods;
QueryBuilder<Food, Long> queryBuilder = daoFood.queryBuilder();
PreparedQuery<Food> preparedQuery = queryBuilder.prepare();
foods = daoFood.query(preparedQuery);
return foods;
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
return new ArrayList<>();
}
public boolean createOrUpdate(Food food) {
try {
// find by NS _id
if (food._id != null && !food._id.equals("")) {
Food old;
QueryBuilder<Food, Long> queryBuilder = getDaoFood().queryBuilder();
Where where = queryBuilder.where();
where.eq("_id", food._id);
PreparedQuery<Food> preparedQuery = queryBuilder.prepare();
List<Food> found = getDaoFood().query(preparedQuery);
if (found.size() > 0) {
old = found.get(0);
if (!old.isEqual(food)) {
getDaoFood().delete(old); // need to delete/create because date may change too
old.copyFrom(food);
getDaoFood().create(old);
log.debug("FOOD: Updating record by _id: " + old.toString());
scheduleFoodChange();
return true;
} else {
return false;
}
} else {
getDaoFood().createOrUpdate(food);
log.debug("FOOD: New record: " + food.toString());
scheduleFoodChange();
return true;
}
}
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
return false;
}
public void delete(Food food) {
try {
getDaoFood().delete(food);
scheduleFoodChange();
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
}
public static void scheduleFoodChange() {
class PostRunnable implements Runnable {
public void run() {
log.debug("Firing EventFoodChange");
MainApp.bus().post(new EventFoodDatabaseChanged());
scheduledFoodEventPost = null;
}
}
// prepare task for execution in 1 sec
// cancel waiting task to prevent sending multiple posts
if (scheduledFoodEventPost != null)
scheduledFoodEventPost.cancel(false);
Runnable task = new PostRunnable();
final int sec = 1;
scheduledFoodEventPost = foodEventWorker.schedule(task, sec, TimeUnit.SECONDS);
}
/*
{
"_id": "551ee3ad368e06e80856e6a9",
"type": "food",
"category": "Zakladni",
"subcategory": "Napoje",
"name": "Mleko",
"portion": 250,
"carbs": 12,
"gi": 1,
"created_at": "2015-04-14T06:59:16.500Z",
"unit": "ml"
}
*/
public void createFoodFromJsonIfNotExists(JSONObject trJson) {
try {
Food food = new Food();
if (trJson.has("type") && trJson.getString("type").equals("food")) {
if (trJson.has("_id"))
food._id = trJson.getString("_id");
if (trJson.has("category"))
food.category = trJson.getString("category");
if (trJson.has("subcategory"))
food.subcategory = trJson.getString("subcategory");
if (trJson.has("name"))
food.name = trJson.getString("name");
if (trJson.has("unit"))
food.units = trJson.getString("unit");
if (trJson.has("portion"))
food.portion = trJson.getDouble("portion");
if (trJson.has("carbs"))
food.carbs = trJson.getInt("carbs");
if (trJson.has("gi"))
food.gi = trJson.getInt("gi");
if (trJson.has("energy"))
food.energy = trJson.getInt("energy");
if (trJson.has("protein"))
food.protein = trJson.getInt("protein");
if (trJson.has("fat"))
food.fat = trJson.getInt("fat");
}
createOrUpdate(food);
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
}
public void deleteFoodById(String _id) {
Food stored = findFoodById(_id);
if (stored != null) {
log.debug("FOOD: Removing Food record from database: " + stored.toString());
delete(stored);
scheduleFoodChange();
}
}
public Food findFoodById(String _id) {
try {
QueryBuilder<Food, Long> queryBuilder = getDaoFood().queryBuilder();
Where where = queryBuilder.where();
where.eq("_id", _id);
PreparedQuery<Food> preparedQuery = queryBuilder.prepare();
List<Food> list = getDaoFood().query(preparedQuery);
if (list.size() == 1) {
return list.get(0);
} else {
return null;
}
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
return null;
}
}

View file

@ -121,7 +121,7 @@ public class FoodFragment extends SubscriberFragment {
} }
}); });
RecyclerViewAdapter adapter = new RecyclerViewAdapter(MainApp.getDbHelper().foodHelper.getFoodData()); RecyclerViewAdapter adapter = new RecyclerViewAdapter(MainApp.getDbHelper().foodHelper.getDao().getFoodData());
recyclerView.setAdapter(adapter); recyclerView.setAdapter(adapter);
loadData(); loadData();
@ -144,7 +144,7 @@ public class FoodFragment extends SubscriberFragment {
} }
void loadData() { void loadData() {
unfiltered = MainApp.getDbHelper().foodHelper.getFoodData(); unfiltered = MainApp.getDbHelper().foodHelper.getDao().getFoodData();
} }
void fillCategories() { void fillCategories() {
@ -299,7 +299,7 @@ public class FoodFragment extends SubscriberFragment {
if (_id != null && !_id.equals("")) { if (_id != null && !_id.equals("")) {
NSUpload.removeFoodFromNS(_id); NSUpload.removeFoodFromNS(_id);
} }
MainApp.getDbHelper().foodHelper.delete(food); MainApp.getDbHelper().foodHelper.getDao().deleteFood(food);
} }
}); });
builder.setNegativeButton(MainApp.sResources.getString(R.string.cancel), null); builder.setNegativeButton(MainApp.sResources.getString(R.string.cancel), null);

View file

@ -0,0 +1,49 @@
package info.nightscout.utils;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* JSonHelper is a Helper class which contains several methods to safely get data from the ggiven JSONObject.
*
* Created by triplem on 04.01.18.
*/
public class JsonHelper {
private static final Logger log = LoggerFactory.getLogger(JsonHelper.class);
private JsonHelper() {};
public static String safeGetString(JSONObject json, String fieldName) throws JSONException {
String result = null;
if (json.has(fieldName)) {
result = json.getString(fieldName);
}
return result;
}
public static double safeGetDouble(JSONObject json, String fieldName) throws JSONException {
double result = 0d;
if (json.has(fieldName)) {
result = json.getDouble(fieldName);
}
return result;
}
public static int safeGetInt(JSONObject json, String fieldName) throws JSONException {
int result = 0;
if (json.has(fieldName)) {
result = json.getInt(fieldName);
}
return result;
}
}