-
Notifications
You must be signed in to change notification settings - Fork 1
Containers
The data management of a core3 application is based around two main concepts: database abstraction layers and containers. In addition to that, there are views which can be used to further process and group data coming from the databases.
Note: Implicit parameters have been removed for brevity.
All core containers can be found here.
Containers represent data going in and out of the data layer and, usually, each one maps to a distinct entity in one or more DBs (for example, table row in MariaDB or a document in CouchDB). Each container has at least an id and a containerType, used for identifying an object across all DBs.
//Base container trait
trait Container {
val id: ObjectID
val objectType: ContainerType
}Useful for storing data that does not change, such as logs or data snapshots.
trait ImmutableContainer extends ContainerUsed for everything else and has the following additional pieces of information:
-
created- Data and time of the object's creation -
updated- Date and time of the object's last update -
updatedBy- ID of the user that performed the last update -
revision- Unique ID used for ensuring data integrity -
revisionNumber- Sequential ID used for ensuring data integrity and tracking the number of changes to an object
trait MutableContainer extends Container {
val created: Timestamp
var updated: Timestamp
var updatedBy: String
var revision: RevisionID
var revisionNumber: RevisionSequenceNumber
}A container class' companion object is used for converting the container to and from the format a DB expects.
Defines the basic methods required from all companion objects:
trait BasicContainerCompanion {
def getDatabaseName(dataType: DataType): String
def matchCustomQuery(queryName: String, queryParams: Map[String, String], container: Container): Boolean
}Defines the methods required to convert a container object to/from JSON:
trait JSONContainerCompanion extends BasicContainerCompanion {
def toJsonData(container: Container, format: JsonDataFormat): JsValue
def fromJsonData(data: JsValue): Container
}Defines the methods required to convert containers to/from SQL DBs:
trait SlickContainerCompanion extends BasicContainerCompanion {
def runCreateSchema(db: DatabaseDef): Future[Boolean]
def runDropSchema(db: DatabaseDef): Future[Boolean]
def runGenericQuery(query: SQLActionBuilder, db: DatabaseDef): Future[Vector[Container]]
def runGet(objectID: ObjectID, db: DatabaseDef): Future[Container]
def runCreate(container: Container, db: DatabaseDef): Future[Boolean]
def runUpdate(container: MutableContainer, db: DatabaseDef): Future[Boolean]
def runDelete(objectID: ObjectID, db: DatabaseDef): Future[Boolean]
def runCustomQuery(queryName: String, queryParams: Map[String, String], db: DatabaseDef): Future[Vector[Container]]
}
trait SlickContainerCompanionImpl[ContainerTupleDef] extends SlickContainerCompanion {
protected def convertToTuple(container: Container): ContainerTupleDef
protected def convertFromTuple(tuple: ContainerTupleDef): Container
}Note:
SlickContainerCompanionImplis the trait to be extended by container companions.SlickContainerCompanionis used by the DALs.
Defines the methods required to convert a container to a searchable entity:
trait SearchContainerCompanion extends JSONContainerCompanion {
def getSearchFields: Map[String, String]
}Note: Normally, a container cannot be reconstructed from search data.
-
Group- Allows grouping of other containers -
LocalUser- Basic user container; used for local authentication -
TransactionLog- Used for storing data about the operations the workflow engine is performing
-
Decide on whether the container is going to be mutable or not
-
Extend the appropriate trait (
MutableContainerorImmutableContainer) and define all container fields
import core3.database
import core3.database.containers._
import core3.database._
import core3.utils.Time._
import core3.utils._
import play.api.libs.json._
import slick.jdbc.MySQLProfile.api._
import slick.jdbc.MySQLProfile.backend.DatabaseDef
import slick.jdbc.SQLActionBuilder
import scala.concurrent.{ExecutionContext, Future}
case class Group(
shortName: String,
var name: String,
var items: Vector[ObjectID],
itemsType: ContainerType,
created: Timestamp,
var updated: Timestamp,
var updatedBy: String,
id: ObjectID,
var revision: RevisionID,
var revisionNumber: RevisionSequenceNumber
)
extends MutableContainer {
override val objectType: ContainerType = "Group"
//... additional methods and/or constructors ...
}- Decide on the container's target DBs and extend the appropriate companion traits:
import core3.database
import core3.database.containers._
import core3.database._
import core3.utils.Time._
import core3.utils._
import play.api.libs.json._
import slick.jdbc.MySQLProfile.api._
import slick.jdbc.MySQLProfile.backend.DatabaseDef
import slick.jdbc.SQLActionBuilder
import scala.concurrent.{ExecutionContext, Future}
object Group
extends JSONContainerCompanion //adds support for JSON-based DBs
with SlickContainerCompanionImpl[( //adds support for SQL DBs
//Slick table row / tuple definition
String, String, String, String, String, java.sql.Timestamp, java.sql.Timestamp, String, String, Int
)] {
private type ContainerTupleDef = (
//Slick table row / tuple definition
String, String, String, String, String, java.sql.Timestamp, java.sql.Timestamp, String, String, Int
)
//... trait method implementation ...
}- Done
Home | Getting Started | Structure | Containers | Workflows | Controllers
