mirror of https://github.com/tasks/tasks
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
310 lines
11 KiB
Java
310 lines
11 KiB
Java
/**
|
|
* See the file "LICENSE" for the full license governing this code.
|
|
*/
|
|
package com.todoroo.astrid.producteev.sync;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Random;
|
|
|
|
import org.json.JSONArray;
|
|
import org.json.JSONException;
|
|
import org.json.JSONObject;
|
|
|
|
import android.content.Context;
|
|
|
|
import com.todoroo.andlib.data.Property;
|
|
import com.todoroo.andlib.data.TodorooCursor;
|
|
import com.todoroo.andlib.service.Autowired;
|
|
import com.todoroo.andlib.service.ContextManager;
|
|
import com.todoroo.andlib.service.DependencyInjectionService;
|
|
import com.todoroo.andlib.sql.Criterion;
|
|
import com.todoroo.andlib.sql.Join;
|
|
import com.todoroo.andlib.sql.Query;
|
|
import com.todoroo.astrid.core.PluginServices;
|
|
import com.todoroo.astrid.dao.MetadataDao.MetadataCriteria;
|
|
import com.todoroo.astrid.dao.StoreObjectDao;
|
|
import com.todoroo.astrid.dao.StoreObjectDao.StoreObjectCriteria;
|
|
import com.todoroo.astrid.dao.TaskDao;
|
|
import com.todoroo.astrid.dao.TaskDao.TaskCriteria;
|
|
import com.todoroo.astrid.data.Metadata;
|
|
import com.todoroo.astrid.data.StoreObject;
|
|
import com.todoroo.astrid.data.Task;
|
|
import com.todoroo.astrid.notes.NoteMetadata;
|
|
import com.todoroo.astrid.producteev.ProducteevUtilities;
|
|
import com.todoroo.astrid.producteev.api.ApiUtilities;
|
|
import com.todoroo.astrid.service.MetadataService;
|
|
import com.todoroo.astrid.tags.TagService;
|
|
|
|
public final class ProducteevDataService {
|
|
|
|
// --- constants
|
|
|
|
/** Utility for joining tasks with metadata */
|
|
public static final Join METADATA_JOIN = Join.left(Metadata.TABLE, Task.ID.eq(Metadata.TASK));
|
|
|
|
/** NoteMetadata provider string */
|
|
public static final String NOTE_PROVIDER = "producteev"; //$NON-NLS-1$
|
|
|
|
// --- singleton
|
|
|
|
private static ProducteevDataService instance = null;
|
|
|
|
public static synchronized ProducteevDataService getInstance() {
|
|
if(instance == null)
|
|
instance = new ProducteevDataService(ContextManager.getContext());
|
|
return instance;
|
|
}
|
|
|
|
// --- instance variables
|
|
|
|
protected final Context context;
|
|
|
|
@Autowired
|
|
private TaskDao taskDao;
|
|
|
|
@Autowired
|
|
private MetadataService metadataService;
|
|
|
|
@Autowired
|
|
private StoreObjectDao storeObjectDao;
|
|
|
|
private final ProducteevUtilities preferences = ProducteevUtilities.INSTANCE;
|
|
|
|
static final Random random = new Random();
|
|
|
|
private ProducteevDataService(Context context) {
|
|
this.context = context;
|
|
DependencyInjectionService.getInstance().inject(this);
|
|
}
|
|
|
|
// --- task and metadata methods
|
|
|
|
/**
|
|
* Clears metadata information. Used when user logs out of service
|
|
*/
|
|
public void clearMetadata() {
|
|
PluginServices.getTaskService().clearDetails(Task.ID.in(Query.select(Metadata.TASK).from(Metadata.TABLE).
|
|
where(MetadataCriteria.withKey(ProducteevTask.METADATA_KEY))));
|
|
metadataService.deleteWhere(Metadata.KEY.eq(ProducteevTask.METADATA_KEY));
|
|
storeObjectDao.deleteWhere(StoreObject.TYPE.eq(ProducteevDashboard.TYPE));
|
|
}
|
|
|
|
/**
|
|
* Gets tasks that were created since last sync
|
|
* @param properties
|
|
* @return
|
|
*/
|
|
public TodorooCursor<Task> getLocallyCreated(Property<?>[] properties) {
|
|
return
|
|
taskDao.query(Query.select(properties).join(ProducteevDataService.METADATA_JOIN).where(
|
|
Criterion.and(
|
|
Criterion.not(Task.ID.in(Query.select(Metadata.TASK).from(Metadata.TABLE).
|
|
where(Criterion.and(MetadataCriteria.withKey(ProducteevTask.METADATA_KEY), ProducteevTask.ID.gt(0))))),
|
|
TaskCriteria.isActive())).
|
|
groupBy(Task.ID));
|
|
}
|
|
|
|
/**
|
|
* Gets tasks that were modified since last sync
|
|
* @param properties
|
|
* @return null if never sync'd
|
|
*/
|
|
public TodorooCursor<Task> getLocallyUpdated(Property<?>[] properties) {
|
|
long lastSyncDate = preferences.getLastSyncDate();
|
|
if(lastSyncDate == 0)
|
|
return taskDao.query(Query.select(Task.ID).where(Criterion.none));
|
|
return
|
|
taskDao.query(Query.select(properties).join(ProducteevDataService.METADATA_JOIN).where(
|
|
Criterion.and(
|
|
MetadataCriteria.withKey(ProducteevTask.METADATA_KEY),
|
|
ProducteevTask.ID.gt(0),
|
|
Task.MODIFICATION_DATE.gt(lastSyncDate))).
|
|
groupBy(Task.ID));
|
|
}
|
|
|
|
/**
|
|
* Searches for a local task with same remote id, updates this task's id
|
|
* @param remoteTask
|
|
* @return true if found local match
|
|
*/
|
|
public boolean findLocalMatch(ProducteevTaskContainer remoteTask) {
|
|
if(remoteTask.task.getId() != Task.NO_ID)
|
|
return true;
|
|
TodorooCursor<Task> cursor = taskDao.query(Query.select(Task.ID).
|
|
join(ProducteevDataService.METADATA_JOIN).where(Criterion.and(MetadataCriteria.withKey(ProducteevTask.METADATA_KEY),
|
|
ProducteevTask.ID.eq(remoteTask.pdvTask.getValue(ProducteevTask.ID)))));
|
|
try {
|
|
if(cursor.getCount() == 0)
|
|
return false;
|
|
cursor.moveToFirst();
|
|
remoteTask.task.setId(cursor.get(Task.ID));
|
|
return true;
|
|
} finally {
|
|
cursor.close();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Saves a task and its metadata
|
|
* @param task
|
|
*/
|
|
public void saveTaskAndMetadata(ProducteevTaskContainer task) {
|
|
taskDao.save(task.task);
|
|
|
|
task.metadata.add(task.pdvTask);
|
|
metadataService.synchronizeMetadata(task.task.getId(), task.metadata,
|
|
Criterion.or(MetadataCriteria.withKey(ProducteevTask.METADATA_KEY),
|
|
Criterion.and(MetadataCriteria.withKey(NoteMetadata.METADATA_KEY),
|
|
NoteMetadata.EXT_PROVIDER.eq(NOTE_PROVIDER)),
|
|
MetadataCriteria.withKey(TagService.KEY)));
|
|
}
|
|
|
|
/**
|
|
* Reads a task and its metadata
|
|
* @param task
|
|
* @return
|
|
*/
|
|
public ProducteevTaskContainer readTaskAndMetadata(TodorooCursor<Task> taskCursor) {
|
|
Task task = new Task(taskCursor);
|
|
|
|
// read tags, notes, etc
|
|
ArrayList<Metadata> metadata = new ArrayList<Metadata>();
|
|
TodorooCursor<Metadata> metadataCursor = metadataService.query(Query.select(Metadata.PROPERTIES).
|
|
where(Criterion.and(MetadataCriteria.byTask(task.getId()),
|
|
Criterion.or(MetadataCriteria.withKey(TagService.KEY),
|
|
MetadataCriteria.withKey(ProducteevTask.METADATA_KEY),
|
|
MetadataCriteria.withKey(NoteMetadata.METADATA_KEY)))));
|
|
try {
|
|
for(metadataCursor.moveToFirst(); !metadataCursor.isAfterLast(); metadataCursor.moveToNext()) {
|
|
metadata.add(new Metadata(metadataCursor));
|
|
}
|
|
} finally {
|
|
metadataCursor.close();
|
|
}
|
|
|
|
return new ProducteevTaskContainer(task, metadata);
|
|
}
|
|
|
|
/**
|
|
* Reads metadata out of a task
|
|
* @return null if no metadata found
|
|
*/
|
|
public Metadata getTaskMetadata(long taskId) {
|
|
TodorooCursor<Metadata> cursor = metadataService.query(Query.select(
|
|
Metadata.PROPERTIES).where(
|
|
MetadataCriteria.byTaskAndwithKey(taskId, ProducteevTask.METADATA_KEY)));
|
|
try {
|
|
if(cursor.getCount() == 0)
|
|
return null;
|
|
cursor.moveToFirst();
|
|
return new Metadata(cursor);
|
|
} finally {
|
|
cursor.close();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reads task notes out of a task
|
|
*/
|
|
public TodorooCursor<Metadata> getTaskNotesCursor(long taskId) {
|
|
TodorooCursor<Metadata> cursor = metadataService.query(Query.select(Metadata.PROPERTIES).
|
|
where(MetadataCriteria.byTaskAndwithKey(taskId, NoteMetadata.METADATA_KEY)));
|
|
return cursor;
|
|
}
|
|
|
|
private void readDashboards() {
|
|
if (dashboards == null) {
|
|
dashboards = readStoreObjects(ProducteevDashboard.TYPE);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reads store objects.
|
|
*/
|
|
public StoreObject[] readStoreObjects(String type) {
|
|
StoreObject[] ret;
|
|
TodorooCursor<StoreObject> cursor = storeObjectDao.query(Query.select(StoreObject.PROPERTIES).
|
|
where(StoreObjectCriteria.byType(type)));
|
|
try {
|
|
ret = new StoreObject[cursor.getCount()];
|
|
for(int i = 0; i < ret.length; i++) {
|
|
cursor.moveToNext();
|
|
StoreObject dashboard = new StoreObject(cursor);
|
|
ret[i] = dashboard;
|
|
}
|
|
} finally {
|
|
cursor.close();
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
// --- dashboard methods
|
|
|
|
private StoreObject[] dashboards = null;
|
|
|
|
/**
|
|
* @return a list of dashboards
|
|
*/
|
|
public StoreObject[] getDashboards() {
|
|
readDashboards();
|
|
return dashboards;
|
|
}
|
|
|
|
/**
|
|
* Reads dashboards
|
|
* @throws JSONException
|
|
*/
|
|
@SuppressWarnings("nls")
|
|
public void updateDashboards(JSONArray changedDashboards) throws JSONException {
|
|
readDashboards();
|
|
for(int i = 0; i < changedDashboards.length(); i++) {
|
|
JSONObject remote = changedDashboards.getJSONObject(i).getJSONObject("dashboard");
|
|
updateDashboards(remote, false);
|
|
}
|
|
|
|
// clear dashboard cache
|
|
dashboards = null;
|
|
}
|
|
|
|
@SuppressWarnings("nls")
|
|
public StoreObject updateDashboards(JSONObject remote, boolean reinitCache) throws JSONException {
|
|
if (reinitCache)
|
|
readDashboards();
|
|
long id = remote.getLong("id_dashboard");
|
|
StoreObject local = null;
|
|
for(StoreObject dashboard : dashboards) {
|
|
if(dashboard.getValue(ProducteevDashboard.REMOTE_ID).equals(id)) {
|
|
local = dashboard;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(remote.getInt("deleted") != 0) {
|
|
if(local != null)
|
|
storeObjectDao.delete(local.getId());
|
|
}
|
|
|
|
if(local == null)
|
|
local = new StoreObject();
|
|
local.setValue(StoreObject.TYPE, ProducteevDashboard.TYPE);
|
|
local.setValue(ProducteevDashboard.REMOTE_ID, id);
|
|
local.setValue(ProducteevDashboard.NAME, ApiUtilities.decode(remote.getString("title")));
|
|
|
|
StringBuilder users = new StringBuilder();
|
|
JSONArray accessList = remote.getJSONArray("accesslist");
|
|
for(int j = 0; j < accessList.length(); j++) {
|
|
JSONObject user = accessList.getJSONObject(j).getJSONObject("user");
|
|
users.append(user.getLong("id_user")).append(',');
|
|
String name = ApiUtilities.decode(user.optString("firstname", "") + ' ' +
|
|
user.optString("lastname", ""));
|
|
users.append(name.trim()).append(';');
|
|
}
|
|
local.setValue(ProducteevDashboard.USERS, users.toString());
|
|
storeObjectDao.persist(local);
|
|
if (reinitCache)
|
|
dashboards = null;
|
|
return local;
|
|
}
|
|
}
|