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

scroll.internal.support.impl.Relationships.scala Maven / Gradle / Ivy

package scroll.internal.support.impl

import scroll.internal.support.RelationshipsApi
import scroll.internal.support.RoleQueriesApi

import scala.reflect.ClassTag

class Relationships(private val roleQueries: RoleQueriesApi) extends RelationshipsApi {

  import scroll.internal.support.impl.Multiplicities._

  class ToBuilder[L <: AnyRef: ClassTag](name: String, leftMul: Multiplicity) extends ToBuilderApi[L] {

    override def to[R <: AnyRef: ClassTag](rightMul: Multiplicity): RelationshipApi[L, R] =
      new Relationship[L, R](name, leftMul, rightMul)

  }

  class FromBuilder(name: String) extends FromBuilderApi {

    override def from[L <: AnyRef: ClassTag](leftMul: Multiplicity): ToBuilder[L] =
      new ToBuilder[L](name, leftMul)

  }

  /** Creates a [[Relationships.Relationship]] with the given name with a fluent relationship creation API.
    *
    * @param name
    *   the name of the created Relationship
    * @return
    *   an instance of the Relationship builder
    */
  override def create(name: String): FromBuilder = new FromBuilder(name)

  /** Class representation of a relationship between two (role) types.
    *
    * @param name
    *   name of the relationship
    * @param leftMul
    *   multiplicity of the left side of the relationship
    * @param rightMul
    *   multiplicity of the right side of the relationship
    * @tparam L
    *   type of the role of the left side of the relationship
    * @tparam R
    *   type of the role of the right side of the relationship
    */
  class Relationship[L <: AnyRef: ClassTag, R <: AnyRef: ClassTag](
    name: String,
    leftMul: Multiplicity,
    rightMul: Multiplicity
  ) extends RelationshipApi[L, R] {

    protected val MULT_NOT_ALLOWED: String = "This multiplicity is not allowed!"

    private def checkMul[T](m: Multiplicity, on: Seq[T]): Seq[T] = {
      m match {
        case MMany() =>
          assert(on.nonEmpty, s"With left multiplicity for '$name' of '*', the resulting role set should not be empty!")
        case ConcreteValue(v) =>
          assert(
            v.compare(on.size) == 0,
            s"With a concrete multiplicity for '$name' of '$v' the resulting role set should have the same size!"
          )
        case RangeMultiplicity(f, t) =>
          (f, t) match {
            case (ConcreteValue(v1), ConcreteValue(v2)) =>
              assert(
                v1 <= on.size && v2 >= on.size,
                s"With a multiplicity for '$name' from '$v1' to '$v2', the resulting role set size should be in between!"
              )
            case (ConcreteValue(v), MMany()) =>
              assert(
                v <= on.size,
                s"With a multiplicity for '$name' from '$v' to '*', the resulting role set size should be in between!"
              )
            case _ =>
              throw new RuntimeException(MULT_NOT_ALLOWED) // default case
          }
      }
      on
    }

    override def left(matcher: L => Boolean = _ => true): Seq[L] =
      checkMul(leftMul, roleQueries.all[L](matcher))

    override def right(matcher: R => Boolean = _ => true): Seq[R] =
      checkMul(rightMul, roleQueries.all[R](matcher))

  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy