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
  • ...

You can download it here. These notes are based on 4.8.0.

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.

Papyrus perspective and select Papyrus select perspective

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

  1. 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")
  2. Model explorer 🍀: Once you open a model, add diagrams to it from this menu: Right-click on "example" > "New diagram".
  3. Model editor 🎥: edit your diagram here. You can move things from the palette (4) to here.
  4. Palette 🎨: every element that you can put inside the kind of diagram you opened.
  5. 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.
  6. 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

Papyrus (eclipse) editor


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.

Papyrus saved


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).

palette use icons hover palette

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.

Align classes

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.

associations

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:

associations shortcut papyrus

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.

Set type Papyrus

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) or Primitive 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"
  • 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()
  • 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