Data model support
To make Circumflex components independent from various view technologies we introduce some basic interfaces here. Different components implement these interfaces while view technologies should provide proper support for them.
|
trait Wrapper[T] {
def item: T
}
|
Containers
Containers are generic data-carrier units. They wrap mutable variable with common functionality like setters, accessors, mutators and metadata. ValueHolder of Circumflex ORM uses container functionality, see its docs for more information.
By convention containers should be tested for equality by their external attributes (like name, identifier, etc.), *but not their internal value*. Implementations should provide sensible canEqual , equal and hashCode methods, but internal value should not be taken into consideration.
|
trait Container[T] extends Equals {
protected var _value: Option[T] = None
|
Setters
Setters provide a handy mechanism for preprocessing values before setting them. They are functions T => T which are applied one-by-one each time you set new non-null value.
|
protected var _setters: Seq[T => T] = Nil
def setters: Seq[T => T] = _setters
def addSetter(f: T => T): this.type = {
_setters ++= List(f)
return this
}
|
Accessing & Setting Values
Values are stored internally as Option[T] . None stands both for uninitialized and null values.
|
def value: Option[T] = _value
def get = value
def apply(): T = value.get
def getOrElse(default: T): T = value.getOrElse(default)
def null_?(): Boolean = value == None
def set(v: Option[T]): this.type = {
_value = v.map { v =>
setters.foldLeft(v) { (v, f) => f(v) }
}
return this
}
def set(v: T): this.type = set(any2option(v))
def setNull: this.type = set(None)
def :=(v: T): Unit = set(v)
|
Methods from Option
Since ValueHolder is just a wrapper around Option , we provide some methods to work with your values in functional style (they delegate to their equivalents in Option ).
|
def map[B](f: T => B): Option[B] =
value.map(f)
def flatMap[B](f: T => Option[B]): Option[B] =
value.flatMap(f)
def orElse[B >: T](alternative: => Option[B]): Option[B] =
value.orElse(alternative)
}
|