Skip to content

Commit f5ae44e

Browse files
authored
Merge pull request #20 from linked-planet/feature/refactor_manager_to_service
Feature/refactor manager to service
2 parents b1a3e4d + 1442d41 commit f5ae44e

File tree

11 files changed

+201
-122
lines changed

11 files changed

+201
-122
lines changed

kotlin-atlassian-client-core-common/src/main/kotlin/com/linkedplanet/kotlinatlassianclientcore/common/api/Page.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ open class Page<T> (
2828
@field:NotNull val currentPageIndex: Int,
2929
@field:NotNull val pageSize: Int
3030
) {
31+
@Suppress("unused") // useful for inheritance by clients
3132
constructor() : this(emptyList<T>(), 0, 0, 0, 1)
3233

3334
override fun equals(other: Any?): Boolean {

kotlin-jira-client/kotlin-jira-client-sdk/src/main/kotlin/com/linkedplanet/kotlinjiraclient/sdk/SdkJiraCommentOperator.kt

Lines changed: 41 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -20,48 +20,67 @@
2020
package com.linkedplanet.kotlinjiraclient.sdk
2121

2222
import arrow.core.Either
23+
import com.atlassian.jira.bc.JiraServiceContextImpl
24+
import com.atlassian.jira.bc.issue.IssueService
25+
import com.atlassian.jira.bc.issue.comment.CommentService
26+
import com.atlassian.jira.bc.issue.comment.CommentService.CommentParameters
2327
import com.atlassian.jira.component.ComponentAccessor
28+
import com.atlassian.jira.issue.MutableIssue
2429
import com.linkedplanet.kotlinjiraclient.api.error.JiraClientError
2530
import com.linkedplanet.kotlinjiraclient.api.interfaces.JiraCommentOperator
2631
import com.linkedplanet.kotlinjiraclient.api.model.JiraIssueComment
27-
import com.linkedplanet.kotlinjiraclient.sdk.util.catchJiraClientError
32+
import com.linkedplanet.kotlinjiraclient.sdk.util.*
2833

2934
object SdkJiraCommentOperator : JiraCommentOperator {
3035

31-
private val issueManager by lazy { ComponentAccessor.getIssueManager() }
32-
private val commentManager by lazy { ComponentAccessor.getCommentManager() }
33-
private val jiraAuthenticationContext by lazy { ComponentAccessor.getJiraAuthenticationContext() }
36+
private val issueService: IssueService = ComponentAccessor.getIssueService()
37+
private val commentService : CommentService = ComponentAccessor.getComponent(CommentService::class.java)
38+
private val jiraAuthenticationContext = ComponentAccessor.getJiraAuthenticationContext()
3439
private fun user() = jiraAuthenticationContext.loggedInUser
35-
private fun dispatchEvent(): Boolean = true // default dispatch behaviour for this operator
40+
private const val DISPATCH_EVENT: Boolean = true // default dispatch behaviour for this operator
3641

3742
override suspend fun getComments(issueKey: String): Either<JiraClientError, List<JiraIssueComment>> =
38-
Either.catchJiraClientError {
39-
val issue = issueManager.getIssueByCurrentKey(issueKey)
40-
val comments = commentManager.getComments(issue)
43+
eitherAndCatch {
44+
val issue = issueService.getIssue(user(), issueKey).toEither().bind().issue
45+
val comments = commentService.getCommentsForUser(user(), issue)
4146
comments.map { JiraIssueComment(it.id.toString(), it.body, it.authorFullName, it.updated.toString()) }
42-
}
47+
}
4348

4449
override suspend fun createComment(issueKey: String, content: String): Either<JiraClientError, Unit> =
45-
Either.catchJiraClientError {
46-
val issue = issueManager.getIssueByCurrentKey(issueKey)
47-
commentManager.create(issue, user(), content, dispatchEvent())
50+
eitherAndCatch {
51+
val issue = issueService.getIssue(user(), issueKey).toEither().bind().issue
52+
val commentParameters = newCommentParameters(issue, content)
53+
val validateComment = commentService.validateCommentCreate(user(), commentParameters).toEither().bind()
54+
commentService.create(user(), validateComment, DISPATCH_EVENT)
55+
validateComment.toEither().bind()
4856
}
4957

5058
override suspend fun updateComment(
5159
issueKey: String,
5260
commentId: String,
5361
content: String
54-
): Either<JiraClientError, Unit> =
55-
Either.catchJiraClientError {
56-
val comment = commentManager.getMutableComment(commentId.toLongOrNull()!!)
57-
comment.body = content
58-
comment.setUpdateAuthor(user())
59-
commentManager.update(comment, dispatchEvent())
60-
}
62+
): Either<JiraClientError, Unit> = eitherAndCatch {
63+
val issue = issueService.getIssue(user(), issueKey).toEither().bind().issue
64+
val commentParameters = newCommentParameters(issue, content)
65+
val valid = commentService.validateCommentUpdate(user(), commentId.toLong(), commentParameters).toEither().bind()
66+
commentService.update(user(), valid, DISPATCH_EVENT)
67+
}
6168

6269
override suspend fun deleteComment(issueKey: String, id: String): Either<JiraClientError, Unit> =
63-
Either.catchJiraClientError {
64-
val comment = commentManager.getCommentById(id.toLongOrNull()!!)
65-
commentManager.delete(comment, dispatchEvent(), user())
70+
eitherAndCatch {
71+
val comment = withErrorCollection { commentService.getCommentById(user(), id.toLongOrNull()!!, it) }.bind()
72+
val jiraServiceContextImpl = JiraServiceContextImpl(user())
73+
commentService.delete(jiraServiceContextImpl, comment, DISPATCH_EVENT)
74+
jiraServiceContextImpl.errorCollection.toEither().bind()
6675
}
76+
77+
private fun newCommentParameters(
78+
issue: MutableIssue,
79+
content: String
80+
): CommentParameters = CommentParameters.CommentParametersBuilder()
81+
.issue(issue)
82+
.body(content)
83+
.author(user())
84+
.build()
85+
6786
}

kotlin-jira-client/kotlin-jira-client-sdk/src/main/kotlin/com/linkedplanet/kotlinjiraclient/sdk/SdkJiraIssueLinkOperator.kt

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -20,49 +20,57 @@
2020
package com.linkedplanet.kotlinjiraclient.sdk
2121

2222
import arrow.core.Either
23+
import com.atlassian.jira.bc.issue.link.IssueLinkService
2324
import com.atlassian.jira.component.ComponentAccessor
25+
import com.atlassian.jira.issue.link.Direction
2426
import com.atlassian.jira.issue.link.IssueLinkTypeManager
2527
import com.linkedplanet.kotlinjiraclient.api.error.JiraClientError
2628
import com.linkedplanet.kotlinjiraclient.api.interfaces.JiraIssueLinkOperator
27-
import com.linkedplanet.kotlinjiraclient.sdk.util.catchJiraClientError
29+
import com.linkedplanet.kotlinjiraclient.sdk.util.eitherAndCatch
30+
import com.linkedplanet.kotlinjiraclient.sdk.util.toEither
2831

2932
object SdkJiraIssueLinkOperator : JiraIssueLinkOperator {
3033

31-
private val issueManager by lazy { ComponentAccessor.getIssueManager() }
32-
private val issueLinkManager by lazy { ComponentAccessor.getIssueLinkManager() }
33-
private val issueLinkTypeManager by lazy { ComponentAccessor.getComponent(IssueLinkTypeManager::class.java) }
34-
private val jiraAuthenticationContext by lazy { ComponentAccessor.getJiraAuthenticationContext() }
34+
private val issueService = ComponentAccessor.getIssueService()
35+
private val issueLinkService = ComponentAccessor.getComponent(IssueLinkService::class.java)
36+
private val issueLinkTypeManager = ComponentAccessor.getComponent(IssueLinkTypeManager::class.java)
37+
private val jiraAuthenticationContext = ComponentAccessor.getJiraAuthenticationContext()
3538

36-
private fun loggedInUser() = jiraAuthenticationContext.loggedInUser
39+
private fun user() = jiraAuthenticationContext.loggedInUser
40+
private const val DISPATCH_EVENT: Boolean = true // default dispatch behaviour for this operator
3741

3842
override suspend fun createIssueLink(
3943
inwardIssueKey: String,
4044
outwardIssueKey: String,
4145
relationName: String
4246
): Either<JiraClientError, Unit> =
43-
Either.catchJiraClientError {
44-
val inwardSourceIssue = issueManager.getIssueByCurrentKey(inwardIssueKey)
45-
val outwardIssue = issueManager.getIssueByCurrentKey(outwardIssueKey)
47+
eitherAndCatch {
48+
val user = user()
49+
val inwardSourceIssue = issueService.getIssue(user, inwardIssueKey).toEither().bind().issue
50+
val outwardIssue = issueService.getIssue(user, outwardIssueKey).toEither().bind().issue
4651
val linkType = issueLinkTypeManager.getIssueLinkTypesByName(relationName).firstOrNull()
4752
?: return issueLinkTypeNotFound(relationName)
48-
val sequence: Long? = null // For UI ordering. Sequence on links does not matter
49-
50-
issueLinkManager.createIssueLink(
51-
inwardSourceIssue.id,
52-
outwardIssue.id,
53+
val validate = issueLinkService.validateAddIssueLinks(
54+
user,
55+
outwardIssue,
5356
linkType.id,
54-
sequence,
55-
loggedInUser()
56-
)
57+
Direction.IN,
58+
listOf(inwardSourceIssue.key),
59+
DISPATCH_EVENT
60+
).toEither().bind()
61+
issueLinkService.addIssueLinks(user, validate)
5762
}
5863

5964
private fun issueLinkTypeNotFound(relationName: String): Either<JiraClientError, Unit> = Either.Left(
6065
JiraClientError("IssueLinkType not found", "No IssueLinkType named $relationName found.", statusCode = 404)
6166
)
6267

6368
override suspend fun deleteIssueLink(linkId: String): Either<JiraClientError, Unit> =
64-
Either.catchJiraClientError {
65-
val issueLink = issueLinkManager.getIssueLink(linkId.toLong())
66-
issueLinkManager.removeIssueLink(issueLink, loggedInUser())
69+
eitherAndCatch {
70+
val user = user()
71+
val issueLink = issueLinkService.getIssueLink(linkId.toLong(), user).toEither().bind().issueLink
72+
val issue = issueService.getIssue(user, issueLink.destinationId).toEither().bind().issue
73+
val validate = issueLinkService.validateDelete(user, issue, issueLink).toEither().bind()
74+
issueLinkService.delete(validate)
6775
}
6876
}

kotlin-jira-client/kotlin-jira-client-sdk/src/main/kotlin/com/linkedplanet/kotlinjiraclient/sdk/SdkJiraIssueOperator.kt

Lines changed: 2 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import arrow.core.Either
2323
import arrow.core.left
2424
import arrow.core.raise.either
2525
import arrow.core.right
26-
import com.atlassian.jira.bc.ServiceResult
2726
import com.atlassian.jira.bc.issue.search.SearchService
2827
import com.atlassian.jira.component.ComponentAccessor
2928
import com.atlassian.jira.event.type.EventDispatchOption
@@ -32,7 +31,6 @@ import com.atlassian.jira.issue.IssueInputParameters
3231
import com.atlassian.jira.issue.MutableIssue
3332
import com.atlassian.jira.jql.parser.JqlQueryParser
3433
import com.atlassian.jira.user.ApplicationUser
35-
import com.atlassian.jira.util.ErrorCollection
3634
import com.atlassian.jira.util.ErrorCollection.Reason
3735
import com.atlassian.jira.util.ErrorCollections
3836
import com.atlassian.jira.web.bean.I18nBean
@@ -46,7 +44,8 @@ import com.linkedplanet.kotlinjiraclient.api.model.JiraIssue
4644
import com.linkedplanet.kotlinjiraclient.sdk.field.SdkJiraField
4745
import com.linkedplanet.kotlinjiraclient.sdk.util.IssueJsonConverter
4846
import com.linkedplanet.kotlinjiraclient.sdk.util.catchJiraClientError
49-
import org.jetbrains.kotlin.util.removeSuffixIfPresent
47+
import com.linkedplanet.kotlinjiraclient.sdk.util.jiraClientError
48+
import com.linkedplanet.kotlinjiraclient.sdk.util.toEither
5049
import javax.inject.Named
5150
import kotlin.math.ceil
5251

@@ -128,31 +127,6 @@ object SdkJiraIssueOperator : JiraIssueOperator<SdkJiraField> {
128127
}.bind()
129128
}
130129

131-
private fun <T : ServiceResult> T.toEither(errorTitle: String? = null): Either<JiraClientError, T> =
132-
when {
133-
this.isValid -> Either.Right(this)
134-
else -> Either.Left(jiraClientError(this.errorCollection, errorTitle
135-
?: "${this::class.simpleName?.removeSuffixIfPresent("ServiceResult")}Error"))
136-
}
137-
138-
private fun ErrorCollection.toEither(errorTitle: String = "SdkError") : Either<JiraClientError, Unit> =
139-
when {
140-
this.hasAnyErrors() -> jiraClientError(this, errorTitle).left()
141-
else -> Unit.right()
142-
}
143-
144-
private fun jiraClientError(errorCollection: ErrorCollection, errorTitle: String = "SdkError"): JiraClientError {
145-
val worstReason: Reason? = Reason.getWorstReason(errorCollection.reasons)
146-
val httpStatusSuffix = worstReason?.let { " (${it.httpStatusCode})" } ?: ""
147-
return JiraClientError(
148-
errorTitle,
149-
errorCollection.errorMessages.joinToString(",\n")
150-
+ errorCollection.errors.map { "'$it.key':${it.value}" }.joinToString(",\n")
151-
+ httpStatusSuffix,
152-
statusCode = worstReason?.httpStatusCode
153-
)
154-
}
155-
156130
override suspend fun <T> getIssueById(
157131
id: Int,
158132
parser: suspend (JsonObject, Map<String, String>) -> Either<JiraClientError, T>

kotlin-jira-client/kotlin-jira-client-sdk/src/main/kotlin/com/linkedplanet/kotlinjiraclient/sdk/SdkJiraIssueTypeOperator.kt

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,33 +20,39 @@
2020
package com.linkedplanet.kotlinjiraclient.sdk
2121

2222
import arrow.core.Either
23+
import com.atlassian.jira.bc.project.ProjectService
2324
import com.atlassian.jira.component.ComponentAccessor
24-
import com.atlassian.jira.config.IssueTypeManager
25+
import com.atlassian.jira.config.IssueTypeService
2526
import com.atlassian.jira.issue.fields.screen.issuetype.IssueTypeScreenSchemeManager
2627
import com.atlassian.jira.issue.issuetype.IssueType
2728
import com.atlassian.jira.issue.operation.IssueOperations
2829
import com.linkedplanet.kotlinjiraclient.api.error.JiraClientError
2930
import com.linkedplanet.kotlinjiraclient.api.interfaces.JiraIssueTypeOperator
3031
import com.linkedplanet.kotlinjiraclient.api.model.JiraIssueType
3132
import com.linkedplanet.kotlinjiraclient.api.model.JiraIssueTypeAttribute
32-
import com.linkedplanet.kotlinjiraclient.sdk.util.catchJiraClientError
33+
import com.linkedplanet.kotlinjiraclient.sdk.util.eitherAndCatch
34+
import com.linkedplanet.kotlinjiraclient.sdk.util.toEither
3335
import javax.inject.Named
3436

3537
@Named
3638
object SdkJiraIssueTypeOperator : JiraIssueTypeOperator {
3739

38-
private val projectManager by lazy { ComponentAccessor.getProjectManager() }
39-
private val issueTypeManager by lazy { ComponentAccessor.getComponent(IssueTypeManager::class.java) }
40-
private val issueTypeScreenSchemeManager by lazy { ComponentAccessor.getComponent(IssueTypeScreenSchemeManager::class.java) }
40+
private val projectService = ComponentAccessor.getComponent(ProjectService::class.java)
41+
private val issueTypeService = ComponentAccessor.getComponent(IssueTypeService::class.java)
42+
private val issueTypeScreenSchemeManager = ComponentAccessor.getComponent(IssueTypeScreenSchemeManager::class.java)
43+
private val jiraAuthenticationContext = ComponentAccessor.getJiraAuthenticationContext()
44+
45+
private fun user() = jiraAuthenticationContext.loggedInUser
4146

4247
override suspend fun getAttributesOfIssueType(
4348
projectId: Number,
4449
issueTypeId: Number
4550
): Either<JiraClientError, List<JiraIssueTypeAttribute>> =
46-
Either.catchJiraClientError {
47-
val issueType = issueTypeManager.getIssueType(issueTypeId.toString())
51+
eitherAndCatch {
52+
val issueType = issueTypeService.getIssueType(user(), issueTypeId.toString()).orNull
53+
?: return@getAttributesOfIssueType issueTypeNotFound(issueTypeId)
4854
val screenSchemes = issueTypeScreenSchemeManager.getIssueTypeScreenScheme(
49-
projectManager.getProjectObj(projectId.toLong())
55+
projectService.getProjectById(user(), projectId.toLong()).toEither().bind().project
5056
)
5157
val screenScheme = screenSchemes.getEffectiveFieldScreenScheme(issueType)
5258
val createScreen = screenScheme.getFieldScreen(IssueOperations.CREATE_ISSUE_OPERATION)
@@ -58,16 +64,22 @@ object SdkJiraIssueTypeOperator : JiraIssueTypeOperator {
5864
fields
5965
}
6066

67+
private fun <T> issueTypeNotFound(issueTypeId: Number): Either<JiraClientError, T> = Either.Left(
68+
JiraClientError("IssueType not found", "No IssueType with id:$issueTypeId found.", statusCode = 404)
69+
)
70+
6171
override suspend fun getIssueType(issueTypeId: Number): Either<JiraClientError, JiraIssueType?> =
62-
Either.catchJiraClientError {
63-
issueTypeManager.getIssueType(issueTypeId.toString())?.let { it: IssueType ->
72+
eitherAndCatch {
73+
val issueType = issueTypeService.getIssueType(user(), issueTypeId.toString()).orNull
74+
?: return@getIssueType issueTypeNotFound(issueTypeId)
75+
issueType.let { it: IssueType ->
6476
JiraIssueType(it.id, it.name)
6577
}
6678
}
6779

6880
override suspend fun getIssueTypes(projectId: Number): Either<JiraClientError, List<JiraIssueType>> =
69-
Either.catchJiraClientError {
70-
projectManager.getProjectObj(projectId.toLong())?.issueTypes
81+
eitherAndCatch {
82+
projectService.getProjectById(user(), projectId.toLong()).toEither().bind().project?.issueTypes
7183
?.map { it: IssueType ->
7284
JiraIssueType(it.id, it.name)
7385
} ?: emptyList()

kotlin-jira-client/kotlin-jira-client-sdk/src/main/kotlin/com/linkedplanet/kotlinjiraclient/sdk/SdkJiraProjectOperator.kt

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,26 +20,31 @@
2020
package com.linkedplanet.kotlinjiraclient.sdk
2121

2222
import arrow.core.Either
23+
import com.atlassian.jira.bc.project.ProjectService
2324
import com.atlassian.jira.component.ComponentAccessor
2425
import com.linkedplanet.kotlinjiraclient.api.error.JiraClientError
2526
import com.linkedplanet.kotlinjiraclient.api.interfaces.JiraProjectOperator
2627
import com.linkedplanet.kotlinjiraclient.api.model.JiraProject
27-
import com.linkedplanet.kotlinjiraclient.sdk.util.catchJiraClientError
28+
import com.linkedplanet.kotlinjiraclient.sdk.util.eitherAndCatch
29+
import com.linkedplanet.kotlinjiraclient.sdk.util.toEither
2830

2931
object SdkJiraProjectOperator : JiraProjectOperator {
3032

31-
private val projectManager by lazy { ComponentAccessor.getProjectManager() }
33+
private val projectService = ComponentAccessor.getComponent(ProjectService::class.java)
34+
private val jiraAuthenticationContext = ComponentAccessor.getJiraAuthenticationContext()
35+
36+
private fun user() = jiraAuthenticationContext.loggedInUser
3237

3338
override suspend fun getProject(projectId: Number): Either<JiraClientError, JiraProject?> =
34-
Either.catchJiraClientError {
35-
projectManager.getProjectObj(projectId.toLong())?.let {
39+
eitherAndCatch {
40+
projectService.getProjectById(user(), projectId.toLong()).toEither().bind().get().let {
3641
JiraProject(it.id.toString(), it.key, it.name)
3742
}
3843
}
3944

4045
override suspend fun getProjects(): Either<JiraClientError, List<JiraProject>> =
41-
Either.catchJiraClientError {
42-
return Either.Right(projectManager.projects.map {
46+
eitherAndCatch {
47+
return Either.Right(projectService.getAllProjects(user()).toEither().bind().get().map {
4348
JiraProject(it.id.toString(), it.key, it.name)
4449
})
4550
}

0 commit comments

Comments
 (0)