下面是一个控制器NameController,派生自BaseController。 NameSpaceController中create方法的端点继承自BaseController。如何在BaseController中注释create方法,以使swagger UI中的每个控制器的Model Schema特定于该类?下面我已经包含了NameSpaceController,BaseController,Model(父模型)和NameSpace模型。
//NameSpace Controller
@Api(value = "Namespace Controller")
class NamespaceController @Inject()(namespaceRepo: NamespaceRepository)
(implicit val executionContext: ExecutionContext) extends BaseController[NamespaceRepository, Namespace](namespaceRepo) {
/**
* Retrieve all Namespaces.
*
* @return sequence of all existing Namespaces
*/
@ApiOperation(value = "Get Namespaces", notes = "Returns all existing Namespaces")
@ApiResponses(Array(
new ApiResponse(code = 500, message = "Internal Server Error"),
new ApiResponse (code = 200, message = "Successful", response = classOf[Namespace])))
def getNamespaces() = Action.async {
namespaceRepo.getNamespaces.map(namespaces => Ok(Json.toJson(namespaces))) recover handleError(s"Error retrieving namespaces.")
}
}
//BaseController
abstract class BaseController[R <: Repository[_, T], T <: Model] @Inject()(repo: R)
(implicit executionContext: ExecutionContext, formatT: Format[T]) extends Controller {
/**
* Creates a new entity.
*
* @return id of the new entity
*/
//Create method annotations
@ApiOperation(value = "Creates a new entity", notes = "Returns id of new entity")
@ApiImplicitParams(Array(
new ApiImplicitParam(
value = "Create an entity",
required = true,
dataType = "com.bamtech.cde.hydra.api.models.Model", //How can this resolve to the derived class?
paramType = "body"
)
))
@ApiResponse(code = 500, message = "Internal Server Error")
def create() = Action.async(parse.json) { request =>
request.body.validate[T].fold(
errors => {
Future(BadRequest(JsError.toJson(errors)))
},
item => {
repo.create(item).map(id => Ok(id.toString)) recover handleError(s"Error creating new item: $item.")
}
)
}
/**
* Retrieves a single entity by its id.
*
* @param id the entity's primary key
* @return the entity identified by `id`, or a 404 if the entity doesn't exist
*/
@ApiOperation(value = "Get entity by ID", notes = "Returns entity identified by ID")
@ApiResponses(Array(
new ApiResponse(code = 500, message = "Internal Server Error"),
new ApiResponse(code = 404, message = "Not Found"),
new ApiResponse(code = 200, message = "Successful", response = classOf[Model])
))
def getById(id: Int) = Action.async {
repo.getById(id).map {
case Some(item) => Ok(Json.toJson(item))
case None => NotFound(s"Item $id does not exist.")
} recover handleError(s"Error retrieving item $id.")
}
/**
* Updates the entity identified by `id`
*
* @param id the entity's primary key
* @return the number of rows affected by the update
*/
def update(/*@ApiParam(value = "ID of the pet to fetch")*/ id: Int) = Action.async(parse.json) { request =>
request.body.validate[T].fold(
errors => {
Future(BadRequest(JsError.toJson(errors)))
},
item => {
if (id != item.getId) {
Future(BadRequest(s"Entity id: $id doesn't match payload id: ${item.getId}."))
} else {
repo.update(item, id).map(rows => Ok(rows.toString)) recover handleError(s"Error updating item: $item.")
}
}
)
}
/**
* Soft deletes the entity identified by `id`
*
* @param id the entity's primary key
* @return the number of rows affected by the soft delete
*/
def delete(id: Int) = Action.async {
repo.setIsDeleted(id, true).map(rows => Ok(rows.toString)) recover handleError(s"Error deleting item $id.")
}
/**
* Restores the entity identified by `id`
*
* @param id the entity's primary key
* @return the number of rows affected by the soft delete
*/
def restore(id: Int) = Action.async {
repo.setIsDeleted(id, false).map(rows => Ok(rows.toString)) recover handleError(s"Error restoring item $id.")
}
/**
* Maps a Scala Throwable to an HTTP status code, and logs the error appropriately.
*
* @param msg message to log and send back to the client
* @return HTTP Result
*/
protected def handleError(msg: String): PartialFunction[Throwable, Result] = {
case e: NotFoundException =>
Logger.warn(msg, e)
NotFound(msg)
case e =>
Logger.error(msg, e)
InternalServerError(msg)
}
}
//Parent Model
@ApiModel(description = "Model", subTypes = Array(classOf[Destination], classOf[Export],classOf[Namespace]), discriminator = "type")
trait Model {
/**
* Gets the primary key for this Model.
*
* @return unique id value
*/
def getId: Int
}
//Namespace Model[POST UI][1]
@ApiModel(value = "Namespace Model", parent = classOf[Model])
case class Namespace(@ApiModelProperty ( dataType = "Int")namespaceId: Option[Int], @ApiModelProperty(example = "ESPN", required =true)name: String, @ApiModelProperty (dataType = "Boolean") isDeleted:Option[Boolean] = Some(false)) extends Model {
override def getId: Int = namespaceId.getOrElse(-1)
}