alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Play Framework/Scala example source code file (Column.scala)

This example Play Framework source code file (Column.scala) is included in my "Source Code Warehouse" project. The intent of this project is to help you more easily find Play Framework (and Scala) source code examples by using tags.

All credit for the original source code belongs to Play Framework; I'm just trying to make examples easier to find. (For my Scala work, see my Scala examples and tutorials.)

Play Framework tags/keywords

any, byte, cannot, column, int, left, long, mayerr, metadataitem, play, play framework, right

The Column.scala Play Framework example source code

/*
 * Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
 */
package anorm

import java.math.{ BigDecimal => JBigDec, BigInteger }

import java.util.{ Date, UUID }

/** Column mapping */
trait Column[A] extends ((Any, MetaDataItem) => MayErr[SqlRequestError, A])

/**
 * Column companion, providing default conversions.
 */
object Column {

  def apply[A](transformer: ((Any, MetaDataItem) => MayErr[SqlRequestError, A])): Column[A] = new Column[A] {

    def apply(value: Any, meta: MetaDataItem): MayErr[SqlRequestError, A] =
      transformer(value, meta)

  }

  def nonNull[A](transformer: ((Any, MetaDataItem) => MayErr[SqlRequestError, A])): Column[A] = Column[A] {
    case (value, meta @ MetaDataItem(qualified, _, _)) =>
      if (value != null) transformer(value, meta)
      else Left(UnexpectedNullableFound(qualified.toString))
  }

  implicit val columnToString: Column[String] =
    nonNull[String] { (value, meta) =>
      val MetaDataItem(qualified, nullable, clazz) = meta
      value match {
        case string: String => Right(string)
        case clob: java.sql.Clob => Right(clob.getSubString(1, clob.length.asInstanceOf[Int]))
        case _ => Left(TypeDoesNotMatch(s"Cannot convert $value: ${value.asInstanceOf[AnyRef].getClass} to String for column $qualified"))
      }
    }

  /**
   * Column conversion to character.
   *
   * {{{
   * import anorm.SqlParser.scalar
   * import anorm.Column.columnToChar
   *
   * val c: Char = SQL("SELECT char FROM tbl").as(scalar[Char].single)
   * }}}
   */
  implicit val columnToChar: Column[Char] = nonNull[Char] { (value, meta) =>
    val MetaDataItem(qualified, nullable, clazz) = meta
    value match {
      case string: String => Right(string.charAt(0))
      case clob: java.sql.Clob => Right(clob.getSubString(1, 1).charAt(0))
      case _ => Left(TypeDoesNotMatch(s"Cannot convert $value: ${value.asInstanceOf[AnyRef].getClass} to Char for column $qualified"))
    }
  }

  implicit val columnToInt: Column[Int] = nonNull { (value, meta) =>
    val MetaDataItem(qualified, nullable, clazz) = meta
    value match {
      case int: Int => Right(int)
      case _ => Left(TypeDoesNotMatch(s"Cannot convert $value: ${value.asInstanceOf[AnyRef].getClass} to Int for column $qualified"))
    }
  }

  implicit val columnToFloat: Column[Float] = nonNull { (value, meta) =>
    val MetaDataItem(qualified, nullable, clazz) = meta
    value match {
      case f: Float => Right(f)
      case bi: BigInteger => Right(bi.floatValue)
      case i: Int => Right(i.toFloat)
      case s: Short => Right(s.toFloat)
      case b: Byte => Right(b.toFloat)
      case _ => Left(TypeDoesNotMatch(s"Cannot convert $value: ${value.asInstanceOf[AnyRef].getClass} to Float for column $qualified"))
    }
  }

  implicit val columnToDouble: Column[Double] = nonNull { (value, meta) =>
    val MetaDataItem(qualified, nullable, clazz) = meta
    value match {
      case bg: JBigDec => Right(bg.doubleValue)
      case d: Double => Right(d)
      case f: Float => Right(new JBigDec(f.toString).doubleValue)
      case bi: BigInteger => Right(bi.doubleValue)
      case i: Int => Right(i.toDouble)
      case s: Short => Right(s.toDouble)
      case b: Byte => Right(b.toDouble)
      case _ => Left(TypeDoesNotMatch(s"Cannot convert $value: ${value.asInstanceOf[AnyRef].getClass} to Double for column $qualified"))
    }
  }

  implicit val columnToShort: Column[Short] = nonNull { (value, meta) =>
    val MetaDataItem(qualified, nullable, clazz) = meta
    value match {
      case b: Byte => Right(b.toShort)
      case s: Short => Right(s)
      case _ => Left(TypeDoesNotMatch(s"Cannot convert $value: ${value.asInstanceOf[AnyRef].getClass} to Short for column $qualified"))
    }
  }

  implicit val columnToByte: Column[Byte] = nonNull { (value, meta) =>
    val MetaDataItem(qualified, nullable, clazz) = meta
    value match {
      case b: Byte => Right(b)
      case s: Short => Right(s.toByte)
      case _ => Left(TypeDoesNotMatch(s"Cannot convert $value: ${value.asInstanceOf[AnyRef].getClass} to Byte for column $qualified"))
    }
  }

  implicit val columnToBoolean: Column[Boolean] = nonNull { (value, meta) =>
    val MetaDataItem(qualified, nullable, clazz) = meta
    value match {
      case bool: Boolean => Right(bool)
      case _ => Left(TypeDoesNotMatch(s"Cannot convert $value: ${value.asInstanceOf[AnyRef].getClass} to Boolean for column $qualified"))
    }
  }

  implicit val columnToLong: Column[Long] = nonNull { (value, meta) =>
    val MetaDataItem(qualified, nullable, clazz) = meta
    value match {
      case int: Int => Right(int: Long)
      case long: Long => Right(long)
      case _ => Left(TypeDoesNotMatch(s"Cannot convert $value: ${value.asInstanceOf[AnyRef].getClass} to Long for column $qualified"))
    }
  }

  // Used to convert Java or Scala big integer
  private def anyToBigInteger(value: Any, meta: MetaDataItem): MayErr[SqlRequestError, BigInteger] = {
    val MetaDataItem(qualified, nullable, clazz) = meta
    value match {
      case bi: BigInteger => Right(bi)
      case int: Int => Right(BigInteger.valueOf(int))
      case long: Long => Right(BigInteger.valueOf(long))
      case _ => Left(TypeDoesNotMatch(s"Cannot convert $value: ${value.asInstanceOf[AnyRef].getClass} to BigInteger for column $qualified"))
    }
  }

  /**
   * Column conversion to Java big integer.
   *
   * {{{
   * import anorm.SqlParser.scalar
   * import anorm.Column.columnToScalaBigInteger
   *
   * val c: BigInteger =
   *   SQL("SELECT COUNT(*) FROM tbl").as(scalar[BigInteger].single)
   * }}}
   */
  implicit val columnToBigInteger: Column[BigInteger] = nonNull(anyToBigInteger)

  /**
   * Column conversion to big integer.
   *
   * {{{
   * import anorm.SqlParser.scalar
   * import anorm.Column.columnToBigInt
   *
   * val c: BigInt =
   *   SQL("SELECT COUNT(*) FROM tbl").as(scalar[BigInt].single)
   * }}}
   */
  implicit val columnToBigInt: Column[BigInt] =
    nonNull((value, meta) => anyToBigInteger(value, meta).map(BigInt(_)))

  implicit val columnToUUID: Column[UUID] = nonNull { (value, meta) =>
    val MetaDataItem(qualified, nullable, clazz) = meta
    value match {
      case d: UUID => Right(d)
      case _ => Left(TypeDoesNotMatch(s"Cannot convert $value: ${value.asInstanceOf[AnyRef].getClass} to UUID for column $qualified"))
    }
  }

  // Used to convert Java or Scala big decimal
  private def anyToBigDecimal(value: Any, meta: MetaDataItem): MayErr[SqlRequestError, JBigDec] = {
    val MetaDataItem(qualified, nullable, clazz) = meta
    value match {
      // TODO: Conversion from integer types
      case bi: JBigDec => Right(bi)
      case double: Double => Right(JBigDec.valueOf(double))
      case l: Long => Right(JBigDec.valueOf(l))
      case _ => Left(TypeDoesNotMatch(s"Cannot convert $value: ${value.asInstanceOf[AnyRef].getClass} to BigDecimal for column $qualified"))
    }
  }

  /**
   * Column conversion to Java big decimal.
   *
   * {{{
   * import java.math.{ BigDecimal => JBigDecimal }
   * import anorm.SqlParser.scalar
   * import anorm.Column.columnToJavaBigDecimal
   *
   * val c: JBigDecimal =
   *   SQL("SELECT COUNT(*) FROM tbl").as(scalar[JBigDecimal].single)
   * }}}
   */
  implicit val columnToJavaBigDecimal: Column[JBigDec] =
    nonNull(anyToBigDecimal)

  /**
   * Column conversion to big decimal.
   *
   * {{{
   * import anorm.SqlParser.scalar
   * import anorm.Column.columnToScalaBigDecimal
   *
   * val c: BigDecimal =
   *   SQL("SELECT COUNT(*) FROM tbl").as(scalar[BigDecimal].single)
   * }}}
   */
  implicit val columnToScalaBigDecimal: Column[BigDecimal] =
    nonNull((value, meta) => anyToBigDecimal(value, meta).map(BigDecimal(_)))

  /**
   * Parses column as Java Date.
   * Time zone offset is the one of default JVM time zone
   * (see [[java.util.TimeZone.getDefault]]).
   *
   * {{{
   * import java.util.Date
   *
   * val d: Date = SQL("SELECT last_mod FROM tbl").as(scalar[Date].single)
   * }}}
   */
  implicit val columnToDate: Column[Date] = nonNull { (value, meta) =>
    val MetaDataItem(qualified, nullable, clazz) = meta
    value match {
      case date: Date => Right(date)
      case time: Long => Right(new Date(time))
      case _ => Left(TypeDoesNotMatch(s"Cannot convert $value: ${value.asInstanceOf[AnyRef].getClass} to Date for column $qualified"))
    }
  }

  implicit def columnToPk[T](implicit c: Column[T]): Column[Pk[T]] =
    nonNull { (value, meta) => c(value, meta).map(Id(_)) }

  implicit def columnToOption[T](implicit transformer: Column[T]): Column[Option[T]] = Column { (value, meta) =>
    if (value != null) transformer(value, meta).map(Some(_)) else (Right(None): MayErr[SqlRequestError, Option[T]])
  }

  /**
   * Parses column as array.
   *
   * val a: Array[String] =
   *   SQL"SELECT str_arr FROM tbl".as(scalar[Array[String]])
   * }}}
   */
  implicit def columnToArray[T](implicit transformer: Column[T], t: scala.reflect.ClassTag[T]): Column[Array[T]] = Column { (value, meta) =>
    val MetaDataItem(qualified, nullable, clazz) = meta

    @annotation.tailrec
    def transf(a: Array[_], p: Array[T]): MayErr[SqlRequestError, Array[T]] =
      a.headOption match {
        case Some(r) => transformer(r, meta).toEither match {
          case Right(v) => transf(a.tail, p :+ v)
          case _ => Left(TypeDoesNotMatch(s"Cannot convert $value: ${value.asInstanceOf[AnyRef].getClass} to array for column $qualified"))
        }
        case _ => Right(p)
      }

    value match {
      case sql: java.sql.Array => try {
        transf(sql.getArray.asInstanceOf[Array[_]], Array[T]())
      } catch {
        case _: Throwable => Left(TypeDoesNotMatch(s"Cannot convert $value: ${value.asInstanceOf[AnyRef].getClass} to array for column $qualified"))
      }

      case _ => Left(TypeDoesNotMatch(s"Cannot convert $value: ${value.asInstanceOf[AnyRef].getClass} to array for column $qualified"))
    }
  }

  /**
   * Parses column as list.
   *
   * val a: List[String] =
   *   SQL"SELECT str_arr FROM tbl".as(scalar[List[String]])
   * }}}
   */
  implicit def columnToList[T](implicit transformer: Column[T], t: scala.reflect.ClassTag[T]): Column[List[T]] = Column { (value, meta) =>
    val MetaDataItem(qualified, nullable, clazz) = meta

    @annotation.tailrec
    def transf(a: Array[_], p: List[T]): MayErr[SqlRequestError, List[T]] =
      a.headOption match {
        case Some(r) => transformer(r, meta).toEither match {
          case Right(v) => transf(a.tail, p :+ v)
          case _ => Left(TypeDoesNotMatch(s"Cannot convert $value: ${value.asInstanceOf[AnyRef].getClass} to list for column $qualified"))
        }
        case _ => Right(p)
      }

    value match {
      case sql: java.sql.Array => try {
        transf(sql.getArray.asInstanceOf[Array[_]], Nil)
      } catch {
        case _: Throwable => Left(TypeDoesNotMatch(s"Cannot convert $value: ${value.asInstanceOf[AnyRef].getClass} to list for column $qualified"))
      }

      case _ => Left(TypeDoesNotMatch(s"Cannot convert $value: ${value.asInstanceOf[AnyRef].getClass} to list for column $qualified"))
    }
  }
}

Other Play Framework source code examples

Here is a short list of links related to this Play Framework Column.scala source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.