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
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import org.springframework.stereotype.Component
@Thing(id="chatagent", title="Chat Agent",
description="A chat agent.", type= LMOSThingType.AGENT)
@Context(prefix = LMOSContext.prefix, url = LMOSContext.url)
@Link(href = "lmos/capabilities", rel = "service-meta", type = "application/json")
@VersionInfo(instance = "1.0.0")
@Component
class ChatAgent(agentProvider: AgentProvider, @Property(readOnly = true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import ai.ancf.lmos.wot.JsonMapper
import ai.ancf.lmos.wot.Wot
import ai.ancf.lmos.wot.reflection.annotations.*
import ai.ancf.lmos.wot.reflection.annotations.Context
import ai.ancf.lmos.wot.reflection.annotations.Link
import ai.ancf.lmos.wot.reflection.annotations.VersionInfo
import ai.ancf.lmos.wot.thing.DEFAULT_CONTEXT
import ai.ancf.lmos.wot.thing.ExposedThing
Expand Down Expand Up @@ -77,6 +78,26 @@ object ExposedThingBuilder {
if(versionInfoAnnotation != null){
version = ai.ancf.lmos.wot.thing.schema.VersionInfo(versionInfoAnnotation.instance, versionInfoAnnotation.model)
}
clazz.findAnnotation<Link>()?.let { linkAnnotation ->
links.add(ai.ancf.lmos.wot.thing.schema.Link(
href = linkAnnotation.href,
type = linkAnnotation.type,
rel = linkAnnotation.rel,
anchor = linkAnnotation.anchor,
sizes = linkAnnotation.sizes,
hreflang = linkAnnotation.hreflang.toList()
))
}
clazz.findAnnotation<Links>()?.values?.forEach { linkAnnotation ->
links.add(ai.ancf.lmos.wot.thing.schema.Link(
href = linkAnnotation.href,
type = linkAnnotation.type,
rel = linkAnnotation.rel,
anchor = linkAnnotation.anchor,
sizes = linkAnnotation.sizes,
hreflang = linkAnnotation.hreflang.toList()
))
}
// 3. Inspect the properties of the class and find @Property annotations
clazz.memberProperties.forEach { property ->
val propertyAnnotation = property.findAnnotation<Property>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,21 @@ annotation class Context(val prefix: String, val url : String)
@Retention(AnnotationRetention.RUNTIME)
annotation class VersionInfo(val instance : String, val model : String = "")

@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
annotation class Link(
val href: String,
val type: String = "",
val rel: String = "",
val anchor: String = "",
val sizes: String = "",
val hreflang: Array<String> = []
)

@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
annotation class Links(val values: Array<Link>)

@Target(AnnotationTarget.PROPERTY, AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.TYPE_PARAMETER)
@Retention(AnnotationRetention.RUNTIME)
annotation class Property(val title: String = "", val description: String = "", val readOnly: Boolean = false, val writeOnly: Boolean = false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class ComplexThingTest {
assertEquals("Complex Thing", thingDescription.title, "ThingDescription title should match")
assertEquals("A thing with complex properties, actions, and events.", thingDescription.description, "ThingDescription description should match")
assertEquals("1.0.0", thingDescription.version?.instance)
assertEquals(listOf(Link("my/link", "my/type", "my-rel", "my-anchor", "my-sizes", listOf("my-lang-1", "my-lang-2"))), thingDescription.links)
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import ai.ancf.lmos.wot.content.toJsonContent
import ai.ancf.lmos.wot.reflection.things.SimpleThing
import ai.ancf.lmos.wot.thing.ExposedThing
import ai.ancf.lmos.wot.thing.schema.ContentListener
import ai.ancf.lmos.wot.thing.schema.Link
import ai.ancf.lmos.wot.thing.schema.StringSchema
import ai.ancf.lmos.wot.thing.schema.WoTThingDescription
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.runTest
import java.util.concurrent.CountDownLatch
Expand All @@ -21,6 +23,7 @@ class SimpleThingTest {
lateinit var wot: Wot
lateinit var simpleThing: SimpleThing
lateinit var exposedThing: ExposedThing
lateinit var thingDescription: WoTThingDescription

@BeforeTest
fun setUp() = runTest {
Expand All @@ -35,11 +38,22 @@ class SimpleThingTest {

// Generate ThingDescription from the class
exposedThing = ExposedThingBuilder.createExposedThing(wot, simpleThing, SimpleThing::class) as ExposedThing
thingDescription = exposedThing.getThingDescription()

servient.addThing(exposedThing)
servient.expose("simpleThing")
}

@Test
fun `test ThingDescription creation for SimpleThing`() {
// Validate Thing metadata
assertEquals("simpleThing", thingDescription.id, "ThingDescription ID should match the class ID")
assertEquals("Simple Thing", thingDescription.title, "ThingDescription title should match")
assertEquals("A thing with complex properties, actions, and events.", thingDescription.description, "ThingDescription description should match")
assertEquals("1.0.0", thingDescription.version?.instance)
assertEquals(listOf(Link("my/link", "my/type", "my-rel", "my-anchor", "my-sizes", listOf("my-lang-1", "my-lang-2"))), thingDescription.links)
}

@Test
fun `Read mutable property`() = runTest {
val content = exposedThing.handleReadProperty("mutableProperty")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@ import kotlin.random.Random
title = "Complex Thing",
description = "A thing with complex properties, actions, and events."
)
@Links(
values = [Link(
href = "my/link",
rel = "my-rel",
type = "my/type",
anchor = "my-anchor",
sizes = "my-sizes",
hreflang = ["my-lang-1", "my-lang-2"]
)]
)
@VersionInfo(instance = "1.0.0")
class ComplexThing(@Property(readOnly = true) val constructorProperty: String = "Hello World") {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ import kotlinx.coroutines.flow.flow
title = "Simple Thing",
description = "A thing with complex properties, actions, and events."
)
@Link(
href = "my/link",
rel = "my-rel",
type = "my/type",
anchor = "my-anchor",
sizes = "my-sizes",
hreflang = ["my-lang-1", "my-lang-2"]
)
@VersionInfo(instance = "1.0.0")
class SimpleThing {

Expand Down
2 changes: 1 addition & 1 deletion kotlin-wot/src/main/kotlin/thing/ThingDescription.kt
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ data class ThingDescription @JsonCreator constructor(
@JsonInclude(NON_EMPTY) override var created: String? = null,
@JsonInclude(NON_EMPTY) override var modified: String? = null,
@JsonInclude(NON_EMPTY) override var support: String? = null,
@JsonInclude(NON_EMPTY) override var links: List<Link>? = null,
@JsonInclude(NON_EMPTY) override var links: MutableList<Link> = mutableListOf(),
@JsonFormat(with = [JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY]) @JsonInclude(NON_EMPTY) override var profile: List<String>? = null,
@JsonInclude(NON_EMPTY) override var schemaDefinitions: MutableMap<String, DataSchema<Any>>? = null,
@JsonInclude(NON_EMPTY) override var uriVariables: MutableMap<String, DataSchema<Any>>? = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ interface WoTThingDescription : BaseSchema {
* @return an array of links.
*/
@get:JsonInclude(JsonInclude.Include.NON_EMPTY)
var links: List<Link>? // Optional: Array of Link
var links: MutableList<Link> // Optional: Array of Link

/**
* Set of form hypermedia controls that describe how an operation can be performed.
Expand Down
Loading