Skip to content
Zbyněk Šlajchrt edited this page Jun 12, 2015 · 19 revisions

1. Modelling Simple Entity

Before starting to play with the basics of Morpheus, we have to install the Morpheus Scala compiler plugin. The instructions can be found here. This plugin generates so called fragment classes for all fragments found in the project.

We can run this tutorial in REPL or as standalone programs that can be found in the tutorial repository.

This tutorial is conceived as a step-by-step development of an imaginary chat application, in which each step reveals a new Morpheus feature.

Before delving into this tutorial, however, I definitely recommend going through the README file, which gives a brief overview of the basic Morpheus concepts.

In this and all following lessons we assume that the following import statements are used.

import org.morpheus._
import Morpheus._

Let's begin with the designing of the Contact entity, which represents the central object of the chat application. Since we plan to use Contact as a fragment in morphs, we have to decorate it by the fragment annotation.

@fragment
trait Contact {
   var firstName: String = _
   var lastName: String = _
   var male: Boolean = _
   var nationality: Locale = _
}

Upon the compilation the Morpheus compiler plugin intercepts this trait and generates its fragment class, which can be then instantiated by the runtime part of Morpheus.

Now we can use the singleton macro to instantiate the Contact entity. The morph type consists of Contact type only. It actually describes the simplest morph model with just one fragment and one alternative.

The singleton macro creates the so called morph kernel, which can be used for assembling various alternatives described by the morph model. There is just one alternative in this case, so we can immediately call use either ! or ~ operators to obtain the reference to the Contact morph.

val contact = singleton[Contact].!
val contact = singleton[Contact].~

The ! operator produces something what is so called immutable morph, while ~ returns a mutable morph. The difference between is not obvious now, since there is only one alternative. When re-morphed, the immutable morph produces a new instance of the newly chosen alternative, while its internal state is not affected in any way. On the other, the mutable morph maintains a mutable reference to an immutable morph. Upon re-morphing this reference is set to the new instance of the immutable morph.

Whether we created one morph or another, both can be used as a plain Contact instance.

contact.firstName = "Pepa"
contact.lastName = "Novák"
contact.male = true
contact.nationality = Locale.CANADA

println(s"${contact.firstName} ${contact.lastName} ${contact.nationality} ${contact.male}")

Note: We used the mutable version of the Contact entity just because of its sheer simplicity and since the immutable version would require more Morpheus stuff to be explained. We will switch to the immutable entity later on.

In the following lesson we will add some behavior to entity Contact.