<commit_before>package aws.dynamodb

import play.api.libs.json.Json.toJson
import play.api.libs.json._

package object models {

  sealed trait AttributeType {
    def typeCode: String
    override def toString = typeCode
  }

  object AttributeType {
    def apply(t: String) = t match {
      case "N" => DDBLong
      case "S" => DDBString
      case "B" => DDBBoolean
      case _ => sys.error("Invalid AttributeType: " + t)
    }
  }

  object DDBLong extends AttributeType {
    override def typeCode = "N"
  }

  object DDBString extends AttributeType {
    override def typeCode = "S"
  }

  object DDBBoolean extends AttributeType {
    override def typeCode = "B"
  }

  sealed trait Status {
    def status: String
  }

  object Status {
    object CREATING extends Status { override def status = "Creating" }
    object ACTIVE extends Status { override def status = "Active" }
    object DELETING extends Status { override def status = "Deleting" }
    object UPDATING extends Status { override def status = "Updating" }
    def apply(s: String) = s.toLowerCase match {
      case "creating" => CREATING
      case "active" => ACTIVE
      case "deleting" => DELETING
      case "updating" => UPDATING
      case _ => sys.error("Invalid table status: " + s)
    }
  }

  case class KeySchemaElement(attributeName: String, attributeType: AttributeType)

  case class KeySchema(hashKey: KeySchemaElement, rangeKey: Option[KeySchemaElement] = None)

  case class ProvisionedThroughput(readCapacityUnits: Long, writeCapacityUnits: Long)

  case class TableDescription(name: String,
                              status: Status,
                              creationDateTime: java.util.Date,
                              keySchema: KeySchema,
                              provisionedThroughput: ProvisionedThroughput,
                              size: Option[Long])

  // JSON Formatters

  implicit def KeySchemaElementFormat: Format[KeySchemaElement] = new Format[KeySchemaElement] {
    def writes(element: KeySchemaElement) = JsObject(Seq(
      "AttributeName" -> JsString(element.attributeName),
      "AttributeType" -> JsString(element.attributeType.toString)))
    def reads(json: JsValue) = JsSuccess(KeySchemaElement(
      (json \ "AttributeName").as[String],
      AttributeType((json \ "AttributeType").as[String])))
  }

  implicit def AttributeTypeFormat: Format[AttributeType] = new Format[AttributeType] {
    def writes(t: AttributeType) = JsString(t.typeCode)
    def reads(json: JsValue) = json match {
      case JsString(t) => JsSuccess(AttributeType(t))
      case _ => JsError("String expected")
    }
  }

  implicit def KeySchemaFormat: Format[KeySchema] = new Format[KeySchema] {
    def writes(schema: KeySchema) = JsObject(
      Seq("HashKeyElement" -> toJson(schema.hashKey)) ++ schema.rangeKey.toSeq.map("rangeKeyElement" -> toJson(_)))
    def reads(json: JsValue) = JsSuccess(KeySchema(
      (json \ "HashKeyElement").as[KeySchemaElement],
      (json \ "RangeKeyElement") match {
        case JsUndefined(e) => None
        case js => js.asOpt[KeySchemaElement]
      }))
  }

  implicit def ProvisionedThroughputFormat = new Format[ProvisionedThroughput] {
    def writes(pt: ProvisionedThroughput) = Json.obj(
      "ReadCapacityUnits" -> Json.toJson(pt.readCapacityUnits),
      "WriteCapacityUnits" -> Json.toJson(pt.writeCapacityUnits))
    def reads(json: JsValue) = JsSuccess(ProvisionedThroughput(
      (json \ "ReadCapacityUnits").as[Long],
      (json \ "WriteCapacityUnits").as[Long]))
  }

  implicit def TableDescriptionFormat = new Format[TableDescription] {
    def writes(desc: TableDescription) = Json.obj(
      "TableName" -> Json.toJson(desc.name),<commit_msg>modified models to use Json combinators<commit_after>package aws.dynamodb

import play.api.libs.json.Json.toJson
import play.api.libs.json._
import play.api.libs.json.util._
import play.api.libs.json.Reads._
import play.api.libs.json.Writes._
  

package object models {

  sealed trait AttributeType {
    def typeCode: String
    override def toString = typeCode
  }

  object AttributeType {
    def apply(t: String) = t match {
      case "N" => DDBLong
      case "S" => DDBString
      case "B" => DDBBoolean
      case _ => sys.error("Invalid AttributeType: " + t)
    }
  }

  object DDBLong extends AttributeType {
    override def typeCode = "N"
  }

  object DDBString extends AttributeType {
    override def typeCode = "S"
  }

  object DDBBoolean extends AttributeType {
    override def typeCode = "B"
  }

  sealed trait Status {
    def status: String
  }

  object Status {
    object CREATING extends Status { override def status = "Creating" }
    object ACTIVE extends Status { override def status = "Active" }
    object DELETING extends Status { override def status = "Deleting" }
    object UPDATING extends Status { override def status = "Updating" }
    def apply(s: String) = s.toLowerCase match {
      case "creating" => CREATING
      case "active" => ACTIVE
      case "deleting" => DELETING
      case "updating" => UPDATING
      case _ => sys.error("Invalid table status: " + s)
    }
  }

  case class KeySchemaElement(attributeName: String, attributeType: AttributeType)

  case class KeySchema(hashKey: KeySchemaElement, rangeKey: Option[KeySchemaElement] = None)

  case class ProvisionedThroughput(readCapacityUnits: Long, writeCapacityUnits: Long)

  case class TableDescription(name: String,
                              status: Status,
                              creationDateTime: java.util.Date,
                              keySchema: KeySchema,
                              provisionedThroughput: ProvisionedThroughput,
                              size: Option[Long])

  // JSON Formatters

  /*implicit def KeySchemaElementFormat: Format[KeySchemaElement] = new Format[KeySchemaElement] {
    def writes(element: KeySchemaElement) = JsObject(Seq(
      "AttributeName" -> JsString(element.attributeName),
      "AttributeType" -> JsString(element.attributeType.toString)))
    def reads(json: JsValue) = JsSuccess(KeySchemaElement(
      (json \ "AttributeName").as[String],
      AttributeType((json \ "AttributeType").as[String])))
  }*/

  /*implicit def AttributeTypeFormat: Format[AttributeType] = new Format[AttributeType] {
    def writes(t: AttributeType) = JsString(t.typeCode)
    def reads(json: JsValue) = json match {
      case JsString(t) => JsSuccess(AttributeType(t))
      case _ => JsError("String expected")
    }
  }*/

  // should be written in a nicer and more symmetric way in more recent code not yet in master ;)
  implicit val AttributeTypeFormat = Format[AttributeType]( 
    __.read[String].map(t => AttributeType(t)),
    Writes( (at: AttributeType) => JsString(at.typeCode) )
  )

  implicit val KeySchemaElementFormat = (
    (__ \ 'AttributeName).format[String] and
    (__ \ 'AttributeType).format[AttributeType]
  )(KeySchemaElement, unlift(KeySchemaElement.unapply))

  implicit def KeySchemaFormat: Format[KeySchema] = new Format[KeySchema] {
    def writes(schema: KeySchema) = JsObject(
      Seq("HashKeyElement" -> toJson(schema.hashKey)) ++ schema.rangeKey.toSeq.map("rangeKeyElement" -> toJson(_)))
    def reads(json: JsValue) = JsSuccess(KeySchema(
      (json \ "HashKeyElement").as[KeySchemaElement],
      (json \ "RangeKeyElement") match {
        case JsUndefined(e) => None
        case js => js.asOpt[KeySchemaElement]
      }))
  }

  implicit def ProvisionedThroughputFormat = new Format[ProvisionedThroughput] {
    def writes(pt: ProvisionedThroughput) = Json.obj(
      "ReadCapacityUnits" -> Json.toJson(pt.readCapacityUnits),
      "WriteCapacityUnits" -> Json.toJson(pt.writeCapacityUnits))
    def reads(json: JsValue) = JsSuccess(ProvisionedThroughput(
      (json \ "ReadCapacityUnits").as[Long],
      (json \ "WriteCapacityUnits").as[Long]))
  }

  implicit def TableDescriptionFormat = new Format[TableDescription] {
    def writes(desc: TableDescription) = Json.obj(
      "TableName" -> Json.toJson(desc.name),
{'fraction_non_alphanumeric': 0.10667328206400396, 'fraction_numerical': 0.0, 'mean_word_length': 3.2126436781609193, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '913072', 'n_tokens_mistral': 2394, 'n_tokens_neox': 2350, 'n_words': 574}