Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.core.notifications

fun checkSeverity(notificationSeverity: String): NotificationSeverity = when (notificationSeverity) {

Check warning

Code scanning / QDJVMC

Unused symbol Warning

Function "checkSeverity" is never used
"Critical" -> NotificationSeverity.CRITICAL
"Warning" -> NotificationSeverity.WARNING
"Info" -> NotificationSeverity.INFO
else -> NotificationSeverity.INFO
}

// TODO: Add actions that can be performed from the notifications here
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.core.notifications

import com.intellij.notification.NotificationType
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.project.Project

object DisplayToastNotifications {

Check warning on line 10 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/DisplayToastNotifications.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Unused symbol

Object "DisplayToastNotifications" is never used
fun show(title: String, message: String, action: List<AnAction>, notificationType: NotificationSeverity) {
val notifyType = when (notificationType) {
NotificationSeverity.CRITICAL -> NotificationType.ERROR
NotificationSeverity.WARNING -> NotificationType.WARNING
NotificationSeverity.INFO -> NotificationType.INFORMATION
}

}

fun shouldShow(project: Project, notificationData: NotificationData) {

Check warning on line 20 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/DisplayToastNotifications.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Unused symbol

Function "shouldShow" is never used
if (RulesEngine.displayNotification(notificationData, project)) {
val notificationContent = notificationData.content.locale
val severity = notificationData.severity
show(notificationContent.title, notificationContent.description, emptyList(), checkSeverity(severity))
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.core.notifications

import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.core.JsonToken
import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.JsonDeserializer
import com.fasterxml.jackson.databind.JsonMappingException
import com.fasterxml.jackson.databind.JsonNode

class OperationConditionDeserializer : JsonDeserializer<NotificationExpression.OperationCondition>() {
override fun deserialize(parser: JsonParser, ctxt: DeserializationContext): NotificationExpression.OperationCondition = when (parser.currentToken) {
JsonToken.VALUE_STRING -> {
// Handle direct string value
NotificationExpression.OperationCondition(parser.valueAsString)
}
else -> throw JsonMappingException(parser, "Cannot deserialize OperatingCondition")
}
}

class ComparisonConditionDeserializer : JsonDeserializer<NotificationExpression.ComparisonCondition>() {
override fun deserialize(parser: JsonParser, ctxt: DeserializationContext): NotificationExpression.ComparisonCondition {
val op = OperationConditionDeserializer().deserialize(parser, ctxt)
return NotificationExpression.ComparisonCondition(op.value)
}
}

class NotEqualsConditionDeserializer : JsonDeserializer<NotificationExpression.NotEqualsCondition>() {
override fun deserialize(parser: JsonParser, ctxt: DeserializationContext): NotificationExpression.NotEqualsCondition {
val op = OperationConditionDeserializer().deserialize(parser, ctxt)
return NotificationExpression.NotEqualsCondition(op.value)
}
}
class GreaterThanConditionDeserializer : JsonDeserializer<NotificationExpression.GreaterThanCondition>() {
override fun deserialize(parser: JsonParser, ctxt: DeserializationContext): NotificationExpression.GreaterThanCondition {
val op = OperationConditionDeserializer().deserialize(parser, ctxt)
return NotificationExpression.GreaterThanCondition(op.value)
}
}
class GreaterThanOrEqualsConditionDeserializer : JsonDeserializer<NotificationExpression.GreaterThanOrEqualsCondition>() {
override fun deserialize(parser: JsonParser, ctxt: DeserializationContext): NotificationExpression.GreaterThanOrEqualsCondition {
val op = OperationConditionDeserializer().deserialize(parser, ctxt)
return NotificationExpression.GreaterThanOrEqualsCondition(op.value)
}
}
class LessThanConditionDeserializer : JsonDeserializer<NotificationExpression.LessThanCondition>() {
override fun deserialize(parser: JsonParser, ctxt: DeserializationContext): NotificationExpression.LessThanCondition {
val op = OperationConditionDeserializer().deserialize(parser, ctxt)
return NotificationExpression.LessThanCondition(op.value)
}
}
class LessThanOrEqualsConditionDeserializer : JsonDeserializer<NotificationExpression.LessThanOrEqualsCondition>() {
override fun deserialize(parser: JsonParser, ctxt: DeserializationContext): NotificationExpression.LessThanOrEqualsCondition {
val op = OperationConditionDeserializer().deserialize(parser, ctxt)
return NotificationExpression.LessThanOrEqualsCondition(op.value)
}
}
class ComplexOperationConditionDeserializer : JsonDeserializer<NotificationExpression.ComplexOperationCondition>() {
override fun deserialize(parser: JsonParser, ctxt: DeserializationContext): NotificationExpression.ComplexOperationCondition {
val node = parser.codec.readTree<JsonNode>(parser)
if (!node.isArray) {
throw JsonMappingException(parser, "anyOf/noneOf must contain an array of values")
}
val values = node.map { it.asText() }
return NotificationExpression.ComplexOperationCondition(values)
}
}
class AnyOfConditionDeserializer : JsonDeserializer<NotificationExpression.AnyOfCondition>() {
override fun deserialize(parser: JsonParser, ctxt: DeserializationContext): NotificationExpression.AnyOfCondition {
val op = ComplexOperationConditionDeserializer().deserialize(parser, ctxt)
return NotificationExpression.AnyOfCondition(op.value)
}
}

class NoneOfConditionDeserializer : JsonDeserializer<NotificationExpression.NoneOfCondition>() {
override fun deserialize(parser: JsonParser, ctxt: DeserializationContext): NotificationExpression.NoneOfCondition {
val op = ComplexOperationConditionDeserializer().deserialize(parser, ctxt)
return NotificationExpression.NoneOfCondition(op.value)
}
}

class ComplexConditionDeserializer : JsonDeserializer<NotificationExpression.ComplexCondition>() {
override fun deserialize(parser: JsonParser, ctxt: DeserializationContext): NotificationExpression.ComplexCondition {
val node = parser.codec.readTree<JsonNode>(parser)
if (!node.isArray) {
throw JsonMappingException(parser, "or/and must contain an array of values")
}
return NotificationExpression.ComplexCondition(node.toNotificationExpressions(parser))
}
}
class OrConditionDeserializer : JsonDeserializer<NotificationExpression.OrCondition>() {
override fun deserialize(parser: JsonParser, ctxt: DeserializationContext): NotificationExpression.OrCondition {
val op = ComplexConditionDeserializer().deserialize(parser, ctxt)
return NotificationExpression.OrCondition(op.expectedValueList)
}
}

class AndConditionDeserializer : JsonDeserializer<NotificationExpression.AndCondition>() {
override fun deserialize(parser: JsonParser, ctxt: DeserializationContext): NotificationExpression.AndCondition {
val op = ComplexConditionDeserializer().deserialize(parser, ctxt)
return NotificationExpression.AndCondition(op.expectedValueList)
}
}

class NotConditionDeserializer : JsonDeserializer<NotificationExpression.NotCondition>() {
override fun deserialize(p: JsonParser, ctxt: DeserializationContext): NotificationExpression.NotCondition {
val node = p.codec.readTree<JsonNode>(p)
val parser = node.traverse(p.codec)
parser.nextToken()

return NotificationExpression.NotCondition(parser.readValueAs(NotificationExpression::class.java))
}
}

private fun JsonNode.toNotificationExpressions(p: JsonParser): List<NotificationExpression> = this.map { element ->
val parser = element.traverse(p.codec)
parser.nextToken()
parser.readValueAs(NotificationExpression::class.java)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.core.notifications

import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.annotation.JsonSubTypes
import com.fasterxml.jackson.annotation.JsonTypeInfo
import com.fasterxml.jackson.databind.annotation.JsonDeserialize

data class NotificationsList(
@JsonProperty("schema")
val schema: Schema,
@JsonProperty("notifications")
val notifications: List<NotificationData>?,
)

data class Schema(
@JsonProperty("version")
val version: String,
)

data class NotificationData(
@JsonProperty("id")
val id: String,
@JsonProperty("schedule")
val schedule: NotificationSchedule,
@JsonProperty("severity")
val severity: String,
@JsonProperty("condition")
val condition: NotificationDisplayCondition?,
@JsonProperty("content")
val content: NotificationContentDescriptionLocale,
@JsonProperty("actions")
val actions: List<NotificationFollowupActions>? = emptyList(),
)

data class NotificationSchedule(
@JsonProperty("type")
val type: String,
)

enum class NotificationSeverity {
INFO,
WARNING,
CRITICAL,
}

data class NotificationContentDescriptionLocale(
@JsonProperty("en-US")
val locale: NotificationContentDescription,
)

data class NotificationContentDescription(
@JsonProperty("title")
val title: String,
@JsonProperty("description")
val description: String,
)

data class NotificationFollowupActions(
@JsonProperty("type")
val type: String,
@JsonProperty("content")
val content: NotificationFollowupActionsContent,
)

data class NotificationFollowupActionsContent(
@JsonProperty("en-US")
val locale: NotificationActionDescription,
)

data class NotificationActionDescription(
@JsonProperty("title")
val title: String,
@JsonProperty("url")
val url: String?,
)

data class NotificationDisplayCondition(
@JsonProperty("compute")
val compute: ComputeType?,
@JsonProperty("os")
val os: SystemType?,
@JsonProperty("ide")
val ide: SystemType?,
@JsonProperty("extension")
val extension: List<ExtensionType>?,
@JsonProperty("authx")
val authx: List<AuthxType>?,
)

data class ComputeType(
@JsonProperty("type")
val type: NotificationExpression?,
@JsonProperty("architecture")
val architecture: NotificationExpression?,
)

data class SystemType(
@JsonProperty("type")
val type: NotificationExpression?,
@JsonProperty("version")
val version: NotificationExpression?,
)

data class ExtensionType(
@JsonProperty("id")
val id: String?,
@JsonProperty("version")
val version: NotificationExpression?,
)

@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.WRAPPER_OBJECT
)
@JsonSubTypes(
JsonSubTypes.Type(value = NotificationExpression.ComparisonCondition::class, name = "=="),
JsonSubTypes.Type(value = NotificationExpression.NotEqualsCondition::class, name = "!="),
JsonSubTypes.Type(value = NotificationExpression.GreaterThanCondition::class, name = ">"),
JsonSubTypes.Type(value = NotificationExpression.GreaterThanOrEqualsCondition::class, name = ">="),
JsonSubTypes.Type(value = NotificationExpression.LessThanCondition::class, name = "<"),
JsonSubTypes.Type(value = NotificationExpression.LessThanOrEqualsCondition::class, name = "<="),
JsonSubTypes.Type(value = NotificationExpression.AnyOfCondition::class, name = "anyOf"),
JsonSubTypes.Type(value = NotificationExpression.NotCondition::class, name = "not"),
JsonSubTypes.Type(value = NotificationExpression.OrCondition::class, name = "or"),
JsonSubTypes.Type(value = NotificationExpression.AndCondition::class, name = "and"),
JsonSubTypes.Type(value = NotificationExpression.NoneOfCondition::class, name = "noneOf")
)
sealed class NotificationExpression {
@JsonDeserialize(using = NotConditionDeserializer::class)
data class NotCondition(
val expectedValue: NotificationExpression,
) : NotificationExpression()

@JsonDeserialize(using = OrConditionDeserializer::class)
data class OrCondition(
val expectedValueList: List<NotificationExpression>,
) : NotificationExpression()

@JsonDeserialize(using = AndConditionDeserializer::class)
data class AndCondition(
val expectedValueList: List<NotificationExpression>,
) : NotificationExpression()

@JsonDeserialize(using = ComplexConditionDeserializer::class)
data class ComplexCondition(
val expectedValueList: List<NotificationExpression>,
) : NotificationExpression()

// General class for comparison operators
@JsonDeserialize(using = OperationConditionDeserializer::class)
data class OperationCondition(
val value: String,
) : NotificationExpression()

@JsonDeserialize(using = ComplexOperationConditionDeserializer::class)
data class ComplexOperationCondition(
val value: List<String>,
) : NotificationExpression()

@JsonDeserialize(using = ComparisonConditionDeserializer::class)
data class ComparisonCondition(
val value: String,
) : NotificationExpression()

@JsonDeserialize(using = NotEqualsConditionDeserializer::class)
data class NotEqualsCondition(
val value: String,
) : NotificationExpression()

@JsonDeserialize(using = GreaterThanConditionDeserializer::class)
data class GreaterThanCondition(
val value: String,
) : NotificationExpression()

@JsonDeserialize(using = GreaterThanOrEqualsConditionDeserializer::class)
data class GreaterThanOrEqualsCondition(
val value: String,
) : NotificationExpression()

@JsonDeserialize(using = LessThanConditionDeserializer::class)
data class LessThanCondition(
val value: String,
) : NotificationExpression()

@JsonDeserialize(using = LessThanOrEqualsConditionDeserializer::class)
data class LessThanOrEqualsCondition(
val value: String,
) : NotificationExpression()

@JsonDeserialize(using = AnyOfConditionDeserializer::class)
data class AnyOfCondition(
val value: List<String>,
) : NotificationExpression()

@JsonDeserialize(using = NoneOfConditionDeserializer::class)
data class NoneOfCondition(
val value: List<String>,
) : NotificationExpression()
}

data class AuthxType(
@JsonProperty("feature")
val feature: String,
@JsonProperty("type")
val type: NotificationExpression?,
@JsonProperty("region")
val region: NotificationExpression?,
@JsonProperty("connectionState")
val connectionState: NotificationExpression?,
@JsonProperty("ssoscopes")
val ssoScopes: NotificationExpression?,
)
Loading
Loading