Move methods out of TagService

pull/189/head
Alex Baker 10 years ago
parent fac28c9ebc
commit def919ef9a

@ -49,6 +49,7 @@ import com.todoroo.astrid.actfm.ActFmCameraModule;
import com.todoroo.astrid.actfm.ActFmCameraModule.CameraResultCallback;
import com.todoroo.astrid.alarms.AlarmService;
import com.todoroo.astrid.dao.MetadataDao;
import com.todoroo.astrid.dao.TagDataDao;
import com.todoroo.astrid.dao.TaskAttachmentDao;
import com.todoroo.astrid.dao.UserActivityDao;
import com.todoroo.astrid.data.RemoteModel;
@ -175,6 +176,7 @@ ViewPager.OnPageChangeListener, EditNoteActivity.UpdatesChangedListener {
@Inject GCalHelper gcalHelper;
@Inject ActivityPreferences preferences;
@Inject DateChangedAlerts dateChangedAlerts;
@Inject TagDataDao tagDataDao;
// --- UI components
@ -360,7 +362,7 @@ ViewPager.OnPageChangeListener, EditNoteActivity.UpdatesChangedListener {
timerAction = new TimerActionControlSet(notificationManager, taskService, getActivity(), getView());
controls.add(timerAction);
TagsControlSet tagsControlSet = new TagsControlSet(preferences, tagService, getActivity());
TagsControlSet tagsControlSet = new TagsControlSet(metadataDao, tagDataDao, preferences, tagService, getActivity());
controls.add(tagsControlSet);
controlSetMap.put(getString(R.string.TEA_ctrl_lists_pref),
tagsControlSet);

@ -18,10 +18,12 @@ import com.todoroo.andlib.sql.Query;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.core.SortHelper;
import com.todoroo.astrid.dao.TaskDao.TaskCriteria;
import com.todoroo.astrid.data.Metadata;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.service.TaskService;
import com.todoroo.astrid.tags.TagService;
import com.todoroo.astrid.tags.TagService.Tag;
import com.todoroo.astrid.tags.TaskToTagMetadata;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -174,7 +176,7 @@ public class Astrid2TaskProvider extends InjectingContentProvider {
cursor.moveToNext();
Task task = new Task(cursor);
String taskTags = tagService.get().getTagsAsString(task.getId(), TAG_SEPARATOR);
String taskTags = getTagsAsString(task.getId(), TAG_SEPARATOR);
Object[] values = new Object[7];
values[0] = task.getTitle();
@ -263,4 +265,27 @@ public class Astrid2TaskProvider extends InjectingContentProvider {
log.error(e.getMessage(), e);
}
}
/**
* Return tags as a list of strings separated by given separator
* @return empty string if no tags, otherwise string
*/
private String getTagsAsString(long taskId, String separator) {
StringBuilder tagBuilder = new StringBuilder();
TodorooCursor<Metadata> tags = tagService.get().getTags(taskId);
try {
int length = tags.getCount();
for (int i = 0; i < length; i++) {
tags.moveToNext();
Metadata metadata = new Metadata(tags);
tagBuilder.append(metadata.getValue(TaskToTagMetadata.TAG_NAME));
if (i < length - 1) {
tagBuilder.append(separator);
}
}
} finally {
tags.close();
}
return tagBuilder.toString();
}
}

@ -16,9 +16,11 @@ import com.todoroo.andlib.utility.AndroidUtilities;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.api.PermaSql;
import com.todoroo.astrid.dao.MetadataDao;
import com.todoroo.astrid.dao.TagDataDao;
import com.todoroo.astrid.dao.TaskDao;
import com.todoroo.astrid.data.Metadata;
import com.todoroo.astrid.data.RemoteModel;
import com.todoroo.astrid.data.TagData;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.tags.TagService;
import com.todoroo.astrid.tags.TaskToTagMetadata;
@ -59,6 +61,7 @@ public class TaskService {
public static final String TRANS_REPEAT_COMPLETE = "repeat-complete"; //$NON-NLS-1$
private final TagDataDao tagDataDao;
private final TaskDao taskDao;
private final Broadcaster broadcaster;
private final FilterCounter filterCounter;
@ -67,8 +70,9 @@ public class TaskService {
private final MetadataDao metadataDao;
@Inject
public TaskService(TaskDao taskDao, Broadcaster broadcaster, FilterCounter filterCounter,
public TaskService(TagDataDao tagDataDao, TaskDao taskDao, Broadcaster broadcaster, FilterCounter filterCounter,
RefreshScheduler refreshScheduler, TagService tagService, MetadataDao metadataDao) {
this.tagDataDao = tagDataDao;
this.taskDao = taskDao;
this.broadcaster = broadcaster;
this.filterCounter = filterCounter;
@ -218,7 +222,7 @@ public class TaskService {
private void quickAdd(Task task, List<String> tags) {
saveWithoutPublishingFilterUpdate(task);
for(String tag : tags) {
tagService.createLink(task, tag);
createLink(task, tag);
}
broadcastFilterListUpdated();
}
@ -301,10 +305,10 @@ public class TaskService {
if (TaskToTagMetadata.KEY.equals(metadata.getKey())) {
if (metadata.containsNonNullValue(TaskToTagMetadata.TAG_UUID) && !RemoteModel.NO_UUID.equals(metadata.getValue(TaskToTagMetadata.TAG_UUID))) {
// This is more efficient
tagService.createLink(task, metadata.getValue(TaskToTagMetadata.TAG_NAME), metadata.getValue(TaskToTagMetadata.TAG_UUID));
createLink(task, metadata.getValue(TaskToTagMetadata.TAG_NAME), metadata.getValue(TaskToTagMetadata.TAG_UUID));
} else {
// This is necessary for backwards compatibility
tagService.createLink(task, metadata.getValue(TaskToTagMetadata.TAG_NAME));
createLink(task, metadata.getValue(TaskToTagMetadata.TAG_NAME));
}
} else {
metadataDao.persist(metadata);
@ -313,4 +317,22 @@ public class TaskService {
return task;
}
private void createLink(Task task, String tagName) {
TagData tagData = tagDataDao.getTagByName(tagName, TagData.NAME, TagData.UUID);
if (tagData == null) {
tagData = new TagData();
tagData.setName(tagName);
tagDataDao.persist(tagData);
}
createLink(task, tagData.getName(), tagData.getUUID());
}
private void createLink(Task task, String tagName, String tagUuid) {
Metadata link = TaskToTagMetadata.newTagMetadata(task.getId(), task.getUuid(), tagName, tagUuid);
if (metadataDao.update(Criterion.and(MetadataDao.MetadataCriteria.byTaskAndwithKey(task.getId(), TaskToTagMetadata.KEY),
TaskToTagMetadata.TASK_UUID.eq(task.getUUID()), TaskToTagMetadata.TAG_UUID.eq(tagUuid)), link) <= 0) {
metadataDao.createNew(link);
}
}
}

@ -31,6 +31,12 @@ import javax.inject.Inject;
public class TagCustomFilterCriteriaExposer extends InjectingBroadcastReceiver {
private static int[] default_tag_images = new int[] {
R.drawable.default_list_0,
R.drawable.default_list_1,
R.drawable.default_list_2,
R.drawable.default_list_3
};
private static final String IDENTIFIER_TAG_IS = "tag_is"; //$NON-NLS-1$
private static final String IDENTIFIER_TAG_CONTAINS = "tag_contains"; //$NON-NLS-1$
@ -65,7 +71,7 @@ public class TagCustomFilterCriteriaExposer extends InjectingBroadcastReceiver {
MetadataDao.MetadataCriteria.withKey(TaskToTagMetadata.KEY),
TaskToTagMetadata.TAG_NAME.eq("?"), Metadata.DELETION_DATE.eq(0))).toString(),
values, tagNames, tagNames,
((BitmapDrawable)r.getDrawable(TagService.getDefaultImageIDForTag(RemoteModel.NO_UUID))).getBitmap(),
((BitmapDrawable)r.getDrawable(getDefaultImageIDForTag(RemoteModel.NO_UUID))).getBitmap(),
context.getString(R.string.CFC_tag_name));
ret[j++] = criterion;
}
@ -81,7 +87,7 @@ public class TagCustomFilterCriteriaExposer extends InjectingBroadcastReceiver {
MetadataDao.MetadataCriteria.withKey(TaskToTagMetadata.KEY),
TaskToTagMetadata.TAG_NAME.like("%?%"), Metadata.DELETION_DATE.eq(0))).toString(),
context.getString(R.string.CFC_tag_contains_name), "",
((BitmapDrawable)r.getDrawable(TagService.getDefaultImageIDForTag(RemoteModel.NO_UUID))).getBitmap(),
((BitmapDrawable)r.getDrawable(getDefaultImageIDForTag(RemoteModel.NO_UUID))).getBitmap(),
context.getString(R.string.CFC_tag_contains_name));
ret[j] = criterion;
}
@ -92,4 +98,12 @@ public class TagCustomFilterCriteriaExposer extends InjectingBroadcastReceiver {
context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
}
private static int getDefaultImageIDForTag(String nameOrUUID) {
if (RemoteModel.NO_UUID.equals(nameOrUUID)) {
int random = (int)(Math.random()*4);
return default_tag_images[random];
}
return default_tag_images[(Math.abs(nameOrUUID.hashCode()))%4];
}
}

@ -16,6 +16,7 @@ import android.text.TextUtils;
import com.todoroo.andlib.service.ContextManager;
import com.todoroo.andlib.sql.Criterion;
import com.todoroo.andlib.sql.Query;
import com.todoroo.andlib.sql.QueryTemplate;
import com.todoroo.astrid.actfm.TagViewFragment;
import com.todoroo.astrid.api.AstridApiConstants;
@ -24,9 +25,11 @@ import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.api.FilterListItem;
import com.todoroo.astrid.api.FilterWithCustomIntent;
import com.todoroo.astrid.api.FilterWithUpdate;
import com.todoroo.astrid.dao.MetadataDao;
import com.todoroo.astrid.dao.TaskDao.TaskCriteria;
import com.todoroo.astrid.data.Metadata;
import com.todoroo.astrid.data.TagData;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.tags.TagService.Tag;
import org.tasks.R;
@ -134,7 +137,7 @@ public class TagFilterExposer extends InjectingBroadcastReceiver implements Astr
if (shouldAddUntagged) {
Filter untagged = new Filter(r.getString(R.string.tag_FEx_untagged),
r.getString(R.string.tag_FEx_untagged),
tagService.untaggedTemplate(),
untaggedTemplate(),
null);
filters.add(untagged);
}
@ -159,4 +162,11 @@ public class TagFilterExposer extends InjectingBroadcastReceiver implements Astr
return prepareFilters();
}
private QueryTemplate untaggedTemplate() {
return new QueryTemplate().where(Criterion.and(
Criterion.not(Task.UUID.in(Query.select(TaskToTagMetadata.TASK_UUID).from(Metadata.TABLE)
.where(Criterion.and(MetadataDao.MetadataCriteria.withKey(TaskToTagMetadata.KEY), Metadata.DELETION_DATE.eq(0))))),
TaskCriteria.isActive(),
TaskCriteria.isVisible()));
}
}

@ -17,22 +17,15 @@ import com.todoroo.andlib.sql.Join;
import com.todoroo.andlib.sql.Order;
import com.todoroo.andlib.sql.Query;
import com.todoroo.andlib.sql.QueryTemplate;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.dao.MetadataDao;
import com.todoroo.astrid.dao.MetadataDao.MetadataCriteria;
import com.todoroo.astrid.dao.TagDataDao;
import com.todoroo.astrid.dao.TaskDao.TaskCriteria;
import com.todoroo.astrid.data.Metadata;
import com.todoroo.astrid.data.RemoteModel;
import com.todoroo.astrid.data.TagData;
import com.todoroo.astrid.data.Task;
import org.tasks.R;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Singleton;
@ -46,13 +39,6 @@ import javax.inject.Singleton;
@Singleton
public final class TagService {
private static int[] default_tag_images = new int[] {
R.drawable.default_list_0,
R.drawable.default_list_1,
R.drawable.default_list_2,
R.drawable.default_list_3
};
private final MetadataDao metadataDao;
private final TagDataDao tagDataDao;
@ -74,6 +60,7 @@ public final class TagService {
* @author Tim Su <tim@todoroo.com>
*
*/
// TODO: get rid of this
public static final class Tag {
public String tag;
public String uuid;
@ -100,21 +87,6 @@ public final class TagService {
return new QueryTemplate().join(Join.inner(Metadata.TABLE.as("mtags"), Task.UUID.eq(Field.field("mtags." + TaskToTagMetadata.TASK_UUID.name))))
.where(fullCriterion);
}
}
public static Criterion tagEqIgnoreCase(String tag, Criterion additionalCriterion) {
return Criterion.and(
MetadataCriteria.withKey(TaskToTagMetadata.KEY), TaskToTagMetadata.TAG_NAME.eqCaseInsensitive(tag),
additionalCriterion);
}
public QueryTemplate untaggedTemplate() {
return new QueryTemplate().where(Criterion.and(
Criterion.not(Task.UUID.in(Query.select(TaskToTagMetadata.TASK_UUID).from(Metadata.TABLE)
.where(Criterion.and(MetadataCriteria.withKey(TaskToTagMetadata.KEY), Metadata.DELETION_DATE.eq(0))))),
TaskCriteria.isActive(),
TaskCriteria.isVisible()));
}
/**
@ -151,42 +123,6 @@ public final class TagService {
return tagData == null ? null : new Tag(tagData);
}
public void createLink(Task task, String tagName) {
TagData tagData = tagDataDao.getTagByName(tagName, TagData.NAME, TagData.UUID);
if (tagData == null) {
tagData = new TagData();
tagData.setName(tagName);
tagDataDao.persist(tagData);
}
createLink(task, tagData.getName(), tagData.getUUID());
}
public void createLink(Task task, String tagName, String tagUuid) {
Metadata link = TaskToTagMetadata.newTagMetadata(task.getId(), task.getUuid(), tagName, tagUuid);
if (metadataDao.update(Criterion.and(MetadataCriteria.byTaskAndwithKey(task.getId(), TaskToTagMetadata.KEY),
TaskToTagMetadata.TASK_UUID.eq(task.getUUID()), TaskToTagMetadata.TAG_UUID.eq(tagUuid)), link) <= 0) {
metadataDao.createNew(link);
}
}
/**
* Delete all links between the specified task and the list of tags
*/
public void deleteLinks(long taskId, String taskUuid, String[] tagUuids) {
Metadata deleteTemplate = new Metadata();
deleteTemplate.setTask(taskId); // Need this for recording changes in outstanding table
deleteTemplate.setDeletionDate(DateUtilities.now());
if (tagUuids != null) {
for (String uuid : tagUuids) {
// TODO: Right now this is in a loop because each deleteTemplate needs the individual tagUuid in order to record
// the outstanding entry correctly. If possible, this should be improved to a single query
deleteTemplate.setValue(TaskToTagMetadata.TAG_UUID, uuid); // Need this for recording changes in outstanding table
metadataDao.update(Criterion.and(MetadataCriteria.withKey(TaskToTagMetadata.KEY), Metadata.DELETION_DATE.eq(0),
TaskToTagMetadata.TASK_UUID.eq(taskUuid), TaskToTagMetadata.TAG_UUID.eq(uuid)), deleteTemplate);
}
}
}
/**
* Return tags on the given task
* @return cursor. PLEASE CLOSE THE CURSOR!
@ -199,29 +135,6 @@ public final class TagService {
return metadataDao.query(query);
}
/**
* Return tags as a list of strings separated by given separator
* @return empty string if no tags, otherwise string
*/
public String getTagsAsString(long taskId, String separator) {
StringBuilder tagBuilder = new StringBuilder();
TodorooCursor<Metadata> tags = getTags(taskId);
try {
int length = tags.getCount();
for (int i = 0; i < length; i++) {
tags.moveToNext();
Metadata metadata = new Metadata(tags);
tagBuilder.append(metadata.getValue(TaskToTagMetadata.TAG_NAME));
if (i < length - 1) {
tagBuilder.append(separator);
}
}
} finally {
tags.close();
}
return tagBuilder.toString();
}
/**
* Return all tags (including metadata tags and TagData tags) in an array list
*/
@ -238,41 +151,6 @@ public final class TagService {
return tagList;
}
/**
* Save the given array of tags into the database
*/
public void synchronizeTags(long taskId, String taskUuid, Set<String> tags) {
HashSet<String> existingLinks = new HashSet<>();
TodorooCursor<Metadata> links = metadataDao.query(Query.select(Metadata.PROPERTIES)
.where(Criterion.and(TaskToTagMetadata.TASK_UUID.eq(taskUuid), Metadata.DELETION_DATE.eq(0))));
try {
for (links.moveToFirst(); !links.isAfterLast(); links.moveToNext()) {
Metadata link = new Metadata(links);
existingLinks.add(link.getValue(TaskToTagMetadata.TAG_UUID));
}
} finally {
links.close();
}
for (String tag : tags) {
TagData tagData = tagDataDao.getTagByName(tag, TagData.NAME, TagData.UUID);
if (tagData == null) {
tagData = new TagData();
tagData.setName(tag);
tagDataDao.persist(tagData);
}
if (existingLinks.contains(tagData.getUUID())) {
existingLinks.remove(tagData.getUUID());
} else {
Metadata newLink = TaskToTagMetadata.newTagMetadata(taskId, taskUuid, tag, tagData.getUUID());
metadataDao.createNew(newLink);
}
}
// Mark as deleted links that don't exist anymore
deleteLinks(taskId, taskUuid, existingLinks.toArray(new String[existingLinks.size()]));
}
/**
* If a tag already exists in the database that case insensitively matches the
* given tag, return that. Otherwise, return the argument
@ -297,6 +175,12 @@ public final class TagService {
return tagWithCase;
}
private static Criterion tagEqIgnoreCase(String tag, Criterion additionalCriterion) {
return Criterion.and(
MetadataCriteria.withKey(TaskToTagMetadata.KEY), TaskToTagMetadata.TAG_NAME.eqCaseInsensitive(tag),
additionalCriterion);
}
public int rename(String uuid, String newName) {
TagData template = new TagData();
template.setName(newName);
@ -307,12 +191,4 @@ public final class TagService {
return metadataDao.update(Criterion.and(MetadataCriteria.withKey(TaskToTagMetadata.KEY), TaskToTagMetadata.TAG_UUID.eq(uuid)), metadataTemplate);
}
public static int getDefaultImageIDForTag(String nameOrUUID) {
if (RemoteModel.NO_UUID.equals(nameOrUUID)) {
int random = (int)(Math.random()*4);
return default_tag_images[random];
}
return default_tag_images[(Math.abs(nameOrUUID.hashCode()))%4];
}
}

@ -25,8 +25,13 @@ import android.widget.TextView.OnEditorActionListener;
import com.todoroo.andlib.data.AbstractModel;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.sql.Criterion;
import com.todoroo.andlib.sql.Query;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.dao.MetadataDao;
import com.todoroo.astrid.dao.TagDataDao;
import com.todoroo.astrid.data.Metadata;
import com.todoroo.astrid.data.TagData;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.tags.TagService.Tag;
import com.todoroo.astrid.ui.PopupControlSet;
@ -37,8 +42,10 @@ import org.tasks.preferences.ActivityPreferences;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import static org.tasks.preferences.ResourceResolver.getResource;
@ -65,10 +72,14 @@ public final class TagsControlSet extends PopupControlSet {
//private final LinearLayout tagsContainer;
private final TextView tagsDisplay;
private final MetadataDao metadataDao;
private final TagDataDao tagDataDao;
private final TagService tagService;
public TagsControlSet(ActivityPreferences preferences, TagService tagService, Activity activity) {
public TagsControlSet(MetadataDao metadataDao, TagDataDao tagDataDao, ActivityPreferences preferences, TagService tagService, Activity activity) {
super(preferences, activity, R.layout.control_set_tags, R.layout.control_set_default_display, R.string.TEA_tags_label_long);
this.metadataDao = metadataDao;
this.tagDataDao = tagDataDao;
this.tagService = tagService;
tagsDisplay = (TextView) getDisplayView().findViewById(R.id.display_row_edit);
image = (ImageView) getDisplayView().findViewById(R.id.display_row_icon);
@ -308,7 +319,7 @@ public final class TagsControlSet extends PopupControlSet {
LinkedHashSet<String> tags = getTagSet();
tagService.synchronizeTags(task.getId(), task.getUUID(), tags);
synchronizeTags(task.getId(), task.getUUID(), tags);
Flags.set(Flags.TAGS_CHANGED);
task.setModificationDate(DateUtilities.now());
}
@ -326,4 +337,57 @@ public final class TagsControlSet extends PopupControlSet {
image.setImageResource(R.drawable.tea_icn_lists_gray);
}
}
/**
* Save the given array of tags into the database
*/
private void synchronizeTags(long taskId, String taskUuid, Set<String> tags) {
HashSet<String> existingLinks = new HashSet<>();
TodorooCursor<Metadata> links = metadataDao.query(Query.select(Metadata.PROPERTIES)
.where(Criterion.and(TaskToTagMetadata.TASK_UUID.eq(taskUuid), Metadata.DELETION_DATE.eq(0))));
try {
for (links.moveToFirst(); !links.isAfterLast(); links.moveToNext()) {
Metadata link = new Metadata(links);
existingLinks.add(link.getValue(TaskToTagMetadata.TAG_UUID));
}
} finally {
links.close();
}
for (String tag : tags) {
TagData tagData = tagDataDao.getTagByName(tag, TagData.NAME, TagData.UUID);
if (tagData == null) {
tagData = new TagData();
tagData.setName(tag);
tagDataDao.persist(tagData);
}
if (existingLinks.contains(tagData.getUUID())) {
existingLinks.remove(tagData.getUUID());
} else {
Metadata newLink = TaskToTagMetadata.newTagMetadata(taskId, taskUuid, tag, tagData.getUUID());
metadataDao.createNew(newLink);
}
}
// Mark as deleted links that don't exist anymore
deleteLinks(taskId, taskUuid, existingLinks.toArray(new String[existingLinks.size()]));
}
/**
* Delete all links between the specified task and the list of tags
*/
private void deleteLinks(long taskId, String taskUuid, String[] tagUuids) {
Metadata deleteTemplate = new Metadata();
deleteTemplate.setTask(taskId); // Need this for recording changes in outstanding table
deleteTemplate.setDeletionDate(DateUtilities.now());
if (tagUuids != null) {
for (String uuid : tagUuids) {
// TODO: Right now this is in a loop because each deleteTemplate needs the individual tagUuid in order to record
// the outstanding entry correctly. If possible, this should be improved to a single query
deleteTemplate.setValue(TaskToTagMetadata.TAG_UUID, uuid); // Need this for recording changes in outstanding table
metadataDao.update(Criterion.and(MetadataDao.MetadataCriteria.withKey(TaskToTagMetadata.KEY), Metadata.DELETION_DATE.eq(0),
TaskToTagMetadata.TASK_UUID.eq(taskUuid), TaskToTagMetadata.TAG_UUID.eq(uuid)), deleteTemplate);
}
}
}
}

Loading…
Cancel
Save