Introduction
I’m a coasters collector. I’m not a huge collector but I want to inventory them in one place. For sure, I can create a PostgreSQL database. But, at the same time, it appears that I can also design my collection using Moose.
So, you’re going to use a complete system analysis software to manage your coasters collection?
Exactly! And why? Because I think it’s simpler.
Design
As for every software system, the first step is to design the model. In my case, I want to represent a collection of coasters. Let’s say a coaster is an entity. It can belong to a brewery or not (for example event coasters). A coaster also has a form. It can be round, squared, oval, or others. A Coaster can also be specific to a country. Because it is a collection, I can register coaster I own and other I do not. Finally, each coaster can have an associated image.
From this description of the problem, I designed my UML schema:
The most complicated part is done. We just need to implement the meta-model in Moose now .
Implementation
First of all, we’ll need a Moose 8 image. You can find everything you need to install Moose in the moose-wiki.
Configuration
Ok! Let’s create a generator that will generate for us the meta-model. We only need to describe the meta-model in the generator. We will name this generator CoasterCollectorMetamodelGenerator.
FamixMetamodelGenerator subclass: #CoasterCollectorMetamodelGenerator
slots: { }
classVariables: { }
package: 'CoasterCollector-Model-Generator'
The generator needs to define two methods class side for the configuration:
-
#packageName
defines where the meta-model will be generated -
#prefix
defines the prefix of each class when they are generated.
We used for #packageName
:
CoasterCollectorMetamodelGenerator class >>#packageName
^ #'CoasterCollector-Model'
We used for #prefix
:
CoasterCollectorMetamodelGenerator class >>#prefix
^ #'CC'
Now, we have to define the entities, their properties, and their relations.
Define entities
A meta-model is composed of entities.
In our case, it corresponds to the entities identified in the UML.
We use the method #defineClasses
to define the entities of our meta-model.
CoasterCollectorMetamodelGenerator>>#defineClasses
super defineClasses.
coaster := builder newClassNamed: #Coaster.
country := builder newClassNamed: #Country.
shape := builder newClassNamed: #Shape.
round := builder newClassNamed: #Round.
square := builder newClassNamed: #Square.
oval := builder newClassNamed: #Oval.
creator := builder newClassNamed: #Creator.
brewery := builder newClassNamed: #Brewery
We also need to define the hierarchy of those entities:
CoasterCollectorMetamodelGenerator>>#defineHierarchy
super defineHierarchy.
brewery --|> creator.
oval --|> shape.
square --|> shape.
round --|> shape
Define properties
As we have defined the classes, we defined the properties of the entities using the #defineProperties
method.
defineProperties
super defineProperties.
creator property: #name type: #String.
country property: #name type: #String.
coaster property: #image type: #String.
coaster property: #owned type: #Boolean
In this example, we did not use Trait already created in Moose.
However, it is possible to use the Trait TNamedEntity
to define that countries and creators have a name instead of using properties.
Define relations
Finally, we defined the relations between our entities:
defineRelations
super defineRelations.
(coaster property: #shape) *- (shape property: #coasters).
(coaster property: #country) *- (country property: #coasters).
(coaster property: #creator) *- (creator property: #coasters)
Generate
Once everything is defined, we only need to use the generator to build our meta-model.
CoasterCollectorMetamodelGenerator generate
The generation creates a new package with our entities.
It also generates a class named Model
used to create an instance of our meta-model.
Create my collection
I have created my meta-model.
Now I need to fill my collection.
First of all, I will create a collection of coasters.
To do so, I instantiate a model with: model := CCModel new
.
And now I can add the entities of my real collection in my model and I can explore it in Moose.
For example, to add a new brewery I execute: model add: (CCBrewery new name: 'Badetitou'; yourself)
.
The code is available on github.
Save the collection
Once I have created the collection, I can save it using the Moose export format (currently JSON and mse). To do so, I execute the following snippet:
'/my/collection/model.json' asFileReference ensureCreateFile
writeStreamDo: [ :stream | model exportToJSONStream: stream ]
Then I can select where I want to export my model.
To import it back into an image, I use the following code
'/my/collection/model.json' asFileReference
readStreamDo: [ :stream | model := CCModel importFromJSONStream: stream ]