Skip to content

Commit 479e6d4

Browse files
committed
Clean up external receiver error handling
1 parent e6f3230 commit 479e6d4

File tree

7 files changed

+101
-99
lines changed

7 files changed

+101
-99
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package com.orgzly.android.external.actionhandlers
22

33
import android.content.Intent
4-
import com.orgzly.android.external.types.Response
4+
import com.orgzly.android.external.types.ExternalHandlerFailure
55

66
class EditNotes : ExternalAccessActionHandler() {
77
override val actions = listOf(
@@ -12,52 +12,42 @@ class EditNotes : ExternalAccessActionHandler() {
1212
action(::deleteNote, "DELETE_NOTE", "DELETE_NOTES")
1313
)
1414

15-
private fun addNote(intent: Intent): Response {
15+
private fun addNote(intent: Intent): String {
1616
val place = intent.getNotePlace()
17-
?: return Response(false, "Could not find parent note/book")
1817
val newNote = intent.getNotePayload()
19-
?: return Response(false, "Invalid payload")
2018
val note = dataRepository.createNote(newNote, place)
21-
return Response(true, "${note.id}")
19+
return "${note.id}"
2220
}
2321

24-
private fun editNote(intent: Intent): Response {
22+
private fun editNote(intent: Intent) {
2523
val noteView = intent.getNote()
26-
?: return Response(false, "Couldn't find note")
2724
val newNote = intent.getNotePayload(title=noteView.note.title)
28-
?: return Response(false, "Invalid payload")
2925
dataRepository.updateNote(noteView.note.id, newNote)
30-
return Response()
3126
}
3227

33-
private fun refileNote(intent: Intent): Response {
28+
private fun refileNote(intent: Intent) {
3429
val notes = intent.getNoteIds()
35-
if (notes.isEmpty())
36-
return Response(false, "No notes specified")
3730
val place = intent.getNotePlace()
38-
?: return Response(false, "Couldn't find note")
3931
dataRepository.refileNotes(notes, place)
40-
return Response()
4132
}
4233

43-
private fun moveNote(intent: Intent): Response {
34+
private fun moveNote(intent: Intent) {
4435
val notes = intent.getNoteIds()
45-
if (notes.isEmpty()) return Response(false, "No notes specified")
4636
with(dataRepository) { when (intent.getStringExtra("DIRECTION")) {
47-
"UP" -> intent.getBook()?.id?.let { moveNote(it, notes, -1) }
48-
"DOWN" -> intent.getBook()?.id?.let { moveNote(it, notes, 1) }
37+
"UP" -> moveNote(intent.getBook().id, notes, -1)
38+
"DOWN" -> moveNote(intent.getBook().id, notes, 1)
4939
"LEFT" -> promoteNotes(notes)
5040
"RIGHT" -> demoteNotes(notes)
51-
else -> return Response(false, "Invalid direction")
41+
else -> throw ExternalHandlerFailure("invalid direction")
5242
} }
53-
return Response()
5443
}
5544

56-
private fun deleteNote(intent: Intent): Response {
57-
val book = intent.getBook() ?: return Response(false, "Couldn't find specified book")
58-
val notes = intent.getNoteIds()
59-
if (notes.isEmpty()) return Response(false, "No notes specified")
60-
dataRepository.deleteNotes(book.id, notes)
61-
return Response()
45+
private fun deleteNote(intent: Intent) {
46+
intent.getNoteIds().groupBy {
47+
dataRepository.getNoteView(it)?.bookName
48+
?: throw ExternalHandlerFailure("invalid note id $it")
49+
}.forEach { (bookName, notes) ->
50+
dataRepository.deleteNotes(dataRepository.getBook(bookName)!!.id, notes.toSet())
51+
}
6252
}
6353
}

Diff for: app/src/main/java/com/orgzly/android/external/actionhandlers/EditSavedSearches.kt

+25-26
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package com.orgzly.android.external.actionhandlers
22

33
import android.content.Intent
44
import com.orgzly.android.db.entity.SavedSearch
5-
import com.orgzly.android.external.types.Response
5+
import com.orgzly.android.external.types.ExternalHandlerFailure
66

77
class EditSavedSearches : ExternalAccessActionHandler() {
88
override val actions = listOf(
@@ -12,37 +12,36 @@ class EditSavedSearches : ExternalAccessActionHandler() {
1212
action(::deleteSavedSearch, "DELETE_SAVED_SEARCH"),
1313
)
1414

15-
private fun addSavedSearch(intent: Intent) =
16-
intent.getNewSavedSearch()?.let {
17-
val id = dataRepository.createSavedSearch(it)
18-
Response(true, "$id")
19-
} ?: Response(false, "Invalid saved search details")
15+
private fun addSavedSearch(intent: Intent): String {
16+
val savedSearch = intent.getNewSavedSearch()
17+
val id = dataRepository.createSavedSearch(savedSearch)
18+
return "$id"
19+
}
2020

21-
private fun editSavedSearch(intent: Intent) = intent.getSavedSearch()?.let { savedSearch ->
22-
intent.getNewSavedSearch(allowBlank = true)?.let { newSavedSearch ->
23-
dataRepository.updateSavedSearch(SavedSearch(
24-
savedSearch.id,
25-
(if (newSavedSearch.name.isBlank()) savedSearch.name
26-
else newSavedSearch.name),
27-
(if (newSavedSearch.query.isBlank()) savedSearch.query
28-
else newSavedSearch.query),
29-
savedSearch.position
30-
))
31-
return Response()
32-
} ?: Response(false, "Invalid saved search details")
33-
} ?: Response(false, "Couldn't find saved search")
21+
private fun editSavedSearch(intent: Intent) {
22+
val savedSearch = intent.getSavedSearch()
23+
val newSavedSearch = intent.getNewSavedSearch(allowBlank = true)
24+
dataRepository.updateSavedSearch(SavedSearch(
25+
savedSearch.id,
26+
(if (newSavedSearch.name.isBlank()) savedSearch.name
27+
else newSavedSearch.name),
28+
(if (newSavedSearch.query.isBlank()) savedSearch.query
29+
else newSavedSearch.query),
30+
savedSearch.position
31+
))
32+
}
3433

35-
private fun moveSavedSearch(intent: Intent) = intent.getSavedSearch()?.let { savedSearch ->
34+
private fun moveSavedSearch(intent: Intent) {
35+
val savedSearch = intent.getSavedSearch()
3636
when (intent.getStringExtra("DIRECTION")) {
3737
"UP" -> dataRepository.moveSavedSearchUp(savedSearch.id)
3838
"DOWN" -> dataRepository.moveSavedSearchDown(savedSearch.id)
39-
else -> return Response(false, "Invalid direction")
39+
else -> throw ExternalHandlerFailure("invalid direction")
4040
}
41-
return Response()
42-
} ?: Response(false, "Couldn't find saved search")
41+
}
4342

44-
private fun deleteSavedSearch(intent: Intent) = intent.getSavedSearch()?.let { savedSearch ->
43+
private fun deleteSavedSearch(intent: Intent) {
44+
val savedSearch = intent.getSavedSearch()
4545
dataRepository.deleteSavedSearches(setOf(savedSearch.id))
46-
return Response()
47-
} ?: Response(false, "Couldn't find saved search")
46+
}
4847
}

Diff for: app/src/main/java/com/orgzly/android/external/actionhandlers/ExternalAccessActionHandler.kt

+41-20
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import com.google.gson.JsonParser
99
import com.orgzly.android.App
1010
import com.orgzly.android.data.DataRepository
1111
import com.orgzly.android.db.entity.SavedSearch
12+
import com.orgzly.android.external.types.ExternalHandlerFailure
1213
import com.orgzly.android.external.types.Response
1314
import com.orgzly.android.ui.NotePlace
1415
import com.orgzly.android.ui.Place
@@ -25,12 +26,12 @@ abstract class ExternalAccessActionHandler {
2526
App.appComponent.inject(this)
2627
}
2728

28-
abstract val actions: List<List<Pair<String, (Intent, Context) -> Response>>>
29+
abstract val actions: List<List<Pair<String, (Intent, Context) -> Any>>>
2930
private val fullNameActions by lazy {
3031
actions.flatten().toMap().mapKeys { (key, _) -> "com.orgzly.android.$key" }
3132
}
3233

33-
fun Intent.getNotePayload(title: String? = null): NotePayload? {
34+
fun Intent.getNotePayload(title: String? = null): NotePayload {
3435
val rawJson = getStringExtra("NOTE_PAYLOAD")
3536
val json = try {
3637
JsonParser.parseString(rawJson)
@@ -56,19 +57,27 @@ abstract class ExternalAccessActionHandler {
5657
json["properties"]?.asMap?.forEach { (k, v) -> this[k] = v }
5758
}
5859
)
59-
} catch (e: NullPointerException) { null }
60+
} catch (e: NullPointerException) {
61+
throw ExternalHandlerFailure("invalid payload")
62+
}
6063
}
6164

62-
fun Intent.getNotePlace() = getNote(prefix="PARENT_")?.let { noteView ->
63-
val place = try {
64-
Place.valueOf(getStringExtra("PLACEMENT") ?: "")
65-
} catch (e: IllegalArgumentException) { Place.UNDER }
66-
dataRepository.getBook(noteView.bookName)?.let { book ->
67-
NotePlace(book.id, noteView.note.id, place)
65+
fun Intent.getNotePlace() = try {
66+
getNote(prefix="PARENT_").let { noteView ->
67+
val place = try {
68+
Place.valueOf(getStringExtra("PLACEMENT") ?: "")
69+
} catch (e: IllegalArgumentException) { Place.UNDER }
70+
dataRepository.getBook(noteView.bookName)?.let { book ->
71+
NotePlace(book.id, noteView.note.id, place)
72+
}
6873
}
69-
} ?: getBook(prefix="PARENT")?.let { book -> NotePlace(book.id) }
74+
} catch (e: ExternalHandlerFailure) { null } ?: try {
75+
NotePlace(getBook(prefix="PARENT_").id)
76+
} catch (e: ExternalHandlerFailure) {
77+
throw ExternalHandlerFailure("could not find parent note/book")
78+
}
7079

71-
fun Intent.getNoteIds(allowSingle: Boolean = true): Set<Long> {
80+
fun Intent.getNoteIds(allowSingle: Boolean = true, allowEmpty: Boolean = false): Set<Long> {
7281
val id = if (allowSingle) getLongExtra("NOTE_ID", -1) else null
7382
val ids = getLongArrayExtra("NOTE_IDS")?.toTypedArray() ?: emptyArray()
7483
val path =
@@ -79,26 +88,33 @@ abstract class ExternalAccessActionHandler {
7988
val paths = (getStringArrayExtra("NOTE_PATHS") ?: emptyArray())
8089
.mapNotNull { dataRepository.getNoteAtPath(it)?.note?.id }
8190
.toTypedArray()
82-
return listOfNotNull(id, *ids, path, *paths).filter { it >= 0 }.toSet()
91+
return listOfNotNull(id, *ids, path, *paths).filter { it >= 0 }.toSet().also {
92+
if (it.isEmpty() && !allowEmpty)
93+
throw ExternalHandlerFailure("no notes specified")
94+
}
8395
}
8496

8597
fun Intent.getNote(prefix: String = "") =
8698
dataRepository.getNoteView(getLongExtra("${prefix}NOTE_ID", -1))
8799
?: dataRepository.getNoteAtPath(getStringExtra("${prefix}NOTE_PATH") ?: "")
100+
?: throw ExternalHandlerFailure("couldn't find note")
88101

89102
fun Intent.getBook(prefix: String = "") =
90103
dataRepository.getBook(getLongExtra("${prefix}BOOK_ID", -1))
91104
?: dataRepository.getBook(getStringExtra("${prefix}BOOK_NAME") ?: "")
105+
?: throw ExternalHandlerFailure("couldn't find book")
92106

93107
fun Intent.getSavedSearch() =
94108
dataRepository.getSavedSearch(getLongExtra("SAVED_SEARCH_ID", -1))
95109
?: dataRepository.getSavedSearches()
96110
.find { it.name == getStringExtra("SAVED_SEARCH_NAME") }
111+
?: throw ExternalHandlerFailure("couldn't find saved search")
97112

98-
fun Intent.getNewSavedSearch(allowBlank: Boolean = false): SavedSearch? {
113+
fun Intent.getNewSavedSearch(allowBlank: Boolean = false): SavedSearch {
99114
val name = getStringExtra("SAVED_SEARCH_NEW_NAME")
100115
val query = getStringExtra("SAVED_SEARCH_NEW_QUERY")
101-
if (!allowBlank && (name.isNullOrBlank() || query.isNullOrBlank())) return null
116+
if (!allowBlank && (name.isNullOrBlank() || query.isNullOrBlank()))
117+
throw ExternalHandlerFailure("invalid parameters for new saved search")
102118
return SavedSearch(0, name ?: "", query ?: "", 0)
103119
}
104120

@@ -120,20 +136,25 @@ abstract class ExternalAccessActionHandler {
120136
.toMap()
121137
} else null
122138

123-
fun action(f: (Intent, Context) -> Response, vararg names: String) = names.map { it to f }
139+
fun action(f: (Intent, Context) -> Any, vararg names: String) = names.map { it to f }
124140

125141
@JvmName("intentAction")
126-
fun action(f: (Intent) -> Response, vararg names: String) =
142+
fun action(f: (Intent) -> Any, vararg names: String) =
127143
action({ i, _ -> f(i) }, *names)
128144

129145
@JvmName("contextAction")
130-
fun action(f: (Context) -> Response, vararg names: String) =
146+
fun action(f: (Context) -> Any, vararg names: String) =
131147
action({ _, c -> f(c) }, *names)
132148

133-
fun action(f: () -> Response, vararg names: String) =
149+
fun action(f: () -> Any, vararg names: String) =
134150
action({ _, _ -> f() }, *names)
135151

136152

137-
fun handle(intent: Intent, context: Context) =
138-
fullNameActions[intent.action!!]?.let { it(intent, context) }
153+
fun handle(intent: Intent, context: Context) = try {
154+
fullNameActions[intent.action!!]
155+
?.let { it(intent, context) }
156+
?.let { Response(true, if (it is Unit) null else it) }
157+
} catch (e: ExternalHandlerFailure) {
158+
Response(false, e.message)
159+
}
139160
}

Diff for: app/src/main/java/com/orgzly/android/external/actionhandlers/GetOrgInfo.kt

+5-13
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,12 @@ class GetOrgInfo : ExternalAccessActionHandler() {
1010
action(::getNote, "GET_NOTE")
1111
)
1212

13-
private fun getBooks() = Response(
14-
true,
15-
dataRepository.getBooks()
16-
.map(Book::from).toTypedArray()
17-
)
13+
private fun getBooks() =
14+
dataRepository.getBooks().map(Book::from).toTypedArray()
1815

19-
private fun getSavedSearches() = Response(
20-
true,
21-
dataRepository.getSavedSearches()
22-
.map(SavedSearch::from).toTypedArray()
23-
)
16+
private fun getSavedSearches() =
17+
dataRepository.getSavedSearches().map(SavedSearch::from).toTypedArray()
2418

2519
private fun getNote(intent: Intent) =
26-
intent.getNote()
27-
?.let { Response(true, Note.from(it)) }
28-
?: Response(false, "Couldn't find note at specified path!")
20+
Note.from(intent.getNote())
2921
}

Diff for: app/src/main/java/com/orgzly/android/external/actionhandlers/ManageWidgets.kt

+6-9
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import android.content.ComponentName
55
import android.content.Context
66
import android.content.Intent
77
import com.orgzly.android.AppIntent
8-
import com.orgzly.android.external.types.Response
8+
import com.orgzly.android.db.entity.SavedSearch
9+
import com.orgzly.android.external.types.ExternalHandlerFailure
910
import com.orgzly.android.widgets.ListWidgetProvider
1011

1112
class ManageWidgets : ExternalAccessActionHandler() {
@@ -14,27 +15,23 @@ class ManageWidgets : ExternalAccessActionHandler() {
1415
action(::setWidget, "SET_WIDGET")
1516
)
1617

17-
private fun getWidgets(context: Context): Response {
18+
private fun getWidgets(context: Context): Map<Int, SavedSearch> {
1819
val widgetManager = AppWidgetManager.getInstance(context)
1920
val componentName = ComponentName(context.packageName, ListWidgetProvider::class.java.name)
20-
val widgetData = widgetManager.getAppWidgetIds(componentName)
21+
return widgetManager.getAppWidgetIds(componentName)
2122
.map { it to ListWidgetProvider.getSavedSearch(context, it, dataRepository) }
2223
.toMap()
23-
return Response(true, widgetData)
2424
}
2525

26-
private fun setWidget(intent: Intent, context: Context): Response {
26+
private fun setWidget(intent: Intent, context: Context) {
2727
val widgetId = intent.getIntExtra("WIDGET_ID", -1)
28-
if (widgetId < 0) return Response(false, "invalid widget ID")
28+
if (widgetId < 0) throw ExternalHandlerFailure("invalid widget id")
2929
val savedSearch = intent.getSavedSearch()
30-
?: return Response(false, "invalid saved search ID")
3130

3231
context.sendBroadcast(Intent(context, ListWidgetProvider::class.java).apply {
3332
action = AppIntent.ACTION_SET_LIST_WIDGET_SELECTION
3433
putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId)
3534
putExtra(AppIntent.EXTRA_SAVED_SEARCH_ID, savedSearch.id)
3635
})
37-
38-
return Response()
3936
}
4037
}
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
package com.orgzly.android.external.actionhandlers
22

3-
import android.content.Context
43
import android.content.Intent
4+
import com.orgzly.android.external.types.ExternalHandlerFailure
5+
import com.orgzly.android.external.types.Note
56
import com.orgzly.android.query.user.InternalQueryParser
6-
import com.orgzly.android.external.types.*
77

88
class RunSearch : ExternalAccessActionHandler() {
99
override val actions = listOf(
1010
action(::runSearch, "SEARCH")
1111
)
1212

13-
private fun runSearch(intent: Intent): Response {
13+
private fun runSearch(intent: Intent): List<Note> {
1414
val searchTerm = intent.getStringExtra("QUERY")
15-
if (searchTerm.isNullOrBlank()) return Response(false, "Invalid search term!")
15+
if (searchTerm.isNullOrBlank()) throw ExternalHandlerFailure("invalid search term")
1616
val query = InternalQueryParser().parse(searchTerm)
1717
val notes = dataRepository.selectNotesFromQuery(query)
18-
return Response(true, notes.map(Note::from).toTypedArray())
18+
return notes.map(Note::from)
1919
}
2020
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package com.orgzly.android.external.types
2+
3+
class ExternalHandlerFailure(msg: String) : Exception(msg)

0 commit comments

Comments
 (0)