-
Notifications
You must be signed in to change notification settings - Fork 0
Components
Most of Salat's code is for internal use only and encapsulated away from the programmer who's using Salat in their project. There are however a few points of interest where rubber meets road, so to speak.
Aside: Please get past any class or method names in this project that don't make sense. If you'd like to propose a better name (or naming convention for other components that comprise Salat), please fork the code, make your changes, and submit a pull request.
Certain data structures required in the course of Salat's operations
must be shared between a number of disparate (de)serializers. The most
obvious shared data structure is a map of Class[_] to Grater[_]: a
cache of sorts, which is useful in the course of discovering a
Grater instance capable of handling objects of a certain case
class. Graters routinely attempt to discover each other. This is an
essential part of Salat's ability to work with arbitrarily nested
graphs of embedded objects.
An object mixing in the Context trait is where Salat expects to
store and find such shared data structures. A context is usually not
an entry point through which Salat's functionality can be accessed. It
is rather meant to be used as an implicit val which can be picked up
by Salat's actual entry points.
For example, the grater[X] function (which you get when you import
com.novus.salat._) expects to find an implicit Context in
the call site's scope. Having a context which knows about all
available Graters is useful because repeated requests for a Grater
which has already been instantiated will return the same instance.
In general, almost all parts of Salat expect to have an implicit val
of type Context somewhere in scope. This way, extensive
configuration of Salat's behavior is possible. One such customization
is the ability to turn off type hint generation at Context
level. All Graters known to this context will refrain from producing
any type hints in DBObject-s.
Salat is designed to perform only two operations for the call site, primarily because its users are expected to only want to do two things:
-
serialize instance of a case class (in other words, produce a corresponding
DBObjectinstance) -
deserialize a
DBObjectback into a properly constructed instance of some case class
Grater is designed as the only exposed part of a graph of internal
Salat objects that fully encapsulate all information necessary to
perform serialization and deserialization of objects. In order to do
anything with Salat, an instance of Grater should first be obtained.
The simplest and most common way of finding a Grater instance is by
calling the grater[X] function. For example, given a case class Widget:
import com.novus.salat._
// Provides implicit Context instance. Don't import this if you
// have defined a custom Context in one of your own imports.
import com.novus.salat.global._
case class Widget(name: String)
val g = grater[Widget]
Of course, the above only works when the concrete case class is known
at compile time. If you'd like to obtain a Grater programmatically
when only a fully-qualified name of a class is available, you can call
any of the lookup (return type Option[Grater[_]] or lookup_!
(return type Grater[_]) methods in trait Context.
Two entry points are provided for this purpose by the Grater class:
asDBObject and asObject.
As is probably obvious, you'd call asDBObject if you wanted to
serialize an object. This method takes as its input a case class
instance, and returns as its output a ready to insert into MongoDB
DBObject.
The inverse operation, deserialization, is performed by calling
asObject with a DBObject instance. Thanks to Casbah's convenient
implicit conversions (which most users of Casbah should and do
import), you shouldn't care whether you're passing in a real
DBObject or Casbah's MongoDBObject.
In case of success, the method will return an instance of the same
case class from which the DBObject was originally produced.