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

scroll.internal.compartment.impl.Compartment.scala Maven / Gradle / Ivy

package scroll.internal.compartment.impl

import scroll.internal.dispatch.DispatchQuery
import scroll.internal.dispatch.SCROLLDynamic
import scroll.internal.errors.SCROLLErrors.RoleNotFound
import scroll.internal.errors.SCROLLErrors.SCROLLError
import scroll.internal.util.ReflectiveHelper

import java.lang.reflect.Method
import scala.reflect.ClassTag

/** This Trait allows for implementing an objectified collaboration with a limited number of participating roles and a
  * fixed scope.
  *
  * ==Overview==
  * Roles are dependent on some sort of context. We call them compartments. A typical example of a compartment is a
  * university, which contains the roles Student and Teacher collaborating in Courses. Everything in SCROLL happens
  * inside of Compartments but roles (implemented as standard Scala classes) can be defined or imported from everywhere.
  * Just mix in this Trait into your own specific compartment class or create an anonymous instance.
  *
  * ==Example==
  * {{{
  * val player = new Player()
  * new Compartment {
  *   class RoleA
  *   class RoleB
  *
  *   player play new RoleA()
  *   player play new RoleB()
  *
  *   // call some behaviour
  * }
  * }}}
  */
trait Compartment extends AbstractCompartment {

  override def newPlayer[W <: AnyRef: ClassTag](obj: W): Player[W] = {
    require(null != obj)
    new Player(obj)
  }

  implicit class Player[W <: AnyRef: ClassTag](override val wrapped: W)
      extends IPlayer[W, Player[W]](wrapped)
        with SCROLLDynamic {

    override def applyDynamicNamed[E](name: String)(args: (String, Any)*)(using
      dispatchQuery: DispatchQuery = DispatchQuery()
    ): Either[SCROLLError, E] = applyDynamic[E](name)(args.map(_._2)*)(using dispatchQuery)

    override def applyDynamic[E](
      name: String
    )(args: Any*)(using dispatchQuery: DispatchQuery = DispatchQuery()): Either[SCROLLError, E] =
      applyDispatchQuery(dispatchQuery, wrapped).view
        .map { (r: AnyRef) =>
          (r, ReflectiveHelper.findMethod(r, name, args.toSeq))
        }
        .collectFirst { case (r: AnyRef, Some(m: Method)) =>
          dispatch[E](r, m, args.toSeq)
        }
        .getOrElse(Left(RoleNotFound(wrapped, name, args.toSeq)))

    override def selectDynamic[E](
      name: String
    )(using dispatchQuery: DispatchQuery = DispatchQuery()): Either[SCROLLError, E] =
      applyDispatchQuery(dispatchQuery, wrapped).view
        .collectFirst {
          case r: AnyRef if ReflectiveHelper.hasMember(r, name) =>
            Right(ReflectiveHelper.propertyOf[E](r, name))
        }
        .getOrElse(Left(RoleNotFound(wrapped, name, Seq.empty[Any])))

    override def updateDynamic(name: String)(value: Any)(using dispatchQuery: DispatchQuery = DispatchQuery()): Unit =
      applyDispatchQuery(dispatchQuery, wrapped).view
        .find(ReflectiveHelper.hasMember(_, name))
        .foreach(ReflectiveHelper.setPropertyOf(_, name, value))

    def hashCode()(using dispatchQuery: DispatchQuery = DispatchQuery()): Int =
      applyDynamic("hashCode")()(using dispatchQuery)

    def toString()(using dispatchQuery: DispatchQuery = DispatchQuery()): String =
      applyDynamic("toString")()(using dispatchQuery)

  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy