All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.scalatra.util.conversion.conversions.scala Maven / Gradle / Ivy

package org.scalatra
package util
package conversion

import java.text.{ DateFormat, SimpleDateFormat }
import java.util.Date

import scala.util.control.Exception.allCatch

import scala.reflect.ClassTag

/**
 * Support types and implicits for [[org.scalatra.util.conversion.TypeConverter]].
 */
trait TypeConverterSupport {

  implicit def safe[S, T](f: S => T): TypeConverter[S, T] =
    (s: S) => allCatch opt f(s)

  /**
   * Implicit convert a `(String) => Option[T]` function into a `TypeConverter[T]`
   */
  implicit def safeOption[S, T](f: S => Option[T]): TypeConverter[S, T] =
    (v1: S) => allCatch.withApply(_ => None)(f(v1))

}

object TypeConverterSupport extends TypeConverterSupport

trait LowestPriorityImplicitConversions extends TypeConverterSupport {
  implicit def lowestPriorityAny2T[T: ClassTag]: TypeConverter[Any, T] = safe {
    case a if implicitly[ClassTag[T]].runtimeClass.isAssignableFrom(a.getClass) => a.asInstanceOf[T]
  }
}

trait LowPriorityImplicitConversions extends LowestPriorityImplicitConversions {

  implicit val anyToBoolean: TypeConverter[Any, Boolean] = safe {
    case b: Boolean => b
    case "ON" | "TRUE" | "OK" | "1" | "CHECKED" | "YES" | "ENABLE" | "ENABLED" => true
    case n: Number => n != 0
    case _ => false
  }

  implicit val anyToFloat: TypeConverter[Any, Float] = safe {
    case i: Byte => i.toFloat
    case i: Short => i.toFloat
    case i: Int => i.toFloat
    case i: Long => i.toFloat
    case i: Double => i.toFloat
    case i: Float => i
    case i: String => i.toFloat
  }

  implicit val anyToDouble: TypeConverter[Any, Double] = safe {
    case i: Byte => i.toDouble
    case i: Short => i.toDouble
    case i: Int => i.toDouble
    case i: Long => i.toDouble
    case i: Double => i
    case i: Float => i.toDouble
    case i: String => i.toDouble
  }

  implicit val anyToByte: TypeConverter[Any, Byte] = safe {
    case i: Byte => i
    case i: Short => i.toByte
    case i: Int => i.toByte
    case i: Long => i.toByte
    case i: Double => i.toByte
    case i: Float => i.toByte
    case i: String => i.toByte
  }

  implicit val anyToShort: TypeConverter[Any, Short] = safe {
    case i: Byte => i.toShort
    case i: Short => i
    case i: Int => i.toShort
    case i: Long => i.toShort
    case i: Double => i.toShort
    case i: Float => i.toShort
    case i: String => i.toShort
  }

  implicit val anyToInt: TypeConverter[Any, Int] = safe {
    case i: Byte => i.toInt
    case i: Short => i.toInt
    case i: Int => i
    case i: Long => i.toInt
    case i: Double => i.toInt
    case i: Float => i.toInt
    case i: String => i.toInt
  }

  implicit val anyToLong: TypeConverter[Any, Long] = safe {
    case i: Byte => i.toLong
    case i: Short => i.toLong
    case i: Int => i.toLong
    case i: Long => i
    case i: Double => i.toLong
    case i: Float => i.toLong
    case i: String => i.toLong
  }

  implicit val anyToString: TypeConverter[Any, String] = safe(_.toString)

}

trait BigDecimalImplicitConversions { self: DefaultImplicitConversions =>
  implicit val stringToBigDecimal: TypeConverter[String, BigDecimal] = safe(BigDecimal(_))
  implicit val stringToSeqBigDecimal: TypeConverter[String, Seq[BigDecimal]] = stringToSeq(stringToBigDecimal)
}

/**
 * Implicit TypeConverter values for value types and some factory method for
 * dates and seqs.
 */
trait DefaultImplicitConversions extends LowPriorityImplicitConversions {

  implicit val stringToBoolean: TypeConverter[String, Boolean] = safe { s =>
    s.toUpperCase match {
      case "ON" | "TRUE" | "OK" | "1" | "CHECKED" | "YES" | "ENABLE" | "ENABLED" => true
      case _ => false
    }
  }

  implicit val stringToFloat: TypeConverter[String, Float] = safe(_.toFloat)

  implicit val stringToDouble: TypeConverter[String, Double] = safe(_.toDouble)

  implicit val stringToByte: TypeConverter[String, Byte] = safe(_.toByte)

  implicit val stringToShort: TypeConverter[String, Short] = safe(_.toShort)

  implicit val stringToInt: TypeConverter[String, Int] = safe(_.toInt)

  implicit val stringToLong: TypeConverter[String, Long] = safe(_.toLong)

  implicit val stringToSelf: TypeConverter[String, String] = safe(identity)

  def stringToDate(format: => String): TypeConverter[String, Date] = stringToDateFormat(new SimpleDateFormat(format))

  def stringToDateFormat(format: => DateFormat): TypeConverter[String, Date] = safe(format.parse(_))

  implicit def defaultStringToSeq[T: ClassTag](implicit elementConverter: TypeConverter[String, T]): TypeConverter[String, Seq[T]] =
    stringToSeq[T](elementConverter)

  def stringToSeq[T: ClassTag](elementConverter: TypeConverter[String, T], separator: String = ","): TypeConverter[String, Seq[T]] =
    safe(s => s.split(separator).toSeq.flatMap(e => elementConverter(e.trim)))

  implicit def seqHead[T: ClassTag](implicit elementConverter: TypeConverter[String, T]): TypeConverter[Seq[String], T] =
    safeOption(_.headOption.flatMap(elementConverter(_)))

  implicit def seqToSeq[T: ClassTag](implicit elementConverter: TypeConverter[String, T]): TypeConverter[Seq[String], Seq[T]] =
    safe(_.flatMap(elementConverter(_)))

}

object Conversions extends DefaultImplicitConversions {

  private type StringTypeConverter[T] = TypeConverter[String, T]
  implicit class ValConversion(private val source: String) extends AnyVal {
    def as[T: StringTypeConverter]: Option[T] = implicitly[TypeConverter[String, T]].apply(source)
  }

  implicit class DateConversion(private val source: String) extends AnyVal {
    def asDate(format: String): Option[Date] = stringToDate(format).apply(source)
  }

  implicit class SeqConversion(private val source: String) extends AnyVal {
    def asSeq[T: ClassTag](separator: String)(implicit tc: TypeConverter[String, T]): Option[Seq[T]] =
      stringToSeq[T](tc, separator).apply(source)
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy