/** * Generated by API Builder - https://www.apibuilder.io * Service version: 0.0.1 * User agent: apibuilder app.apibuilder.io/nccloud/common/0.0.1/async_http_2_5_client */ package de.nccloud.common.v0.models { /** * Represents a link to a resource. */ sealed trait Link extends _root_.scala.Product with _root_.scala.Serializable /** * Basic audit information for a resource. */ final case class Audit( createdAt: _root_.org.joda.time.DateTime, createdBy: _root_.java.util.UUID, updatedAt: _root_.org.joda.time.DateTime, updatedBy: _root_.java.util.UUID ) /** * Links to further information about the occurred error. * * @param about A link that leads to further details about this particular occurrence of the * problem. * @param `type` A link that identifies the type of the error that this particular error is an * instance of. */ final case class ErrorLinks( about: _root_.scala.Option[de.nccloud.common.v0.models.Link] = None, `type`: _root_.scala.Option[de.nccloud.common.v0.models.Link] = None ) /** * Reference to the primary source of an error. * * @param source The source of the problem in the form specified by `type`. */ final case class ErrorSource( `type`: de.nccloud.common.v0.models.ErrorSourceType, source: String ) /** * An error returned on failed API requests. * * @param code An app specific error code. * @param title A short human readable summary of the problem. * @param detail A human readable explanation of the problem. * @param meta Non-standard meta-information about the error. */ final case class GenericError( links: _root_.scala.Option[de.nccloud.common.v0.models.ErrorLinks] = None, code: String, title: String, detail: String, source: _root_.scala.Option[de.nccloud.common.v0.models.ErrorSource] = None, meta: _root_.scala.Option[_root_.play.api.libs.json.JsObject] = None ) /** * Indicating the health of a service. * * @param message An optional message giving more detailed information about the current health. */ final case class HealthCheck( status: de.nccloud.common.v0.models.HealthStatus, message: _root_.scala.Option[String] = None ) /** * Represents a link with some meta information. * * @param href An URI-reference pointing to the links target. * @param title A human-readable label for the link. * @param `type` Optional media type of the link's target. */ final case class LinkObject( href: String, title: _root_.scala.Option[String] = None, `type`: _root_.scala.Option[String] = None ) extends Link /** * Paging information returned from a paged request. * * @param totalResults Total number of results that can potentially be returned. * @param totalPages Total number of pages that can potentially be returned. */ final case class PageResponse( offset: Int, limit: Int, sort: Seq[de.nccloud.common.v0.models.Sort], totalResults: Long, totalPages: Long ) /** * Form containing paging information. * * @param offset Offset of the current page. The pages are 0-indexed, meaning the first page * starts at 0. * @param limit The number of results to be returned by the api. * @param sort Defines multiple properties for the results to be sorted by. The order of the * definition defines the priority. If omitted, the service will use an * implementation dependent default sort. */ final case class PagingForm( offset: Int = 0, limit: Int = 25, sort: _root_.scala.Option[Seq[de.nccloud.common.v0.models.Sort]] = None ) /** * Information about a deployed service. * * @param uri URI under which this service is deployed. * @param title A human-readable title of the service. * @param description A human-readable description of the service. */ final case class ServiceInfo( name: String, version: String, uri: String, title: _root_.scala.Option[String] = None, description: _root_.scala.Option[String] = None ) /** * Single property to sort by. * * @param property The property by which the results should be sorted. * @param direction The direction in which the results should be sorted. */ final case class Sort( property: String, direction: de.nccloud.common.v0.models.SortDirection ) /** * Provides future compatibility in clients - in the future, when a type is added * to the union Link, it will need to be handled in the client code. This * implementation will deserialize these future types as an instance of this class. * * @param description Information about the type that we received that is undefined in this version of * the client. */ final case class LinkUndefinedType( description: String ) extends Link /** * Wrapper class to support the union types containing the datatype[string] */ final case class LinkString( value: String ) extends Link /** * Type of an error source. */ sealed trait ErrorSourceType extends _root_.scala.Product with _root_.scala.Serializable object ErrorSourceType { /** * Indicating a [JSON pointer](https://tools.ietf.org/html/rfc6901) to the value * that has caused the error. */ case object Pointer extends ErrorSourceType { override def toString = "pointer" } /** * Indicating an URI query parameter causing the error. */ case object Parameter extends ErrorSourceType { override def toString = "parameter" } /** * Indicating a request header causing the error. */ case object Header extends ErrorSourceType { override def toString = "header" } /** * UNDEFINED captures values that are sent either in error or * that were added by the server after this library was * generated. We want to make it easy and obvious to users of * this library to handle this case gracefully. * * We use all CAPS for the variable name to avoid collisions * with the camel cased values above. */ final case class UNDEFINED(override val toString: String) extends ErrorSourceType /** * all returns a list of all the valid, known values. We use * lower case to avoid collisions with the camel cased values * above. */ val all: scala.List[ErrorSourceType] = scala.List(Pointer, Parameter, Header) private val byName: Map[String, ErrorSourceType] = all.map(x => x.toString.toLowerCase -> x).toMap def apply(value: String): ErrorSourceType = fromString(value).getOrElse(UNDEFINED(value)) def fromString(value: String): _root_.scala.Option[ErrorSourceType] = byName.get(value.toLowerCase) } /** * The status of a service. */ sealed trait HealthStatus extends _root_.scala.Product with _root_.scala.Serializable object HealthStatus { /** * The service is running and healthy. */ case object Running extends HealthStatus { override def toString = "running" } /** * The service is not yet running. */ case object Starting extends HealthStatus { override def toString = "starting" } /** * The service has encountered errors and is not running property. */ case object Unhealthy extends HealthStatus { override def toString = "unhealthy" } /** * UNDEFINED captures values that are sent either in error or * that were added by the server after this library was * generated. We want to make it easy and obvious to users of * this library to handle this case gracefully. * * We use all CAPS for the variable name to avoid collisions * with the camel cased values above. */ final case class UNDEFINED(override val toString: String) extends HealthStatus /** * all returns a list of all the valid, known values. We use * lower case to avoid collisions with the camel cased values * above. */ val all: scala.List[HealthStatus] = scala.List(Running, Starting, Unhealthy) private val byName: Map[String, HealthStatus] = all.map(x => x.toString.toLowerCase -> x).toMap def apply(value: String): HealthStatus = fromString(value).getOrElse(UNDEFINED(value)) def fromString(value: String): _root_.scala.Option[HealthStatus] = byName.get(value.toLowerCase) } /** * The direction in which to sort by a property. */ sealed trait SortDirection extends _root_.scala.Product with _root_.scala.Serializable object SortDirection { /** * Sort ascending. */ case object Asc extends SortDirection { override def toString = "asc" } /** * Sort descending. */ case object Desc extends SortDirection { override def toString = "desc" } /** * UNDEFINED captures values that are sent either in error or * that were added by the server after this library was * generated. We want to make it easy and obvious to users of * this library to handle this case gracefully. * * We use all CAPS for the variable name to avoid collisions * with the camel cased values above. */ final case class UNDEFINED(override val toString: String) extends SortDirection /** * all returns a list of all the valid, known values. We use * lower case to avoid collisions with the camel cased values * above. */ val all: scala.List[SortDirection] = scala.List(Asc, Desc) private val byName: Map[String, SortDirection] = all.map(x => x.toString.toLowerCase -> x).toMap def apply(value: String): SortDirection = fromString(value).getOrElse(UNDEFINED(value)) def fromString(value: String): _root_.scala.Option[SortDirection] = byName.get(value.toLowerCase) } } package de.nccloud.common.v0.models { package object json { import play.api.libs.json.__ import play.api.libs.json.JsString import play.api.libs.json.Writes import play.api.libs.functional.syntax._ import de.nccloud.common.v0.models.json._ private[v0] implicit val jsonReadsUUID: play.api.libs.json.Reads[_root_.java.util.UUID] = __.read[String].map { str => _root_.java.util.UUID.fromString(str) } private[v0] implicit val jsonWritesUUID: play.api.libs.json.Writes[_root_.java.util.UUID] = (x: _root_.java.util.UUID) => play.api.libs.json.JsString(x.toString) private[v0] implicit val jsonReadsJodaDateTime: play.api.libs.json.Reads[_root_.org.joda.time.DateTime] = __.read[String].map { str => _root_.org.joda.time.format.ISODateTimeFormat.dateTimeParser.parseDateTime(str) } private[v0] implicit val jsonWritesJodaDateTime: play.api.libs.json.Writes[_root_.org.joda.time.DateTime] = (x: _root_.org.joda.time.DateTime) => { play.api.libs.json.JsString(_root_.org.joda.time.format.ISODateTimeFormat.dateTime.print(x)) } private[v0] implicit val jsonReadsJodaLocalDate: play.api.libs.json.Reads[_root_.org.joda.time.LocalDate] = __.read[String].map { str => _root_.org.joda.time.format.ISODateTimeFormat.dateTimeParser.parseLocalDate(str) } private[v0] implicit val jsonWritesJodaLocalDate: play.api.libs.json.Writes[_root_.org.joda.time.LocalDate] = (x: _root_.org.joda.time.LocalDate) => { play.api.libs.json.JsString(_root_.org.joda.time.format.ISODateTimeFormat.date.print(x)) } implicit val jsonReadsCommonErrorSourceType: play.api.libs.json.Reads[de.nccloud.common.v0.models.ErrorSourceType] = new play.api.libs.json.Reads[de.nccloud.common.v0.models.ErrorSourceType] { def reads(js: play.api.libs.json.JsValue): play.api.libs.json.JsResult[de.nccloud.common.v0.models.ErrorSourceType] = { js match { case v: play.api.libs.json.JsString => play.api.libs.json.JsSuccess(de.nccloud.common.v0.models.ErrorSourceType(v.value)) case _ => { (js \ "value").validate[String] match { case play.api.libs.json.JsSuccess(v, _) => play.api.libs.json.JsSuccess(de.nccloud.common.v0.models.ErrorSourceType(v)) case _: play.api.libs.json.JsError => (js \ "error_source_type").validate[String] match { case play.api.libs.json.JsSuccess(v, _) => play.api.libs.json.JsSuccess(de.nccloud.common.v0.models.ErrorSourceType(v)) case err: play.api.libs.json.JsError => err } } } } } } def jsonWritesCommonErrorSourceType(obj: de.nccloud.common.v0.models.ErrorSourceType) = { play.api.libs.json.JsString(obj.toString) } def jsObjectErrorSourceType(obj: de.nccloud.common.v0.models.ErrorSourceType) = { play.api.libs.json.Json.obj("value" -> play.api.libs.json.JsString(obj.toString)) } implicit def jsonWritesCommonErrorSourceType: play.api.libs.json.Writes[ErrorSourceType] = { (obj: de.nccloud.common.v0.models.ErrorSourceType) => { de.nccloud.common.v0.models.json.jsonWritesCommonErrorSourceType(obj) } } implicit val jsonReadsCommonHealthStatus: play.api.libs.json.Reads[de.nccloud.common.v0.models.HealthStatus] = new play.api.libs.json.Reads[de.nccloud.common.v0.models.HealthStatus] { def reads(js: play.api.libs.json.JsValue): play.api.libs.json.JsResult[de.nccloud.common.v0.models.HealthStatus] = { js match { case v: play.api.libs.json.JsString => play.api.libs.json.JsSuccess(de.nccloud.common.v0.models.HealthStatus(v.value)) case _ => { (js \ "value").validate[String] match { case play.api.libs.json.JsSuccess(v, _) => play.api.libs.json.JsSuccess(de.nccloud.common.v0.models.HealthStatus(v)) case _: play.api.libs.json.JsError => (js \ "health_status").validate[String] match { case play.api.libs.json.JsSuccess(v, _) => play.api.libs.json.JsSuccess(de.nccloud.common.v0.models.HealthStatus(v)) case err: play.api.libs.json.JsError => err } } } } } } def jsonWritesCommonHealthStatus(obj: de.nccloud.common.v0.models.HealthStatus) = { play.api.libs.json.JsString(obj.toString) } def jsObjectHealthStatus(obj: de.nccloud.common.v0.models.HealthStatus) = { play.api.libs.json.Json.obj("value" -> play.api.libs.json.JsString(obj.toString)) } implicit def jsonWritesCommonHealthStatus: play.api.libs.json.Writes[HealthStatus] = { (obj: de.nccloud.common.v0.models.HealthStatus) => { de.nccloud.common.v0.models.json.jsonWritesCommonHealthStatus(obj) } } implicit val jsonReadsCommonSortDirection: play.api.libs.json.Reads[de.nccloud.common.v0.models.SortDirection] = new play.api.libs.json.Reads[de.nccloud.common.v0.models.SortDirection] { def reads(js: play.api.libs.json.JsValue): play.api.libs.json.JsResult[de.nccloud.common.v0.models.SortDirection] = { js match { case v: play.api.libs.json.JsString => play.api.libs.json.JsSuccess(de.nccloud.common.v0.models.SortDirection(v.value)) case _ => { (js \ "value").validate[String] match { case play.api.libs.json.JsSuccess(v, _) => play.api.libs.json.JsSuccess(de.nccloud.common.v0.models.SortDirection(v)) case _: play.api.libs.json.JsError => (js \ "sort_direction").validate[String] match { case play.api.libs.json.JsSuccess(v, _) => play.api.libs.json.JsSuccess(de.nccloud.common.v0.models.SortDirection(v)) case err: play.api.libs.json.JsError => err } } } } } } def jsonWritesCommonSortDirection(obj: de.nccloud.common.v0.models.SortDirection) = { play.api.libs.json.JsString(obj.toString) } def jsObjectSortDirection(obj: de.nccloud.common.v0.models.SortDirection) = { play.api.libs.json.Json.obj("value" -> play.api.libs.json.JsString(obj.toString)) } implicit def jsonWritesCommonSortDirection: play.api.libs.json.Writes[SortDirection] = { (obj: de.nccloud.common.v0.models.SortDirection) => { de.nccloud.common.v0.models.json.jsonWritesCommonSortDirection(obj) } } implicit def jsonReadsCommonAudit: play.api.libs.json.Reads[de.nccloud.common.v0.models.Audit] = { for { createdAt <- (__ \ "created_at").read[_root_.org.joda.time.DateTime] createdBy <- (__ \ "created_by").read[_root_.java.util.UUID] updatedAt <- (__ \ "updated_at").read[_root_.org.joda.time.DateTime] updatedBy <- (__ \ "updated_by").read[_root_.java.util.UUID] } yield Audit(createdAt, createdBy, updatedAt, updatedBy) } def jsObjectAudit(obj: de.nccloud.common.v0.models.Audit): play.api.libs.json.JsObject = { play.api.libs.json.Json.obj( "created_at" -> play.api.libs.json.JsString(_root_.org.joda.time.format.ISODateTimeFormat.dateTime.print(obj.createdAt)), "created_by" -> play.api.libs.json.JsString(obj.createdBy.toString), "updated_at" -> play.api.libs.json.JsString(_root_.org.joda.time.format.ISODateTimeFormat.dateTime.print(obj.updatedAt)), "updated_by" -> play.api.libs.json.JsString(obj.updatedBy.toString) ) } implicit def jsonWritesCommonAudit: play.api.libs.json.Writes[Audit] = { (obj: de.nccloud.common.v0.models.Audit) => { de.nccloud.common.v0.models.json.jsObjectAudit(obj) } } implicit def jsonReadsCommonErrorLinks: play.api.libs.json.Reads[de.nccloud.common.v0.models.ErrorLinks] = { for { about <- (__ \ "about").readNullable[de.nccloud.common.v0.models.Link] `type` <- (__ \ "type").readNullable[de.nccloud.common.v0.models.Link] } yield ErrorLinks(about, `type`) } def jsObjectErrorLinks(obj: de.nccloud.common.v0.models.ErrorLinks): play.api.libs.json.JsObject = { (obj.about match { case None => play.api.libs.json.Json.obj() case Some(x) => play.api.libs.json.Json.obj("about" -> de.nccloud.common.v0.models.json.jsObjectLink(x)) }) ++ (obj.`type` match { case None => play.api.libs.json.Json.obj() case Some(x) => play.api.libs.json.Json.obj("type" -> de.nccloud.common.v0.models.json.jsObjectLink(x)) }) } implicit def jsonWritesCommonErrorLinks: play.api.libs.json.Writes[ErrorLinks] = { (obj: de.nccloud.common.v0.models.ErrorLinks) => { de.nccloud.common.v0.models.json.jsObjectErrorLinks(obj) } } implicit def jsonReadsCommonErrorSource: play.api.libs.json.Reads[de.nccloud.common.v0.models.ErrorSource] = { for { `type` <- (__ \ "type").read[de.nccloud.common.v0.models.ErrorSourceType] source <- (__ \ "source").read[String] } yield ErrorSource(`type`, source) } def jsObjectErrorSource(obj: de.nccloud.common.v0.models.ErrorSource): play.api.libs.json.JsObject = { play.api.libs.json.Json.obj( "type" -> play.api.libs.json.JsString(obj.`type`.toString), "source" -> play.api.libs.json.JsString(obj.source) ) } implicit def jsonWritesCommonErrorSource: play.api.libs.json.Writes[ErrorSource] = { (obj: de.nccloud.common.v0.models.ErrorSource) => { de.nccloud.common.v0.models.json.jsObjectErrorSource(obj) } } implicit def jsonReadsCommonGenericError: play.api.libs.json.Reads[de.nccloud.common.v0.models.GenericError] = { for { links <- (__ \ "links").readNullable[de.nccloud.common.v0.models.ErrorLinks] code <- (__ \ "code").read[String] title <- (__ \ "title").read[String] detail <- (__ \ "detail").read[String] source <- (__ \ "source").readNullable[de.nccloud.common.v0.models.ErrorSource] meta <- (__ \ "meta").readNullable[_root_.play.api.libs.json.JsObject] } yield GenericError(links, code, title, detail, source, meta) } def jsObjectGenericError(obj: de.nccloud.common.v0.models.GenericError): play.api.libs.json.JsObject = { play.api.libs.json.Json.obj( "code" -> play.api.libs.json.JsString(obj.code), "title" -> play.api.libs.json.JsString(obj.title), "detail" -> play.api.libs.json.JsString(obj.detail) ) ++ (obj.links match { case None => play.api.libs.json.Json.obj() case Some(x) => play.api.libs.json.Json.obj("links" -> de.nccloud.common.v0.models.json.jsObjectErrorLinks(x)) }) ++ (obj.source match { case None => play.api.libs.json.Json.obj() case Some(x) => play.api.libs.json.Json.obj("source" -> de.nccloud.common.v0.models.json.jsObjectErrorSource(x)) }) ++ (obj.meta match { case None => play.api.libs.json.Json.obj() case Some(x) => play.api.libs.json.Json.obj("meta" -> x) }) } implicit def jsonWritesCommonGenericError: play.api.libs.json.Writes[GenericError] = { (obj: de.nccloud.common.v0.models.GenericError) => { de.nccloud.common.v0.models.json.jsObjectGenericError(obj) } } implicit def jsonReadsCommonHealthCheck: play.api.libs.json.Reads[de.nccloud.common.v0.models.HealthCheck] = { for { status <- (__ \ "status").read[de.nccloud.common.v0.models.HealthStatus] message <- (__ \ "message").readNullable[String] } yield HealthCheck(status, message) } def jsObjectHealthCheck(obj: de.nccloud.common.v0.models.HealthCheck): play.api.libs.json.JsObject = { play.api.libs.json.Json.obj( "status" -> play.api.libs.json.JsString(obj.status.toString) ) ++ (obj.message match { case None => play.api.libs.json.Json.obj() case Some(x) => play.api.libs.json.Json.obj("message" -> play.api.libs.json.JsString(x)) }) } implicit def jsonWritesCommonHealthCheck: play.api.libs.json.Writes[HealthCheck] = { (obj: de.nccloud.common.v0.models.HealthCheck) => { de.nccloud.common.v0.models.json.jsObjectHealthCheck(obj) } } implicit def jsonReadsCommonLinkObject: play.api.libs.json.Reads[de.nccloud.common.v0.models.LinkObject] = { for { href <- (__ \ "href").read[String] title <- (__ \ "title").readNullable[String] `type` <- (__ \ "type").readNullable[String] } yield LinkObject(href, title, `type`) } def jsObjectLinkObject(obj: de.nccloud.common.v0.models.LinkObject): play.api.libs.json.JsObject = { play.api.libs.json.Json.obj( "href" -> play.api.libs.json.JsString(obj.href) ) ++ (obj.title match { case None => play.api.libs.json.Json.obj() case Some(x) => play.api.libs.json.Json.obj("title" -> play.api.libs.json.JsString(x)) }) ++ (obj.`type` match { case None => play.api.libs.json.Json.obj() case Some(x) => play.api.libs.json.Json.obj("type" -> play.api.libs.json.JsString(x)) }) } implicit def jsonWritesCommonLinkObject: play.api.libs.json.Writes[LinkObject] = { (obj: de.nccloud.common.v0.models.LinkObject) => { de.nccloud.common.v0.models.json.jsObjectLinkObject(obj) } } implicit def jsonReadsCommonPageResponse: play.api.libs.json.Reads[de.nccloud.common.v0.models.PageResponse] = { for { offset <- (__ \ "offset").read[Int] limit <- (__ \ "limit").read[Int] sort <- (__ \ "sort").read[Seq[de.nccloud.common.v0.models.Sort]] totalResults <- (__ \ "total_results").read[Long] totalPages <- (__ \ "total_pages").read[Long] } yield PageResponse(offset, limit, sort, totalResults, totalPages) } def jsObjectPageResponse(obj: de.nccloud.common.v0.models.PageResponse): play.api.libs.json.JsObject = { play.api.libs.json.Json.obj( "offset" -> play.api.libs.json.JsNumber(obj.offset), "limit" -> play.api.libs.json.JsNumber(obj.limit), "sort" -> play.api.libs.json.Json.toJson(obj.sort), "total_results" -> play.api.libs.json.JsNumber(obj.totalResults), "total_pages" -> play.api.libs.json.JsNumber(obj.totalPages) ) } implicit def jsonWritesCommonPageResponse: play.api.libs.json.Writes[PageResponse] = { (obj: de.nccloud.common.v0.models.PageResponse) => { de.nccloud.common.v0.models.json.jsObjectPageResponse(obj) } } implicit def jsonReadsCommonPagingForm: play.api.libs.json.Reads[de.nccloud.common.v0.models.PagingForm] = { for { offset <- (__ \ "offset").read[Int] limit <- (__ \ "limit").read[Int] sort <- (__ \ "sort").readNullable[Seq[de.nccloud.common.v0.models.Sort]] } yield PagingForm(offset, limit, sort) } def jsObjectPagingForm(obj: de.nccloud.common.v0.models.PagingForm): play.api.libs.json.JsObject = { play.api.libs.json.Json.obj( "offset" -> play.api.libs.json.JsNumber(obj.offset), "limit" -> play.api.libs.json.JsNumber(obj.limit) ) ++ (obj.sort match { case None => play.api.libs.json.Json.obj() case Some(x) => play.api.libs.json.Json.obj("sort" -> play.api.libs.json.Json.toJson(x)) }) } implicit def jsonWritesCommonPagingForm: play.api.libs.json.Writes[PagingForm] = { (obj: de.nccloud.common.v0.models.PagingForm) => { de.nccloud.common.v0.models.json.jsObjectPagingForm(obj) } } implicit def jsonReadsCommonServiceInfo: play.api.libs.json.Reads[de.nccloud.common.v0.models.ServiceInfo] = { for { name <- (__ \ "name").read[String] version <- (__ \ "version").read[String] uri <- (__ \ "uri").read[String] title <- (__ \ "title").readNullable[String] description <- (__ \ "description").readNullable[String] } yield ServiceInfo(name, version, uri, title, description) } def jsObjectServiceInfo(obj: de.nccloud.common.v0.models.ServiceInfo): play.api.libs.json.JsObject = { play.api.libs.json.Json.obj( "name" -> play.api.libs.json.JsString(obj.name), "version" -> play.api.libs.json.JsString(obj.version), "uri" -> play.api.libs.json.JsString(obj.uri) ) ++ (obj.title match { case None => play.api.libs.json.Json.obj() case Some(x) => play.api.libs.json.Json.obj("title" -> play.api.libs.json.JsString(x)) }) ++ (obj.description match { case None => play.api.libs.json.Json.obj() case Some(x) => play.api.libs.json.Json.obj("description" -> play.api.libs.json.JsString(x)) }) } implicit def jsonWritesCommonServiceInfo: play.api.libs.json.Writes[ServiceInfo] = { (obj: de.nccloud.common.v0.models.ServiceInfo) => { de.nccloud.common.v0.models.json.jsObjectServiceInfo(obj) } } implicit def jsonReadsCommonSort: play.api.libs.json.Reads[de.nccloud.common.v0.models.Sort] = { for { property <- (__ \ "property").read[String] direction <- (__ \ "direction").read[de.nccloud.common.v0.models.SortDirection] } yield Sort(property, direction) } def jsObjectSort(obj: de.nccloud.common.v0.models.Sort): play.api.libs.json.JsObject = { play.api.libs.json.Json.obj( "property" -> play.api.libs.json.JsString(obj.property), "direction" -> play.api.libs.json.JsString(obj.direction.toString) ) } implicit def jsonWritesCommonSort: play.api.libs.json.Writes[Sort] = { (obj: de.nccloud.common.v0.models.Sort) => { de.nccloud.common.v0.models.json.jsObjectSort(obj) } } implicit def jsonReadsCommonLinkString: play.api.libs.json.Reads[de.nccloud.common.v0.models.LinkString] = { (__ \ "value").read[String].map { x => LinkString(value = x) } } implicit def jsonReadsCommonLink: play.api.libs.json.Reads[de.nccloud.common.v0.models.Link] = { ( (__ \ "string").read(jsonReadsCommonLinkString).asInstanceOf[play.api.libs.json.Reads[Link]] orElse (__ \ "link_object").read(jsonReadsCommonLinkObject).asInstanceOf[play.api.libs.json.Reads[Link]] orElse play.api.libs.json.Reads(jsValue => play.api.libs.json.JsSuccess(LinkUndefinedType(jsValue.toString))).asInstanceOf[play.api.libs.json.Reads[Link]] ) } def jsObjectLink(obj: de.nccloud.common.v0.models.Link): play.api.libs.json.JsObject = { obj match { case x: de.nccloud.common.v0.models.LinkString => play.api.libs.json.Json.obj("string" -> play.api.libs.json.Json.obj("value" -> play.api.libs.json.JsString(x.value))) case x: de.nccloud.common.v0.models.LinkObject => play.api.libs.json.Json.obj("link_object" -> de.nccloud.common.v0.models.json.jsObjectLinkObject(x)) case x: de.nccloud.common.v0.models.LinkUndefinedType => { scala.util.Try { // If we received a JSON object - echo it back. This is a workaround for a bug in // serialization for unions w/out discriminators where they sometimes have the // type wrapper and sometimes do not play.api.libs.json.Json.parse(x.description).asInstanceOf[play.api.libs.json.JsObject] } match { case scala.util.Success(o) => o case scala.util.Failure(_) => sys.error("The type[de.nccloud.common.v0.models.LinkUndefinedType] should never be serialized") } } } } implicit def jsonWritesCommonLink: play.api.libs.json.Writes[Link] = { (obj: de.nccloud.common.v0.models.Link) => { de.nccloud.common.v0.models.json.jsObjectLink(obj) } } } } package de.nccloud.common.v0 { import org.asynchttpclient.{AsyncCompletionHandler, AsyncHttpClient, Realm, Request, RequestBuilder, Response, DefaultAsyncHttpClient, DefaultAsyncHttpClientConfig} object Constants { val Namespace = "de.nccloud.common.v0" val UserAgent = "apibuilder app.apibuilder.io/nccloud/common/0.0.1/async_http_2_5_client" val Version = "0.0.1" val VersionMajor = 0 } class Client( val baseUrl: String, auth: scala.Option[de.nccloud.common.v0.Authorization] = None, defaultHeaders: Seq[(String, String)] = Nil, asyncHttpClient: AsyncHttpClient = Client.defaultAsyncHttpClient ) extends interfaces.Client { import org.slf4j.{Logger, LoggerFactory} import de.nccloud.common.v0.models.json._ def closeAsyncHttpClient(): Unit = { asyncHttpClient.close() } val logger = LoggerFactory.getLogger(getClass) def healthChecks: HealthChecks = HealthChecks def serviceInfos: ServiceInfos = ServiceInfos object HealthChecks extends HealthChecks { override def getHealthcheck( requestHeaders: Seq[(String, String)] = Nil )(implicit ec: scala.concurrent.ExecutionContext): scala.concurrent.Future[de.nccloud.common.v0.models.HealthCheck] = { _executeRequest("GET", s"/_internal_/healthcheck", requestHeaders = requestHeaders).map { case r if r.getStatusCode == 200 => _root_.de.nccloud.common.v0.Client.parseJson("de.nccloud.common.v0.models.HealthCheck", r, _.validate[de.nccloud.common.v0.models.HealthCheck]) case r => throw de.nccloud.common.v0.errors.FailedRequest(r.getStatusCode, s"Unsupported response code[${r.getStatusCode}]. Expected: 200", requestUri = Some(r.getUri.toJavaNetURI)) } } override def getProbeAndReady( requestHeaders: Seq[(String, String)] = Nil )(implicit ec: scala.concurrent.ExecutionContext): scala.concurrent.Future[Unit] = { _executeRequest("GET", s"/_internal_/probe/ready", requestHeaders = requestHeaders).map { case r if r.getStatusCode == 200 => () case r if r.getStatusCode == 400 => throw de.nccloud.common.v0.errors.UnitResponse(r.getStatusCode) case r => throw de.nccloud.common.v0.errors.FailedRequest(r.getStatusCode, s"Unsupported response code[${r.getStatusCode}]. Expected: 200, 400", requestUri = Some(r.getUri.toJavaNetURI)) } } override def getProbeAndLive( requestHeaders: Seq[(String, String)] = Nil )(implicit ec: scala.concurrent.ExecutionContext): scala.concurrent.Future[Unit] = { _executeRequest("GET", s"/_internal_/probe/live", requestHeaders = requestHeaders).map { case r if r.getStatusCode == 200 => () case r => throw de.nccloud.common.v0.errors.FailedRequest(r.getStatusCode, s"Unsupported response code[${r.getStatusCode}]. Expected: 200", requestUri = Some(r.getUri.toJavaNetURI)) } } } object ServiceInfos extends ServiceInfos { override def getService( requestHeaders: Seq[(String, String)] = Nil )(implicit ec: scala.concurrent.ExecutionContext): scala.concurrent.Future[de.nccloud.common.v0.models.ServiceInfo] = { _executeRequest("GET", s"/_internal_/service", requestHeaders = requestHeaders).map { case r if r.getStatusCode == 200 => _root_.de.nccloud.common.v0.Client.parseJson("de.nccloud.common.v0.models.ServiceInfo", r, _.validate[de.nccloud.common.v0.models.ServiceInfo]) case r => throw de.nccloud.common.v0.errors.FailedRequest(r.getStatusCode, s"Unsupported response code[${r.getStatusCode}]. Expected: 200", requestUri = Some(r.getUri.toJavaNetURI)) } } } def _logRequest(request: Request): Unit = { if (logger.isInfoEnabled) { logger.info("_logRequest: " + request) } } def _logResponse(response: Response): Unit = { if (logger.isInfoEnabled) { logger.info("_logResponse: status=" + response.getStatusCode + ", responseBody: " + response.getResponseBody(java.nio.charset.Charset.forName("UTF-8"))) } } def _requestBuilder(method: String, path: String, requestHeaders: Seq[(String, String)]): RequestBuilder = { val builder = new RequestBuilder(method) .setUrl(baseUrl + path) .addHeader("User-Agent", Constants.UserAgent) .addHeader("X-Apidoc-Version", Constants.Version) .addHeader("X-Apidoc-Version-Major", Constants.VersionMajor.toString) defaultHeaders.foreach { h => builder.addHeader(h._1, h._2) } requestHeaders.foreach { h => builder.addHeader(h._1, h._2) } auth.fold(builder) { case Authorization.Basic(username, passwordOpt) => { builder.setRealm( new Realm.Builder(username, passwordOpt.getOrElse("")) .setUsePreemptiveAuth(true) .setScheme(Realm.AuthScheme.BASIC) .build() ) } case a => sys.error("Invalid authorization scheme[" + a.getClass + "]") } } def _executeRequest( method: String, path: String, queryParameters: Seq[(String, String)] = Nil, requestHeaders: Seq[(String, String)] = Nil, body: Option[play.api.libs.json.JsValue] = None )(implicit ec: scala.concurrent.ExecutionContext): scala.concurrent.Future[org.asynchttpclient.Response] = { val allHeaders = body match { case None => requestHeaders case Some(_) => _withJsonContentType(requestHeaders) } val request = _requestBuilder(method, path, allHeaders) queryParameters.foreach { pair => request.addQueryParam(pair._1, pair._2) } val requestWithParamsAndBody = body.fold(request) { b => val serialized = play.api.libs.json.Json.stringify(b) request.setBody(serialized) } val finalRequest = requestWithParamsAndBody.build() _logRequest(finalRequest) val result = scala.concurrent.Promise[org.asynchttpclient.Response]() asyncHttpClient.executeRequest(finalRequest, new AsyncCompletionHandler[Unit]() { override def onCompleted(r: org.asynchttpclient.Response) = { _logResponse(r) result.success(r) } override def onThrowable(t: Throwable) = result.failure(t) } ) result.future } /** * Adds a Content-Type: application/json header unless the specified requestHeaders * already contain a Content-Type header */ def _withJsonContentType(headers: Seq[(String, String)]): Seq[(String, String)] = { headers.find { _._1.toUpperCase == "CONTENT-TYPE" } match { case None => headers ++ Seq(("Content-Type" -> "application/json; charset=UTF-8")) case Some(_) => headers } } } object Client { private lazy val defaultAsyncHttpClient = { new DefaultAsyncHttpClient( new DefaultAsyncHttpClientConfig.Builder().build() ) } def parseJson[T]( className: String, r: _root_.org.asynchttpclient.Response, f: (play.api.libs.json.JsValue => play.api.libs.json.JsResult[T]) ): T = { f(play.api.libs.json.Json.parse(r.getResponseBody(java.nio.charset.Charset.forName("UTF-8")))) match { case play.api.libs.json.JsSuccess(x, _) => x case play.api.libs.json.JsError(errors) => { throw de.nccloud.common.v0.errors.FailedRequest(r.getStatusCode, s"Invalid json for class[" + className + "]: " + errors.mkString(" "), requestUri = Some(r.getUri.toJavaNetURI)) } } } } sealed trait Authorization extends _root_.scala.Product with _root_.scala.Serializable object Authorization { final case class Basic(username: String, password: Option[String] = None) extends Authorization } package interfaces { trait Client { def baseUrl: String def healthChecks: de.nccloud.common.v0.HealthChecks def serviceInfos: de.nccloud.common.v0.ServiceInfos } } trait HealthChecks { /** * Get the current health of the service. */ def getHealthcheck( requestHeaders: Seq[(String, String)] = Nil )(implicit ec: scala.concurrent.ExecutionContext): scala.concurrent.Future[de.nccloud.common.v0.models.HealthCheck] /** * Endpoint for readiness probe. */ def getProbeAndReady( requestHeaders: Seq[(String, String)] = Nil )(implicit ec: scala.concurrent.ExecutionContext): scala.concurrent.Future[Unit] /** * Endpoint for liveliness probe. */ def getProbeAndLive( requestHeaders: Seq[(String, String)] = Nil )(implicit ec: scala.concurrent.ExecutionContext): scala.concurrent.Future[Unit] } trait ServiceInfos { /** * Get information about the deployed service. */ def getService( requestHeaders: Seq[(String, String)] = Nil )(implicit ec: scala.concurrent.ExecutionContext): scala.concurrent.Future[de.nccloud.common.v0.models.ServiceInfo] } package errors { import de.nccloud.common.v0.models.json._ final case class UnitResponse(status: Int) extends Exception(s"HTTP $status") final case class FailedRequest(responseCode: Int, message: String, requestUri: Option[_root_.java.net.URI] = None) extends _root_.java.lang.Exception(s"HTTP $responseCode: $message") } object PathSegment { // See https://github.com/playframework/playframework/blob/2.3.x/framework/src/play/src/main/scala/play/utils/UriEncoding.scala def encode(s: String, inputCharset: String): String = { val in = s.getBytes(inputCharset) val out = new java.io.ByteArrayOutputStream() for (b <- in) { val allowed = segmentChars.get(b & 0xFF) if (allowed) { out.write(b) } else { out.write('%') out.write(upperHex((b >> 4) & 0xF)) out.write(upperHex(b & 0xF)) } } out.toString("US-ASCII") } private def upperHex(x: Int): Int = { // Assume 0 <= x < 16 if (x < 10) (x + '0') else (x - 10 + 'A') } private val segmentChars: java.util.BitSet = membershipTable(pchar) private def pchar: Seq[Char] = { val alphaDigit = for ((min, max) <- Seq(('a', 'z'), ('A', 'Z'), ('0', '9')); c <- min to max) yield c val unreserved = alphaDigit ++ Seq('-', '.', '_', '~') val subDelims = Seq('!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '=') unreserved ++ subDelims ++ Seq(':', '@') } private def membershipTable(chars: Seq[Char]): java.util.BitSet = { val bits = new java.util.BitSet(256) for (c <- chars) { bits.set(c.toInt) } bits } } }