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

org.specs2.matcher.DataTable.scala Maven / Gradle / Ivy

The newest version!
package org.specs2
package matcher

import execute.*
import fp.{given, *}, syntax.*
import ResultExecution.*
import text.{NotNullStrings, Show1, Show10, Show2, Show3, Show4, Show5, Show6, Show7, Show8, Show9, TextTable, Trim}
import Trim.*
import NotNullStrings.*
import scala.concurrent.*, duration.*

/** This trait provides implicit definitions and types to create DataTables.
  *
  * A DataTable has a header defining column names and rows holding values. It is possible to apply a function taking
  * the row values and returning a Result.
  *
  * A TableHeader is defined by separating the column names with '|': ` "a" | "b" | "c"`
  *
  * A DataRow is defined by separating the row values with '!': ` 1 ! 2 ! 3`
  *
  * Note that the '!' method can conflict with the creation of Examples when the value is a string. In that case it is
  * possible to use the '!!! method to disambiguate:
  *
  * `"1" !! "2" ! "3"`
  *
  * In that case the first column of the header can also be defined with '||' for pure symmetry reasons:
  *
  * `"a" || "b" | "c"` `"1" !! "2" ! "3"`
  *
  * @see
  *   org.specs2.matcher.DataTablesSpec for examples
  */
trait DataTables extends ExpectationsCreation:

  /** @return a TableHeader with one heading only */
  given Conversion[String, TableHeader] with
    def apply(a: String): TableHeader =
      new TableHeader(List(a))

  /** @return a DataRow with one value only */
  given [T]: Conversion[T, DataRow1[T]] with
    def apply(a: T): DataRow1[T] =
      DataRow1(a)

  /** A DataTable with its header
    *
    * Children of this class are parametrized with the types of values that their rows can hold.
    */
  abstract class Table(val titles: List[String], val execute: Boolean = false):

    /** Collect the results of each row
      * @param results
      *   list of (row description, row execution result)
      * @return
      *   an aggregated Result from a list of results
      */
    protected def collect[R: AsResult](results: List[(Seq[String], R)]): DecoratedResult[DataTable] =
      val result = allSuccess(results)
      val decorated =
        DecoratedResult(
          DataTable(titles, results),
          result.setMessage {
            TextTable("" +: titles :+ "", results.map { case (line, r) => resultLine(line, AsResult(r)) }*).show
          }
        )
      checkResultFailure(decorated)
      decorated

    /** @return the logical and combination of all the results */
    private def allSuccess[R: AsResult](results: List[(Seq[String], R)]): Result =
      results.foldMap(r => AsResult(r._2))

    /** @return the status of the row + the values + the failure message if any */
    private def resultLine(line: Seq[String], result: Result): Seq[String] =
      val message = if result.isSuccess then "" else result.message
      result.status +: line :+ message

  /** GENERATED */
  case class TableHeader(titles: List[String]):
    def |(title: String) = copy(titles = this.titles :+ title)
    def ||(title: String) = copy(titles = this.titles :+ title)
    def |[T1](row: DataRow1[T1]) = new Table1(titles, List(row))
    def |>[T1](row: DataRow1[T1]) = new Table1(titles, List(row), execute = true)
    def |[T1, T2](row: DataRow2[T1, T2]) = new Table2(titles, List(row))
    def |>[T1, T2](row: DataRow2[T1, T2]) = new Table2(titles, List(row), execute = true)
    def |[T1, T2, T3](row: DataRow3[T1, T2, T3]) = new Table3(titles, List(row))
    def |>[T1, T2, T3](row: DataRow3[T1, T2, T3]) = new Table3(titles, List(row), execute = true)
    def |[T1, T2, T3, T4](row: DataRow4[T1, T2, T3, T4]) = new Table4(titles, List(row))
    def |>[T1, T2, T3, T4](row: DataRow4[T1, T2, T3, T4]) = new Table4(titles, List(row), execute = true)
    def |[T1, T2, T3, T4, T5](row: DataRow5[T1, T2, T3, T4, T5]) = new Table5(titles, List(row))
    def |>[T1, T2, T3, T4, T5](row: DataRow5[T1, T2, T3, T4, T5]) = new Table5(titles, List(row), execute = true)
    def |[T1, T2, T3, T4, T5, T6](row: DataRow6[T1, T2, T3, T4, T5, T6]) = new Table6(titles, List(row))
    def |>[T1, T2, T3, T4, T5, T6](row: DataRow6[T1, T2, T3, T4, T5, T6]) =
      new Table6(titles, List(row), execute = true)
    def |[T1, T2, T3, T4, T5, T6, T7](row: DataRow7[T1, T2, T3, T4, T5, T6, T7]) = new Table7(titles, List(row))
    def |>[T1, T2, T3, T4, T5, T6, T7](row: DataRow7[T1, T2, T3, T4, T5, T6, T7]) =
      new Table7(titles, List(row), execute = true)
    def |[T1, T2, T3, T4, T5, T6, T7, T8](row: DataRow8[T1, T2, T3, T4, T5, T6, T7, T8]) = new Table8(titles, List(row))
    def |>[T1, T2, T3, T4, T5, T6, T7, T8](row: DataRow8[T1, T2, T3, T4, T5, T6, T7, T8]) =
      new Table8(titles, List(row), execute = true)
    def |[T1, T2, T3, T4, T5, T6, T7, T8, T9](row: DataRow9[T1, T2, T3, T4, T5, T6, T7, T8, T9]) =
      new Table9(titles, List(row))
    def |>[T1, T2, T3, T4, T5, T6, T7, T8, T9](row: DataRow9[T1, T2, T3, T4, T5, T6, T7, T8, T9]) =
      new Table9(titles, List(row), execute = true)
    def |[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10](row: DataRow10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]) =
      new Table10(titles, List(row))
    def |>[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10](row: DataRow10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]) =
      new Table10(titles, List(row), execute = true)

  case class Table1[T1](
      override val titles: List[String],
      rows: List[DataRow1[T1]],
      override val execute: Boolean = false,
      show1: Show1[T1] = Show1[T1]()
  ) extends Table(titles, execute) { outer =>
    def |[S1 >: T1](row: DataRow1[S1])(using s1: Show1[S1] = Show1[S1]()) =
      Table1(titles, outer.rows :+ row, execute, s1)
    def |[R: AsResult](f: (T1) => R) = executeRow(f, execute)
    def |>[R: AsResult](f: (T1) => R) = executeRow(f, true)
    def executeRow[R: AsResult](f: (T1) => R, exec: Boolean): DecoratedResult[DataTable] =
      if exec then collect(rows map { (d: DataRow1[T1]) => (show1.showList(d.t1), AsResult(f(d.t1)).execute) })
      else DecoratedResult(DataTable(titles, Seq[DataTableRow]()), Success("ok"))
    def |@[M[_], R](f: (T1) => M[R])(using asResult: AsResult[R], app: Applicative[M]): M[DecoratedResult[DataTable]] =
      executeRowApply(f, execute)
    def |@>[M[_], R](f: (T1) => M[R])(using asResult: AsResult[R], app: Applicative[M]): M[DecoratedResult[DataTable]] =
      executeRowApply(f, true)
    def |*[R](f: (T1) => R)(using asResult: AsResult[R], ec: ExecutionContext): DecoratedResult[DataTable] =
      executeRowApply((t1: T1) => Future(f(t1))(ec), execute).run
    def |*>[R](f: (T1) => R)(using asResult: AsResult[R], ec: ExecutionContext): DecoratedResult[DataTable] =
      executeRowApply((t1: T1) => Future(f(t1))(ec), true).run
    def executeRowApply[R, M[_]](f: (T1) => M[R], exec: Boolean)(using
        asResult: AsResult[R],
        app: Applicative[M]
    ): M[DecoratedResult[DataTable]] =
      if exec then
        app.map(app.traverse(rows) { (d: DataRow1[T1]) =>
          app.map(f(d.t1))(r => (show1.showList(d.t1), AsResult(r).execute))
        })(rs => collect(rs))
      else app.pure(DecoratedResult(DataTable(titles, Seq[DataTableRow]()), Success("ok")))
  }
  case class Table2[T1, T2](
      override val titles: List[String],
      rows: List[DataRow2[T1, T2]],
      override val execute: Boolean = false,
      show2: Show2[T1, T2] = Show2[T1, T2]()
  ) extends Table(titles, execute) { outer =>
    def |[S1 >: T1, S2 >: T2](row: DataRow2[S1, S2])(using s2: Show2[S1, S2] = Show2[S1, S2]()) =
      Table2(titles, outer.rows :+ row, execute, s2)
    def |[R: AsResult](f: (T1, T2) => R) = executeRow(f, execute)
    def |>[R: AsResult](f: (T1, T2) => R) = executeRow(f, true)
    def executeRow[R: AsResult](f: (T1, T2) => R, exec: Boolean): DecoratedResult[DataTable] =
      if exec then
        collect(rows map { (d: DataRow2[T1, T2]) => (show2.showList(d.t1, d.t2), AsResult(f(d.t1, d.t2)).execute) })
      else DecoratedResult(DataTable(titles, Seq[DataTableRow]()), Success("ok"))
    def |@[M[_], R](
        f: (T1, T2) => M[R]
    )(using asResult: AsResult[R], app: Applicative[M]): M[DecoratedResult[DataTable]] =
      executeRowApply(f, execute)
    def |@>[M[_], R](
        f: (T1, T2) => M[R]
    )(using asResult: AsResult[R], app: Applicative[M]): M[DecoratedResult[DataTable]] =
      executeRowApply(f, true)
    def |*[R](f: (T1, T2) => R)(using asResult: AsResult[R], ec: ExecutionContext): DecoratedResult[DataTable] =
      executeRowApply((t1: T1, t2: T2) => Future(f(t1, t2))(ec), execute).run
    def |*>[R](f: (T1, T2) => R)(using asResult: AsResult[R], ec: ExecutionContext): DecoratedResult[DataTable] =
      executeRowApply((t1: T1, t2: T2) => Future(f(t1, t2))(ec), true).run
    def executeRowApply[R, M[_]](f: (T1, T2) => M[R], exec: Boolean)(using
        asResult: AsResult[R],
        app: Applicative[M]
    ): M[DecoratedResult[DataTable]] =
      if exec then
        app.map(app.traverse(rows) { (d: DataRow2[T1, T2]) =>
          app.map(f(d.t1, d.t2))(r => (show2.showList(d.t1, d.t2), AsResult(r).execute))
        })(rs => collect(rs))
      else app.pure(DecoratedResult(DataTable(titles, Seq[DataTableRow]()), Success("ok")))
  }
  case class Table3[T1, T2, T3](
      override val titles: List[String],
      rows: List[DataRow3[T1, T2, T3]],
      override val execute: Boolean = false,
      show3: Show3[T1, T2, T3] = Show3[T1, T2, T3]()
  ) extends Table(titles, execute) { outer =>
    def |[S1 >: T1, S2 >: T2, S3 >: T3](row: DataRow3[S1, S2, S3])(using s3: Show3[S1, S2, S3] = Show3[S1, S2, S3]()) =
      Table3(titles, outer.rows :+ row, execute, s3)
    def |[R: AsResult](f: (T1, T2, T3) => R) = executeRow(f, execute)
    def |>[R: AsResult](f: (T1, T2, T3) => R) = executeRow(f, true)
    def executeRow[R: AsResult](f: (T1, T2, T3) => R, exec: Boolean): DecoratedResult[DataTable] =
      if exec then
        collect(rows map { (d: DataRow3[T1, T2, T3]) =>
          (show3.showList(d.t1, d.t2, d.t3), AsResult(f(d.t1, d.t2, d.t3)).execute)
        })
      else DecoratedResult(DataTable(titles, Seq[DataTableRow]()), Success("ok"))
    def |@[M[_], R](
        f: (T1, T2, T3) => M[R]
    )(using asResult: AsResult[R], app: Applicative[M]): M[DecoratedResult[DataTable]] =
      executeRowApply(f, execute)
    def |@>[M[_], R](
        f: (T1, T2, T3) => M[R]
    )(using asResult: AsResult[R], app: Applicative[M]): M[DecoratedResult[DataTable]] =
      executeRowApply(f, true)
    def |*[R](f: (T1, T2, T3) => R)(using asResult: AsResult[R], ec: ExecutionContext): DecoratedResult[DataTable] =
      executeRowApply((t1: T1, t2: T2, t3: T3) => Future(f(t1, t2, t3))(ec), execute).run
    def |*>[R](f: (T1, T2, T3) => R)(using asResult: AsResult[R], ec: ExecutionContext): DecoratedResult[DataTable] =
      executeRowApply((t1: T1, t2: T2, t3: T3) => Future(f(t1, t2, t3))(ec), true).run
    def executeRowApply[R, M[_]](f: (T1, T2, T3) => M[R], exec: Boolean)(using
        asResult: AsResult[R],
        app: Applicative[M]
    ): M[DecoratedResult[DataTable]] =
      if exec then
        app.map(app.traverse(rows) { (d: DataRow3[T1, T2, T3]) =>
          app.map(f(d.t1, d.t2, d.t3))(r => (show3.showList(d.t1, d.t2, d.t3), AsResult(r).execute))
        })(rs => collect(rs))
      else app.pure(DecoratedResult(DataTable(titles, Seq[DataTableRow]()), Success("ok")))
  }
  case class Table4[T1, T2, T3, T4](
      override val titles: List[String],
      rows: List[DataRow4[T1, T2, T3, T4]],
      override val execute: Boolean = false,
      show4: Show4[T1, T2, T3, T4] = Show4[T1, T2, T3, T4]()
  ) extends Table(titles, execute) { outer =>
    def |[S1 >: T1, S2 >: T2, S3 >: T3, S4 >: T4](row: DataRow4[S1, S2, S3, S4])(using
        s4: Show4[S1, S2, S3, S4] = Show4[S1, S2, S3, S4]()
    ) = Table4(titles, outer.rows :+ row, execute, s4)
    def |[R: AsResult](f: (T1, T2, T3, T4) => R) = executeRow(f, execute)
    def |>[R: AsResult](f: (T1, T2, T3, T4) => R) = executeRow(f, true)
    def executeRow[R: AsResult](f: (T1, T2, T3, T4) => R, exec: Boolean): DecoratedResult[DataTable] =
      if exec then
        collect(rows map { (d: DataRow4[T1, T2, T3, T4]) =>
          (show4.showList(d.t1, d.t2, d.t3, d.t4), AsResult(f(d.t1, d.t2, d.t3, d.t4)).execute)
        })
      else DecoratedResult(DataTable(titles, Seq[DataTableRow]()), Success("ok"))
    def |@[M[_], R](
        f: (T1, T2, T3, T4) => M[R]
    )(using asResult: AsResult[R], app: Applicative[M]): M[DecoratedResult[DataTable]] =
      executeRowApply(f, execute)
    def |@>[M[_], R](
        f: (T1, T2, T3, T4) => M[R]
    )(using asResult: AsResult[R], app: Applicative[M]): M[DecoratedResult[DataTable]] =
      executeRowApply(f, true)
    def |*[R](f: (T1, T2, T3, T4) => R)(using asResult: AsResult[R], ec: ExecutionContext): DecoratedResult[DataTable] =
      executeRowApply((t1: T1, t2: T2, t3: T3, t4: T4) => Future(f(t1, t2, t3, t4))(ec), execute).run
    def |*>[R](
        f: (T1, T2, T3, T4) => R
    )(using asResult: AsResult[R], ec: ExecutionContext): DecoratedResult[DataTable] =
      executeRowApply((t1: T1, t2: T2, t3: T3, t4: T4) => Future(f(t1, t2, t3, t4))(ec), true).run
    def executeRowApply[R, M[_]](f: (T1, T2, T3, T4) => M[R], exec: Boolean)(using
        asResult: AsResult[R],
        app: Applicative[M]
    ): M[DecoratedResult[DataTable]] =
      if exec then
        app.map(app.traverse(rows) { (d: DataRow4[T1, T2, T3, T4]) =>
          app.map(f(d.t1, d.t2, d.t3, d.t4))(r => (show4.showList(d.t1, d.t2, d.t3, d.t4), AsResult(r).execute))
        })(rs => collect(rs))
      else app.pure(DecoratedResult(DataTable(titles, Seq[DataTableRow]()), Success("ok")))
  }
  case class Table5[T1, T2, T3, T4, T5](
      override val titles: List[String],
      rows: List[DataRow5[T1, T2, T3, T4, T5]],
      override val execute: Boolean = false,
      show5: Show5[T1, T2, T3, T4, T5] = Show5[T1, T2, T3, T4, T5]()
  ) extends Table(titles, execute) { outer =>
    def |[S1 >: T1, S2 >: T2, S3 >: T3, S4 >: T4, S5 >: T5](row: DataRow5[S1, S2, S3, S4, S5])(using
        s5: Show5[S1, S2, S3, S4, S5] = Show5[S1, S2, S3, S4, S5]()
    ) = Table5(titles, outer.rows :+ row, execute, s5)
    def |[R: AsResult](f: (T1, T2, T3, T4, T5) => R) = executeRow(f, execute)
    def |>[R: AsResult](f: (T1, T2, T3, T4, T5) => R) = executeRow(f, true)
    def executeRow[R: AsResult](f: (T1, T2, T3, T4, T5) => R, exec: Boolean): DecoratedResult[DataTable] =
      if exec then
        collect(rows map { (d: DataRow5[T1, T2, T3, T4, T5]) =>
          (show5.showList(d.t1, d.t2, d.t3, d.t4, d.t5), AsResult(f(d.t1, d.t2, d.t3, d.t4, d.t5)).execute)
        })
      else DecoratedResult(DataTable(titles, Seq[DataTableRow]()), Success("ok"))
    def |@[M[_], R](
        f: (T1, T2, T3, T4, T5) => M[R]
    )(using asResult: AsResult[R], app: Applicative[M]): M[DecoratedResult[DataTable]] =
      executeRowApply(f, execute)
    def |@>[M[_], R](
        f: (T1, T2, T3, T4, T5) => M[R]
    )(using asResult: AsResult[R], app: Applicative[M]): M[DecoratedResult[DataTable]] =
      executeRowApply(f, true)
    def |*[R](
        f: (T1, T2, T3, T4, T5) => R
    )(using asResult: AsResult[R], ec: ExecutionContext): DecoratedResult[DataTable] =
      executeRowApply((t1: T1, t2: T2, t3: T3, t4: T4, t5: T5) => Future(f(t1, t2, t3, t4, t5))(ec), execute).run
    def |*>[R](
        f: (T1, T2, T3, T4, T5) => R
    )(using asResult: AsResult[R], ec: ExecutionContext): DecoratedResult[DataTable] =
      executeRowApply((t1: T1, t2: T2, t3: T3, t4: T4, t5: T5) => Future(f(t1, t2, t3, t4, t5))(ec), true).run
    def executeRowApply[R, M[_]](f: (T1, T2, T3, T4, T5) => M[R], exec: Boolean)(using
        asResult: AsResult[R],
        app: Applicative[M]
    ): M[DecoratedResult[DataTable]] =
      if exec then
        app.map(app.traverse(rows) { (d: DataRow5[T1, T2, T3, T4, T5]) =>
          app.map(f(d.t1, d.t2, d.t3, d.t4, d.t5))(r =>
            (show5.showList(d.t1, d.t2, d.t3, d.t4, d.t5), AsResult(r).execute)
          )
        })(rs => collect(rs))
      else app.pure(DecoratedResult(DataTable(titles, Seq[DataTableRow]()), Success("ok")))
  }
  case class Table6[T1, T2, T3, T4, T5, T6](
      override val titles: List[String],
      rows: List[DataRow6[T1, T2, T3, T4, T5, T6]],
      override val execute: Boolean = false,
      show6: Show6[T1, T2, T3, T4, T5, T6] = Show6[T1, T2, T3, T4, T5, T6]()
  ) extends Table(titles, execute) { outer =>
    def |[S1 >: T1, S2 >: T2, S3 >: T3, S4 >: T4, S5 >: T5, S6 >: T6](row: DataRow6[S1, S2, S3, S4, S5, S6])(using
        s6: Show6[S1, S2, S3, S4, S5, S6] = Show6[S1, S2, S3, S4, S5, S6]()
    ) = Table6(titles, outer.rows :+ row, execute, s6)
    def |[R: AsResult](f: (T1, T2, T3, T4, T5, T6) => R) = executeRow(f, execute)
    def |>[R: AsResult](f: (T1, T2, T3, T4, T5, T6) => R) = executeRow(f, true)
    def executeRow[R: AsResult](f: (T1, T2, T3, T4, T5, T6) => R, exec: Boolean): DecoratedResult[DataTable] =
      if exec then
        collect(rows map { (d: DataRow6[T1, T2, T3, T4, T5, T6]) =>
          (show6.showList(d.t1, d.t2, d.t3, d.t4, d.t5, d.t6), AsResult(f(d.t1, d.t2, d.t3, d.t4, d.t5, d.t6)).execute)
        })
      else DecoratedResult(DataTable(titles, Seq[DataTableRow]()), Success("ok"))
    def |@[M[_], R](
        f: (T1, T2, T3, T4, T5, T6) => M[R]
    )(using asResult: AsResult[R], app: Applicative[M]): M[DecoratedResult[DataTable]] =
      executeRowApply(f, execute)
    def |@>[M[_], R](
        f: (T1, T2, T3, T4, T5, T6) => M[R]
    )(using asResult: AsResult[R], app: Applicative[M]): M[DecoratedResult[DataTable]] =
      executeRowApply(f, true)
    def |*[R](
        f: (T1, T2, T3, T4, T5, T6) => R
    )(using asResult: AsResult[R], ec: ExecutionContext): DecoratedResult[DataTable] =
      executeRowApply(
        (t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6) => Future(f(t1, t2, t3, t4, t5, t6))(ec),
        execute
      ).run
    def |*>[R](
        f: (T1, T2, T3, T4, T5, T6) => R
    )(using asResult: AsResult[R], ec: ExecutionContext): DecoratedResult[DataTable] =
      executeRowApply(
        (t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6) => Future(f(t1, t2, t3, t4, t5, t6))(ec),
        true
      ).run
    def executeRowApply[R, M[_]](f: (T1, T2, T3, T4, T5, T6) => M[R], exec: Boolean)(using
        asResult: AsResult[R],
        app: Applicative[M]
    ): M[DecoratedResult[DataTable]] =
      if exec then
        app.map(app.traverse(rows) { (d: DataRow6[T1, T2, T3, T4, T5, T6]) =>
          app.map(f(d.t1, d.t2, d.t3, d.t4, d.t5, d.t6))(r =>
            (show6.showList(d.t1, d.t2, d.t3, d.t4, d.t5, d.t6), AsResult(r).execute)
          )
        })(rs => collect(rs))
      else app.pure(DecoratedResult(DataTable(titles, Seq[DataTableRow]()), Success("ok")))
  }
  case class Table7[T1, T2, T3, T4, T5, T6, T7](
      override val titles: List[String],
      rows: List[DataRow7[T1, T2, T3, T4, T5, T6, T7]],
      override val execute: Boolean = false,
      show7: Show7[T1, T2, T3, T4, T5, T6, T7] = Show7[T1, T2, T3, T4, T5, T6, T7]()
  ) extends Table(titles, execute) { outer =>
    def |[S1 >: T1, S2 >: T2, S3 >: T3, S4 >: T4, S5 >: T5, S6 >: T6, S7 >: T7](
        row: DataRow7[S1, S2, S3, S4, S5, S6, S7]
    )(using s7: Show7[S1, S2, S3, S4, S5, S6, S7] = Show7[S1, S2, S3, S4, S5, S6, S7]()) =
      Table7(titles, outer.rows :+ row, execute, s7)
    def |[R: AsResult](f: (T1, T2, T3, T4, T5, T6, T7) => R) = executeRow(f, execute)
    def |>[R: AsResult](f: (T1, T2, T3, T4, T5, T6, T7) => R) = executeRow(f, true)
    def executeRow[R: AsResult](f: (T1, T2, T3, T4, T5, T6, T7) => R, exec: Boolean): DecoratedResult[DataTable] =
      if exec then
        collect(rows map { (d: DataRow7[T1, T2, T3, T4, T5, T6, T7]) =>
          (
            show7.showList(d.t1, d.t2, d.t3, d.t4, d.t5, d.t6, d.t7),
            AsResult(f(d.t1, d.t2, d.t3, d.t4, d.t5, d.t6, d.t7)).execute
          )
        })
      else DecoratedResult(DataTable(titles, Seq[DataTableRow]()), Success("ok"))
    def |@[M[_], R](
        f: (T1, T2, T3, T4, T5, T6, T7) => M[R]
    )(using asResult: AsResult[R], app: Applicative[M]): M[DecoratedResult[DataTable]] =
      executeRowApply(f, execute)
    def |@>[M[_], R](
        f: (T1, T2, T3, T4, T5, T6, T7) => M[R]
    )(using asResult: AsResult[R], app: Applicative[M]): M[DecoratedResult[DataTable]] =
      executeRowApply(f, true)
    def |*[R](
        f: (T1, T2, T3, T4, T5, T6, T7) => R
    )(using asResult: AsResult[R], ec: ExecutionContext): DecoratedResult[DataTable] =
      executeRowApply(
        (t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6, t7: T7) => Future(f(t1, t2, t3, t4, t5, t6, t7))(ec),
        execute
      ).run
    def |*>[R](
        f: (T1, T2, T3, T4, T5, T6, T7) => R
    )(using asResult: AsResult[R], ec: ExecutionContext): DecoratedResult[DataTable] =
      executeRowApply(
        (t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6, t7: T7) => Future(f(t1, t2, t3, t4, t5, t6, t7))(ec),
        true
      ).run
    def executeRowApply[R, M[_]](f: (T1, T2, T3, T4, T5, T6, T7) => M[R], exec: Boolean)(using
        asResult: AsResult[R],
        app: Applicative[M]
    ): M[DecoratedResult[DataTable]] =
      if exec then
        app.map(app.traverse(rows) { (d: DataRow7[T1, T2, T3, T4, T5, T6, T7]) =>
          app.map(f(d.t1, d.t2, d.t3, d.t4, d.t5, d.t6, d.t7))(r =>
            (show7.showList(d.t1, d.t2, d.t3, d.t4, d.t5, d.t6, d.t7), AsResult(r).execute)
          )
        })(rs => collect(rs))
      else app.pure(DecoratedResult(DataTable(titles, Seq[DataTableRow]()), Success("ok")))
  }
  case class Table8[T1, T2, T3, T4, T5, T6, T7, T8](
      override val titles: List[String],
      rows: List[DataRow8[T1, T2, T3, T4, T5, T6, T7, T8]],
      override val execute: Boolean = false,
      show8: Show8[T1, T2, T3, T4, T5, T6, T7, T8] = Show8[T1, T2, T3, T4, T5, T6, T7, T8]()
  ) extends Table(titles, execute) { outer =>
    def |[S1 >: T1, S2 >: T2, S3 >: T3, S4 >: T4, S5 >: T5, S6 >: T6, S7 >: T7, S8 >: T8](
        row: DataRow8[S1, S2, S3, S4, S5, S6, S7, S8]
    )(using s8: Show8[S1, S2, S3, S4, S5, S6, S7, S8] = Show8[S1, S2, S3, S4, S5, S6, S7, S8]()) =
      Table8(titles, outer.rows :+ row, execute, s8)
    def |[R: AsResult](f: (T1, T2, T3, T4, T5, T6, T7, T8) => R) = executeRow(f, execute)
    def |>[R: AsResult](f: (T1, T2, T3, T4, T5, T6, T7, T8) => R) = executeRow(f, true)
    def executeRow[R: AsResult](f: (T1, T2, T3, T4, T5, T6, T7, T8) => R, exec: Boolean): DecoratedResult[DataTable] =
      if exec then
        collect(rows map { (d: DataRow8[T1, T2, T3, T4, T5, T6, T7, T8]) =>
          (
            show8.showList(d.t1, d.t2, d.t3, d.t4, d.t5, d.t6, d.t7, d.t8),
            AsResult(f(d.t1, d.t2, d.t3, d.t4, d.t5, d.t6, d.t7, d.t8)).execute
          )
        })
      else DecoratedResult(DataTable(titles, Seq[DataTableRow]()), Success("ok"))
    def |@[M[_], R](
        f: (T1, T2, T3, T4, T5, T6, T7, T8) => M[R]
    )(using asResult: AsResult[R], app: Applicative[M]): M[DecoratedResult[DataTable]] =
      executeRowApply(f, execute)
    def |@>[M[_], R](
        f: (T1, T2, T3, T4, T5, T6, T7, T8) => M[R]
    )(using asResult: AsResult[R], app: Applicative[M]): M[DecoratedResult[DataTable]] =
      executeRowApply(f, true)
    def |*[R](
        f: (T1, T2, T3, T4, T5, T6, T7, T8) => R
    )(using asResult: AsResult[R], ec: ExecutionContext): DecoratedResult[DataTable] =
      executeRowApply(
        (t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6, t7: T7, t8: T8) =>
          Future(f(t1, t2, t3, t4, t5, t6, t7, t8))(ec),
        execute
      ).run
    def |*>[R](
        f: (T1, T2, T3, T4, T5, T6, T7, T8) => R
    )(using asResult: AsResult[R], ec: ExecutionContext): DecoratedResult[DataTable] =
      executeRowApply(
        (t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6, t7: T7, t8: T8) =>
          Future(f(t1, t2, t3, t4, t5, t6, t7, t8))(ec),
        true
      ).run
    def executeRowApply[R, M[_]](f: (T1, T2, T3, T4, T5, T6, T7, T8) => M[R], exec: Boolean)(using
        asResult: AsResult[R],
        app: Applicative[M]
    ): M[DecoratedResult[DataTable]] =
      if exec then
        app.map(app.traverse(rows) { (d: DataRow8[T1, T2, T3, T4, T5, T6, T7, T8]) =>
          app.map(f(d.t1, d.t2, d.t3, d.t4, d.t5, d.t6, d.t7, d.t8))(r =>
            (show8.showList(d.t1, d.t2, d.t3, d.t4, d.t5, d.t6, d.t7, d.t8), AsResult(r).execute)
          )
        })(rs => collect(rs))
      else app.pure(DecoratedResult(DataTable(titles, Seq[DataTableRow]()), Success("ok")))
  }
  case class Table9[T1, T2, T3, T4, T5, T6, T7, T8, T9](
      override val titles: List[String],
      rows: List[DataRow9[T1, T2, T3, T4, T5, T6, T7, T8, T9]],
      override val execute: Boolean = false,
      show9: Show9[T1, T2, T3, T4, T5, T6, T7, T8, T9] = Show9[T1, T2, T3, T4, T5, T6, T7, T8, T9]()
  ) extends Table(titles, execute) { outer =>
    def |[S1 >: T1, S2 >: T2, S3 >: T3, S4 >: T4, S5 >: T5, S6 >: T6, S7 >: T7, S8 >: T8, S9 >: T9](
        row: DataRow9[S1, S2, S3, S4, S5, S6, S7, S8, S9]
    )(using s9: Show9[S1, S2, S3, S4, S5, S6, S7, S8, S9] = Show9[S1, S2, S3, S4, S5, S6, S7, S8, S9]()) =
      Table9(titles, outer.rows :+ row, execute, s9)
    def |[R: AsResult](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9) => R) = executeRow(f, execute)
    def |>[R: AsResult](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9) => R) = executeRow(f, true)
    def executeRow[R: AsResult](
        f: (T1, T2, T3, T4, T5, T6, T7, T8, T9) => R,
        exec: Boolean
    ): DecoratedResult[DataTable] =
      if exec then
        collect(rows map { (d: DataRow9[T1, T2, T3, T4, T5, T6, T7, T8, T9]) =>
          (
            show9.showList(d.t1, d.t2, d.t3, d.t4, d.t5, d.t6, d.t7, d.t8, d.t9),
            AsResult(f(d.t1, d.t2, d.t3, d.t4, d.t5, d.t6, d.t7, d.t8, d.t9)).execute
          )
        })
      else DecoratedResult(DataTable(titles, Seq[DataTableRow]()), Success("ok"))
    def |@[M[_], R](
        f: (T1, T2, T3, T4, T5, T6, T7, T8, T9) => M[R]
    )(using asResult: AsResult[R], app: Applicative[M]): M[DecoratedResult[DataTable]] =
      executeRowApply(f, execute)
    def |@>[M[_], R](
        f: (T1, T2, T3, T4, T5, T6, T7, T8, T9) => M[R]
    )(using asResult: AsResult[R], app: Applicative[M]): M[DecoratedResult[DataTable]] =
      executeRowApply(f, true)
    def |*[R](
        f: (T1, T2, T3, T4, T5, T6, T7, T8, T9) => R
    )(using asResult: AsResult[R], ec: ExecutionContext): DecoratedResult[DataTable] =
      executeRowApply(
        (t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6, t7: T7, t8: T8, t9: T9) =>
          Future(f(t1, t2, t3, t4, t5, t6, t7, t8, t9))(ec),
        execute
      ).run
    def |*>[R](
        f: (T1, T2, T3, T4, T5, T6, T7, T8, T9) => R
    )(using asResult: AsResult[R], ec: ExecutionContext): DecoratedResult[DataTable] =
      executeRowApply(
        (t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6, t7: T7, t8: T8, t9: T9) =>
          Future(f(t1, t2, t3, t4, t5, t6, t7, t8, t9))(ec),
        true
      ).run
    def executeRowApply[R, M[_]](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9) => M[R], exec: Boolean)(using
        asResult: AsResult[R],
        app: Applicative[M]
    ): M[DecoratedResult[DataTable]] =
      if exec then
        app.map(app.traverse(rows) { (d: DataRow9[T1, T2, T3, T4, T5, T6, T7, T8, T9]) =>
          app.map(f(d.t1, d.t2, d.t3, d.t4, d.t5, d.t6, d.t7, d.t8, d.t9))(r =>
            (show9.showList(d.t1, d.t2, d.t3, d.t4, d.t5, d.t6, d.t7, d.t8, d.t9), AsResult(r).execute)
          )
        })(rs => collect(rs))
      else app.pure(DecoratedResult(DataTable(titles, Seq[DataTableRow]()), Success("ok")))
  }
  case class Table10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10](
      override val titles: List[String],
      rows: List[DataRow10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]],
      override val execute: Boolean = false,
      show10: Show10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10] = Show10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]()
  ) extends Table(titles, execute) { outer =>
    def |[S1 >: T1, S2 >: T2, S3 >: T3, S4 >: T4, S5 >: T5, S6 >: T6, S7 >: T7, S8 >: T8, S9 >: T9, S10 >: T10](
        row: DataRow10[S1, S2, S3, S4, S5, S6, S7, S8, S9, S10]
    )(using s10: Show10[S1, S2, S3, S4, S5, S6, S7, S8, S9, S10] = Show10[S1, S2, S3, S4, S5, S6, S7, S8, S9, S10]()) =
      Table10(titles, outer.rows :+ row, execute, s10)
    def |[R: AsResult](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) => R) = executeRow(f, execute)
    def |>[R: AsResult](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) => R) = executeRow(f, true)
    def executeRow[R: AsResult](
        f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) => R,
        exec: Boolean
    ): DecoratedResult[DataTable] =
      if exec then
        collect(rows map { (d: DataRow10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]) =>
          (
            show10.showList(d.t1, d.t2, d.t3, d.t4, d.t5, d.t6, d.t7, d.t8, d.t9, d.t10),
            AsResult(f(d.t1, d.t2, d.t3, d.t4, d.t5, d.t6, d.t7, d.t8, d.t9, d.t10)).execute
          )
        })
      else DecoratedResult(DataTable(titles, Seq[DataTableRow]()), Success("ok"))
    def |@[M[_], R](
        f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) => M[R]
    )(using asResult: AsResult[R], app: Applicative[M]): M[DecoratedResult[DataTable]] =
      executeRowApply(f, execute)
    def |@>[M[_], R](
        f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) => M[R]
    )(using asResult: AsResult[R], app: Applicative[M]): M[DecoratedResult[DataTable]] =
      executeRowApply(f, true)
    def |*[R](
        f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) => R
    )(using asResult: AsResult[R], ec: ExecutionContext): DecoratedResult[DataTable] =
      executeRowApply(
        (t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6, t7: T7, t8: T8, t9: T9, t10: T10) =>
          Future(f(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10))(ec),
        execute
      ).run
    def |*>[R](
        f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) => R
    )(using asResult: AsResult[R], ec: ExecutionContext): DecoratedResult[DataTable] =
      executeRowApply(
        (t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6, t7: T7, t8: T8, t9: T9, t10: T10) =>
          Future(f(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10))(ec),
        true
      ).run
    def executeRowApply[R, M[_]](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) => M[R], exec: Boolean)(using
        asResult: AsResult[R],
        app: Applicative[M]
    ): M[DecoratedResult[DataTable]] =
      if exec then
        app.map(app.traverse(rows) { (d: DataRow10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]) =>
          app.map(f(d.t1, d.t2, d.t3, d.t4, d.t5, d.t6, d.t7, d.t8, d.t9, d.t10))(r =>
            (show10.showList(d.t1, d.t2, d.t3, d.t4, d.t5, d.t6, d.t7, d.t8, d.t9, d.t10), AsResult(r).execute)
          )
        })(rs => collect(rs))
      else app.pure(DecoratedResult(DataTable(titles, Seq[DataTableRow]()), Success("ok")))
  }

  extension [A](f: Future[A])
    def run: A =
      Await.result(f, Duration.Inf)

  abstract class DataRow[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10] extends Product:
    def show = productIterator.mkString("|", "|", "|")
    def showCells = productIterator.map(_.notNull).toSeq

  case class DataRow1[+T1](t1: T1) extends DataRow[T1, Any, Any, Any, Any, Any, Any, Any, Any, Any]:
    def ![S2](t2: S2) = DataRow2(t1, t2)
    def !![S2](t2: S2) = DataRow2(t1, t2)
  case class DataRow2[+T1, +T2](t1: T1, t2: T2) extends DataRow[T1, T2, Any, Any, Any, Any, Any, Any, Any, Any]:
    def ![S3](t3: S3) = DataRow3(t1, t2, t3)
    def !![S3](t3: S3) = DataRow3(t1, t2, t3)
  case class DataRow3[+T1, +T2, +T3](t1: T1, t2: T2, t3: T3)
      extends DataRow[T1, T2, T3, Any, Any, Any, Any, Any, Any, Any]:
    def ![S4](t4: S4) = DataRow4(t1, t2, t3, t4)
    def !![S4](t4: S4) = DataRow4(t1, t2, t3, t4)
  case class DataRow4[+T1, +T2, +T3, +T4](t1: T1, t2: T2, t3: T3, t4: T4)
      extends DataRow[T1, T2, T3, T4, Any, Any, Any, Any, Any, Any]:
    def ![S5](t5: S5) = DataRow5(t1, t2, t3, t4, t5)
    def !![S5](t5: S5) = DataRow5(t1, t2, t3, t4, t5)
  case class DataRow5[+T1, +T2, +T3, +T4, +T5](t1: T1, t2: T2, t3: T3, t4: T4, t5: T5)
      extends DataRow[T1, T2, T3, T4, T5, Any, Any, Any, Any, Any]:
    def ![S6](t6: S6) = DataRow6(t1, t2, t3, t4, t5, t6)
    def !![S6](t6: S6) = DataRow6(t1, t2, t3, t4, t5, t6)
  case class DataRow6[+T1, +T2, +T3, +T4, +T5, +T6](t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6)
      extends DataRow[T1, T2, T3, T4, T5, T6, Any, Any, Any, Any]:
    def ![S7](t7: S7) = DataRow7(t1, t2, t3, t4, t5, t6, t7)
    def !![S7](t7: S7) = DataRow7(t1, t2, t3, t4, t5, t6, t7)
  case class DataRow7[+T1, +T2, +T3, +T4, +T5, +T6, +T7](t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6, t7: T7)
      extends DataRow[T1, T2, T3, T4, T5, T6, T7, Any, Any, Any]:
    def ![S8](t8: S8) = DataRow8(t1, t2, t3, t4, t5, t6, t7, t8)
    def !![S8](t8: S8) = DataRow8(t1, t2, t3, t4, t5, t6, t7, t8)
  case class DataRow8[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8](
      t1: T1,
      t2: T2,
      t3: T3,
      t4: T4,
      t5: T5,
      t6: T6,
      t7: T7,
      t8: T8
  ) extends DataRow[T1, T2, T3, T4, T5, T6, T7, T8, Any, Any]:
    def ![S9](t9: S9) = DataRow9(t1, t2, t3, t4, t5, t6, t7, t8, t9)
    def !![S9](t9: S9) = DataRow9(t1, t2, t3, t4, t5, t6, t7, t8, t9)
  case class DataRow9[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9](
      t1: T1,
      t2: T2,
      t3: T3,
      t4: T4,
      t5: T5,
      t6: T6,
      t7: T7,
      t8: T8,
      t9: T9
  ) extends DataRow[T1, T2, T3, T4, T5, T6, T7, T8, T9, Any]:
    def ![S10](t10: S10) = DataRow10(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10)
    def !![S10](t10: S10) = DataRow10(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10)
  case class DataRow10[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10](
      t1: T1,
      t2: T2,
      t3: T3,
      t4: T4,
      t5: T5,
      t6: T6,
      t7: T7,
      t8: T8,
      t9: T9,
      t10: T10
  ) extends DataRow[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10] {}

case class DataTable(titles: Seq[String], rows: Seq[DataTableRow]):
  def isSuccess = rows.forall(_.isSuccess)
  def show = TextTable(titles, rows.map(row => row.cells.map(_.toString))).show

object DataTable:
  def apply[R: AsResult](titles: Seq[String], results: Seq[(Seq[String], R)]): DataTable =
    DataTable(titles, results.collect { case (v, r) => DataTableRow(v, AsResult(r)) })

case class DataTableRow(cells: Seq[String], result: Result):
  def isSuccess = result.isSuccess

object DataTableRow:
  def apply[R: AsResult](values: String, result: R): DataTableRow =
    DataTableRow(values.trimEnclosing("|").splitTrim("\\|"), AsResult(result))

private[specs2] object DataTables extends DataTables

object DataTablesGenerator:
  def main(args: Array[String]) =
    println(all(10))
  def all(n: Int) =
    List(tableHeader(n), tableClasses(n), dataRowClass(n), dataRowClasses(n)).mkString("\n\n").replace("\n", "\n  ")

  def tableHeader(n: Int) =
    "case class TableHeader(titles: List[String]) {\n" +
      "  def |(title: String) = copy(titles = this.titles :+ title)\n" +
      "  def ||(title: String) = copy(titles = this.titles :+ title)\n" +
      (1 to n)
        .flatMap { i =>
          val addRow = types(i) + "(row: " + dataRow(i) + ") = new " + table(i) + "(titles, List(row)"
          val addRowStill = "def |" + addRow
          val addRowExecute = "def |>" + addRow
          List(addRowStill, addRowExecute + ", execute = true").map(_ + ")")
        }
        .mkString("  ", "\n  ", "\n") +
      "}"

  def tableClasses(n: Int) =
    (1 to n)
      .map { i =>
        List(
          "case class Table" + i + types(i) + "(override val titles: List[String], rows: List[" + dataRow(
            i
          ) + "], override val execute: Boolean = false, " + s"show$i: Show$i${types(i)} = Show$i${types(i)}()" + ") extends " +
            "Table(titles, execute) { outer =>",
          "  def |" + st(i) + "(row: " + dataRow(i, letter = "S") + ")(using s" + i + ": Show" + i + types(
            i,
            letter = "S"
          ) + " = Show" + i + types(i, letter = "S") + "()) = " + table(
            i
          ) + "(titles, outer.rows :+ row, execute, s" + i + ")",
          "  def |[R : AsResult](f: " + typesTuple(i) + " => R) = executeRow(f, execute)",
          "  def |>[R : AsResult](f: " + typesTuple(i) + " => R) = executeRow(f, true)",
          "  def executeRow[R : AsResult](f: " + typesTuple(
            i
          ) + " => R, exec: Boolean): DecoratedResult[DataTable] = {",
          "    if (exec)",
          "      collect(rows map { (d: " + dataRow(i) + ") => (show" + i + ".showList(" + (1 to i)
            .map("d.t" + _)
            .mkString(",") + "), AsResult(f(" + (1 to i).map("d.t" + _).mkString(",") + ")).execute) })",
          "    else DecoratedResult(DataTable(titles, Seq[DataTableRow]()), Success(\"ok\"))",
          "  }",
          "  def |@[M[_], R](f: " + typesTuple(
            i
          ) + " => M[R])(using asResult: AsResult[R], app: Applicative[M]): M[DecoratedResult[DataTable]] =",
          "    executeRowApply(f, execute)",
          "  def |@>[M[_], R](f: " + typesTuple(
            i
          ) + " => M[R])(using asResult: AsResult[R], app: Applicative[M]): M[DecoratedResult[DataTable]] =",
          "    executeRowApply(f, true)",
          "  def |*[R](f: " + typesTuple(
            i
          ) + " => R)(using asResult: AsResult[R], ec: ExecutionContext): DecoratedResult[DataTable] = ",
          "    executeRowApply(" + parametersList(i: Int) + " => Future(f(" + (1 to i)
            .map("t" + _)
            .mkString(",") + "))(ec), execute).run",
          "  def |*>[R](f: " + typesTuple(
            i
          ) + " => R)(using asResult: AsResult[R], ec: ExecutionContext): DecoratedResult[DataTable] = ",
          "    executeRowApply(" + parametersList(i: Int) + " => Future(f(" + (1 to i)
            .map("t" + _)
            .mkString(",") + "))(ec), true).run",
          "  def executeRowApply[R, M[_]](f: " + typesTuple(
            i
          ) + " => M[R], exec: Boolean)(using asResult: AsResult[R], app: Applicative[M]): M[DecoratedResult[DataTable]] = {",
          "    if (exec)",
          "      app.map(app.traverse(rows) { (d: DataRow" + i + types(i) + ") =>",
          "        app.map(f(" + (1 to i).map("d.t" + _).mkString(",") + "))(r => (show" + i + ".showList(" + (1 to i)
            .map("d.t" + _)
            .mkString(",") + "), AsResult(r).execute))",
          "      })(rs => collect(rs))",
          "    else app.pure(DecoratedResult(DataTable(titles, Seq[DataTableRow]()), Success(\"ok\")))",
          "  }",
          "}"
        ).mkString("\n")
      }
      .mkString("\n")
  def dataRowClass(n: Int) =
    "abstract class DataRow" + variantTypes(n) + " extends Product {\n" +
      "  def show = productIterator.mkString(\"|\", \"|\", \"|\")\n" +
      "  def showCells = productIterator.map(_.notNull).toSeq\n" +
      "}"
  def dataRowClasses(n: Int) =
    (1 to n)
      .map { i =>
        List(
          "case class " + dataRowDecl(i) + parametersList(i) + " extends DataRow[" + typesList(i, n) + "] {",
          if i < n then
            "  def ![S" + (i + 1) + "](t" + (i + 1) + ": S" + (i + 1) + ") = " + "DataRow" + (i + 1) + parameters(i + 1)
          else "",
          if i < n then
            "  def !![S" + (i + 1) + "](t" + (i + 1) + ": S" + (i + 1) + ") = " + "DataRow" + (i + 1) + parameters(
              i + 1
            )
          else "",
          "}"
        ).mkString("\n")
      }
      .mkString("\n")
  def parametersList(i: Int) = (1 to i).map(j => "t" + j + ": T" + j).mkString("(", ", ", ")")
  def parameters(i: Int) = (1 to i).map("t" + _).mkString("(", ", ", ")")
  def variantTypes(i: Int, letter: String = "T") = typesAsList(i, letter).map("+" + _).mkString("[", ", ", "]")
  def st(i: Int) = (1 to i).map(j => "S" + j + " >: T" + j).mkString("[", ", ", "]")
  def types(i: Int, letter: String = "T") = typesAsList(i, letter).mkString("[", ", ", "]")
  def typesAsList(i: Int, letter: String = "T"): Seq[String] = (1 to i).map(letter + _)
  def typesList(i: Int): String = typesAsList(i).mkString(", ")
  def typesList(i: Int, n: Int): String = (List(typesList(i)) ::: (i + 1 to n).map(t => "Any").toList).mkString(", ")
  def typesTuple(i: Int) = typesAsList(i).mkString("(", ", ", ")")
  def dataRowDecl(i: Int, letter: String = "T") = "DataRow" + i + variantTypes(i, letter)
  def dataRow(i: Int, letter: String = "T") = "DataRow" + i + typesAsList(i, letter).mkString("[", ", ", "]")
  def table(i: Int) = "Table" + i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy