Structure:
tempalates/seatBooking.html:
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>com.virtualpairprogrammers.theater.services.TheaterService Booking</title> </head> <body> <h1>com.virtualpairprogrammers.theater.services.TheaterService Booking</h1> <h2>Seat availability</h2> <form action="/checkAvailability" th:object="${bean}" method="POST"> <p>Check if seat number <select th:field="*{selectedSeatNum}"> <option th:each="n : ${bean.seatNums}" th:value="${n}" th:text="${n}" /> </select> in row <select th:field="*{selectedSeatRow}"> <option th:each="r : ${bean.seatRows}" th:value="${r}" th:text="${r}" /> </select> is available <input type="submit"/></p> </form> <p th:text="${bean.result}"></p> </body> </html>
Control/MainController:
package com.virtualpairprogrammers.theater.control import com.virtualpairprogrammers.theater.services.BookingService import com.virtualpairprogrammers.theater.services.TheaterService import org.springframework.beans.factory.annotation.Autowired import org.springframework.stereotype.Controller import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RequestMethod import org.springframework.web.servlet.ModelAndView @Controller class MainController { @Autowired lateinit var theaterService: TheaterService @Autowired lateinit var bookingService: BookingService @RequestMapping("") fun homePage() : ModelAndView { return ModelAndView("seatBooking", "bean", CheckAvailabilityBackingBean()) } @RequestMapping("checkAvailability", method= arrayOf(RequestMethod.POST)) fun checkAvailability(bean: CheckAvailabilityBackingBean): ModelAndView { val selectedSeat = theaterService.find(bean.selectedSeatNum, bean.selectedSeatRow) val result = bookingService.isSeatFree(selectedSeat) bean.result = "Seat $selectedSeat is " + if (result) "available" else "booked" return ModelAndView("seatBooking", "bean", bean) } } /* * A typical JavaServer Faces application includes one or more backing beans, * each of which is a type of JavaServer Faces managed bean that can be associated with * the components used in a particular page. * This section introduces the basic concepts of creating, configuring, * and using backing beans in an application. * */ class CheckAvailabilityBackingBean() { val seatNums = 1..36 val seatRows = 'A'..'O' // below must be var because those data are sent back and forward between // server and template var selectedSeatNum: Int = 1 var selectedSeatRow: Char = 'A' var result: String = "" }
domain/Seat:
package com.virtualpairprogrammers.theater.domain import java.math.BigDecimal data class Seat(val row: Char, val num: Int, val price: BigDecimal, val description: String) { override fun toString(): String = "Seat $row-$num $$price ($description)" }
services/TheaterService:
package com.virtualpairprogrammers.theater.services import com.virtualpairprogrammers.theater.domain.Seat import org.springframework.stereotype.Service import java.math.BigDecimal @Service class TheaterService { private val hiddenSeats = mutableListOf<Seat>() constructor() { fun getPrice(row: Int, num: Int) : BigDecimal { return when { row >=14 -> BigDecimal(14.50) num <=3 || num >= 34 -> BigDecimal(16.50) row == 1 -> BigDecimal(21) else -> BigDecimal(18) } } fun getDescription(row: Int, num: Int) : String { return when { row == 15 -> "Back Row" row == 14 -> "Cheaper Seat" num <=3 || num >= 34 -> "Restricted View" row <=2 -> "Best View" else -> "Standard Seat" } } for (row in 1..15) { for (num in 1..36) { hiddenSeats.add(Seat((row+64).toChar(), num, getPrice(row,num), getDescription(row,num) )) } } } val seats get() = hiddenSeats.toList() fun find(num: Int, row: Char): Seat { return seats.filter {it.row === row && it.num === num }.first() } }
services/BookingService:
package com.virtualpairprogrammers.theater.services import com.virtualpairprogrammers.theater.domain.Seat import org.springframework.stereotype.Service @Service class BookingService() { fun isSeatFree(seat: Seat): Boolean { return true } }