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

org.specs2.text.NullString.scala Maven / Gradle / Ivy

The newest version!
package org.specs2
package text

import control.Exceptions._
import Quote._

/**
 * Utility methods to replace a null String with "null"
 *
 * They also make sure that the toString or mkString methods don't throw exceptions when being evaluated
 */
private[specs2]
trait NotNullStrings {

  /**
   * @return the string evaluation of an object
   *
   * - if it is null => null
   * - if this is an Array or a collection => it tries the toString method of the collection or evaluate each element separately (because they could be null too)
   * - if this is another type of object   => calls the toString method
   */
  implicit def anyToNotNull(a: Any) = new NotNullAny(a)
  class NotNullAny(a: Any) {
    def  notNull: String = {
      if (a == null) "null"
      else {
        a match {
          case ar: Array[_]           => ar.notNullMkString(", ", "Array(", ")")
          case it: TraversableOnce[_] => it.notNullMkStringWith(addQuotes = false)
          case _                      => evaluate(a)
        }
      }
    }

    /**
     * @return the string evaluation of an object + its class name
     *
     * - if it is null => null
     * - if this is an Array or a collection => it prints the class name of the full collection if each element has the same type: List[Int] for example
     *                                          other it prints each element with its class name
     * - if this is another type of object   => calls the toString method + getClass.getName
     */
    def  notNullWithClass: String = {
      if (a == null) "null"
      else {
        def sameElementTypes(ts: TraversableOnce[_]) =
          ts.nonEmpty && (ts.toSeq.collect { case t if !(t == null) => t.getClass.getName }.size == ts.size)
        tryOrElse {
          a match {
            case ar: Array[_]           =>
              if (sameElementTypes(ar)) ar.map(a => quote(a.notNull)).mkString(", ", "Array(", "): Array["+ar(0).getClass.getName+"]")
              else                      ar.map(_.notNullWithClass).mkString(", ", "Array(", ")")
            case it: TraversableOnce[_] =>
              if (sameElementTypes(it)) it.toSeq.notNullMkStringWith(addQuotes = true)+": "+it.getClass.getName+"["+it.toSeq(0).getClass.getName+"]"
              else                      it.toSeq.map(_.notNullWithClass)+": "+it.getClass.getName
            case _                      => evaluate(a)+": "+a.getClass.getName
          }
        }(evaluate(a)+": "+a.getClass.getName) // in case the collection throws an exception during its traversal
      }
    }
  }

  private def evaluate(value: =>Any, msg: String = "Exception when evaluating toString: ") = {
    val string = catchAllOr(value.toString) { (t: Throwable) => msg + t.getMessage }
    if (string == null) "null"
    else                string
  }

  trait NotNullMkString {
    def notNullMkString(sep: String, start: String = "", end: String = ""): String
  }
  implicit def arrayToNotNull[T](a: Array[T]): NotNullMkString = if (a == null) new NullMkString else new NotNullTraversableOnce(a.toSeq)

  class NullMkString extends NotNullMkString {
    def notNullMkString(sep: String, start: String = "", end: String = ""): String = "null"
  }

  implicit def traversableOnceToNotNull[T](a: =>TraversableOnce[T]): NotNullTraversableOnce[T] = new NotNullTraversableOnce(a)
  class NotNullTraversableOnce[T](values: =>TraversableOnce[T]) extends NotNullMkString {
    def notNullMkString(sep: String, start: String = "", end: String = ""): String = {
      if (values == null) "null"
      else                evaluate(catchAllOrElse(values.mkString(start, sep, end))(evaluate(values.toString)))
    }
    def notNullMkStringWith(addQuotes: Boolean = false): String = {
      def traversableWithQuotedElements = values.toSeq.map(v => quote(evaluate(v), addQuotes)).toString
      def quotedTraversable             = quote(evaluate(values.toString))

      if (values == null) quote("null", addQuotes)
      else if (addQuotes) evaluate(catchAllOrElse(traversableWithQuotedElements)(quotedTraversable))
      else                evaluate(catchAllOrElse(evaluate(values.toString))(values.toSeq.map(v => evaluate(v)).toString))
    }
  }

}
private[specs2]
object NotNullStrings extends NotNullStrings




© 2015 - 2025 Weber Informatics LLC | Privacy Policy