Papyrus
Papyrus is an open-source UML tool based on Eclipse. It's a multipurpose software allowing us to:
- 🤔 Design UML 2 diagrams
- 🏭 Generate code from diagrams
- 🛣️ Simulate your diagrams
- 👀 Connect diagrams and write meta-models
- ...
To install Papyrus, you need to install Java first. If you have problems when starting Papyrus, check out this video.
Once the software is started, create a new papyrus model. A model is made of 3 files: xxx.di
, xxx.notation
, and xxx.uml
.
⚠️ Their software may be buggy at times and crash. Make sure to often save your diagrams and keep copies of your work.
Core concepts
Model
All diagrams are parts of a model. It allows us to connect diagrams and reuse what we defined in other diagrams between diagrams.
If you change the model, it will be changed everywhere.
View and model
The Model explorer is the only thing you can trust.
The view may change and the model may not. It may occur if you try to rename something and the new name is invalid.
Perspectives
Perspectives allow you to view your model from different perspectives. Ensure that you are using the Papyrus perspective when you are creating models.
and select
If you use a perspective at least once, a shortcut will be available right next to the perspective menu. See also: "Window > Perspective".
Papyrus Interface
-
Project explorer 📂: Double-click on a model to open it
- Export your diagrams (right-click on model -> export)
- Open your project in the file explorer (right-click on the folder "example" and "show in")
- Model explorer 🍀: Once you open a model, add diagrams to it from this menu: Right-click on "example" > "New diagram".
- Model editor 🎥: edit your diagram here. You can move things from the palette (4) to here.
- Palette 🎨: every element that you can put inside the kind of diagram you opened.
-
Property view 🔐: Edit the properties of what you selected
- ex: give another name to a class
- ex: give a type to an attribute
- ex: write some documentation
- etc.
-
Outline view 🌍: you can move faster in the model editor view using the Outline tab.
- You can use it to view your diagram from afar
- You can change the outline view (by clicking on the tree-like icon) to see your model as a tree
Tips and recommendations
Don't scroll in the property view
You can scroll to change the values of a field (such as checked -> uncheck, or the type of your attribute, etc.) when you are in the Property view.
Unfortunately, you can't control it: you might change something or cancel everything you did by mistake ⚠️.
Modified file symbol
It's common, but there is a little star before every edited filename.
Icons for Palette
The palette has quite a lot of elements. It's faster and easier to change the palette view to a list of icons (Right-click to change the view).
Dark Mode
Navigate to Window > Preferences
and set your settings.
Fast creation of items
From the palette, you can double-click on something to create a new element, there is no need to drag-and-drop it.
Align items
It's kind of useless, but to create nicer diagrams, you may use "align" to cleanly arrange items in a diagram.
Either by using this icon or CTRL+{some arrow}, after selecting elements, you can align every class based on the position of the last selected class. You can use "distribute" too.
Class diagrams in Papyrus
Associations
When selecting an association, directed associations are created by default. After using an undirected association, it will use these.
After creating an association, in the Property view you can add a direction, set the multiplicity, transform it into a composition or aggregation, etc. rather easily.
Wait a bit while your mouse is on top of a class, and a shortcut to create associations will pop up:
Interfaces
As a reminder:
- ➡️ If a class implements/realizes an interface, then the head of the arrow is on the interface.
- ➡️ If a class extends/generalizes another class, then the head of the arrow is on the other class.
Layout/Appearance
You can right-click on a class:
- Reformat: reformat what you selected
- Filter: show/hide attributes/operations/...
- You can also give colors to classes
- ...
Types
When clicking on an attribute, there is a field "Type" inside the Property View. Click on "... > Tree > EPackage Primitive Types" and select your type.
Notes
- "Boolean [1]" after the type means that the cardinality is 1 (=this is a value, more than 1 means this is an array/a list/a queue/...)
- You could drag and drop a class inside the field, instead of picking a primitive type.
- If you need to create a new type, use either
DataType
(cannot be instanced) orPrimitive type
or a class if none are what you want
External Types
In Java, you may use classes such as java.util.Arrays
in your diagrams. ⚠️ It's complicated to do it properly.
Initial Configuration
- Navigate to the model explorer and click on the root
- Go to Profile > Profile Applications
- Next to "+" and "x", click on "apply registered profile"
- Add "Papyrus Code Generation Profile"
- Add "Papyrus Java Profile"
- Next to "+" and "x", click on "apply registered profile"
- Add a new package (new child) "ExternalTypes". Click on it, then Profile, then Applied Stereotypes, and add NoCodeGen.
- Create a stereotype (Profile > +) "External".
- Create a new class diagram called "Dependencies".
Step per dependency
- Add your classname if the "External" Stereotype
- Add your class to the diagram along with the external class
- Create a usage relationship to request an import (A to B means A imports B).
Code Generation
Install dependencies
You need papyrus.designer, Xtend IDE, and acceleo.
papyrus.designer
- Help > Install New Software
- Enter
https://ci.eclipse.org/papyrus/job/papyrus-designer-2020-06/lastSuccessfulBuild/artifact/releng/org.eclipse.papyrus.designer.p2/target/repository/
and press enter - Select the first
Papyrus base elements for code generation
- Select the first
Papyrus Java profile ...
- Next (wait)
- Next
- "I accept" and Finish (wait, check the bottom right of papyrus)
- Restart (when prompted)
You'll then have to download a plugin for code generation:
Xtend IDE 🍬
- Help > Install New Software
- Enter
https://download.eclipse.org/modeling/tmf/xtext/updates/composite/latest/
and press enter - Select Xtend IDE inside XText
- Next (wait)
- Next
- "I accept" and Finish (wait, check the bottom right of papyrus)
- Restart (when prompted)
Acceleo 🍫
Acceleo only generates code from class diagrams.
- Help > Install New Software
- Enter
https://download.eclipse.org/acceleo/updates/releases/3.7/R201911060712
and press enter - Select Acceleo in Acceleo
- Next (wait)
- Next
- "I accept" and Finish (wait, check the bottom right of papyrus)
- Restart (when prompted)
Improve the generation
Acceleo improvements
Get started by opening the file: /org.eclipse.acceleo.examples.uml2java/
> src > /org/eclipse/acceleo/examples/uml2java/main/uml2java.mtl
.
You may also have to edit org.eclipse.acceleo.module.sample
> src > org/eclipse/acceleo/module/sample/
.
Code samples
[for (p : Package | aModel.nestedPackage->sortedBy(name))]
[comment DONE then display Package's name/]
Package [p.name/]
[comment DONE and indent classes and interfaces names/]
[for (c : Class | p.packagedElement->filter(Class)->sortedBy(name))]
[generateClassElement(c)/]
[/for]
[for (i : Interface | p.packagedElement->filter(Interface)->sortedBy(name))]
[generateInterfaceElement(i)/]
[/for]
[/for]
For file: common/fileUtils.mtl
.
[**
* Generates the type in Java given an OCL type
* @param aType The OCL Type
*/]
[template public genType(aType : String)]
[if (aType.toUpperFirst() = 'Real')]Float[else][aType.toUpperFirst()/][/if]
[/template]
You then need to use your newly created function everywhere:
- use
genType(aProperty.type.name)
- instead of
aProperty.type.name
- or instead of
aProperty.type.name.toUpperFirst()
- instead of
- of course, sometimes the variable isn't called aProperty
The locations are
- classJavaFile: fields (1), operations (1), parameters (1), accessors (2)
- interfaceJavaFile: genInterfaceJavaFile (1), parameters (1)
Support NoCodeGen
The NoCodeGen attribute is ignored during code generation. In ClassUtils.java
, requiredClassifiers
, before the return:
// import
// import org.eclipse.papyrus.designer.languages.common.profile.Codegen.NoCodeGen;
EList<Classifier> usedClassesReturn = new UniqueEList<Classifier>();
for(Classifier c : usedClasses) {
if (!GenUtils.hasStereotypeTree(c, NoCodeGen.class)) {
usedClassesReturn.add(c);
}
}
Edit noCodeGen in JavaModelElementsCreator.
- GenUtils.hasStereotypeTree(element, ExternLibrary.class) ||
+ GenUtils.hasStereotypeTree(element, ExternLibrary.class) &&
+ GenUtils.hasStereotypeTree(element, NoCodeGen.class);
Support Code Generation From The Diagram
Inside a diagram, add the implementation
- Right-click on a class
- New Child > Opaque Behavior > Owned ...
- Name it (ex:
getXXX
) - Language > + > Java
- Write some code
// todo
return false;
- Click on a method (ex:
getXXX
) - In UML, look for the field Method
- Add your Opaque Behavior
Default implementation in the generator
You must change the return type so that it is always a class (ex float
is now Float
). The default behavior will be to return null, but only if this is not a constructor nor a method returning void.
In JavaOperations.xtend, in javaReturnSpec
- JavaGenUtils.javaQualifiedName(operation.type, operation.owner) + ' '
+ JavaGenUtils.javaQualifiedName(operation.type, operation.owner).toFirstUpper() + ' '
And in javaOperationDeclaration
- «IF mustGenerateBody(operation)»«JavaOperations.javaOperationImplementation(operation)»«ENDIF»
+ «IF mustGenerateBody(operation)»«JavaOperations.javaOperationImplementation(operation)»
+ «IF javaReturnSpec(operation) != 'void ' && !isConstructor(operation)»return null;«ENDIF»«ENDIF»
Acceleo: improve import support
An easy way to do this is to hard code the import, by adding some lines in genDefaultImport inside common/fileUtils.mtl
[template public genDefaultImport(aType : Type)]
// [protected ('for imports')]
import java.util.*;
// [/protected]
[/template]
The problem with this is that it doesn't work for your classes as they are not within a package.
In fileUtils, edit these two functions with
[template private packagePath(aType : Type)]
- [ /* something */ /]
+ ['/' + aType.getSourcePackage() + '/' + /* something */ /]
[/template]
[template public genPackageValue(aType : Type)]
- [ /* something */ /]
+ [aType.getSourcePackage() + '.' + /* something */ /]
[/template]
And create the template getSourcePackage
[template public getSourcePackage(aType : Type)]
[aType.getModel().name/]
[/template]
Handle Duplicate Methods
Obviously, this is a problem in your model, but you can edit classJavaFile, template operations
- [for (anOperation : Operation | aClass.getOperations()->union(aClass.getImplementedInterfaces().ownedOperation))]
+ [for (anOperation : Operation | aClass.getOperations())]
Do not generate External Classes
Wrap the code generating aClass inside this if. You can trick this code to make it work with other templates.
[let c : Classifier = aClass.oclAsType(Classifier)]
[if (c.getAppliedStereotypes()->collect(name)->count('External') = 0)]
[/if]
[/let]
Runtime Eclipse
- Run > Run Configurations (or Debug Configurations)
- Double-click on Eclipse
- You may name the configuration "runtime_eclipse"
- Press Run (resp. Debug)
- And click on proceed if prompted.
Process With Code Generation
Inside the Runtime Eclipse:
- Import projects
- Existing Projects Into Workspace
- Browse > Find SMModel
- Once imported, double-click on the model
For Xtend 🍬, in the Model Explorer:
- Right-click on "Project XXX" (your project)
- Generate Code for State Machine
- Create JDT (Yes > Set JDK to XXX > Finish)
For Acceleo 🍫, in the Project Explorer:
- Expand "Project XXX" (your project) to see the UML file
- Right-click on the UML file
- Acceleo Model To Text
- Generate UML2java
- You got a folder src-gen
It will generate a new model with the generated Java classes 👑.
👻 To-do 👻
Stuff that I found, but never read/used yet.
- Papyrus CEA Guide
- Warning: do not create an activity twice (use sync with editor, navigate to find it)
- Warning: in activities, every call must be Typed