scala domain modeling and architecture
DESCRIPTION
TRANSCRIPT
Scala Domain Modeling and Architecture Experience Report
Hossam Karim
for {! ! locus ← Chromosome ⤞ Gene ⤞ Locus! if Locus ∈ range! ! path ← locus ⤞ Sequence ⤞ nucleotide! if nucleotide alignment (_ > 89)! ! } yield path!
inputMessage >>= fasta >>= { case n: Nucleotide ⇒ ! ("media" → "nucleotide") ~> n.giNumber case _: AminoAcid ⇒ ! fail[String](! "Expected a ‘nucleotide’ Sequence") case _ ⇒ ! fail[String](! "Expected a ‘single’ Sequence representation”) } >>= { for { query ← meta.Sequence ⤞ meta.nucleotide if meta.nucleotide.giNumber === _ } yield query } >>= xml !
inputMessage >>= fasta >>= { case n: Nucleotide ⇒ ! ("media" → "nucleotide") ~> n.giNumber case _: AminoAcid ⇒ ! fail[String](! "Expected a ‘nucleotide’ Sequence") case _ ⇒ ! fail[String](! "Expected a ‘single’ Sequence representation”) } >>= { for { query ← meta.Sequence ⤞ meta.nucleotide if meta.nucleotide.giNumber === _ } yield query } >>= xml !
inputMessage >>= fasta >>= { case n: Nucleotide ⇒ ! ("media" → "nucleotide") ~> n.giNumber case _: AminoAcid ⇒ ! fail[String](! "Expected a ‘nucleotide’ Sequence") case _ ⇒ ! fail[String](! "Expected a ‘single’ Sequence representation”) } >>= { for { query ← meta.Sequence ⤞ meta.nucleotide if meta.nucleotide.giNumber === _ } yield query } >>= xml !
inputMessage >>= fasta >>= { case n: Nucleotide ⇒ ! ("media" → "nucleotide") ~> n.giNumber case _: AminoAcid ⇒ ! fail[String](! "Expected a ‘nucleotide’ Sequence") case _ ⇒ ! fail[String](! "Expected a ‘single’ Sequence representation”) } >>= { for { query ← meta.Sequence ⤞ meta.nucleotide if meta.nucleotide.giNumber === _ } yield query } >>= xml !
inputMessage >>= fasta >>= { case n: Nucleotide ⇒ ! ("media" → "nucleotide") ~> n.giNumber case _: AminoAcid ⇒ ! fail[String](! "Expected a ‘nucleotide’ Sequence") case _ ⇒ ! fail[String](! "Expected a ‘single’ Sequence representation”) } >>= { for { query ← meta.Sequence ⤞ meta.nucleotide if meta.nucleotide.giNumber === _ } yield query } >>= xml !
trait Message[A, H] { val body: Validation[H, Option[A]] val headers: H } trait MessageBuilder { def build[A, H: Monoid]( body: Validation[H, Option[A]], headers: H): Message[A, H] }
trait Message[A, H] { val body: Validation[H, Option[A]] val headers: H } trait MessageBuilder { def build[A, H: Monoid]( body: Validation[H, Option[A]], headers: H): Message[A, H] }
implicit def m2m[H]! (implicit builder: MessageBuilder, ! monoid: Monoid[H]) =! new Monad[({type λ[α] = Message[α, H]})#λ] { def pure[A](a: => A): Message[A, H] = . . .! def bind[A, B]! (a: Message[A, H], ! f: (A) => Message[B, H]): Message[B, H] = . . . }
def pure[A](a: => A) = ! builder.build[A, H](Success(Option(a)), ∅[H])
def bind[A, B](! m: Message[A, H], ! f: (A) => Message[B, H]): Message[B, H] = {! val mb: Message[B, H] = m.body match { case Success(Some(value)) ⇒ f(value) case Success(None) ⇒! builder.build[B, H](! Success(Option.empty[B]), ∅[H]) case Failure(a) ⇒! builder.build[B, H](! Failure(a), ∅[H] |+| a) }! builder.build[B, H](mb.body, m.headers |+| mb.headers) }
implicit object BasicMessageBuilder extends MessageBuilder { def build[A, H: Monoid](! body: Validation[H, Option[A]], headers: H) = BasicMessage(body, headers) } !implicit object DiagnosisMessageBuilder extends! MessageBuilder { def build[A, H: Monoid](! body: Validation[H, Option[A]], headers: H) = DiagnosisMessage(body, headers) } def body[A](value: A)(implicit builder: MessageBuilder) :! Message[A, HL] = builder.build(Success(Some(value)), List.empty[Header])
import Basic._!//import Diagnosis._!//import Transactional._!!gene map { for (! e ← meta.Chromosome ⤞ meta.Gene ! if meta.Gene.uuid === _.uuid! ) yield e } >>= search
(genex <**> geney) (_ ++ _) >>= header("media-type", "application/vnd.x.gene+json") >>= json for { m ← body(<gene xmlns="urn:model:gene:1.0">...</gene>) gene ← xml(m) } yield gene gene map { for { e ← meta.Gene ⤞ meta.Gene.uuid if meta.Gene.uuid === _.uuid } yield e } >>= search
import scalaz._!import Scalaz._!// profit!!
trait Resource {! val name: String!} ! trait Ontology extends Resource {! val nestingOntology: Option[Ontology]! val nestedOntology: List[Ontology]! val ownedType: List[Type]! val ownedRelation: List[Relation]!}!
trait GraphResource { this: Resource => } trait GraphVertex extends GraphResource { this: Entity => val graphFeatures: List[PrimitiveFeature] val master: Boolean val rootToMasterEdge: GraphEdge with Relation val masterToSelf: Option[GraphEdge with Relation] = None } trait GraphEdge extends GraphResource { this: Relation => }
trait RelationalResource { this: Resource => } trait NamedRelationalResource extends RelationalResource { this: Resource => val relationalName: String } trait RelationalEntity extends NamedRelationalResource { this: Entity => } trait RelationalCompositeFeature extends RelationalResource { this: CompositeFeature => val mapping: Map[String, String] }
object Chromosome extends Entity with RelationalEntity! with GraphVertex with XmlElement { self => sealed trait ChromosomePart { val ownerType = self } // Ontology Trait val featuringType = self val ownedFeature = chromatine :: Nil // XML Trait val namespace = "urn:domain:chromosome:1.0" val prefix = "chr" // Features val chromatine = new Chromatine( name = "chromatine", ownerType = Chromosome, mapping = Map.empty[String, String]) }
implicit def enrich[A <: DomainModel](model: A) = new { def metamodel: Option[Type] = Ontology.typeOf(model) } def xmlFilter[A <: DomainModel] = (model: A) ⇒ model.metamodel match { case Some(_: XmlElement) ⇒ body(XmlModel[A](model)) case _ ⇒ fail[XmlModel[A]]! ("No XmlElement meta-model definition could be found") } def ingoingEdges[A <: DomainModel] = (model: A) ⇒ model.metamodel match { case Some(vertex: GraphVertex) ⇒ ! Ontology.edges.filter(_.target == vertex) case _ ⇒ List.empty[GraphEdge] }
implicit def enrich[A <: DomainModel](model: A) = new { def metamodel: Option[Type] = Ontology.typeOf(model) } def xmlFilter[A <: DomainModel] = (model: A) ⇒ model.metamodel match { case Some(_: XmlElement) ⇒ body(XmlModel[A](model)) case _ ⇒ fail[XmlModel[A]]! ("No XmlElement meta-model definition could be found") } def ingoingEdges[A <: DomainModel] = (model: A) ⇒ model.metamodel match { case Some(vertex: GraphVertex) ⇒ ! Ontology.edges.filter(_.target == vertex) case _ ⇒ List.empty[GraphEdge] }
trait Type extends Resource trait SimpleType extends Type trait Entity extends Type!! trait Relation extends Type trait Feature[+T <: Type] extends Resource trait SimpleFeature[+T <: SimpleType] extends Feature[T] trait PrimitiveFeature extends SimpleFeature[Primitive] trait EnumerationFeature extends SimpleFeature[Enumeration] trait CompositeFeature extends SimpleFeature[Composite] trait Primitive extends SimpleType trait Enumeration extends SimpleType trait Composite extends SimpleType
trait PrimitiveLogic { val resource: Primitive def ===[A](value: Primitive[A]): Operator = . . . def in[A](values: PrimitiveList[A]): Operator = . . . } def find(operator: Operator): Option[T] def list(operator: Operator): List[T]!
import PrimitiveLogic._ dao list (Locus.locusUUID in list) dao find (Locus.locusUUID === uuid)
import Logic._ val validation = Sequence.nucleotide.accession.accessionNumber !== x import GraphOps._ val path = Sequence.nucleotide ⤞ Sequence.protein ⤞ Locus.typeOfGene where (_ !== y)
for {! ! locus ← Chromosome ⤞ Gene ⤞ Locus! if Locus ∈ range! ! path ← locus ⤞ Sequence ⤞ nucleotide! if nucleotide alignment (_ > 89)! ! } yield path!
trait Qvt[PIM, Query, View, PSM] { def query(pim: PIM): List[Query] def view(query: Query): View def transform(view: View): PSM }
class GraphSimpleQvt( ontologyProfile: OntologyProfile, graphProfile: GraphProfile) extends SimpleQvt[Model, Package, GraphOntology] { def query(pim: Model) = { walk[Package](pim)(_.getNestedPackages). filter(graphProfile.graphPredicate) } def transform(view: Package) = graph(view) def graph(element: Package): GraphOntology = { ... } . . . }
def walk[A] (element: A) (f: A => Iterable[A]): List[A] = { val children = f(element).toList children ++ ! (children.flatMap(walk(_, f))) }
def packageName(element: Package): String = Stream! .iterate(element)(_.getNestingPackage) .takeWhile(!_.isInstanceOf[Model]) .map(_.getName) .reverse .mkString(".") //.scala rocks !!
Thank You