@@ -4,10 +4,12 @@ import ai.ancf.lmos.wot.Servient
44import ai.ancf.lmos.wot.content.Content
55import ai.ancf.lmos.wot.content.ContentCodecException
66import ai.ancf.lmos.wot.content.ContentManager
7+ import ai.ancf.lmos.wot.thing.ExposedThing
8+ import ai.ancf.lmos.wot.thing.ThingDescription
79import ai.ancf.lmos.wot.thing.form.Form
810import ai.ancf.lmos.wot.thing.form.Operation
9- import ai.ancf.lmos.wot.thing.schema.ExposedThing
1011import ai.ancf.lmos.wot.thing.schema.InteractionAffordance
12+ import ai.ancf.lmos.wot.thing.schema.WoTExposedThing
1113import ai.anfc.lmos.wot.binding.ProtocolServer
1214import ai.anfc.lmos.wot.binding.ProtocolServerException
1315import com.fasterxml.jackson.databind.DeserializationFeature
@@ -18,11 +20,13 @@ import io.ktor.server.application.*
1820import io.ktor.server.engine.*
1921import io.ktor.server.netty.*
2022import io.ktor.server.plugins.contentnegotiation.*
23+ import io.ktor.server.plugins.statuspages.*
2124import io.ktor.server.request.*
25+ import io.ktor.server.response.*
2226import io.ktor.server.routing.*
2327import io.ktor.util.reflect.*
28+ import io.ktor.utils.io.*
2429import org.slf4j.LoggerFactory
25- import java.util.concurrent.ExecutionException
2630import kotlin.collections.set
2731
2832/* *
@@ -192,20 +196,25 @@ fun defaultServer(host: String, port: Int, servient: Servient): EmbeddedServer<*
192196}
193197
194198fun Application.setupRouting (servient : Servient ) {
199+ install(StatusPages ) {
200+ exception<IllegalArgumentException > { call, cause ->
201+ call.respondText(text = " 500: $cause " , status = HttpStatusCode .InternalServerError )
202+ throw cause // re-throw if you want it to be logged
203+ }
204+ }
195205 setupJackson()
196-
197206 routing {
198207 route(" /" ) {
199208 get {
200- call.respond(servient.things.values.toList(), typeInfo<List <ExposedThing >>())
209+ call.respond(servient.things.values.toList(), typeInfo<List <WoTExposedThing >>())
201210 }
202211 }
203212 route(" /{id}" ) {
204213 get {
205214 val id = call.parameters[" id" ]
206215 val thing: ExposedThing ? = servient.things[id]
207216 if (thing != null ) {
208- call.respond(thing, typeInfo<ExposedThing >())
217+ call.respond(thing, typeInfo<ThingDescription >())
209218 } else {
210219 call.response.status(HttpStatusCode .NotFound )
211220 }
@@ -218,23 +227,16 @@ fun Application.setupRouting(servient: Servient) {
218227 */
219228 get {
220229 val id = call.parameters[" id" ] ? : return @get call.response.status(HttpStatusCode .BadRequest )
221- val propertyName = call.parameters[" name" ]
230+ val propertyName = call.parameters[" name" ] ? : return @get call.response.status( HttpStatusCode . BadRequest )
222231 val thing = servient.things[id] ? : return @get call.response.status(HttpStatusCode .NotFound )
223232 val property = thing.properties[propertyName]
224233 if (property != null ) {
225234 if (! property.writeOnly) {
226- try {
227-
228- thing.
229-
230- // val value = property.read()
231- // contentType = getOrDefaultRequestContentType(call.request)
232- // val content = ContentManager.valueToContent(value, contentType.toString())
233-
234- }
235- catch (e: ContentCodecException ) {
236- call.response.status(HttpStatusCode .InternalServerError )
237- } catch (e: ExecutionException ) {
235+ try {
236+ val content = thing.handleReadProperty(propertyName)
237+ call.respondBytes { content.body }
238+ }
239+ catch (e: ContentCodecException ) {
238240 call.response.status(HttpStatusCode .InternalServerError )
239241 }
240242 } else {
@@ -246,50 +248,36 @@ fun Application.setupRouting(servient: Servient) {
246248 }
247249 put {
248250 val id = call.parameters[" id" ] ? : return @put call.response.status(HttpStatusCode .BadRequest )
249- val propertyName = call.parameters[" name" ]
251+ val propertyName = call.parameters[" name" ] ? : return @put call.response.status( HttpStatusCode . BadRequest )
250252 val thing = servient.things[id] ? : return @put call.response.status(HttpStatusCode .NotFound )
251- val property = thing.properties[propertyName]
252- if (property != null ) {
253- if (! property.readOnly) {
254- // val contentType = getOrDefaultRequestContentType(call.request)
255- // val content = Content(contentType.toString(), call.receiveChannel().toByteArray())
256-
257-
258- } else {
259- call.response.status(HttpStatusCode .BadRequest )
260- }
253+ val property = thing.properties[propertyName] ? : return @put call.response.status(HttpStatusCode .NotFound )
254+ val contentType = getOrDefaultRequestContentType(call.request)
255+ val content = Content (contentType.toString(), call.receiveChannel().toByteArray())
256+ if (! property.readOnly && content.body.isNotEmpty()) {
257+ call.respondBytes { thing.handleWriteProperty(propertyName, content).body }
261258 } else {
262- call.response.status(HttpStatusCode .NotFound )
259+ call.response.status(HttpStatusCode .BadRequest )
263260 }
264261 }
265262 }
266263 post(" /actions/{name}" ) {
267264 val id = call.parameters[" id" ] ? : return @post call.response.status(HttpStatusCode .BadRequest )
268- val actionName = call.parameters[" name" ]
265+ val actionName = call.parameters[" name" ] ? : return @post call.response.status( HttpStatusCode . BadRequest )
269266 val thing = servient.things[id] ? : return @post call.response.status(HttpStatusCode .NotFound )
270- val action = thing.actions[actionName]
271- if (action != null ) {
272- val requestContentType = getOrDefaultRequestContentType(call.request).toString()
273- val content = Content (requestContentType, call.receive())
274-
275- if (action.input != null ){
276- val input = ContentManager .contentToValue(content, action.input!! )
277- // val newValue = action.invokeAction(input, null)
278- // call.respond(newValue, typeInfo<Any>())
279- }else {
280- // val newValue = action.invokeAction(null, null)
281- // call.respond(newValue, typeInfo<Any>())
267+ val action = thing.actions[actionName] ? : return @post call.response.status(HttpStatusCode .NotFound )
268+ val contentType = getOrDefaultRequestContentType(call.request)
269+ val content = Content (contentType.toString(), call.receiveChannel().toByteArray())
270+ if (action.input != null && content.body.isEmpty()) {
271+ call.response.status(HttpStatusCode .BadRequest )
272+ }else {
273+ val actionResult = thing.handleInvokeAction(actionName, content)
274+ if (actionResult != null && actionResult.body.isNotEmpty()) {
275+ call.respondBytes { actionResult.body }
276+ } else {
277+ call.response.status(HttpStatusCode .NoContent )
282278 }
283-
284-
285- /*
286- val options = mapOf<String, Map<String, Any>>(
287- "uriVariables" to parseUrlParameters(request.queryMap().toMap(), action.uriVariables)
288- )
289- */
290- } else {
291- call.response.status(HttpStatusCode .NotFound )
292279 }
280+
293281 }
294282 get(" /events/{name}" ) {
295283 call.response.status(HttpStatusCode .OK )
0 commit comments