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

Getting Started

Umple is a technology for Model-Oriented Programming.

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

Umple allows you to do the following things:

  1. Create UML models textually. 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 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 if the generator doesn't create code of the type you would like, you can always embed native (i.e. Java, Php, etc.) methods in the Umple, or else use Umple's aspect oriented capabilities to achieve what you need. As a last resort, you can edit the code generator, since it is open source. As a result the concept of 'round tripping' is obsolete in Umple. You should treat Umple-generated code just lke 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 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 'Select Example'. Each of these 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, instructions on how to edit this manual are here.

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

/*
 * 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

 

Another Example

/*
 * 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

 

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 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 therefore have to ensure that any given Umple file has methods of just one chosen target language (Java, PHP, Ruby. etc.).

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 without warning, with the result that expected functionality in the generated system is missing. You can use the strictness directive to force Umple to warn when this occurs; this can be particularly useful in early development, when the Umple is intended to be only a model

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 assocations, 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 deveop systems that are deplpyed 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 be therefore be grouped together. There are limits to this, however: At the current time, this mechanism does not allow you to override existing elememts, which you might need to do to add a feature. Taken together, these mechanisms allow for a form of product-line development. Umple does, however, have an extra feature, called VML that should assist with this when complete.

@@syntax [[program]] [[comment]] [[directive]] [[useStatement]] [[namespace]] [[entity]]

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 your 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 dont 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:

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

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


      

Load the above code into UmpleOnline

 

Another Example

// 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] */

Types of Directives

Directives appear as the 'main' entries in an Umple file.

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- : [[glossary]]
    | [[generate]]
    | [[distribute]]
    | [[generate_path]]
    | [[filter]]
    | [[useStatement]]
    | [[namespace]]
    | [[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
    |Php
    |RTCpp
    |SimpleCpp
    |Ruby
    |Cpp
    |Json
    |StructureDiagram
    |Yuml
    |Violet
    |Umlet
    |Simulate
    |TextUml
    |Scxml
    |GvStateDiagram
    |GvClassDiagram
    |GvClassTraitDiagram
    |GvEntityRelationshipDiagram
    |Alloy
    |NuSMV
    |Papyrus
    |Ecore
    |Xmi
    |Xtext
    |Sql
    |Umple
    |UmpleSelf
    |USE
    |Test
    |SimpleMetrics
    |Uigu2] ( [=suboptionIndicator:-s
    |--suboption] " [**suboption] " )* ;

generate_path : generate [=language:Java
    |Php
    |RTCpp
    |SimpleCpp
    |Ruby
    |Cpp
    |Json
    |StructureDiagram
    |Yuml
    |Violet
    |Umlet
    |Simulate
    |TextUml
    |Scxml
    |GvStateDiagram
    |GvClassDiagram
    |GvClassTraitDiagram
    |GvEntityRelationshipDiagram
    |Alloy
    |NuSMV
    |Papyrus
    |Ecore
    |Xmi
    |Xtext
    |Sql
    |UmpleSelf
    |USE
    |test] " [**output] " [=override:--override
    |--override-all]? ( [=suboptionIndicator:-s
    |--suboption] " [**suboption] " )* ;

// Use statements allow incorporation of other Umple files. See UseStatements
useStatement : use [use] ;

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

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

Use Statements

Use statements allow you to decompose your system by embedding or referencing other model or program entities (i.e. classes) within your current model.

A model file will only be included once, subsequent "use" commands for the same file will be ignored.

A common technique is 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.

Example

use Core.ump;

      

Load the above code into UmpleOnline

 

Syntax


// Use statements allow incorporation of other Umple files. See UseStatements
useStatement : use [use] ;

Namespace Directives

Namespaces allow you to group similar entities to promote cohesion, as well as reduce the possibility of name collision.

Example

namespace school.admin;

class Faculty{}
class Student{}

namespace elevator.structure;

class Building
{
  1 -- * Classroom;
}

class Classroom{}

      

Load the above code into UmpleOnline

 

Syntax


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

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 intend that the only base language code would 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, and 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. 'expect n' declares that message number n should occur; it is an error if the message does not. This is used in testing to create example cases of message n; an error would be triggered if message n does not appear. 'allow n' is used in the case of errors, to tell the compiler to not actually 'fail', but to report that error as if it was a warning. This is also used in testing to include cases that give message n, without the compiler reporting that it has failed. 'disallow n', where n is a warning, tells the compiler to treat n as if it was an error, and fail the compilation. Some of the above are still under development.

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]] ) ;

Class Definition

A class definition defines an object-oriented class available for use as a type in your system.

To define a class, specify the keyword 'class', followed by the name of the class (starting in a capital letter) and then the body of the class within curly brackets. The body can contain various elements that are listed in the Class Content page.

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


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

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

Load the above code into UmpleOnline

 

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]]
    | [[distributable]]
    | [[proxyPattern]]
    | [[classDefinition]]
    | [[trace]]
    | [[emitMethod]]
    | [[templateAttributeDefinition]]
    | [[primitiveDefinition]]
    | [[portDefinition]]
    | [[portBindingDefinition]]
    | [[position]]
    | [[displayColor]]
    | [[abstract]]
    | [[keyDefinition]]
    | [[softwarePattern]]
    | [[depend]]
    | [[symmetricReflexiveAssociation]]
    | [[attribute]]
    | [[stateMachine]]
    | [[activeMethodDefinition]]
    | [[inlineAssociation]]
    | [[concreteMethodDeclaration]]
    | [[constantDeclaration]]
    | [[modelConstraint]]
    | [[invariant]]
    | ;
    | [[enumerationDefinition]]
    | [[exception]]
    | [[extraCode]]

interface Definition

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

Umple currently supports Java, PHP and Ruby as native languages.

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

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]]
    | [[constantDeclaration]]
    | [[constantDeclarationDeprecated]]
    | [[abstractMethodDeclaration]]
    | [[position]]
    | [[displayColor]]
    | [[isA]]
    | [[distributableInterface]]
    | [[exception]]
    | [[extraCode]]

Class Content

A class can contain any of the following items. Interfaces are limited to those indicated.

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 generatlization, 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

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

class Student
{
  isA Person;
  Integer number;
}
      

Load the above code into UmpleOnline

 

Another Example

// 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] ;

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

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());

  // 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.
  // Note that currently in Umple the space before and after the =
  // is required.
  defaulted r = "";
}

      

Load the above code into UmpleOnline

 

Syntax


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

simpleAttribute- : [~name] ;

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

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 examples illustrate the data types available for Umple attributes. Except as specified, they will generate primitive datatypes in Java

Example


class Demo 
{
  Integer i;
  Float flt;
  String str;  // the default of no type is specified
  Double dbl;
  Boolean bln;
  Date dte; // In Java. uses the java.sql.Date class
  Time tme; // In Java. uses the java.sql.Time class
}

      

Load the above code into UmpleOnline

 

Another Example


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 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. We may in future add a capability to Umple to ensure this cannot happen.

In the examples below, we show how using attribute notation is very simular 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
// 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

 

Another Example


// 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 Example

// 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, you can have attribute with multiple values.

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

Example

class Office {
   Integer number;
   Phone[] installedTelephones;
} 

class Phone {
  String digits;
  String callerID;
}


      

Load the above code into UmpleOnline

 

Syntax


complexAttribute- : [=unique]? [=lazy]? [=ivar]? [=modifier:immutable
    |settable
    |internal
    |defaulted
    |const
    |fixml]? [[typedName]] (= [**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

 

Another Example

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]] )+

Aspects of attributes under development

The unique keyword currently generates no code. In future the intent is that it will force all values of an attribute in your running program to be different.

If you discover any other problems or have requests please add an issue at bugs.umple.org.

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

 

Another Example

// 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

 

Another Example

// 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

 

Another Example

// 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 the an association refers to a non-existent class.

@@example @@source manualexamples/AssociationDefinition1.ump @@endexample

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.

 

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'
// 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

 

Another Example

// 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

 

Another Example

// 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).
// These 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 the any class. Contrast this with the Umple code showing the same model with inline associations.

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]] | [[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

 

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.

 

Example

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

      

Load the above code into UmpleOnline

 

Another Example

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

      

Load the above code into UmpleOnline

 

Another Example

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

      

Load the above code into UmpleOnline

 

Another Example

// 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

class Vehicle {}

class Wheel {}

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

      

Load the above code into UmpleOnline

 

Another Example

class Vehicle {}

class Wheel {}

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

      

Load the above code into UmpleOnline

 

Another Example

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

class Wheel {}

      

Load the above code into UmpleOnline

 

Another Example

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 specialiations, 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 most of the items found in an ordinary class. However it always has two or more 1..many associations to other classes. These are syntactically shown as just a multiplicity (usually *, but 1..* and similar cases are allowed) followed by the name of the participating class (and an optional role name).

Example

// 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

 

Another Example

// The following shows the same example as using a regular class
// Instead of an association class
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

 

Another Example

// 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 position 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

 

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]]
    | [[classDefinition]]
    | [[position]]
    | [[displayColor]]
    | [[invariant]]
    | [[softwarePattern]]
    | [[depend]]
    | [[singleAssociationEnd]]
    | [[stateMachine]]
    | [[attribute]]
    | [[association]]
    | [[inlineAssociation]]
    | ;
    | [[extraCode]]

singleAssociationEnd : [[multiplicity]] [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 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().

At the time of writing, there remain several issues: For now, you should avoid having two sorted associations in the same class.

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.

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

 

Syntax


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

isSorted- : sorted { [priority] }

Basic State Machines

A state machine has a fixed set of of values (called states) The state machine transitions from state to state by the occurrence of events. State machines are very useful for quickly defining a program's behaviour.

In Umple, a state machine is modeled as a special type of attribute. In any class, simply specify the state machine name, and follow the name by a block starting with '{' and ending with '}'. This indicates to Umple that you are defining a state machine, and not an ordinary attribute.

Within the block, you list the names of the various states. Each state is followed by a block, again indicated using '{' to start and '} to end. This block defines the details of a state.

Details of each state can include:

Note that, in addition, you can specify code to be executed whenever an event is processed by using before or after directives.

The following diagram shows a garage door state machine as a UML diagram. The Umple code for this is at the bottom of this page. Note that UmpleOnline currently cannot draw state machines. state machne for garage door  

Example


// This example shows a simple state machine without any actions or guards
//
// In the following, status is a state machine, and acts like an
// attributes, whose value is set by various events.
//
// Open, Closing, Closed, Opening and HalfOpen are the possible
// values, or states, of status.
//
// buttonOrObstacle, reachBottom and reachTop are events. These
// become generated methods that can be called to cause a state
// change.
//
// To make the state diagram appear in UmpleOnline, select 'Options'
// then choose 'GraphViz State Diagram'
class GarageDoor
{
   status {
      Open { buttonOrObstacle -> Closing;  }
      Closing {
          buttonOrObstacle -> Opening;
          reachBottom -> Closed;
      }
      Closed { buttonOrObstacle -> Opening; }
      Opening {
          buttonOrObstacle -> HalfOpen;
          reachTop -> Open;
      }
      HalfOpen { buttonOrObstacle -> Opening; }
  }
}


      

Load the above code into UmpleOnline

 

Another Example

// This is a more fully-featured state machine for
// a garage door corresponding to the diagram above
class Garage {
  lazy Boolean entranceClear=true;
  GarageDoor { 
    Closed {
      entry/{stopMotor();}  
      entry/{triggerEnergySaveMode();}
      exit/ {triggerNormalEnergyMode();}
      pressButton -> /{turnLightOn();} Opening; 
    }
    Opening {
      entry/{runMotorForward();}
      openingCompleted -> Open;
    }
    Open {
      entry/{stopMotor();}
      // do {wait(60000); turnLightOff();}
      pressButton [getEntranceClear()] -> Closing;
    }
    Closing {
      entry/{runMotorInReverse();}
      closingCompleted -> Closed;
      pressButton -> /{flashLightOn();} Opening; 
    }
  }
  
  boolean runMotorInReverse() {
     System.out.println("Running motor in reverse");
    return true;
  }
  
  boolean flashLightOn() {
     System.out.println("Flashing light on");
    return true;
  }

  boolean turnLightOn() {
     System.out.println("Turning light on");
    return true;
  }
  
   boolean turnLightOff() {
     System.out.println("Turning light off");
    return true;
  }
  
  boolean runMotorForward() {
     System.out.println("Running motor forwards");
    return true;
  }

  boolean triggerEnergySaveMode() {
     System.out.println("Triggering Energy Saving Mode");
    return true;
  }

  boolean stopMotor() {
     System.out.println("Stopping motor");
    return true;
  }

  boolean triggerNormalEnergyMode() {
     System.out.println("Triggering Normal Energy Mode");
         return true;
  }
  
  boolean waitawhile() {
    System.out.println("Waiting");
    return true;
  }
  
  boolean test() {
          System.out.println("Testing");
         return true;
  }
  
}

      

Load the above code into UmpleOnline

 

Syntax


stateMachine : [[enum]]
    | [[inlineStateMachine]]
    | [[referencedStateMachine]]
    | [[activeDefinition]]

//Issue 148
inlineStateMachine : [=queued]? [=pooled]? [~name] { ( [[comment]]
    | [[state]]
    | [[trace]]
    | [=||]
    | [[standAloneTransition]])* }

// An enum is a state machine that has no events
// stateName is prefixed with ~ to match alphanumeric names only.
// This is needed to solve issue 399, which is cause when a terminating } is parsed as part of the statename.
enum : [~name:key] { [~stateName]? (, [~stateName])* }

state : [=final]? [stateName] { [[stateInternal]]* }

stateEntity- : [=||]
    | [[entryOrExitAction]]
    | [[autoTransition]]
    | [[transition]]
    | [[activity]]
    | [[state]]
    | [[trace]]
    | ;

autoTransition : [[activity]]? [[autoTransitionBlock]]

// Autotransitions have no event. The transition is immediately taken
// or taken after the do activity ends[[guard]]? -> [[action]]?
// The action can come before or after the arrow
autoTransitionBlock- : [[guard]]? ( [[action]] -> | -> [[action]] | -> ) [stateName] ;

// A transition guard can come before or after the arrow
// The order of guard and event definition can also be interchanged
transition : ( [[eventDefinition]] [[guard]]
    | [[guard]] [[eventDefinition]]
    | [=unspecified]? [[guard]]
    | [[eventDefinition]])? ( [[action]] ->
    | -> [[action]]
    | -> ) [stateName] ;

eventDefinition- : [[afterEveryEvent]] | [[afterEvent]] | [~event] ( [[parameterList]] )?

// The timer in a timed event can be an number, variable, function() or function(num)
afterEveryEvent- : afterEvery ( [!timer:[+*/a-zA-Z0-9_\.-]+(\([0-9\.]*\))?] )

afterEvent- : after ( [!timer:[+*/a-zA-Z0-9_\.-]+(\([0-9\.]*\))?] )

// An action can be executed on a transition, or on entry or exit
action : / [[moreCode]]+

entryOrExitAction : [=type:entry|exit] / [[moreCode]]+

// A do activity is long-lasting and can be interrupted
activity : do [[moreCode]]+

guard : [ [[constraint]] ]

State Machine Actions and Do Activities

When an transition is taken, an action can occur. This is indicated using a slash "/" followed by arbitrary code in braces.

Similarly, when entering or exiting a state, an action can occur. This is indicated using the keywords entry or exit, followed by a slash, followed by code.

The actions described above should take negligible time to execute.

If a longer-running computation or activity should run while in a state, encode this using the keyword do, followed by code. In languages such as Java that support it, a thread will be started to invoke the thread. This allows the state machine to 'stay live' and be able to respond to other events, even while the do activity is running. Note that at the current time, the do activity thread must terminate itself; as an enhancement, the do activity thread should be interrupted and cancelled when a transition is taken out of the state.

Example


namespace example;

class LightFixture
{
  bulb
  {
    On {
      entry / { doEntry(); }
      exit / { doExit(); }
      push -> /{ doTransition(); } Off;
      do { doThisContinuouslyWhileOn(); }
    }
    Off {}
  }

  void doEntry() {System.out.println("Entry");}
  void doExit() {System.out.println("Exit");}
  void doTransition() {System.out.println("Transition");}
  void doThisContinuouslyWhileOn() {
    while (true) {
      System.out.println("Still on");
      try {
        Thread.sleep(1000);
      }
      catch (InterruptedException e) {}
    }
  }
}


      

Load the above code into UmpleOnline

 

Another Example

// This demonstrates that actions can be different in different target languages
class DemoSM
{
  Integer id;
  sm {
    s1 {
      e1 / Java {id=5;} Php {$id=5;} -> s2;
    }
    s2 {
    }
  }
}


      

Load the above code into UmpleOnline

 

Syntax


// An action can be executed on a transition, or on entry or exit
action : / [[moreCode]]+

entryOrExitAction : [=type:entry|exit] / [[moreCode]]+

// A do activity is long-lasting and can be interrupted
activity : do [[moreCode]]+

Nested State Machines

State machined can be nested inside another. This often allows for simpler Umple (or UML) notation, since events that need to cause effects in every substate of the outer state do not have to be repeated in each of the substates.

The first example below illustrates nesting abstractly. The next example shows nesting in a concrete example. The third example is the same as the second, but with no nesting, to illustrate the difference.

Example


// Illustration of nested states. Event e1 will take the system into
// state s2, and its first substrate s2a. Event e2 directly goes to s2b.
// Event e3 toggles between s2b and s2a. Event e1 when in s2, goes to s1

class A {
  sm {
     s1 {
        e1 -> s2;
        e2 -> s2b;
     }
     s2 {
        e1 -> s1;
        s2a {
          e3 -> s2b;
        }
        s2b {
          e3 -> s2a;
        }
     }
  }
}


      

Load the above code into UmpleOnline

 

Another Example

// Example showing nested states.

class Course {
  code;
  description;
  1 -- * CourseSection;
}

class CourseSection
{
  // Example from Lethbridge and Laganiere: Object Oriented Software
  // Engineering: Practical Software Development using UML and Java
  // McGraw Hill, 2005  www.lloseng.com

  sectionId;
  Integer classSize = 0;
  Integer minimumClassSize = 10;
  Integer maximumClassSize = 100;
  
  // State machine controlling status
  status
  {
    Planned {
      openRegistration -> NotEnoughStudents;
    }
    Open {
      cancel -> Cancelled;
      NotEnoughStudents {
        closeRegistration -> Cancelled;
        register [getClassSize() > getMinimumClassSize()] -> EnoughStudents;
      }
      EnoughStudents {
        closeRegistration -> Closed;
        register [getClassSize() > getMaximumClassSize()] -> Closed;
      }
    }
    Cancelled {}
    Closed {}
  }

  boolean requestToRegister(Student aStudent)
  {
    register();
    return setClassSize(getClassSize()+1);
  }
}

class Student {
  //Remainder of this class defined elsewhere
}
      

Load the above code into UmpleOnline

 

Another Example

// Example with an opportunity to nest states, to avoid repeating
// transitions

class Course {
  code;
  description;
  1 -- * CourseSection;
}

class CourseSection
{
  // Example from Lethbridge and Laganiere: Object Oriented Software
  // Engineering: Practical Software Development using UML and Java
  // McGraw Hill, 2005  www.lloseng.com

  sectionId;
  Integer classSize = 0;
  Integer minimumClassSize = 10;
  Integer maximumClassSize = 100;
  
  // State machine controlling status
  status
  {
    Planned {
      openRegistration -> OpenNotEnoughStudents;
    }
    OpenNotEnoughStudents {
      closeRegistration -> Cancelled;
      cancel -> Cancelled;
      register [getClassSize() > getMinimumClassSize()] -> OpenEnoughStudents;
    }
    OpenEnoughStudents {
      closeRegistration -> Closed;
      cancel -> Cancelled;
      register [getClassSize() > getMaximumClassSize()] -> Closed;
    }
    Cancelled {}
    Closed {}
  }

  boolean requestToRegister(Student aStudent)
  {
    register();
    return setClassSize(getClassSize()+1);
  }
}

class Student {
  // Remainder of class defined elsewhere
}
      

Load the above code into UmpleOnline

 

Final States

In Umple, there are two ways to define final states.

The first way is to use the "Final" keyword. This automatically defines a final state for the top-level state machine. Once the state machine is in this state, it is considered to be complete, and it is terminated. The "Final" keyword can be used as shown in the example below. Note, if a user defines a state named "Final", error E074 User Defined State Cannot be Named Final will be thrown.

The second way is to use the "final" keyword. Using this keyword allows users to define final states as shown below. In the case of concurrent state machines, all state machines within the same concurrent region must be in their final states before the enclosing region is considered to be complete. In the case of non-concurrent state machines, as soon as a final state is entered, the state machine is considered to be complete.

Example

// Using the keyword "Final" automatically defines the 
// final state for the top-level state machine "sm"

class X {
  sm {
    s1 {
      goToS2 -> s2;
    }
    s2 {
      goToFinal -> Final;
    }
  }
}
      

Load the above code into UmpleOnline

 

Another Example

// "s1" is an orthogonal region, and it is considered to be complete when
// all of the concurrent state machines are in their final states
// (i.e. s2 is in state "s4", s5 is in state "s7", and s8 is in state "s10")

class X {
  sm {
    s1 {
      s2 {
        s3 {
         goToS4 -> s4;
        }
        final s4 { }
      }
      ||
      s5 { 
        s6 {
          goToS7 -> s7;
        }
        final s7 { }
      }
      ||
      s8 {
        s9 {
          goToS10 -> s10;
        }
        final s10 { }
      }
    }
  }
}
      

Load the above code into UmpleOnline

 

Another Example

// "sm" will be considered as complete when
// it is in either state "s3" or "s5"

class X {
  sm {
    s1 {
      s2 {
        goToS3 -> s3;
        goToS4 -> s4;
      }
      final s3 { }
    }
    s4 {
      goToS5 -> s5;
      final s5 { }
    }
  }
}
      

Load the above code into UmpleOnline

 

Auto-Transitions

It is possible to arrange for a state machine to transition automatically from one state to the next immediately after completing entry actions or upon completion of a do activity. This is specified using a transition without any preceding event. Such transitions may have guards and transition actions.

Example


// In this example, the system will transition to s2 automatically
// when the do activity ends
class X {
  sm {
    s1 {
      entry / {
        System.out.println("Starting first sleep");
      }
      do {
        Thread.sleep(2000);
        System.out.println("Ending first sleep");
      }
      -> s2;
    }
    s2 {
      entry / {
        System.out.println("Starting second sleep");
      }
      do {
        Thread.sleep(2000);
        System.out.println("Ending second sleep");
      }
    }
  }
  public static void main(String [ ] args) {
    X x = new X();
  }
}


      

Load the above code into UmpleOnline

 

Syntax


autoTransition : [[activity]]? [[autoTransitionBlock]]

// Autotransitions have no event. The transition is immediately taken
// or taken after the do activity ends[[guard]]? -> [[action]]?
// The action can come before or after the arrow
autoTransitionBlock- : [[guard]]? ( [[action]] -> | -> [[action]] | -> ) [stateName] ;

Timed Transitions

A transition can be triggered after a specified delay (a floating point value, given in seconds). The transition will be taken after the delay provided the object is still in the state and any guard is true. This is accomplished using the 'after' keyword.

The 'afterEvery' keyword, tries to trigger a transition repeatedly at a specified interval while the object remains in the state.

Example


// In this example, the system will transition to state b
// after a 1-second delay
class X {
  sm {
    a {
      entry / {System.out.println("entering a");}
      after(1) -> b;
    }
    b {
      entry / {System.out.println("entering b");}
    }
  }
  public static void main(String [ ] args) {
    X x = new X();
  }
}


      

Load the above code into UmpleOnline

 

Another Example

// In this example, the system will transition to state b
// when the value of the attribute count drops below 5
// An attempt to make this transition is taken every second
// The do activity slowly drops the value of count
class X 
{
  Integer count = 10;
  sm 
  {
    a 
    {
      entry / { System.out.println("entering a"); }
      do 
      {
        while (count > 0) 
        {
          System.out.println("Count = " + count);
          Thread.sleep(1000);
          count --;
        }
      }
      afterEvery(1) [count<5] -> b;
    }
    b 
    {
      entry / { System.out.println("entering b"); }
    }
  }

  public static void main(String [] args) 
  {
    X x = new X();
  }
}


      

Load the above code into UmpleOnline

 

Syntax


// The timer in a timed event can be an number, variable, function() or function(num)
afterEveryEvent- : afterEvery ( [!timer:[+*/a-zA-Z0-9_\.-]+(\([0-9\.]*\))?] )

afterEvent- : after ( [!timer:[+*/a-zA-Z0-9_\.-]+(\([0-9\.]*\))?] )

Events With Parameters

An event can have a parameter (of any valid type that the generated language can accept). The generated event method will have this parameter. The value of the parameter can be used in guards or transition actions.

It is absolutely necessary that all events with the same name have the same parameter type, or else an error will be raised.

Example


// The do activity of the first state machine is a thread that
// communicates with the second state machine.
// It calls the event method e with different arguments.
// The second state machine only changes state when the
// guard detects that the argument is valid
// The argument is also used in the transition action code.
class X {
  stateMachine1 {
    s1a {
      do {
        // This do activity sends events to stateMachine1
        e(5);
        Thread.sleep(1000);
        e(6);
        Thread.sleep(1000);
        e(7);
        Thread.sleep(1000);
        e(8);
      }
      -> s1b;
    }
    s1b {}
  } 
  stateMachine2 {
    s2a {
      entry / {System.out.println("s2a");}
      e(int a) [a > 6] / {System.out.println("e"+a);} -> s2b;
    }
    s2b {
      entry / {System.out.println("s2b");}
      e(int a) / {System.out.println("e"+a);} -> s2a;
    }
  }
  public static void main(String [ ] args) {
    X x = new X();
  }
}


      

Load the above code into UmpleOnline

 

Syntax


Queued State Machines

Standard state machines operate in a single thread. When an event method is called, the state machine code that runs continues the same thread of the caller. This can be satisfactory for simple applications, but it doesn't work in multi-threaded environments, and can also result in deadlocks.

To overcome the above problems, a state machine may be declared as 'queued' by just placing the keyword queued before the declaration of the state machine. In a queued state machine, the calls to the event methods simply add a record to the queue, and then return. The calling thread can then continue and do other activities. A separate thread exists in each state machine to take events off the queue and process them, in the order they are received.

A queued state machine will process events in the same order as a regular state machine. See also pooled state machines for a variation on this semantics.

Example


// Test of queued state machines.
// The word queued results in a thread being created to process events.

class TestSM {
  queued sm{
    s1 {
      e1 /{System.out.println("e1");} ->s2;
    }
    s2 {
      e2 /{System.out.println("e2");} ->s3;
    }
    s3 {
      e3 /{System.out.println("e3");} ->s4;
    }
    s4 {
      e4 /{System.out.println("e4");} ->s1;
    }
  }
  
  public static  void main(String [] ags){
    TestSM test=new TestSM();
    test.e1(); // processed s2
    test.e2(); // processed s3
    test.e3(); // processed s4
    test.e4(); // processed s1

    test.e1(); // processed s2
    test.e3(); // queued: ignored  pooled: left in queue, until we are next in s3
    test.e4(); //      pooled: left in queue, until next in s4
    test.e2(); //      pooled: processed goes to s3
               //      pooled: process e3 from queue goes to s4
               //      pooled: process s4 from queue goes to s1
    test.e1(); 
    test.e3(); 
    test.e2(); 
    test.e4();
    
    test.e1();
    test.e2();
    test.e3();
    test.e4();

    test.e1();
    test.e2();
    test.e4();
    test.e3();
    test.e4();

    test.e1();
    test.e3();
    test.e2();
    test.e3();
    test.e1();
    test.e4();

    test.e2();
    test.e1();
    test.e2();

  }
}


      

Load the above code into UmpleOnline

 

Syntax


//Issue 148
inlineStateMachine : [=queued]? [=pooled]? [~name] { ( [[comment]]
    | [[state]]
    | [[trace]]
    | [=||]
    | [[standAloneTransition]])* }

Pooled State Machines

Queued and regular state machines always process events in the order they arrive, and ignore events that cannot be handled in the current state. Sometimes, however, you want to 'save' events that arrive out of sequence, and process them as soon you enter a state that can handle them. This is accomplished by adding the word 'pooled' before a state machine definition.

In a pooled state machine there is a queue in a separate thread, just like in a queued state machine, however, if the next event to be processed has no handler in the current state, then it remains at the front of the queue, and the queue processor looks further back in the queue for the first event that can be handled.

A queued state machine will therefore often process events in a different order from a regular state machine.

Example


// Test of pooled state machines.
// The word pooled results in a thread being created to process events, and
// 'pooled' semantics being employed. Events which cannot be handled are kept waiting
// until entry into a state where they can be handled.

class TestSM {
   String ev="";
   pooled sm{
    s1 {
      e1 /{ev="e1";} ->s2;
      e5 /{ev="e5";} ->s2;
    }
    s2 {
      e2 /{ev="e2";} ->s3;
    }
    s3 {
      e3 /{ev="e3";} ->s4;
    }
    s4 {
      e4 /{ev="e4";} ->s1;
    }
  }
  after e* {
    if(wasEventProcessed)
      System.out.println(ev);
  }
  
  public static  void main(String [] ags){
    TestSM test=new TestSM();
    test.e1(); // processed s2
    test.e5(); // Will only be processed in the pooled case (eventually)
    test.e2(); // processed s3
    test.e3(); // processed s4
    test.e4(); // processed s1

    test.e1(); // processed s2
    test.e3(); // queued: ignored  pooled: left in queue, until we are next in s3
    test.e4(); //      pooled: left in queue, until next in s4
    test.e2(); //      pooled: processed goes to s3
               //      pooled: process e3 from queue goes to s4
               //      pooled: process s4 from queue goes to s1
    test.e1(); 
    test.e3(); 
    test.e2(); 
    test.e4();
    
    test.e1();
    test.e2();
    test.e3();
    test.e4();

    test.e1();
    test.e2();
    test.e4();
    test.e3();
    test.e4();

    test.e1();
    test.e3();
    test.e2();
    test.e3();
    test.e1();
    test.e4();

    test.e2();
    test.e1();
    test.e2();

  }
}


      

Load the above code into UmpleOnline

 

Syntax


//Issue 148
inlineStateMachine : [=queued]? [=pooled]? [~name] { ( [[comment]]
    | [[state]]
    | [[trace]]
    | [=||]
    | [[standAloneTransition]])* }

Method Definition

The Umple language allows a developer to extend the functionality of a class with arbitrary methods written the natively compiled language (e.g. Java, Php or Ruby).

Within these arbitrary methods, a developer may call generated methods that access the Umple attributes, associations and state machines. To determine what API methods are available to be called by methods, refer to the API reference or generate Javadoc from an Umple file using UmpleOnline.

A standard Umple method will specify the return type, then the name, then the argument list and finally the method body in curly brackets. The generated output for the method will use correct format for the generated language and will be public.

Example

generate Java;

// A class with a method displayName() that has no arguments
class Person
{
  name;
  
  String displayName()
  {
    return("Hello, my name is " + getName());
  }
}

      

Load the above code into UmpleOnline

 

Another Example

generate Java;

// A class with a method that has arguments
class Person
{
  name;
  
  String displayName(String greeting, String property)
  {
    return(
      greeting +
      ", my " +
      property +
      " is " +
      getName());
  }
}


      

Load the above code into UmpleOnline

 

Another Example

generate Java;

// A class with a method that uses 'public'.
class Person
{
  name;
  
  public String displayName()
  {
    return("Hello, my name is " + getName());
  }
}

      

Load the above code into UmpleOnline

 

Syntax


// Methods: The code in concrete methods is passed to the base language
// See user manual page MethodDefinition
concreteMethodDeclaration : [=modifier:public|protected|private]? [=static]? [type]? [[methodDeclarator]] [[methodThrowsExceptions]]? [[methodBody]]
    | [=modifier:public|protected]? [=abstract] [type]? [[methodDeclarator]] [[methodThrowsExceptions]]? ;

methodDeclarator : [methodName] [[parameterList]]

parameterList : ( ([[parameter]] ( , [[parameter]] )* )? )

parameter : [[typedName]]

Alternative Languages

In Umple, the body of a method will by default be emitted unchanged. This ties the model to the particular programming language. However it is possible to provide alternative implementations for different programming languages by preceding the method body with the language name.

This multi-lingual capability also works for other places where native code is injected such as in state machine guards and actions, or in derived attributes.

Example

// Generating Java and Php the following will result in the appropriate 
// method body being selected.
class LanguageSpecific {
  int m1() Java {
    // Return 1 if the model is compiled into Java
    return 1;
  }
  Php {
     // Return 0 if the model is compiled into Php
    return 0;
  }
}

      

Load the above code into UmpleOnline

 

Another Example

// A method body may work for several languages.
// If no language is specified it is taken as the default.
class LanguageSpecific {
  int m1()
  Java,Php {
    // Return 0 if the model is compiled into Java or Php
    return 0;
  }
  {
    // Default implementation for other languages
    return 1;
  }
}

      

Load the above code into UmpleOnline

 

Traits

A trait is a group of functionality that serves as building blocks for classes. A trait implements such functionality through methods, state machines, and other modeling elements used for modeling behavior. Traits require a set of functionality which is defined by required methods. These required methods must be provided by clients of traits, either directly or indirectly. Clients of traits can be classes and other traits. In other words, a trait is a partial description of a class that can be reused in several different classes. In other words, a trait is a partial description of a class that can be reused in several different classes.

Traits can be used in place of standard inheritance where there is already a superclass, since multiple inheritance is not allowed in Umple to be consistent with Java and several other languages. Traits can be used to inject attributes, associations, state machines, constraints, methods and many other elements. They are one of several approaches in Umple to separation of concerns. The others are the mixin ability (ability to specify a class several times and have the elements added together), and the aspect oriented capabilities. Note that traits themselves are subject to being mixed in. You can declare two parts of the same trait in two different places in an Umple system.

Umple traits are defined through the keyword 'trait' followed by a unique name and a pair of curly brackets. The name must be alphanumeric and start with an alpha character, or the symbol (underscore). We also recommend capitalizing the first letter of traits names, as is the case for classes and interfaces in Umple. All elements of traits are defined inside the curly brackets except template parameters defined between the name and the curly brackets. In the current version, Umple traits can have methods, attributes, state machines, template parameters, required interfaces, and associations. Furthermore, Umple traits cannot be used as a type.

Required methods are defined similarly to the way abstract methods are defined in classes. They have exactly the same syntax, but it is also possible in traits to define required methods without the keyword abstract. If a method is defined like a normal method without a body (or implementation), the Umple compiler will consider that as a required method.

Provided methods are defined in the same way as concrete methods are defined in classes. Indeed, they have exactly the same syntax and semantics. Provided methods also support multiple code blocks, for generation of systems in different languages.

Traits are not part of UML. A UML class diagram drawn from an Umple file containing traits will 'flatten' the traits. The trait elements will appear in all classes that include that trait. In the first example below, the name and address attribute will appear in the class diagram of both Person and Company

The example 2 below shows a trait called TEquality. It has a required methods named isEqual and a provided method named isNotEqual. The provided methods uses the required method to satisfy part of its functionality.

Example

/*
 Example 1: use of a trait in Umple
 The trait has regular attributes, derived attribute  
 and a method that are copied into Organization  
 and Company  
*/
trait Identifiable {
  firstName;
  lastName;
  address;
  phoneNumber;
  fullName = {firstName + " " + lastName}
  Boolean isLongName() { return lastName.length() > 1;}  
}
class Person {
  isA Identifiable;
}
class Organization {
  Integer registrationNumber;
}
class Company {
  isA Organization, Identifiable;
}

      

Load the above code into UmpleOnline

 

Another Example

/*
	Example 2: showing a trait designed for comparison regarding if two objects are equal or not.
*/
trait TEquality{
  Boolean isEqual(Object object);
  Boolean isNotEqual(Object object){ 
    return isEqual(object) ? true : false;
  }
} 

      

Load the above code into UmpleOnline

 

Syntax


traitDefinition : trait [name] [[traitParameters]]? { [[traitContent]]* }

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

Clients of Traits

Traits are used by clients (classes and traits) by specifying the keyword 'isA' followed by their names and a semi-colon. Traits cannot use themselves (even through several uses in a cyclic manner). When clients specify names of traits for use, those traits must exist in the system. If a trait uses more than one trait, it can separate them by comma or use the keyword 'isA' for each one.

In the example 1 below, trait T2 uses trait T1 defined in line 10 and class C2 uses trait T2 defined in line 20. Clients can use other traits if they satisfy their required methods. Satisfaction of required methods is performed by having exactly the same methods implemented in clients. For example, trait T2 uses trait T1 and so it is required to have the required methods of trait T1 implemented in trait T2. Trait T2 achieves this through implementing two methods named method1() and method2() defined in lines 12 and 13.

Trait T2 is not a final client, therefore, it could use trait T1 without implementing those required methods, in that case, the required methods of trait T2 would be method1(), method2(), and method 3(). Class C2, which is a final client, uses trait T2 and therefore needs to implement its required method, which is method3(). However, there is no direct implementation for it. Instead, class C2 obtains such an implementation indirectly from its superclass, which is C1. Therefore, it satisfies the required method of trait T2.

When clients use traits, they obtain all provided methods defined in the traits. This includes all other provided methods those traits might obtain from their own used traits. For example, trait T2 gets the provided method method4() from trait T1. This provided method can be called by all other provided methods defined in trait T2. Therefore trait T2 provides three provided methods named method1(), method2(), and method4(). Class C2 uses trait T2 and so it obtains all provided methods.

Please consider that it is allowed for abstract classes to use traits without satisfying their required methods. If this is the case, the required methods of traits will be considered as abstract methods for the abstract class. Then, all subclasses of the abstract class are required to implement those abstract methods. This process ensures that required methods will finally be implemented. It is worth noting that interfaces cannot use traits because they cannot have concrete methods in their definitions.

Example

/*
  Example 1: showing how traits can be used by their clients.
*/
trait T1{
  abstract void method1();
  abstract void method2();
  void method4(){/*implementation*/ }
}
trait T2{
  isA T1;
  void method3();
  void method1(){/*implementation*/ }
  void method2(){/*implementation*/ }
}
class C1{
  void method3(){/*implementation*/ }
}
class C2{
  isA C1;
  isA T2;
  void method2(){/*implementation*/ }
}

      

Load the above code into UmpleOnline

 

Attributes in Traits

Attributes in traits are defined in the same way they are defined for classes. Traits also support all modifiers that can be applied to attributes. The example 1 below shows the way attributes can be defined and used in traits.

As seen, there is a trait named Identifiable that has five attributes: first-Name, lastName, address, phoneNumber, and fullName. It also has a provided method named isLongName(). There are no required methods because the trait offers pure functionality to its clients. Class Person uses trait Identifiable and obtains the provided method and defined attributes from the trait. Class Company also uses the trait Identifiable and extends class Organization. It obtains both attributes coming from its superclass and used trait. All attributes are flattened similar to the way provided methods are flattened.

When clients use traits, a name conflict might happen because a client might have an attribute and obtains a new attribute with the same name from a trait. Modelers are responsible to resolve the conflict. The conflict is detected automatically. Unlike conflicts with other elements in traits, in the current implementation of our work, there is no operator to resolve an attribute name clash conflict. Our current recommendation is to change the name of attributes in the clients of traits and avoid changing names in traits because this could break other clients of those traits.

Another way to avoid conflicts is to use stateless traits. In that case, traits use required methods to have access to states (attributes). The example 2 below shows trait T1 uses two required methods getData() and setData(Integer) to have access and write to the attribute data of type Integer. It also has a provided method that uses the method getData() to obtain the value of the attribute data. Then, it performs some operation on it (in this case adding 2 to the value,) and finally uses the method setData(Integer) to save the new value into the attribute data. The class C1 uses trait T1 and has the attribute data. Since Umple automatically generates accessor and mutators for attributes, they satisfy the required methods defined in trait T1 and so there is no need to implement them manually in class C1.

Example

/*
 Example 1: use of a trait in Umple
 The trait has regular attributes, derived attribute  
 and a method that are copied into Organization  
 and Company  
*/
trait Identifiable {
  firstName;
  lastName;
  address;
  phoneNumber;
  fullName = {firstName + " " + lastName}
  Boolean isLongName() { return lastName.length() > 1;}  
}
class Person {
  isA Identifiable;
}
class Organization {
  Integer registrationNumber;
}
class Company {
  isA Organization, Identifiable;
}

      

Load the above code into UmpleOnline

 

Another Example

/*
 Example 2: showing how states in traits can be obtained by required methods.
*/
trait T1{
  Integer getData();
  void setData(Integer);
  Integer processData(){
    int data = getData();
    data=data+2;
    setData(data);
  }
}
class C1{
  Integer data;
  isA T1;
}

      

Load the above code into UmpleOnline

 

Trait Template Parameters

Template parameters at the modeling level are combined with other modeling elements like associations. This combination increases modularity and reusability to an extent that is not achievable at the implementation level. Template parameters can be referred to in required and provided methods and attributes. Traits can have template parameters with generic or primitive data types. The difference in their use is that it is possible to put restrictions on bound types of generically-typed parameters. Such, restrictions might include a declaration that the interfaces or classes must be extended or implemented by other specific classes. These restrictions are only available for generic-type parameters because primitive types cannot implement or extend any other types and so there is no way of imposing such constraints on them.

Template parameters are defined after the name of a traits inside a pair of angle brackets. Each parameter has a name and they are separated by a comma. Restrictions on the templates applied in the same manner Umple allows extending and implementing interfaces and classes respectively. In other words, the keyword 'isA' is used after the name of a template parameter followed by the name of interfaces or a class. If there are more than one interface or one interface and one class they are separated by the symbol '&'.

When clients use traits, they must bind types to their parameters and also types must satisfy their restrictions. Values are bound through the symbol '=', in the manner values are generally assigned to attributes. The bindings are performed inside a pair of angle brackets, each one separated by a comma. Therefore, when a client uses a trait with template parameters, they need to extend the normal way of using traits by having angle brackets appearing after the name of traits.

The example 1 below shows how template parameters can be defined and used. It depicts a trait called T1 (line 4) with one template parameter named TP. The template parameter is restricted to implement the interface I1, defined in line 8. The restriction is applied to make sure a correct type will be bound to the template parameter. Trait T1 has a required method named method2() with a return and a parameter of type TP (which is a template parameter). Furthermore, it has a provided method named method3() with a parameter of type TP.

Class C1 defined in line 11 uses trait T1 and assigns class C1 as a binding type to TP. Since class C1 has already implemented interface I1 (line 12), the type is acceptable. Class C1 needs to implement the required method of trait T1, but it must be performed based on the type assigned to the template parameter TP. Therefore, class C1 implements method2() with the correct data type (which is C1) for the parameter and return types. Line 15 shows the exact signature of the implemented method. In the same manner, the provided method obtained is also adapted based on the binding value. The same process is adopted for class C2, but it binds C2 to the parameter TP and so the required method method2() needs to be implemented with type C2. The provided method obtained is based on type C2. There is a method called method1() for classes C1 and C2 that implement interface I1. They have the same signature but different implementations.

Since a trait can use other traits, a trait with template parameters can use other traits with template parameters. Therefore, traits can bind a template parameter to another template parameter to achieve better flexibility. This is performed in the same manner a type is bound to a template parameter. Furthermore, template parameters are modulated for each trait so it is possible for a trait with template parameters to use other traits with the same names for their template parameters.

The example 2 below shows how one template parameter is bound to another one. Trait T1 has the template parameter TP used to define the type of parameter for the provided method method2(). Trait T2 has the template parameter TP used to define the type of parameter for the provided method method3(). It also uses trait T1 and binds its own template parameter to traits T1’s template parameter (line 9). Note that trait T2 can also bind any other types to the template parameter TP, if it is required. Finally, class C1 uses trait T2 and binds String to the template parameter TP (line 13)

Umple introduces a special syntax to allow having template parameters that can be substituted in code blocks. For template parameters to operate on code in code blocks, they need to be encompassed within a pair of the symbol '#'. This ensures that the dedicated Umple scanner (i.e. not a full code parser) will be able to detect strings matching the template parameters correctly and replace them with binding values.

The example 3 shows how a template parameter is used in the body of a method. As seen, trait T1 has a template parameter named TP (line 4). The provided method method2() needs to return a string which is a combination of calling the required method method1() and a method named process() from the template parameter TP. In the body of the provided method method2(), an instance of the template parameter needs to be created so as to call the method process(). This is achieved by having the name of template parameter encompassed by '#' in places that require types (line 7). The rest needs to follow the syntax of the language used to implement the code blocks, in this case, Java. Class C2 uses trait T1 and binds class C1 to the template parameter TP (line 15). It also implements the required method method1() in order to able to use the trait.

Example

/*
	Example 1: showing how template parameters in traits are defined and used.
*/
trait T1< TP isA I1 > {
  abstract TP method2(TP data);
  String method3(TP data){ /*implementation*/ }
}	
interface I1{
  void method1();
}
class C1{
  isA I1; 
  isA T1<TP = C1>;
  void method1(){/*implementation*/}	
  C1 method2(C1 data){ /*implementation*/ }
}
class C2{
  isA I1;
  isA T1< TP = C2 >;
  void method1(){/*implementation*/}
  C2 method2(C2 data){ /*implementation*/ }
}

      

Load the above code into UmpleOnline

 

Another Example

/*
	Example 2: showing how one template parameter in a trait is bound to another one.
*/
trait T1<TP>{
  void method1();
  void method2(TP data) {/*implementation*/}
}
trait T2<TP>{
  isA T1< TP = TP >;
  void method3(TP Data) {/*implementation*/}
}
class C1{
  isA T2< TP = String >;
  void method1(){/*implementation*/}
}

      

Load the above code into UmpleOnline

 

Another Example

/*
	Example 3: showing how template parameters in traits are used in code blocks.
*/
trait T1 <TP>{
  String method1();
  String method2(){
    #TP# instance = new #TP#();
    return method1() +":"+instance.process();
  }
}
class C1{
  String process(){/*implementation*/}
}
class C2{
  isA T1< TP = C1 >;
  String method1(){/*implementation*/ }
}

      

Load the above code into UmpleOnline

 

Syntax


traitParameters : < [[traitFullParameters]] ( , [[traitFullParameters]] )* >

traitFullParameters : [~parameter] ([[traitParametersInterface]])? ( = [~defaultType] )?

traitParametersInterface- : isA [~tInterface]( & [~tInterface])*

Associations in Traits

An association is a useful mechanism at the modeling level that specifies relationships among instances of classifiers. An association implies the presence of certain variables and provided methods in both associated classifiers.

Associations are defined in the same way they are defined for classes. Traits can make associations with interfaces, classes, and template parameters. If one end of the association is a template parameter, the binding type must be checked to make sure it is compatible with the type of the association. For example, if a trait has a bidirectional association with a template parameter, the binding value cannot be an interface and it must be a class. This is an extra constraint applied to template parameters.

When an association is defined, APIs (set of methods) are generated in the class to allow such actions as adding, deleting and querying links of associations. Traits may use these APIs inside provided methods to achieve their needed implementation. The Example below depicts a simple version of the observer pattern implemented based on traits. As can be seen in line 7, the concept of the subject in the observer pattern has been implemented as trait Subject, which gets its observer as a template parameter. A direct association has been defined in trait Subject (Line 8), which has a multiplicity of zero or one on the Subject side and zero or many on the Observer side. This association lets each subject have many observers and it also applies the case in which observers do not need to know the subject. The trait has encapsulated the association between the subject and observers and then applies it to proper elements when it is used by a client.

As each subject must have a notification mechanism to let observers know about changes, there is a provided method notifyObservers() for this. This method obtains access to all observers through the association. Two classes Dashboard and Sensor play the roles of observer and subject. Class Dashboard has a method named update(Sensor) (line 2) used by the future subject to update it. Class Sensor obtains the feature of being a subject through using trait Subject and binding Dashboard to parameter Observer

Example

/*
  Example 1: implementing observable pattern with traits and associations.
*/
class Dashboard{
  void update (Sensor sensor){ /*implementation*/ }
}
class Sensor{
  isA Subject< Observer = Dashboard >;
}
trait Subject <Observer>{
  0..1  -> * Observer;
  void notifyObservers() { /*implementation*/ }
}
      

Load the above code into UmpleOnline

 

Required Interfaces of Traits

Required functionality of classic traits is defined in terms of required methods. However, there are shortcomings with this approach. The first shortcoming is that there is no way to reuse a list of required methods. For example, consider a case in which there are traits that happen to have the same set of required methods but different provided methods. In this case, there is duplication due to repeated listing of the same methods. Furthermore, if there are several traits that must always have the same list of required methods, an inconsistency could be introduced in the design by changing just one of them and not all.

From a different perspective, another shortcoming appears when we know the clients of traits and that they must implement certain interfaces in order to have a correct implementation for the required methods. In fact, there is no way to put dependencies at the semantics level on clients through traits because required methods are simply syntactically captured. This suggests that it might be a good idea to put a restriction on clients that specifies the interfaces they must implement. Such a restriction would ensure that traits are not used in clients that just happen to have methods with the same signature. This is important because having reusable elements which work correctly with minimum errors should be the designers’ responsibility and not the user’s.

In order to address these issues, required interfaces can be used. Using these, traits can either put extra restrictions on clients or just manage their required methods in a more modular and reusable way. Traits may use already-existing interfaces or new interfaces may be written to accomplish the desired modularization. Furthermore, developers will be able to create a hierarchy of interfaces to optimize the reusability. Traits define their required interfaces through the keyword 'isA' followed by the name of interfaces and a semi-colon. When a class use traits, it needs to implement the required interfaces of those traits. If a trait uses other traits with required interfaces, those required interfaces are added to the set of required interfaces of the trait and final clients are required to implement all of those required interfaces.

The example 1 below shows how required interfaces are used and applied. There is a hierarchical design for required methods in terms of interfaces, making it reusable and consistent. Traits T1 and T2 have the same required interface (lines 13 and 17) and if there is a modification in the required interface it will be applied to both. Classes C1 and C2 have to implement interfaces I1 (Line 28) and I2 (line 31) to be able to use trait T1 and T2.

Example

/*
	Example 1: showing how required interfaces in traits are defined and used.
*/
interface I1{
  void method1();
  double method2();
}
interface I2 {
  isA I1;
  Boolean method3();
}
trait T1{
  isA I1;
  Float method3(){/*implementation*/ }	
}
trait T2{
  isA I1;
  Float method4(){/*implementation*/ }	
}
trait T3{
  isA T1,T2;
}
class C3{
  void method1(){/*implementation*/ }
  Double method2(){/*implementation*/ }
}
class C1{
  isA C3, I1, T1;
}
class C2 {
  isA C3, I2, T3;
  Boolean method3(){/*implementation*/ }
}

      

Load the above code into UmpleOnline

 

State Machines in Traits

A trait can have zero or many state machines, each with a unique name. The definition of state machines in traits follows the same rules and constraints that exist for them in classes. The example 1 shows a trait called T1 (lines 4-13) with two state machines sm1 (lines 5-8) and sm2 (lines 9-12). Use of trait T1 in class C1 results in class C1 having those two state machines as native state machines. In general, if a class already has state machines with completely distinct names to those being introduced via traits, the introduced state machines are just ‘flattened’ into the class, i.e. they are treated as though they were coded directly in the class.

Introduced machines that have names duplicating existing state machine names are composed (merged) with the existing machines, and the resulting composed machines are flattened into the class. The same concept is applied when traits are used by other traits. The example 2 expresses the same model designed in the example 1, in which class C1 has two state machines, but it uses trait T2 (line 18) to obtain the same state machine. Trait T2 provides state machine sm2 from its own definition (lines 12-15) and state machine sm1 from trait T1 (line 11). This use of traits by other traits allows building more complex traits (and hence more complex state machines) from simpler ones.

State machines in traits are considered as provided functionality. More concretely, any event in a state machine is considered as a provided method, and so can satisfy the required methods of used traits. State machines are supposed to encapsulate their own actions and guards so they can be reused as a piece of functionality. For example, a guard can be defined as a reference to an attribute in the trait or to a parameter of the event, so when the state machine is reused the attribute and parameter are reused as well. The same perspective is true for actions. In real world cases, state machines may need to obtain those conditions and actions from the context (e.g. clients) in which they are reused. State machines hence require those conditions and actions to behave correctly. This requirement is in alignment with the notion of required methods of traits. Therefore, required actions and guards of state machines can be expressed as required methods of traits. Indeed, if events of state machines are considered as provided methods and their guards and actions are considered as required methods, then state machines can define functional behavior and therefore the required behavior of them can again be satisfied by other state machines in the clients. It should be noted that if guards, actions, and activities of state machines are defined as methods (not inline code blocks directly in the state machine), they are not anymore required methods. They will be treated as provided methods, and traits’ rules related to provided methods will be applied to them

The example 3 shows how required methods are satisfied by events of state machines. As seen, trait T1 has two required methods, m1(String) and m2(), called in actions of transitions e1(string) and e2 in states s1 and s2 of state machine sm1 respectively. Class C1 uses trait T1 and must satisfy those required methods. Class C1 does not have any concrete method to satisfy the required methods, but it has state machine sm2. State machine sm2 has two event m1(String) and m2 which satisfy the required methods of trait T1. If state machines are used to satisfy the required methods, there is a limitation in return types of required methods. All required methods must have Boolean as their return types, otherwise, events cannot satisfy them. The reason for this limitation is that all event automatically obtain Boolean as their return types by the Umple compiler.

Like the way template parameters defined in traits are used for required and provided methods, they can also be used in collaboration with state machines. Template parameters can be used to define the types of parameters for events. They can also be used in code blocks related to actions and activities. The example 4 illustrates how template parameters can be used with events of state machines. State machine sm in trait T1 has two events. Event e1 has a parameter of type TP (line 6) and event e2 has two parameters with types TP and String (line 7). Class C2 uses trait T1 (line 12) and binds class C1 to the template parameters TP.

Example

/*
	Example 1: showing how state machines are defined and used in traits.
*/
trait T1 {
  sm1{
  s0 {e1-> s1;}
  s1 {e0-> s0;}
}
sm2{
  s0 {e1-> s1;}
  s1 {e0-> s0;}
}
}
class C1 {
  isA T1;
}

      

Load the above code into UmpleOnline

 

Another Example

/*
	Example 2: showing how state machines are defined through different traits.
*/
trait T1 {
  sm1{
  s0 {e1-> s1;}
  s1 {e0-> s0;}
  }
}
trait T2 {
  isA T1;
  sm2{
  s0 {e1-> s1;}
  s1 {e0-> s0;}
  }
}
class C1 {
  isA T2;
}

      

Load the above code into UmpleOnline

 

Another Example

/*
	Example 3:showing how required methods of traits are satisfied by events of state machines.
*/
trait T1{
  Boolean m1(String input);
  Boolean m2();
  sm1{
    s1{ e1(String data) -> /{ m1(data); } s2;   }
    s2{ e2 -> /{ m2(); } s1; }
  }
}
class C1{
  isA T1;
  sm2{
    s1{ m1(String str) -> s2;}
    s2{ m2 ->  s1;}
  }
}
      

Load the above code into UmpleOnline

 

Another Example

/*
	Example 4: showing how template parameters in traits are used inside state machines.
*/
trait T1<TP>{
  sm{
  s1{ e1(TP p1)-> s2; }
    s2{ e2(String p1, TP p2) -> s1; }
  }
}  
class C1{/*implementation*/}
class C2{
  isA T1<TP=C1>;
}
      

Load the above code into UmpleOnline

 

Method Operators in Traits

Operators are capabilities that allow resolving the conflicts and also managing the granularity of traits. Operators are applied to traits when traits are used by clients. Clients can apply more than one operator to a specific trait, but those operators need to be compatible with each other. There is no sequence in the way operators are applied. Operators are defined inside angle brackets after the name of traits and can be mixed with binding types to template parameters. The general structure by which a client uses operators is as follows:

isA TName < Operator1, Operator2, …, Operatorn >

TName specifies the name of a trait to which each Operatori,i=1..n is applied. There is no limitation on the number of operations that can be applied to a trait. Two operators with the same functionality can only be applied to different elements. Errors resulting from violations of this are detected and reported to the modeler. Note that all processes related to the flattening and composition algorithm are performed after applying the operators.

If traits have template parameters and those template parameters have been used as types in provided methods (or event of state machines), their types do not affect the signature of provided methods referred to by operators. In other words, types of template parameters are applied to traits after operators are applied. The identification factor for selecting a provided method is its signature. However, the return type of provided methods is not used for identification because the name and list of types of parameters can uniquely differentiate each provided method from others. When parameters of provided methods are specified, there is no need to define the name of parameters

Removing/keeping provided methods

This operator allows removing or keeping provided methods of a trait. The syntax for this operator is as follows:

(+|-) methodName(argumentTypes)

The symbol – indicates removing while the symbol + indicates keeping. The symbol must precede the signature of the provided method. When the symbol – is applied to a provided method of a trait, it removes the method from the set of provided methods. However, when the symbol + is applied to a provided method of a trait, the provided method is kept and the rest are removed. Please consider that multiple keeping operators can be used together to keep several methods and throw away the rest.

The example 1 below shows how class C1 removes the provided methods method2() and method3() (line 12) while class C2 keeps the provided method method5(), coming from trait T1 (line 16). As seen, class C1 obtains two provided methods method4() and method5() in addition to the method1() which satisfies the required methods of trait T1. Class C2 just has the provided method method5() in addition to method1().

Renaming (Aliasing)

The renaming operator allows changing the name of provided methods and also their visibilities. This operator can also be mixed partially with the keeping operator to provide better flexibility. The operator does not allow changing the types of parameters or number of parameters. The reason is that the provided methods might be used by other provided methods and so any change regarding types and numbers can break traits. The current implementation of the operator does not support renaming recursive methods. The syntax for this operator is as follows:

(+) methodName(argumentTypes) as newName

The example 2 shows this operator in action. Class C1 uses trait T1 (line 12) and renames its provided method method1() to function2. There is no need to specify parentheses for the new name. Class C2 uses trait T1 (line 16) and while it renames provided method3() to function3, it also changes the visibility of the provided method to be private. Finally, class C3 uses trait T1 and renames the provided method method5(Integer) to function5. However, it also forces other provided methods of trait T1 to be removed. This feature can be really useful if there is a utility trait and we are just interested in a provided method with the name that suits our domain.

Example

/*
	Example 1: showing how the operator "Removing/keeping provided methods" works.
*/
trait T1{
  abstract method1(); 
  void method2(){/*implementation*/}
  void method3(){/*implementation*/}
  void method4(){/*implementation*/}
  void method5(){/*implementation*/}
}
class C1{
  isA T1<-method2() , -method3()>;
  void method1() {/*implementation related to C1*/}
}
class C2{
  isA T1<+method5()>;
  void method1() {/*implementation related to C2*/}
}
      

Load the above code into UmpleOnline

 

Another Example

/*
	Example 2: showing how the operator "Renaming (Aliasing) provided methods" works.
*/
trait T1{
  abstract method1(); 
  void method2(){/*implementation*/}
  void method3(){/*implementation*/}
  void method4(){/*implementation*/}
  void method5(Integer data){/* implementation*/}
}
class C1{
  isA T1< method2() as function2 >;
  void method1() {/*implementation related to C1*/}
}
class C2{
  isA T1< method3() as private function3 >;
  void method1() {/*implementation related to C2*/}
}
class C3{
  isA T1< +method5(Integer) as function5 >;
  void method1() {/*implementation related to C3*/}
}
      

Load the above code into UmpleOnline

 

Syntax


iEFunction : [=modifier:+|-] [~methodName] [[iEParameterList]]

functionAliasName : [=modifier:+]? ( ( [~smName]
    | [!smPattern:\d+|[**]]) .)? [~methodName] [[iEParameterList]] as [[IEVisibilityAlias]]

State Machine Operators in Traits

As with operators on methods, certain operators can be applied to traits’ state machines when they are used in clients . These provide mechanisms to improve flexibility, assign state machines to specific states, and resolve conflicts caused by name collisions. These operators follow the same structure defined for operators on methods.

Changing the name of a state machine

This operator is used to change the name of a state machine when it is to be reused by a client. This operator can also be mixed partially with the keeping operator to provide better flexibility. The syntax for this operator is as follow:

(+) stateMachineName as newName

When a state machine with a given name is specified by the renaming operator, it must be available in the trait being operated on, either directly in the trait or another trait used by the trait. The example 1 shows how names of state machines in trait T1 can be changed to mach1 and mach2. As seen, in example 1 both state machines that are available directly in trait T1 have been renamed. The example 2 shows how class C1 uses the operator to rename the state machine sm1 in trait T1 and also automatically remove other state machines, which are just state machine sm2 in this case.

There are two main scenarios for this operator. The first is merging: when a client already has a state machine and will obtain another state machine coming from the used trait. The two machines might have some of the same states but different functionality. The client wants to have all functionality merged in one state machine (described as we progress). In this case, the operator is used to change the name of the incoming state machine from the trait, to match the name of the existing state machine. The result is that the new functionality will be merged into the existing state machine. The second scenario is for avoiding conflicts. This occurs when a client has an existing state machine and wants to incorporate another one with different functionality, but that happens to have the same name. In this case, the client can change the name of the incoming state machine to be different from the existing state machine. This second scenario can be needed in various conflict-resolution scenarios

Changing the Name of a State

This operator changes the name of a state inside a specific state machine. The operator covers both simple and composite states. The syntax used for this purpose is as follows:

stateMachineName.stateName.....stateName as newName

The state to be renamed is specified based on a series of names separated by dots, starting with the name of the state machine. If the state is a simple or composite state at the top level of a hierarchical state machine, then it comes directly after the name of the state machine. However, if it is deeper in the hierarchy, the chain of parents must also be specified. The last name in the series is always the name of the state to be renamed. In example 3, trait T1 has a state machine with a composite state named s0 (line 6). Composite state s0 has two internal states s11 and s12. Class C1 uses trait T1 and changes the name of state s0 to state0 and the name of s11 to state11 (line 15). In order to specify the state s0, it is preceded by the name of a state machine, which is sm. For state s11, the name of the state machine, the composite state, and the region name precede it. In Umple, the name of the single region inside a composite state is set automatically to the name of the composite state. The operator applies also the same rule when it changes a composite state.

The first scenario for this operator is to change the vocabulary used for the names of states. This adds flexibility when a trait is specified in a generalized context and there is a need to adapt names so as to be more domain-specific. E.g. ‘tripEnded’ in a general transportation state machine becomes ‘landed’ in an adaptation to the airline domain, or ‘docked’ in an adaptation to the water transport domain. The second scenario is when two states need to be merged, but they have different names. By changing the name of one so it matches the other, then the algorithm knows to merge them. The third scenario occurs when there are two states in a state machine to be composed, but we want to keep those two states separate and prevent merging.

Changing the name of regions

This operator allows renaming a specified region. It is just like the operator used for changing the name of states. The difference is that the last name in the sequential series of names (separated by dots) is the name of a region to be changed. Since names of regions are set automatically by the Umple compiler and they are equal to the names of their initial states, renaming the name of a region must also be applied to its initial state. This is performed automatically by the operator. The applications for this operator are like those for changing the name of states. In particular, this operator is used when several regions are supposed to be merged or kept separate.

Change the name of events

This operator is used to change the name of events that will trigger transitions in state machines. The syntax used for this operator is as follows:

(* | stateMachineName).eventName(argumentTypes) as new_Name

Through this operator, it is possible to rename an event related to a specific state machine or all state machines in a trait. For the first case, the modeler specifies the name of the state machine (stateMachineName). For the second case, an asterisk (*) is specified. The event name (eventName) must end with a pair of parentheses including any needed argument types. This operator does not allow changing the argument types because that would break the implementation of the event method. The operator is used mostly to change the event names based on a new domain’s requirements. It can also be used to keep an event from being overwritten by the client’s state machine and vice versa.

In example 4, trait T1 has two state machines sm1 and sm2. These state machines have common events named e1(Integer) and e0(). Class C1 want to use trait T1 with some changes in the name of events. It is required to rename all event names e0() to event0() and just change the event name e1(Integer) to event1() in state machine s1. Line 15 depicts how class C1 achieves it. Since the change on event e0() is going to happen in both the state machines, the symbol * has been used. However, the name of state machine sm1 was used for the event e1(Integer) because we do not want to have it changed in state machine sm2.

Example

/*
	Example 1: showing how the operator "Changing the name of a state machine" works.
*/
trait T1 {
  sm1{
    s0 {e1-> s1;}
    s1 {e0-> s0;}
  }
  sm2{
    s0 {e1-> s1;}
    s1 {e0-> s0;}
  }
}
class C1 {
 isA T1<sm1 as mach1, sm2 as mach2>;
}
      

Load the above code into UmpleOnline

 

Another Example

/*
	Example 2: showing how the operator "Changing the name of a state machine" works.
*/
trait T1 {
  sm1{
    s0 {e1-> s1;}
    s1 {e0-> s0;}
  }
  sm2{
    s0 {e1-> s1;}
    s1 {e0-> s0;}
  }
}
class C1 {
 isA T1<+sm1 as mach1>;
}

      

Load the above code into UmpleOnline

 

Another Example

/*
	Example 3: showing how the operator "Changing the name of a state" works.
*/
trait T1 {
  sm{
    s0{
      e1-> s1;
      s11{ e12-> s12; }
      s12{ e11-> s11; }   
    }
    s1{ e0-> s1;  }  
  }
}
class C1 {
  isA T1<sm.s0 as state0, sm.s0.s0.s11 as state11>;
}

      

Load the above code into UmpleOnline

 

Another Example

/*
	Example 4: showing how the operator "Change the name of events" works.
*/
trait T1 {
  sm1{
    s0 {e1(Integer index)-> s1;}
  s1 {e0-> s0;}
}
sm2{
    t0 {e1(Integer index)-> t1;}
  t1 {e0-> t0;}
}
}
class C1 {
  isA T1<sm1.e1(Integer) as event1, *.e0() as event0>;
}

      

Load the above code into UmpleOnline

 

Syntax


functionAliasName : [=modifier:+]? ( ( [~smName]
    | [!smPattern:\d+|[**]]) .)? [~methodName] [[iEParameterList]] as [[IEVisibilityAlias]]

Selecting Operators

As with operators on methods, certain operators can be applied to traits’ state machines when they are used in clients. These provide mechanisms to improve flexibility, assign state machines to specific states, and resolve conflicts caused by name collisions. These operators follow the same structure defined for operators on methods.

Removing/keeping a state machine

This operator is used to remove or keep a state machine when a client uses a trait. In the removing mode, specified by the minus symbol '-', the indicated state machine is ignored and is not included in the client. In the keeping mode, specified by '+', only the indicated state machine is kept and the others are ignored. This operator can be used to keep the client free of unneeded detail or conflict. The syntax used for this operator is as follows:

(-|+) stateMachineName

In example 5, trait T1 has three state machines sm1, sm2, and sm3. Classes C1 requires state machine sm2 and sm3 while class C2 requires just state machine sm2. Class C1 achieves this through removing state machine sm1 from trait T1 (line 16). Class C2 obtains its required state machine through keeping just state machine sm2 (line 19). Classes C2 could also achieve the same result through removing sm1 and sm2. Using the keeping operator is more convenient when there are several state machines and modelers need just one them.

Removing/keeping a state

This operator is used to remove or keep a simple or composite state when using a state machine in a trait. The syntax for this operator is as follows:

(-|+) stateMachineName.stateName.....stateName

This works much like removing/keeping a state machine, using a minus sign for removing and a plus for keeping. The symbols are followed by the name of the state. In the removing mode, this operation will delete all incoming and outgoing transitions of the state as well. In the keeping mode, the specified state will be kept and the remaining states will be removed. This also includes removing all transitions from other states to the specified state. This mode can be applied to the initial states, but if it is applied to other states, the initial state will not be removed. The operator is helpful for cases in which base state machines do not need the functionality of that specific state, or have the same state and do not want to merge it with the one coming from the reused trait. Another use is when clients use more than one trait and those traits have common state machines and states. These common states might have different functionality and clients might want to keep one version.

In example 6, trait T1 has state machine sm1 (line5). Class C1 uses trait T1 and removes state s2 from the state machine sm1 (line 25). As seen, in addition to the state s2, all outgoing transitions (named e2()) from states s0, s1, and s3 have been removed. The operator also removed incoming transition e3() from state s2 to state s3. Class C2 uses trait T1 and requires just state s1 of state machine sm1. As seen, all other states except s0 have been removed. The reason is that state s0 is the initial state of state machine sm1 and removing it results in non-reachable states. The Umple compiler does not allow this situation. Furthermore, all transitions coming from other states to s1 have been removed (in this case, there is none) except transitions coming from the initial state s0. The operator also removes the outgoing transitions e2() and e3() of state s1 to other states s2 and s3 except the ones going to the initial state (in this case, there is none).

Removing/keeping a region

This operator is used to remove or keep a region of a state machine. The syntax used for this operator is exactly like the one defined for removing or keeping a state, except the last name in the dot-separated chain specifies the name of the region. This operator is utilized in cases similar to those explained for removing a state. It can also be used to make a composite state a simple state by reducing the number of regions to zero.

In example 7, two classes C1 and C2 uses trait T1 and manipulate its state machine’s regions. State machine sm has a composite state s1 with three regions r1, r2, and r3. Class C1 removes region r1 from the composite state s1 (line 23) while class C2 keeps region r2 (line 26). As seen in both cases, the region name appears after the name of state machine sm and the state s1. We can see since region r1 has been removed in class C1, the incoming transition e2() has also been removed automatically. In class C2, all outgoing transition from region r2 to other regions, including e2() and e4(), have been removed automatically in addition to region r1 and r3.

Removing/keeping a transition

This operator is used to remove or keep a transition from a state machine. The syntax for this operator is as follows:

(-|+) stateMachineName.stateName.....stateName.((eventName(argumentTypes) ([guard])?) | [guard?])

A minus symbol is followed by a transition that needs to be removed. A plus symbol is used to pick a transition to keep. A transition is defined by specifying the name of the state machine, states (including regions for nested states), event, and guard. The symbol '?' is not part of the operator and it is there to show which elements are optional. The name of the state machine and states are mandatory. The event name (along with its arguments) depends on the type of transition.

If the transition is 'auto' (immediately taken on entry to the state or upon completion of a do activity) there is no need to specify it, otherwise, it must be specified. If a transition has a guard, it must be specified using the same syntax used when specifying transitions (inside square brackets). However, if a transition is auto and unguarded, it must be defined with an empty guard "[]" and without any event name. Actions and destination states are not part of the definition for this operator because the above definition suffices to uniquely select any transition. The operator is utilized when base state machines do not need a specific transition coming from the used trait. Furthermore, base state machines might want to extend a transition of a state, but it might already have a transition matching the given specification.

In example 8, class C1 uses trait T1 (line 25) and keeps the transition with the event name e2(Integer) from the state machine sm and state s1. Other transitions related to the state s1, which are e3() and e4(), are removed. Since the transition does not have a guard, brackets are not required in the specification of the transition. Class C2 also uses trait T1 (line 28), but it removes the transition with the event name e4() and a guard on the variable cond from the state machine sm and state s1. This case shows how a transition with the event name and guard can be specified. Class C3 uses trait T2, but it removes an auto transition from state s2 with a guard on the variable cond. As seen, no name has been defined in the operator for the event and the guard is just defined inside brackets. Finally, class C4 use the trait T1 (line 34), but it removes an auto transition without a guard. As seen, an empty bracket after the name of the state is used to specify the transition.

Example

/*
	Example 5: showing how the operator "Removing/keeping a state machine" works.
*/
trait T1 {
  sm1{
    s0 { e0-> s0;}
  }
sm2{
    t0 { e0-> t0;}
  }
sm3{
    w0 { e0-> w0;}
  }
}
class C1 {
  isA T1<-sm1>;
}
class C2 {
  isA T1<+sm2>;
}

      

Load the above code into UmpleOnline

 

Another Example

/*
	Example 6: showing how the operator "Removing/keeping a state" works.
*/
trait T1 {
  sm1{
    s0 { 
      e1-> s1;
      e2-> s2;
    }
    s1 { 
      e2-> s2;
      e3-> s3;
    }
    s2 { 
      e3-> s3;
      e2-> s2;
    }
    s3 { 
      e0-> s0;
      e2-> s2;
    }  
  }
}
class C1 {
  isA T1<-sm1.s2>;
}
class C2 {
  isA T1<+sm1.s1>;
}


      

Load the above code into UmpleOnline

 

Another Example

/*
	Example 7: showing how the operator "Removing/keeping a region" works.
*/
trait T1{
  sm {
    s1{
      r1{ e1-> r11; }
      r11{}
      ||
      r2{
        e2-> r11;
        e3-> r21;
        e4-> r31;
      }
      r21{}
      ||
      r3{e5->r31; }
      r31{}
    }
  }
}
class C1{
  isA T1<-sm.s1.r1>;
}
class C2{
  isA T1<+sm.s1.r2>;
}



      

Load the above code into UmpleOnline

 

Another Example

/*
	Example 8: showing how the operator "Removing/keeping a transition" works.
*/
trait T1{
  internal Boolean cond;
  sm {
    s1{
      e2(Integer i)-> s2;
      e3[!cond]-> s3;
      e4[cond]-> s4;
    }
    s2{
      [cond] -> s3;
      [!cond]-> s4;
    }
    s3{ 
      -> s1;
    }
    s4{
     -> s1;
    }
  }
}
class C1{
  isA T1<+sm.s1.e2(Integer)>;
}
class C2{
  isA T1<-sm.s1.e4()[cond]>;
}
class C3{
  isA T1<-sm.s2.[cond]>;
}
class C4{
  isA T1<-sm.s3.[]>;
}
      

Load the above code into UmpleOnline

 

Syntax


//| [[StateMachineTransitionAlias]]
StateMachineAliasName : ([=iEStateMachineModifier:+])? [~smName] ([[StateNames]])? as [~smDesName] ([[DesStateNames]])?

//iEStateMachine : [=iEStateMachineModifier:+|-] [~smName] [[StateNames]]?
iEStateMachine : [=modifier:+|-] [~smName] ( [[StateNames]] ( ( [[iEParameterList]] [[guardOption]]? )
    | ( . [[guardOption]] ) )? )?

Extending a State

This operator is used to assign a state machine to a specific state inside another state machine, hence turning that state into a composite state. The syntax used for this operator is as follows:

srcStateMachineName as desStateMachineName.stateName.....stateName

This operator involves two state machines. The srcStateMachineName is found in the trait, and the desStateMachineName is found in the client. The state in the client can be simle or composite. This operator provides a practical mechanism to incrementally compose a state machine from various parts. For example, simple 'on/off' pairs of states with events to toggle between are fairly common and can be injected easily into destination states using this operator. If a composited state is extended with this operator, it will trigger our composition algorithm which. Furthermore, the operator can be used to bring more than one state machine inside a state.

In example 9, class C1 has state machine sm with two states s1 and s2. Trait T1 has state machine sm1. Class C1 needs to have state machine sm1 activated when it is in state s2. Class C1 achieves this by specifying the source state machine and destination state when it uses trait T1 (line 15).

Example

/*
	Example 9: showing how the operator "Extending a state by adding a state machine to it" works.
*/
trait T1{
  sm1{    
    m1{
      t2-> m2;
    }
    m2{
      t1-> m1;
    }
  }
}
class C1{
  isA T1<sm1 as sm.s2>;
  sm{
    s1{
      e2-> s2; 
    }
    s2{
      e1-> s1;
    }
  }
}

      

Load the above code into UmpleOnline

 

Traits and Umple Mixins

In the same way Umple supports mixins to compose classes, traits can also be composed in this way. This means that a trait can be defined in several places or files and when they are used by clients, all elements defined in those separate places will be applied to clients.

The example 1 depicts two definitions for trait T1 (lines 4 and 8). Class C1 uses trait T1 and implement the required method method1() and also obtains two provided methods method2() and method3().

Example

/*
	Example 1: showing how traits are combined with Umple mixins.
*/
trait T1{
  void method1();
  void method2(){/*impl… */ }
}
trait T1{
  void method3(){/*impl… */ }
}
class C1{
  isA T1;
  void method1(){/*impl… */ }    
}

      

Load the above code into UmpleOnline

 

Flattening of Traits

A system modeled with traits can be transformed to a compatible model without traits. This process is called flattening. Traits are flattened to clients when they are used by clients, so it would also be beneficial to be able to instantly switch between a view with traits and a flattened view. This could help modelers to understand how traits are represented in any object-oriented target languages, as well as the implications of the traits to the generated system. Furthermore, flattened model is useful when it is required to understand what provided methods are available in each final client.

In order to achieve this in UmpleOnline, first the menu OPTIONS must be selected. Then, sub menus Graphviz Class and Traits must be selected for DIAGRAM TYPE and SHOW VIEW respectively. In order to switch to the flattened model, modelers simply need to deselect Traits in SHOW VIEW. These two views can also be generated through the Umple command line interface and the Umple Eclipse Plugin.

In order to see the flattened model textually, first the menu TOOLS must be selected. Then, from the drop down named GENERATE select Internal Umple Representation. Finally, click on Generate code to see the result or to download it.

Basic Templates

Generating string output is a very common task for programs. Common types of output include html, xml and executable code. Umple has a special capability for this, as do many other technogies (it is central to PhP, for example). The advantage of Umple's approach is that it adds generation templates in a uniform manner to C++, Java, PhP and other languages that Umple supports. The same templates can be reused.

The Umple generation templates are essentially a readable way to generate special methods that emit Strings (and also in Java's case StringBuilders).

Two basic elements are needed to use generation templates:


 

Templates The first essential element is the templates themselves. These are shown as a name followed by arbitrary text in <<! !>> brackets. The text in the brackets can contain anything you want. See the examples below to understand how these are used.

<<!output this!>>

will build the string 'output this' when specified in an emit method (below).


 

Emit method specifications: The second essential element is one or more 'emit' statements. These specify the methods to be generated. As with any method there can be a set of arbitrary parameters. Following this, in a second set of parameters is comma-separated list of templates to emit. For example, the following says to generate a method with signature String printRow(intTimes, intCount); that will emit a string containing the contents of the row and cr templates:

emit printRow(int times, int count)(row, cr);  


 

Optional elements in templates are:

Expression blocks: Inside the template, programmers can specify arbitrary expressions in <<= >> brackets. These can refer to attributes of the class, parameters to the emit method, states and so on. The result of the expression will be substituted every time the template method is called. This appears in all examples below.

Code blocks: Also inside the template program logic can be embedded in <<# #>> brackets. This enables conditional emission of parts of a template, or looping within the template. This appears in the second example below.

Comment blocks: Comments in templates can be shown within <</* */>>


 

The first two examples below show how simple templates can be used to output strings, in this case a one-column multiplication table. The first example uses two template methods, the second being called in a loop. The second example generates the same output, but all the looping logic is enclosed in the template itself. The third example shows a more substantial template with a lot of 'boilerplate' text that is easy to read and edit in the Umple source. Manually writing the generated would be substantially more awkward.

Umple's mixin capability allows templates to be kept in separate files. This can faciliatate reuse.

Example

// Simple example to demonstrate umple's template base string generation
// mechanism.
// In this approach there is an iterative call to the emit function

class MathExample {

  // A simple template to inject a platform-specific newline
  cr <<!
!>>

  // Two templates for different lines of output
  header <<!Print out a <<=times>> times table!>>
  row <<!  <<=times>> times <<=count>> is <<=times*count>>!>>

  // Specification for two methods to be generated to output  
  // parts of the text
  // Method arguments are in the first parentheses
  // Templates to output are in the second set
  emit printHeader(int times)(header, cr);
  emit printRow(int times, int count)(row, cr);

  // Main program to run the above and generate the output
  public static void main(String[] argv) {
    int times = 10; // default
    MathExample m = new MathExample();

    if(argv.length > 0) {
      times=Integer.parseInt(argv[0]);
    }

    // Print the header
    System.out.print(m.printHeader(times)); 
    // Print one row for each element
    for (int i=0; i <= times; i++) {
      System.out.print(m.printRow(times,i));
    }
  }
}


      

Load the above code into UmpleOnline

 

Another Example

// Simple example to demonstrate umple's template base string generation
// mechanism.
// In this approach iteration is embedded in the rows template
// and there is a single emitter function generated called result

class MathExample {

  // A simple template to inject a platform-specific newline
  cr <<!
!>>

  // A template for the header lines
  header <<!Print out a <<=times>> times table!>>

  // A template that generates all the rows by iterating
  rows <<!<<# for  (int i=0; i <= times; i++) {#>>

<<=times>> times <<=i>> is <<=times*i>><<#}#>>!>>

  // Specification of a single method to emit the result
  emit result(int times)(header, rows, cr);
  
  public static void main(String[] argv) {
    int times = 10; // default
    if(argv.length > 0) {
      times=Integer.parseInt(argv[0]);
    }
    // Output the entire result
    System.out.print(new MathExample().result(times)); 
  }
}


      

Load the above code into UmpleOnline

 

Another Example

// Example of creating a lengthy output in Umple from a template
// Note this is plain text. See the next page for html generation.
// The company is, of course, fictitious.
class RefLetterRequest {
  // Attributes used to construct the instance
  String fileno; String recipient; String applicant;
  String sender; String senderTitle;
  
  // Letter template
  letterTemplate <<!
Subject: Reference request for <<=applicant>>, File #<<=fileno>>

Dear <<=recipient>>,
Our company, Umple Enterprises, is hiring talented software
engineers.

We have received an application from <<=applicant>> who named you
as an individual who could provide a letter of reference. Would you
please reply to this letter, answering the following questions:
  * In what capacity do you know <<=applicant>>
  * For how long have you known <<=applicant>>
  * Describe the abilities of <<=applicant>> in software development
  * What his or her strengths and weaknesses?
  * Please provide your phone number and suitable times to call in
    case we need to follow up 
    
Yours sincerely,
<<=sender>>
<<=senderTitle>>
!>>

  // Specification of the method to generate
  emit letterTemplate()(letterTemplate);

  // Main program to generate the letter
  public static void main(String[] argv) {
    if(argv.length < 5) {
      System.err.println("You must specify arguments for fileno, recipient, applicant, sender, sendertitle");
    }
    // Output the entire result
    else System.out.print(new RefLetterRequest(
      argv[0], argv[1],argv[2], argv[3], argv[4]
    ).letterTemplate()); 
  }
}


      

Load the above code into UmpleOnline

 

Syntax


templateAttributeDefinition : [[templateName]] [[templateAttribute]]

templateName : ( [~classname] . )? [name] [[templateParameters]]?

emitMethod : [=modifier:public
    |protected
    |private]? [=static]? [type]? [=emit] [[methodDeclarator]] [[templateList]]?;

templateList- : ( ( [[templateName]] ( , [[templateName]] )* )? )

templateAttribute# : <<! [[templateAttributeContent]]* !>>

templateAttributeContent- : [[templateExpression]]
    | [[templateComment]]
    | [[templateCodeBlock]]
    | [[templateExactSpaces]]
    | [[templateInclude]]
    | [[templateText]]

templateText# : [**templateTextContent:<<(=|#|/[*]|$|@)]

templateComment# : <</* [**templateCommentContent] */>>

templateExpression# : <<= ( [[templateExpression]]
    | [**templateExpressionContent:<<(=|#|/[*]|$|@)] )+ >>

templateCodeBlock# : <<# ( [[templateExpression]] | [**templateLanguageCode:<<(=|#|/[*]|$|@)] )* #>>

Html Generation

The first example below illustrates the generation template capability of Umple. It is an html generation library. The second example is a program that uses the second example.

Example

// Umple library for generating html
// Currently it supports h1, h2 ... as well as p, and table tags.
// This will be extended to support more of html later
// It serves as an illustration of Umple's generation templates

// Class representing either a top level html node or a collection of subnodes
class HtmlNode {
  String getContent() {return "";};  // should be abstract
}

// Simple text to be output between tags - these are leaves
class HtmlTextNode {
  isA HtmlNode;
  String content;
}

// Non-leaf nodes in the html tree
class HtmlRegularNode {
  isA HtmlNode;
  const String Xmltagstart = "<";
  const String Xmltagend = ">";

  // Arguments for the constructor
  String tag; // e.g. p, h1, a
  String arguments; // e.g. href
  
  0..1 -> * HtmlNode subnodes; // whatever to emit between tags
  
  // The following template will render any html node
  rendering <<!<<=Xmltagstart>><<=getTag()>> <<=getArguments()>><<=Xmltagend>>
  <<#
  for(HtmlNode n : getSubnodes()) {#>><<=n.getContent()>>
  <<#}#>><<=Xmltagstart>>/<<=getTag()>><<=Xmltagend>>!>>
  
  emit getContent()(rendering);
  
  HtmlTable table() {
    HtmlTable t = new HtmlTable();
    addSubnode(t);
    return t;
  }
  
  HtmlTextNode text(String s) {
    HtmlTextNode t = new HtmlTextNode(s);
    addSubnode(t);
    return(t);
  }

  HtmlRegularNode taggedText(String tag, String arguments, String s) {
    HtmlRegularNode r = new HtmlRegularNode(tag, arguments);
    HtmlTextNode t = new HtmlTextNode(s);
    r.addSubnode(t);
    addSubnode(r);
    return(r);
  }
}

class HtmlTable {
  isA HtmlRegularNode;

  HtmlTable() {
    super("table","");
  }

  HtmlRow tr() {
    HtmlRow r = new HtmlRow();
    addSubnode(r);
    return r;
  }  
}

class HtmlRow {
  isA HtmlRegularNode;

  HtmlRow() {
    super("tr","");
  }

  // Add a cell that contains text
  HtmlCell td(String s) {
    HtmlCell c = td();
    c.text(s);
    return(c);
  }

  // Add a cell that can contain anything
  HtmlCell td() {
    HtmlCell c = new HtmlCell();
    addSubnode(c);
    return c;
  }
}

class HtmlCell {
  isA HtmlRegularNode;

  HtmlCell() {
    super("td","");
  }
}

class HtmlGen {

  lazy HtmlNode firstNode;

  // Subtrees for the header and body
  0..1 -> * HtmlNode headerNodes;
  0..1 -> * HtmlNode bodyNodes;
 
  after constructor {
    firstNode = new HtmlTextNode(filehead());
  }

  filehead <<!<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">!>>
  emit filehead()(filehead);

  xmlns <<!xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"!>>
  emit xmlns()(xmlns);
  
  wholefile <<!<<=getFirstNode().getContent()>>
<html <<=xmlns()>> >
  <head>
  <<#for(HtmlNode h: getHeaderNodes()) {#>>
    <<=h.getContent()>>
  <<#}#>>
  </head>
  <body>
  <<#for(HtmlNode h: getBodyNodes()) {#>>
    <<=h.getContent()>>
  <<#}#>>
  </body>
</html>
!>>
    
  emit wholefile()(wholefile);

  // Creates a new simple node; but does not add it anywhere
  HtmlRegularNode simpleNode(String tag, String content) {
    HtmlTextNode t = new HtmlTextNode(content);
    HtmlRegularNode r = new HtmlRegularNode(tag,"");
    r.addSubnode(t);
    return r;
  }

  // Add a top level node of any type that contains a string
  HtmlNode addNode(HtmlNode n) {
    addBodyNode(n);
    return n;
  } 

  // Add a node of any type that contains a string
  HtmlRegularNode addSimpleNode(String tag, String text) {
    HtmlRegularNode t = simpleNode(tag,text);
    addBodyNode(t);
    return t;
  } 

  // Adds a top level header at a certain level with plain text
  // Subsequent calls can be made to add additional elements
  // to the result
  HtmlRegularNode h(int level, String text) {
    return addSimpleNode("h"+level,text);
  } 

  // Adds a top level p with plain text
  // Subsequent calls can add additional elements to the p
  // beyond just the text
  HtmlRegularNode p(String text) {
    return addSimpleNode("p",text);
  } 

    
  // Adds a top level table
  HtmlTable table() {
    HtmlTable t = new HtmlTable();
    addBodyNode(t);
    return t;
  }
}


      

Load the above code into UmpleOnline

 

Another Example

// Umple program demonstrating generation
// of the html generation library for Umple

use ../HtmlGeneration.ump;

class TimesTable {
  public static void main(String[] argv) {
    int times = 10; // default
    HtmlGen h = new HtmlGen();
    HtmlRegularNode p;

    if(argv.length > 0) {
      times=Integer.parseInt(argv[0]);
    }
    
    // Specify the table main header
    h.h(1, "Multiplication Table: "+times);

    // Generate an explanatory paragraph
    p = h.p("The following is a ");
    p.taggedText("i","","simple");
    p.text(" multiplication table");
    
    // Generate another paragraph with some subnodes
    // showing a slightly different use of the API
    p = new HtmlRegularNode("p","");    
    h.addNode(p);
    p.text("Nodes in ");
    p.taggedText("font", "color=\"red\"", "red");
    p.text(" are powers of 3");

    h.h(2, "The table");

    // Create a table at the top level
    HtmlTable t=h.table();

    // Add the top row of the table
    HtmlRow r;
    r=t.tr();
    r.td("*");
    for(int i=1; i<= times; i++) {
      r.td().taggedText("b","",""+i);;
    }

    // Add the interior rows of the table
    for(int i=1; i<= times; i++) {
      r=t.tr();
      r.td().taggedText("b","",""+i);
      for(int j=1; j<= times; j++) {
        String output=""+i*j;
        if((i*j)%3==0) {
          HtmlCell c = r.td();
          c.taggedText("font", "color=\"red\"",output);
        }
        else {
          r.td(output);
        }
      }
    }
    
    System.out.println(h.wholefile()); 
  }
}


      

Load the above code into UmpleOnline

 

Active Objects

An active object is an object that, when constructed, runs its own thread. This is indicated in Umple by the 'active' keyword followed by a block of code. A collection of active objects, working together, constitute a concurrent system.

Additional Umple features are under development to allow for sending signals to and from concurrent objects.

Example

class A {
  name;
 
  active {
    System.out.println("Object "+getName()+"is now active");
    for (int i = 1; i < 10; i++) {
      System.out.println(" "+name+" was here");
      Thread.sleep(1000);
    }
  }

  public static void main(String[] argv) {
    new A("1");
    new A("2");
  }
}


      

Load the above code into UmpleOnline

 

Syntax


activeDefinition : [=active] [[codeLangs]] [name]? [[moreCode]]+

Concurrency Using Do Activities

Multiple concurrent blocks that become active when in a particular state can accomplished in Umple using a state machine with two substates separated by the || symbol, each with a do activity. Both do activities will run concurrently.

Example

class X {
  activesm {
    topstate {
      thread1 {
        do {
          System.out.println("Doing the activity - Normally this would last a long time");
          Thread.sleep(1000);
          System.out.println("Done thread 1");
        }
      }
      ||
      thread2 {
        do {
          System.out.println("Doing the other activity - Again normally this would last a long time");
          Thread.sleep(3000);
          System.out.println("Done thread 2");
        }
      }
    }
  }
  public static void main(String[] argv) {
    new X();
  }
}


      

Load the above code into UmpleOnline

 

Another Example

// This is a more sophisticated example
class X {
 sm {
   s1 {
     do {
        System.out.println("In S1");
        Thread.sleep(1000);
        System.out.println("Still in S1 after sleep");
        Thread.sleep(2000);
        System.out.println("About to leave S1");
      }
      -> s2;
    }
    s2 {
     do {
        System.out.println("In S2");
        Thread.sleep(1000);
        System.out.println("Still in S2 after sleep");
        Thread.sleep(2000);
        System.out.println("About to leave S2");
      }
      nesteds2a {
        do {
          System.out.println("In S2a");
          Thread.sleep(1000);
          System.out.println("Still in S2a after sleep");
          Thread.sleep(2000);
          System.out.println("About to leave S2a");
        }
      }
      ||
      nesteds2b {
       do {
          System.out.println("In S2b");
          Thread.sleep(1000);
          System.out.println("Still in S2b after sleep");
          Thread.sleep(2000);
          System.out.println("About to leave S2b");
        }
      }
    }
  }
  public static void main(String[] argv) {
    System.out.println("In Main");
    X theX = new X();
    System.out.println("End of Main");
  }
}


      

Load the above code into UmpleOnline

 

Simple Constraints

Umple supports basoc OCL-type constraints that limit what umple-generated mutator methods (set, add, etc.) and constructors can do.

Constraints are specified within square brackets, in the same manner as guards on state machines.

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

Example

// 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

 

Another Example

// 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]] )

// 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. This is still under development.

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


methodBody- : ( [[codeLangs]] { ( [[precondition]] | [[postcondition]] )* [**code] } )+

// 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]] ]

Basic Composite Structure Diagrams

A composite structure diagram is used to show how various instances of classes, called parts, are connected at run time in order communicate with each other.

To specify composite structure, the following are the elements that need to be present in an Umple system:

The example below first defines two classes with ports; a third class contains instances of the first two.

Under development: Composite structure diagrams, ports and active methods are currently under development. Code generation only works in C++

See also the Wikipedia page on Composite Structure Diagrams.

Example

// Example system representing constraint-based ping-pong example
// Demonstrates the composite Structure Diagram in Umple

class Component1 {
  // Relay-Port
  public in Integer pIn1;
  public out Integer pOut1;
  pIn1 -> pOut1;


  [pIn1]
  active increment {
     pOut1(pIn1 + 1);
  }

  [pOut1]
  active logOutPort1 {
     cout << "CMP 1 : Out data = " << pOut1 << endl;
  }
  
}

class Component2 {
  public in Integer pIn2;
  public out Integer pOut2;
  pIn2 -> pOut2;

  [pIn2, pIn2 < 10]
  active stop {
       pOut2(pIn2 + 1);
  }

  [pOut2]
  active logOutPort2 {
     cout << "CMP 2 : Out data = " << pOut2 << endl;
  }
}


class Atomic {
Component1 cmp1;
Component2 cmp2;
Integer startValue;

  after constructor {
     cmp1->pIn1(startValue);
     
  }


  cmp1.pOut1 -> cmp2.pIn2;
  cmp2.pOut2 -> cmp1.pIn1;
}


      

Load the above code into UmpleOnline

 

Syntax


primitiveDefinition : primitive [name] { [[primitiveBody]]* }

portMultiplicity : [!portMultiplicity:\[[0-9]+\]]

typedPortName : [~type]? [~portName] [[portMultiplicity]]?

portDefinition : [=modifier:public
    |protected
    |private]? [=inverse:conjugated]? [=direction:in
    |out
    |port] [[typedPortName]] ;

// Port Connectors
portBindingDefinition : ( [~fromClassname] . )? [fromPort] -> ( [~toClassname] . )? [toPort] [[bindinHandler]]

bindinHandler : { [**code] } | ;

// Port Watchlist Definition
portWatch- : ( [[constraintList]] | [[comment]] )*

// Active Method Definition
activeMethodDefinition : [[portWatch]]? [=modifier:public
    |protected
    |private]? [type]? [=activeType:atomic
    |synchronous
    |intercept]? [=active] [[activeMethodDeclarator]] [[activeMethodBody]]+

activeMethodDeclarator : [~methodName] [[parameterList]]?

//activeMethodBody : [[activeDirectionHandler]] { ( [[activeTrigger]] )* [**code] }
activeMethodBody : [[activeDirectionHandler]]? { ( [[comment]] | [[activeTrigger]] | [**code] )* }

activeDirectionHandler : [=direction:forward|inverse] ( , [=direction:forward|inverse] )*

activeTrigger : [[hitchConstraint]]? [[constraintList]]? [=trigger:/] [[activeTriggerBody]] [[thenDefinition]]? [[resolveDefinition]]?

activeTriggerBody- : ( [[deferredList]] | [[activeTriggerDefinition]] )

deferredList : [ [[activeTriggerDefinition]] ( , [[activeTriggerDefinition]] )* ]

activeTriggerDefinition- : [[anonymousTriggerBody]] | [[invoke]]

thenDefinition : .then ( [[anonymousTriggerBody]]? )

resolveDefinition : .resolve ( [[anonymousTriggerBody]]? )

hitchConstraint : [=clause:after|poll] ( [timer] )

constraintList : [ [[basicConstraint]] ( , [[basicConstraint]] )* ]

basicConstraint- : [[timeConstraint]] | [[messageConstraint]] | [[constraint]]

timeConstraint : [=clause:latency|period|timeout] ( [timer] )

messageConstraint : [=clause:priority] ( [priorityValue] )

invoke : ( [~classname] . )? [name] ( ( [parameter] ( , [parameter] )* )? ) ;

anonymousTriggerBody : { [**code] }

Singleton Pattern

Use the Singleton keyword to mark a class as a singleon 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.

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


Example

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

      

Load the above code into UmpleOnline

 

Another Example

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

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

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

      

Load the above code into UmpleOnline

 

Another Example

// 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


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])? ;

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

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

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


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

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

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

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

Before and After Statements

You can request that certain code be run before or after various Umple-defined actions on attributes, associations and the components of state machines. The ability to do this with methods will be available soon, giving capabilities similar to aspect-oriented languages.

Using 'before' allows you to enforce preconditions, such that the attribute or association will not be set if the precondition is not true. To reject setting a value, add 'return false'.

You can add before and after clauses to add code to generated methods of the form getX, setX, addX, removeX, getXs (to get all elements of an association), numberOfXs, indexOfX, where X is the name of the attribute or association. You can also add code before and after the constructor.

See also this example of using aspect-orientation to help interface Umple with existing libraries.

Example


class X
{
  a;
  whenWasASet;
  
  after setA {
     setWhenWasASet(getA() + System.currentTimeMillis());
  }
}

      

Load the above code into UmpleOnline

 

Another Example


class Person {
  name;
  before setName {
    if (aName != null && aName.length() > 20) { return false; }
  }
}


      

Load the above code into UmpleOnline

 

Another Example

class Operation {
  const Boolean DEBUG=true;
  query;
  before constructor {
    if (aQuery == null)
    {
      throw new RuntimeException("Please provide a valid query");
    }
  }
  after constructor {
    if (DEBUG) { System.out.println("Created " + query); }
  }
}

      

Load the above code into UmpleOnline

 

Syntax


// Aspect oriented code injection: BeforeandAfterStatements
codeInjection- : [[beforeCode]] | [[afterCode]]

beforeCode : before ([=operationSource:custom
    |generated
    |all])? [[injectionOperation]] ( , [[injectionOperation]] )* ([[codeLang]] [[codeLangs]])? { [**code] } ( [[moreCode]] )*

afterCode : after ([=operationSource:custom
    |generated
    |all])? [[injectionOperation]] ( , [[injectionOperation]] )* ([[codeLang]] [[codeLangs]])? { [**code] } ( [[moreCode]] )*

Code Injection Pattern Matching

When creating before and after statements, you can arrange for the code to be injected into certain methods that match a pattern. You can use * as a wildcard, and ! as an exclusion operator. The following examples will both generate the same code.

Another example of pattern matching for code injection can be found on the page on pooled state machines, where the same code is injected into all the event methods matching a certain pattern

Example


class Student
{
  const Boolean DEBUG = true;
  firstName;
  lastName;
  cityOfBirth;
  before get*Name { 
    if ( DEBUG) { System.out.println("accessing the name"); }
  }
}


      

Load the above code into UmpleOnline

 

Another Example


class Student
{
  const Boolean DEBUG = true;
  firstName;
  lastName;
  cityOfBirth;
  before get*,!getCityOfBirth { 
    if ( DEBUG) { System.out.println("accessing the name"); }
  }
}

      

Load the above code into UmpleOnline

 

Code Injection in Event Methods

State machine event methods are generated automatically from a state machine. Sometimes a programmer wants to execute some code whenever a given event is processed by a state machine, no matter what state the state machine is in.

Code can be injected before or after any event, as shown in the example below. Note that in the case of queued or pooled state machines, the injected code will only be triggered when the event is actually processed by the state machine (i.e. when it is removed from the queue).

Example


class Car {
  queued radio {
    on {
      radioToggle -> off;
    }
    off {
      radioToggle -> on;
    }
  }
  after radioToggle {soundBeep();}
}


      

Load the above code into UmpleOnline

 

Model Oriented Tracing Language (MOTL)

Model Oriented Tracing Language (MOTL) allows developers to specify tracing at the model level.

Historically, developers have traced software using various techniques:

However, in software generated from UML, these techniques can only be used effectively on generated code. They require understanding the structure of that generated code; furthermore trace directives need replacing when the code is replaced. Tracing thus occurs at a level of abstraction below the level at which the system is implemented.


MOTL is designed to allow tracing with direct reference to UML model elements (state machines and their states and events, associations and attributes). MOTL specifies how to inject trace code into generated code for UML constructs.


MOTL syntax is designed to be be usable independently of Umple. For example, trace statements could be used to inject tracing into code generated from a UML model specified in Papyrus. The current implementation of MOTL focuses on tracing Umple-generated code. In order to trace a UML model created by an arbitrary UML tool, it is currently necessary to have the model from that tool converted to Umple first.


MOTL can be used to generate tracing directives for different types of tracers. At its simplest level, if the phrase 'tracer Console;' is used (or no tracer statement is included), then trace output is directed to standard error. Generation of tracing for DTrace and LTTNG is under development.


MOTL can be used in two modes:


The following pages describe how to use MOTL. Many aspects of MOTL are under development. Some future pages for tracing features under development cam be found in Umple wiki pages.


The MOTL project has been sponsored by NSERC, Ericsson and Defence Research and Development Canada, in the Distributed Multi-Core Tracing Project managed by Ecole Polytechnique de Montreal

Tracing Basics

Simple tracing is specified using trace directives, which all start with the word 'trace'. This is normally followed by the UML entity to trace (attribute, association, state, etc.).


Beyond, this, other clauses can be added to limit tracing to certain conditions, to switch on or off tracing in certain situations, and to specify data that will be output.


Each 'trace' statement emits exactly one trace record when something occurs to a matching UML entity; by default it is only changes in value that trigger emission of a trace record, but later pages describe how accesses to the value can also be traced. The format of the trace record will depend on the tracer being used but by default will contain the name of the entity and the new value of that entity.

The following are extremely simple example of tracing using MOTL on a UML Integer attribute. The default console tracer is used, so output will be sent to standard error.

Example


class Student
{
  Integer id;
  
  // Whenever the id attribute is changed, emit a trace record
  // The record will have the format id=value
  trace id;
  
  // The following Java main program can be used to demonstrate this in operation
  // This will output a record when id is set to 9.
  public static void main(String [ ] args) {
    Student s = new Student(6);
    s.setId(9); 
  }
}


      

Load the above code into UmpleOnline

 

Another Example


class Student
{
  lazy Integer id;
  lazy name;
  
  // It is possible to specify multiple UML entities to trace as follows
  // It is also possible to indicate interesting information to record
  // in addition to the value of the element being traced
  trace id, name record "interesting behavior";
  trace id record "Even more interesting";

  // Traces will be triggered for each call to a 'set' method
  // and twice for id, since there are two trace statements for id  
  public static void main(String [ ] args) {
    Student s = new Student();
    s.setId(9); 
    s.setName("Tim");
  }
}


      

Load the above code into UmpleOnline

 

Tracing Attributes

MOTL allows the tracing of attributes at the model level. Attribute tracing can occur whenever an attribute value is changed (i.e. setter is called) or/and when the value is accessed (i.e. the getter method is called). Thus, attribute tracing can be made to occur any of the following modes:

Example

// This traces setId() and setName()
class Student
{
  Integer id;
  String name;
  trace id;
  trace set name;
}


      

Load the above code into UmpleOnline

 

Another Example

// This traces  getId() method
class Student
{
  Integer id;
  trace get id;
}

      

Load the above code into UmpleOnline

 

Another Example

// This example traces getId() and setId()
class Student
{
  Integer id;
  trace set,get id;
}


      

Load the above code into UmpleOnline

 

Syntax


traceDirective : trace [[Prefix]]? [[traceEntity]] [[Postfix]] ;

traceEntity- : [traceEntity] (()? ())? ( , [traceEntity] (()? ())? )*

Tracing State Machines

State machines are representations of system behaviour. States can have entry or exit actions and do activities; they can also be composite (i.e. nested) or concurrent. MOTL provides modellers with the capability of specifying tracing for all these modelling elements.

Example

class LightBulb
{
  Integer v = 0;
  status
  {
    On { 
      entry / { setV(1); } 
      flip -> Off;
    }
    Off { 
      entry / { setV(2); }
      flip -> On;
    }
  }
  // trace whenever we enter/exit state On 
  trace On;
  // trace whenever we exit state Off and report value of attribute v 
  trace exit Off record v;
}
      

Load the above code into UmpleOnline

 

Another Example

class LightBulb
{
  status
  {
    On { 
      flip -> Off;
    }
    Off { 
      flip -> On;
    }
  }
  // trace any triggering of event flip
  trace flip;
}
      

Load the above code into UmpleOnline

 

Another Example

// this example will trace all states of State machine GarageDoor 

class GarageDoor
{
    // UML state machine digram for a Garage door, written in Umple
    status { 	
      	Open { buttonOrObstacle -> Closing;  }  	
      	Closing {
          buttonOrObstacle -> Opening;
          reachBottom -> Closed;
      	}
      	Closed { buttonOrObstacle -> Opening; }
      	Opening {
          buttonOrObstacle -> HalfOpen;
          reachTop -> Open;
      	}
      	HalfOpen { buttonOrObstacle -> Opening; }
    }
    // trace whole state machine
    trace status;
}
      

Load the above code into UmpleOnline

 

Syntax


traceDirective : trace [[Prefix]]? [[traceEntity]] [[Postfix]] ;

traceEntity- : [traceEntity] (()? ())? ( , [traceEntity] (()? ())? )*

Tracing Associations

Associations describe the relationships between class instances; role names are used to clarify the relation at both ends of an association. MOTL allows the tracing of associations by referring to the role names. Tracing can occur whenever an association link is added or deleted at run time:

Example

// This example will record any addition/removal to supervisor assoc link 

class Student {
  Integer id;
}

class Professor {
  1 -- * Student supervisor;
  
  trace supervisor;
}
      

Load the above code into UmpleOnline

 

Another Example

// This example will record any addition to assoc link 'supervisor'

class Student {
  Integer id;
}

class Professor {
  1 -- * Student supervisor;
  
  trace add supervisor;
}
      

Load the above code into UmpleOnline

 

Another Example

// This example will record any removal of any supervisor assoc link 

class Student {
  Integer id;
}

class Professor {
  1 -- * Student supervisor;
  
  trace remove supervisor;
}
      

Load the above code into UmpleOnline

 

Syntax


traceDirective : trace [[Prefix]]? [[traceEntity]] [[Postfix]] ;

traceEntity- : [traceEntity] (()? ())? ( , [traceEntity] (()? ())? )*

Tracing Constraints

Constraints can be imposed upon the traced UML entity to limit the scope of tracing to when a certain condition is true. MOTL provides a set of constraints that can be classified into a prefix and postfix constraints.

Example

class Student
{
  name;
  Integer id;

  // trace code is injected in attribute setter with specified precondition
  trace name where [name == "john"];

  // trace code is injected in attribute setter with specified postcondition
  trace id giving [id > 9000];

  // this example traces attribute name whenever its value is changed for 5 times 
  trace name for 5;
}

class Professor {
  name;
  1 -- * Student supervisor;
  
  // trace code is injected in attribute setter with role name cardinality condition
  trace name where [ supervisor cardinality > 10];
}


      

Load the above code into UmpleOnline

 

Another Example

class Student
{
  name;
  Integer id;
  // trace attribute id and record provided string message as part of  the trace output
  trace id record "i am tracing attribute name";
  
  status {
    s1 { e1 -> s2; }
    s2 {}
  }
  // trace whenever we enter/exit state "s1" and record attribute name
  trace s1 record name;
}


      

Load the above code into UmpleOnline

 

Another Example

class Student
{
  name;
  Integer id;
  
  // tracing of attribute name starts and doesn't stop until condition becomes true
  trace name until [name == "john"];

  // tracing of attribute id until condition becomes true and then always continue tracing 
  trace id after [id == 234];
}


      

Load the above code into UmpleOnline

 

Syntax


traceCondition : [=conditionType:where|until|after|giving]? [ [[constraintToken]] ]

traceFor- : for [traceFor]

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

Tracing Methods

Tracing non api methods is possible using MOTL. Entry and/or exit of methods can be traced.

Example

// this example shows how to trace non api method entry

class JavaMethod
{
  trace method();
    
  int method( int x ) {
    x += 5;
    return x;
  }
}


      

Load the above code into UmpleOnline

 

Another Example

// this example shows how to trace non api method exit
// incase of methods with return statement, trace code is 
// injected before the return

class JavaMethod
{
  trace exit method();
    
  int method( int x ) {
    x += 5;
    return x;
  }
}


      

Load the above code into UmpleOnline

 

Syntax


traceDirective : trace [[Prefix]]? [[traceEntity]] [[Postfix]] ;

Tracers

MOTL sets the Console to be its default tracer. However, it provides a set of potential tracers that will have an impact on how tracing is injected and how its collected. Modellers can control the model tracer using a tracer directive.

MOTL tracers can be classified into two main categories: Built in tracers and third party tracers. The main difference between these two categories is that the first category tracers doesn’t require any additional jars imported into your model generated code, while the later requires jars specific to each tracer.

  1. (Built in tracers)
  2.  
  3. (Third party tracers)

Example

// this example generates traces using the File tracer
tracer File;

class Student
{
  Integer id;
  trace id;
}


      

Load the above code into UmpleOnline

 

Another Example

// this example generates traces using the Java native logging API
tracer JavaAPI;

class Student
{
  Integer id;
  name;
  // trace id with default logging level info
  trace id;
  // trace name to logging level severe
  trace name logLevel severe;
}
      

Load the above code into UmpleOnline

 

Another Example

// this example generates tracespoints using the Lttng tracer
tracer Lttng;

class Student
{
  Integer id;
  trace id;
}

      

Load the above code into UmpleOnline

 

Another Example

// this example generates traces using the log4j tracer
// Default log4j xml configuration file is generated (log4j2.xml) 
tracer log4j;

class Student
{
  Integer id;
  name;
  
  // trace attribute id with log4j level set to (info)
  trace id logLevel info;

  // trace attribute id with log4j level set to (error)
  trace name logLevel error;
}

      

Load the above code into UmpleOnline

 

Another Example


// this example generates traces using the log4j tracer
// Customized log4j xml configuration file is generated (log4j2.xml)
// Root logger level will be debug
// Info logging level will be written into console output
// Error logging level will be written into file
tracer log4j root=debug info = console error = file;

class Student
{
  Integer id;
  name;
  
  // trace attribute id with log4j level set to (info)
  trace id logLevel info;

  // trace attribute id with log4j level set to (error)
  trace name logLevel error;
}

      

Load the above code into UmpleOnline

 

Syntax


Trace Output

Specifying trace directives at the model level will inject trace points in source code generated from the model. MOTL was designed to collect a wide range of information when tracing is triggered at the execution time.

Collected information includes current system time, thread ID, Object hash code, etc. MOTL tracers will output an initial header to indicate each traced field name.

Using UmpleOnline

The following describes how to use the UmpleOnline tool accessible online at try.umple.org

For information about writing Umple models or code in UmpleOnline, look at the Getting Started section of this user manual, or any other topic in the left column of this page, including information about defining classes, attributes, associations and state machines.


Loading and saving

Left Pane: Umple textual code

Right Pane: UML diagram

Bottom Pane: Errors, Warnings and Generated Results

Shortcuts


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

UmpleOnline URL options

UmpleOnline allows you to append various options to its URLi, enabling startup in a certain state. These are preceded by an ampersand, except the first in a list which would be preceded by a question mark.

Umple in Presentations and Documents

Embedding a pure diagram in a web page

Using &nochrome&notext&nomenu&readOnly allows you to embed a pure diagram in a web page. Using &nochrome&nodiagram&nomenu&readOnly allows textual listings in any other web page. Using &nochrome&notext allows a UML diagram editor to be embedded.

For example, Click here to see a document with an embedded iFrame containing an editor opening on the RoutesAndLocations example. The chrome and text is hidden.

For a read-only version, with ability to generate code, use http://try.umple.org/?example=RoutesAndLocations&notext&nochrome&readOnly

Coloring model elements

Umple has a special directive that allows you to highlight certain elements (currently only classes) in UmpleOnline and GraphViz output. Simply write 'displayColor xxx;' in a class where xxx is any html colour such as "red" or "#BBCCFF". UK spelling displayColour also works.

Umplification - An Introduction

Umplification involves transforming step by step a base language program to an Umple program; each step is a refactoring. The starting point and the ending point of each transformations will be a system rendered in a textual form combining model elements in the Umple syntax and base language code.

Umplification involves increasing the proportion of modeling elements.

The key insight is that a pure Java program can be seen as a speci al case of an Umple program. A pure model can also be seen as such a special case. So Umplification involves repeatedly modifying the Umple to add abstractions, while maintaining the semantics of the program, and also maintaining to the greatest extent possible such elements as layout, algorithmic methods and comments

Two main features differentiate Umple from existing reverse engineering techniques.

  1. The Tranformations required are intended to be applie incrementally by a programmer who has a body of legacy code and wants to gradually transform it intoUmple, preserving much of the layout, comments and other aspects of the original code if possible.
  2. The transformations required are at the same time code-to-model,model-to-model and code-to-code.

Umplification Process

To start, source files with language L (e.g. Java, C++) code are initially renamed as Umple files, with extension .ump.

Then, iteratively, small transformations are performed that gradually add UML abstractions. Each iteration should involve testing to check that the program’s semantics are preserved.


Umplification can be performed automatically by a reverse engineering technology that can parse a program in any native programming language and extract the Umple model from it.

Interfacing to External Code

This example shows some of the techniques that can be used when writing Umple code that will be connected to code written separately, such as code in a GUI library. Use of the:

Example

/*
This example demonstrates an example of using the internal,
depends, external, before and after keywords to interface
umple code to code in another system.

The internal keyword is suitable for situations where the
developer doesn't want setter/getters to be generated.
GUI windows are an example of such a case. A GUI window/unit
contains several components but the rest of the program
may only need the value stored within those components.
So it's a good practice to hide UI components from classes
other than the containing one. 

*/

// required to make HelloInternals class a JFrame
external JFrame{}

class HelloInternals {
  // HelloInternals extends JFrame
  isA JFrame;

  // importing required classes
  depend javax.swing.JFrame;
  depend javax.swing.JLabel;

  /* messageLabel is a component of the frame; often we don't want sub-components
  of a GUI unit to be settable/gettable. By making them internal Umple will avoid
  generating setter/getter for messageLabel. Using lazy Umple will avoid adding a
  constructor parameter for this component */
  lazy internal JLabel messageLabel;
  
  // the contents of messageLabel 
  String message;
  
  /* before getting the message, this code updates the message attribute using the
  text from messageLabel */  
  before getMessage {
    message=messageLabel.getText();
  }
  
  /* after setting the messae, this code updates messageLabel to contain the newly
  updated message */
  after setMessage {
    messageLabel.setText(message);
  }
  
  // using after constructor is a good way of initiating a GUI unit
  after constructor {
    getContentPane().setLayout(null);
  
    messageLabel=new JLabel(message);
    messageLabel.setBounds(10, 10, 200, 20);
    add(messageLabel);
    
    pack();
    setSize(250, 200);
  }
}


      

Load the above code into UmpleOnline

 

2D Shapes System

Example

// 2D Shapes class hierarchy - sample UML class diagram in Umple
// From Book by Lethbridge and Laganiere, McGraw Hill 2004
// Object-Oriented Software Engineering: Practical Software Engineering using UML and Java
// See http://www.lloseng.com

//Namespace for core of the system.
namespace Shapes.core;

class Shape2D {
 center;
}
//Abstract
class EllipticalShape {
 isA Shape2D;
 semiMajorAxis;
}
//Abstract
class Polygon { 
 isA Shape2D;
}
class Circle {
 isA EllipticalShape;
}
class Ellipse{
 isA EllipticalShape;
}
class SimplePolygon {
 orientation;
 isA Polygon;
}
class ArbitraryPolygon {
 points;
 isA Polygon;
}
class Rectangle {
 isA SimplePolygon;
 height;
 width;
}
class RegularPolygon {
 numPoints;
 radius;
 isA SimplePolygon;
}

      

Load the above code into UmpleOnline

 

Airline System

A simple airline system that manages flight and passenger information

Example

// Airline system - sample UML class diagram in Umple
// From Book by Lethbridge and Laganiere, McGraw Hill 2004
// Object-Oriented Software Engineering: Practical Software Engineering using UML and Java
// See http://www.lloseng.com

namespace Airline;

class Airline{
  1 -- * RegularFlight;
  1 -- * Person;
}

class RegularFlight{
  Time time;
  unique Integer flightNumber;
  1 -- * SpecificFlight;
}

class SpecificFlight{
  unique Date date;
}

class PassengerRole
{
  isA PersonRole;
  immutable String name ;
  1 -- * Booking;
}
  

class EmployeeRole
{
  String jobFunction ;
  isA PersonRole;
  * -- 0..1 EmployeeRole supervisor;
  * -- * SpecificFlight;
}

class Person
{
  settable String name;
  Integer idNumber;
  1 -- 0..2 PersonRole;
}

class PersonRole{}

class Booking{
  String seatNumber;
  * -- 1 SpecificFlight;
}

      

Load the above code into UmpleOnline

 

Banking System

Example

// Sample UML class diagram for a banking system, written in Umple

//Namespace for core of the system.
namespace BankingSystem.core.humanResources;
class PersonRole{}

class Person{
 name;
 address;
 phoneNumber;
 
 1 -- * PersonRole;
}

class Employee{
 isA PersonRole;
}

class Client
{
 isA PersonRole;
 name;
 address;
 phoneNumber;
 1..2 -- 1..* Account;
}

class Manager {
 isA Employee;
 0..1 -- * Employee;
}

//Accounts,  priviledges, etc.
namespace BankingSystem.core.intangableResources;
class Account{
 Integer accountNumber;
 Float balance;
 Float creditLimit;
 * -> 1 AccountType;
}

class AccountType
{
 Float monthlyFee;
 Float interestRate;
 
 * -- * Privilege;
}

class Privilege
{
 description;
}

class CreditCardAccount{
 isA Account;
 Date expiryDate;

 1 -- 1..* Card;
}

class MortgageAccount {
 isA Account;
 collateral;
}

//Anything physicaly tangable
namespace BankingSystem.core.tangableResources;
class Card
{
 holderName;
}

class Branch {
 isA Division;
 address;
 branchNumber;

 1 -- * Account;
}

class Division{
 name;
 
 1 -- * Employee; 
 0..1 -- 0..* Division subDivision;
}

      

Load the above code into UmpleOnline

 

Banking System (b)

Example

/*
  Banking System - sample UML class diagram written in Umple
  Last updated: February 21, 2011
*/
//Namespace for core of the system.
namespace BankingSystem.core;

class FinancialInstitution {
 name;
 1 -- * ReusableFinancialInstrument;
}

class CreditCardCompany{
 isA FinancialInstitution;
}

class Bank{
 isA FinancialInstitution;
 1 -- * Branch;
}

class FinancialInstrument{
}

class ReusableFinancialInstrument{
 isA FinancialInstrument;
 number;
 pin;
 * -> 1 Currency;
}

class CreditCard {
 isA ReusableFinancialInstrument;
 creditLimit;
 name;
}

class DebitCard {
 isA ReusableFinancialInstrument;
}

class Cheque {
 isA FinancialInstrument;
 amount;
 Date date;
 sequenceNumber;
}

class BankAccount{
 isA FinancialInstrument;
 accountNumber;
 balance;
 Float overdraftOrCreditLimit;
 
 1..* -- * DebitCard;
 1 -- * Cheque; 
}

class Currency
{
 code;
 exchangeRate;
}

class Branch
{
 name;
 address;
 1 -- * BankAccount;
}

class Loan{
 isA BankAccount;
}

      

Load the above code into UmpleOnline

 

Election System


Example

// UML class diagram for a system for managing elections, written in Umple
namespace electorial;

// association should be ->
class PollingStation {
 Integer number;
 address;

 1 -- * PollInElection; 
} 
 
class ElectedBody{
 description;

 1 -- * Position;
}

 //Different elections may have different sets of polls
class Election{
 Date date;
 
 1 -- * PollInElection;
 1 -- * ElectionForPosition;
}

class ElectionForPosition{
 1 -- * Candidature;
}

//Eg. Mayor, Councilor. AKA seats
//A position can have different elections for it at different times, eg. once every four years.
class Position {
 description;
 1 -- * ElectionForPosition;
}

//We need candidature class since a candidate can run for different 
//positions and for the smae positions at subsequent elections
class Candidature {
 internal Boolean isIncumbent = false;
 
 public void markAsIncumbent()
 {
   isIncumbent = true;
 }
 
 public String toString()
 {
   return isIncumbent ? "Incumbent" : "Candidature";
 }
}

class Candidate {
 name;
 Integer phoneNumber;
 address;
 
 1 -- * Candidature;
}

class PollInElection {
 Integer number;
 
 1 -- * Voter;
}

associationClass VotesInPoll{
 * Candidature;
 * PollInElection;
 Integer numVotes;
}

class Voter{
 name;
 address;
 * -- * Candidature;
}

class ElectoralDistrict{
 1 -- * Voter; 
 0..1 -- * Position; 
 0..1 -- * ElectoralDistrict subDistrict;
}    

      

Load the above code into UmpleOnline

 

Warehouse System

Example

// UML class diagram of a system for managing a warehouse
namespace warehouse;

class MovementLocation{}

class SlotSet{
 isA MovementLocation;
 0..1 -- 0..1 BoxOrPallet;
 1 -- * Slot;
}

class Slot{
 Integer number;
 Double width;
}

class Level{
 Integer height;
 Integer number;
 1 -- * Slot;
}

class LoadingGate{
 Integer number;
 isA MovementLocation;
}

class Truck{
 Integer registerNum;
 Boolean isWaiting;

 1 -- * DeliverOrShipmentBom;
}
class Rwbm{
 Integer id;
}

class Item{
 Double value;
 Integer hazardID;
 Integer breakability;
}

class Row{
 Integer depth;
 Integer number;
 
 1 -- * Level;
}

//Note that here we have the choice to use
// Time or Double, if the customer requires Double due to 
// some interoperability issues with a legacy syste, we can easily
// accomodate them and use Double instead of Time.
class RwbmMovement{
 Double startTime;
 Double endTime;
 
 * toMovement -- 1 MovementLocation to;
 * fromMovement -- 1 MovementLocation from;
 * -- 1 BoxOrPallet movedBox;
 1 -- * Rwbm;
}

// Both associations should be ->
class DeliverOrShipmentBom {
 Double startTimeLoadOrUnload;
 Double endTimeExpected;
 * delivery -- 0..1 LoadingGate sentThrough;
 * arrival -- 0..1 LoadingGate arriveAt;
}

class BoxOrPallet{
 Integer rfidTagNumber;
 Double lengthINmm;
 Double widthINmm;
 Double heightINmm;
 Double weightINkg;
 String contentType;
 
 * -- * DeliverOrShipmentBom;
 1 -- * Item; 
}

      

Load the above code into UmpleOnline

 

Canal System

Canal system class diagram.

See also the state diagram for the canal lock.

The following are the requirements from which this was derived:

The Canal Monitoring and Control System is used to automate canal locks in response to water craft that want to pass through a canal system. The system can be installed in any network of canals. Each canal is divided up into segments. Each segment has two ends which can either be a bend, a lock gate, a low bridge, or a system entry/exit point (where boats can move to or from other waterways such as rivers and lakes). A special kind of canal segment is a lock. The water level in a lock can be raised or lowered so its height matches the height of an adjacent segment. Several locks can exist side by side (as in the Rideau Canal next to Parliament Hill in Ottawa). A low bridge is a location where the bridge needs raising for a boat to pass. A bend is simply a place where the canal changes direction - keeping track of these helps simplify mapping of the system.

The system keeps track of the GPS co-ordinates of each segment end, the height of the water above sea level in each segment (which can change in locks), and optionally a name given to a series of locks or segments.

Each water craft using the system must have a transponder. The transponder includes a GPS unit and transceiver. When the captain of a craft wants to travel through the system, he enters his plannned destination in the transponder. The size of the boat is also tracked. The transponder regularly transmits the location of the craft to the control system so the control system can monitor traffic.

When a craft reaches a gate, the system knows it is there and needs to pass through since it has received the data about the desired destination. The control system takes care of opening the gate, raising or lowering of the water level, and then opening the next gate, etc. When a boat reaches a low bridge, a similar procedure takes place, except that raising or lowering the water doesn't happen.

When there are a lot of boats, the system makes several of them queue up so they can pass through a lock or low bridge at the same time. The system has, however, to ensure that only the right number and size of boats are put into a lock at once, so the lock doesn't become overly full (the system knows the size of each lock). Complicating matters is the fact that there will be boats travelling in both directions.

Example

// UML class diagram that models a canal as a network of segments, with Locks
// See the State Machine section for a state machine for each lock
class CanalNetwork {
  name;
  0..1 -- * CanalNetwork subNetwork;
  0..1 -- * Craft activeVessels;
  * -- * SegEnd;
}

class SegEnd {
  name;
  GPSCoord location;
}

class Segment {
  Float waterLevel; // m above sea level 
  1..* -- 2 SegEnd;
}

class Lock {
  isA Segment;
  Float maxLevel;
  Float minLevel;
}

class Bend {
  isA SegEnd;
}

class EntryAndExitPoint {
  isA SegEnd;
}

class MooringPoint {
  isA SegEnd;
}

class Obstacle {
  isA SegEnd;
  0..1 downstreamObstacle -- * Craft upStreamQueue;
  0..1 upstreamObstacle -- * Craft downStreamQueue;  
}

class LowBridge {
  isA Obstacle;
}

class LockGate {
  isA Obstacle;
}

class Craft {
  lazy GPSCoord location;
}

class Trip {
  0..1 -> 1..* SegEnd;
  0..1 -- 1 Craft;
}

class Transponder {
  id;
  0..1 -- 0..1 Craft;
}

class GPSCoord {
   Float lattitide;
   Float longitude;
}
      

Load the above code into UmpleOnline

 

Canal Lock State Machine

Canal Lock State Machine

See also the class diagram and requirements for the canal system.

Example

// UML state machine diagram for a canal lock, represented in UML 

class Lock
{
  Boolean boatGoingDown = false;
  Boolean boatGoingUp = false;
  Boolean boatBlockingGate = false;
  
  lockState {
    BothDoorsClosedLockFull {
      // Waiting for boat
      boatRequestsToEnterAndGoDown -> OpeningUpperGate;
      boatRequestsToEnterAndGoUp -> LoweringWater;
    }

    OpeningUpperGate {
      upperGateFullyOpen -> UpperGateOpen;
    }

    UpperGateOpen {
      entry / {setBoatGoingUp(false);}
      boatInLockRequestingToGoDown -> / {setBoatGoingDown(true);} ClosingUpperGate;
      after3minutes [!boatBlockingGate] -> ClosingUpperGate;
    }

    ClosingUpperGate {
      upperGateFullyClosed [boatGoingDown]-> LoweringWater;
      upperGateFullyClosed [!boatGoingDown]-> BothDoorsClosedLockFull;   
    }
    
    LoweringWater {
      waterLevelMatchesDownStream -> OpeningLowerGate;
    } 
    
    
    BothDoorsClosedLockEmpty {
      // Waiting for boat
      boatRequestsToEnterAndGoUp -> OpeningLowerGate;
      boatRequestsToEnterAndGoDown -> RaisingWater;
    }

    OpeningLowerGate {
      lowerGateFullyOpen -> LowerGateOpen;
    }

    LowerGateOpen {
      entry / {setBoatGoingDown(false);}
      boatInLockRequestingToGoUp -> / {setBoatGoingUp(true);} ClosingLowerGate;
      after3minutes [!boatBlockingGate] -> ClosingLowerGate;
    }

    ClosingLowerGate {
      lowerGateFullyClosed [boatGoingUp]-> RaisingWater;
      lowerGateFullyClosed [!boatGoingUp]-> BothDoorsClosedLockEmpty;   
    }
    
    RaisingWater {
      waterLevelMatchesUpStream -> OpeningUpperGate;
    } 
  }
}

      

Load the above code into UmpleOnline

 

Card Games

This system will allow players to play card games such as Whist and Oh Hell online.

The system should manage the cards in a deck of cards, the players (including who is dealer), the hands of cards each player has, the tricks, the pile of cards on the table. It should also manage the matches between players. Use some background research to improve these simple requirements.

Example

// Umple class diagram representing card games in the Oh Hell and Whist family

class Card {
  suit;  // "hearts", "clubs", "diamonds", "spades" 
  rank;  // A23456789JQK
  Boolean isJoker; // suit and rank are null for a Joker
}

class CardSet {
  // Could be a complete deck or a trick
  1 -- * Card;
}

class NotDealtCardSet {
  // This would be initialized with a complete 52-card set
  // at the start of each game
  // During dealing, the cards would be distributed to players
  isA CardSet;
}

class Trick {
  // A group of cards with one contributed by each player, and
  // eventually won by a player
  // One is built after each player has played a card
  isA CardSet;
}

class Player {
   // These are the people playing.
   name;

   // A hand is dealt at the start of a game
   // The cards a player has in his or her hand
   0..1 -- * Card hand; 

   // The tricks won by a player this game
   1 -- * Trick; 
   
   // All hands and tricks are cleared at the end of each game
   // ready for dealing again

   // The following is used only in Oh Hell
   Integer currentTricksBid;
}

class ScoringTeam {
   // for Oh Hell, it is each player for himself, so there is one player
   // for Whist there are partners, so there are two players
   1 -- 1..2 Player;
   
   // The score that each team has accumulated so far
   // based on tricks taken or difference between tricks and bid
   Integer score;
}

class Match {
  // A match is played in a number of games
  Boolean isWhist; // True if whist; false if Oh Hell  

  // The following determines the players
  // the first player in the first team deals first
  * -- 2..* ScoringTeam; // Exactly 2 if Whist
  
  Integer scoreToWin; // The score agreed to in order to declare winner

  1 -- * Game games; // Games continue until a player or team wins
  // Assume that the last game in games is the current one
}

class Game {
   trumps; // a suit (if any) that is the trumps for this game
   
   // One player is the dealer each game
   // The dealer deals out all or most of the cards at the start
   // Players take turn laying down cards to form the next trick
   * -- 1 Player dealer;
   
   // As the cards are laid down the following set is created.
   // After all players have contributed a new trick is created from the
   // following and awarded to a player
   0..1 -- * Card currentTrickBeingBuilt;

   * gameLed -- 0..1 Player currentLead; // the player next to lay down a card
}

class Card
{
  position 125 15 135 100;
}

class CardSet
{
  position 186 153 109 45;
  position.association Card__CardSet 30,0 31,100;
}

class NotDealtCardSet
{
  position 129 244 123 45;
}

class Trick
{
  position 278 245 109 45;
}

class Player
{
  position 43 429 192 82;
  position.association Card:hand__Player 7,0 0,88;
}

class ScoringTeam
{
  position 561 411 122 64;
  position.association Player__ScoringTeam 0,31 192,55;
}

class Match
{
  position 532 48 159 82;
  position.association Match__ScoringTeam 120,82 60,0;
  position.association Game:games__Match 30,82 72,0;
}

class Game
{
  position 442 280 123 64;
  position.association Game__Player:currentLead 11,64 192,11;
  position.association Card:currentTrickBeingBuilt__Game 0,10 135,50;
  position.association Game:gameLed__Player:currentLead 24,64 192,30;
  position.association Game__Player:dealer 0,38 192,10;
}


      

Load the above code into UmpleOnline

 

Pizza Delivery

Requirements for this system are as follows:

A take-out pizza restaurant wants to set up an online ordering system. A customer must have an account to use the system. When the customer creats his or her account, the following information is stored: Email address (which becomes the user id), contact phone number, password, name, address, preferred credit card number, and credit card expiry date. When the customer creates an order the following information is stored: The time the order was placed, the address for delivery, the contact phone number, the total price, the credit card number charged, the expiry date of the credit card, the items ordered and the total price. An item can be pizza or drinks. For each pizza item, the information stored will include the kind of pizza (thin crust, thick crust or gluten-free crust), the size (small, medium, large), the list of toppings (e.g. cheeze, bacon, vegetables, etc.), the number of items like this (e.g. 10 would mean 10 identical pizzas) and the total price for this pizza item. For each drink item, the information stored is type, size, number, and total price. The system also records each delivery: Associated with each delivery is the name of the delivery driver; the time the driver picked up the order(s) and the time each order was delivered. A driver may take more than one order on a delivery run.

Example

// UML Class diagram representing a system for taking online orders for Pizza

class Account
{
  emailAddress;
  contactPhoneNumber;
  password;
  name;
  address;
  preferredCredCard;
  expiryDate;
  0..1 -- * Order;
}

class Order
{
  timePlaced;
  contactPhoneNumber;
  Float totalPrice;
  creditCardCharged;
  expiryDate;
  1 -- * OrderItem;
}

class OrderItem
{
  Integer number;
  Float totalPrice;
}

class PizzaOrder
{
    isA OrderItem;
kind;
  * -> * ToppingType toppings;
  * -> 1 StandardPizzaSize;
}

class ToppingType
{
  description;
}

class StandardPizzaSize
{
  sizeLabel;
}

class DrinkOrder
{
    isA OrderItem;
    drinkSize;
size;
}

class Delivery
{
  Time timePickedUp;
  Time timeDelivered;
  * -- 0..1 Driver;
  0..1 -- 1..* Order;
}

class Driver
{
  name;
}


      

Load the above code into UmpleOnline

 

Community Association

Requirements for this system are as follows:

You are in charge of the website of a community. Residents in the community can sign up to join the community association for a fee of $30. If they do, then they can vote for the executive of the association and can use facilities and attend certain events for free. Only one membership is required per residence and it must be renewed by the end of October each year (it is valid for one year). For each member the system stores the street address, apartment number (if there is one) the email address, the telephone number, and the names of the residents. Anyone under 18 is flagged, as there are special events for these people. The community runs a rink in the winter and three tennis courts in the summer. Members of the community association are given priority to sign up for blocks of time in these facilities, to a maximum of four hours per week. Residents who are not members can sign up 24 hours before their booked time, if there are still any free time slots. When a non-member signs up in this way, they need to give their name, street address and email address. Some time slots in the rink and tennis courts are left unbooked for free 'first-come-first-served' access'

@@example @@source CommunityAssociation.ump @@endexample

Co-Op Education

Requirements for a University System to Manage Co-Op Programs

The co-op system works as follows. Employers contact the university and list potential jobs. Each job has a description, employer, location, start and end date, and a list of programs (e.g. SEG, CSI, MCG) for which it is applicable.

Each student in the system has a name, student number, list of available time slots (when they are not in courses, or not doing interviews), resume and transcript.

Students in various programs apply for jobs. Students choose a set of jobs they are interested in. The system shows the list of interested students to employers, and employers pick a set of students to interview. The system sets interview times that match the employee’s and student’s availability (set of available time slots).

At the end of the process, the system arranges for the employer to offer each job to a student. If the first student does not accept, the system arranges for other students (the employer’s second, third choices, etc. ) to be offered the job

Example

// UML class diagram in Umple showing the data managed by
// a co-operative education system that has to place students with employers

class Program
{
  name;
  1..* -- * Student;
}

class Application
{
  * -- 1 Student;
  * -- 1 Job;
  1..* -- 0..1 Interview;
  1 -- 0..1 Offer;
}

class Job
{
  description;
  location;
  Date startDate;
  Date endDate;
  * -- 1..* Program;
}

class Employer
{
  name;
  1 -- * Job;
  0..1 -> * TimeSlot;
}

class Interview
{
  location;
  0..1 -> 0..1 TimeSlot;
}

class TimeSlot
{
  startTime;
  endTime;
  status;
}

class Student
{
  Integer stNum;
  1 -- 1 Transcript;
  0..1 -> * TimeSlot;
}

class Resume
{
  text;
  0..1 -- 1 Student;
}

class Transcript
{
  text;
}

class Offer
{
  ranking;
  Boolean accepted;
}


      

Load the above code into UmpleOnline

 

Vending Machine Classes

The following are basic requirements for a vending machine

A vending machine dispenses a variety of products. Each product is held in one or more dispensers, identified by slot and row in the machine. The system keeps track of the number of each product type in each dispenser, so it knows when a dispenser becomes empty.

The vending machine has several coin holders. Each coin holder can contain a specific type of coin worth a particular number of cents, and with a certain weight and diameter. The system tracks the number of coins in each holder, so it can determine whether it can give change, and what coins it should give as change when somebody buys a product. Each holder also has a maximum capacity The system keeps an electronic record of each successful purchase (transaction); it records the product dispensed from a dispenser and the number of coins added (i.e. paid by the customer) or deleted (i.e. given as change) from coin holders.

Example

// UML state machine diagram of a vending machine
// There is also a class diagram example separately
class VendingMachine
{
  controlUnit {
    ReceivingMoney {
      pressSelection  -> ReceivingMoney;
      enterCoin  -> ReceivingMoney;
      pressSelection -> DeliveringItem;
    }

    DeliveringItem {
      deliveryComplete  -> Waiting;
      deliveryComplete -> ReturningMoney;
    }
    
    ReturningMoney {
      retunringComplete -> Waiting;
    }
    
    Waiting {
      enterCoin -> ReceivingMoney;
    }
  }
}
      

Load the above code into UmpleOnline

 

Routes And Locations

This example has been built for the Comparing Modeling Approaches Workshop

Example

// RoutesAndLocations.ump  Class diagram represented in Umple
//
// Author: Timothy C. Lethbridge

namespace routesAndLocations;

/* 

This file describes reusable model elements that are used in the 
bCMS Crisis Management System. It is necessary to have a rudimentary
Graphical Information System such as described in this submodel as part
of bCMS in order to plan routes and to track where crises are. This file
has the necessary classes.

*/

/* 
 * A CityMap contains the precompiled streets and landmarks
 * This must be read in from the database on system initialization
 */
class CityMap {
  singleton;
  0..1 -> * Landmark fireStn;
  0..1 -> * Landmark policeStn;
  0..1 -> * Landmark otherLm;
  0..1 -> * NamedRoad;
}
  
/*
 * A Location describes a place such as an intersection, landmark, bend in a road, etc.
 */
class Location {
  Float lattitude;
  Float longitude;
}

class Landmark {
  isA Location;
  
  // Name of landmark (name of fire station, business, address)
  description;  
  landmarkType { fireStation { } policeStation { } touristDestination { } other { } } 
}

/*
 * RoadNodes are places where RoadSegments connect. A node with just one incoming
 * and one outgoing is used to handle changes in direction, e.g. as a road turns
 * a corner, changes in speed limit, changes in number of lanes, and other factors.
 * When there is more than one outgoing or incoming, the node represents points
 * where traffic flow can split and join.
 * A crossroads is one type. Entry into a roundabout would be another,
 * Highway merges and exits are other kinds as are parking lots and entries
 * into or out of fire stations..
 *
 * RoadSegments leaving the city lead to no RoadNode
 * RoadSegments entering the city come from no RoadNode
 */
class RoadNode {
  Integer id;
   // Could be at a landmark
  0..1 -> 1 Location nodeLocation;
  0..1 end -- * RoadSegment incomingRoads;
  0..1 start -- * RoadSegment outgoingRoads;
}

class Intersection {
  isA RoadNode;
  // illegal, but possible turns for police and fire
  0..1 -> * Turn illegalTurns;
  // Impossible turns , e.g. because of barriers, turning radius
  0..1 -> * Turn impossibleTurns;
}

/* 
 * Turns are used to model illegal turns, e.g. turning left
 * when there is 'no left turn' allowed, or 'no U turn' allowed.
 */
class Turn {
  RoadSegment turnFrom;
  RoadSegment turnTo;
}

/*
 * A named road might have the name of a street, the number of
 * a highway, etc. A RoadSegment can have several names because
 * for example, sometimes several numbered highways share a segment
 */
class NamedRoad {
  name;
  
  // Most roads have two directions, e.g. North and South
  direction;  
  
  // Listed in order
  * -- 1..* RoadSegment segments; 
}
  
/*
 * A RoadSegment represents a section of road on which a vehicle can drive.
 * The ends of each segment have been modeled using RoadNodes.
 * Note that distance can be calculated from the speed limit, and locations
 */
class RoadSegment {
  Integer speedLimit;
  
  // Indicator of real-time congestion; 0=blocked
  Integer currentReportedSpeed; 
  Integer lanes;
  
  // The following are used to determine addresses
  Integer streetNumberAtStart;
  Integer streetNumberAtEnd;
  * -> * RoadSegment inverseSegments;
}

/* 
 * A route is a plan to get from one location to another
 * It is built by algorithms that traverse the nodes and arcs of the map
 * taking into account speed, congestion, etc.
 */
class Route {
   // Ordered list of segments
   0..1 -> 1..* RoadSegment;

   // Time seconds at current flow speeds
   Integer estimatedTime; 
}

      

Load the above code into UmpleOnline

 

Coordination State Machine

This example has been built for the Comparing Modeling Approaches Workshop

Note that this file is too large for the 'Open In UmpleOnline' to work in most browsers. You will need to copy the text to the clipboard and paste it into UmpleOnline.

Example

// CoordinationStateMachine.ump
// This UML state machine diagram in Umple is for the
// bCMS car crash management system
// See http://cserg0.site.uottawa.ca/cma2012/CaseStudy.pdf
// and http://www.cs.colostate.edu/remodd/v1/content/repository-model-driven-development-remodd-overview
// Author: Timothy C. Lethbridge

/* 
 * State machine for co-ordination of the
 * crisis, as seen from one SC. If  
 * communication is operating properly the
 * other coordinators' state machines will
 * generally be in the same states and
 * substates.
 *
 * Modelled given Section 4 of the requirements
 * This is a mixin to class crisis.
 */
class Crisis {

  // Number of ms allowed to negotiate routes,  
  // establish credentials
  Integer timeoutInMs = 20000;
  
  // True if we are the initiator of the crisis 
  // request, false otherwise
  Boolean thisSideInitiator;
  Boolean thisSideInitiatorOfTermination;
  
  Boolean routeAgreedYet;
  
  // True of we are the PSC, false of we are  
  // the FSC
  Boolean police;

  // Top level state machine
  crisisCoordinationStage {
  
    // 0. When initiated the crisis is in 
    // noCrisis state
    // It has been created but not yet 
    // populated, awaiting initiation
    // of coordination and data..
    noCrisis {
      entry / {setThisSideInitiator(false);}
      // We are initiating and requesting the 
      // other side to respond
      initiateCrisis / {
        setThisSideInitiator(true);
        sendInitiateCrisisRequestToOtherSC(); 
        } -> establishingCommunication;

      // We are responding to a request from 
      // the other SC 
      receiveInitiateCrisisRequest -> 
        establishingCommunication;
    }
    
    // 1. Establish communication and 
    // identification when a crisis begins
    establishingCommunication {
      entry / {sendSecureCredentials();}
      secureCredentialsConfirmed -> 
        managingCrisis;
      
      // Return to idle after some delay if 
      // other side initiated and did not
      // respond. It might have been a 
      // hacker. Alternatively if there is a
      // real crisis, normal manual processes 
      // would happen.
      after (timeoutInMs) 
        [!isThisSideInitiator()] -> noCrisis;
    }

    // Managing crisis involves continually 
    // exchanging information
    // Negotiating or renegotiating routes and 
    // other crisis details
    // These are handled concurrently.
    managingCrisis {
      // A crisis is underway. We initially 
      // start with empty data
      // which will be populated over time
      entry / {initiateEmptyCrisis(); }
    
      // 2,4,5,6. Exchanging details about what 
      // each knows about the crisis
      // So the information each coordinator 
     // has is the same.
      exchangingDetails {
        // Requirement Scenario 2
        ourUpdateToCrisisData
          / {sendCrisisData();}
          -> exchangingDetails;
        receiveCrisisData
          / {updateCrisisData();}
          -> exchangingDetails;
        
        // Requirement Scenario 4
        ourVehicleDispatched
          / {sendVehicleDispatch();}
          -> exchangingDetails;
        receiveVehicleDispatched
          / {updateTheirDispatch();}
          -> exchangingDetails;
        
        // Requirement Scenario 5
        ourVehicleArrived
          / {sendVehicleArrived();}
          -> exchangingDetails;
        receiveVehicleArrived
          / {updateTheirArrival();}
          -> exchangingDetails;
        
        // Requirement Scenario 6
        ourVehicleMetObjective
          / {sendVehicleMetObjective();}
          -> exchangingDetails;
        receiveMetObjective
        / {updateTheirMetObjective();}
        -> exchangingDetails;
        
        // Requirement 5.a - breakdown
        breakdown / {dispatchAndUpdateOther();} 
          -> exchangingDetails;
        
        // Requirement 5.b - 
        // congestion/blockage
        // TO DO
        
        // Requirement 5.c escalate crisis - 
        // renegotiate routes
        // TO DO
        
        
      } // End of exchangingDetails
        //concurrent substate
      ||
      
      // 7. Both parties must agree to close 
      // the crisis; either can initiate
      crisisEndManagement {
      
        // Normal substate of crisisEndManagement - no end in sight yet
        ongoingCrisis {
        
          // We could initiate termination
          initiateTermination / {
            setThisSideInitiatorOfTermination(true);
            sendTerminationRequestToOtherSC();
            } -> waitingForTerminationConfirmation;
          receiveTerminationRequestFromOtherSC 
          -> 
            waitingForUserTerminationAgreement;
        }
        
        waitingForUserTerminationAgreement {
          do {confirmWithUserToTerminate();}
          confirmTermination -> tearDown;
          after (timeoutInMs) -> ongoingCrisis;
        }
            
        // Substate of where we are waiting for 
        // the other end to agree
        waitingForTerminationConfirmation {
          receiveTerminationConfirmation
            -> tearDown;
          
          // If the other side has not agreed, 
          // we keep the crisis active
          after (timeoutInMs) -> ongoingCrisis;
        }
        
        // End of crisis
        tearDown {
          entry / {deleteCrisis();}
          -> noCrisis;
        }
      } // End of crisisEndManagement 
        // concurrent substate
      ||

      // 3. Negotiating route plan
      negotiatingRoutePlan {
    
        // Negotiation happens in parallel with 
        // reporting timeout
        negotiation {
          entry / {setRouteAgreedYet(false);}
          informOfNumberOfVehicles
            / {sendNumberOfVehicles();}
            -> negotiation;
          receiveNumberOfVehicles [isPolice()] 
            -> planningRoute;
          receiveRouteProposal [!isPolice()]
            -> approvingRoute;
          
          // Requirement 3.3.a2.a1
          receiveNoAgreeableRoute
            [!isPolice()] -> noRouteAgreement;
          
          // The PSC plans the route -- only 
          // PSC can be in this state
          planningRoute {
             do {planRoute();}
             routePlanComplete
               / {sendPlanToFSC(); }
               -> awaitingRouteApproval;
             
             // Requirement 3.3.a2.a1 - no more 
             // possible routes
             noMoreRoutes
               / {sendNoMoreRoutesToFSC(); }
               -> noRouteAgreement;
          }

          // The FSC approves the route  -- 
          // only FSC can be in this state
          approvingRoute {
            do {userConfirmRouteAcceptable();}
            routeAcceptable
              / {sendApprovalToPSC();}
              -> routeAgreed;
            routeUnacceptable
              / {sendDisapprovalToFSC();}
              -> negotiation;
          }
          
          // The PSC awaits for approval from 
          // the FSC. Only the PSC can be in 
          // this state
          awaitingRouteApproval {
            receiveApprovalFromFSC
              -> routeAgreed;
            
            // Requirement 3.3.a - FSC 
            // disagrees
            receiveDisapprovalFromFSC / {
              addRouteToDisapprovedChoices(); 
              } -> planningRoute;
          }
          
          routeAgreed {
            entry / {setRouteAgreedYet(true);}
          }
          
          noRouteAgreement {
             // requirement 3.3.a2.a1
          }
        } // End of Negotiation concurrent 
          // substate of negotiatingRoutePlan
        ||
        managingTimeliness {
          timeAcceptable {
            // Requirement 3.a1. Negotiations 
            // are taking excessive time
            after (timeoutInMs)
              [!isRouteAgreedYet()]
              -> timeUnacceptable;
          }
          timeUnacceptable {
            // Although negotiations may yet 
            // complete, we are going to send
            // out our own vehicles because too 
            // much time has passed
            do {
              promptAndLogReasonForTimeout(); }
          }
        } // End of managingTimeiness 
          //concurrent substate of 
          // negotiatingRoutePlan
      } // End of NegotiatingRoutePlan 
        //concurrent substate
    } // End of Managing Crisis top level state
  } // End of crisisCoordinationStage state 
    // machine
} // End of state machine mixin for 
  // Crisis

      

Load the above code into UmpleOnline

 

Privacy and Risks

 

Risks in using Umple and UmpleOnline

License: All use of Umple and UmpleOnline is subject to the Umple MIT license. Please read it carefully, since it disclaims liability. This is not because we don't want to be 'good engineers' and take responsibility for work, rather it is because we are following the open source model, which allows a wide variety of people to modify Umple.

Risk due to support by hosting organizations: UmpleOnline is hosted at the University with funds from research grants. Should these research grants cease, support for Umple may cease unless others take over responsibility for hosting. Similarly, the code is hosted on Google Code. If Google decides to cease hosting projects for free, Umple would need to be hosted somewhere else.

Risk of deprecation, missing features and defects: It is possible that code which works today may cease working in the future. Development is performed by students and in the context of research. You will therefore find incomplete features and bugs. We encourage you to report new ones (and fix them) and to realize that you may need to work around the existing ones. That said, we do use test-driven development to maintain what we believe is a high level of quality.

Limitations of UmpleOnline: The purpose of UmpleOnline is purely to allow people to explore Umple and model-oriented programming, particularly in an educational context. UmpleOnline is not intended to be a commercial or open source development tool; this is one of the reasons why it is only capable of storing a single Umple file per user session. If you want to do serious development in Umple, with multiple files, you should download it.

Not certified for safety critical or mission critical use: At the current time Umple-generated code should not be used for mission-critical or safety critical uses, including software for any device that may pose a safety risk if it performs incorrectly, or software that would cause economic damage if it failed. We intend that, in time, Umple and tools like it will in fact help improve safety and reliability. But at the current time we have not subjected Umple to the rigorous validation it needs for such uses, and there are many known issues that would preclude such current use.

Need to apply best practices: Should you choose to use Umple for production use, it is critical that you follow rigorous software engineering practices including (but not limited to): Requirements analysis, careful design and thorough testing. See here for a list of Umple best practies.

 

Privacy: Saving of data in UmpleOnline

Models entered in UmpleOnline are automatically stored on servers at the University of Ottawa. Each time you type and pause for three seconds, each time you make an edit to a diagram, and each time you generate code, your data is saved. The data includes one or more .ump files, plus the data you have generated from those files (Java code etc.).

Data saved automatically in this way remains stored at the University of Ottawa for up to two days. This is so you can continue an editing session, even if you walk away from your computer for an extended period. We have an automated process that will normally delete such data after two days. However we reserve the right to record general statistics about the size of models and other uses of Umple tools before we delete such data.

If you choose 'Create a Bookmarkable URL' then your model is stored, indefinitely, subject to deletion rules described below. Such a file can be edited and deleted by anyone to whom you give the URL, or by anyone who guesses the URL.

If we detect abuse of UmpleOnline, we reserve the right to attempt to track the user using such tools as the originating IP address, and to block access from such an address or address range.

We do intend to install tools to survey users about their experiences with Umple. We will likely use external tools such as SurveyMoney for such surveys; people who complete such surveys would then be subject to the privacy rules of such external tools. Users would be requested to give informed consent prior to taking such a survey, and such informed consent would first be approved by the University of Ottawa's Research Ethics Board.

 

Sharing of personal data in UmpleOnline

The only data saved by UmpleOnline is the model you create, either graphically or textually or both. There is currently no login mechanism so there is no userid, name or other personal data associated with your model. We may impose a login requirement in the future, but in that case we would only store the minimum of data (loginID, your name, an encrypted salted password, and an email address for account confirmation, to contact you and to allow for password reset).

You may, however, embed (at your choice) confidential information in the code or models you write in UmpleOnline. It is important for you to realize that this information is accessible to others.

Since no userid is currently associated with UmpleOnline models, we have no way of determining who has saved which models at the current time. We cannot guarantee to be able to recover any file you may have 'lost'. Nor can we determine whether anyone else has looked at or modified your files.

 

Data deletion

You may delete your own model in UmpleOnline: Simply select all the text and delete it. To delete all records of generated code, it is suggested that you replace your model by a single line of code (such as class X {} and then generate code from it (generate code in all formats you have previously generated).

Staff at the University of Ottawa reserve the right to delete models for any of the following reasons:

 

Access and use by others

If somebody is able to guess the URL of your model, or you give it to them, then they can modify and delete your model. Important models should therefore be saved using other means. Instructions for how to do that are here.

 

Anonymity

There is currently no login mechanism to UmpleOnline so there is no way to trace users, as stated earlier. This may change in the future

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.

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
    |Php
    |RTCpp
    |SimpleCpp
    |Ruby
    |Cpp
    |Json
    |StructureDiagram
    |Yuml
    |Violet
    |Umlet
    |Simulate
    |TextUml
    |Scxml
    |GvStateDiagram
    |GvClassDiagram
    |GvClassTraitDiagram
    |GvEntityRelationshipDiagram
    |Alloy
    |NuSMV
    |Papyrus
    |Ecore
    |Xmi
    |Xtext
    |Sql
    |Umple
    |UmpleSelf
    |USE
    |Test
    |SimpleMetrics
    |Uigu2] ( [=suboptionIndicator:-s
    |--suboption] " [**suboption] " )* ;

generate_path : generate [=language:Java
    |Php
    |RTCpp
    |SimpleCpp
    |Ruby
    |Cpp
    |Json
    |StructureDiagram
    |Yuml
    |Violet
    |Umlet
    |Simulate
    |TextUml
    |Scxml
    |GvStateDiagram
    |GvClassDiagram
    |GvClassTraitDiagram
    |GvEntityRelationshipDiagram
    |Alloy
    |NuSMV
    |Papyrus
    |Ecore
    |Xmi
    |Xtext
    |Sql
    |UmpleSelf
    |USE
    |test] " [**output] " [=override:--override
    |--override-all]? ( [=suboptionIndicator:-s
    |--suboption] " [**suboption] " )* ;

Umple Grammar

Below is the complete grammar for Umple . This page is generated automatically from the grammar used to parse Umple code.

Refer to the Grammar Notation section for more explanation of the EBNF syntax used here.



// The master source of this first part of the Umple grammar is available at
// http://code.google.com/p/umple/source/browse/trunk/cruise.umple/src/umple_core.grammar
// The html rendering is generated from the master and appears in the Umple User manual
// at page http://grammar.umple.org

// Copyright: All contributors to the Umple Project
// This file is made available subject to the open source license found at:
// http://umple.org/license

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


umpleProgram- : ( [[comment]] | [[directive]] | ; )*


// 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- : [[glossary]]
    | [[generate]]
    | [[distribute]]
    | [[generate_path]]
    | [[filter]]
    | [[useStatement]]
    | [[namespace]]
    | [[tracerDirective]]
    | [[entity]]
    | [[debug]]
    | [[strictness]]
    | [[toplevelExtracode]]
    | [[toplevelException]]


// A glossary item is used to fine tune pluralization during code generation
glossary : glossary { [[word]]* }

word : [singular] : [plural] ;

distribute :distributable [=distributeTech:RMI
    |WS]? [=distributePattern:0
    |1
    |2
    |3]? [=distributeVal:on
    |off
    |forced] ;

// 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]] ) ;

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


// 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
    |Php
    |RTCpp
    |SimpleCpp
    |Ruby
    |Cpp
    |Json
    |StructureDiagram
    |Yuml
    |Violet
    |Umlet
    |Simulate
    |TextUml
    |Scxml
    |GvStateDiagram
    |GvClassDiagram
    |GvClassTraitDiagram
    |GvEntityRelationshipDiagram
    |Alloy
    |NuSMV
    |Papyrus
    |Ecore
    |Xmi
    |Xtext
    |Sql
    |Umple
    |UmpleSelf
    |USE
    |Test
    |SimpleMetrics
    |Uigu2] ( [=suboptionIndicator:-s
    |--suboption] " [**suboption] " )* ;


generate_path : generate [=language:Java
    |Php
    |RTCpp
    |SimpleCpp
    |Ruby
    |Cpp
    |Json
    |StructureDiagram
    |Yuml
    |Violet
    |Umlet
    |Simulate
    |TextUml
    |Scxml
    |GvStateDiagram
    |GvClassDiagram
    |GvClassTraitDiagram
    |GvEntityRelationshipDiagram
    |Alloy
    |NuSMV
    |Papyrus
    |Ecore
    |Xmi
    |Xtext
    |Sql
    |UmpleSelf
    |USE
    |test] " [**output] " [=override:--override
    |--override-all]? ( [=suboptionIndicator:-s
    |--suboption] " [**suboption] " )* ;


// Use statements allow incorporation of other Umple files. See UseStatements
useStatement : use [use] ;


toplevelExtracode : top [top] [[moreCode]]


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


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


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

inlineComment- : // [**inlineComment]

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


// The Debug statement turns on debugging in code generation. For developer use only
debug- : [=debug] ;


// Instructs a class or method to be abstract
abstract- : [=abstract] ;

// The master of this second part of the Umple grammar is available at
// http://code.google.com/p/umple/source/browse/trunk/cruise.umple/src/umple_classes.grammar

// Copyright: All contributors to the Umple Project
// This file is made available subject to the open source license found at:
// http://umple.org/license

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


//The external keyword declares a class that is defined in a different
// compilation unit
externalDefinition : external [=interface]? [name] { [[classContent]]* }


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


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


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


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


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

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


// 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]]
    | [[constantDeclaration]]
    | [[constantDeclarationDeprecated]]
    | [[abstractMethodDeclaration]]
    | [[position]]
    | [[displayColor]]
    | [[isA]]
    | [[distributableInterface]]
    | [[exception]]
    | [[extraCode]]

distributableInterface : [[distributable]]

// Constants in interfaces (e.g. const String ACONSTANT="aValue";)
// Note: in Classes const is a modifier
constantDeclarationDeprecated : constant [[typedName]] (= [**value])? ;

constantDeclaration : const [[typedName]] (= [**value])? ;



distributable- : [=distributable:distributable] [=distributeTech:RMI|WS]? ;

proxyPattern- : [=proxyPattern:proxyPattern] ;

moreCode- : [[codeLangs]] { [**code] }

codeLangs- : ([=codeLang:Java
    |RTCpp
    |SimpleCpp
    |Cpp
    |Php
    |Ruby
    |Alloy
    |UmpleSelf] ( , [=codeLang:Java
    |Alloy
    |RTCpp
    |SimpleCpp
    |Cpp
    |Php
    |Ruby
    |UmpleSelf] )* )?


// Methods: The code in concrete methods is passed to the base language
// See user manual page MethodDefinition
concreteMethodDeclaration : [=modifier:public|protected|private]? [=static]? [type]? [[methodDeclarator]] [[methodThrowsExceptions]]? [[methodBody]]
    | [=modifier:public|protected]? [=abstract] [type]? [[methodDeclarator]] [[methodThrowsExceptions]]? ;

abstractMethodDeclaration : [type] [[methodDeclarator]] ;

methodBody- : ( [[codeLangs]] { ( [[precondition]] | [[postcondition]] )* [**code] } )+

methodDeclarator : [methodName] [[parameterList]]

methodThrowsExceptions : throws [~exception] ( , [~exception] )*

parameterList : ( ([[parameter]] ( , [[parameter]] )* )? )

parameter : [[typedName]]


// Details of associations: See manual page AssociationDefinition

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

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

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

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

singleAssociationEnd : [[multiplicity]] [type] [~roleName]? ;


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

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

isSorted- : sorted { [priority] }


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

simpleAttribute- : [~name] ;

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

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

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



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

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


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


// Anything inside a class that is not parsable by Umple is passed on to the base language
// compiler. To raise warnings when this occurs, use the strictness directive.
extraCode- : [**extraCode]


list- : [!list:\[\s*\]]

typedName- : [type]? [[list]]? [~name]

traitDefinition : trait [name] [[traitParameters]]? { [[traitContent]]* }

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

traitParameters : < [[traitFullParameters]] ( , [[traitFullParameters]] )* >

traitFullParameters : [~parameter] ([[traitParametersInterface]])? ( = [~defaultType] )?

traitParametersInterface- : isA [~tInterface]( & [~tInterface])*

requiredModelElements : require ([[requiredState]] | [[requiredEvent]])

requiredState : [smName] ;

//.[~stateName](.[~stateName])* ;
requiredEvent : [smName] ( ( [parameter] ( , [parameter] )* )? ) ;

//.[~stateName](.[~stateName])*


//iE = Include Exclude
AllInclusionExclusionAlias- : [[InclusionExclusionAlias]] ( , [[InclusionExclusionAlias]] )*

InclusionExclusionAlias- : [[functionIncludeExcludeAlias]] | [[StateMachineIncludeExcludeAlias]]

functionIncludeExcludeAlias- : [[functionInExAlias]] ( , [[functionInExAlias]] )*

functionInExAlias- : [[functionAliasName]] | [[iEFunction]] | [[traitAppliedParameters]]

iEFunction : [=modifier:+|-] [~methodName] [[iEParameterList]]

iEParameterList : ( ( [parameter] ( , [parameter] )* )? )

functionAliasName : [=modifier:+]? ( ( [~smName]
    | [!smPattern:\d+|[**]]) .)? [~methodName] [[iEParameterList]] as [[IEVisibilityAlias]]


IEVisibilityAlias- : ([[IEVisibility]] [~aliasName]?) | ([~aliasName])

IEVisibility- : [=iEVisibility:public|private|protected]

traitAppliedParameters : [~pName] = [~rName]


StateMachineIncludeExcludeAlias- : [[ StateMachineInExAlias]] ( , [[StateMachineInExAlias]] )*

StateMachineInExAlias- : [[StateMachineAliasName]] | [[iEStateMachine]]

//| [[StateMachineTransitionAlias]]
StateMachineAliasName : ([=iEStateMachineModifier:+])? [~smName] ([[StateNames]])? as [~smDesName] ([[DesStateNames]])?

StateNames : . [~sName] ( [[StateNamesPassing]] )*

DesStateNames :[[StateNames]]

StateNamesPassing : [[StateNames]]

//iEStateMachine : [=iEStateMachineModifier:+|-] [~smName] [[StateNames]]?
iEStateMachine : [=modifier:+|-] [~smName] ( [[StateNames]] ( ( [[iEParameterList]] [[guardOption]]? )
    | ( . [[guardOption]] ) )? )?

guardOption : [[guard]] | []

//This is for events in state machines
//StateMachineTransitionAlias : ( [~smName] | [!smPattern:\d+|[*]]) . [~eventName] [[iEParameterList]] as [~AliasName]
//This is Umple's grammar for parsing fixml documents
fixml : [[fixmlDefinition]] | [[fixmComment]] | [[fixmlDoc]]

fixmlDoc : <! [**value] >

fixmComment : <?xml [[tagDefinition]]* ?>

fixmlDefinition : <FIXML> [[fixmlContent]]* </FIXML>

fixmlContent : [[endContent]] | [[ extendContent ]]

endContent : < [~name] ( [[tagDefinition]] )* />

extendContent : < [~name] ( [[tagDefinition]] )* > ( [[endContent]]
    | [[extendContent]]
    | [[attContent]])* < ( / ) [~name] >

tagDefinition : [name] = "[**value]"

attContent : < [~name] > [**value:\<] < ( / ) [~name] >

// The master of this second part of the Umple grammar is available at
// http://code.google.com/p/umple/source/browse/trunk/cruise.umple/src/umple_patterns.grammar

// Copyright: All contributors to the Umple Project
// This file is made available subject to the open source license found at:
// http://umple.org/license

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


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

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

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

isAName- : " [**extendsNames] " [[gTemplateParameter]]?
    | [extendsName] [[gTemplateParameter]]?


gTemplateParameter : < [[AllInclusionExclusionAlias]] >


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


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


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


// Aspect oriented code injection: BeforeandAfterStatements
codeInjection- : [[beforeCode]] | [[afterCode]]


parameterTypes : [parameterType] (, [parameterType])*

parameterListing : ( ([[parameterTypes]])? )


injectionOperation : [operationName] ([[parameterListing]])?


beforeCode : before ([=operationSource:custom
    |generated
    |all])? [[injectionOperation]] ( , [[injectionOperation]] )* ([[codeLang]] [[codeLangs]])? { [**code] } ( [[moreCode]] )*

afterCode : after ([=operationSource:custom
    |generated
    |all])? [[injectionOperation]] ( , [[injectionOperation]] )* ([[codeLang]] [[codeLangs]])? { [**code] } ( [[moreCode]] )*

// The master of this part of the Umple grammar is available at
// http://code.google.com/p/umple/source/browse/trunk/cruise.umple/src/umple_state_machines.grammar

// Copyright: All contributors to the Umple Project
// This file is made available subject to the open source license found at:
// http://umple.org/license

// State machine elements in Umple. See user manual page: BasicStateMachines
stateMachineDefinition : statemachine [=queued]? [=pooled]? [name] { [[state]]* }

stateMachine : [[enum]]
    | [[inlineStateMachine]]
    | [[referencedStateMachine]]
    | [[activeDefinition]]


activeDefinition : [=active] [[codeLangs]] [name]? [[moreCode]]+


//Issue 148
inlineStateMachine : [=queued]? [=pooled]? [~name] { ( [[comment]]
    | [[state]]
    | [[trace]]
    | [=||]
    | [[standAloneTransition]])* }

referencedStateMachine : [name] as [definitionName] ( { [[extendedStateMachine]] } | ; )


//Issue 547 and 148
extendedStateMachine# : ( [[comment]]
    | [=changeType:+| - |- |*]? [[state]]
    | [[standAloneTransition]] )*


// An enum is a state machine that has no events
// stateName is prefixed with ~ to match alphanumeric names only.
// This is needed to solve issue 399, which is cause when a terminating } is parsed as part of the statename.
enum : [~name:key] { [~stateName]? (, [~stateName])* }


state : [=final]? [stateName] { [[stateInternal]]* }


//Issue 547 and 148
stateInternal-# : [[comment]]
    | [=changeType:+| - |- |*]? [[stateEntity]]
    | [[standAloneTransition]] |[**extraCode]

stateEntity- : [=||]
    | [[entryOrExitAction]]
    | [[autoTransition]]
    | [[transition]]
    | [[activity]]
    | [[state]]
    | [[trace]]
    | ;


autoTransition : [[activity]]? [[autoTransitionBlock]]


// Autotransitions have no event. The transition is immediately taken
// or taken after the do activity ends[[guard]]? -> [[action]]?
// The action can come before or after the arrow
autoTransitionBlock- : [[guard]]? ( [[action]] -> | -> [[action]] | -> ) [stateName] ;


// A transition guard can come before or after the arrow
// The order of guard and event definition can also be interchanged
transition : ( [[eventDefinition]] [[guard]]
    | [[guard]] [[eventDefinition]]
    | [=unspecified]? [[guard]]
    | [[eventDefinition]])? ( [[action]] ->
    | -> [[action]]
    | -> ) [stateName] ;


//Issue148
standAloneTransition : ( [[eventDefinition]] [[guard]]
    | [[guard]] [[eventDefinition]]
    | [=unspecified]? [[guard]]
    | [[eventDefinition]])? [~fromState] ( [[action]] ->
    | -> [[action]]
    | -> ) [~toState] ;


eventDefinition- : [[afterEveryEvent]] | [[afterEvent]] | [~event] ( [[parameterList]] )?


// The timer in a timed event can be an number, variable, function() or function(num)
afterEveryEvent- : afterEvery ( [!timer:[+*/a-zA-Z0-9_\.-]+(\([0-9\.]*\))?] )

afterEvent- : after ( [!timer:[+*/a-zA-Z0-9_\.-]+(\([0-9\.]*\))?] )


// An action can be executed on a transition, or on entry or exit
action : / [[moreCode]]+

entryOrExitAction : [=type:entry|exit] / [[moreCode]]+


// A do activity is long-lasting and can be interrupted
activity : do [[moreCode]]+


guard : [ [[constraint]] ]

// The master of this part of the Umple grammar is available at
// http://code.google.com/p/umple/source/browse/trunk/cruise.umple/src/umple_traces.grammar

// Copyright: All contributors to the Umple Project
// This file is made available subject to the open source license found at:
// http://umple.org/license

// Trace capabilities of the MOTL sublanguage of Umple.
// See user manual page: ModelOrientedTracingLanguage(MOTL)

// ======= TRACER
// ======= grammar rules - The tool to output the trace: Tracers
tracerDirective : tracer [tracerType] [[tracerOptions]] ;

tracerOptions- : [[logConfig]]* [[traceMessageHeader]]? [tracerArgument]?

logConfig : (root = [rootLevel])
    | (monitorInterval = [monitorInterval])
    | ( [logLevel] ( , [logLevel] )* = [logAppender] ( , [logAppender] )* )

traceMessageHeader : [=switch:on|off] : [option] ( , [option] )*


// ======= TRACE
// ======= grammar rules

trace : [[traceDirective]] | [[traceCase]]


traceDirective : trace [[Prefix]]? [[traceEntity]] [[Postfix]] ;


traceEntity- : [traceEntity] (()? ())? ( , [traceEntity] (()? ())? )*


Prefix : [[PrefixOption]] ( , [[PrefixOption]] )*

PrefixOption- : [=option:set|get|in|out|entry|exit|cardinality|add|remove]


Postfix- : ( [[traceCondition]]
    |[[traceFor]]
    |[[tracePeriod]]
    |[[traceDuring]]
    |[[traceLevel]]
    |[[traceRecord]]
    |[[executeClause]]
    |[[logLevel]]
    |[[traceCaseActivation]] )*

traceCondition : [=conditionType:where|until|after|giving]? [ [[constraintToken]] ]

traceFor- : for [traceFor]

tracePeriod- : period [tracePeriod]

traceDuring- : during [traceDuration]

traceLevel- : level [traceLevel]

traceRecord- : record [[recordEntity]]

recordEntity- : ( only )? ( " [**recordString] " | [traceRecord] ) ( , [traceRecord] )*

logLevel- : logLevel [[logLevelOption]] ( , [[logLevelOption]] )*

logLevelOption- : [=logLevel:trace
    |debug
    |info
    |warn
    |error
    |fatal
    |all
    |finest
    |finer
    |fine
    |config
    |warning
    |severe]

executeClause- : execute { [**traceExecute] }


traceCase : [[traceCaseDef]] | [[traceCaseActivation]] | [[traceCaseDeactivation]]

traceCaseDef- : tracecase [tracecase_name] { [[traceDirective]]* }

traceCaseActivation- : activate [tracecase_act_name] (onAllObjects | onThisThreadOnly)? ;

traceCaseDeactivation- : deactivate [tracecase_deact_name] onThisObject [[deActivateFor]]? ;

deActivateFor- : for [deactivate_for]



//--------- Old rules (left as reference) ---------
//++Tracer
//traceType : tracer [tracerType] ( [=onoff:on|off] : [[tracerOptions]] ( , [[tracerOptions]] )* )* ( [=verbisty:verbose] )? ( [tracerArgument] )* [[log4jConfig]]* ([[tracerOptions]])* ;
//traceType : tracer [tracerType] ( , [tracerType] )* [[log4jConfig]]* ([[tracerOptions]])* ;
//traceType : tracer [=tracerType:Console|File|String|Visual] ( , [=tracerType:Console|File|String|Visual] )* ( [=onoff:on|off] : [[tracerOptions]] ( , [[tracerOptions]] )* )* ( [=verbisty:verbose] )? ( [tracerArgument] )* ;
//tracerOptions- : [[tracerOn]]? [=option:Time|time|Thread|thread|File|file|Line|line|Trace|trace|Trigger|trigger|TraceFile|tracefile|TraceLine|traceline|TriggerLine|triggerline|TriggerFile|triggerfile|Class|class|Object|object|Operation|operation|Name|name|Value|value] [=option:Time|time|Thread|thread|File|file|Line|line|Trace|trace|Trigger|trigger|TraceFile|tracefile|TraceLine|traceline|TriggerLine|triggerline|TriggerFile|triggerfile|Class|class|Object|object|Operation|operation|Name|name|Value|value]*
//tracerOn : on:|off:
//log4jConfig : (root = [rootLevel]) | (monitorInterval = [monitorInterval]) | (OPEN_ROUND_BRACKET) [log4jLevel] ( , [log4jLevel] )* (CLOSE_ROUND_BRACKET) = (OPEN_ROUND_BRACKET) [log4jAppender] ( , [log4jAppender] )* (CLOSE_ROUND_BRACKET)
//--------------------------------------------------
// The master of this part of the Umple grammar is available at
// http://code.google.com/p/umple/source/browse/trunk/cruise.umple/src/umple_constraints.grammar

// Copyright: All contributors to the Umple Project
// This file is made available subject to the open source license found at:
// http://umple.org/license

// 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]] ]

postcondition : [ [name]? post : [[constraint]] ]


invariant : [ ([name] :)? ([[constraint]]) ]

constraintToken : [[constraint]]


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

negativeConstraint : ( ! | not ) ( [[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]]

linkingOpBody : [[constraint]]

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


loneBoolean : [[constraintVariable]]


//must be a boolean //fixing is here!!!
boolExpr : [[constraintVariable]] [[equalityOperator]] [[boolLiteral]]
    | [[boolLiteral]] [[equalityOperator]] [[constraintVariable]]
    | [[boolLiteral]]

boolLiteral : [=literal:true|false]


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

stringExprPlain- : [[constraintVariable]] [[equalityOperator]] [[stringLiteral]]
    | [[stringLiteral]] [[equalityOperator]] [[constraintVariable]]

stringExprOperator- : [[stringComplexExpression]] [[equalityOperator]] [[stringComplexExpression]]
    | [[stringComplexExpression]] [[equalityOperator]] [[stringName]]
    | [[stringName]] [[equalityOperator]] [[stringComplexExpression]]

stringLiteral- : " [**quote] " | ' [**quote] '

stringName- : [[stringLiteral]] | [[constraintVariable]]

stringComplexExpression : [[stringPlusOperator]]

stringPlusOperator- : [[stringName]] ( [=concat:+] [[stringPlusOperator]] )?


//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]]

numberExpression1- : ( [[arithmeticCall]]
    | [[numberName]] ) [[ordinalOp]] ( [[arithmeticCall]]
    | [[numberName]] )

numberExpression2- : ( [[arithmeticCall]]
    | [[constraintVariable]] ) [[equalityOperator]] ( [[arithmeticCall]]
    | [[numberLiteral]] )

numberExpression3- : ( [[arithmeticCall]]
    | [[numberLiteral]] ) [[equalityOperator]] ( [[arithmeticCall]]
    | [[constraintVariable]] )

numberExpression4- : ( [[arithmeticCall]]
    | [[numberLiteral]] ) [[equalityOperator]] ( [[arithmeticCall]]
    | [[numberLiteral]] )

numberLiteral- : [!number:-?[0-9]+([\\.][0-9]+)?]

numberName- : [[numberLiteral]] | [[constraintVariable]]

arithmeticCall : ( ( [[lowArithmeticOperatorCall]]
    | [[highArithmeticOperatorCall]] ) )

lowArithmeticOperatorCall- : ( [[highArithmeticOperatorCall]]
    | [[arithmeticResolve]] )? [=operator:+|-|>>|<<] ( [[arithmeticCall]]
    | [[arithmeticResolve]] )

highArithmeticOperatorCall- : [[arithmeticResolve]] [=operator:*|/|^|%] ( [[highArithmeticOperatorCall]]
    | [[arithmeticResolve]] )

arithmeticResolve- : ( [[arithmeticCall]] ) | [[numberName]]


equalityOperator- : [=equalsOp:==|equals] | [=notequalsOp:!=|/=|=!|=/=]

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


associationExpr : [[constraintVariable]] [[associationOperators]] [[associationLiteral]]

associationOperators- : [=firstOp:cardinality|has] ( [[ordinalOp]] | [[equalityOperator]] | [=all] )?

associationLiteral : [[constraintParameter]] ( , [[associationLiteral]] )?


statemachineExpr : [[constraintVariable]] [[statemachineOperators]] [[statemachineLiteral]]

statemachineOperators- : [=isInOp:is|state] [=ignore:==|in]
    | [=isNotInOp:is|state] ( [=ignore:!=]
    | [=ignore:not] [=ignore:in] )

statemachineLiteral- : [=state]? [~stateName]


constraintVariable- : [[negativeConstraint]] | [[constraintName]]

constraintName : [=new]? [!name:[a-zA-Z_][a-zA-Z0-9_-]*] [[constraintIndexOperator]]* [[constraintParameterList]]? [[constraintScopeOperator]]?

constraintIndexOperator- : [ [!index:[0-9]+] ]

constraintScopeOperator : ( . | -> ) [[constraintVariable]]

constraintParameterList : ( ([[constraintParameter]] ([=comma:,] [[constraintParameter]])*)? )

constraintParameter : [=boolLit:true|false]
    | [[stringLiteral]]
    | [[constraintVariable]]
    | [[numberLiteral]]


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+|[**])] )?



// NOTE: Additional grammar parts deleted while testing is ongoing.
// The master of this part of the Umple grammar is available at
// http://code.google.com/p/umple/source/browse/trunk/cruise.umple/src/umple_structure.grammar
//@author Ahmed M.Orabi {@link ahmedvc@hotmail.com}
//@author Mahmoud M.Orabi {@link mahmoud_3rabi@hotmail.com}

primitiveDefinition : primitive [name] { [[primitiveBody]]* }

primitiveBody- : [[isA]] | [[constraint]]


// Port Definition
portName : ( [~classname] . )? [name]

portMultiplicity : [!portMultiplicity:\[[0-9]+\]]


typedPortName : [~type]? [~portName] [[portMultiplicity]]?

portDefinition : [=modifier:public
    |protected
    |private]? [=inverse:conjugated]? [=direction:in
    |out
    |port] [[typedPortName]] ;


// Port Connectors
portBindingDefinition : ( [~fromClassname] . )? [fromPort] -> ( [~toClassname] . )? [toPort] [[bindinHandler]]

bindinHandler : { [**code] } | ;


// Port Watchlist Definition
portWatch- : ( [[constraintList]] | [[comment]] )*


// Active Method Definition
activeMethodDefinition : [[portWatch]]? [=modifier:public
    |protected
    |private]? [type]? [=activeType:atomic
    |synchronous
    |intercept]? [=active] [[activeMethodDeclarator]] [[activeMethodBody]]+

activeMethodDeclarator : [~methodName] [[parameterList]]?


//activeMethodBody : [[activeDirectionHandler]] { ( [[activeTrigger]] )* [**code] }
activeMethodBody : [[activeDirectionHandler]]? { ( [[comment]] | [[activeTrigger]] | [**code] )* }

activeDirectionHandler : [=direction:forward|inverse] ( , [=direction:forward|inverse] )*


activeTrigger : [[hitchConstraint]]? [[constraintList]]? [=trigger:/] [[activeTriggerBody]] [[thenDefinition]]? [[resolveDefinition]]?

activeTriggerBody- : ( [[deferredList]] | [[activeTriggerDefinition]] )

deferredList : [ [[activeTriggerDefinition]] ( , [[activeTriggerDefinition]] )* ]

activeTriggerDefinition- : [[anonymousTriggerBody]] | [[invoke]]


thenDefinition : .then ( [[anonymousTriggerBody]]? )

resolveDefinition : .resolve ( [[anonymousTriggerBody]]? )


hitchConstraint : [=clause:after|poll] ( [timer] )

constraintList : [ [[basicConstraint]] ( , [[basicConstraint]] )* ]

basicConstraint- : [[timeConstraint]] | [[messageConstraint]] | [[constraint]]

timeConstraint : [=clause:latency|period|timeout] ( [timer] )

messageConstraint : [=clause:priority] ( [priorityValue] )

invoke : ( [~classname] . )? [name] ( ( [parameter] ( , [parameter] )* )? ) ;

anonymousTriggerBody : { [**code] }


// The master of this part of the Umple grammar is available at
// http://code.google.com/p/umple/source/browse/trunk/cruise.umple/src/umple_template.grammar
//@author Ahmed M.Orabi {@link ahmedvc@hotmail.com}
//@author Mahmoud M.Orabi {@link mahmoud_3rabi@hotmail.com}

templateDefinition : template [name] { [[templateContent]]* }

templateContent- : [[comment]]
    | [[emitMethod]]
    | [[templateAttributeDefinition]]
    | [[trace]]
    | [[position]]
    | [[displayColor]]
    | [[abstract]]
    | [[keyDefinition]]
    | [[softwarePattern]]
    | [[depend]]
    | [[symmetricReflexiveAssociation]]
    | [[attribute]]
    | [[templateAttribute]]
    | [[stateMachine]]
    | [[inlineAssociation]]
    | [[concreteMethodDeclaration]]
    | [[constantDeclaration]]
    | [[invariant]]
    | ; |[[exception]]
    | [[extraCode]]



templateAttributeDefinition : [[templateName]] [[templateAttribute]]

templateName : ( [~classname] . )? [name] [[templateParameters]]?

templateParameters : ( [[templateParameter]] ( , [[templateParameter]] )* )

templateParameter- : [parameter] | " [**parameter] "


emitMethod : [=modifier:public
    |protected
    |private]? [=static]? [type]? [=emit] [[methodDeclarator]] [[templateList]]?;

templateList- : ( ( [[templateName]] ( , [[templateName]] )* )? )


templateAttribute# : <<! [[templateAttributeContent]]* !>>

templateAttributeContent- : [[templateExpression]]
    | [[templateComment]]
    | [[templateCodeBlock]]
    | [[templateExactSpaces]]
    | [[templateInclude]]
    | [[templateText]]

templateText# : [**templateTextContent:<<(=|#|/[*]|$|@)]


templateComment# : <</* [**templateCommentContent] */>>

templateExpression# : <<= ( [[templateExpression]]
    | [**templateExpressionContent:<<(=|#|/[*]|$|@)] )+ >>

templateCodeBlock# : <<# ( [[templateExpression]] | [**templateLanguageCode:<<(=|#|/[*]|$|@)] )* #>>

templateExactSpaces# : <<$ [**templateExactSpacesContent] >>

templateInclude# : <<@ [[templateName]] >>

//templateOpen- : <
//templateClose- : !>>

// The master of this part of the Umple grammar is available at
// http://code.google.com/p/umple/source/browse/trunk/cruise.umple/src/umple_layout.grammar

// Copyright: All contributors to the Umple Project
// This file is made available subject to the open source license found at:
// http://umple.org/license

// Layout elements are injected into classes as mixins by diagramming tools such
// as UmpleOnline. Programmers can tweak the layout textually.
position- : [[associationPosition]] | [[elementPosition]]

elementPosition : position [x] [y] [width] [height] ;

associationPosition : position.association [name] [[coordinate]] [[coordinate]] ;

coordinate : [x] , [y]

displayColor : ( displayColor | displayColour ) [**colorValue] ;


// The master of this second part of the Umple grammar is available at
// http://code.google.com/p/umple/source/browse/trunk/cruise.umple/src/umple_exceptions.grammar

// Copyright: All contributors to the Umple Project
// This file is made available subject to the open source license found at:
// http://umple.org/license

misnamedAttribute : [name] ; | [type] [name] ;

malformedConstraint : [ [!stuff:[^\]]*] ]

malformedStatement1 : [!stuff:[^\\{\\};]*] ( [!stuff:[^\\{\\};]*] )* ;

malformedStatemachine1 : [!stuff:[^\\{\\}\\(\\) ]*] { [**innerstuff] }

malformedStatement2 : [!stuff:[^\\{\\};]*] ( [!stuff:[^\\{\\};]*] )* { [**innerstuff] } ;

malformedStatemachine2 : [!stuff:[^\\{\\}\\(\\)]*] ( [!stuff:[^\\{\\}\\(\\)]*] )* { [**innerstuff] }

malformedMethod : [!stuff:[^\\{\\}\\(\\)]*] ( [!stuff:[^\\{\\}]*] )* { [**innerstuff] }

exception : [[misnamedAttribute]]
    | [[malformedStatement1]]
    | [[malformedStatemachine1]]
    | [[malformedStatement2]]
    | [[malformedStatemachine2]]
    | [[malformedConstraint]]
    | [[malformedMethod]]


toplevelException : [[toplevelExceptionMain]] ( { [**extraStuff] } )? ( " [**quotedStuff] " )? ( ; )?

toplevelExceptionMain : [=access:public
    |private
    |protected]? [identifier] [=queued]? [name]? [[inheritanceException]]? [name]*

inheritanceException : ( [=level:extends|implements]? [name] ( , [name] )* )+

// Copyright: All contributors to the Umple Project
// This file is made available subject to the open source license found at:
// http://umple.org/license

// beginning of use.grammar

// This is essentially rewriting the grammar rules present in the USE compiler, which exist in a similar format.

useProgram : model [id] ([[useGeneralClassDefinition]]
    | [[useInlineComment]]
    | [[useAssociation]])*


useGeneralClassDefinition- : [[useClassDefinition]]


useClassDefinition : (abstract)? class [id] [[useAttributes]]? end


useAttributes : attributes [[useAttributeDefinition]]*


useAttributeDefinition : [id] : [[useType]] (;)?


useType- : [[useSimpleType]]


useSimpleType : [id]


useInlineComment- : (-- [**inlineComment]) | (// [**inlineComment])


useAssociation : association [name] between [[useAssociationEnd]] [[useAssociationEnd]] end


useAssociationEnd : [name] [ [[useMultiplicity]] ]


useMultiplicity- : [[useMultiplicityRange]]


useMultiplicityRange : [[useMultiplicitySpec]] (.. [[useMultiplicitySpec]])?


useMultiplicitySpec : [integerSpec:\d+|[**]]

// Copyright: All contributors to the Umple Project
// This file is made available subject to the open source license found at:
// http://umple.org/license

filter : filter ( [filterName] )? { ([[filterStatement]])* }


filterStatement- : [[filterCombinedValue]] | [[filterNamespace]] | [[filterValue]] | [[hops]]


hops- : hops {([[super]] | [[sub]] | [[association]])*}


filterValue : include ([classname]) ( , [classname] )*;


super : super [superNum];


sub : sub [subNum];


association : association [associationNum];


filterNamespace : namespace [Namespace] (, [Namespace])* ;


filterCombinedValue : includeFilter ([filterName]) ( , [filterName] )*;

Grammar Notation

In Umple we use our own extended EBNF syntax for the grammar, with our own parsing tool. The reason for this is that we wanted several advanced features in the grammar and parser.

Samples of syntax in this user manual are generated directly from the input grammar files used to parse Umple code.

Our syntax offers a very simple mechanism to define a new language, as well as extend an existing one. We will be using examples to help explain our syntax.

 

Example of a simple rule

Let's start with a simple assignment rule (not part of Umple, just an example):

assignment : [name] = [value] ;

Above, the rule name is "assignment". An assignment is comprised of a non-terminal called "name", then the equals symbol ("="), a non-terminal "value" and finally a semi-colon symbol (";").

A non-terminal by default as shown above is a sequence of characters that is a non-whitespace that is delimited by the next symbol (based on the specified grammar). In the above case, the non-terminal "name" will be defined by the characters leading up to either a space, newline, or an equals ("=").

Here are a few examples that satisfy the assignment rule above:

 

Rules that refer to other rules

Let us now consider nesting sub-rules within a rule. Sub-rules are words between [[ and ]]. Again, the following is illustrative, and is not Umple itself

directive- : [[facadeStatement]] | [[useStatement]]
facadeStatement- : [=facade] ;
useStatement : use [=type:file|url] [location] ;

Above, we have three rules, "directive", "facadeStatement", and "useStatement". A "directive" is either a "facadeStatement" or a "useStatement" (the "or" expression is defined by the vertical bar "|"). As indicated earlier, to refer to a rule within another rule, we use double square brackets ("[[" and "]]").

By default, rule names are added to the tokenization string (the result of parsing the input, shown in blue below). But, some rules act more like placeholders to help modularize the grammar (and to promote reuse). To exclude a rule name (and just the name, the rule itself will still be evaluated and tokenized as required), simply add a minus ("-") at the end of its name.

Above, we see that the rule names "directive", and "facadeStatement" are not added to the tokenization string because of the trailing minus signs..

For example, the text "facade;" is tokenized as follows:
[facade:facade]

Without the ability to exclude rule names, that same text would be tokenized with the following additional (and unnecessary) text:
[directive][facadeStatement][facade:facade]

 

Terminal symbols and constants

Symbols (i.e.terminals), such as "=" and ";" are used in the analysis phase of the parsing (to decide which parsing rule to invoke), but they are not added to the resulting tokenziation string for later processing.

If we want to tokenize symbols, we can create a constant using the notation

[=name]  

In the earlier example we see that a "facadeStatement" is represented by the sequence of characters "facade" (i.e. a constant).

To support lists of potential matches we use a similar notation

[=name:list|separated|by|bars].

In the earlier example, we see that the "type" non-terminal can be the constant string sequence "file" or "url".

Hence, here are a few examples that satisfy the earlier example:

 

Optionality and repeating

Parentheses can be used to group several elements in the grammar into a single element for the purposes of the following special treatment.

An asterisk * means that zero or more of the preceding elements may occur.

A plus sign + means that one or more of the preceding elements must occur.

A question mark ? means that the preceding element may occur.

 

Avoiding consumption of whitespace

Normally when parsing, all whitespace (spaces, carriage returns, tabs, etc.) around tokens are ignored, and the token output by the parser does not contain them. However, if a # symbol is found after the rule (on the left hand side) then all whitespace is preserved. This is useful for cases where that space is actually useful, such as in Umple's templates.

 

Comments and arbitrary input

The grammar syntax supports a simple mechanism for non-terminals that can include whitespace (e.g. comments). Text in [** ] such as [**arbitraryStuff] is not parsed. However if the rule name is followed by a colon, such as [**templateTextContent:<<(=|#|/[**] then a pattern for different types of brackets that can be internally parsed can be specified. So the above says ignore everything except things in <<= <<# <</* , which will be processed.

Let us consider the rules to define inline and multi-line comments.

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

The [*name] (e.g. [*inlineComment]) non-terminal will match everything until a newline character. The [**name] (e.g. [**multilineComment]) non-terminal will match everything (including newlines) until the next character sequence is matched. In the case above, a "multilineComment" will match everything between "/*" and "*/".

Here are a few examples that satisfy the assignment rule above:

 

Special matching cases

By default, [name] matches identifiers that can include underscore and certain other symbols. To match alphanumeric identifiers only, then use

[~name]
To match based on a regular expression (such as a sequence of one or more digits in this case):
[!bound:\d+]

To match one or more identifiers, but with some being optionally omitted use this notation:

[attr_qualifier,attr_type,attr_name>2,1,0]

This states that there will be one, two, or three identifiers.  The priority of inputs is attr_name,attr_type and attr_qualifier.

API Summary

The following table describes the API generated from various Umple features. This is designed as a quick reference. To find the exact API for any system that would be generated in Java, use UmpleOnline and request to generate JavaDoc output.

Summary of the API generated by Umple from attributes, associations, state machines and other features
API GENERATED IN ALL CASES                        
void delete() removes object, correctly handling cascade deletion and referential integrity
any methods in the code are emitted as-is; they are made public if this is not declared
API GENERATED FROM ATTRIBUTES                        
T is the type of the attribute (String if omitted); note that Umple builtin types such as Integer become native types such as int
z is the attribute name
Note that the API for array attributes is shown as a column in the associations table further down
Umple concept   basic initialized lazy defaulted lazy immutable immutable autounique constant internal key  
Umple notation   T z; T z = val; lazy T z; defaulted T z = val; lazy immutable T z; immutable z; autounique z const T z=val internal T z; key { z }  
Querying value                        
T getZ() return the value yes yes yes yes yes yes yes; T always int depends
boolean isZ() return true if value is true if T Boolean if T Boolean if T Boolean if T Boolean if T Boolean if T Boolean depends
boolean equals(Object) is equal to another? yes
Mutating                        
boolean setZ(T) mutates the attribute yes yes yes yes yes; true only once depends
boolean resetZ() restores original default yes
Other                        
T getDefaultZ() returns original default yes
int hashCode() Likely unique value yes
constructor args T T
initial value   constructor val val null/0/false val null/0/false constructor val or val next int static val construtor val  
API GENERATED FROM ASSOCIATIONS                      
X is the name of current class
W is the name of the class at the other end of the association; used in method names unless a role name is present; pluralization rules are applied
r is a role name used when referring to W (optional, except in reflexive associations)
Umple concept   ? To many ? To many with role optional ? To one required many directional immutable immutable optional reflexive symmetric reflexive array attribute
Umple notation    -- * W;  -- * W r;  -- 0..1 W;  -- 1 W;  -- 1..* W;  -> 1--* W; immutable 1 -> * W; immutable 1 -> 0..1 W; * -- * X r; * self r; W [] r;
Querying link(s)                        
W getW() return the W yes; W or null yes W or null
W getW(index) pick a specific linked W yes yes; getR(index) yes yes yes R and X R yes; getR(index)
List<W> getWs() ges immutable list of links yes yes; getR() yes yes yes R and Xs yes; W[] getR()
boolean hasWs() is cardinality > 0? yes yes; hasR() yes yes yes R and Xs R yes; hasR()
int indexOfW(W) look up specific W -1 if none yes yes;  … ofR(W) yes yes yes R and X R yes;  … ofR(W)
int numberOfWs() cardinality yes yes; … ofR() yes yes yes R and Xs R yes; … ofR()
Mutating                        
boolean setW(W) add a link to existing W yes if * -- or 0..1 -- never never
W addW(args) construct a new W and adds link if 1 -- * W if 1 -- * W r never never
boolean addW(W) add a link to existing W yes yes; addR(W) yes yes never never R and X R yes; addR(W)
boolean setWs(W…) add a set of links yes yes never never
boolean removeW(W) remove link to W if possible yes yes; removeR(W) yes yes never never R and Xs R yes; removeR(W)
Other                        
static int minimumNumberOfWs() multiplicity lower bound yes yes; … ofR() yes yes yes R and Xs R
static int maximumNumberOfWs() multiplicity upper bound if > 1
static int requiredNumberOfWs() fixed multiplicity if > 1
boolean isNumberOfWsValid() false if breaching constraints yes; true initially
constructor args W (W args if 1 -- 1) W … W
initial value   empty empty empty constructor val empty empty constructor val constructor val empty empty empty
API GENGERATED FROM STATE MACHINES                      
sm is the name of the state machine
Umple concept   Sm with events Enum with no events                  
enum getSm() current state for statemachine sm yes yes
String getSmFullName() current state for statemachine sm yes yes
enum getSmS2() state of substate s2 yes
boolean e() event method e (for all events) yes yes
boolean setSm(enum) set state directly yes
Substates allowed yes
initial value first state listed                      
API GENERATED FROM SINGLETON                        
static X getInstance()

Umple messages

General information about Umple errors and warnings

The subsequent pages in the user manual describe each of the errors or warnings that can be emitted by the compiler. These can appear in UmpleOnline, Eclipse and the command-line compiler.

An error is a situation where the compiler can't generate code because the Umple code doesn't make sense; i.e. there is something critical missing, or there is an inconsistency.

A warning is a situation where code can be generated, but the resulting system may not to have the intended semantics (it may not behave as intended) because of an inconsistency, redundancy or assumption that may not be correct.



For developers of Umple itself: The file defining the messages in English is called en.error and is located in cruise.umple/src. Errors have severity 1 or 2, and warnings have severity 3, 4 and 5. When adding a message, a user manual page should be added describing it.
All messages should be detected in the parsing phase by calling setFailedPosition.
It is intended in the future that internationalized versions of Umple will be created; for example fr.error would be the French version. In the near future, it is intended to enable messages from Java or other compilers to be passed through as part of the Umple compilation process; these would be the same as the native language compiler, except that line numbers would be changed to point to the correct line of Umple code.

W001 Singleton With Non-Lazy Attribute

Umple semantic warning reported when a singleton class has an attribute that is not marked lazy

A singleton class can't have any arguments in its constructor. In general in Umple, unless an attribute is specified as 'lazy', then an argument for the attribute is added to the constructor. In the case of singletons this is not done. This warning is to let programmer know this. To avoid the warning, add the keyword 'lazy' to all attributes of a singleton class. However, whether or not this is done, the generated code will behave as if it had been done.

Example

// This example generates the warning message
class X {
  singleton;
  Integer x;
}

      

Load the above code into UmpleOnline

 

Another Example

// The following shows how to avoid the warning
class X {
  singleton;
  lazy Integer x;
}

      

Load the above code into UmpleOnline

 

W002 Singleton With Required Object

Umple semantic warning reported when a singleton class has an association with a multiplicity lower bound of 1 at the other end of the association

The constructor of a singleton can't take any arguments. Therefore it can't have a required link to another object, since this would have to be specified in the constructor. Any associations to other classes should therefore have multiplicity with lower bound of zero.

Note: Conceptually this warning would also have been produced if the lower bound was something greater than 1 (e.g. 5). However Umple treats a multiplicity specified with a lower bound > 1 as if the multiplicity lower bound was 0. The programmer is supposed to add the n elements immediately after construction. The API has a validity check method to verify this has been done.

Example

// This example generates the warning message
class X {
  singleton;
  0..1 -- 1 Y;
}

class Y {
}

      

Load the above code into UmpleOnline

 

Another Example

// The following shows how to avoid the warning
class X {
  singleton;
  0..1 -- 0..1 Y;
}

class Y {
}

      

Load the above code into UmpleOnline

 

W003 Redundant Lazy With Initialization

Umple syntactic warning reported when the lazy keyword in specified when there is also an initializer

The function of the 'lazy' keyword is to indicate that an attribute is not to appear in the constructor. However an initializer for the attribute has the same effect, so specifying both 'lazy' and an initializer is redundant, and hints that there may be a mistake. The solution is just to remove the extraneous 'lazy'.

Example

// This example generates the warning
class X3lazy {
  lazy Integer a = 1;
}

      

Load the above code into UmpleOnline

 

Another Example

// This shows how the warning can be removed.
class X3lazy {
  Integer a = 1;
}

      

Load the above code into UmpleOnline

 

E004 Invalid Multiplicity

Umple syntactic error reported when an invalid multiplicity is specified

Valid multiplicities in Umple include

When this error message appears, the multiplicity doesn't fit any of the above patterns. A common error, for example, is to use the notation 'n', as found in Entity-Relationship Diagrams. This is not valid in Umple; only integers, and * may appear.

Example

// This example generates the error message
class X {
  1 -- 0..1..2 Y;
}

class Y {
}

      

Load the above code into UmpleOnline

 

Another Example

// The following shows how to avoid the error
class X {
  1 -- 0..2 Y;
}

class Y {
}

      

Load the above code into UmpleOnline

 

E005 Undefined Class in Association

Umple semantic error reported when an an association is specified to a class that cannot be found

The classes at both ends of an association must exist in the system being compiled. It might be that the specified class is spelled wrongly or has been omitted from the compilation. If you are making an association to a class in existing code, then simply declare the class as external, as shown in the third example below.

Example

// This example generates the error message
class X {
  1 -- * Y;
}

      

Load the above code into UmpleOnline

 

Another Example

// The following shows how to avoid the error
class X {
  1 -- * Y;
}
class Y {}

      

Load the above code into UmpleOnline

 

Another Example

// It is also possible to designate that the class Y is external in the following manner
class X {
  1 -- * Y;
}
external Y {}

      

Load the above code into UmpleOnline

 

Another Example

// The following will also generate the error message
class X {}
class Y {}

association {
  1 X -- * Z;
}

      

Load the above code into UmpleOnline

 

E006 Missing Default

Umple syntactic error reported when no default value is specified after an attribute that is marked defaulted

The keyword 'defaulted' means that the attribute will be given a default value if the value is not set in the constructor. Omitting the default value is therefore illogical. The default value is specified after an equals sign.

Example

// This example generates the error message
class X {
  defaulted Integer a;
}

      

Load the above code into UmpleOnline

 

Another Example

// The following shows how to avoid the error
class X {
  defaulted Integer a = 5;
}

      

Load the above code into UmpleOnline

 

W007 Key Already Specified

Umple semantic warning reported when a second key statement is encountered in a class

To avoid confusion, a class should normally only have one key specification. This warning is intended to direct the programmer to list the multiple attributes within the same key directive, rather specifying them separately.

The reason for this is that without this warning, code that is separated by many lines or found in a mixin file might modify the key in a way that wasn't anticipated by the developer who is not aware of the existence of multiple key statements.

Developers can ignore this warning without any consequences. The examples below will generate the same compiled code.

Example

// This example generates the message
class X {
  name;
  id;
  key { name }
  key { id }
}


      

Load the above code into UmpleOnline

 

Another Example

// This example below avoids the message
class X {
  name;
  id;
  key { name, id }
}


      

Load the above code into UmpleOnline

 

E008 Association Class Missing End

Umple semantic error reported when an association class is only defined with one end

An association class must have two classes designated as its ends. Instances of the association class represent links between instances of the associated classes, so it is illogical for an association class to have only one end.

Example

// This example generates the error message
class A {}

class B {}

associationClass C {
   * A;
}

      

Load the above code into UmpleOnline

 

Another Example

// The following shows how to avoid the error
class A {}

class B {}

associationClass C {
   * A;
   * B;
}

      

Load the above code into UmpleOnline

 

E009 Reflexive Lower Bound

Umple semantic error reported when a reflexive association has a multiplicity with a lower bound greater than one

A reflexive association must have multiplicity with lower bounds of zero at both ends (e.g. *, 0.1 or or 0..2), otherwise an illogical situation would result. For example, creating a parent-child association on class Person (the example below) with a lower bound of 2 would mean that every Person in the system must have parents, ad infinitum.

Example

// This example generates the error message
class Person {
  * -- 2 Person parents;
}

      

Load the above code into UmpleOnline

 

Another Example

// The following shows how to avoid the error
class Person {
  * -- 0..2 Person parents;
}

      

Load the above code into UmpleOnline

 

W010 Singleton Multiplicity Over 1

Umple semantic warning reported when a singleton class has an association with incoming multiplicity > 1

Since there can only be one instance of a singleton class, it is logically impossible for another class to have links to more than one instance of the singleton class.

Example

// This example generates the warning message
class X {
  singleton;
}

class Y {
   0..1 -- * X;
}

      

Load the above code into UmpleOnline

 

Another Example

// The following shows how to avoid the warning
class X {
  singleton;
}

class Y {
   0..1 -- 1 X;
}

      

Load the above code into UmpleOnline

 

E011 Class is Subclass Of Self

Umple semantic error reported when a class is designated as a subclass of itself.

The inheritance hierarchy cannot have cycles. It must be a strict tree. It is therefore not allowed to make a class into a subclass of itself.

Example

// This example generates the error message
class X {
  isA X;
}

      

Load the above code into UmpleOnline

 

Another Example

// The following shows how to avoid the error
class Y {}

class X {
  isA Y;
}

      

Load the above code into UmpleOnline

 

E012 Class Indirectly Subclass of Self

Umple semantic error reported when a class is designated as a subclass of itself, through some other class.

The inheritance hierarchy cannot have cycles. It must be a strict tree. It is therefore not allowed to make a cycle or loop, in which a class is indirectly a subclass of itself.

Example

// This example generates the error message
class A {
  isA C;
}

class B {
  isA A;
}

class C {
  isA B;
}

      

Load the above code into UmpleOnline

 

Another Example

// The following shows how to avoid the error
class A {
}

class B {
  isA A;
}

class C {
  isA B;
}

      

Load the above code into UmpleOnline

 

E013 Non Immutable Association

Umple semantic error reported when an immutable class is defined as having an association to a non-immutable class.

By definition, an immutable class can't change state, so it can't have an association that can change state or an association to a class that can change state.

Example

// The following example generates the error message
class X {
   Integer x;
}

class Y {
  String s;
  immutable;
  0..1 -> 0..1 X;
}
      

Load the above code into UmpleOnline

 

Another Example

// One way to solve this is to make the association point to
// another immutable class
// But note that this only works for one-way associations
class X {
   Integer x;
   immutable;
}

class Y {
  immutable;
  String s;
  0..1 -> 0..1 X;
}
      

Load the above code into UmpleOnline

 

Another Example

// Another solution is to not require the association to be immutable,
// just the attributes. But this may not match the intended semantics.
class X {
   immutable Integer x;
}

class Y {
    immutable String s;
    0..1 -- 0..1 X;
}
      

Load the above code into UmpleOnline

 

E014 Immutable Subclass of Mutable

Umple semantic error reported when an attempt is made to create an immutable subclass of a mutable superclass

Immutability means that no aspect of the state (attribute, association, state machine) can change in a class once constructed. However if a superclass has mutable elements, they are inherited as mutable. As a result it is not allowed for an immutable class to be a subclass of a mutable class.

Note that this will occur if the entire subclass is being declared as immutable and if any element of the superclass is not immutable. It is possible to have mixes of immutable elements and mutable elements in any given class. In the example below, one solution would be to declare attribute b as immutable and remove the class-level immutable status. Class X14immut would be mutable because it would inherit mutable attribute a.

Example

// This example generates message 14
class B {
  a;
}

class X14immut {
  isA B;
  immutable;
  b;
}


      

Load the above code into UmpleOnline

 

W015 Immutable Class State Machine

Umple semantic warning reported when an immutable class is defined as having a state machine.

By definition, an immutable class can't change state, so it can't have a state machine. Any state machine defined is ignored.

Example

// The following example shows how to generate this warning.
// Removing the immutable keyword will solve the problem.
class X {
  immutable;
  Integer y;
  sm {
    S1 {
    }
  }
}

      

Load the above code into UmpleOnline

 

E016 Non Immutable Superclass

Umple semantic error reported when an immutable class is defined as having a superclass that is non-immutable.

In an inheritance hierarchy, all classes must be immutable, or all non-immutable, otherwise the substitutability principle would broken.

Example

// The following example generates the error message
// A solution is to make class X immutable
class X {
  a;
}
class Y {
  immutable;
  isA X;
}
      

Load the above code into UmpleOnline

 

E017 Non Immutable Bidirectionality

Umple semantic error reported when a non-directed association is declared to be immutable, or appears in an immutable class.

Allowing two-way associations to be immutable would be impossible since it would require change to one object when it is linked to the other, and that would break the concept of immutability.

Example

// The following example generates the error message
// Change the -- to -> to solve the problem
class Y {
  immutable;
  1 -- * Z;
  isA X;
}

class Z {
  immutable;
  y;
}
      

Load the above code into UmpleOnline

 

E018 Reflexive Immutable

Umple semantic error reported when an immutable reflexive association is declared as having 1 at the other end

This is a special case of the general rule that reflexive associations must have upper bounds greater than zero.

Example

// The following example generates the error message
class X {
    immutable;
    0..1 -> 1 X;
}

      

Load the above code into UmpleOnline

 

E019 Duplicate Association

Umple semantic error reported when a class is given two associations with the same name.

Associations between the same classes must be given different names. This error can occur when two associations have the same role name; the solution is to change one of the role names. The error can also occur when two associations are created without any role name at all. In that case the default name is generated from the associated class. The solution is to add a role name to one of the associations.

Example

// The following example shows how to generate this error.
class X {
}

class Y {
  1 -> * X;
  1 -> * X;
}

      

Load the above code into UmpleOnline

 

E020 Interface Association Not One Way

Umple semantic error reported when an association to an interface is declared to be bidirectional or pointing from the interface.

An association can be declared from a class to an interface, but if this is done, it must be one way using the '->' notation. The reason for this is that no concrete methods can be generated in an interface.

Example

// This example generates the message
class X20classintfarrow {
  1 -- * IA;
}

interface IA {}

      

Load the above code into UmpleOnline

 

Another Example

// This example generates the message
class X20classintfarrow {
  1 -> * IA;
}

interface IA {}

      

Load the above code into UmpleOnline

 

E021 Invalid Reflexive Association

Umple syntactic error reported when a class has a reflexive association (an association with both ends the same) but there is neither a role name (indicating it is asymmetric), nor a 'self' keyword (indicating it is symmetric).

Code cannot be generated for asymmetric reflexive associations unless there is a role name at at least one end. This ensures the generated API has distinct words for each end.

For more information about reflexive associations, see this page.

Example

// The following example shows how to generate this error.
class X {
    0..1 -- 0..1 X;
}

      

Load the above code into UmpleOnline

 

Another Example

// The following example shows how to fix the error if this is an asymmetric association.
class X {
    0..1 -- 0..1 X right;
}

      

Load the above code into UmpleOnline

 

Another Example

// The following example shows how to fix the error if this is a symmetric association.
class X {
    0..1 self right;
}

      

Load the above code into UmpleOnline

 

E022 Duplicate Attribute

Umple semantic error reported when a class is given two attributes with the same name.

Attributes in a class must have distinct names. The solution to this error is to rename or delete one of the attributes. This error is particularly prone to appear when a class is composed of two or more files using Umple's 'mixin' capability; the attribute should be defined in one file or the other, but not both.

@@example @@source manualexamples/E022DuplicateAttribute1.ump @@endexample

E023 Attribute Association Name Clash

Umple semantic error reported when an association has the same name as an attribute or vice versa,

An association generates a variable and methods that would clash with an attributes of the same name. If a role name is used, then it must be distinct from all attributes. If no role name is used then the class name (with first character converted to lower case) at the 'other end' of the association must be distinct from all attributes.

Ths problem can sometimes be hard to notice if an association is declared 'backwards' in the 'other' class, or independently of either class. It is especially tricky if the clashing association or attribute is in a separate mixin.

Example

// This example generates error 23 because an attribute and role name share a name
class X23atdupassoc1 {
   a;
   1 -- 0..1 Another a;
}

class Another {}


      

Load the above code into UmpleOnline

 

Another Example

// This generates error 23 because attribute b clashes with
// class name B in the association
class X23atdupassoc2 {
   b;
   1 -- 0..1 B;
}

class B {}

      

Load the above code into UmpleOnline

 

E024 Sort Key Not of Umple Type

Umple semantic error reported when a sort key for a sorted association does not use one of the builtin Umple types

The sort key for an sorted association must have one of the simple types Integer, Short, Long, Double, Float or String. This allows sensible code to be generated for comparisons. The set of allowed types may be expanded in the future.

Example

// This example generates the error message
class X {
  1 -- * Y sorted {endDate};
}

class Y {
   Date endDate;
}


      

Load the above code into UmpleOnline

 

E025 Sort Key Not Found

Umple semantic error reported when a sort key for a sorted association is not an attribute of the destination class

The sort key of a sorted association must be one of the attributes of the class at the other end of the association.

Example

// This example generates the error message
class X {
    * -- 1 Y sorted {nom};
}

class Y {
  name;
}


      

Load the above code into UmpleOnline

 

E026 Duplicate Key Item

Umple semantic error reported when a key has a duplicate item

If an item (attribute, association, state machine) appears twice in a key it is an error since Umple cannot tell the preferred order of items.

Example

// The following example has error 26 since they key has 'a' twice
class X26dupiteminkey {
  a;
  b;
  key {a, b, a} 
}

      

Load the above code into UmpleOnline

 

W027 Key Identifier Incorrect

Umple semantic warning reported when an identifier in a key statement was not found

The list of identifiers in a key statement can include attributes, associations (role name for example) or state machines. This message indicates that the referenced identifier could not be found. This is usually the result of a typographical error. The extraneous identifier is ignored, which is likely to result in incorrect code.

Example

// This example generates the message
class X27itemkeynotdef {
  a;
  key {b}; 
}


      

Load the above code into UmpleOnline

 

E028 Constraint Identifier Incorrect

Umple semantic error reported when an identifier (attribute, etc.) in a constraint cannot be found

Currently, constraints can refer to attributes in the current class; in the future they will be able to refer to other model elements. This message indicates that an identifier referenced in the constraint was not found. This is often just due to a typographical error, but it might be due to the current limitations of constraints.

Example

// This example generates the message
class X28attrconsrnotdef {
  Integer a;
  [b > 5]
}

      

Load the above code into UmpleOnline

 

E029 Constraint Type Mismatch

Umple semantic error reported when there is a type mismatch in a constraint

It is only possible to compare a String to a String, a Boolean to a Boolean, and a number to a number, etc. Violations result in a type mismatch error.

Example

// This example generates the message
class X29attrtypeconstr {
  a;
  [a > 5]
}

      

Load the above code into UmpleOnline

 

Another Example

// The following shows how to avoid the message
class X29attrtypeconstr {
  Integer a;
  [a > 5]
}


      

Load the above code into UmpleOnline

 

W030 Redefined Namespace

Umple semantic warning reported when a class is declared in separate places to be in two namespaces

Since a class can only be in one namespace, the last namespace declaration overides earlier ones. This can sometimes be useful, e.g. when creating a mixin to change the default location of a class. However it is normally a sign of a mistake, hence the warning.

Example

// This example generates the message
// Namespace b, encountered later, will be the namespace of the class
namespace a;

class X30redefnamespace {
}

namespace b;

class X30redefnamespace {
}

      

Load the above code into UmpleOnline

 

W031 Namespace Not Used

Umple semantic warning reported when a namespace is never applied to any class

If you declare a namespace and then declare another before using the first namespace, this warning is issued. The reason for the warning is that this can happen accidentally, for example if you add a namespace declaration before a comment and then add a different one after a comment but before the class is declared.

Example

// This example generates the message because 
// namespace n is never used
namespace n;
namespace m;

class X21namespacenotused {}

      

Load the above code into UmpleOnline

 

E032 Reserved Role Name

Umple reports this error when a specific role name is used

In order to define a reflexive association, it is necessary to specify role names. There is a situation where it is possible to define a reflexive association with one role name. When this happens, Umple uses an implicit name for the second role name which is the plural form of the class name (e.g. if the class name is Computer, plural form would be computers). Therefore, if a user uses plural form of the class name as role name, Umple produces an error.

Example

// This example generates the error message

class Course {  
  * -- * Course courses;  
}  


      

Load the above code into UmpleOnline

 

Another Example

// The following shows how to avoid the error

class Course {  
  * -- * Course course_s ;  
}  


      

Load the above code into UmpleOnline

 

Another Example

// This example generates the error message

class Course {  
  * courses -- * Course;  
}  


      

Load the above code into UmpleOnline

 

Another Example

// The following shows how to avoid the error

class Course {  
  * course_s -- * Course;  
}  


      

Load the above code into UmpleOnline

 

W033 Missing Superclass

Umple semantic warning issued when a referenced superclass is not found

When you declare a superclass of a class, that class must exist. If the class does not exist, then this warning is issued.

It might be the case that the class is in fact declared in some code that is defined externally. In that case the existence of the external class should be made known to Umple using the external keyword;

Example

// This example generates the warning since T is not defined
class S {
  isA T;
}


      

Load the above code into UmpleOnline

 

Another Example

// This example solves the problem by defining T as an external class
// Umple will not generate any code for T, but now knows it exists
class S {
  isA T;
}
external T {};


      

Load the above code into UmpleOnline

 

E034 Multiple Inheritance

Umple semantic error generated when multiple inheritance is encountered

Umple does not currently support multiple inheritance, in order to be consistent with code generated in Java, and also to make models simpler.

Example

// The following will generate this error

class P1 {}
class P2 {}

class Sub {
  isA P1, P2;
}

      

Load the above code into UmpleOnline

 

Another Example

// The following is another way of formulating the same declarations, also resulting in the error

class P1 {}
class P2 {}

class Sub {
  isA P1;
  isA P2;
}



      

Load the above code into UmpleOnline

 

Another Example

// If all but one of the parents is declared as an Interface, the problem is solved

interface P1 {}
class P2 {}

class Sub {
  isA P1;
  isA P2;
}



      

Load the above code into UmpleOnline

 

W035 Uninitialized Constant

Umple semantic warning generated when a Umple builtin data type constant is not initialized

It makes little sense to have a constant unless it is given a value. If a constant is of one of the built-in Umple data types we will set it to a default value: Integer, Double and Float will be set to zero, String will be set to an empty String, Boolean will be set to false, Date will be set to the date where the code was generated and Time will be set to midnight (00:00:00). However, the warning is issued since forgetting to initialize a constant is a common source of errors.

Example

// The following will generate this warning

class X {
  const String A; //same as const String a = "";
}

      

Load the above code into UmpleOnline

 

Another Example


// The following will resolve the issue

class X {
  const String A = "Something Interesting";
}


      

Load the above code into UmpleOnline

 

W036 Unmanaged Multiplicity

Umple semantic warning generated when a directed association has a multiplicity with hard constraints

Umple generates code to manage the manipulation of the directed end (with the arrowhead) of a directed association. However there are no inverse references in such a case. In the example below, there are no references from class B to class X. As a result, the multiplicity on the undirected end is purely 'documentation'.

Specifying a hard constraint such as 1 or 2 for the upper or lower bound in such a case may be misleading and is typically incorrect. This error is raised whenever the multiplicity is other than * or 0..1

Example

// The following will generate this warnbing

class X {
  1 -> * B first;
  1..3 -> * B second;
  0..2 -> * B third;
}

class B {}

      

Load the above code into UmpleOnline

 

Another Example

// The following solves the problem by either making the association unndirected
// or making the bounds have soft constraints

class X {
  0..1 -> * B first;
  * -> * B second;
  0..2 -- * B third;
}

class B {}


      

Load the above code into UmpleOnline

 

E037 Uninitialized Constant Object

Umple semantic error generated when an Object constant is not initialized

It makes little sense to have a constant unless it is given a value. Since there is no obvious default value for arbitrary data types, unitialized constants that are not from a default Umple data type the code cannot be parsed until the constants are initialized.

Example

// This example generates error 37
class X {
  const Y A;
}

class Y {
  Integer a;
}

      

Load the above code into UmpleOnline

 

Another Example

// This example resolves error 37

class X {
  const Y A=new Y(3);
}

class Y {
  Integer a;
}

      

Load the above code into UmpleOnline

 

E040 Singleton Has Subclasses

Umple semantic error generated when a singleton class has subclasses

Singleton is a software pattern to allow only one instance of a class. A singleton class has a private constructor and cannot be inherited.

Example


// In this example a singleton class has subclasses and it generates an error
class Airplane
{
  singleton;
}
class F16
{
	isA Airplane;
}
      

Load the above code into UmpleOnline

 

Another Example


//I this example the singleton class does not have a subclass and is correct
class Airplane
{
  
}
class TheAirplane
{
  singleton;
}
class F16
{
	isA Airplane;
}
      

Load the above code into UmpleOnline

 

W044 Attribute Duplicated in Superclass

Umple semantic warning reported when an attribute in a class is a duplicate of an attribute in a superclass.

The purpose of this warning is to alert the developer that they have to resolve the issue by changing the name of the duplicated attribute in either the superclass or subclass, or else remove one of them entirely. This warning will soon be changed to an error.

Example

// This example generates the warning message
class A {
  attr;
}

class B {
  isA A;
  attr;
}


      

Load the above code into UmpleOnline

 

Another Example

//This example solves the problem
class A {
  attr;
}

class B {
  isA A;
  differentAttr;
}


      

Load the above code into UmpleOnline

 

W045 Initialized Value in Key

Umple semantic warning reported when an attribute in the key is given an initial value

If an attribute is given an initial value and is part of a key, then there is potential for keys of all instances of a class to be the same, meaning that they would be treated as equal and would have the same hash value. It is unlikely that a developer intends for this to be the case, so a warning is thrown to inform them of this behaviour.

Example

// This example generates the message
class X {
  Integer z = 1;
  key { z }
}


      

Load the above code into UmpleOnline

 

Another Example

// The following shows how to avoid the message
class X {
  Integer z;
  key { z  }
}


      

Load the above code into UmpleOnline

 

W046 Attribute Has Template Type

Umple syntactic warning reported when an attribute has a template type, characterized by brackets "<...>".

Template types do not follow Umple modelling conventions. Umple encourages users to take full advantage of associations in their modelling, which in almost all contexts replace the need for template types. Multivalued attributes can also be used.

Example

// This example generates the message

class A {
  depend java.util.List;
  List<OtherClass> otherClassGroup;
}
class OtherClass {}


      

Load the above code into UmpleOnline

 

Another Example

// The following shows how to avoid the message using a multivalued attribute
class A {
  OtherClass[] otherClassGroup;
}
class OtherClass {}


      

Load the above code into UmpleOnline

 

Another Example

// The following shows how to avoid the message using an association
class A {
  0..1 -- * OtherClass;
}
class OtherClass {}


      

Load the above code into UmpleOnline

 

W047 Empty Key Statement

Umple semantic warning reported when a key statement has no elements inside of it

An empty key statement has no meaning, but Umple will detect the key statement and generate methods associated with having a key. This might lead the developer to think that they have defined a key when in fact the generated methods cannot differentiate between instances of the class in question. The warning is shown to notify the developer of the potential mistake.

Example

// This example generates the message
class A {
  id;
  key { }
}


      

Load the above code into UmpleOnline

 

Another Example

// The following shows how to avoid the message.
class A {
  id;
  key { id }
}


      

Load the above code into UmpleOnline

 

W049 Duplicated Method Name

Umple semantic warning reported when two methods have the same names and return types

You cannot have two methods that have the same names and return types. The warning is shown to notify the developer of the potential mistake.

Example

// This example generates the message
class A{
  void test1(){return("hello world")}
  void test1(){return("dlrow olleh")}
}



      

Load the above code into UmpleOnline

 

Another Example

// The following shows how to avoid the message.
class A{
  void test1(){}
  void test2(){}
}


      

Load the above code into UmpleOnline

 

W050 Target State Not Found

Umple semantic warning reported when the target state of a transition is not listed.

An end state (with no outgoing transitions) is generated. The purpose of the warning is to alert the developer that they may have a typographical error in the target state name.

Example

// This example generates the error message
class X {
  sm {
    s1 {
      e1 -> s2;
    }
  }
}


      

Load the above code into UmpleOnline

 

Another Example

// This example solves the problem
class X {
  sm {
    s1 {
      e1 -> s2;
    }
    s2 {}
  }
}


      

Load the above code into UmpleOnline

 

E051 Event Parameters Must Match

Umple semantic error reported when events with the same name have different parameters

When parameters are specified on a state machine event, all transitions with the same event name must have identical parameters. The reason for this is that there is only one event method generated.

Example

// This example generates the error message
class X {
  sm {
    s1 {
      e1(String s) -> s2;
    }
    s2 {
      e1(Float f) -> s2;
    }
  }
}


      

Load the above code into UmpleOnline

 

Another Example

// This example solves the problem
class X {
  sm {
    s1 {
      e1(String s) -> s2;
    }
    s2 {
      e1(String s) -> s2;
    }
  }
}


      

Load the above code into UmpleOnline

 

E052 State Machine Name Clash

Umple semantic error reported when a state machine name matches the name of another element such as an association or attribute

Since, in effect, a state machine defines a special kind of attribute (whose value is enumerated as one of the states and is controlled by events) it is not allowed to have an attribute or association with the same name as a state machine.

Example

// This example generates the message because the state machine a
// clashes with the attribute a
class X52assattnamestatemachine1 {
  a;
  a {
    s1 {}
    s2 {}
  }
}

      

Load the above code into UmpleOnline

 

Another Example

// The sample generates the message because the state machine a
// clashes with the association role name a
class X52assattnamestatemachine2 {
  1 - 0.1 B a;
  a {
    s1 {}
    s2 {}
  }
}
class B {}

      

Load the above code into UmpleOnline

 

E053 No Concurrency At Top Level

Umple semantic error reported when concurrent substates are placed at the top level of a state machine

A state machine must be in one top level state at all times. Concurrent substates can exist in any substate at any level, but not directly in a top level state. The second example below shows how this can be handled simply by adding a level of nesting.

If the intent is simply to create concurrent do activities, and alternative is to use Umple's active objects notation.

Example

// This example generates the message
class X53conctoplevel {
  sm {
    s1 {
      do {System.out.println("Reached s1");}
    }
    ||
    s2
    {
      do {System.out.println("Reached s1");}
    }
  }
}

      

Load the above code into UmpleOnline

 

Another Example

// The following shows how to avoid the message
class X53conctoplevel {
  sm {
    s0 {
      s1 {
        do {System.out.println("Reached s1");}
      }
      ||
      s2
      {
        do {System.out.println("Reached s1");}
      }
    }
  }
}

      

Load the above code into UmpleOnline

 

W054 Duplicate Events

Umple warning generated when there is a duplicate unguarded event that will never be reached

In the example below, the second transition e from s1 can never be triggered because when e occurs the first transition is taken.

Example


class X {
  sm {
    s1 {
      e-> s2;
      e-> s3;
    }
    s2 {}
    s3 {}
  }
}


      

Load the above code into UmpleOnline

 

W055 Duplicate Events Within Substates

Umple warning generated when there is a duplicate unguarded event that will never be reached, in the situation where there is a superstate and a substate with the same event

In the example below, the event e from the s1 superstate and the event e in the s1a substate are ambiguous. Current semantics is that the event in the superstate takes precedence, but this semantics may be changed..

Example


class X {
  sm {
    s1 {
      e-> s2;
      s1a {
        e-> s3;
      }
    }
    s2 {}
    s3 {}
  }
}


      

Load the above code into UmpleOnline

 

W071 Duplicate Method Different Type

Umple sematic warning reported when two methods have the same names but different types

In some programming languages like Java, you cannot have the same method names even the return types are different. The warning is shown to notify the developer of the potential mistake.

Example

// This example generates the message
class A{
  void test1(){return("hello world")}
  Integer test1(){return("dlrow olleh")}
}



      

Load the above code into UmpleOnline

 

Another Example

// The following shows how to avoid the message.
class A{
  void test2(){}
  Integer test1(){}
}


      

Load the above code into UmpleOnline

 

W072 Refactored Final State

Umple sematic warning when do activities, exit actions, outgoing transitions, and/or nested state machines are removed by the compiler from final states.

In Umple, final states are allowed to be empty, or they can contain entry actions.

Example

// The following shows how to generate the warning

class InvalidFinalState {
  status{
    on{
      turnoff -> off;
      powerOff-> FINAL;
    }
    
    off{
      turnOn -> on;  
    }

    final FINAL{
      entry/{entry();}
      do{exe();}
      reboot -> on;
      nestedSm {
        s1 {
          -> s2;
        }
        s2 {

        }
      }
      exit/{exit();}
    }
  }
}

      

Load the above code into UmpleOnline

 

Another Example

// The following shows how to avoid the warning

class X {
  status{
    on{
      turnoff -> off;
      powerOff-> FINAL;
    }    
    off{
      turnOn -> on;  
    }
    final FINAL{
      entry/{entry();}
    }
  }
}

      

Load the above code into UmpleOnline

 

Another Example

// The following shows how to avoid the warning

class X {
  status{
    on{
      turnoff -> off;
      powerOff-> FINAL;
    }    
    off{
      turnOn -> on;  
    }
    final FINAL{

    }
  }
}

      

Load the above code into UmpleOnline

 

E073 Duplicate Parallel State Machine Name

Umple semantic error reported when parallel state machines in the same composite state have the same name.

In Umple, parallel state machines within the same composite state must have different names.

Example

// The following example generates the error
// "s1" has two parallel state machines that are named "t1"

class X {
  sm{
    s1{
      t1{
        goT2-> t2;
      }
      t2{ }
      ||
      t1{
        goT4-> t4;
      }
      t4{}
    }
  }
}

      

Load the above code into UmpleOnline

 

Another Example

// The following example shows how to avoid the error

class X {
  sm{
    s1{
      t1{
        goT2-> t2;
      }
      t2{ }
      ||
      t3{
        goT4-> t4;
      }
      t4{}
    }
  }
}

      

Load the above code into UmpleOnline

 

E074 User Defined State Cannot be Named Final

Umple semantic error reported when a user-defined state is named 'Final' keyword

In Umple, 'Final' is a reserved keyword. It is used to define the final state for the top-level state machine.

Example

// The following example generates the error
// "s1" has a state named "Final"

class X {
  sm {
    s1 {
      Final {}
    }
  }
}
      

Load the above code into UmpleOnline

 

Another Example

// The following example does not generate the error

class X {
  sm {
    s1 {
      goToFinal-> Final;
    }
  }
}
      

Load the above code into UmpleOnline

 

E095 Duplicate Enumerations

Umple semantic error reported when duplicate enumerations are detected

In Umple, enumerations must have unique names.

Example

// This example causes the error
enum Month {x,y,z}
enum Month {o,p,q}

class A{
  Month m;
  Month p;
}

      

Load the above code into UmpleOnline

 

Another Example

// This example causes the error

class A{
  enum Month {x,y,z}
  enum Month {o,p,q}
}

      

Load the above code into UmpleOnline

 

Another Example

// This example does not cause the error. The enumeration within the class is prioritized over
// the enumeration defined outside of the class

enum Month {x,y,z}

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

      

Load the above code into UmpleOnline

 

E096 Enumeration Naming Conflict

Umple semantic error reported when an enumeration defined in a class has the same name as the class, or when a model level enumeration has the same name as a class, interface, or trait.

In Umple, class enumerations must not have the same name as the class they are defined in. Model level enumerations must have unique names.

Example

// This example generates the error since the enumeration "X" will be added
// to the class "X" because of attribute "t".

enum X{ Red, Blue, Green }

class X{
  X t;
}

      

Load the above code into UmpleOnline

 

Another Example

// This generates the error because the enumeration "X" has the same name
// as the class it's defined in
 
class X{
  enum X { Red, Blue, Green }
}

      

Load the above code into UmpleOnline

 

Another Example

// This example generates the error since enumeration "Y" conflicts with interface "Y"

interface Y { 
  name;
}

class X {
 isA Y;
}

enum Y { Red, Blue, Green }

      

Load the above code into UmpleOnline

 

Another Example

// This example generates the error since enumeration "Y" conflicts with trait "Y"

class X {
 isA Y;
}

trait Y { 
  name;
}

enum Y { Red, Blue, Green }
      

Load the above code into UmpleOnline

 

Another Example

// This example does not generate the error
enum Z { Orange, Yellow }

class X {
 enum Y { Red, Blue, Green }
 Z attr;
}

      

Load the above code into UmpleOnline

 

E097 Enumeration and State Machine Conflict

Umple semantic error reported when an enumeration, and a state machine within the same class have the same name.

In Umple, enumerations and state machines within the same class cannot have the same name.

Example

// This example generates the error because enumeration "Y" has the same name as state machine "Y"

class X {
 enum Y { Red, Blue, Green }
 Y {
  s1 { 
    goToS2 -> s2;
  }
  s2 { }
 }
}

      

Load the above code into UmpleOnline

 

Another Example

// This example generates the error because enumeration "Y" will be 
// added to class "X" since the "attr" parameter of "showY" is "Y".

enum Y { Red, Blue, Green }

class X {
  showY(Y attr) { System.out.println(attr); }
  Y {
   s1 {}
  }
}

      

Load the above code into UmpleOnline

 

Another Example

// This example does not generate the error

class X {
 enum Y { Red, Blue, Green }
 Z {
  s1 { 
    goToS2 -> s2;
  }
  s2 { }
 }
}

      

Load the above code into UmpleOnline

 

WE1xx Identifier Invalid

Umple syntactic error or warning reported when an identifier does not have the correct syntax

In Umple, identifiers used for classes, association role names, types, attributes, state machines, states, events and other elements must be alphanumeric. In addition, class and interface names should start with a capital letter (or _), and other elements should start with a lower case letter. The exact error message you received will tell you which identifier has the problem. The examples below will generate these messages.

Example

// Class with non-alphanumeric name (100)
class @ {}


      

Load the above code into UmpleOnline

 

Another Example

// Warnings from attribute starting with upper case letter (131)
class X {
  Attrib;
}

class Y {}


      

Load the above code into UmpleOnline

 

Another Example

// Attribute name with special characters (130)
class X {
  na$me;
}


      

Load the above code into UmpleOnline

 

Another Example

// Attribute name with special characters that looks like an association (132)
// If this is supposed to be an association, put spaces before and after the -- and *
class X {
  1--*Y;
}

class Y {}


      

Load the above code into UmpleOnline

 

Another Example

// Attribute type with special characters that looks like an association (140)
// If this is supposed to be an association, put spaces before and after the --
class X {
  1--* Y;
}

class Y {}


      

Load the above code into UmpleOnline

 

Another Example

// State machine name with special characters (150)
class X {
  ed%4 {
    s1 {}
  }
}


      

Load the above code into UmpleOnline

 

Another Example

// State  name with special characters (152)
class X {
  ed4 {
    s*1 {}
  }
}


      

Load the above code into UmpleOnline

 

W102 Enumeration Causes Method Parameter Ambiguity

Umple semantic warning reported when an enumeration makes a method parameter's type ambiguous. This occurs when there is another class that could also be the parameter's type.

Example

// This example generates the warning because it is ambiguous if "param"
// is an object of class "Y" or the enumeration "Y".

class X {
  enum Y { Red, Blue, Green }
  showY(Y param) { System.out.println(param); }
}

class Y { }

      

Load the above code into UmpleOnline

 

Another Example

// This example does not generate the warning

class X {
  enum Y { Red, Blue, Green }
  showY(Y param) { System.out.println(param); }
}

class Z { }

      

Load the above code into UmpleOnline

 

Another Example

// This example does not generate the warning

enum Z { Red, Blue, Green }

class X {
  showY(Y param) { System.out.println(param); }
}

class Y { }

      

Load the above code into UmpleOnline

 

W103 Enumeration Causes Event Parameter Ambiguity

Umple semantic warning reported when an enumeration makes an event parameter's type ambiguous. This occurs when there is another class that could also be the parameter's type.

Example

// This example generates the warning because "goToS2" has "param" which could be
// either an object of class "Y" or the enumeration "Y"

class X {
  enum Y { Red, Blue, Green }
  sm {
    s1 {
      goToS2(Y param) /{ System.out.println(param); } -> s2;
    }
    s2 {}
  }
}

class Y { }

      

Load the above code into UmpleOnline

 

Another Example

// This example does not generate the warning

class X {
  enum Y { Red, Blue, Green }
  sm {
    s1 {
      goToS2(Y param) /{ System.out.println(param); } -> s2;
    }
    s2 {}
  }
}

class Z { }

      

Load the above code into UmpleOnline

 

E104 Enumeration in Bi-directional Association

Umple semantic error reported when an enumeration is used in a bi-directional association.

In Umple, enumerations cannot be used in bi-directional associations.

Example

// This example generates the error

class X {
  enum Y { Red, Blue, Green }
  0..1 -- * Y;
}

class Y{ }

      

Load the above code into UmpleOnline

 

Another Example

// This example does not generate the error

class X {
  enum Y { Red, Blue, Green }
  0..1 -- * Z;
}

class Z { }

      

Load the above code into UmpleOnline

 

E105 Enumeration in Composition

Umple semantic error reported when an enumeration is used in a composition.

In Umple, enumerations cannot be used in compositions.

Example

// This example generates the error

class X {
  enum Y { Red, Blue, Green }
  0..1 <@>- * Y;
}

class Y {
  name;
}

      

Load the above code into UmpleOnline

 

Another Example

// This example does not generate the error

class X {
  enum Y { Red, Blue, Green }
  0..1 <@>- * Z;
}

class Z {
  name;
}

      

Load the above code into UmpleOnline

 

W106 Enumeration in Uni-directional Association

Umple semantic warning reported when an enumeration is used in a uni-directional association.

Example

// This example generates the warning

class X {
  enum Y{ Red, Blue, Green }
  0..1 -> * Y;
}

class Y { }

      

Load the above code into UmpleOnline

 

Another Example

// This example generates the warning

class X {
  enum Y{ Red, Blue, Green }
  0..1 <- * Y;
}

class Y { }

      

Load the above code into UmpleOnline

 

Another Example

// This example does not generate the warning

class X {
  enum Y { Red, Blue, Green }
  0..1 -> * Z;
}

class Z { }

      

Load the above code into UmpleOnline

 

E112 Duplicate Constants in Interface

Umple semantic error reported when an interface is given two or more constants with the same name.

Constants in an attribute must have distinct names. The solution to this error is to rename or delete one of the constants.

Example

// The following example shows how to generate this error.
interface X {
  const A="dog";
  const A="cat";
}

      

Load the above code into UmpleOnline

 

W141 Value Type Mismatch

Umple syntactic warning reported when an attempt is made to initiate an attribute with a value that does not match the type of the attribute

Numbers must be initialized with numbers, strings with strings in double quotes, and Booleans with true or false. For Dates the value format is a string "yyyy-mm-dd"; for Times the format is "hh:mm:ss".

Note that for an initialization value with no type specified will result in the attribute having its type inferred from the vbalue. This is demonstrated in the third example.

Example

// The following will generate this warning on every line of the class
class X {
  Date d = "20130708";
  Integer i = "abc";
  String s = 123;
  Boolean b = 1;
  Time t = "120000";
}


      

Load the above code into UmpleOnline

 

Another Example

// The following shows how to solve the above problem
class X {
  Date d = "2013-07-08";
  Integer i = 7;
  String s = "123";
  Boolean b = true;
  Time t = "12:00:00";
}

      

Load the above code into UmpleOnline

 

Another Example

// The following shows how to solve the above problem not even showing the type at all
class X {
  d = "2013-07-08";
  i = 7;
  s = "123";
  b = true;
  t = "12:00:00";
  m = 2.3;
}

      

Load the above code into UmpleOnline

 

E180 Duplicate Association Name Class Hierarchy

Umple semantic error reported when a subclass has an association that is not a specialization named the same as a superclass association

A subclass can not have an association with the same role name as an association of its superclass, unless it is a valid specialization.

Example

class Person {
	* -> * Person friends;
}

class Student {
	isA Person;
	* -> * Dog friends;
}

class Dog {
}
      

Load the above code into UmpleOnline

 

E200 Trait Identifier Invalid

Umple syntactic error related to identifiers of traits

In Umple, identifiers used for traits must be alphanumeric. It means that must start with an alpha character, or _ .

Example

//This example shows an error in the name of trait
trait T@ {
	//traits elements
}
      

Load the above code into UmpleOnline

 

Another Example

//This example shows an error in the name of trait
trait 1T {
	//traits elements
}
      

Load the above code into UmpleOnline

 

Another Example

//This example shows a valid name for the trait
trait Color {
	//traits elements
}
      

Load the above code into UmpleOnline

 

Another Example

//This example shows a valid name of traits
trait Equality {
	//traits elements
}
      

Load the above code into UmpleOnline

 

W201 Trait Name Syntax

Umple syntactic warning related to identifiers of traits

In Umple, identifiers used for traits, classes and interfaces should start with a capital letter (or "_"), and other elements should start with a lower case letter.

Example

//This example shows a warning in the name of traits because they start with lower cases.
trait color {
	//traits elements
}

trait equality{
	//traits elements
}

      

Load the above code into UmpleOnline

 

Another Example

//This example shows a valid name for the trait
trait Color {
	//traits elements
}
      

Load the above code into UmpleOnline

 

Another Example

//This example shows a valid name of traits
trait Equality {
	//traits elements
}
      

Load the above code into UmpleOnline

 

E202 Trait not defined

Umple semantic error resulting from a trait not being defined

In Umple, when traits are used inside of classes or traits they have to be defined. The Umple compiler does not allow the use of traits that are not defined in the system.

Example

//In  this example, trait "T" uses trait "T1" which is not available. 
interface I{
	//elements
}

class A {
	isA I;
	isA T; 
}

trait T{
  isA T1;
}

      

Load the above code into UmpleOnline

 

Another Example

//In  this example, the error has been resolved just by defining trait T1. 
interface I{
	//elements
}

class A {
	isA I;
	isA T; 
}

trait T{
  isA T1;
}

trait T1{
	//elements
}

      

Load the above code into UmpleOnline

 

E203 Not having an unique identifier

Umple semantic error related to not using traits which do not have unique identifiers

In Umple, all elements which are capable of being reused should have unique identifiers. Traits, as reusable elements in Umple also have to follow the same rule. Identifiers of traits should be unique in the system. The conflict happens among classes, interfaces, and traits. Therefore, These three elements always should have unique identifiers.

Example

//In  this example, Identifier of trait "I" is not unique. 
class A{
	isA I;
}

class I {
  //elements
}

trait I{
  //elements
}

      

Load the above code into UmpleOnline

 

Another Example

//In  this example, Identifier of trait "T" is unique.
class A{
	isA T;
}

class I {
  //elements
}

trait T{
  //elements
}

      

Load the above code into UmpleOnline

 

E204 Self Use of Traits

Umple semantic error related to self use of traits

In Umple, traits cannot be used in an explicit or implicit cyclic way. It means that a trait cannot use itself and it also cannot be used in a cyclic use. This error happens when a trait extends itself.

Example

// In this example, there is a explicit use of a trait inside of itself.
class A{
	isA T;
}

trait T{
  isA T;
}
      

Load the above code into UmpleOnline

 

E205 Cycle in Traits

Umple semantic error related to a cycle of trait use

In Umple, traits cannot be used in an explicit or implicit cyclic way. This means that a trait cannot use itself and it also cannot be used in a cyclic hierarchy. This error happens when a hierarchy is created completely based on traits. Moreover, this issue generally arises because of invalid design or error in typing a trait name.

Example

// In this example, there is a cycle created in a hierarchy.
class A{
	isA T;
}

trait T{
  isA T1;
}
trait T1{
	isA T;
}

      

Load the above code into UmpleOnline

 

E206 Satisfaction of Bound Type

Umple semantic error related to binding a type to a template parameter

If clients bind types to the template parameters of used traits and the types exist but they do not satisfy the constraints of the template parameters, this error is raised. The constraint is related to the implementation of interfaces.

Example

// In this example, there is an error because class C1 does not implement interface I. Any bound value to template parameter TP must implement interface I.
trait T1<TP isA I>{
  /*implementation*/
}
interface I{/*implementation*/}
class C1{/*implementation*/}
class C{
  isA T1< TP = C1 >;
  /*implementation*/
}




      

Load the above code into UmpleOnline

 

E208 Required Methods Not Available

Umple semantic error related to not having required methods of traits in classes

Traits need to have required methods in order to provide the functionality they have designed to provide. These required methods can provide special functionality or be way of accessing states (attributes) in host classes. This error is raised when a required method is not available.

Example

// In this example, the required method "FinalResult()" in Trait "T" is not satisfied by class "A".
class A{
	isA T;
}

trait T{
	Integer FinalResult();	
	void calculate(){
		//method FinalResult() will be used here;	
	}	
}

      

Load the above code into UmpleOnline

 

Another Example

// In this example, the require method "FinalResult()" in Trait "T" is satisfied by class "A".
class A{
	isA T;	
	internal Integer x;	
	Integer FinalResult(){
		return x/100;
	}
}

trait T{
	Integer FinalResult();	
	void calculate(){
		//method FinalResult() will be used here;	
	}	
}

      

Load the above code into UmpleOnline

 

E210 Conflict in Methods

Umple semantic error related to having two methods with the same signature but different implementation

Traits can be used in serveral hierarchies without any priority. It means that classes can be composed of several traits and also a trait can be composed of other traits. This brings cases in which two methods with the same signature come from either different traits or a different hierarchy path. If those methods come from two different traits, it is obvious that there is a conflict because those have been implemented for different purposes. On the other hand, if two methods come from two different paths but the source of those methods the same trait, then there is no conflict. However, there is a case in which the source is the same but one of the methods is overridden by traits somewhere in the path. In this case, there is a conflict because now functionality is not unique. The Umple compiler detects these cases and raises this error.

Example

// In this example, there is a conflict in class "A" on the method "test()".
class A{
	isA T1;
	isA T2;
} 
trait T1 { 
	void test(){
	//special implementation by T1
	}
} 
trait T2 { 
	void test(){
	//special implementation by T2
	}
}


      

Load the above code into UmpleOnline

 

Another Example

// In this example, there is a conflict in trait "T" on the method "test()".
class A{
	isA T;
}
trait T{
	isA T1;
	isA T2;
}
trait T1{
	void test(){
	//special implementation by T1	
	}
}
trait T2{
	void test(){
	//special implementation by T2	
	}
}

      

Load the above code into UmpleOnline

 

Another Example

// In this example, there is a no conflict in class "A".
class A{
	isA T1;
	isA T2;
} 
trait T1 { 
	isA M;
} 
trait T2 { 
	isA M;
}
trait M{
	void test(){
	//special implementation by M
	}
}



      

Load the above code into UmpleOnline

 

Another Example

// In this example, there is a conflict in class "A" because method "test" is overridden in trait "T2".
class A{
	isA T1;
	isA T2;
} 
trait T1 { 
	isA M;
} 
trait T2 { 
	isA M;
	void test(){
	//special implementation by T2
	}
}
trait M{
	void test(){
	//special implementation by M
	}
}



      

Load the above code into UmpleOnline

 

E211 Two or More Modifications

Umple semantic error related to two or more modifications of provided methods of traits

When traits are used inside classes or traits, it is possible to add or remove provided methods. This feature is used to resolve conflicts and also when we do not need some provided methods or just need one of them. Logically, it is not correct to add a method twice or add and then remove a method. These problems are detected by the Umple compiler.

Example

// In this example, there are two modifications ("add") for the method "show()" when trait "T2" is used inside of trait "T1".
class A{
	isA T1;
}
trait T1{
	isA T2 <+show(),+show()>;
}
trait T2{
	void show(){
	//implementation
	}
}

      

Load the above code into UmpleOnline

 

Another Example

// In this example, there are two modifications ("add" and "remove") for the method "show()" when trait "T2" is used inside of trait "T1".
class A{
	isA T1;
}
trait T1{
	isA T2 <-show(),+show()>;
}
trait T2{
	void show(){
	//implementation
	}
}

      

Load the above code into UmpleOnline

 

E212 Methods Not Available

Umple semantic error related to modification of unavailable methods in traits

When traits are used inside classes or traits, it is possible to add or remove provided methods and also to change visibility and their names. This feature is used to resolve conflicts when we do not need some provided methods, just need one of them, need different visibilty, or need a different name. Logically, it is not correct to do these operations on methods which are not available. These problems are detected by the Umple compiler.

Example

// In this example, there is an error because trait "T1" tries to remove method "show()" from trait "T2" while it is not available in trait "T2".
class A{
	isA T1;
}
trait T1{
	isA T2 <-show()>;
}
trait T2{
}

      

Load the above code into UmpleOnline

 

Another Example

// In this example, there is an error because trait "T1" tries to add just method "show()" from trait "T2" to itself while it is not available in trait "T2".
class A{
	isA T1;
}
trait T1{
	isA T2 <+show()>;
}
trait T2{

}

      

Load the above code into UmpleOnline

 

Another Example

// In this example, there is an error in class "A" because it tries to change visibility of method "test()" which is not available in trait T. Consider that the method "test()" defined in trait "T" is a required method.
class A{
	isA T<test() as private>;
}
trait T{
	void test();
}

      

Load the above code into UmpleOnline

 

E213 Bidirectional Association in Traits

Umple semantic error related to having bidirectional association with interfaces

Traits can make associations with interfaces, classes, and template parameters. If one end of the association is a template parameter, the binding type must be checked to make sure it is compatible with the type of the association. For example, if a trait has a bidirectional association with a template parameter, the binding value cannot be an interface and it must be a class. Breaking this constraint is reported to modelers using this error code.

Example

// In this example, there is an error because a bidirectional association is created with interface I, which is not valid.
interface I {
  /*implementation*/
}
trait T <RelatedClass> {
  0..1 -- * RelatedClass;
  /*implementation*/
}
class C{
 isA T<RelatedClass=I>;
 /*implementation*/
}









      

Load the above code into UmpleOnline

 

E214 Two Identical Parameter Names

Umple semantic error related to having two identical template parameter names

When defining traits, it is possible to define template parameters for traits. The names of these parameters should be unique in order to let the compiler perform the correct binding for them. Therefore, when there are two or more template parameters, the Umple compiler detects it as an error.

Example

// In this example, there is an error because trait T has two template parameters with the same name.
trait T<TP,TP>{  
  TP name;
}
class C1{ 
  isA T;
}

      

Load the above code into UmpleOnline

 

E215 Template Parameter Not Available

Umple semantic error related to binding a template parameter of a trait which is not available

When using traits, we can bind types to template parameters. In the process of binding, we can just refer to parameters which are available. The Umple compiler detects cases in which there are template parameters not defined a trait.

Example

// In this example, there is an error because class A cannot bind type String to template parameter Y, which is not defined. for trait T.
class A{
  isA T< X= Integer, Y = String>;
}
trait T<X>{
	X variable;
}


      

Load the above code into UmpleOnline

 

E216 Twice Binding of a Parameter

Umple semantic error related to binding a template parameter twice

When using traits, we can bind values for template parameters. In the process of binding, we can bind two values for a template parameters. This bring a case in which there is no clear binding. The Umple compiler detects this case and prevents the system from being complied.

Example

// In this example, there is an error because there is two bindings for template parameter "X" in class "A".
class A{
	isA T< X = B , X = C >;
}
Class B{
	//elements
}
Class C{
	//elements
}
trait T<X,Z>{
	//elements
}

      

Load the above code into UmpleOnline

 

E217 Conflict in Types of Attributes

Umple semantic error related to having an attribute from a trait with different types

We can define template parameters for traits and use them with different bindings in several hierarchy paths. If types of some attributes are based on template parameters, there is a case in which those are bound with different values. In a case that a trait is going to be used in a diamond form of hierarchy, this can result in a conflict. Note that if the types are the same, then there is no conflict.

Example

// In this example, there is a conflict because in trait "T" there will be two attributes with the same name "data" but with different types which are "B" and "C".
class A{
	isA T;
}
class B{
	//elements
}
class C{
	//elements
}
trait T{
	isA T1;
	isA T2;
}
trait T1{
	isA Share<Type = B>;
}
trait T2{
	isA Share<Type = C>;
}
trait Share<Type> {
	Type data;
}

      

Load the above code into UmpleOnline

 

W218 Conflict in Attributes

Umple semantic error related to having an attribute with the same name in a traits and a class

When classes uses traits, all attributes in traits are flattened in classes. Therefore, if there are attributes with the same name, they might create a conflict. The Umple compiler considers this as a warning because it is the developers responsibilty to decide about the nature of the conflict. Sometimes, developers indicate exactly the same attributes and therefore there is no need to consider the conflict as an error. However, generally, if there are some attributes in host classes which traits need to use them, traits define them as required methods (needed accessors). In this case, host classes need to have accessors for those attributes. In the case of this warning, the Umple compiler just removes one of those attributes and proceeds.

Example

// In this example, there is a warning because in class "A" there will be two attributes with the name called "name".

class A{
	isA T;
	name;
}
trait T{
	name;
}


      

Load the above code into UmpleOnline

 

Another Example

// In this example, there is a warning because in trait "T" there will be two attributes with the name called "name".
class A{
	isA T;
}
trait T{
	isA T1;
	name;
}
trait T1{
	name;
}


      

Load the above code into UmpleOnline

 

E219 No Binding for Parameters

Umple semantic error related to having two same template parameter names

When defining traits, it is possible to define template parameters for traits. It means when traits with template parameters are going to be used by classes or traits, they must bind values for the parameters. If there is no binding for a parameter, the Umple compiler raises an error and shows which parameter does not have a value.

Example

// In this example, there is an error because class "A" doesn't bind a value to one of the template parameters of trait "T" named "Y".
class A{
	isA T<X = B>;
}
class B{
	//elements
}
trait T<X,Y>{
	//elements
}

      

Load the above code into UmpleOnline

 

Another Example

// In this example, there is an error because class "A" doesn't bind a value to template parameters of trait "T".
class A{
	isA T;
}
class B{
	//elements
}
trait T<X,Y>{
	//elements
}

      

Load the above code into UmpleOnline

 

E220 Two Methods With the Same Name

Umple semantic error related to changing name of a provided method in traits to one which already exists

When changing the name of provided methods in traits, it is necessary to be sure that there are no other methods with the same names that come from other traits. If the changed name already exists inside of a class, in this case there is no problem becase methods of classes have priority over ones coming from traits. In this case, the method from traits will be disregarded. Otherwise, there is a conflict on the name of methods. The Umple compiler detects this case and raises the error.

Example

// In this example, there is an error because in class "A" there will be two methods with the name "ShowInConsole".
class A{
	isA T<show() as ShowInConsole>;
}
trait T{
	isA T1;
	void show(){/*T*/}
}
trait T1{
	void ShowInConsole(){/*T1*/}
}

      

Load the above code into UmpleOnline

 

Another Example

// In this example, there is an error because in class "A" there will be two methods with the name "ShowInConsole".
class A{
	isA T<show() as ShowInConsole>;
	isA T1;
}
trait T{
	void show(){/*T*/}
}
trait T1{
	void ShowInConsole(){/*T1*/}
}

      

Load the above code into UmpleOnline

 

Another Example

// In this example, there is an error because in class "A" method "ShowInConslole" has high priority.
class A{
	isA T<show() as ShowInConsole>;
	isA T1;
	void ShowInConsole(){
	//Implementation 
	}  
}
trait T{
	void show(){
	//Implementation
	}
}
trait T1{
	void ShowInScreen(){
	//Implementation
	}
}

      

Load the above code into UmpleOnline

 

E221 Availability of Bound Type

Umple semantic error related to binding types to template parameters

When using a trait with a template parameter, a type must be bound to that template parameter. If the bound type is not available in the system, the Umple compiler raises this error.

Example

// In this example, there is an error because class C binds type C1 to the template parameter of trait T, while type C is not available in the system.
trait T<TP>{
/*implementation*/
}
class C{
  isA T<TP=C1>;
  /*implementation*/
}


      

Load the above code into UmpleOnline

 

E222 Satisfaction of Required Interfaces

Umple semantic error related to satisfaction of required interfaces of traits

When a class use traits, it needs to implement the required interfaces of those traits, otherwise, the Umple compiler detects missing interfaces and raises this error code. If a trait uses other traits with required interfaces, those required interfaces are added to the set of required interfaces of the trait and final clients are required to implement all of those required interfaces as well.

Example

// In this example, there is an error because class C must implement required interface of trait T, which is interface I.
trait T{
  /*implementation*/
  isA I;
}
interface I{
  /*implementation*/
}
class C{
  isA T;
  /*implementation*/
}


      

Load the above code into UmpleOnline

 

E223 Availability of Types

Umple semantic error related to availability of types used to constraint template parameters

If traits define template parameters and put constraints on them, the classes and interfaces involved in the constraints must exist in the system under design, otherwise, this error is raised.

Example

// In this example, there is an error because type I used to constraint template parameters TP in trait T does not exist.
trait T<TP isA I>{
  /*implementation*/
}
class C1{
  /*implementation*/
}
class C1{
  isA T< TP = C1 >;
  /*implementation*/
}


      

Load the above code into UmpleOnline

 

E224 Multiple Inheritance Constraint

Umple semantic error related to putting multiple inheritance constraint on template parameters

If a multiple inheritance is applied as a constraint to a template parameter, it is detected and this error is raised. Umple does not support multiple inheritance.

Example

// In this example, there is an error because trait T puts multiple inheritance constraint on its template parameter TP.
trait T<TP isA C1&C2>{
  /*implementation*/
}
class C1{ 
  /*implementation*/
}
class C2{ 
  /*implementation*/
}



      

Load the above code into UmpleOnline

 

E225 Satisfaction of Bound Type

Umple semantic error related to binding a type to a template parameter

If clients bind types to the template parameters of used traits and the types exist but they do not satisfy the constraints of the template parameters, this error is raised. The constraint is related to inheritance.

Example

// In this example, there is an error because class C1 is not subclass of class C2. Any bound value to template parameter TP must be a subclass of class C2.
trait T<TP isA C2>{
  /*implementation*/
}
class C{
  isA T< TP = C1 >;
  /*implementation*/
}
class C1{/*implementation*/}
class C2{/*implementation*/}




      

Load the above code into UmpleOnline

 

W228 Different Initial States

Umple semantic error related to composing state machines or regions

If two state machines or regions are being composed and do not the same initial states.

Example

// In this example, there is an warning because two traits T1 and T2 have state machines with the same name but with different initial states.
trait T1{
  sm{
    s1{ e1 ->  s2;}
    s2{ e3 ->  s3;}
    s3{ e2 ->  s2;}
  }
}
trait T2{
  sm{
    t1{ t1 ->  t2;}
    t2{ t3 ->  s3;}
    s3{ t2 ->  t2;}
  }
}
class C1{
  isA T1,T2;
}





      

Load the above code into UmpleOnline

 

E229 Two Times Renaming

Umple semantic error related to state machine operators

When a state is to be renamed, it should not be renamed more than one time. If this happens, the Umple compiler detects that and raises this error.

Example

// In this example, there is an error because class C tries two rename states s0 of trait T two times.
trait T {
  sm{
    s0{
      e1-> s1;
      s11{ e12-> s12; }
      s12{ e11-> s11; }   
    }
    s1{ e0-> s1;  }  
  }
}
class C {
  isA T<sm.s0 as state0, sm.s0 as state01>;
}





      

Load the above code into UmpleOnline

 

E230 Availability of State Machines

Umple semantic error related to state machine operators

When a state machine or state with a given name is specified by the renaming operator, it must be available in the trait being operated on, either directly in the trait or another trait used by the trait. Otherwise, the Umple compiler raises this error.

Example

// In this example, there is an error because state machine sm3 is not available in trait T.
trait T {
  sm1{
	s0 {e1-> s1;}
	s1 {e0-> s0;}
  }
  sm2{
	s0 {e1-> s1;}
	s1 {e0-> s0;}
  }
}
class C3 {
 isA T<sm3 as mach1>;
}





      

Load the above code into UmpleOnline

 

E231 Availability of Events

Umple semantic error related to state machine operators

When an event name is used with a specific name for its state machine, the state machine and event must be available in the trait, otherwise, the Umple compiler raises this error.

Example

// In this example, there is an error because event e2() is not available in state machine sm.
trait T {
  sm{
    s0{
      e1-> s1;
      s11{ e12-> s12; }
      s12{ e11-> s11; }   
    }
    s1{ e0-> s1;  }  
  }
}
class C {
  isA T<sm.e2() as event2>;
}






      

Load the above code into UmpleOnline

 

E232 Availability of Events

Umple semantic error related to state machine operators

When an event name is used with a specific name for its state machine, the state machine and event must be available in the trait. The same restriction is applied when the symbol * is used for the name of state machines. If the event is not available in at least one of state machines existing in the trait, then the Umple compiler raises thi error code.

Example

// In this example, there is an error because event e2() is not available in state machines of trait T.
trait T {
  sm{
    s0{
      e1-> s1;
      s11{ e12-> s12; }
      s12{ e11-> s11; }   
    }
    s1{ e0-> s1;  }  
  }
}
class C {
  isA T<*.e2() as event2>;
}






      

Load the above code into UmpleOnline

 

E233 Removing Initial State

Umple semantic error related to state machine operators

The removing operator cannot be applied to the initial states of a state machine or a composite state. If the modeler applies it in such cases, the Umple compiler raises this error.

Example

// In this example, there is an error because the initial state of a state machine cannot be removed.
trait T {
  sm{
    s0{
      e1-> s1;
      s11{ e12-> s12; }
      s12{ e11-> s11; }   
    }
    s1{ e0-> s1;  }  
  }
}
class C {
  isA T<-sm.s0>;
}






      

Load the above code into UmpleOnline

 

E234 Compositing Non-Deterministic Transitions

Umple semantic error related to state machine composition algorithm

Umple does not support non-deterministic state machines and so composed state machines must be deterministic as well. Our composition algorithm automatically detects transitions that cause the composed state to be non-deterministic and raises this error code.

The example below shows how a transition in a base state could be cause to have non-determinism. As seen, both state machines in class C1 and trait T1 have state s1 and they need to be composed. The state s1 in trait T1 has transition e1[x>0] and the transition’s destination is s2. The base state s1 has transition e1 without a guard and its destination state is state s3. This transition does not exist in the state s1 coming from the trait, so it can be added to the composed state s1. However, this causes a situation in which the composite state machine can be in two states s2 and s3 simultaneously. Therefore, the composition is not allowed.

Example

// In this example, there is an error because the composed state machine will be nondeterministic.
trait T1{
  sm{
    s1{ e1[x>0] -> s2;  }
    s2{ e2 -> s1; }
  }
}
class C1{
  isA T1;
  sm{
    s1{
      e1 -> s3;
      e3 -> s3;
    }
    s3{ }
  }
}







      

Load the above code into UmpleOnline

 

E235 SuperCall Conflict

Umple semantic error related to state machine composition algorithm

When clients use more than one trait, using the keyword superCall can cause a conflict. This happens because an order of execution is required.

As seen in the example below, class C1 uses two traits T1 and T2 and there is matching state s1 and matching transition e1 needed to be composed. Since the keyword has been used in the base transition e1, it indicates that the actions of matching transitions to be executed, but are more than one action to be executed. Therefore, the Umple compiler prevents these models from being composed.

Example

// In this example, there is an error because the keyword superCall can be pointed out to two used traits.
trait T1{
  sm{
    s1{ e1 -> /{action1();} s1; }
  }
}
trait T2{
  sm{
    s1{ e1 -> /{action2();} s2;}
    s2{}
  }
}
class C1{
  isA T1,T2;
  sm{
    s1{ e1 -> /{superCall; action3();} s3; }
    s3{}
  }
}







      

Load the above code into UmpleOnline

 

E236 Two State Entries

Umple semantic error related to state machine composition algorithm

A client can use more than one trait (and obtain more than one state machine) and so it is possible to have more than two states whose entry (or exit) actions (and do activities) need to be composed with the base state’s entry action. In this case, the composition algorithm needs to consider an order among them. Since we do not consider any order when traits are used by clients, this should be respected in the composition of actions. Therefore, the Umple compiler detects this case and raises this error. Note that this conflict happens if more than one state coming from used traits have an entry action.

The example below shows a case in which composition of entry actions is considered as a conflict. The base state s1 in class C1 has no entry action and so it can accept entry actions coming from state machines in T1 and T2. However, there are two entries coming from used traits which cause a conflict. Note that if class C1 did not have state machine sm, it would still be a conflict for composition. However, if state s1 in class C1 had an entry then this would not be a conflict because those entries coming from traits would be disregarded.

Example

// In this example, there is an error because of having different ways to compose entries of two states S1 coming from traits T1 and T2.
trait T1{
  sm{
    s1{ entry /{action1();} }
  }
}
trait T2{
  sm{
    s1{ entry /{action2();} }
  }
}
class C1{
  isA T1, T2;
  sm{
    s1{}
  } 
}







      

Load the above code into UmpleOnline

 

E237 Composing Two State Entries

Umple semantic error related to state machine composition algorithm

A client can use more than one trait (and obtain more than one state machine) and so it is possible to have more than two states whose entry (or exit) actions (and do activities) need to be composed with the base state’s entry action. In this case, the composition algorithm needs to consider an order among them. Since we do not consider any order when traits are used by clients, this should be respected in the composition of actions. Therefore, the Umple compiler detects this case and raises this error. Note that this conflict happens if more than one state coming from used traits have an entry action.

The example below shows a case in which composition of entry actions is considered as a conflict. The base state s1 in class C1 has no entry action and so it can accept entry actions coming from state machines in T1 and T2. However, there are two entries coming from used traits which cause a conflict. Note that if class C1 did not have state machine sm, it would still be a conflict for composition. However, if state s1 in class C1 had an entry then this would not be a conflict because those entries coming from traits would be disregarded.

Example

// In this example, there is an error because class C rename the region name r1 to r2 which is already available in the state machine sm.
trait T{
  sm {
    s1{
      r1{ e1-> r11; }
      r11{}
      ||
      r2{ e2-> r21; }
      r21{}
    }
  }
}
class C{
  isA T<sm.s1.r1 as r2>;
}








      

Load the above code into UmpleOnline

 

W901 Deprecated Keyword Constant

Umple warning reported when deprecated keyword "constant" is used.

The keyword "constant" is still supported in Umple interfaces due to legacy reasons. However, there is no guarantee that this keyword will be supported in the future. The keyword "const" should be used instead.

Example

// This causes the warning
interface Y {
  constant A=5;
}

      

Load the above code into UmpleOnline

 

Another Example

// This does not cause the warning
interface Y {
  const A=5;
}

      

Load the above code into UmpleOnline

 

W1002-3 Unexpected Embedded Code

Umple warning reported when embedded code is found in a native language like Java, PHP or C++, yet 'strictness' has been set indicating this should not occur.

If strictness is set to 'modelOnly', this means that the developer intends to only include classes, associations, state machines and other modeling elements, but not embedded code in another programming language, not even method bodies.

If strictness is set to 'noExtraCode', it is the same as the above, except that method bodies are allowed.

This warning is issued when strictness has been set to one of the above, yet Umple has encountered sytax that interprets as either a method body or some other code in a class that it cannot parse, and is assuming it is native code to be passed to the native compiler.

This warning can often happen when the programmer/modeler wrote Umple code with a syntax error, so Umple thinks it is not Umple, but some other language. Here are some things to try in order to resolve this warning:

Example

// The following example shows how to generate this warning.
strictness modelOnly;
class X {
  public static void main() {
    System.out.println("Hello World");
  }
}

      

Load the above code into UmpleOnline

 

E1004-5 Messages not as Expected

Umple errors reported when an expected message is not found or a disallowed message is found.

The strictness clause with 'expected' can be used to indicate that a certain message is expected. An error occurs when the expected warning or error does not actually occur.

Similarly, the strictness clause with 'disallowed' can be used to indicate that a certain message is not expected. An error occurs when the expected warning or error does occur.

W1006 State Machine Not Parsed

Umple semantic warning reported when a state machine could not be fully parsed and is treated as 'extra code'.

In Umple, elements of a class not recognized as valid Umple are assumed to be elements of the target programming language that are embedded in the Umple. However, this warning is raised when the Umple compiler has reason to believe that the developer might have been trying to specify a state machine, because the segment of code starts with something like sm {.

Since that sequence is not found in target languages, and since it is easy to make a mistake specifying states, substates, or events, this message is generated. If you encounter this message and indeed intended to specify a state machine, look carefully at the state machine code. Make sure the curly brackets match; make sure there are semicolons after transitions (unless the transitions have an action). If you are still stuck, comment out segments until you can narrow down the problem.

@@example @@source manualexamples/W1006StateMachineNotParsed1.ump @@endexample

W1007 Element Not Parsed

Umple semantic warning reported when a when Umple finds an un-parsable element in a class, which is likely a malformed attribute or association declaration.

Umple emits such elements 'as is' as 'extra code' in its generated code, in case they are some part of the base language that Umple cannot understand

Example

// The following will generate two such warnings
class X {
  blah blah blah;
  1 - * X;
}

      

Load the above code into UmpleOnline

 

W1008 Method Not Parsed

Umple semantic warning reported when a method could not be fully parsed and is treated as 'extra code'. The method will still be emitted and can be called, but Umple cannot analyse it.

In Umple, elements of a class not recognized as valid Umple are assumed to be elements of the target programming language that are embedded in the Umple. However, this warning is raised when the Umple compiler has reason to believe that the developer might have been trying to specify a method, but omitted some aspect.

Note that currently, Java main methods generate this warning. It can be safely ignored in that context, and the warning will eventually be removed.

Example

// This example generates the warning because there is a missing return type
class X {
  m() {}
}


      

Load the above code into UmpleOnline

 

W1011 Invalid Association Class Key

Umple semantic warning reported when an Association Class key is missing a required member.

For Association Classes with explicit keys, each class that participates in the relationship should be declared as a member of that key.

Example

// This example generates the warning because one participating class is missing from the key
class Passenger {}

class Flight {}

associationClass Booking {
  Integer number;
  * Passenger passenger;
  * Flight flight;
  key {number, flight}
}


      

Load the above code into UmpleOnline

 

Another Example

// This example shows how to remove the warning by completing the key
class Passenger {}

class Flight {}

associationClass Booking {
  Integer number;
  * Passenger passenger;
  * Flight flight;
  key {number, flight, passenger}
}


      

Load the above code into UmpleOnline

 

E15xx Parsing Error

Umple error messages reported when the Umple parser can't interpret the code.

These messages occurs in several contexts:

E1510 Use File Missing

Umple error messages reported when a use statement refers to a file that cannot be loaded.

The argument to a use statement must be a valid .ump file found in the same directory as the file with the use statement, or in its parent directory, or in a subdirectory named lib.

Check the spelling of the filename, and check file permissions.

W20xx Error in Embedded Code

Umple warning issued when a base language compiler encounters a non-umple error

Under development: Umple can have code in any programming language embedded in method bodies or other constructs. This warning is issued when the compiler for the embedded language reports an error. This can occur of the -c option is supplied to the Umple compiler, telling it to invoke the base language compiler after the Umple is generated.

Page Being Developed

You most likely encountered an error or warning in UmpleOnline, and clicking on the message displayed this page. The web page explaining that message has not yet been created. In the meantime, you can search the manual or browse the links on the left.

W9999 Feature Under Development

Umple warning reported a feature is used that is not yet fully implemented in Umple

Features are often added to the syntax of Umple before they are added to the semantics and code generation. This is to ensure that adding the feature will not break existing code. If you receive this warning, then it means you are using such a feature. No code is yet generated from this feature, or else the generated code is incomplete.