Umple Combined User Manual
http://www.umple.org
This version is one large page and is intended to allow searching through the entire manual, or easy printing to pdf for offline reading. For most purposes you will want to work with the individual manual pages at http://manual.umple.org. A published 526-page pdf version of the Umple User Manual is also available for download.
 

Getting Started

Umple is a technology for Model-Oriented Programming.

The Umple home page is https://www.umple.org. To download Umple for the command line or an IDE, go to https://umple.org/dl. To use Umple online as a web app, go to https://try.umple.org

Umple allows you to do the following things:

  1. Create UML models textually. Rather than drawing diagrams, it can often be faster to create UML class diagrams and state machines using Umple's textual format that looks just like programming-language code. Editing, comparing and many other tasks can often be done faster using this textual form. Umple has tools that allow you to edit the model textually (and see changes appear in a UML diagram) or to edit a UML diagram (and see changes appear in the textual code)

  2. Add UML modeling constructs directly into your programs, when you are programming in Java, PHP, C++ or Ruby. For example, when programming in Java, you can directly add a UML state machine into your code. This can save you a lot of coding. The Umple compiler acts as a pre-processor, first compiling the state machine to Java, and then compiling the Java into an executable program.

  3. Generate high quality code from UML models. The Umple compiler creates code in languages like Java, C++ and PHP that is of top quality. It is a goal of the Umple team to create the best open-source code-generation tool available. The generated code never needs to be edited and never should be edited, since You can always embed native methods (i.e. Java, Php, etc.) in the Umple, or else use Umple's aspect oriented capabilities to alter the effects of generated code. As a result the concept of 'round tripping' is obsolete in Umple. You should treat Umple-generated code just like you would treat bytecode-or machine code, i.e. as a development artifact that can be thrown away and recreated. Nevertheless, we have endeavoured to make the generated code as clean and readable as possible so you can verify its correctness and learn how it works.

  4. Incrementally Umplify a program. A program in a base language like Java should pass through the Umple compiler unchanged. As a result you can incrementally refactor such a program, stripping off complex code for such things as associations, state machines and certain patterns, and replacing it by simple Umple code. This can be done bit-by-bit, while testing thoroughly at each step. When you are done, you will have a program that should not only be more compact, but also more reliable and more maintainable. In addition, you have the benefit of being able to view UML diagrams of your program.

The term "Umple" derives from "UML Programming Language", "Simple" and "Ample".

The quickest way to get started with Umple is to go to UmpleOnline, and select an example listed under 'EXAMPLES'. Each of the user manual pages also allows you to instantly load the examples into UmpleOnline.

To learn more about Umple, read the links on the left of this page, or go to the Umple Home page. In particular, you should browse the tutorials and videos about Umple


See here for the statement regarding privacy and other risks when using Umple.


If you are an ordinary user and notice an error in this manual, please report it using our issue tracking system here Flag it as a defect in the user documentation. If you still have trouble after reading this manual, please contact our help mailing list and post a request for help. If you are a contributer, you can click on the link 'edit in github' found at the bottom left of each manual page; also instructions on how to edit this manual are here.

YouTube Video with Additional Explanation

 
 

Hello World Examples

As is customary when introducing a new language, here are some 'hello world' examples for Umple. Load these examples into UmpleOnline by clicking on the links. Then generate Java code by clicking on the 'Generate' button. Next click on the 'download zip file' link and run 'javac' on the result or else compile it in Eclipse.

First example below: This looks identical to how a Java 'hello world' example would look, illustrating a key feature of Umple: Umple adds features to existing languages: Code in the original language can and does remain the same. Umple just replaces and simplifies some (or a lot) of it.

Second example below: This shows some very simple features of Umple: An attribute, an association, a generalization, some Java methods and the mixin capability:

Umple and UML: Here is the class diagram of the second example in UML. If you click on the 'open in UmpleOnline' link, you will see the UML diagram generated. You can then edit the UML diagram to change the code, or change the code to edit the UML diagram.

UML class diagram showing superclass Person (with attribute name), and with subclasses Student and Mentor. There is a 0..1 -- * association between the subclasses.

Example Showing a Simple Class with a Main Method

/*
 * Simple Hello World example for Umple.
 * Compile this with Umple and it will generate Java
 * that is essentially the same.
 * 
 * You could just as readily compile this code directly
 * with javac. However, this serves as the starting point:
 * Other examples in this manual show other things you
 * can do with Umple
 */
class HelloWorld {
  public static void main(String [ ] args) {
    System.out.println("Hello World");
  }
}

      

Load the above code into UmpleOnline

 

Example Showing Three Classes with an Association and Attributes (Diagram is Above)

/*
 * Introductory example of Umple showing classes,
 * attribute, association, generalization, methods
 * and the mixin capability. Generate java and run this.
 * 
 * The output will be:
 * The mentor of Tom The Student is Nick The Mentor
 * The students of Nick The Mentor are [Tom The Student]
 */
class Person {
  name; // Attribute, string by default
  String toString () {
    return(getName());
  }
}

class Student {
  isA Person;
}

class Mentor {
  isA Person;
}

association {
  0..1 Mentor -- * Student;
}

class Person {
  // Notice that we are defining more contents for Person
  // This uses Umple's mixin capability
  
  public static void main(String [ ] args) {
    Mentor m = new Mentor("Nick The Mentor");
    Student s = new Student("Tom The Student");
    s.setMentor(m);
    System.out.println("The mentor of "
      + s  + " is " +  s.getMentor());
    System.out.println("The students of "
      +  m  + " are " +  m.getStudents());
  }
}
      

Load the above code into UmpleOnline

 

Example Showing a Simple Class with a Main Method for Python Generation

/*
 * Simple Hello World example for Umple.
 * Compile this with Umple and it will generate Java
 * that is essentially the same.
 *
 * You could just as readily compile this code directly
 * with javac. However, this serves as the starting point:
 * Other examples in this manual show other things you
 * can do with Umple
 */
class HelloWorld {
  public static void main(String [ ] args) {
    print("Hello World")
  }
}

      

Load the above code into UmpleOnline

 

Example Showing Three Classes with an Association and Attributes (Diagram is Above) for Python Generation

/*
 * Introductory example of Umple showing classes,
 * attribute, association, generalization, methods
 * and the mixin capability. Generate java and run this.
 * 
 * The output will be:
 * The mentor of Tom The Student is Nick The Mentor
 * The students of Nick The Mentor are [Tom The Student]
 */
class Person {
  name; // Attribute, string by default
  String __str__() {
    return self.getName()
  }
}

class Student {
  isA Person;
}

class Mentor {
  isA Person;
}

association {
  0..1 Mentor -- * Student;
}

class Person {
  // Notice that we are defining more contents for Person
  // This uses Umple's mixin capability
  
  public static void main(String [ ] args) {
    import Mentor
    import Student
    m = Mentor.Mentor("Nick The Mentor")
    s = Student.Student("Tom The Student")
    s.setMentor(m)
    print("The mentor of " + str(s)  + " is " +  str(s.getMentor()))
    print("The students of " +  str(m)  + " are " + str(list(map(str, m.getStudents()))))
  }
}
      

Load the above code into UmpleOnline

 

Umple Tools

Umple files conventionally use the extension .ump. To create a model or a system you would use one or more of the following tools to view, edit and compile .ump files.

More details on downloading, installing and running Umple can be found here.

Structure of Umple Code

Organizing the contents of an Umple (.ump) file

An Umple file will contain a number of top level items we call directives. These can be:

 

Methods in classes

Much of the code in an Umple file is processed by the Umple compiler, and used to generate code in a 'base' or 'native' language (e.g, Java, PHP or Ruby) for the final system. However methods are treated differently: They are passed through essentially unchanged to the resulting system.

If you include methods in Umple code, you generally have to ensure that any given Umple file has methods of just one chosen target language (Java, PHP, Ruby. etc.). A special syntax is, however, available if you want to generate code in more than one target language.

Anything that Umple can't parse itself may be interpreted to be a method; this can result in unintended results: What you intend to be some Umple code such as an attribute or association may end up being treated as 'extra code', i.e. a method, and passed through unchanged (normally with a warning).

The resulting system will contain many more methods than those that you explicitly include. This is because one of the key points about Umple is that it generates a high percentage of the methods you would normally need to write by hand if you were programming directly in the target language. In other words, when you compile Umple constructs such as associations, attributes and state machines, you are generating many methods that you can call; the set of methods you can call is the generated API. You can find out the API by using Javadoc, or a similar tool, on the generated code, or you can look at the quick reference manual page. One of the options in UmpleOnline is to generate Javadoc output.

 

Organizing a system containing many files

If your system is large, you should divide it into many files. One way to do this is to follow the Java convention of having one .ump file per class. Another common approach is to have one or more files for the model code (just the pure UML elements such as classes with their attributes, associations and state machines) and separate files for the methods; you can in fact have some files for Java methods, and other files for PHP or Ruby methods. The same model can then be used to develop systems that are deployed in multiple base languages.

The fact that Umple allows for multiple definitions to be added to create a complete definition, also means that you can create mixins. A mixin is a file that has some definitions that can be added to add extra features to a system. You can therefore organize your system, in whole or in part, by feature. The various pieces of code needed to implement a feature (including entire new classes, or bits such as associations and methods to add to existing classes), can therefore be grouped together. There are limits to this, however: At the current time, this mechanism does not allow you to override existing elements, which you might need to do to add a feature. Taken together, these mechanisms allow for a form of product-line development.


Examples of Mixins

The below video shows some ways to incorporate mixins to Umple classes. Follow the following links to watch further examples for:

YouTube Video with Additional Explanation

 
 

Syntax


// The core of umple is a "program". This is the grammar's 'start symbol'
// Comments and lone semicolons are ignored
program- : [[useProgram]] | [[umpleProgram]]

// Directives are the top-level items in an umple file. See manual page TypesofDirectives
// A directive is either used to configure the system or else is
// an actual entity of the system to be modelled or generated
directive- : [[checkForUnintendedBracket]]
    | [[glossary]]
    | [[generate]]
    | [[distribute]]
    | [[generate_path]]
    | [[filter]]
    | [[useStatement]]
    | [[namespace]]
    | [[requirement]]
    | [[reqImplementation]]
    | [[tracerDirective]]
    | [[entity]]
    | [[debug]]
    | [[strictness]]
    | [[toplevelExtracode]]
    | [[toplevelException]]

// Use statements allow incorporation of other Umple files. See UseStatements
useStatement : use [use] ( , [extraUse] )*

// Namespaces divide the code into logical groups. See NamespaceDirectives
namespace- : namespace [namespace] [[namespaceoption]]? ;

// The main top level elements to be found in an Umple file
entity- : [[mixsetIsFeature]]
    | [[requireStatement]]
    | [[mixsetDefinition]]
    | [[classDefinition]]
    | [[traitDefinition]]
    | [[fixml]]
    | [[interfaceDefinition]]
    | [[externalDefinition]]
    | [[associationDefinition]]
    | [[associationClassDefinition]]
    | [[stateMachineDefinition]]
    | [[templateDefinition]]
    | [[enumerationDefinition]]
    | [[toplevelCodeInjection]]

// Comments follow the same conventions as C-family languages. UmpleComments
comment- : [[inlineComment]] | [[multilineComment]] | [[annotationComment]]

Convincing Potential Adopters

Convincing yourself, your development team or your management to use Model-Oriented Programming with Umple

Here are some arguments to make to help convince you, your management and your colleagues to adopt model-oriented programming and Umple in particular:

  1. Model-code duality: Umple means you no longer have to maintain models separately from the code. Your code and model become the same thing. Your models therefore don't get out of date and your volume of separately-maintained documentation becomes less. Model elements in the Umple code, along with their comments, become the design documentation.

  2. Rapid application development: Models containing the essential structure of a system can be developed extremely fast, and modified extremely rapidly. This is because most people can edit Umple text faster than they can use a drawing tool. But the ability to use a drawing tool is not sacrificed you can still draw an Umple model as a diagram with UmpleOnline!

  3. Less code to write: Code for UML constructs like associations, state machines and certain patterns is generated. Less code means fewer bugs. Developers can concentrate on the more interesting or critical parts of their code.

  4. Fewer bugs: It is extremely difficult to consistently write bug-free code for complex constructs like state machines, or associations that maintain referential integrity and respect multiplicity constraints. Umple does this for you.

  5. The full power of UML features: Unlike Umple, most other code generators do not generate code that enforces multiplicity in class diagrams, or allows unlimited levels of nesting of state machines. Umple has incorporated the research of several PhD and masters theses to deliver state-of-the-art code generation.

  6. Text-diagram duality: Umple allows visualization of key aspects of your code with UmpleOnline. Furthermore the diagram can be edited to change the code, or the code can be edited to change the diagram. Both of these occur in real time.

  7. Product-line and feature-oriented development: Umple brings mixin technology to Java and PhP, allowing you to easily build different versions of your software for different customers or hardware platforms. Umple code can also be organized on a feature-by-feature basis.

  8. Aspect orientation to adapt generated code: You can inject your own code before and after any generated methods to enforce constraints or change semantics.

  9. Generation for multiple languages: Umple allows development targeted to several different programming languages at the same time: All the developer has to do is to maintain language-independent files for the models, and link them to language-specific code for algorithms.

  10. Incremental adoption: You can start with just one Umple statement in a million lines of code and gradually increase Umple usage. Your software will remain fully compliable and functional as you gradually increase your uptake of Umple.

  11. Use just like a pre-processor: Programmers have been confidently using pre-processors for half a century.

  12. Fully open source with a liberal license: If you dont like something about Umple you can fix it and contribute to the community. But there are no restrictions on what you do with Umple or its generated code since it uses an MIT-style license.

  13. Commitment to the future: The team at the University of Ottawa developing Umple plan to continue active development for the years to come. This will not become one of those research programs that comes to an end and is then abandoned. We recognize that ideas can take decades to percolate to the community. We plan to be right there supporting Umple as this happens.

Countering the counterarguments

Here are some common arguments against adopting a new software development technology, and how they don't apply in model-oriented programming:

  1. Complexity: Adding a new technology might add more complexity to our project so might require more learning by our employees and might make our systems harder to understand:
    Not true for Umple, because:

  2. Confidence: Our company would have no way to be confident about whether it works or not and we do not have the time or resources to do the needed due diligence:
    Not true for Umple, because:

  3. Support: If the technology stopped being supported, we would not be able to maintain our code base.
    Not true for Umple, because:

  4. Process: Our testing and building processes are likely to only work for well-known technologies:
    Not true for Umple, because:

  5. Compatibility: We use a lot of re-used, proprietary or legacy code that might be incompatible with the new technology:
    Not true for Umple, because:

List of Umple Keywords

Here is the list of all keywords in the Umple modeling language. These cannot be used as identifiers in cases where that would cause confusion.

The following tags are used to group certain keywords

Languages supported

Umple code can result in generation of various languages. Code from these languages can be inserted into Umple, or Umple can be inserted into code for the languages. The resulting systems can be used as part of larger projects involving these languages.

Here is the status of the programming languages currently:

Umple also generates a rich assortment of other outputs. The complete current list can be seen using the command line with the --help option; the list also appears below.

Several Graphviz diagrams can be generated (UML class diagrams, UML state diagrams, Entity-relationship diagrams, etc.), as can formal methods code in NuXmv and Alloy, and various forms of analysis outputs such as state tables and metrics.

Syntax


// The generate clause can be used to generate multiple outputs
// The --override is used to say that subsequent generate statements will be ignored
generate : generate [=language:Java
    |Nothing
    |Php
    |RTCpp
    |SimpleCpp
    |Ruby
    |Python
    |Cpp
    |Json
    |StructureDiagram
    |Yuml
    |Violet
    |Umlet
    |Simulate
    |TextUml
    |Scxml
    |GvStateDiagram
    |GvClassDiagram
    |GvFeatureDiagram
    |GvClassTraitDiagram
    |GvEntityRelationshipDiagram
    |Alloy
    |NuSMV
    |NuSMVOptimizer
    |Papyrus
    |Ecore
    |Xmi
    |Xtext
    |Sql
    |StateTables
    |EventSequence
    |Umple
    |UmpleSelf
    |USE
    |Test
    |SimpleMetrics
    |PlainRequirementsDoc
    |Uigu2
    |ExternalGrammar] ( [=suboptionIndicator:-s
    |--suboption] " [**suboption] " )* ;

generate_path : generate [=language:Java
    |Nothing
    |Php
    |RTCpp
    |SimpleCpp
    |Ruby
    |Python
    |Cpp
    |Json
    |StructureDiagram
    |Yuml
    |Violet
    |Umlet
    |Simulate
    |TextUml
    |Scxml
    |GvStateDiagram
    |GvClassDiagram
    |GvFeatureDiagram
    |GvClassTraitDiagram
    |GvEntityRelationshipDiagram
    |Alloy
    |NuSMV
    |NuSMVOptimizer
    |Papyrus
    |Ecore
    |Xmi
    |Xtext
    |Sql
    |StateTables
    |EventSequence
    |Umple
    |UmpleSelf
    |USE
    |Test
    |SimpleMetrics
    |PlainRequirementsDoc
    |Uigu2
    |ExternalGrammar] " [**output] " [=override:--override
    |--override-all]? ( [=suboptionIndicator:-s
    |--suboption] " [**suboption] " )* ;

Umple Comments

Comments provide a mechanism to document your work to provide some insight into why you are performing a certain action, as opposed to simply showing how.

Comments should be used just like in any programming language.

Comments immediately before class definitions, attribute definitions, association definitions and method definitions, as well as comments embedded in methods will be output into the generated code. Comments before definitions in Java will use Javadoc style; this means that when you generate JavaDoc output the API documentation will contain the comments. You are encouraged to create your Java comments using Javadoc tags.

Comments can be either inlineComments, or multilineComments.


Example Showing Inline Comments

// The Umple system is both fun
// and efficient to development with


      

Load the above code into UmpleOnline

 

Example Showing Both Inline And Multiline Comments

// The Umple system is both fun and
// efficient to development with

/* 
  This apple can only be compared to 
  other apples
*/

      

Load the above code into UmpleOnline

 

Inline Comments

Use two slashes to place comments after any text on the line. The comment ends at the end of the line. This is the same syntax as in Java, C++ and several other languages.

Example

// Umple is both fun and efficient to develop with


      

Load the above code into UmpleOnline

 

Syntax


inlineComment- : // [**inlineComment]

Multiline Comments

Use multiline comments starting with slash-star and ending with star-slash to document your work. You should put a comment block, for example, at the beginning of each file.

This syntax is the same as in Java and C++.

Example

/* 
  This apple can only be compared to 
  other apples
*/


      

Load the above code into UmpleOnline

 

Syntax


multilineComment- : /* [**multilineComment] */

Requirements

Requirements allow for the same comment to appear in different sections of the code without typing out the comment multiple times.

They consist of two components: the requirement definition, which contains the comment statement to be added, and the requirement implementation, which specifies where the requirement statement should be added.

Multiple requirements can be called through an implementsReq statement.


Example

req R01 {
  This is a comment we would like to add
  multiple times in different locations.

  The identifier used for this requirement is
  R01.
}

req R02 {
  This is a second requirement statement.
}

implementsReq R01;
class Example {
  implementsReq R02;
  var1;
  var2; implementsReq R01, R02;
}
      

Load the above code into UmpleOnline

 

Types of Directives

Directives appear as the 'main' entries in an Umple file. The following are the main types:

Syntax


// Directives are the top-level items in an umple file. See manual page TypesofDirectives
// A directive is either used to configure the system or else is
// an actual entity of the system to be modelled or generated
directive- : [[checkForUnintendedBracket]]
    | [[glossary]]
    | [[generate]]
    | [[distribute]]
    | [[generate_path]]
    | [[filter]]
    | [[useStatement]]
    | [[namespace]]
    | [[requirement]]
    | [[reqImplementation]]
    | [[tracerDirective]]
    | [[entity]]
    | [[debug]]
    | [[strictness]]
    | [[toplevelExtracode]]
    | [[toplevelException]]

// The generate clause can be used to generate multiple outputs
// The --override is used to say that subsequent generate statements will be ignored
generate : generate [=language:Java
    |Nothing
    |Php
    |RTCpp
    |SimpleCpp
    |Ruby
    |Python
    |Cpp
    |Json
    |StructureDiagram
    |Yuml
    |Violet
    |Umlet
    |Simulate
    |TextUml
    |Scxml
    |GvStateDiagram
    |GvClassDiagram
    |GvFeatureDiagram
    |GvClassTraitDiagram
    |GvEntityRelationshipDiagram
    |Alloy
    |NuSMV
    |NuSMVOptimizer
    |Papyrus
    |Ecore
    |Xmi
    |Xtext
    |Sql
    |StateTables
    |EventSequence
    |Umple
    |UmpleSelf
    |USE
    |Test
    |SimpleMetrics
    |PlainRequirementsDoc
    |Uigu2
    |ExternalGrammar] ( [=suboptionIndicator:-s
    |--suboption] " [**suboption] " )* ;

generate_path : generate [=language:Java
    |Nothing
    |Php
    |RTCpp
    |SimpleCpp
    |Ruby
    |Python
    |Cpp
    |Json
    |StructureDiagram
    |Yuml
    |Violet
    |Umlet
    |Simulate
    |TextUml
    |Scxml
    |GvStateDiagram
    |GvClassDiagram
    |GvFeatureDiagram
    |GvClassTraitDiagram
    |GvEntityRelationshipDiagram
    |Alloy
    |NuSMV
    |NuSMVOptimizer
    |Papyrus
    |Ecore
    |Xmi
    |Xtext
    |Sql
    |StateTables
    |EventSequence
    |Umple
    |UmpleSelf
    |USE
    |Test
    |SimpleMetrics
    |PlainRequirementsDoc
    |Uigu2
    |ExternalGrammar] " [**output] " [=override:--override
    |--override-all]? ( [=suboptionIndicator:-s
    |--suboption] " [**suboption] " )* ;

// Use statements allow incorporation of other Umple files. See UseStatements
useStatement : use [use] ( , [extraUse] )*

// Namespaces divide the code into logical groups. See NamespaceDirectives
namespace- : namespace [namespace] [[namespaceoption]]? ;

// The main top level elements to be found in an Umple file
entity- : [[mixsetIsFeature]]
    | [[requireStatement]]
    | [[mixsetDefinition]]
    | [[classDefinition]]
    | [[traitDefinition]]
    | [[fixml]]
    | [[interfaceDefinition]]
    | [[externalDefinition]]
    | [[associationDefinition]]
    | [[associationClassDefinition]]
    | [[stateMachineDefinition]]
    | [[templateDefinition]]
    | [[enumerationDefinition]]
    | [[toplevelCodeInjection]]

Use Statements

Use statements allow you to decompose your system by embedding or referencing files containing other model or program entities (i.e. classes) within your current model or to include optional blocks of code that are specified within mixsets.

A model file or mixset will only be included once, subsequent "use" commands for the same file will be ignored. If a mixset name is preceded by a ! then this indicates to not use the mixset, and cancels out any previous use statement that requested to use the mixset.

A common technique is to create a 'master' Umple file that does nothing but have a list of use statements.

Parts of an individual class can be specified in separate files, and brought together using several use statements. For example the associations or attributes could be in one (or several) files, and the methods could be in one (or more) additional files.

Another way to decompose a system is to have a 'core' set of files that can be included in several different systems using use statements.

Use statements work in a manner similar to 'include' directives in other languages.

A file referred to by a use statement must be in the same directory as the file that has the use statement, or in a parent directory, or in a subdirectory named lib. There are also some builtin Umple files that can be loaded, with the prefix lib:. Finally an https URL may be used to load a file from the Internet

Example

use Core.ump;
      

Load the above code into UmpleOnline

 

Syntax


// Use statements allow incorporation of other Umple files. See UseStatements
useStatement : use [use] ( , [extraUse] )*

Namespace Directives

Namespaces allow you to group similar entities to promote cohesion, as well as reduce the possibility of name collision. Sub-namespaces are separated using a period (.).

In the first example, the classes Faculty and Student will be in namespace school.admin. In Java they will be generated into the admin package (directory) within the school package. Similarly, class Building will be in the elevator.structure namespace.

A previously defined namespace for an entity can be redefined using the "--redefine" option. If the "--redefine" option is not used, the namespace will not change and a warning will be issued (example 2).

Entities declared before any namespace or after "namespace default;" will be in the default package. Entities declared after "namespace -;" will not be in the last declared namespace. Instead, they will be in the default package. If declared after a non-default namespace, the namespace of an entity in the default namespace will be redefined (example 3).

There are some cases where an entity should be imported thus cannot be in the default package and will automatically be placed in another package (example 4). However, automatic import code generation in interfaces that extend interfaces in other packages is not supported yet.

Example 1: Sub-namespaces

namespace school.admin;

class Faculty{}
class Student{}

namespace elevator.structure;

class Building
{
  1 -- * Classroom;
}

class Classroom{}
      

Load the above code into UmpleOnline

 

Example 2: Redefining a namespace

// Entities A, B and C are currently in
// namespace m.

namespace m;
class A{}
interface B{}
class C{}


// To redefine the namespace of an
// entity, use the --redefine option.
// B is now in namespace n.

namespace n --redefine;
interface B{}


// If --redefine is not used, a warning will
// be issued when trying to redefine the 
// namespace of an entity

namespace p;
class C{}


// Using namepace -; will deactivate the last
// declared namespace. There will not be an
// attempt to redefine the namespace of interface
// B and a warning will not be issued

namespace -;
interface B{}
      

Load the above code into UmpleOnline

 

Example 3: Default namespace

// Class A will be in the default namespace

class A{}
class B{}


// Class B was in the default namespace
// But now will be in namespace m

namespace m;
class B{}
class C{}
namespace -;


// Because namespace -; was used, namespace m
// is no longer active, and class D will be 
// in the default namespace

class D{}


// Class C is in namespace m, but can
// be placed in the default namespace

namespace default --redefine;
class C{}
      

Load the above code into UmpleOnline

 

Example 4: Automatically redefined namespace

// Classes A is in the 
// default namespace. Class B is in
// namespace m. Both are
// linked to each other via an association,
// therefore, and because they are not all
// in the same namespace, an import text
// should be generated. However, many programming
// languages do not support import from
// the default namespace so the namespace of
// A will become m because B is in m.

class A{}
namespace m;
class B{*--* A;}
namespace -;


// The same issue occurs when an
// entity in a non-default namespace
// extends or implements an entity
// in the default namespace

interface E{}
interface F{}
namespace n;
interface J{isA E;}
class K{isA F;}


// Here an import text will be generated for A in X
// because A is in a different namespace
// This feature is not yet supported for interfaces
// that extend interfaces in other namespaces
// and the import text will not be generated for K in Y

namespace p;
class X{isA A;}
// interface Y{isA E;}
      

Load the above code into UmpleOnline

 

Syntax


// Namespaces divide the code into logical groups. See NamespaceDirectives
namespace- : namespace [namespace] [[namespaceoption]]? ;

namespaceoption : [=option:--redefine]

Strictness Directive

The strictness directive is used to control certain messages that the Umple compiler may issue. It has five subdirectives that are specified by a second keyword following 'strictness':

The first two are 'modelOnly' or 'noExtraCode'. These are used when the programmer or modeller intends not to include base language code, and wants a warning to appear if base language code is found. Base language code is code in a language like Java or PhP that is discovered by Umple but not interpreted in any way. One example is the code in the bodies of methods; however, when parsing a class, any time Umple can't parse what it finds, it assumes it must be base language code. It just emits the base language code for the base language compiler to deal with. However there are circumstances when the developer does not want this: The developer may be creating a pure model or may want that the only base language code would be in the body of methods. It is advantageous therefore to tell the compiler to raise a warning if it thinks it has found base language code in some other context, since otherwise, an ordinary Umple syntax error may go undetected, until the base language compiler is run on the code.

The second set of subdirectives are 'expect', 'allow' and 'disallow'. These are used to control the effect of certain messages. They are followed by a message number.

Some of the above are still under development.

The strictness directives take effect on the entire system being built. The code of all Ump files of that system will be subject to the strictness subdirectives.

Example

// Tell the compiler that error 25
// will appear (and fail if it does not)
strictness expect 25;

// Tell the compiler that if error 22
// occurs, not to fail the compile.
// However, this does not mean that
// code can be generated
strictness allow 22;

// UNDER DEVELOPMENT: The following
// is not operational yet
// Tell the compiler that  base language
// code should not appear
strictness modelOnly;

// Tell the compiler that the only base
// language code could be in method bodies
// Any other unparsable 'extra code' in classes
// will be rejected.
strictness noExtraCode;


      

Load the above code into UmpleOnline

 

Syntax


// A high level of strictness will cause warnings to be issued when base language code
// is found, where it might not have been intended. Strictness can also be used
// To either suppress certain messages, or to declare that they should be present.
// NOTE: This is currently under development
strictness- : strictness ( [=strictness:modelOnly|noExtraCode|none]
    | [[strictnessMessage]]
    | [[strictnessDisableAuto]] ) ;

strictnessMessage : [=message:allow|ignore|expect|disallow] [messageNumber]

strictnessDisableAuto : disable [**expression]

Class Definition

A class definition defines an object-oriented class available for use as a type in the system you are developing. Objects (chunks of data) are created as instances of the class. A class describes the structure of that data in terms of attributes (simple data like strings and numbers), associations (links to and from other objects), state machines, as well as many other things described in this manual.

To define a class in Umple, specify the keyword 'class', followed by the name of the class (starting in a capital letter in order to respect naming conventions as well as to avoid a warning) and then the body of the class within curly brackets.

The body can contain various elements that are listed in the Class Content page.

Traits can be used to add the same set of items to several unrelated classes..

The following UML diagram shows two classes: a Student class and an Address class, linked by an association. The corresponding Umple is below.

UML diagram showing Student and Address

Example Showing two Classes (Class Diagram is Above)


class Student
{
  firstName;   // attribute - defaults to String
  lastName;
  Integer number;  // attribute with type Integer
  * -- * Address;  // Many-to-many association
  
  // Method, whose content is not processed by Umple
  public String fullName()  
  {
    return getFirstName() + " " + getLastName();
  } 
}

class Address
{
  String[] line;  // Multi-valued attribute
}
      

Load the above code into UmpleOnline

 

YouTube Video with Additional Explanation

 
 

Syntax


// Classes are the most common elements in Umple.
// See user manual page ClassDefinition
classDefinition : class [name] { [[classContent]]* }

// The following items can be found inside the body of classes or association classes
classContent- : [[comment]]
    | [[reqImplementation]]
    | [[innerClass]]
    | [[mixsetDefinition]]
    | [[distributable]]
    | [[proxyPattern]]
    | [[strictness]]
    | [[classDefinition]]
    | [[trace]]
    | [[emitMethod]]
    | [[templateAttributeDefinition]]
    | [[primitiveDefinition]]
    | [[portDefinition]]
    | [[portBindingDefinition]]
    | [[position]]
    | [[displayColor]]
    | [[abstract]]
    | [[keyDefinition]]
    | [[softwarePattern]]
    | [[depend]]
    | [[symmetricReflexiveAssociation]]
    | [[attribute]]
    | [[testCase]]
    | [[genericTestCase]]
    | [[testSequence]]
    | [[testClassInit]]
    | [[stateMachine]]
    | [[activeMethodDefinition]]
    | [[inlineAssociation]]
    | [[concreteMethodDeclaration]]
    | [[constantDeclaration]]
    | [[modelConstraint]]
    | [[invariant]]
    | ;
    | [[enumerationDefinition]]
    | [[exception]]
    | [[extraCode]]

interface Definition

An interface defines a list of abstract methods that are to be implemented in one or more classes. An interface can be composed of the following elements:

To implement an interface in a class, or to create subinterfaces, use an isA clause.

Umple also supports a feature called traits, that has some similarities to interfaces. However, traits concrete methods, attributes and state machines to also be contained in them.

In the following example, RegisterCapable is an interface that defines a single abstract method registerForCourse(). This is implemented concretely by CorporateClient and IndividualStudent.

Example

interface RegisterCapable
{
  depend school.util.*;
  
  boolean registerForCourse(Course aCourse);
}

class Person {
  name;
}


class CorporateClient {
  isA RegisterCapable;
  boolean registerForCourse(Course aCourse) {
     // write code here
  }
  0..1 <- * Person employees;
}

class IndividualStudent {
  isA Person, RegisterCapable;
  boolean registerForCourse(Course aCourse) {
     // write code here
  }
}


class Course
{
  name;
  description;
  * -- * Person registrants;
}
      

Load the above code into UmpleOnline

 

Syntax


// An Interface can only contain method. See interfaceDefinition
interfaceDefinition : interface [name] { [[depend]]* [[interfaceBody]] }

// Interfaces: Note that if the format of an abstractMethodDeclaration is not
// followed, then the body will extraCode and passed to the base language
// See user manual page interfaceDefinition
interfaceBody- : [[interfaceMemberDeclaration]]*

interfaceMemberDeclaration : [[comment]]
    | [[reqImplementation]]
    | [[constantDeclaration]]
    | [[constantDeclarationDeprecated]]
    | [[abstractMethodDeclaration]]
    | [[position]]
    | [[displayColor]]
    | [[isA]]
    | [[interfaceTest]]
    | [[distributableInterface]]
    | [[exception]]
    | [[extraCode]]

Class Content

A class can contain any of the following items. Interfaces are limited to those indicated as [Allowed in interfaces]. A trait can contain most of the items, indicated as indicated as [Allowed in traits].

Syntax


// The following items can be found inside the body of classes or association classes
classContent- : [[comment]]
    | [[reqImplementation]]
    | [[innerClass]]
    | [[mixsetDefinition]]
    | [[distributable]]
    | [[proxyPattern]]
    | [[strictness]]
    | [[classDefinition]]
    | [[trace]]
    | [[emitMethod]]
    | [[templateAttributeDefinition]]
    | [[primitiveDefinition]]
    | [[portDefinition]]
    | [[portBindingDefinition]]
    | [[position]]
    | [[displayColor]]
    | [[abstract]]
    | [[keyDefinition]]
    | [[softwarePattern]]
    | [[depend]]
    | [[symmetricReflexiveAssociation]]
    | [[attribute]]
    | [[testCase]]
    | [[genericTestCase]]
    | [[testSequence]]
    | [[testClassInit]]
    | [[stateMachine]]
    | [[activeMethodDefinition]]
    | [[inlineAssociation]]
    | [[concreteMethodDeclaration]]
    | [[constantDeclaration]]
    | [[modelConstraint]]
    | [[invariant]]
    | ;
    | [[enumerationDefinition]]
    | [[exception]]
    | [[extraCode]]

traitContent- : [[mixsetDefinition]]
    | [[testCase]]
    | [[requiredModelElements]]
    | [[comment]]
    | [[reqImplementation]]
    | [[traitDefinition]]
    | [[trace]]
    | [[position]]
    | [[displayColor]]
    | [[abstract]]
    | [[keyDefinition]]
    | [[softwarePattern]]
    | [[depend]]
    | [[symmetricReflexiveAssociation]]
    | [[attribute]]
    | [[stateMachine]]
    | [[inlineAssociation]]
    | [[concreteMethodDeclaration]]
    | [[abstractMethodDeclaration]]
    | [[constantDeclaration]]
    | [[invariant]]
    | ;
    | [[exception]]
    | [[extraCode]]

isA clause

The isA keyword is used to denote an inheritance relationship (generalization) between two classes, or a class and the interfaces it implements, or a class and the traits it includes.

This corresponds to keywords such as 'extends', 'subclass', etc. in other languages. The isA keyword was chosen so as to be independent of other languages, and due to the strong conceptual similarity between interfaces, classes and traits.

Note that it is possible to avoid using the isA keyword for class generalization, by directly embedding a subclass inside a superclass. Note that this does not create an inner class in the Java sense, but instead creates a subclass. The two examples below give identical results.

The following is how a generalization appears in UML. The corresponding Umple is below. Note that in UmpleOnline, the expected layout for generalizations places superclasses above subclasses.

Generalization with Person as superclass and Student as subclass

Example Showing Student as a Subclass of Person

// A superclass-subclass relationship defined using the isA keyword
class Person
{
  name;
}

class Student
{
  isA Person;
  Integer number;
}
      

Load the above code into UmpleOnline

 

The Same Model as Above but Using Nesting Instead of IsA

// A superclass-subclass relationship defined
// by embedding the subclass in the superclass
class Person
{
  name;
  
  class Student
  {
    Integer number;
  }
}

      

Load the above code into UmpleOnline

 

Syntax


// Generalization and inheritance isAclause
isA- : [[singleIsA]] | [[multipleIsA]]

singleIsA- : isA [[isAName]] ( , isA [[isAName]] )* ;

multipleIsA- : isA [[isAName]] ( , [[isAName]] )* ;

Depend clause

The depend clause is used to indicate a dependency to another namespace, class or interface.

See also this example of how to use the depend clause to arrange for Umple to work with external code.

Example

namespace sports.core;

class Equipment
{
  name;
  Integer weight;
}

namespace sports.baseball;

class Baseball
{
  depend sports.core.*;

  public boolean isRequired(Equipment eq)
  {
    return eq.getName().equals("bat");
  }
}

      

Load the above code into UmpleOnline

 

Syntax


// Depend clause. See user manual page Dependclause
depend- : depend [depend] ;

Custom Constructor

Custom constructors should normally not be provided in Umple. Consider using before and after keywords to adjust what the automatically-generated constructor does, or adjusting constructor parameters using keywords like lazy.

Umple generates its own constructors: The arguments are composed from the list of attributes in the class (in the order provided), as well as any associations with a 1 multiplicity at the other end. To avoid having an argument in the generated constructor, designate an attribute as 'lazy' or specify association multiplicity to be 0..1 instead of 1. Umple also generates code to constrain the value of what appears in each constructor if a constraint is specified.

Attribute Definition

An attribute represents some information held by a class.

The attribute can have many properties, and can be defaulted to a certain value.

It is important to distinguish an attribute from the concept of a 'field' or 'instance variable' in Java or another programming language. An attribute is a UML/Umple entity that represents simple data. In Java it will become a field, but there will also be methods associated with the Umple attribute to get it, set it, and constrain its value. An attribute may also automatically be added to the argument list of the constructor and constructed in the constructor. In addition to representing attributes, Java fields also represent the ends of associations. Both attributes and associations should be considered more abstract than fields.

A summary of the generated methods for each attribute can be found on the API summary page.

Umple state machines are a special kind of attribute, and Umple also allows you to inject code that will constrain or alter the values of attributes using aspect-oriented techniques.

The example below shows the basic properties of attributes.

Example


class Group 
{
  // Simple Umple Integer. Note that code generation
  // in different languages will use the simplest
  // native type in that language. In Java it will
  // use int.
  // The initial value must be supplied through a
  // constructor argument.
  // The value can later be accessed through set and
  // get methods (here setI and getI).
  Integer i;

  // const: Declares a constant (static final in Java).
  const Integer Max = 100;

  // immutable: A constructor argument is required so
  // it can be set at construction time; cannot be
  // changed after that since no set method is
  // generated.
  immutable String str;
  
  // lazy: A constructor argument is not required.
  // Numbers are initialized to zero.
  // Objects (including Strings) are initialized to null,
  // Booleans are initialized to false.
  lazy Time t;
  lazy Boolean b;
  lazy s;
  
  // settable: Set using a constructor argument and
  // can be changed after that. This is the default,
  // so the settable keyword can be omitted.
  settable Date d;
  
  // internal: No getter and setter methods created.
  // Only for private use in internal methods. However
  // in this case it is initalized using =  The code
  // following = is in the 'base' language, here Java.
  internal Time t2 = new Time(
    System.currentTimeMillis());

  // unique: Every new object created must have a
  // unique new value assigned.
  // You can get the value. You can set it as well,
  // but it has to be unique.  
  unique u;

  // autounique: Every new object created will have a
  // new integer assigned.
  // You can get the value (an integer) but not set it.  
  autounique x;

  // The value is initialized as shown in the constructor.
  // There is no constructor argument generated.
  String q = "chicken"; 
      
  // defaulted: Set in the constructor to the default,
  // and can be reset to the default any time by
  // calling a reset method (here resetP()). 
  // Can also be set to any other value using setP().
  // The default can be queried by calling getDefaultP().
  defaulted String p = "robot";
  
  // Similar to the above, except this shows that if
  // no type is given, then the default type is String.
  defaulted r = "";
}
      

Load the above code into UmpleOnline

 

Syntax


// Details of attributes. See user manual page AttributeDefinition
attribute : [[simpleAttribute]]
    | [[autouniqueAttribute]]
    | [[multivaluedAttribute]]
    | [[derivedAttribute]]
    | [[complexAttribute]]

simpleAttribute- : [~name] ;

autouniqueAttribute- : [=autounique] [~name] ;

multivaluedAttribute- : [=unique]? [=lazy]? [=ivar]? [=modifier:immutable
    |settable
    |internal
    |defaulted
    |const
    |fixml]? [type]? [[list]] [~name] (= { [**value] })? ;

derivedAttribute- : [=modifier:immutable
    |settable
    |internal
    |defaulted
    |const
    |fixml]? [[typedName]] = ( [[moreCode]] )+

complexAttribute- : [=unique]? [=lazy]? [=ivar]? [=modifier:immutable
    |settable
    |internal
    |defaulted
    |const
    |fixml]? [[typedName]] (= [**value])? ;

Umple Builtin Data Types

The following example illustrates the data types available for Umple attributes. Except as specified, they will generate primitive datatypes in Java.

Initialization of values can be performed in a manner similar to Java or C++. Initialization of Dates uses yyyy-mm-dd format, and initialization of Times use hh:mm:dd format.

Example


class Demo 
{
  Integer i;
  Integer i2 = 5;

  String str;  // the default if no type is specified
  str2;
  str3 = "";
  
  Float flt;

  Double dbl;
  Double dbl2 = 8.0;

  Boolean bln;
  Boolean bln2 = false;

  Date dte; // In Java. uses the java.sql.Date class
  Date dte2 = "2018-09-25";

  Time tme; // In Java. uses the java.sql.Time class
  Time tme2 = "14:56:50";
}
      

Load the above code into UmpleOnline

 

Example Using a Native Java Type Rather than a Builtin Umple Type


class DemoNonUmpleType
{
  // If you use a non-umple type that is specific to a base
  // programming language, then code will be generated
  // consistent with that type, but generation of code
  // independent of base language is no longer possible
  int demoJavaInt;
}
      

Load the above code into UmpleOnline

 

Classes as Attribute Types

You can declare a class as a data type of an attribute. This allows for declaration of a 'containment' relationship.

If the data type you are using for an attribute is an Umple class, users should also consider using an association, and particularly a composition instead. This allows drawing of diagrams and more consistency checks by the Umple compiler.

If you use the methods in the Umple-generated API to access the object stored in such an attribute, and pass this contained object to some remote subsystem, then that remote subsystem will be able to affect the containing object in a backhanded sort of way. This is considered content coupling in software engineering, and should be carefully controlled or avoided.

In the examples below, we show how using attribute notation is very similar to using a directed association, except that with attribute notation, you can set the value to null.

Example

// This first example uses attribute notation
// The address is required on the constructor, but
// can be null. An instance of Address can be
// considered to be contained within the
// Person class.
//
// Although there is nothing currently preventing
// the same address instance from being re-used in
// multiple classes, it is strongly suggested to
// avoid that. If you want to reuse the same
// Address, then use association notation instead.
class Person {
  name;
  
  // The following uses a class as the attribute type
  Address address;
}

class Address {
  street;
  city;
  postalCode;
  country;
}
      

Load the above code into UmpleOnline

 

Alternative to the Above that Uses an Association


// Contrast this example with the previous one
// Here we use a directed association instead of 
// an attribute.
// Note that the multiplicity on the left is of no
// relevance. It is conventional to show it as *
// to indicate that the value could be attached to
// several objects.
//
// Here when you construct a Person, the address
// cannot be null. 
class Person {
  name;
  
  * -> 1 Address address;
}

class Address {
  street;
  city;
  postalCode;
  country;
}
      

Load the above code into UmpleOnline

 

Another Alternative with an Association Having Multiplicity Indicating Optional

// In this example, we have made the address
// optional. Now, it does not appear on the
// constructor. However when you add an address it
// still cannot be null.
//
// Note also that in this example, the role name
// 'address' is left off to show  it is optional.

class Person {
  name;
  
  * -> 0..1 Address;
}

class Address {
  street;
  city;
  postalCode;
  country;
}
      

Load the above code into UmpleOnline

 

MultiValued Attributes

As in UML, Umple allows one to specify an attribute with multiple values.

We encourage the use of association notation in this context, however the attribute notation can be useful sometimes.

Initialization of multivalued attributes is also allowed, as shown in the example.

Example

class Office {
   Integer number;
   Phone[] installedTelephones;
   String[] emails = {"abc@umple.org", "def@umple.org"};
   Integer [] incomingNumbers = {765432, 987654};
} 

class Phone {
  String digits;
  String callerID;
}
      

Load the above code into UmpleOnline

 

Syntax


multivaluedAttribute- : [=unique]? [=lazy]? [=ivar]? [=modifier:immutable
    |settable
    |internal
    |defaulted
    |const
    |fixml]? [type]? [[list]] [~name] (= { [**value] })? ;

Lazy Immutable Attributes

If you want to avoid having an attribute change after it is initially set, but do not want to have an argument in the constructor, then use the combination of keywords 'lazy immutable'.

You can call the set method just once on such an attribute. The set method will return false if you try again. This is useful for interacting with architectures where objects are constructed for you, so you have no ability to specify constructor arguments.

Note that if the lazy keyword is omitted, then there will be no set method and an argument will be present in the constructor to initialize the attribute. See also the immutable pattern.


Example

class A 
{
    lazy immutable z;
}
      

Load the above code into UmpleOnline

 

Syntax


complexAttribute- : [=unique]? [=lazy]? [=ivar]? [=modifier:immutable
    |settable
    |internal
    |defaulted
    |const
    |fixml]? [[typedName]] (= [**value])? ;

Derived Attributes

When declaring an attribute in Umple, you can specify an arbitrary expression after the equals sign to create an attribute that will be computed. There will be no set method on such an attribute.

Note that unless you use the simplest of expressions, you will be limited to only being able to generate code for the language of the expression.

You should make sure you call the get methods provided in the Umple-generated API (rather than directly accessing variables) and avoid having any side-effects in your expressions. Currently this is not enforced, but may be in the future.

For other examples of derived attributes see the sections on the Delegation pattern and sorted associations.

Example

class Point 
{
    // Cartesian coordinates
    Float x;
    Float y;
    
    // Polar coordinates
    Float rho = {
      Math.sqrt(Math.pow(getX(), 2)
      + Math.pow(getY(), 2))
    }
    Float theta =
      {Math.toDegrees(Math.atan2(getY(),getX()))}
}
      

Load the above code into UmpleOnline

 

Example with the Language of the Expression Being Specified

class Rectangle {
  Double height;
  Double width;
  Double area =
    Java {height*width} Php {$height*$width}
}
      

Load the above code into UmpleOnline

 

Syntax


derivedAttribute- : [=modifier:immutable
    |settable
    |internal
    |defaulted
    |const
    |fixml]? [[typedName]] = ( [[moreCode]] )+

Unique Attributes

Attributes in Umple can be unique. Applying the unique keyword to an attribute ensures that each instance of the class in the currently running program has a unique value for that attribute.

In the first example, each player has a unique ranking. The ranking of a player can change but two players cannot have the same ranking.

The autounique keyword can be used to automatically assign a unique Integer to every new instance created (example 2).

Certain runtime errors can occur if attempts are made to violate uniqueness.

Example 1

// Every player has a ranking.
// Rankings can be modified,
// but two different players 
// can not have the same ranking.

class Player
{
  unique Integer ranking;
}
      

Load the above code into UmpleOnline

 

Example 2

// Unique registration numbers (Integer)
// are automatically assigned to every
// new registration created

class Registration
{
	autounique registrationNumber;
}
      

Load the above code into UmpleOnline

 

Syntax


autouniqueAttribute- : [=autounique] [~name] ;

complexAttribute- : [=unique]? [=lazy]? [=ivar]? [=modifier:immutable
    |settable
    |internal
    |defaulted
    |const
    |fixml]? [[typedName]] (= [**value])? ;

Enumeration Definition

The Umple language allows developers to define enumerations for either a single class, or to share between classes. An enumeration is a user-defined data type that is a set of constants.

As shown in the examples below, enumerations require the keyword "enum" followed by the name of the enumeration, and its values. If duplicate enumerations are detected, E095 Duplicate Enumerations will be raised. If enumerations outside of class bodies have the same name as the enumerations within class bodies, the enumerations within class bodies will be used in the generated code.

Model-level enumerations will be added to classes when they do not already have enumerations defined with the same name, and the enumeration is detected in attribute types, method return types, method parameter types, and/or event parameter types.

Example

// In this example, the "Status" enumeration
// is defined for the "Student" class

class Student {
  enum Status { FullTime, PartTime }
  Status status;
}
      

Load the above code into UmpleOnline

 

Example of Enumeration Shared by Two Different Classes

// In this example, the "Status" enumeration
// is shared by the "GradStudent"
// and "UndergradStudent" class

enum Status { FullTime, PartTime }

class GradStudent {
  Status status;
}

class UndergradStudent {
  Status status;
}
      

Load the above code into UmpleOnline

 

Example of Enumerations Defined for a Single Class or Shared between Different Classes

// In this example, the "Status" enumeration
// is shared by the "GradStudent"
// and "UndergradStudent" class
// The "Semester" enumeration is only defined
// for the "UndergradStudent" class

enum Status { FullTime, PartTime }

class GradStudent {
  Status status;
}

class UndergradStudent {
  enum Semester { Spring, Summer, Fall, Winter }
  Status status;
  Semester semester;
}
      

Load the above code into UmpleOnline

 

Example with Enumerations Defined Within and Outside of Class Bodies

// In this case, the "Month" enumeration
// defined in class A will be used in
// the generated code

namespace example;

enum Month {x,y,z}

class A{
  enum Month {o,p,q}
  Month m;
  Month p;
}
      

Load the above code into UmpleOnline

 

Syntax


// Enumerations can be declared outside the body of classes
// See user manual page EnumerationDefinition
enumerationDefinition : enum [name] { [enumValue](, [enumValue])* }

Association Definition

An association defines a relationship from a class to another class. More specifically, it defines which links (i.e. references or pointers) may exist at run time between instances of the classes.

Umple supports binary associations (associations with just two ends). This definition includes reflexive associations, in which both ends are the same class.

An association can specify the following information:

The following is a UML diagram showing associations. The corresponding Umple is at the end of the page.

UML class diagram showing classes A, B and C with several associations

Associations can be presented in two ways in Umple.

There are several special kinds of associations in Umple.

Umple will report an error if an association refers to a non-existent class.

Example

// Example code illustrating various
// kinds of associations
class A {}

// Class with inline association having role name
class B {
  1 -- * A endTwo; 
}

// Class with reflexive association
class C {
  0..1 -- * C;
  1 -- 0..1 D; // D is external
}

// Independently defined and directed association
association {
  0..1 A -> * C;
}

// Class with composition
class E {
  0..1 e <@>- * A a;
}

// Reference to a class defined elsewhere
external D {}
      

Load the above code into UmpleOnline

 

Multiplicity

Multiplicity describes the allowable number of entities that can participate in one end of an association. In most cases you provide both a lower and upper bound, but the "many" (or "*") case assumes a zero lower bound.

The most common cases are:

Multiplicity must be specified for both ends of an association. At run time, code generated by Umple will ensure that the lower bounds and upper bounds are respected. Also the multiplicity determines which methods will be generated in the API for the model. For example, when * is specified, methods are generated to access all the associated objects, and to access an object at a specific index. The number of objects linked at run-time is called 'cardinality'.

If multiplicity is specified incorrectly, the compiler will generate an error message highlighting the line with the multiplicity error.

 

'Mandatory many' example

// When multiplicity is given as *, which is the
// same as 0..* there can be any number of links
// from an instance at the other end of the
// association to instances at this end 
//
// The lower bound is zero and the upper bound is
// 'many'
class A
{
  // an instance of A has many B's
  1 -- * B;
  
  // An instance of C has many A's
  * -- 1 C;
}

class B {} class C {}
      

Load the above code into UmpleOnline

 

Example with lower and upper bounds

// When the mutiplicity is shown as two integers
// separated by .. then the first integer is the
// lower bound, and the second integer is the
// upper bound.
//
// Here, at one end of the association
// the lower bound is 0..1 (which means 'optional'
// and at the other end of the association
// the lower bound is 3 and the upper bound is 5
class D {
  0..1 -- 3..5 E;
}

class E{}
      

Load the above code into UmpleOnline

 

Example with single integer multiplicity

// When the multiplicity is a single integer there
// must be exactly that number of objects linked
// at all times (including when the object at the
// other end is first created). Except for '1', 
// such multiplicities are rare.
//
// Here, there must be exactly two objects (lower
// and upper bound are both 2)
class F {
  0..1 -- 2 G;
}

class G{}
      

Load the above code into UmpleOnline

 

Syntax


multiplicity- : [!lowerBound:\d+|[**]] .. [!upperBound:\d+|[**]] | [!bound:\d+|[**]]

Inline Associations

An association represents a relationship between two classes. Associations can be defined within a class, in a similar manner as you would define an attribute.

Contrast this with the same model defined using independently defined associations.

Example


class Group 
{
  // a many-to-many association
  // An item has zero or more groups and a group
  // has zero or more items
  * -- * Item item;
  
  // An item has an optional description
  // The association is directed, so descriptions
  // do not know which groups link to them
  1 -> 0..1 Description;
}

class Item
{}

class Description
{}
      

Load the above code into UmpleOnline

 

Syntax


inlineAssociation : [=modifier:immutable]? [[inlineAssociationEnd]] [=arrow:--
    |->
    |<-
    |><
    |<@>-
    |-<@>] [[associationEnd]] ;

inlineAssociationEnd : [[multiplicity]] [~roleName]? [[isSorted]]?

associationEnd : [[multiplicity]] [type] [~roleName]? [[isSorted]]?

Independently Defined Associations

An association can be defined separately from any class. Contrast this with the Umple code showing the same model with inline associations.

Specifying an association independently of the two associated classes, as in the example below, can sometimes make code clearer. Specifying the association inline in one of the two classes can be clearer in other cases, particularly when it is defined in the more important class. But the decision regarding which alternative to use is left to the designer.

Example


class Group { }
class Item {}
class Description {}

association {
  * Group -- * Item;
}

association {
  1 Group -> 0..1 Description;  
}
      

Load the above code into UmpleOnline

 

Syntax


// Associations can be declared outside the body of classes.
// See user manual page IndependentlyDefinedAssociations
associationDefinition : association [name]? { ([[comment]]
    | [[reqImplementation]]
    | [[mixsetDefinition]]
    | [[association]])* }

association : [=modifier:immutable]? [[associationEnd]] [=arrow:--
    |->
    |<-
    |><
    |<@>-
    |-<@>] [[associationEnd]] ;

associationEnd : [[multiplicity]] [type] [~roleName]? [[isSorted]]?

association : association [associationNum];

Role Names

A role name is an additional name attached to an association. In the following example, the word 'supervisor' could be omitted, but it clarifies that the graduate student's professor is called his or her supervisor.

Example


class Person {
  name;
}

class GraduateStudent {
  isA Person;
  Integer id;
  * -- 0..2 Professor supervisor;
}

class Professor {
  isA Person;
  rank;
}
      

Load the above code into UmpleOnline

 

One-to-One Associations

The examples of associations in the previous user manual pages all showed cases where the lower-bound of the multiplicity at both ends is zero. For example there can be zero graduate students supervised by a professor, and zero professors might be assigned to supervise a graduate student initially.

Allowing a lower bound of zero means that one object can be created without having to first create the object(s) it is to be linked to. The vast majority of associations have a lower bound of zero at at least one of the two ends.

However there are a few situations where the lower bound at both ends of the association ought to be greater than zero. Here we will consider the one-to-one case. In the example below, a Company must always have one BoardOfDirectors and a BoardOfDirectors must always belong to one Company. But which should be created first? If we create the Company first, then a multiplicity constraint would be violated since for a period of time it would lack a Board. One solution would be to relax the constraint and decide that the association should not be 1-1. However Umple does allow 1-1 associations and creates a special API to allow both objects to be created at the same time.

The generated code has a constructor with the arguments normally found in the constructors of both associated classes. So in the following main program, the call to the constructor of Company with just a single argument (company name) will construct both the Company and the BoardOfDirectors and link them (the BoardOfDirectors class normally takes no argument on its constructor). If the constructor of BoardOfDirectors had had any arguments they could have been provided to the constructor of Company. The constructor of Board of Directors also could have been used to create both objects simultaneously.

It is worth noting that when a one-to-one association exists, there must always exist in the running system an equal number of both instances of both associated classes, and they must be linked in pairs.

Another observation is that modellers tend to over-use one-to-one associations. A superior modeling solution might be to merge the two classes; in this case just have a Company class.


 

An Executable Example Showing the Use of a One-to-One Association

// Core class of the example
// A company is a corporation
class Company {
  name;
  
  // A company must have a BoardOfDirectors
  // that must be created at the same time
  // as the Company itself
  1 -- 1 BoardOfDirectors;
}

// BoardOfDirectors is in a 1-1 relationship
// with Company meaning that theoretically it
// could just be merged into the Company class
// However to facilitate separation of concerns
// it is sometimes best to keep such classes
// separate
class BoardOfDirectors {
  // A BoardMember is just a member of one
  // board (but a person can be on multiple
  // boards using multiple BoardMembers)
  1 -- * BoardMember;
}

// A board must have a set of members
// Former board members tracked 
class BoardMember {
  bio; // Brief description of background
  lazy Date joinedBoard;
  lazy Date leftBoard;
  
  // One of the roles a person could play would
  // be as a Board member
  * boardMembership -- 1 Person;
}

// Generic Person class
class Person {
  name;
  Date dateOfBirth;
}

// Mixin with a main program demonstrating
// manipulation of 1--1 and other associations
class Company {
  depend java.sql.Date;
  
  public static void main(String [] args) {
  
    // First create some instances of Person
    // They are initially not on any boards
    Person p1 = new Person("Alice",
      Date.valueOf("1990-01-01"));
    Person p2 = new Person("Bob",
      Date.valueOf("1991-02-02"));
    
    // Create a Company using the simpler of its
    // two constructors that doesn't require a
    // board to already exist. This will actually
    // create the BoardOfDirectors at the same time
    Company c = new Company("UmpleCorp");
    
    BoardOfDirectors b = c.getBoardOfDirectors();
    
    b.addBoardMember("Largest Shareholder", p1);
    b.addBoardMember("Founder", p2);
    
    // Output the results to prove that this works
    System.out.println("Key company info: "+c);
    System.out.println("Board members: "+
      b.getBoardMembers());
    
  }
}
      

Load the above code into UmpleOnline

 

Reflexive Associations

A reflexive association is an association from a class to itself. There are two main types: Symmetric and Asymmetric.

Asymmetric Reflexive Associations: The ends of the association are semantically different from each other, even though the associated class is the same. Examples include parent-child, supervisor-subordinate and predecessor-successor.

The first and second examples below show courses having prerequisites that are other courses. It is necessary to specify a role name at one or both ends of the association to distinguish the ends. Also it is necessary to ensure that the lower bound is always zero on both ends. The reason for this is that otherwise an illogical situation would arise: For example, if you said that each course must have one or more pre-requisites, then what about the very first courses in the hierarchy? The compiler will report an error if the lower bound on a multiplicity is one or higher.

The following is how an asymmetric reflexive association appears in UML, as generated by UmpleOnline. The corresponding Umple code is in the first example below.

UML Class course with asymmetric reflexive many-many association with role names prerequisites and successors  

Symmetric Reflexive Associations: There is no logical difference in the semantics of each association end. The fourth example shows one of these: A set of courses that are mutually exclusive with each other essentially make up a set. If course A is mutually exclusive with B, then course B is mutually exclusive with A. In other words, students who have taken one course cannot take another in the set. Umple uses the keyword 'self' to identify this case. Note that at the current time the asociaton itself does not appear in UmpleOnline; this will be fixed.

 

Asymmetric association with role names on both ends

// Example asymmetric association with role names
// on both ends
class Course {
  * successor -- * Course prerequisite;
}

      

Load the above code into UmpleOnline

 

Asymmetric association with role names on one end

// Example asymmetric association with role name
// on one end
class Course {
   * -- * Course prerequisite;
}

      

Load the above code into UmpleOnline

 

Asymmetric association with role names on the other end

// Example asymmetric association with role name
// on the other end
class Person {
   0..2 parents -- * Person;
}

      

Load the above code into UmpleOnline

 

Symmetric association

// Example symmetric association. Note the use of
// the keyword self
class Course {
   * self  isMutuallyExclusiveWith;
}

      

Load the above code into UmpleOnline

 

Syntax


symmetricReflexiveAssociation : [[multiplicity]] self [roleName] ;

Compositions

A composition is a subtype of association where the delete is mandatory regardless of the multiplicity (enforced delete).

Compositions are used for associations where once the objects are associated, it makes sense for the deletion of one to cause the deletion of the other. This differs from the pre-existing associations, where the delete is dependent on the multiplicity.

For example, consider the case of a Vehicle and Wheel classes. With a regular association, the code would be as follows (where a Wheel can be associated to at most 1 Vehicles, and a Vehicle can have between 2 and 4 Wheels).

See Example 1

Here, the delete code for Vehicle does not delete the associated Wheels, since the multiplicity on Wheel is 0..1 which means the Wheel can exist without a Vehicle. However, on deleting a Vehicle it would make more sense for the associated Wheels to be deleted.

This is where compositions are useful. Rewriting the above example so that a Vehicle is composed with Wheel:

See Example 2

With the composition code, notice how the delete code for the Vehicle deletes all the Wheels associated, although the multiplicity is unchanged.

Compositions can be specified inline, or as separate associations (the same way as regular associations). The following two examples are equivalent to the Wheel-Vehicle example specified above.

See Examples 3 and 4

The following diagram is a representation of how the composition in the included examples is represented in UML, as generated in an editable class diagram by UmpleOnline.

UML class diagrams for Vehicle composed with Wheel  

Syntax

The syntax for compositions is the same as for regular associations, except for the arrow used. While in regular associations, the syntax is a -- b for "a associated with b", for compositions it is a <@>- b for "a composed with b", or a -<@> b for "b composed with a". In the class diagrams generated for compositions, the symbol is a filled-in diamond arrow.

 

Example 1

class Vehicle {}

class Wheel {}

association {
    0..1 Vehicle v -- 2..4 Wheel w;
}
      

Load the above code into UmpleOnline

 

Example 2

class Vehicle {}

class Wheel {}

// vehicle composed with wheels
association {
    0..1 Vehicle v <@>- 2..4 Wheel w;
}
      

Load the above code into UmpleOnline

 

Example 3

class Vehicle {
   0..1 v <@>- 2..4 Wheel w;
}

class Wheel {}
      

Load the above code into UmpleOnline

 

Example 4

class Vehicle {}

class Wheel {
  2..4 w -<@> 0..1 Vehicle v;
}
      

Load the above code into UmpleOnline

 

Syntax


association : [=modifier:immutable]? [[associationEnd]] [=arrow:--
    |->
    |<-
    |><
    |<@>-
    |-<@>] [[associationEnd]] ;

inlineAssociation : [=modifier:immutable]? [[inlineAssociationEnd]] [=arrow:--
    |->
    |<-
    |><
    |<@>-
    |-<@>] [[associationEnd]] ;

association : association [associationNum];

Association Specializations

A specialization is a subset of duplicate associations where:

For example, consider the case of Vehicle and Wheel classes and an Optional One to Many association between them. A Wheel can only belong to one Vehicle, but the concept of a Vehicle can include any number of Wheels. Say, for instance, we wanted to create a new Bicycle class that extends Vehicle, but we would like to make use of the association that already exists with a stricter multiplicity (say, a Bicycle can have up to 2 Wheels).

 

Without specializations, we need to create a new association between Bicycle and Wheel and thus generate some unneeded code and duplicate data fields (both Vehicle and Bicycle would have a list of Wheels, which behave more or less the same). With specializations, simply stating that we want a new association between Bicycle and Wheel (as long as the names match up to the Vehicle to Wheel association) is enough to generate more appropriate code.

 

Example

// Here we define our base classes
class Vehicle {}
class Wheel {}

// Here we define our subclasses
class Bicycle { isA Vehicle; }
class Unicycle { isA Vehicle; }

// This is the "parent association" so to speak.
// It defines the Vehicle to Wheel relationship
// with as much abstraction as possible.
association {
  0..1 Vehicle vehicle -- 0..* Wheel wheel;
}

// Here, we'd like to extend the functionality of
// the previous association to work with
// subclasses of Vehicle, while utilizing as much
// of the existing code as possible.
// Specializations allow us to do this, since:
// -> Bicycle and Unicycle extend Vehicle;
// -> Wheel is part of the Wheel hierarchy;
// -> The bounds on the left are not less specific
//    than the left bound of the parent
//    association;
// -> The bounds on the right are not less
//    specific than the right bound of the parent
//    association;
// -> Finally, the role names are the same.
association
  { 0..1 Bicycle vehicle -- 0..2 Wheel wheel; }
association
  { 0..1 Unicycle vehicle -- 0..1 Wheel wheel; }


      

Load the above code into UmpleOnline

 

Association Class Definition

An association class defines an object-oriented pattern to manage * -- * (many to many) associations when data needs to be stored about each link of that association.

An association class is a class and can have the items found in an ordinary class (attributes, state machines, etc.).

However it always has two or more 1..many associations to other classes. Each of these is written as:

The first role name is generally omitted. It is only required if both participating class names are the same (i.e. a reflexive association class). There is an example of this below.

The first example below shows classic use of association classes. A Ticket can be sold to Person in order to attend a Seminar. A Seminar can have many Persons, and a Person can attend many Seminars, so one might imagine simply creating a * -- * association between these classes. However, we want to record the ticket number and price for each Person attending each Seminar. We encode these attributes in the Ticket association class.

For most purposes, an association class behaves in the same manner as though it was an ordinary class with two * -- 1 associations to the participating classes (Person and Seminar in this first example). This is shown in the second example below. However, we want to restrict the possibility of having more than one Ticket sold to the same Person for the same Seminar. Association classes add this constraint.

The third example below shows that it is possible to have more than two classes participate in an association class.

The fourth and fifth examples show the use of the role name for the association class itself. The use of such role names is mandatory when the association class on a reflexive many-many association, i.e. the associated classes are the same. In this example there are Members (e.g. people in a club) and some are assigned to be mentors of others. We want to record the date of each assignment, and we do that using an association class. But since both associated classes are the same (Member), we need to use role names on both ends to ensure all links can be navigated unambiguously. At the Assignment end we have menteeAssignments and mentorAssignments (note the plural) and at the Member end we have roles mentor and mentee.

If we do not use the role names in the 5th example, then error 19 will occur because it will not be possible to refer unambiguously to either side of the association.

Example 1

// A person can attend many seminars,
// and a seminar can be attended by many people
// The relationship between Person and Seminar is
// thus many-to-many.
//
// There is, however, data to record about each
// ticket. This can be  recorded as an
// association class
//
// Note the following doesn't currently render
// in UmpleOnline using Correct UML
// association class notation.
// There are plans to fix this.
associationClass Ticket
{
  Integer ticketNumber;
  Double price = 0.0;
  
  * Person attendee;
  * Seminar;
}

class Person
{
  name;
}

class Seminar
{
  Date when;
  address;
}
      

Load the above code into UmpleOnline

 

Example 2

// The following shows how we might model sales of
// Ticket for Seminars to Persons without using an
// association class. Note, however, that in this
// model, it would be possible to sell more than
// one ticket to a Person for the same Seminar.
// Using an association class would hence be
// better than this.
class Ticket
{
  Integer ticketNumber;
  Double price = 0.0;
  
  * -- 1 Person attendee;
  * -- 1 Seminar;
}

class Person
{
  name;
}

class Seminar
{
  Date when;
  address;
}
      

Load the above code into UmpleOnline

 

Example 3

// The following shows a 'quaternary' association,
// where the association class represents data in
// an association that links four classes.
class SportsPlayer {
  name;
}

class Season {
  year;
}

// e.g. goalie, forward etc.
class PlayingPosition {
  description;
}

class Team {
  name;
}

// This gathers the number of points a player
// gained on a particular team in a particular
// season while playing in a particular position
// To get the total points in any one category,
// you would have to add the points several
// instances
associationClass PlayerInPosition {
  Integer points;
  * SportsPlayer player;
  * Season;
  * Team;
  * PlayingPosition position;
}
      

Load the above code into UmpleOnline

 

Example 4

// The following example is a simple class that
// shows an association class using both a
// single role name for one associated class (a1)
// and two role names to make links to the
// other associated class.
class A{
    f;
}


associationClass B{
    * A a1;
    * b2 C c1;
}


class C {
    d;
}
      

Load the above code into UmpleOnline

 

Example 5

// This shows a reflexive association class, where
// the associated classes are the same (Member).
// In this case we must use role names at both
// ends to ensure navigation to the correct sets
// (mentors, mentees)
class Member {
  name;
}

associationClass Assignment {
  Date dateEstablished;
  * menteeAssignments Member mentor;
  * mentorAssignments Member mentee;
}
      

Load the above code into UmpleOnline

 

Syntax


// Associations that would be many-many can also become full-fledged classes too
// See user manual page AssociationClassDefinition
associationClassDefinition : associationClass [name] { [[associationClassContent]]* }

associationClassContent- : [[comment]]
    | [[reqImplementation]]
    | [[classDefinition]]
    | [[position]]
    | [[displayColor]]
    | [[invariant]]
    | [[softwarePattern]]
    | [[depend]]
    | [[association]]
    | [[inlineAssociation]]
    | [[singleAssociationEnd]]
    | [[attribute]]
    | [[stateMachine]]
    | [[enumerationDefinition]]
    | ;
    | [[extraCode]]

singleAssociationEnd : [[multiplicity]] ( ( [otherEndroleName] [type] [roleName] )
    | ( [type] [~roleName]? ) ) ;

Sorted Associations

It is possible to arrange for associations to maintain themselves in sorted order according to the value of an attribute. Create a derived attribute in order to define a complex sort order or to sort on the value of an attribute of an associated class (the first example below does this in one case).

To declare an association as sorted do the following: after specifying the multiplicity, and any role name, give the keyword 'sorted' followed by the name of an attribute (sort key) in curly brackets. Whenever an add method is called to add an item to the association, Umple ensures the association is maintained in sorted order. .

Note that Umple associations are always 'ordered' by default; i.e. the user controls the position of items. Declaring an association as sorted makes this automatic. The presence of 'sorted' adds a 'sort' function to the API to allow for resorting (if the attributes on which sorting is based are changed, for example) and removes the API for manually ordering the association using addXAt().

Errors are generated if the attribute specified as the sort key attribute does not exist in the class, or the sort key attribute is not of a recognized type.

Java serialization of sorted associations is possible without the need to modify the Java code generated by Umple. The two ends of a sorted association implement the Serializable interface by default. Association items can be serialized and deserialized. After deserialization, more items can be added to the association and the association is maintained in sorted order as demonstrated by the second example.

Example

// This example demonstrates two cases of sorted
// associations. The main program adds items out
// of order. But when they are printed the output
// will be sorted
class Academy {
  1 -- * Course;
  1 -- * Student registrants sorted {id};
}

class Student {
  Integer id;
  name;
}

class Course {
  code;
}

class Registration {
  * -- 1 Student;

  // In each course, sort registrations by name
  * sorted {name} -- 1 Course;

  // Derived delegated attribute used for sorting
  // printing
  name = {getStudent().getName()}

  // Derived delegated attribute used for sorting
  // printing
  code = {getCourse().getCode()}

  
  public String toString() {
    return "Registration: " + getName()
      + ":" + getCode();
  }
}

// Mixin with main program and toString method
class Academy {
  public static void main(String [ ] args) {
    Academy ac = new Academy();
    Student j = ac.addRegistrant(12,"Jim");
    Student a = ac.addRegistrant(4,"Ali");
    Student m = ac.addRegistrant(8,"Mary");
    Student f = ac.addRegistrant(3,"Francois");
    Course c = ac.addCourse("CS191");
    Course c2 = ac.addCourse("AN234");    
    j.addRegistration(c);
    a.addRegistration(c);
    m.addRegistration(c);
    f.addRegistration(c);
    m.addRegistration(c2);
    f.addRegistration(c2);
    System.out.println(ac);
  }
  public String toString() {
    String result="Students:\n";
    for (Student s: getRegistrants()) {
      result +=s + "\n";
    }
    result +="Courses:\n";
    for (Course c: getCourses()) {
      result +=c + "\n";
    }

    return result;
  }
}

class Student {
  public String toString() {
    String result="Student=" + id + "["
      + name + "\n";
    for (Registration r: getRegistrations()) {
      result +="  In: " + r + "\n";
    }
    return result;
  }
}

class Course {
  public String toString() {
    String result ="Course=" + code + "\n";
    for (Registration r: getRegistrations()) {
      result +="  Has: " + r + "\n";
    }    
    return result;
  }
}
      

Load the above code into UmpleOnline

 

Example of sorted associations serialisation in Java

// This example demonstrates serialisation of
// sorted associations in Java. The main program
// adds items to an object out of order, serialize the
// object, deserialize it and then add more items
// to it. When they are printed after deserialisation,
// all items will appear in the right order.

class Academy {
  1 -- * Student registrants sorted {id};
}

class Student {
  Integer id;
  name;
}

// Mixin with main program, toString method
// and serialization test

class Academy {
  depend java.nio.file.*;
  depend java.io.*;
  
  public static void main(String [ ] args) {
    String filename = "SortedSerializableAssociation.ser";
    Academy ac = new Academy();
    Student j = ac.addRegistrant(12,"Jim");
    Student a = ac.addRegistrant(4,"Ali");

    System.out.println("Before Serialization");
    System.out.println(ac);
   
    //serialization
    try
    { 
      FileOutputStream file = new FileOutputStream(filename); 
      ObjectOutputStream out = new ObjectOutputStream(file); 
      out.writeObject(ac);       
      out.close(); 
      file.close();       
    } 
    catch(Exception ex) 
    { 
      System.out.println(ex.getMessage());
    } 

    Academy ac2 = null; 

    // Deserialization 
    try
    { 
      FileInputStream file = new FileInputStream(filename); 
      ObjectInputStream in = new ObjectInputStream(file);       
      ac2 = (Academy)in.readObject();       
      in.close(); 
      file.close();
    } 
    catch(Exception ex) 
    { 
      System.out.println(ex.getMessage());
    } 

    // Adding new elements and comparing 
    try
    { 
	Student m = ac2.addRegistrant(8,"Mary");
	Student f = ac2.addRegistrant(3,"Francois");
    }    
    catch(Exception ex) 
    { 
      System.out.println(ex.getMessage());
    } 
    
    System.out.println("After Serialization");
    System.out.println(ac2);
    
  }
  
  public String toString() {
    String result="Students:\n";
    for (Student s: getRegistrants()) {
      result +=s + "\n";
    }
    return result;
  }
}

class Student {
  public String toString() {
    String result="Student=" + id + "["
      + name +"]"+ "\n";
    return result;
  }
}

      

Load the above code into UmpleOnline

 

Syntax


inlineAssociationEnd : [[multiplicity]] [~roleName]? [[isSorted]]?

isSorted- : sorted { [priority] }

Simple Constraints

Umple supports basic OCL-type Boolean constraints that limit what umple-generated mutator methods (set, add, etc.) and constructors can do. If a constraint is violated set methods will return false, and constructors will throw an exception.

Constraints are specified within square brackets. Simple constraints can refer to attributes and literals (numbers, strings). These can be compared using standard comparison operators such as < and >. Expressions can be conjoined by the and operator && or the or operator ||. An exclamation mark is the not operator. Parentheses can be used to adjust the standard order of operations.

Guards on state machines are also Boolean expressions and, like simple constraints, are also enclosed within square brackets.

Additional capabilities are being developed in Umple to allow other types of constraints.

Example with simple constraints

// The following demonstrates two simple
// constraints limiting the range of age
// The test code demonstrates that this works
// as expected.
class Client {
  const Integer MinAge =18;
  Integer age;
  [age >= MinAge]
  [age <= 120]
  
  public static void main(String [ ] args) {
    Client c = new Client(40);
    for (int i: new int[]
      {-1,10,17,18,19,50,119,120,122,1000}) 
    {
       System.out.println(
         "Trying to initialize age to "+i);
       System.out.println(c.setAge(i)
         ? "  Success"
         : "  FAILURE");
    }
  }
}

      

Load the above code into UmpleOnline

 

Example with more operators

// Example with a few more operators
class X {
  Integer i;
  Integer j;
  [i > j]
  [i < 5 && j > 0]
  [! (i == 10)]
}
      

Load the above code into UmpleOnline

 

Syntax


// A constraint is an expression optionally be surrounded in round brackets or negated
constraint- : [[constraintBody]] [[linkingOp]]? | [[constraintExpr]] [[linkingOp]]?

//negativeConstraint : ( ! | not ) ( [[constraintName]] | [[constraint]] ) fixed issue1536 'Umple does not parse properly the guards'
negativeConstraint : ( ! | [!constraintNegSymbol:not\s+] ) ( [[constraintName]] | [[constraint]] )

// A constraint body is a constraint expression (possibly with a linking operator such as && or ||).
constraintBody : ( [[constraint]] )

linkingOp- : ( [=andOp:and|&&|&]
    | [[equalityOperator]]
    | [!orOp:(or|\Q||\E)] ) [[linkingOpBody]]

constraintExpr- : [[statemachineExpr]]
    | [[stringExpr]]
    | [[boolExpr]]
    | [[numExpr]]
    | [[associationExpr]]
    | [[genExpr]]
    | [[loneBoolean]]
    | { [!fakeContraint:[^\n]+] }

//must be string
stringExpr : [[stringExprOperator]] | [[stringExprPlain]]

//basically the "other" catagory, contains everything that can be equal to something else
genExpr : [[constraintVariable]] [[equalityOperator]] [[constraintVariable]]

//for floats, doubles and ints
numExpr : [[numberExpression1]]
    | [[numberExpression2]]
    | [[numberExpression3]]
    | [[numberExpression4]]

ordinalOp- : [=greaterOp:greater|>=|=>|=>=]
    | [=lessOp:less|<=|=<|=<=]
    | [=moreOp:larger|>]
    | [=smallerOp:smaller|<]

Preconditions

You can specify basic preconditions in methods as shown below. Like other constraints, they are specified in square brackets. Precondition appears as the first lines of a method and must start with 'pre:'. A precondition can refer to one or more attributes or method arguments. If a precondition is not satisfied when the method is run an exception will be thrown; in Java a RuntimeException is used.

Example

class PotentialVoter {
  Integer age;
  
  int vote(int candidate) {
    [pre: age >= 18]
    [pre: candidate > 0]
    // rest of stuff that we do not interpret
     return 0;
  }
}

      

Load the above code into UmpleOnline

 

Syntax


// Constraints in Umple.
// This is currently under development. Constraint capability is being
// developed in agile increments. The first step, described below,
// allows limiting the values of attributes. Code generation is not currently enabled.
// Constraints may appear in classes (including association classes)
// as well as in states.
precondition : [ [name]? pre : [[constraint]] ]

//queuedMethodDeclaration- : queued [[methodDeclarator]] [[methodThrowsExceptions]]? [[methodBody]]
methodBody- : ( [[codeLangs]] { ( [[precondition]]
    | [[postcondition]]
    | [[assertion]]|[[testCase]] )* [**code] } )+

Model Constraints

Constraints can be used to assert that certain properties of the model are as expected, as shown in the examples below. Associations, attributes and generalizations can be checked.

Why would model constraints be useful, given that a programmer can just inspect the code to see if there are statements declaring the facts in question? The answer is that Umple has sophisticated separation of concerns mechanisms including traits, mixins and mixsets, and the developer may not be completely sure that a given model constraint will always be true. An attribute, for example, might be only introduced into the class in a completely different file or mixset, and the developer may not be certain that the file or mixset is being included. Using a model constraint allows a developer who wants to use that attribute in a method to cause an Umple compilation error if it does not in fact exist, rather than waiting to see if Java code fails to compile.

Below is an example of a model constraint, but there are other examples in the manual pages that give help about the error messages raised by these constraints:

Example

class X {
  // Checks that this class has an association
  // with class Z.
  [model: -- Z]
}

class Y {
  isA X;
  // Verifies that this is a subclass of X
  [model: isA X]
}

class Z {
 a;
 1 -- * X;
 // Verifies that there is an association a
 [model: has a] 
}
      

Load the above code into UmpleOnline

 

Syntax


modelConstraint- : [ model : [[modelConstraintBody]] ]

modelConstraintBody : ( [[modelConstraintBody]] ) [[modelLinkingOp]]?
    | [[modelExpr]] [[modelLinkingOp]]?

modelLinkingOp : ( [=and:&|&&|and|,] | [!or:([|][|]?|or|;)] ) [[modelConstraintBody]]

modelExpr : [~source]? [[modelRelationOp]] [~target]

modelRelationOp- : [[modelRelationOpAssociation]]
    | [[modelRelationOpAttribute]]
    | [[modelRelationOpInheritance]]

modelRelationOpInheritance : [=subclass:isA]
    | [=subclass:subclass|child|>>] ( of )?
    | [=subclass:inherits] ( from )?
    | [=superclass:parent|superclass|<<] ( of )?

modelRelationOpAttribute : [=op:has] ( attribute | attr )? [=classification:named|of]?

modelRelationOpAssociation : [[modelRelationAssociationEnd]]? [=op:--
    |->
    |<-
    |-<@>
    |<@>-] [[modelRelationAssociationEnd]]?

modelRelationAssociationEnd : [!bound:(\d+|[**])] ( .. [!bound:(\d+|[**])] )?

Singleton Pattern

Use the Singleton keyword to mark a class as a singleton class. The code ensures that only one object of the class is instantiated at runtime.

For more details on the Singleton pattern, see this Wikipedia page.

Example

class Airline
{
  singleton;
}
      

Load the above code into UmpleOnline

 

Syntax


softwarePattern- : [[isA]] | [[singleton]] | [[immutable]] | [[keyDefinition]] | [[codeInjection]]

// A class that can have only one instance SingletonPattern
singleton- : [=singleton] ;

Immutable Pattern

Mark a class as immutable to force all its contents to be immutable. The code ensures all attributes and associations can only be set in the constructor, and cannot be modified again subsequently.

The only associations allowed to be immutable are directed associations to other immutable classes.

A class can only be immutable if all its superclasses are also immutable. Declaring a superclass immutable forces its subclasses to be immutable; in other words, immutability is inherited. If the subclasses break immutability constraints (such as the type of attributes allowed), then errors will be raised.

Individual attributes and associations can be marked as immutable instead of the entire class. An attribute can be marked as lazy immutable if it needs to be initialized after the constructor has finished. An immutable class cannot have an association to a non-immutable class.

For more details on the Immutable pattern, see this Wikipedia page.


Immutable class

// A simple example of an immutable class
class Point2D
{
  immutable;
  Float x;
  Float y;
}
      

Load the above code into UmpleOnline

 

Immutable class with reference to another class

// An example of one immutable class making reference to another

class Path
{
  immutable;
  1 -> * Point2D pathElements;
}

class Point2D
{
  immutable;
  Float x;
  Float y;
}

strictness allow 36; // We are OK with this warning
      

Load the above code into UmpleOnline

 

Immutable association

// Example of the declaration of an association to be immutable
// Note that this can be set only the first time
class X {
  Integer id;
  immutable * -> 0..1 Y;
}

class Y {
  immutable;
  someInfo;
}  
      

Load the above code into UmpleOnline

 

Syntax


softwarePattern- : [[isA]] | [[singleton]] | [[immutable]] | [[keyDefinition]] | [[codeInjection]]

// A class that can't be modified when created ImmutablePattern
immutable- : [=immutable] ;

association : [=modifier:immutable]? [[associationEnd]] [=arrow:--
    |->
    |<-
    |><
    |<@>-
    |-<@>] [[associationEnd]] ;

inlineAssociation : [=modifier:immutable]? [[inlineAssociationEnd]] [=arrow:--
    |->
    |<-
    |><
    |<@>-
    |-<@>] [[associationEnd]] ;

derivedAttribute- : [=modifier:immutable
    |settable
    |internal
    |defaulted
    |const
    |fixml]? [[typedName]] = ( [[moreCode]] )+

complexAttribute- : [=unique]? [=lazy]? [=ivar]? [=modifier:immutable
    |settable
    |internal
    |defaulted
    |const
    |fixml]? [[typedName]] (= [**value])? ;

association : association [associationNum];

Delegation Pattern

Delegation is one of the most fundamental patterns, that underpins many more sophisticated patterns found in the Gang of Four book. To simplify code, reduce coupling, and adhere to the 'Law of Demeter', it encourages you to create one-line methods that do nothing other than call methods in neighbouring classes. Other code in your class then calls the delegation methods, rather than also calling the methods in the neighbouring classes. That way, very few methods (just the delegation methods) actually need to traverse associations

In Umple there is no special syntax for delegation, however the notation for derived attributes has the effect of creating delegation methods in the manner shown in the example below.

Delegation methods can also be used to help build occurrences of other patterns such as

Note that delegation methods as shown here are 'read only'. They generate a get method with the name of the derived attribute, not a set method.


Example


// This system has many delegation methods so that information in one class can
// be obtained in a neighbouring class easily. The delegation is created using
// derived attributes, which generate get methods for use by other code.
class Airline {
  code;
  name;
  1 -- * RegularFlight;
}

// A regular flight flies every day and has a flight number and other fixed data.
class RegularFlight {
  Integer number;
  Time depTime;
  * outgoing -- 1 Airport origin;
  * incoming-- 1 Airport destination;
  fullNumber = {getAirline().getCode()+getNumber()}
}

// A specific flight actually has passengers
class SpecificFlight {
  * -- 1 RegularFlight;
  Date depDate;
  
  // Four delegation attributes to save multiple methods in this
  // class from having to traverse the association
  flightNumber = {getRegularFlight().getFullNumber()}
  Airport origin = {getRegularFlight().getOrigin()}
  Airport destination = {getRegularFlight().getDestination()}
  Time plannedDepTime = {getRegularFlight().getDepTime()}
}

// A passenger on a flight
class Booking {
  lazy seat;
  * -- 1 SpecificFlight;
  * -- 1 Passenger;
  
  // Second-level delegation - data comes from RegularFlight
  flightNumber = {getSpecificFlight().getFlightNumber()}
  Airport destination = {getSpecificFlight().getDestination()}
  
  // Simple delegation
  passengerName = {getPassenger().getName()}
  Time plannedDepTime = {getSpecificFlight().getPlannedDepTime()}

  //Simple method using the data gathered by delegation
  public String toString() {
    return getFlightNumber()+" "+getPlannedDepTime()+" "+
      getDestination().getName()+" "+getPassengerName()+" "+getSeat();
  }
}

class Passenger {
  lazy Integer freqFlyerNumber;
  name;
} 

class Airport {
  code;
  name;
 }


// Mixin with main program to test the above
class Airline {
  public static void main(String [ ] args) {
    Airport ott = new Airport("YOW","Ottawa");
    Airport tor = new Airport("YYZ","Toronto Pearson");
    Airline a = new Airline("AO","Air Ottawa");
    RegularFlight r = a.addRegularFlight(100,java.sql.Time.valueOf("13:12:00"),ott,tor);
    SpecificFlight f = r.addSpecificFlight(java.sql.Date.valueOf("2017-03-15"));
    Passenger p = new Passenger("John");
    Booking b = new Booking(f,p);
    System.out.println(b);
  }
}
      

Load the above code into UmpleOnline

 

Keys for Equality and Hashing

In any class you can specify a set of attributes and associations as keys. The associations must have a multiplicity of 1 at the other end. This allows Umple to generate code that defines what objects of the class are equal (they have the same values for the key).

Umple will also generate a hashCode method in any class that has a defined key. This helps when looking up an object in a set.

Place the comma-separated list of key elements in curly brackets, after the word key. If you have multiple key statements, a warning is generated.

Example

class Sport {
  name;
  description;
  code;
  key { code }
}

class League {
  name;
  id;
  geographicalArea;
  * -- 1 Sport;
  Date seasonStart;
  Date seasonEnd;
  key { id }
}

class Team {
  name;
  * -- 1 League;
}

class Player {
  name;
  Integer id;
  key { id }
 }

class PlayerOnTeam {
  Integer year;
  * -- 1 Player;
  * -- 1 Team;
  key { year, player, team }
}

      

Load the above code into UmpleOnline

 

Syntax


softwarePattern- : [[isA]] | [[singleton]] | [[immutable]] | [[keyDefinition]] | [[codeInjection]]

// For equality and hashing KeysforEqualityandHashing
keyDefinition- : [[defaultKey]] | [[key]]

// Keys are used to define quality and hash codes, plus Sql keys.
// See user manual page KeysforEqualityandHashing
defaultKey : key { }

key : key { [keyId] ( , [keyId] )* }

Abstraction Occurrence

When modeling, it is common to encounter situations where there will be objects (abstractions) that need to store information that will not vary among many other objects (occurrences). We want to avoid duplicating the data in each occurrence.

Examples include:

It is an antipattern (i.e. poor design) to use the same class for both abstraction and occurrence. It is also an antipattern to use generalization (i.e. erroneously making the occurence a subclass of the abstraction) because that would result in duplication of data in the attributes of the occurrences. This is often not well-understood by inexperienced modelers.

The solution is to create a one-to-many association between the abstraction class and the association class. Umple provides a built-in pattern to make abstraction-occurrence relationships explicit, although using an ordinary association would be a valid alternative.

To use this pattern, add a use statement to incorporate the built-in AbstractionOccurrence.ump file. Then use isA statements to declare which class is an Abstraction, and which is an occurrence (of which Abstraction). Follow what is show in the second block of code below.

This is one of several patterns in Umple Umple that are built into the language as of 1.32 via a use statement. See the code below.

The Abstraction-Occurrence pattern code that is imported by specifying use lib:AbstractionOccurrence.ump

// Generic pattern for abstractions and occurrences
// In any Umple program say 'use lib:AbstractionOccurrence.ump;' to include this pattern.

// Something that has many occurrences
// Examples include a TV show that has episodes, where the show has a name you don't want to repeat in each episode
// Or a route that has runs, or a published book in a library where there are many copies
trait Abstraction {}

// Something representing occurrences of an abstraction
// where both the abstraction and the occurrences need their own instances
// It is common for modellers to make mistakes and just have one class
// Or to consider the Occurrences as instances of the abstractions, but these are antipatterns
trait Occurrence <Abstraction> {
 * -- 1 Abstraction;
}
      

Load the above code into UmpleOnline

 

Example of the Abstraction-Occurrence pattern to specify a library

/* Example of using builtin Umple
 * Abstraction Occurrence pattern file
*/

use lib:AbstractionOccurrence.ump;

class Author {
 name;
}

class Book {
  isA Abstraction;
  title;
  * -- * Author;
}

class CopyOfBook {
  isA Occurrence <Abstraction = Book>;
  Integer barcode;
}
      

Load the above code into UmpleOnline

 

Player Role

When modeling, it is common to encounter situations where one wants to make multiple subclasses, but can not or should not for various reasons. One reason not to create a subclass is because instances may need to change class as their roles in the system change. Another reason not to create a subclass is because an instance may need to play two or more roles smultaneously.

The solution is to create a Role class and to link it by a many-to-one association to the main class (which we will call the Player class).

To use this pattern, add a use statement to incorporate the built-in PlayerRole.ump file. Then use isA statements to declare which class is a Player, and which is an Role (of which Player). Follow what is show in the second block of code below.

This is one of several patterns in Umple Umple that are built into the language as of 1.32 via a use statement. See the code below.

 

The Player Role pattern code that is imported by specifying use lib:PlayerRole.ump

// Generic pattern for players and roles
// In any Umple program say 'use lib:PlayerRole.ump;' to include this pattern.

// A player is an object that can have many roles
// A person can be an employee and a student
trait Player {}

// A captures some functionality that a player may have
// either temporarily or in conjunction with other roles
trait Role <Player> {
 * -- 1 Player;
}
      

Load the above code into UmpleOnline

 

Example of the Player-Role pattern to specify a system for a child sports team

/* Example of using builtin Umple
 * Player Role pattern
*/

use lib:PlayerRole.ump;

class Person {
 isA Player;
 name;
}

class TeamRole {
  isA Role<Player=Person>;
}

class Athlete {
  isA TeamRole;
}

class Coach {
  isA TeamRole;
}

class ParentOfAthlete
{
  isA TeamRole;
  * -- * Athlete;
}


class SportsTeam {
  nickname;
  * -- * TeamRole;
}

      

Load the above code into UmpleOnline

 

Transportation Pattern A

Transportation systems for airlines, bus networks and train networks have many things in common. This is a high level pattern to capture one way of representing common features of those models.

The pattern consists of traits representing