Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions docs/existing_use_cases_1.cml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
UseCase UC1_CML_Editing {
actor = "ContextMapper User"
actor = "Context Mapper User"
interactions =
"recognise" a "SyntaxError",
"recognise" a "CmlKeyword",
Expand All @@ -16,21 +16,21 @@ UseCase UC1_CML_Editing {
}

UseCase UC2_CML_QuickFix {
actor = "ContextMapper User"
actor = "Context Mapper User"
interactions =
"create" a "MissingBoundedContext",
"split" a "UserStory"
benefit = "I am able to fix small mistakes in my CML definition"
}

UseCase UC3_CML_Generate_ContextMap {
actor = "ContextMapper User"
actor = "Context Mapper User"
interactions = "generate" a "VisualContextMap"
benefit = "I am able to create a context map diagram from my CML context map"
}

UseCase UC4_CML_Generate_PlantUML {
actor = "ContextMapper User"
actor = "Context Mapper User"
interactions = "generate" a "PlantUmlDiagram"
benefit = "I am able to create visual representations of my CML definitions"
}
30 changes: 11 additions & 19 deletions docs/existing_use_cases_2.cml
Original file line number Diff line number Diff line change
@@ -1,31 +1,23 @@
UseCase UC5_CML_Generate_SketchMiner {
actor = "ContextMapper User"
actor = "Context Mapper User"
interactions = "generate" a "SketchMinerDiagram"
benefit = "I am able to create a BPMN diagram from my process flow definitions"
}

UseCase UC6_CML_Generate_MDSLContract {
actor = "ContextMapper User"
actor = "Context Mapper User"
interactions = "generate" a "MDSLContract"
benefit = "I am able to create an MDSL contract from my CML definitions"
}

UseCase UC7_CML_ServiceCutter {
actor = "ContextMapper User"
interactions =
"create" a "ServiceCutterConfiguration",
"generate" a "ServiceCutterDiagram"
benefit = "I am able to create ServiceCutter diagrams so I can visually see my service cuts"
}

UseCase UC8_CML_FreeMarker {
actor = "ContextMapper User"
UseCase UC7_CML_FreeMarker {
actor = "Context Mapper User"
interactions = "apply" a "FreeMakerTemplate"
benefit = "I am able to create my own files, e.g. Markdown, from my CML definitions"
}

UseCase UC9_CML_Refactorings {
actor = "ContextMapper User"
UseCase UC8_CML_Refactorings {
actor = "Context Mapper User"
interactions =
"split" an "Aggregate",
"split" a "BoundedContext",
Expand All @@ -39,14 +31,14 @@ UseCase UC9_CML_Refactorings {
benefit = "I am able to easily restructure my CML definitions"
}

UseCase UC10_CML_Discovery {
actor = "ContextMapper User"
interactions = "discover" a "ContextMapperDefintion" for "my existing project"
UseCase UC9_CML_Discovery {
actor = "Context Mapper User"
interactions = "discover" a "Context MapperDefintion" for "my existing project"
benefit = "I am able to get CML defintions for my existing project"
}

UseCase U11_CML_Validators {
actor = "ContextMapper User"
UseCase U10_CML_Validators {
actor = "Context Mapper User"
interactions = "validate" a "CMLFile"
benefit = "I am able to validate my CML files for their semantic correctness"
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,7 @@ package org.contextmapper.intellij.actions.generators
import com.intellij.openapi.project.Project
import com.redhat.devtools.lsp4ij.LanguageServerItem
import com.redhat.devtools.lsp4ij.LanguageServerManager
import com.redhat.devtools.lsp4ij.commands.CommandExecutor
import com.redhat.devtools.lsp4ij.commands.LSPCommandContext
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.contextmapper.intellij.actions.LspCommandExecutor
import org.contextmapper.intellij.utils.CONTEXT_MAPPER_SERVER_ID
import org.eclipse.lsp4j.Command
Expand All @@ -26,70 +22,78 @@ class ContextMapperGenerator(

val context = LSPCommandContext(command, project)

val languageServerResult = getLanguageServer()
if (languageServerResult.isFailure) {
future.complete(Result.failure(languageServerResult.exceptionOrNull()!!))
return future
}
context.preferredLanguageServerId = CONTEXT_MAPPER_SERVER_ID
context.preferredLanguageServer = languageServerResult.getOrNull()
languageServerManager.getLanguageServer(CONTEXT_MAPPER_SERVER_ID)
.thenAcceptAsync { languageServer ->
executeCommand(future, context, languageServer)
}
.exceptionally { throwable ->
future.complete(
Result.failure(
ContextMapperGeneratorException(
"Could not find language server instance.",
throwable,
),
),
)
null
}

val response = commandExecutor(context)
CoroutineScope(Dispatchers.IO).launch {
processResponse(response, future)
}
return future
}

private fun processResponse(
response: CommandExecutor.LSPCommandResponse,
future: CompletableFuture<Result<GeneratorResult>>
private fun executeCommand(
future: CompletableFuture<Result<GeneratorResult>>,
context: LSPCommandContext,
languageServerItem: LanguageServerItem?
) {
val result = response.response

if (result != null) {
try {
val returnedValue = result.join()
if (languageServerItem == null) {
future.complete(
Result.failure(
ContextMapperGeneratorException(
"Could not find language server instance.",
),
),
)
return
}
context.preferredLanguageServerId = CONTEXT_MAPPER_SERVER_ID
context.preferredLanguageServer = languageServerItem

val generatedFilesResult = extractGeneratedFiles(returnedValue)
if (generatedFilesResult.isFailure) {
future.complete(Result.failure(generatedFilesResult.exceptionOrNull()!!))
}
val response = commandExecutor(context).response
if (response == null) {
future.complete(Result.failure(ContextMapperGeneratorException("Generator failed without error")))
return
}

val generatedFiles = generatedFilesResult.getOrNull()!!
if (generatedFiles.isEmpty()) {
future.complete(Result.success(GeneratorResult(listOf())))
} else {
future.complete(Result.success(GeneratorResult(generatedFiles)))
}
} catch (ex: Exception) {
response.thenAcceptAsync { generatorResult -> processResponse(future, generatorResult) }
.exceptionally { throwable ->
future.complete(
Result.failure(
ContextMapperGeneratorException(
"Generator failed with exception: ${ex.message}",
ex,
"Generator failed with exception: ${throwable.message}",
throwable,
),
),
)
null
}
} else {
future.complete(Result.failure(ContextMapperGeneratorException("Generator failed without error")))
}
}

private fun getLanguageServer(): Result<LanguageServerItem?> {
return try {
val languageServer =
languageServerManager.getLanguageServer(CONTEXT_MAPPER_SERVER_ID)
.join()
Result.success(languageServer)
} catch (ex: Exception) {
Result.failure(
ContextMapperGeneratorException(
"Could not find language server instance.",
ex,
),
)
private fun processResponse(
future: CompletableFuture<Result<GeneratorResult>>,
generatorResult: Any
) {
val generatedFilesResult = extractGeneratedFiles(generatorResult)
if (generatedFilesResult.isFailure) {
future.complete(Result.failure(generatedFilesResult.exceptionOrNull()!!))
return
}

val generatedFiles = generatedFilesResult.getOrNull()!!
if (generatedFiles.isEmpty()) {
future.complete(Result.success(GeneratorResult(listOf())))
} else {
future.complete(Result.success(GeneratorResult(generatedFiles)))
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.contextmapper.intellij.actions.generators

import com.intellij.openapi.project.Project
import com.redhat.devtools.lsp4ij.LanguageServerItem
import com.redhat.devtools.lsp4ij.LanguageServerManager
import com.redhat.devtools.lsp4ij.commands.CommandExecutor
import com.redhat.devtools.lsp4ij.settings.UserDefinedLanguageServerSettings
Expand All @@ -17,6 +18,8 @@ import org.junit.jupiter.api.Assertions.assertNotNull
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import java.util.concurrent.CompletableFuture
import java.util.function.Consumer

class ContextMapperGeneratorTest() {
private val command = Command("TestCommand", "cmd.id")
Expand All @@ -35,7 +38,11 @@ class ContextMapperGeneratorTest() {
mockk(relaxed = true) {
every { getLanguageServer(any()) } returns
mockk {
every { join() } returns mockk(relaxed = true)
val actionSlot = slot<Consumer<LanguageServerItem?>>()
every { thenAcceptAsync(capture(actionSlot)) } answers {
actionSlot.captured.accept(mockk(relaxed = true))
CompletableFuture.completedFuture(null)
}
}
}
project =
Expand All @@ -55,7 +62,11 @@ class ContextMapperGeneratorTest() {
mockk<CommandExecutor.LSPCommandResponse> {
every { response } returns
mockk {
every { join() } returns listOf("diagram.puml")
val actionSlot = slot<Consumer<Any>>()
every { thenAcceptAsync(capture(actionSlot)) } answers {
actionSlot.captured.accept(listOf("diagram.puml"))
CompletableFuture.completedFuture(null)
}
}
}

Expand All @@ -74,7 +85,11 @@ class ContextMapperGeneratorTest() {
mockk<CommandExecutor.LSPCommandResponse> {
every { response } returns
mockk {
every { join() } returns listOf<String>()
val actionSlot = slot<Consumer<Any>>()
every { thenAcceptAsync(capture(actionSlot)) } answers {
actionSlot.captured.accept(listOf<String>())
CompletableFuture.completedFuture(null)
}
}
}

Expand All @@ -93,7 +108,10 @@ class ContextMapperGeneratorTest() {
mockk<CommandExecutor.LSPCommandResponse> {
every { response } returns
mockk {
every { join() } throws Exception("Test Exception")
val actionSlot = slot<Consumer<Any>>()
every { thenAcceptAsync(capture(actionSlot)) } answers {
CompletableFuture.failedFuture(Exception("Test Exception"))
}
}
}

Expand Down Expand Up @@ -128,7 +146,11 @@ class ContextMapperGeneratorTest() {
mockk<CommandExecutor.LSPCommandResponse> {
every { response } returns
mockk {
every { join() } returns mockk<ResponseErrorException>()
val actionSlot = slot<Consumer<Any>>()
every { thenAcceptAsync(capture(actionSlot)) } answers {
actionSlot.captured.accept(mockk<ResponseErrorException>())
CompletableFuture.completedFuture(null)
}
}
}

Expand All @@ -145,7 +167,10 @@ class ContextMapperGeneratorTest() {
fun testGeneratorWithMissingLanguageServer() {
every { languageServerManager.getLanguageServer(eq(CONTEXT_MAPPER_SERVER_ID)) } returns
mockk {
every { join() } throws RuntimeException()
val actionSlot = slot<Consumer<LanguageServerItem?>>()
every { thenAcceptAsync(capture(actionSlot)) } answers {
CompletableFuture.failedFuture(RuntimeException())
}
}

val result =
Expand Down
Loading