1
0
mirror of https://github.com/moparisthebest/k-9 synced 2024-11-30 13:12:25 -05:00

Whitespace cleanup

This commit is contained in:
cketti 2012-10-16 22:42:51 +02:00
parent 83d5102f3d
commit f1e433e6df
10 changed files with 930 additions and 930 deletions

View File

@ -426,18 +426,18 @@ public class Accounts extends K9ListActivity implements OnItemClickListener {
* Creates and initializes the special accounts ('Unified Inbox' and 'All Messages') * Creates and initializes the special accounts ('Unified Inbox' and 'All Messages')
*/ */
private void createSpecialAccounts() { private void createSpecialAccounts() {
// create the unified inbox meta account ( all accounts is default when none specified ) // create the unified inbox meta account ( all accounts is default when none specified )
String name = getString(R.string.integrated_inbox_title); String name = getString(R.string.integrated_inbox_title);
LocalSearch tmpSearch = new LocalSearch(name); LocalSearch tmpSearch = new LocalSearch(name);
tmpSearch.addAllowedFolder(SearchSpecification.GENERIC_INBOX_NAME); tmpSearch.addAllowedFolder(SearchSpecification.GENERIC_INBOX_NAME);
integratedInboxAccount = new SearchAccount(tmpSearch, name, integratedInboxAccount = new SearchAccount(tmpSearch, name,
getString(R.string.integrated_inbox_detail)); getString(R.string.integrated_inbox_detail));
// create the all messages search ( all accounts is default when none specified ) // create the all messages search ( all accounts is default when none specified )
name = getString(R.string.search_all_messages_title); name = getString(R.string.search_all_messages_title);
tmpSearch = new LocalSearch(name); tmpSearch = new LocalSearch(name);
unreadAccount = new SearchAccount(tmpSearch, name, unreadAccount = new SearchAccount(tmpSearch, name,
getString(R.string.search_all_messages_detail)); getString(R.string.search_all_messages_detail));
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -563,7 +563,7 @@ public class Accounts extends K9ListActivity implements OnItemClickListener {
final SearchAccount searchAccount = (SearchAccount)account; final SearchAccount searchAccount = (SearchAccount)account;
MessagingController.getInstance(getApplication()) MessagingController.getInstance(getApplication())
.searchLocalMessages(searchAccount.getRelatedSearch(), new MessagingListener() { .searchLocalMessages(searchAccount.getRelatedSearch(), new MessagingListener() {
@Override @Override
public void searchStats(AccountStats stats) { public void searchStats(AccountStats stats) {
mListener.accountStatusChanged(searchAccount, stats); mListener.accountStatusChanged(searchAccount, stats);
@ -637,9 +637,9 @@ public class Accounts extends K9ListActivity implements OnItemClickListener {
if (K9.FOLDER_NONE.equals(realAccount.getAutoExpandFolderName())) { if (K9.FOLDER_NONE.equals(realAccount.getAutoExpandFolderName())) {
FolderList.actionHandleAccount(this, realAccount); FolderList.actionHandleAccount(this, realAccount);
} else { } else {
LocalSearch search = new LocalSearch(realAccount.getAutoExpandFolderName()); LocalSearch search = new LocalSearch(realAccount.getAutoExpandFolderName());
search.addAllowedFolder(realAccount.getAutoExpandFolderName()); search.addAllowedFolder(realAccount.getAutoExpandFolderName());
search.addAccountUuid(realAccount.getUuid()); search.addAccountUuid(realAccount.getUuid());
MessageList.actionDisplaySearch(this, search, true);} MessageList.actionDisplaySearch(this, search, true);}
} }
return true; return true;
@ -1786,18 +1786,18 @@ public class Accounts extends K9ListActivity implements OnItemClickListener {
public void onClick(View v) { public void onClick(View v) {
final String description = getString(R.string.search_title, account.getDescription(), getString(searchModifier.resId)); final String description = getString(R.string.search_title, account.getDescription(), getString(searchModifier.resId));
LocalSearch search = null; LocalSearch search = null;
if (account instanceof SearchAccount) { if (account instanceof SearchAccount) {
search = ((SearchAccount) account).getRelatedSearch(); search = ((SearchAccount) account).getRelatedSearch();
search.setName(description); search.setName(description);
} else { } else {
search = new LocalSearch(description); search = new LocalSearch(description);
search.addAccountUuid(account.getUuid()); search.addAccountUuid(account.getUuid());
} }
search.allRequiredFlags(searchModifier.requiredFlags); search.allRequiredFlags(searchModifier.requiredFlags);
search.allForbiddenFlags(searchModifier.forbiddenFlags); search.allForbiddenFlags(searchModifier.forbiddenFlags);
MessageList.actionDisplaySearch(Accounts.this, search, false); MessageList.actionDisplaySearch(Accounts.this, search, false);
} }
} }

View File

@ -622,9 +622,9 @@ public class FolderList extends K9ListActivity implements OnNavigationListener {
} }
private void onOpenFolder(String folder) { private void onOpenFolder(String folder) {
LocalSearch search = new LocalSearch(folder); LocalSearch search = new LocalSearch(folder);
search.addAccountUuid(mAccount.getUuid()); search.addAccountUuid(mAccount.getUuid());
search.addAllowedFolder(folder); search.addAllowedFolder(folder);
MessageList.actionDisplaySearch(this, search, false); MessageList.actionDisplaySearch(this, search, false);
} }
@ -1265,18 +1265,18 @@ public class FolderList extends K9ListActivity implements OnNavigationListener {
final String description = getString(R.string.search_title, final String description = getString(R.string.search_title,
getString(R.string.message_list_title, account.getDescription(), displayName), getString(R.string.message_list_title, account.getDescription(), displayName),
getString(searchModifier.resId)); getString(searchModifier.resId));
LocalSearch search = new LocalSearch(description); LocalSearch search = new LocalSearch(description);
try { try {
search.allRequiredFlags(searchModifier.requiredFlags); search.allRequiredFlags(searchModifier.requiredFlags);
search.allForbiddenFlags(searchModifier.forbiddenFlags); search.allForbiddenFlags(searchModifier.forbiddenFlags);
} catch (Exception e) { } catch (Exception e) {
// TODO Auto-generated catch block // TODO Auto-generated catch block
e.printStackTrace(); e.printStackTrace();
} }
search.addAllowedFolder(folderName); search.addAllowedFolder(folderName);
search.addAccountUuid(account.getUuid()); search.addAccountUuid(account.getUuid());
MessageList.actionDisplaySearch(FolderList.this, search, false); MessageList.actionDisplaySearch(FolderList.this, search, false);
} }
} }
@ -1285,11 +1285,11 @@ public class FolderList extends K9ListActivity implements OnNavigationListener {
LocalSearch search = new LocalSearch(description); LocalSearch search = new LocalSearch(description);
search.addAccountUuid(account.getUuid()); search.addAccountUuid(account.getUuid());
try { try {
search.allRequiredFlags(new Flag[]{Flag.SEEN}); search.allRequiredFlags(new Flag[]{Flag.SEEN});
} catch (Exception e) { } catch (Exception e) {
// TODO Auto-generated catch block // TODO Auto-generated catch block
e.printStackTrace(); e.printStackTrace();
} }
} }
} }

View File

@ -48,8 +48,8 @@ import com.fsck.k9.search.SearchSpecification.SearchCondition;
*/ */
public class MessageList extends K9FragmentActivity implements MessageListFragmentListener, public class MessageList extends K9FragmentActivity implements MessageListFragmentListener,
OnBackStackChangedListener, OnSwipeGestureListener { OnBackStackChangedListener, OnSwipeGestureListener {
// for this activity // for this activity
private static final String EXTRA_SEARCH = "search"; private static final String EXTRA_SEARCH = "search";
// used for remote search // used for remote search
@ -59,22 +59,22 @@ public class MessageList extends K9FragmentActivity implements MessageListFragme
public static void actionDisplaySearch(Context context, SearchSpecification search, boolean newTask) { public static void actionDisplaySearch(Context context, SearchSpecification search, boolean newTask) {
actionDisplaySearch(context, search, newTask, true); actionDisplaySearch(context, search, newTask, true);
} }
public static void actionDisplaySearch(Context context, SearchSpecification search, boolean newTask, boolean clearTop) { public static void actionDisplaySearch(Context context, SearchSpecification search, boolean newTask, boolean clearTop) {
context.startActivity(intentDisplaySearch(context, search, newTask, clearTop)); context.startActivity(intentDisplaySearch(context, search, newTask, clearTop));
} }
public static Intent intentDisplaySearch(Context context, SearchSpecification search, boolean newTask, boolean clearTop) { public static Intent intentDisplaySearch(Context context, SearchSpecification search, boolean newTask, boolean clearTop) {
Intent intent = new Intent(context, MessageList.class); Intent intent = new Intent(context, MessageList.class);
intent.putExtra(EXTRA_SEARCH, search); intent.putExtra(EXTRA_SEARCH, search);
if (clearTop) { if (clearTop) {
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
} }
if (newTask) { if (newTask) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
} }
return intent; return intent;
} }
@ -91,11 +91,11 @@ public class MessageList extends K9FragmentActivity implements MessageListFragme
private Account mAccount; private Account mAccount;
private String mFolderName; private String mFolderName;
private LocalSearch mSearch; private LocalSearch mSearch;
private boolean mSingleFolderMode; private boolean mSingleFolderMode;
private boolean mSingleAccountMode; private boolean mSingleAccountMode;
private boolean mIsRemote; private boolean mIsRemote;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -123,8 +123,8 @@ public class MessageList extends K9FragmentActivity implements MessageListFragme
} }
private void decodeExtras(Intent intent) { private void decodeExtras(Intent intent) {
// check if this intent comes from the system search ( remote ) // check if this intent comes from the system search ( remote )
if (intent.getStringExtra(SearchManager.QUERY) != null) { if (intent.getStringExtra(SearchManager.QUERY) != null) {
if (Intent.ACTION_SEARCH.equals(intent.getAction())) { if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
//Query was received from Search Dialog //Query was received from Search Dialog
Bundle appData = getIntent().getBundleExtra(SearchManager.APP_DATA); Bundle appData = getIntent().getBundleExtra(SearchManager.APP_DATA);
@ -132,40 +132,40 @@ public class MessageList extends K9FragmentActivity implements MessageListFragme
mSearch = new LocalSearch(); mSearch = new LocalSearch();
mSearch.addAccountUuid(appData.getString(EXTRA_SEARCH_ACCOUNT)); mSearch.addAccountUuid(appData.getString(EXTRA_SEARCH_ACCOUNT));
mSearch.addAllowedFolder(appData.getString(EXTRA_SEARCH_FOLDER)); mSearch.addAllowedFolder(appData.getString(EXTRA_SEARCH_FOLDER));
String query = intent.getStringExtra(SearchManager.QUERY); String query = intent.getStringExtra(SearchManager.QUERY);
mSearch.or(new SearchCondition(SEARCHFIELD.SENDER, ATTRIBUTE.CONTAINS, query)); mSearch.or(new SearchCondition(SEARCHFIELD.SENDER, ATTRIBUTE.CONTAINS, query));
mSearch.or(new SearchCondition(SEARCHFIELD.SUBJECT, ATTRIBUTE.CONTAINS, query)); mSearch.or(new SearchCondition(SEARCHFIELD.SUBJECT, ATTRIBUTE.CONTAINS, query));
mIsRemote = true; mIsRemote = true;
} }
} }
} else { } else {
// regular LocalSearch object was passed // regular LocalSearch object was passed
mSearch = intent.getParcelableExtra(EXTRA_SEARCH); mSearch = intent.getParcelableExtra(EXTRA_SEARCH);
} }
String[] accounts = mSearch.getAccountUuids(); String[] accounts = mSearch.getAccountUuids();
mSingleAccountMode = ( accounts != null && accounts.length == 1 mSingleAccountMode = ( accounts != null && accounts.length == 1
&& !accounts[0].equals(SearchSpecification.ALL_ACCOUNTS)); && !accounts[0].equals(SearchSpecification.ALL_ACCOUNTS));
mSingleFolderMode = mSingleAccountMode && (mSearch.getFolderNames().size() == 1); mSingleFolderMode = mSingleAccountMode && (mSearch.getFolderNames().size() == 1);
if (mSingleAccountMode) { if (mSingleAccountMode) {
mAccount = Preferences.getPreferences(this).getAccount(accounts[0]); mAccount = Preferences.getPreferences(this).getAccount(accounts[0]);
if (mAccount != null && !mAccount.isAvailable(this)) { if (mAccount != null && !mAccount.isAvailable(this)) {
Log.i(K9.LOG_TAG, "not opening MessageList of unavailable account"); Log.i(K9.LOG_TAG, "not opening MessageList of unavailable account");
onAccountUnavailable(); onAccountUnavailable();
return; return;
} }
} }
if (mSingleFolderMode) { if (mSingleFolderMode) {
mFolderName = mSearch.getFolderNames().get(0); mFolderName = mSearch.getFolderNames().get(0);
} }
// now we know if we are in single account mode and need a subtitle // now we know if we are in single account mode and need a subtitle
mActionBarSubTitle.setVisibility((!mSingleFolderMode) ? View.GONE : View.VISIBLE); mActionBarSubTitle.setVisibility((!mSingleFolderMode) ? View.GONE : View.VISIBLE);
} }
@Override @Override
@ -329,10 +329,10 @@ public class MessageList extends K9FragmentActivity implements MessageListFragme
if (fragmentManager.getBackStackEntryCount() > 0) { if (fragmentManager.getBackStackEntryCount() > 0) {
fragmentManager.popBackStack(); fragmentManager.popBackStack();
} else if (!mSingleFolderMode) { } else if (!mSingleFolderMode) {
onBackPressed(); onBackPressed();
} else { } else {
onShowFolderList(); onShowFolderList();
} }
return true; return true;
} }
case R.id.compose: { case R.id.compose: {
@ -581,10 +581,10 @@ public class MessageList extends K9FragmentActivity implements MessageListFragme
@Override @Override
public void showMoreFromSameSender(String senderAddress) { public void showMoreFromSameSender(String senderAddress) {
LocalSearch tmpSearch = new LocalSearch("From " + senderAddress); LocalSearch tmpSearch = new LocalSearch("From " + senderAddress);
tmpSearch.addAccountUuids(mSearch.getAccountUuids()); tmpSearch.addAccountUuids(mSearch.getAccountUuids());
tmpSearch.and(SEARCHFIELD.SENDER, senderAddress, ATTRIBUTE.CONTAINS); tmpSearch.and(SEARCHFIELD.SENDER, senderAddress, ATTRIBUTE.CONTAINS);
MessageListFragment fragment = MessageListFragment.newInstance(tmpSearch, false); MessageListFragment fragment = MessageListFragment.newInstance(tmpSearch, false);
addMessageListFragment(fragment); addMessageListFragment(fragment);
@ -668,10 +668,10 @@ public class MessageList extends K9FragmentActivity implements MessageListFragme
@Override @Override
public void showThread(Account account, String folderName, long threadRootId) { public void showThread(Account account, String folderName, long threadRootId) {
LocalSearch tmpSearch = new LocalSearch(); LocalSearch tmpSearch = new LocalSearch();
tmpSearch.addAccountUuids(mSearch.getAccountUuids()); tmpSearch.addAccountUuids(mSearch.getAccountUuids());
tmpSearch.and(SEARCHFIELD.THREAD_ROOT, String.valueOf(threadRootId), ATTRIBUTE.EQUALS); tmpSearch.and(SEARCHFIELD.THREAD_ROOT, String.valueOf(threadRootId), ATTRIBUTE.EQUALS);
MessageListFragment fragment = MessageListFragment.newInstance(tmpSearch, false); MessageListFragment fragment = MessageListFragment.newInstance(tmpSearch, false);
addMessageListFragment(fragment); addMessageListFragment(fragment);
} }

View File

@ -632,20 +632,20 @@ public class MessagingController implements Runnable {
} }
}); });
} }
public void searchLocalMessagesSynchronous(final LocalSearch search, final MessagingListener listener) { public void searchLocalMessagesSynchronous(final LocalSearch search, final MessagingListener listener) {
final AccountStats stats = new AccountStats(); final AccountStats stats = new AccountStats();
final HashSet<String> uuidSet = new HashSet<String>(Arrays.asList(search.getAccountUuids())); final HashSet<String> uuidSet = new HashSet<String>(Arrays.asList(search.getAccountUuids()));
Account[] accounts = Preferences.getPreferences(mApplication.getApplicationContext()).getAccounts(); Account[] accounts = Preferences.getPreferences(mApplication.getApplicationContext()).getAccounts();
boolean allAccounts = uuidSet.contains(SearchSpecification.ALL_ACCOUNTS); boolean allAccounts = uuidSet.contains(SearchSpecification.ALL_ACCOUNTS);
// for every account we want to search do the query in the localstore // for every account we want to search do the query in the localstore
for (final Account account : accounts) { for (final Account account : accounts) {
if (!allAccounts && !uuidSet.contains(account.getUuid())) { if (!allAccounts && !uuidSet.contains(account.getUuid())) {
continue; continue;
} }
// Collecting statistics of the search result // Collecting statistics of the search result
MessageRetrievalListener retrievalListener = new MessageRetrievalListener() { MessageRetrievalListener retrievalListener = new MessageRetrievalListener() {
@Override @Override
@ -666,15 +666,15 @@ public class MessagingController implements Runnable {
} }
} }
}; };
// alert everyone the search has started // alert everyone the search has started
if (listener != null) { if (listener != null) {
listener.listLocalMessagesStarted(account, null); listener.listLocalMessagesStarted(account, null);
} }
// build and do the query in the localstore // build and do the query in the localstore
try { try {
LocalStore localStore = account.getLocalStore(); LocalStore localStore = account.getLocalStore();
localStore.searchForMessages(retrievalListener, search); localStore.searchForMessages(retrievalListener, search);
} catch (Exception e) { } catch (Exception e) {
if (listener != null) { if (listener != null) {
@ -686,9 +686,9 @@ public class MessagingController implements Runnable {
listener.listLocalMessagesFinished(account, null); listener.listLocalMessagesFinished(account, null);
} }
} }
} }
// publish the total search statistics // publish the total search statistics
if (listener != null) { if (listener != null) {
listener.searchStats(stats); listener.searchStats(stats);
} }
@ -3164,7 +3164,7 @@ public class MessagingController implements Runnable {
search.addAllowedFolder(account.getInboxFolderName()); search.addAllowedFolder(account.getInboxFolderName());
search.addAccountUuid(account.getUuid()); search.addAccountUuid(account.getUuid());
Intent intent = MessageList.intentDisplaySearch(mApplication, search, true, true); Intent intent = MessageList.intentDisplaySearch(mApplication, search, true, true);
PendingIntent pi = PendingIntent.getActivity(mApplication, 0, intent, 0); PendingIntent pi = PendingIntent.getActivity(mApplication, 0, intent, 0);
builder.setContentIntent(pi); builder.setContentIntent(pi);
@ -3250,7 +3250,7 @@ public class MessagingController implements Runnable {
search.addAllowedFolder(account.getInboxFolderName()); search.addAllowedFolder(account.getInboxFolderName());
search.addAccountUuid(account.getUuid()); search.addAccountUuid(account.getUuid());
Intent intent = MessageList.intentDisplaySearch(mApplication, search, true, true); Intent intent = MessageList.intentDisplaySearch(mApplication, search, true, true);
PendingIntent pi = PendingIntent.getActivity(mApplication, 0, intent, 0); PendingIntent pi = PendingIntent.getActivity(mApplication, 0, intent, 0);
builder.setContentIntent(pi); builder.setContentIntent(pi);

View File

@ -667,16 +667,16 @@ public class LocalStore extends Store implements Serializable {
public Long doDbWork(final SQLiteDatabase db) { public Long doDbWork(final SQLiteDatabase db) {
Cursor cursor = null; Cursor cursor = null;
try { try {
cursor = db.rawQuery("SELECT id FROM folders WHERE name = '" + name + "'", null); cursor = db.rawQuery("SELECT id FROM folders WHERE name = '" + name + "'", null);
cursor.moveToFirst(); cursor.moveToFirst();
return cursor.getLong(0); return cursor.getLong(0);
} finally { } finally {
Utility.closeQuietly(cursor); Utility.closeQuietly(cursor);
} }
} }
}); });
} }
// TODO this takes about 260-300ms, seems slow. // TODO this takes about 260-300ms, seems slow.
@Override @Override
public List <? extends Folder > getPersonalNamespaces(boolean forceListAll) throws MessagingException { public List <? extends Folder > getPersonalNamespaces(boolean forceListAll) throws MessagingException {
@ -920,7 +920,7 @@ public class LocalStore extends Store implements Serializable {
} }
int i = 0; int i = 0;
if (str.charAt(0) == '-') { if (str.charAt(0) == '-') {
return false; return false;
} }
for (; i < length; i++) { for (; i < length; i++) {
char c = str.charAt(i); char c = str.charAt(i);
@ -930,36 +930,36 @@ public class LocalStore extends Store implements Serializable {
} }
return true; return true;
} }
public Message[] searchForMessages(MessageRetrievalListener retrievalListener,
LocalSearch search) throws MessagingException {
// update some references in the search that have to be bound to this one store
for (ConditionsTreeNode node : search.getLeafSet()) {
if (node.mCondition.field == SEARCHFIELD.FOLDER) {
// TODO find better solution
if (isFolderId(node.mCondition.value)) {
continue;
}
if (node.mCondition.value.equals(LocalSearch.GENERIC_INBOX_NAME)) {
node.mCondition.value = mAccount.getInboxFolderName();
}
node.mCondition.value = String.valueOf(getFolderId(node.mCondition.value));
}
}
// build sql query public Message[] searchForMessages(MessageRetrievalListener retrievalListener,
String sqlQuery = "SELECT " + GET_MESSAGES_COLS + "FROM messages WHERE deleted = 0 " LocalSearch search) throws MessagingException {
+ (search.getConditions() != null ? "AND (" + search.getConditions() + ")" : "") + " ORDER BY date DESC";
// update some references in the search that have to be bound to this one store
for (ConditionsTreeNode node : search.getLeafSet()) {
if (node.mCondition.field == SEARCHFIELD.FOLDER) {
// TODO find better solution
if (isFolderId(node.mCondition.value)) {
continue;
}
if (node.mCondition.value.equals(LocalSearch.GENERIC_INBOX_NAME)) {
node.mCondition.value = mAccount.getInboxFolderName();
}
node.mCondition.value = String.valueOf(getFolderId(node.mCondition.value));
}
}
// build sql query
String sqlQuery = "SELECT " + GET_MESSAGES_COLS + "FROM messages WHERE deleted = 0 "
+ (search.getConditions() != null ? "AND (" + search.getConditions() + ")" : "") + " ORDER BY date DESC";
if (K9.DEBUG) { if (K9.DEBUG) {
Log.d(K9.LOG_TAG, "Query = " + sqlQuery); Log.d(K9.LOG_TAG, "Query = " + sqlQuery);
} }
return getMessages(retrievalListener, null, sqlQuery, new String[] {}); return getMessages(retrievalListener, null, sqlQuery, new String[] {});
} }
/* /*
* Given a query string, actually do the query for the messages and * Given a query string, actually do the query for the messages and
* call the MessageRetrievalListener for each one * call the MessageRetrievalListener for each one

View File

@ -63,9 +63,9 @@ public class UnreadWidgetProvider extends AppWidgetProvider {
clickIntent = FolderList.actionHandleAccountIntent(context, account, null, clickIntent = FolderList.actionHandleAccountIntent(context, account, null,
false); false);
} else { } else {
LocalSearch search = new LocalSearch(account.getAutoExpandFolderName()); LocalSearch search = new LocalSearch(account.getAutoExpandFolderName());
search.addAllowedFolder(account.getAutoExpandFolderName()); search.addAllowedFolder(account.getAutoExpandFolderName());
search.addAccountUuid(account.getUuid()); search.addAccountUuid(account.getUuid());
clickIntent = MessageList.intentDisplaySearch(context, search, true, true); clickIntent = MessageList.intentDisplaySearch(context, search, true, true);
} }
clickIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); clickIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);

View File

@ -14,388 +14,388 @@ import com.fsck.k9.search.SearchSpecification.SEARCHFIELD;
import com.fsck.k9.search.SearchSpecification.SearchCondition; import com.fsck.k9.search.SearchSpecification.SearchCondition;
/** /**
* This class stores search conditions. It's basically a boolean expression binary tree. * This class stores search conditions. It's basically a boolean expression binary tree.
* The output will be SQL queries ( obtained by traversing inorder ). * The output will be SQL queries ( obtained by traversing inorder ).
* *
* TODO removing conditions from the tree * TODO removing conditions from the tree
* TODO implement NOT as a node again * TODO implement NOT as a node again
* *
* @author dzan * @author dzan
*/ */
public class ConditionsTreeNode implements Parcelable{ public class ConditionsTreeNode implements Parcelable{
public enum OPERATOR { public enum OPERATOR {
AND, OR, CONDITION; AND, OR, CONDITION;
} }
public ConditionsTreeNode mLeft; public ConditionsTreeNode mLeft;
public ConditionsTreeNode mRight; public ConditionsTreeNode mRight;
public ConditionsTreeNode mParent; public ConditionsTreeNode mParent;
/* /*
* If mValue isn't CONDITION then mCondition contains a real * If mValue isn't CONDITION then mCondition contains a real
* condition, otherwise it's null. * condition, otherwise it's null.
*/ */
public OPERATOR mValue; public OPERATOR mValue;
public SearchCondition mCondition; public SearchCondition mCondition;
/* /*
* Used for storing and retrieving the tree to/from the database. * Used for storing and retrieving the tree to/from the database.
* The algorithm is called "modified preorder tree traversal". * The algorithm is called "modified preorder tree traversal".
*/ */
public int mLeftMPTTMarker; public int mLeftMPTTMarker;
public int mRightMPTTMarker; public int mRightMPTTMarker;
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
// Static Helpers to restore a tree from a database cursor // Static Helpers to restore a tree from a database cursor
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
/** /**
* Builds a condition tree starting from a database cursor. The cursor * Builds a condition tree starting from a database cursor. The cursor
* should point to rows representing the nodes of the tree. * should point to rows representing the nodes of the tree.
* *
* @param cursor Cursor pointing to the first of a bunch or rows. Each rows * @param cursor Cursor pointing to the first of a bunch or rows. Each rows
* should contains 1 tree node. * should contains 1 tree node.
* @return A condition tree. * @return A condition tree.
*/ */
public static ConditionsTreeNode buildTreeFromDB(Cursor cursor) { public static ConditionsTreeNode buildTreeFromDB(Cursor cursor) {
Stack<ConditionsTreeNode> stack = new Stack<ConditionsTreeNode>(); Stack<ConditionsTreeNode> stack = new Stack<ConditionsTreeNode>();
ConditionsTreeNode tmp = null; ConditionsTreeNode tmp = null;
// root node // root node
if (cursor.moveToFirst()) { if (cursor.moveToFirst()) {
tmp = buildNodeFromRow(cursor); tmp = buildNodeFromRow(cursor);
stack.push(tmp); stack.push(tmp);
} }
// other nodes // other nodes
while (cursor.moveToNext()) { while (cursor.moveToNext()) {
tmp = buildNodeFromRow(cursor); tmp = buildNodeFromRow(cursor);
if (tmp.mRightMPTTMarker < stack.peek().mRightMPTTMarker ){ if (tmp.mRightMPTTMarker < stack.peek().mRightMPTTMarker ){
stack.peek().mLeft = tmp; stack.peek().mLeft = tmp;
stack.push(tmp); stack.push(tmp);
} else { } else {
while (stack.peek().mRightMPTTMarker < tmp.mRightMPTTMarker) { while (stack.peek().mRightMPTTMarker < tmp.mRightMPTTMarker) {
stack.pop(); stack.pop();
} }
stack.peek().mRight = tmp; stack.peek().mRight = tmp;
} }
} }
return tmp; return tmp;
}
/**
* Converts a single database row to a single condition node.
*
* @param cursor Cursor pointing to the row we want to convert.
* @return A single ConditionsTreeNode
*/
private static ConditionsTreeNode buildNodeFromRow(Cursor cursor) {
ConditionsTreeNode result = null;
SearchCondition condition = null;
OPERATOR tmpValue = ConditionsTreeNode.OPERATOR.valueOf(cursor.getString(5));
if (tmpValue == OPERATOR.CONDITION) {
condition = new SearchCondition(SEARCHFIELD.valueOf(cursor.getString(0)),
ATTRIBUTE.valueOf(cursor.getString(2)), cursor.getString(1));
}
result = new ConditionsTreeNode(condition);
result.mValue = tmpValue;
result.mLeftMPTTMarker = cursor.getInt(3);
result.mRightMPTTMarker = cursor.getInt(4);
return result;
} }
///////////////////////////////////////////////////////////////
// Constructors
///////////////////////////////////////////////////////////////
public ConditionsTreeNode(SearchCondition condition) {
mParent = null;
mCondition = condition;
mValue = OPERATOR.CONDITION;
}
public ConditionsTreeNode(ConditionsTreeNode parent, OPERATOR op) { /**
mParent = parent; * Converts a single database row to a single condition node.
mValue = op; *
mCondition = null; * @param cursor Cursor pointing to the row we want to convert.
} * @return A single ConditionsTreeNode
*/
private static ConditionsTreeNode buildNodeFromRow(Cursor cursor) {
/////////////////////////////////////////////////////////////// ConditionsTreeNode result = null;
// Public modifiers SearchCondition condition = null;
///////////////////////////////////////////////////////////////
/**
* Adds the expression as the second argument of an AND
* clause to this node.
*
* @param expr Expression to 'AND' with.
* @return New top AND node.
* @throws Exception
*/
public ConditionsTreeNode and(ConditionsTreeNode expr) throws Exception {
return add(expr, OPERATOR.AND);
}
/**
* Convenience method.
* Adds the provided condition as the second argument of an AND
* clause to this node.
*
* @param condition Condition to 'AND' with.
* @return New top AND node, new root.
*/
public ConditionsTreeNode and(SearchCondition condition) {
try {
ConditionsTreeNode tmp = new ConditionsTreeNode(condition);
return and(tmp);
} catch (Exception e) {
// impossible
return null;
}
}
/**
* Adds the expression as the second argument of an OR
* clause to this node.
*
* @param expr Expression to 'OR' with.
* @return New top OR node.
* @throws Exception
*/
public ConditionsTreeNode or(ConditionsTreeNode expr) throws Exception {
return add(expr, OPERATOR.OR);
}
/**
* Convenience method.
* Adds the provided condition as the second argument of an OR
* clause to this node.
*
* @param condition Condition to 'OR' with.
* @return New top OR node, new root.
*/
public ConditionsTreeNode or(SearchCondition condition) {
try {
ConditionsTreeNode tmp = new ConditionsTreeNode(condition);
return or(tmp);
} catch (Exception e) {
// impossible
return null;
}
}
/**
* This applies the MPTT labeling to the subtree of which this node
* is the root node.
*
* For a description on MPTT see:
* http://www.sitepoint.com/hierarchical-data-database-2/
*/
public void applyMPTTLabel() {
applyMPTTLabel(1);
}
///////////////////////////////////////////////////////////////
// Public accessors
///////////////////////////////////////////////////////////////
/**
* Returns the condition stored in this node.
* @return Condition stored in the node.
*/
public SearchCondition getCondition() {
return mCondition;
}
/**
* This will traverse the tree inorder and call toString recursively resulting
* in a valid SQL where clause.
*/
@Override
public String toString() {
return (mLeft == null ? "" : "(" + mLeft + ")")
+ " " + ( mCondition == null ? mValue.name() : mCondition ) + " "
+ (mRight == null ? "" : "(" + mRight + ")") ;
}
/**
* Get a set of all the leaves in the tree.
* @return Set of all the leaves.
*/
public HashSet<ConditionsTreeNode> getLeafSet() {
HashSet<ConditionsTreeNode> leafSet = new HashSet<ConditionsTreeNode>();
return getLeafSet(leafSet);
}
/**
* Returns a list of all the nodes in the subtree of which this node
* is the root. The list contains the nodes in a pre traversal order.
*
* @return List of all nodes in subtree in preorder.
*/
public List<ConditionsTreeNode> preorder() {
ArrayList<ConditionsTreeNode> result = new ArrayList<ConditionsTreeNode>();
Stack<ConditionsTreeNode> stack = new Stack<ConditionsTreeNode>();
stack.push(this);
while(!stack.isEmpty()) {
ConditionsTreeNode current = stack.pop( );
if( current.mLeft != null ) stack.push( current.mLeft );
if( current.mRight != null ) stack.push( current.mRight );
result.add(current);
}
return result;
}
///////////////////////////////////////////////////////////////
// Private class logic
///////////////////////////////////////////////////////////////
/**
* Adds two new ConditionTreeNodes, one for the operator and one for the
* new condition. The current node will end up on the same level as the
* one provided in the arguments, they will be siblings. Their common
* parent node will be one containing the operator provided in the arguments.
* The method will update all the required references so the tree ends up in
* a valid state.
*
* This method only supports node arguments with a null parent node.
*
* @param Node to add.
* @param Operator that will connect the new node with this one.
* @return New parent node, containing the operator.
* @throws Exception Throws when the provided new node does not have a null parent.
*/
private ConditionsTreeNode add(ConditionsTreeNode node, OPERATOR op) throws Exception{
if (node.mParent != null) {
throw new Exception("Can only add new expressions from root node down.");
}
ConditionsTreeNode tmpNode = new ConditionsTreeNode(mParent, op);
tmpNode.mLeft = this;
tmpNode.mRight = node;
if (mParent != null) {
mParent.updateChild(this, tmpNode);
}
this.mParent = tmpNode;
node.mParent = tmpNode;
return tmpNode;
}
/** OPERATOR tmpValue = ConditionsTreeNode.OPERATOR.valueOf(cursor.getString(5));
* Helper method that replaces a child of the current node with a new node.
* If the provided old child node was the left one, left will be replaced with
* the new one. Same goes for the right one.
*
* @param oldChild Old child node to be replaced.
* @param newChild New child node.
*/
private void updateChild(ConditionsTreeNode oldChild, ConditionsTreeNode newChild) {
// we can compare objects id's because this is the desired behaviour in this case
if (mLeft == oldChild) {
mLeft = newChild;
} else if (mRight == oldChild) {
mRight = newChild;
}
}
/**
* Recursive function to gather all the leaves in the subtree of which
* this node is the root.
*
* @param leafSet Leafset that's being built.
* @return Set of leaves being completed.
*/
private HashSet<ConditionsTreeNode> getLeafSet(HashSet<ConditionsTreeNode> leafSet) {
// if we ended up in a leaf, add ourself and return
if (mLeft == null && mRight == null) {
leafSet.add(this);
return leafSet;
// we didn't end up in a leaf
} else {
if (mLeft != null) {
mLeft.getLeafSet(leafSet);
}
if (mRight != null) {
mRight.getLeafSet(leafSet);
}
return leafSet;
}
}
/**
* This applies the MPTT labeling to the subtree of which this node
* is the root node.
*
* For a description on MPTT see:
* http://www.sitepoint.com/hierarchical-data-database-2/
*/
private int applyMPTTLabel(int label) {
mLeftMPTTMarker = label;
if (mLeft != null){
label = mLeft.applyMPTTLabel(label += 1);
}
if (mRight != null){
label = mRight.applyMPTTLabel(label += 1);
}
++label;
mRightMPTTMarker = label;
return label;
}
///////////////////////////////////////////////////////////////
// Parcelable
//
// This whole class has to be parcelable because it's passed
// on through intents.
///////////////////////////////////////////////////////////////
@Override
public int describeContents() {
return 0;
}
@Override if (tmpValue == OPERATOR.CONDITION) {
public void writeToParcel(Parcel dest, int flags) { condition = new SearchCondition(SEARCHFIELD.valueOf(cursor.getString(0)),
dest.writeInt(mValue.ordinal()); ATTRIBUTE.valueOf(cursor.getString(2)), cursor.getString(1));
dest.writeParcelable(mCondition, flags); }
dest.writeParcelable(mLeft, flags);
dest.writeParcelable(mRight, flags); result = new ConditionsTreeNode(condition);
} result.mValue = tmpValue;
result.mLeftMPTTMarker = cursor.getInt(3);
public static final Parcelable.Creator<ConditionsTreeNode> CREATOR result.mRightMPTTMarker = cursor.getInt(4);
= new Parcelable.Creator<ConditionsTreeNode>() {
public ConditionsTreeNode createFromParcel(Parcel in) { return result;
return new ConditionsTreeNode(in); }
}
public ConditionsTreeNode[] newArray(int size) { ///////////////////////////////////////////////////////////////
return new ConditionsTreeNode[size]; // Constructors
} ///////////////////////////////////////////////////////////////
}; public ConditionsTreeNode(SearchCondition condition) {
mParent = null;
private ConditionsTreeNode(Parcel in) { mCondition = condition;
mValue = OPERATOR.values()[in.readInt()]; mValue = OPERATOR.CONDITION;
mCondition = in.readParcelable(ConditionsTreeNode.class.getClassLoader()); }
mLeft = in.readParcelable(ConditionsTreeNode.class.getClassLoader());
mRight = in.readParcelable(ConditionsTreeNode.class.getClassLoader()); public ConditionsTreeNode(ConditionsTreeNode parent, OPERATOR op) {
mParent = null; mParent = parent;
if (mLeft != null) { mValue = op;
mLeft.mParent = this; mCondition = null;
} }
if (mRight != null) {
mRight.mParent = this;
} ///////////////////////////////////////////////////////////////
} // Public modifiers
///////////////////////////////////////////////////////////////
/**
* Adds the expression as the second argument of an AND
* clause to this node.
*
* @param expr Expression to 'AND' with.
* @return New top AND node.
* @throws Exception
*/
public ConditionsTreeNode and(ConditionsTreeNode expr) throws Exception {
return add(expr, OPERATOR.AND);
}
/**
* Convenience method.
* Adds the provided condition as the second argument of an AND
* clause to this node.
*
* @param condition Condition to 'AND' with.
* @return New top AND node, new root.
*/
public ConditionsTreeNode and(SearchCondition condition) {
try {
ConditionsTreeNode tmp = new ConditionsTreeNode(condition);
return and(tmp);
} catch (Exception e) {
// impossible
return null;
}
}
/**
* Adds the expression as the second argument of an OR
* clause to this node.
*
* @param expr Expression to 'OR' with.
* @return New top OR node.
* @throws Exception
*/
public ConditionsTreeNode or(ConditionsTreeNode expr) throws Exception {
return add(expr, OPERATOR.OR);
}
/**
* Convenience method.
* Adds the provided condition as the second argument of an OR
* clause to this node.
*
* @param condition Condition to 'OR' with.
* @return New top OR node, new root.
*/
public ConditionsTreeNode or(SearchCondition condition) {
try {
ConditionsTreeNode tmp = new ConditionsTreeNode(condition);
return or(tmp);
} catch (Exception e) {
// impossible
return null;
}
}
/**
* This applies the MPTT labeling to the subtree of which this node
* is the root node.
*
* For a description on MPTT see:
* http://www.sitepoint.com/hierarchical-data-database-2/
*/
public void applyMPTTLabel() {
applyMPTTLabel(1);
}
///////////////////////////////////////////////////////////////
// Public accessors
///////////////////////////////////////////////////////////////
/**
* Returns the condition stored in this node.
* @return Condition stored in the node.
*/
public SearchCondition getCondition() {
return mCondition;
}
/**
* This will traverse the tree inorder and call toString recursively resulting
* in a valid SQL where clause.
*/
@Override
public String toString() {
return (mLeft == null ? "" : "(" + mLeft + ")")
+ " " + ( mCondition == null ? mValue.name() : mCondition ) + " "
+ (mRight == null ? "" : "(" + mRight + ")") ;
}
/**
* Get a set of all the leaves in the tree.
* @return Set of all the leaves.
*/
public HashSet<ConditionsTreeNode> getLeafSet() {
HashSet<ConditionsTreeNode> leafSet = new HashSet<ConditionsTreeNode>();
return getLeafSet(leafSet);
}
/**
* Returns a list of all the nodes in the subtree of which this node
* is the root. The list contains the nodes in a pre traversal order.
*
* @return List of all nodes in subtree in preorder.
*/
public List<ConditionsTreeNode> preorder() {
ArrayList<ConditionsTreeNode> result = new ArrayList<ConditionsTreeNode>();
Stack<ConditionsTreeNode> stack = new Stack<ConditionsTreeNode>();
stack.push(this);
while(!stack.isEmpty()) {
ConditionsTreeNode current = stack.pop( );
if( current.mLeft != null ) stack.push( current.mLeft );
if( current.mRight != null ) stack.push( current.mRight );
result.add(current);
}
return result;
}
///////////////////////////////////////////////////////////////
// Private class logic
///////////////////////////////////////////////////////////////
/**
* Adds two new ConditionTreeNodes, one for the operator and one for the
* new condition. The current node will end up on the same level as the
* one provided in the arguments, they will be siblings. Their common
* parent node will be one containing the operator provided in the arguments.
* The method will update all the required references so the tree ends up in
* a valid state.
*
* This method only supports node arguments with a null parent node.
*
* @param Node to add.
* @param Operator that will connect the new node with this one.
* @return New parent node, containing the operator.
* @throws Exception Throws when the provided new node does not have a null parent.
*/
private ConditionsTreeNode add(ConditionsTreeNode node, OPERATOR op) throws Exception{
if (node.mParent != null) {
throw new Exception("Can only add new expressions from root node down.");
}
ConditionsTreeNode tmpNode = new ConditionsTreeNode(mParent, op);
tmpNode.mLeft = this;
tmpNode.mRight = node;
if (mParent != null) {
mParent.updateChild(this, tmpNode);
}
this.mParent = tmpNode;
node.mParent = tmpNode;
return tmpNode;
}
/**
* Helper method that replaces a child of the current node with a new node.
* If the provided old child node was the left one, left will be replaced with
* the new one. Same goes for the right one.
*
* @param oldChild Old child node to be replaced.
* @param newChild New child node.
*/
private void updateChild(ConditionsTreeNode oldChild, ConditionsTreeNode newChild) {
// we can compare objects id's because this is the desired behaviour in this case
if (mLeft == oldChild) {
mLeft = newChild;
} else if (mRight == oldChild) {
mRight = newChild;
}
}
/**
* Recursive function to gather all the leaves in the subtree of which
* this node is the root.
*
* @param leafSet Leafset that's being built.
* @return Set of leaves being completed.
*/
private HashSet<ConditionsTreeNode> getLeafSet(HashSet<ConditionsTreeNode> leafSet) {
// if we ended up in a leaf, add ourself and return
if (mLeft == null && mRight == null) {
leafSet.add(this);
return leafSet;
// we didn't end up in a leaf
} else {
if (mLeft != null) {
mLeft.getLeafSet(leafSet);
}
if (mRight != null) {
mRight.getLeafSet(leafSet);
}
return leafSet;
}
}
/**
* This applies the MPTT labeling to the subtree of which this node
* is the root node.
*
* For a description on MPTT see:
* http://www.sitepoint.com/hierarchical-data-database-2/
*/
private int applyMPTTLabel(int label) {
mLeftMPTTMarker = label;
if (mLeft != null){
label = mLeft.applyMPTTLabel(label += 1);
}
if (mRight != null){
label = mRight.applyMPTTLabel(label += 1);
}
++label;
mRightMPTTMarker = label;
return label;
}
///////////////////////////////////////////////////////////////
// Parcelable
//
// This whole class has to be parcelable because it's passed
// on through intents.
///////////////////////////////////////////////////////////////
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mValue.ordinal());
dest.writeParcelable(mCondition, flags);
dest.writeParcelable(mLeft, flags);
dest.writeParcelable(mRight, flags);
}
public static final Parcelable.Creator<ConditionsTreeNode> CREATOR
= new Parcelable.Creator<ConditionsTreeNode>() {
public ConditionsTreeNode createFromParcel(Parcel in) {
return new ConditionsTreeNode(in);
}
public ConditionsTreeNode[] newArray(int size) {
return new ConditionsTreeNode[size];
}
};
private ConditionsTreeNode(Parcel in) {
mValue = OPERATOR.values()[in.readInt()];
mCondition = in.readParcelable(ConditionsTreeNode.class.getClassLoader());
mLeft = in.readParcelable(ConditionsTreeNode.class.getClassLoader());
mRight = in.readParcelable(ConditionsTreeNode.class.getClassLoader());
mParent = null;
if (mLeft != null) {
mLeft.mParent = this;
}
if (mRight != null) {
mRight.mParent = this;
}
}
} }

View File

@ -11,81 +11,81 @@ import android.os.Parcelable;
import com.fsck.k9.mail.Flag; import com.fsck.k9.mail.Flag;
/** /**
* This class represents a local search. * This class represents a local search.
* Removing conditions could be done through matching there unique id in the leafset and then * Removing conditions could be done through matching there unique id in the leafset and then
* removing them from the tree. * removing them from the tree.
* *
* @author dzan * @author dzan
* *
* TODO implement a complete addAllowedFolder method * TODO implement a complete addAllowedFolder method
* TODO conflicting conditions check on add * TODO conflicting conditions check on add
* TODO duplicate condition checking? * TODO duplicate condition checking?
* TODO assign each node a unique id that's used to retrieve it from the leaveset and remove. * TODO assign each node a unique id that's used to retrieve it from the leaveset and remove.
* *
*/ */
public class LocalSearch implements SearchSpecification { public class LocalSearch implements SearchSpecification {
private String mName; private String mName;
private boolean mPredefined; private boolean mPredefined;
// since the uuid isn't in the message table it's not in the tree neither // since the uuid isn't in the message table it's not in the tree neither
private HashSet<String> mAccountUuids = new HashSet<String>(); private HashSet<String> mAccountUuids = new HashSet<String>();
private ConditionsTreeNode mConditions = null; private ConditionsTreeNode mConditions = null;
private HashSet<ConditionsTreeNode> mLeafSet = new HashSet<ConditionsTreeNode>(); private HashSet<ConditionsTreeNode> mLeafSet = new HashSet<ConditionsTreeNode>();
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
// Constructors // Constructors
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
/** /**
* Use this only if the search won't be saved. Saved searches need * Use this only if the search won't be saved. Saved searches need
* a name! * a name!
*/ */
public LocalSearch(){} public LocalSearch(){}
/** /**
* *
* @param name * @param name
*/ */
public LocalSearch(String name) { public LocalSearch(String name) {
this.mName = name; this.mName = name;
} }
/** /**
* Use this constructor when you know what you'r doing. Normally it's only used * Use this constructor when you know what you'r doing. Normally it's only used
* when restoring these search objects from the database. * when restoring these search objects from the database.
* *
* @param name Name of the search * @param name Name of the search
* @param searchConditions SearchConditions, may contains flags and folders * @param searchConditions SearchConditions, may contains flags and folders
* @param accounts Relative Account's uuid's * @param accounts Relative Account's uuid's
* @param predefined Is this a predefined search or a user created one? * @param predefined Is this a predefined search or a user created one?
*/ */
protected LocalSearch(String name, ConditionsTreeNode searchConditions, protected LocalSearch(String name, ConditionsTreeNode searchConditions,
String accounts, boolean predefined) { String accounts, boolean predefined) {
this(name); this(name);
mConditions = searchConditions; mConditions = searchConditions;
mPredefined = predefined; mPredefined = predefined;
mLeafSet = new HashSet<ConditionsTreeNode>(); mLeafSet = new HashSet<ConditionsTreeNode>();
if (mConditions != null) { if (mConditions != null) {
mLeafSet.addAll(mConditions.getLeafSet()); mLeafSet.addAll(mConditions.getLeafSet());
} }
// initialize accounts // initialize accounts
if (accounts != null) { if (accounts != null) {
for (String account : accounts.split(",")) { for (String account : accounts.split(",")) {
mAccountUuids.add(account); mAccountUuids.add(account);
} }
} else { } else {
// impossible but still not unrecoverable // impossible but still not unrecoverable
} }
} }
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
// Public manipulation methods // Public manipulation methods
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
/** /**
* Sets the name of the saved search. If one existed it will * Sets the name of the saved search. If one existed it will
* be overwritten. * be overwritten.
@ -97,215 +97,215 @@ public class LocalSearch implements SearchSpecification {
} }
/** /**
* Add a new account to the search. When no accounts are * Add a new account to the search. When no accounts are
* added manually we search all accounts on the device. * added manually we search all accounts on the device.
* *
* @param uuid Uuid of the account to be added. * @param uuid Uuid of the account to be added.
*/ */
public void addAccountUuid(String uuid) { public void addAccountUuid(String uuid) {
if (uuid.equals(ALL_ACCOUNTS)) { if (uuid.equals(ALL_ACCOUNTS)) {
mAccountUuids.clear(); mAccountUuids.clear();
} }
mAccountUuids.add(uuid); mAccountUuids.add(uuid);
} }
/** /**
* Adds all the account uuids in the provided array to * Adds all the account uuids in the provided array to
* be matched by the seach. * be matched by the seach.
* *
* @param accountUuids * @param accountUuids
*/ */
public void addAccountUuids(String[] accountUuids) { public void addAccountUuids(String[] accountUuids) {
for (String acc : accountUuids) { for (String acc : accountUuids) {
addAccountUuid(acc); addAccountUuid(acc);
} }
} }
/** /**
* Removes an account UUID from the current search. * Removes an account UUID from the current search.
* *
* @param uuid Account UUID to remove. * @param uuid Account UUID to remove.
* @return True if removed, false otherwise. * @return True if removed, false otherwise.
*/ */
public boolean removeAccountUuid(String uuid) { public boolean removeAccountUuid(String uuid) {
return mAccountUuids.remove(uuid); return mAccountUuids.remove(uuid);
} }
/** /**
* Adds the provided node as the second argument of an AND * Adds the provided node as the second argument of an AND
* clause to this node. * clause to this node.
* *
* @param field Message table field to match against. * @param field Message table field to match against.
* @param string Value to look for. * @param string Value to look for.
* @param contains Attribute to use when matching. * @param contains Attribute to use when matching.
* *
* @throws IllegalConditionException * @throws IllegalConditionException
*/ */
public void and(SEARCHFIELD field, String value, ATTRIBUTE attribute) { public void and(SEARCHFIELD field, String value, ATTRIBUTE attribute) {
and(new SearchCondition(field, attribute, value)); and(new SearchCondition(field, attribute, value));
} }
/** /**
* Adds the provided condition as the second argument of an AND * Adds the provided condition as the second argument of an AND
* clause to this node. * clause to this node.
* *
* @param condition Condition to 'AND' with. * @param condition Condition to 'AND' with.
* @return New top AND node, new root. * @return New top AND node, new root.
*/ */
public ConditionsTreeNode and(SearchCondition condition) { public ConditionsTreeNode and(SearchCondition condition) {
try { try {
ConditionsTreeNode tmp = new ConditionsTreeNode(condition); ConditionsTreeNode tmp = new ConditionsTreeNode(condition);
return and(tmp); return and(tmp);
} catch (Exception e) { } catch (Exception e) {
// impossible // impossible
return null; return null;
} }
} }
/** /**
* Adds the provided node as the second argument of an AND * Adds the provided node as the second argument of an AND
* clause to this node. * clause to this node.
* *
* @param node Node to 'AND' with. * @param node Node to 'AND' with.
* @return New top AND node, new root. * @return New top AND node, new root.
* @throws Exception * @throws Exception
*/ */
public ConditionsTreeNode and(ConditionsTreeNode node) throws Exception { public ConditionsTreeNode and(ConditionsTreeNode node) throws Exception {
mLeafSet.addAll(node.getLeafSet()); mLeafSet.addAll(node.getLeafSet());
if (mConditions == null) { if (mConditions == null) {
mConditions = node; mConditions = node;
return node; return node;
} }
return mConditions.and(node); return mConditions.and(node);
} }
/** /**
* Adds the provided condition as the second argument of an OR * Adds the provided condition as the second argument of an OR
* clause to this node. * clause to this node.
* *
* @param condition Condition to 'OR' with. * @param condition Condition to 'OR' with.
* @return New top OR node, new root. * @return New top OR node, new root.
*/ */
public ConditionsTreeNode or(SearchCondition condition) { public ConditionsTreeNode or(SearchCondition condition) {
try { try {
ConditionsTreeNode tmp = new ConditionsTreeNode(condition); ConditionsTreeNode tmp = new ConditionsTreeNode(condition);
return or(tmp); return or(tmp);
} catch (Exception e) { } catch (Exception e) {
// impossible // impossible
return null; return null;
} }
} }
/** /**
* Adds the provided node as the second argument of an OR * Adds the provided node as the second argument of an OR
* clause to this node. * clause to this node.
* *
* @param node Node to 'OR' with. * @param node Node to 'OR' with.
* @return New top OR node, new root. * @return New top OR node, new root.
* @throws Exception * @throws Exception
*/ */
public ConditionsTreeNode or(ConditionsTreeNode node) throws Exception { public ConditionsTreeNode or(ConditionsTreeNode node) throws Exception {
mLeafSet.addAll(node.getLeafSet()); mLeafSet.addAll(node.getLeafSet());
if (mConditions == null) { if (mConditions == null) {
mConditions = node; mConditions = node;
return node; return node;
} }
return mConditions.or(node); return mConditions.or(node);
} }
/** /**
* Add all the flags to this node as required flags. The * Add all the flags to this node as required flags. The
* provided flags will be combined using AND with the root. * provided flags will be combined using AND with the root.
* *
* @param requiredFlags Array of required flags. * @param requiredFlags Array of required flags.
*/ */
public void allRequiredFlags(Flag[] requiredFlags) { public void allRequiredFlags(Flag[] requiredFlags) {
if (requiredFlags != null) { if (requiredFlags != null) {
for (Flag f : requiredFlags) { for (Flag f : requiredFlags) {
and(new SearchCondition(SEARCHFIELD.FLAG, ATTRIBUTE.CONTAINS, f.name())); and(new SearchCondition(SEARCHFIELD.FLAG, ATTRIBUTE.CONTAINS, f.name()));
} }
} }
} }
/** /**
* Add all the flags to this node as forbidden flags. The * Add all the flags to this node as forbidden flags. The
* provided flags will be combined using AND with the root. * provided flags will be combined using AND with the root.
* *
* @param forbiddenFlags Array of forbidden flags. * @param forbiddenFlags Array of forbidden flags.
*/ */
public void allForbiddenFlags(Flag[] forbiddenFlags) { public void allForbiddenFlags(Flag[] forbiddenFlags) {
if (forbiddenFlags != null) { if (forbiddenFlags != null) {
for (Flag f : forbiddenFlags) { for (Flag f : forbiddenFlags) {
and(new SearchCondition(SEARCHFIELD.FLAG, ATTRIBUTE.NOT_CONTAINS, f.name())); and(new SearchCondition(SEARCHFIELD.FLAG, ATTRIBUTE.NOT_CONTAINS, f.name()));
} }
} }
} }
/** /**
* TODO * TODO
* FOR NOW: And the folder with the root. * FOR NOW: And the folder with the root.
* *
* Add the folder as another folder to search in. The folder * Add the folder as another folder to search in. The folder
* will be added AND to the root if no 'folder subtree' was found. * will be added AND to the root if no 'folder subtree' was found.
* Otherwise the folder will be added OR to that tree. * Otherwise the folder will be added OR to that tree.
* *
* @param name Name of the folder to add. * @param name Name of the folder to add.
*/ */
public void addAllowedFolder(String name) { public void addAllowedFolder(String name) {
/* /*
* TODO find folder sub-tree * TODO find folder sub-tree
* - do and on root of it & rest of search * - do and on root of it & rest of search
* - do or between folder nodes * - do or between folder nodes
*/ */
and(new SearchCondition(SEARCHFIELD.FOLDER, ATTRIBUTE.EQUALS, name)); and(new SearchCondition(SEARCHFIELD.FOLDER, ATTRIBUTE.EQUALS, name));
} }
/* /*
* TODO make this more advanced! * TODO make this more advanced!
* This is a temporarely solution that does NOT WORK for * This is a temporarely solution that does NOT WORK for
* real searches because of possible extra conditions to a folder requirement. * real searches because of possible extra conditions to a folder requirement.
*/ */
public List<String> getFolderNames() { public List<String> getFolderNames() {
ArrayList<String> results = new ArrayList<String>(); ArrayList<String> results = new ArrayList<String>();
for (ConditionsTreeNode node : mLeafSet) { for (ConditionsTreeNode node : mLeafSet) {
if (node.mCondition.field == SEARCHFIELD.FOLDER if (node.mCondition.field == SEARCHFIELD.FOLDER
&& node.mCondition.attribute == ATTRIBUTE.EQUALS) { && node.mCondition.attribute == ATTRIBUTE.EQUALS) {
results.add(node.mCondition.value); results.add(node.mCondition.value);
} }
} }
return results; return results;
} }
/** /**
* Gets the leafset of the related condition tree. * Gets the leafset of the related condition tree.
* *
* @return All the leaf conditions as a set. * @return All the leaf conditions as a set.
*/ */
public Set<ConditionsTreeNode> getLeafSet() { public Set<ConditionsTreeNode> getLeafSet() {
return mLeafSet; return mLeafSet;
} }
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
// Public accesor methods // Public accesor methods
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
/** /**
* TODO THIS HAS TO GO!!!! * TODO THIS HAS TO GO!!!!
* very dirty fix for remotesearch support atm * very dirty fix for remotesearch support atm
*/ */
public String getRemoteSearchArguments() { public String getRemoteSearchArguments() {
for (ConditionsTreeNode node : getLeafSet()) { for (ConditionsTreeNode node : getLeafSet()) {
if (node.getCondition().field == SEARCHFIELD.SUBJECT if (node.getCondition().field == SEARCHFIELD.SUBJECT
|| node.getCondition().field == SEARCHFIELD.SENDER ) { || node.getCondition().field == SEARCHFIELD.SENDER ) {
return node.getCondition().value; return node.getCondition().value;
} }
} }
return null; return null;
} }
/** /**
* Returns the name of the saved search. * Returns the name of the saved search.
* *
@ -314,22 +314,22 @@ public class LocalSearch implements SearchSpecification {
public String getName() { public String getName() {
return (mName == null ? "" : mName); return (mName == null ? "" : mName);
} }
/** /**
* Checks if this search was hard coded and shipped with K-9 * Checks if this search was hard coded and shipped with K-9
* *
* @return True is search was shipped with K-9 * @return True is search was shipped with K-9
*/ */
public boolean isPredefined() { public boolean isPredefined() {
return mPredefined; return mPredefined;
} }
/** /**
* Returns all the account uuids that this search will try to * Returns all the account uuids that this search will try to
* match against. * match against.
* *
* @return Array of account uuids. * @return Array of account uuids.
*/ */
@Override @Override
public String[] getAccountUuids() { public String[] getAccountUuids() {
if (mAccountUuids.size() == 0) { if (mAccountUuids.size() == 0) {
@ -346,43 +346,43 @@ public class LocalSearch implements SearchSpecification {
* *
* @return The root node of the related conditions tree. * @return The root node of the related conditions tree.
*/ */
@Override @Override
public ConditionsTreeNode getConditions() { public ConditionsTreeNode getConditions() {
return mConditions; return mConditions;
} }
///////////////////////////////////////////////////////////////
// Parcelable
///////////////////////////////////////////////////////////////
@Override
public int describeContents() {
return 0;
}
@Override ///////////////////////////////////////////////////////////////
public void writeToParcel(Parcel dest, int flags) { // Parcelable
dest.writeString(mName); ///////////////////////////////////////////////////////////////
dest.writeByte((byte) (mPredefined ? 1 : 0)); @Override
dest.writeStringList(new ArrayList<String>(mAccountUuids)); public int describeContents() {
dest.writeParcelable(mConditions, flags); return 0;
} }
public static final Parcelable.Creator<LocalSearch> CREATOR @Override
= new Parcelable.Creator<LocalSearch>() { public void writeToParcel(Parcel dest, int flags) {
public LocalSearch createFromParcel(Parcel in) { dest.writeString(mName);
return new LocalSearch(in); dest.writeByte((byte) (mPredefined ? 1 : 0));
} dest.writeStringList(new ArrayList<String>(mAccountUuids));
dest.writeParcelable(mConditions, flags);
public LocalSearch[] newArray(int size) { }
return new LocalSearch[size];
} public static final Parcelable.Creator<LocalSearch> CREATOR
}; = new Parcelable.Creator<LocalSearch>() {
public LocalSearch createFromParcel(Parcel in) {
public LocalSearch(Parcel in) { return new LocalSearch(in);
mName = in.readString(); }
mPredefined = in.readByte() == 1;
mAccountUuids.addAll(in.createStringArrayList()); public LocalSearch[] newArray(int size) {
mConditions = in.readParcelable(LocalSearch.class.getClassLoader()); return new LocalSearch[size];
mLeafSet = mConditions.getLeafSet(); }
} };
public LocalSearch(Parcel in) {
mName = in.readString();
mPredefined = in.readByte() == 1;
mAccountUuids.addAll(in.createStringArrayList());
mConditions = in.readParcelable(LocalSearch.class.getClassLoader());
mLeafSet = mConditions.getLeafSet();
}
} }

View File

@ -14,36 +14,36 @@ import com.fsck.k9.R;
public class SearchAccount implements BaseAccount { public class SearchAccount implements BaseAccount {
// create the all messages search ( all accounts is default when none specified ) // create the all messages search ( all accounts is default when none specified )
public static SearchAccount createAllMessagesAccount(Context context) { public static SearchAccount createAllMessagesAccount(Context context) {
String name = context.getString(R.string.search_all_messages_title); String name = context.getString(R.string.search_all_messages_title);
LocalSearch tmpSearch = new LocalSearch(name); LocalSearch tmpSearch = new LocalSearch(name);
return new SearchAccount(tmpSearch, name, return new SearchAccount(tmpSearch, name,
context.getString(R.string.search_all_messages_detail)); context.getString(R.string.search_all_messages_detail));
} }
// create the unified inbox meta account ( all accounts is default when none specified )
public static SearchAccount createUnifiedInboxAccount(Context context) { // create the unified inbox meta account ( all accounts is default when none specified )
public static SearchAccount createUnifiedInboxAccount(Context context) {
String name = context.getString(R.string.integrated_inbox_title); String name = context.getString(R.string.integrated_inbox_title);
LocalSearch tmpSearch = new LocalSearch(name); LocalSearch tmpSearch = new LocalSearch(name);
tmpSearch.addAllowedFolder(SearchSpecification.GENERIC_INBOX_NAME); tmpSearch.addAllowedFolder(SearchSpecification.GENERIC_INBOX_NAME);
return new SearchAccount(tmpSearch, name, return new SearchAccount(tmpSearch, name,
context.getString(R.string.integrated_inbox_detail)); context.getString(R.string.integrated_inbox_detail));
} }
private String mEmail = null; private String mEmail = null;
private String mDescription = null; private String mDescription = null;
private LocalSearch mSearch = null; private LocalSearch mSearch = null;
private String mFakeUuid = null; private String mFakeUuid = null;
public SearchAccount(LocalSearch search, String description, String email) throws IllegalArgumentException{ public SearchAccount(LocalSearch search, String description, String email) throws IllegalArgumentException{
if (search == null) { if (search == null) {
throw new IllegalArgumentException("Provided LocalSearch was null"); throw new IllegalArgumentException("Provided LocalSearch was null");
} }
this.mSearch = search; this.mSearch = search;
this.mDescription = description; this.mDescription = description;
this.mEmail = email; this.mEmail = email;
} }
@Override @Override
@ -55,33 +55,33 @@ public class SearchAccount implements BaseAccount {
public synchronized void setEmail(String email) { public synchronized void setEmail(String email) {
this.mEmail = email; this.mEmail = email;
} }
@Override @Override
public String getDescription() { public String getDescription() {
return mDescription; return mDescription;
} }
@Override @Override
public void setDescription(String description) { public void setDescription(String description) {
this.mDescription = description; this.mDescription = description;
} }
public LocalSearch getRelatedSearch() { public LocalSearch getRelatedSearch() {
return mSearch; return mSearch;
} }
@Override @Override
/* /*
* This will only be used when accessed as an Account. If that * This will only be used when accessed as an Account. If that
* is the case we don't want to return the uuid of a real account since * is the case we don't want to return the uuid of a real account since
* this is posing as a fake meta-account. If this object is accesed as * this is posing as a fake meta-account. If this object is accesed as
* a Search then methods from LocalSearch will be called which do handle * a Search then methods from LocalSearch will be called which do handle
* things nice. * things nice.
*/ */
public String getUuid() { public String getUuid() {
if (mFakeUuid == null){ if (mFakeUuid == null){
mFakeUuid = UUID.randomUUID().toString(); mFakeUuid = UUID.randomUUID().toString();
} }
return mFakeUuid; return mFakeUuid;
} }
} }

View File

@ -4,79 +4,79 @@ import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
public interface SearchSpecification extends Parcelable { public interface SearchSpecification extends Parcelable {
/** /**
* Get all the uuids of accounts this search acts on. * Get all the uuids of accounts this search acts on.
* @return Array of uuids. * @return Array of uuids.
*/ */
public String[] getAccountUuids(); public String[] getAccountUuids();
/** /**
* Returns the search's name if it was named. * Returns the search's name if it was named.
* @return Name of the search. * @return Name of the search.
*/ */
public String getName(); public String getName();
/** /**
* Returns the root node of the condition tree accompanying * Returns the root node of the condition tree accompanying
* the search. * the search.
* *
* @return Root node of conditions tree. * @return Root node of conditions tree.
*/ */
public ConditionsTreeNode getConditions(); public ConditionsTreeNode getConditions();
/* /*
* Some meta names for certain conditions. * Some meta names for certain conditions.
*/ */
public static final String ALL_ACCOUNTS = "allAccounts"; public static final String ALL_ACCOUNTS = "allAccounts";
public static final String GENERIC_INBOX_NAME = "genericInboxName"; public static final String GENERIC_INBOX_NAME = "genericInboxName";
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
// ATTRIBUTE enum // ATTRIBUTE enum
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
public enum ATTRIBUTE { public enum ATTRIBUTE {
CONTAINS(false), EQUALS(false), STARTSWITH(false), ENDSWITH(false), CONTAINS(false), EQUALS(false), STARTSWITH(false), ENDSWITH(false),
NOT_CONTAINS(true), NOT_EQUALS(true), NOT_STARTSWITH(true), NOT_ENDSWITH(true); NOT_CONTAINS(true), NOT_EQUALS(true), NOT_STARTSWITH(true), NOT_ENDSWITH(true);
private boolean mNegation; private boolean mNegation;
private ATTRIBUTE(boolean negation) { private ATTRIBUTE(boolean negation) {
this.mNegation = negation; this.mNegation = negation;
} }
public String formQuery(String value) { public String formQuery(String value) {
String queryPart = ""; String queryPart = "";
switch (this) { switch (this) {
case NOT_CONTAINS: case NOT_CONTAINS:
case CONTAINS: case CONTAINS:
queryPart = "'%"+value+"%'"; queryPart = "'%"+value+"%'";
break; break;
case NOT_EQUALS: case NOT_EQUALS:
case EQUALS: case EQUALS:
queryPart = "'"+value+"'"; queryPart = "'"+value+"'";
break; break;
case NOT_STARTSWITH: case NOT_STARTSWITH:
case STARTSWITH: case STARTSWITH:
queryPart = "'%"+value+"'"; queryPart = "'%"+value+"'";
break; break;
case NOT_ENDSWITH: case NOT_ENDSWITH:
case ENDSWITH: case ENDSWITH:
queryPart = "'"+value+"%'"; queryPart = "'"+value+"%'";
break; break;
default: queryPart = "'"+value+"'"; default: queryPart = "'"+value+"'";
} }
return (mNegation ? " NOT LIKE " : " LIKE ") + queryPart; return (mNegation ? " NOT LIKE " : " LIKE ") + queryPart;
} }
}; };
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
// SEARCHFIELD enum // SEARCHFIELD enum
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
/* /*
* Using an enum in order to have more robust code. Users ( & coders ) * Using an enum in order to have more robust code. Users ( & coders )
* are prevented from passing illegal fields. No database overhead * are prevented from passing illegal fields. No database overhead
* when invalid fields passed. * when invalid fields passed.
* *
* By result, only the fields in here are searchable. * By result, only the fields in here are searchable.
@ -84,7 +84,7 @@ public interface SearchSpecification extends Parcelable {
* Fields not in here at this moment ( and by effect not searchable ): * Fields not in here at this moment ( and by effect not searchable ):
* id, html_content, internal_date, message_id, * id, html_content, internal_date, message_id,
* preview, mime_type * preview, mime_type
* *
*/ */
public enum SEARCHFIELD { public enum SEARCHFIELD {
SUBJECT("subject"), DATE("date"), UID("uid"), FLAG("flags"), SUBJECT("subject"), DATE("date"), UID("uid"), FLAG("flags"),
@ -93,7 +93,7 @@ public interface SearchSpecification extends Parcelable {
ATTACHMENT_COUNT("attachment_count"), DELETED("deleted"), THREAD_ROOT("thread_root"); ATTACHMENT_COUNT("attachment_count"), DELETED("deleted"), THREAD_ROOT("thread_root");
private String dbName; private String dbName;
private SEARCHFIELD(String dbName) { private SEARCHFIELD(String dbName) {
this.dbName = dbName; this.dbName = dbName;
} }
@ -102,25 +102,25 @@ public interface SearchSpecification extends Parcelable {
return dbName; return dbName;
} }
} }
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
// SearchCondition class // SearchCondition class
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
/** /**
* This class represents 1 value for a certain search field. One * This class represents 1 value for a certain search field. One
* value consists of three things: * value consists of three things:
* an attribute: equals, starts with, contains,... * an attribute: equals, starts with, contains,...
* a searchfield: date, flags, sender, subject,... * a searchfield: date, flags, sender, subject,...
* a value: "apple", "jesse",.. * a value: "apple", "jesse",..
* *
* @author dzan * @author dzan
*/ */
public class SearchCondition implements Parcelable{ public class SearchCondition implements Parcelable{
public String value; public String value;
public ATTRIBUTE attribute; public ATTRIBUTE attribute;
public SEARCHFIELD field; public SEARCHFIELD field;
public SearchCondition(SEARCHFIELD field, ATTRIBUTE attribute, String value) { public SearchCondition(SEARCHFIELD field, ATTRIBUTE attribute, String value) {
this.value = value; this.value = value;
this.attribute = attribute; this.attribute = attribute;
@ -128,26 +128,26 @@ public interface SearchSpecification extends Parcelable {
} }
private SearchCondition(Parcel in) { private SearchCondition(Parcel in) {
this.value = in.readString(); this.value = in.readString();
this.attribute = ATTRIBUTE.values()[in.readInt()]; this.attribute = ATTRIBUTE.values()[in.readInt()];
this.field = SEARCHFIELD.values()[in.readInt()]; this.field = SEARCHFIELD.values()[in.readInt()];
} }
public String toHumanString() { public String toHumanString() {
return field.toString() + attribute.toString(); return field.toString() + attribute.toString();
} }
@Override @Override
public String toString() { public String toString() {
return field.getDatabaseName() + attribute.formQuery(value); return field.getDatabaseName() + attribute.formQuery(value);
} }
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (o instanceof SearchCondition) { if (o instanceof SearchCondition) {
SearchCondition tmp = (SearchCondition) o; SearchCondition tmp = (SearchCondition) o;
if (tmp.attribute == attribute if (tmp.attribute == attribute
&& tmp.value.equals(value) && tmp.value.equals(value)
&& tmp.field == field) { && tmp.field == field) {
return true; return true;
} else { } else {
@ -158,27 +158,27 @@ public interface SearchSpecification extends Parcelable {
} }
} }
@Override @Override
public int describeContents() { public int describeContents() {
return 0; return 0;
} }
@Override @Override
public void writeToParcel(Parcel dest, int flags) { public void writeToParcel(Parcel dest, int flags) {
dest.writeString(value); dest.writeString(value);
dest.writeInt(attribute.ordinal()); dest.writeInt(attribute.ordinal());
dest.writeInt(field.ordinal()); dest.writeInt(field.ordinal());
} }
public static final Parcelable.Creator<SearchCondition> CREATOR public static final Parcelable.Creator<SearchCondition> CREATOR
= new Parcelable.Creator<SearchCondition>() { = new Parcelable.Creator<SearchCondition>() {
public SearchCondition createFromParcel(Parcel in) { public SearchCondition createFromParcel(Parcel in) {
return new SearchCondition(in); return new SearchCondition(in);
} }
public SearchCondition[] newArray(int size) { public SearchCondition[] newArray(int size) {
return new SearchCondition[size]; return new SearchCondition[size];
} }
}; };
} }
} }