User Tools

Site Tools


v060:language

Language Guide for version 0.6.0

txtUML models can be written using two different syntaxes:

  • XtxtUML is a custom modelling syntax designed to be clean and short.
  • JtxtUML is a Java API to create models using Java syntax.

This page introduces the txtUML language concepts by showing both syntactic variants.

Model

txtUML models can be split into separate files. The model itself is represented by a package marked as a model.

In XtxtUML, this marking is done in a model-info.xtxtuml file of the following form:

// XtxtUML:
model-package example.x.model as "ExampleModel";

In JtxtUML, the marking is done in a package-info.java file, using the following annotation:

// JtxtUML:
@Model("ExampleModel")
package name.of.package;
 
import hu.elte.txtuml.api.model.Model;

Primitive types

The currently supported primitive types in txtUML:

  • Integer,
  • Boolean,
  • String,
  • Real.

Both in XtxtUML and JtxtUML, the primitive types are represented by the following Java types respectively:

  • int,
  • boolean,
  • java.lang.String,
  • double.

Classes

// XtxtUML:
// Must be defined inside the package representing the model.
class ExampleClass {
  // attributes, operations, state machine
}
 
class DerivedClass extends ExampleClass { /* ... */ }
// JtxtUML:
// Must be defined inside the package representing the model.
class ExampleClass extends ModelClass {
  // attributes, operations, state machine
}
 
class DerivedClass extends ExampleClass { /* ... */ }

Additionally in XtxtUML, in case of an empty class definition, the curly braces can be replaced by a semicolon. That is, the following class definitions are semantically equivalent:

// XtxtUML:
class ExampleClass {}
// XtxtUML:
class ExampleClass;

Attributes

In txtUML, the attributes of classes can only be primitive types, data types or model enums. References to instances of model classes must be held with the use of associations.

// XtxtUML:
class ExampleClass {
  // Syntax is the same as in Java.
  int i;
  private String str;
}
// JtxtUML:
class ExampleClass extends ModelClass {
  // Java fields.
  int i;
  private String str;
}

Operations

In addition to the allowed types for attributes, parameters and the result of an operation can also be model classes or signals.

// XtxtUML:
class ExampleClass {
  // Syntax is the same as in Java.
  public void op1(boolean param) { /* ... */ }
 
  public int op2(ExampleClass param) { /* ... */ }
}
// JtxtUML:
class ExampleClass extends ModelClass {
  // Java methods.
  public void op1(boolean param) { /* ... */ }
 
  public int op2(ExampleClass param) { /* ... */ }
}

Associations

// XtxtUML:
// Must be defined inside the package representing the model.
association ExampleAssociation {
  // A and B are XtxtUML classes.
  1..* A a;
  1..* B b;
}
// JtxtUML:
// Must be defined inside the package representing the model.
class ExampleAssociation extends Association {
  // A and B are Java classes that extend ModelClass
  // (they represent classes of the model).
  class a extends Some<A> {}
  class b extends Some<B> {}
}

Multiplicities

In XtxtUML, multiplicities can be written as in UML. Some examples:

  • *
  • 1
  • 1..4
  • 2..*

In JtxtUML, the following pre-defined multiplicities might be used:

  • Many (0..*),
  • Some (1..*),
  • MaybeOne (0..1),
  • One (1..1).

Also, the Multiple class is given to define custom multiplicities:

// JtxtUML:
class ExampleAssociation2 extends Association {
  @Min(1) // If not specified, the lower bound is 0.
  @Max(2) // If not specified, the upper bound is * (unlimited).
  class a extends Multiple<A> {}
  class b extends Many<B> {}
}
// XtxtUML:
association ExampleAssociation3 {
  // A non-navigable association end.
  hidden 1..* A a;
  // A navigable association end.
  1..* B b;
}
// JtxtUML:
class ExampleAssociation3 extends Association {
  // A non-navigable association end.
  class a extends HiddenSome<A> {}
  // A navigable association end.
  class b extends Some<B> {}
}

Composite associations

Composite associations describe ownership relations.

// XtxtUML:
composition ExampleComposition {
  container A a;
  * B b;
}
// JtxtUML:
class ExampleComposition extends Composition {
  class a extends Container<A> {}
  class b extends Many<B> {}
}

According to UML, the multiplicity of the container end is implicitly 0..1, the multiplicity of the other end can be arbitrarily defined. Both ends can be either navigable or non-navigable: The container end can be made non-navigable by writing hidden container in XtxtUML or extending HiddenContainer in JtxtUML.

Model enums

// XtxtUML:
// Must be defined inside the package representing the model.
enum ExampleEnum {
  A, B, C
}
// JtxtUML:
// Must be defined inside the package representing the model.
enum ExampleEnum implements ModelEnum {
  A, B, C
}

Data types

Data types in txtUML represent value types. As a result, their instances have no identity and they must be immutable, i.e. all of their fields must be final. Data types are not yet supported in XtxtUML.

// JtxtUML:
// Must be defined inside the package representing the model.
class ExampleDataType extends DataType {
  // Attributes of the data type are given as final Java fields.
  public final int i; 
  public final boolean b;
 
  // Constructors are allowed to set the fields.
  ExampleDataType(int i, boolean b) { /* ... */ }
 
  // Operations are allowed too.
  public int op(int param) { /* ... */ }
}
 
class DerivedDataType extends ExampleDataType { /* ... */ }

Signals

// XtxtUML:
// Must be defined inside the package representing the model.
signal ExampleSignal {
  // Parameters of the signal are given as fields.
  public int i; 
  public boolean b;
}

In XtxtUML, only signal parameters are allowed inside a signal definition, from which a constructor is going to be inferred. Signal inheritance is not yet supported in XtxtUML.

// JtxtUML:
// Must be defined inside the package representing the model.
class ExampleSignal extends Signal {
  // Parameters of the signal are given as Java fields.
  public int i; 
  public boolean b;
 
  // Constructors are allowed to set the fields.
  ExampleSignal(int i, boolean b) { /* ... */ }
}
 
class DerivedSignal extends ExampleSignal { /* ... */ }

Ports and connectors

Classes can have ports, and ports can be connected by connectors. Instead of sending a signal directly to another object, it is possible to send the message to one of the sender's own ports, from where the signal is propagated to the target object via connectors. The advantage of port-based communication is that the sender does not need to know about the target object: It is possible to create a “component library” and connect these components in different setups, without changing the internal implementation of the “components”.

Interfaces

Ports are typed by interfaces, which list the signals that can be sent to or from the ports. The signals must be declared independently of the interfaces, and a signal can be used in more than one interface.

// XtxtUM
interface ExampleInterface {
  reception ExampleSignal1;
  reception ExampleSignal2;
}
// JtxtUML
public interface ExampleInterface extends Interface {
  public void reception(ExampleSignal1 signal);
  public void reception(ExampleSignal2 signal);
}

Ports

Ports of a class are defined inside the class. Ports can be characterized by two interfaces: The provided interface defines which signals can be sent to that port by the environment of the class. The required interface tells which signals can be sent from the port to the environment.

// XtxtUML
port ExamplePort {
  provided Interface1;
  required Interface2;
}
// JtxtUML
public class ExamplePort extends Port<Interface1,Interface2> {}

If a port is designed for one-way communication, then one of the interfaces is empty. In XtxtUML, the empty interface is just omitted from the definition:

// XtxtUML
port AcceptingPort {
  provided Interface1;
}

In JtxtUML there are two options. First, the API contains a predefined empty interface:

// JtxtUML
public class AcceptingPort extends Port<Interface1,Interface.Empty> {}

Second, InPort and OutPort can be used as shorthands for one-way ports:

// JtxtUML
public class AcceptingPort extends InPort<Interface1> {}

Behavior ports

If a signal arrives to a port from the outside, it is either processed by the state machine of the class or routed to another object. In the first case the port is called behavior port, and is defined as follows:

// XtxtUML
behavior port ExamplePort {
  provided Interface1;
  required Interface2;
}
// JtxtUML
@BehaviorPort
public class ExamplePort extends Port<Interface1,Interface2> {}

Connectors

Connectors are not simply defined between ports of classes, but ports of parts. Parts are defined by composite associations. For example:

// XtxtUML:
composition ExampleComposition {
  container A a;
  B b;
}
// JtxtUML:
class ExampleComposition extends Composition {
  class a extends Container<A> {}
  class b extends One<B> {}
}

In this case the role name ExampleComposition.b is a part of class A.

Let us suppose that class A has two parts: Comp1.b of type B and Comp2.c of type C. Let P be a port of B and Q be a port of C. It is possible to connect the port P on part b with Q on part c using an assembly connector:

// XtxtUML
connector ExampleConnector {
  Comp1.b->B.P connEnd1;
  Comp2.c->C.Q connEnd2;
}
// JtxtUML
public class ExampleConnector extends Connector {
  public class connEnd1 extends One<Comp1.b, B.P> {}
  public class connEnd2 extends One<Comp2.c, C.Q> {}
}

Currently only One is supported as connector end multiplicity.

The above assembly connector is valid only if the interfaces of the ports are compatible, meaning that the required interface of P is the same as the provided interface of Q and vice versa.

The other connector type is called delegation connector. These connect a port of a class with a port of one of its parts. A delegation connector means that any signal arriving to the port from the outside is delegated to the specified port of the given part.

For example, if Comp3.d is a part of A of type D, the role name of the composite association at A is Comp3.a, R is a port of class A and S is a port of D, then a delegation connector between R and S is defined as follows:

// XtxtUML
delegation ExampleDelegation {
  Comp3.a->A.R connEnd1;
  Comp3.b->D.S connEnd2;
}
// JtxtUML
public class ExampleDelegation extends Delegation {
  public class connEnd1 extends One<Comp3.a, A.R> {}
  public class connEnd2 extends One<Comp3.d, D.S> {}
}

Currently only One is supported as connector end multiplicity.

The above delegation connector is valid only if the interfaces of the ports are compatible, meaning that the required interface of R is the same as the required interface of S and similarly for the provided interfaces.

We suggest reviewing the clock and pingpong models of the demo projects to see examples for port based communication.

State machines

In txtUML, elements of the state machine of a class are all written inside the class.

Initial state and initial transition

// XtxtUML:
// Inside an XtxtUML class.
initial Init;

// OtherVertex is either a state, a composite state or a choice.
transition T0 {
  from Init;
  to OtherVertex;
}
// JtxtUML:
// Inside a Java class extending ModelClass.
class Init extends Initial {}
 
// OtherVertex is either a state, a composite state or a choice.
@From(Init.class) @To(OtherVertex.class)
class T0 extends Transition {}

States

// XtxtUML:
// Inside an XtxtUML class.
state S1 {
  // Defining entry or exit activities is optional.
  entry { /* ... */ }
  exit { /* ... */ }  
}
// JtxtUML:
// Inside a Java class extending ModelClass.
class S1 extends State {
  // Overriding entry or exit is optional.
  // Their default implementation does nothing.
  @Override
  public void entry() { /* ... */ }
  @Override
  public void exit() { /* ... */ }  
}

In XtxtUML, use the trigger keyword inside entry or exit to obtain the signal instance that triggered the currently performed transition. Its type is automatically inferred as the common supertype of the possible triggers. In JtxtUML, the protected getTrigger method shall be used instead.

Additionally in XtxtUML, in case of an empty state, composite state or choice definition, the curly braces can be replaced by a semicolon. That is, the following definitions are semantically equivalent:

// XtxtUML:
state S1 {}
// XtxtUML:
state S1;

Transitions

// XtxtUML:
// Inside an Xtxtuml class.
transition LabeledTransition {
  from S1; // S1 is a state or composite state.
  to V1; // V1 is a vertex (state, composite state or choice).
  trigger Sig; // Sig is a signal.
  
  // Defining an effect or a guard is optional.
  effect { /* ... */ }
  // The default guard is true.
  guard ( /* boolean expression */ );
}

transition UnlabeledTransition {
  from C1; // C1 is a choice.
  to V1; // V1 is a vertex (state, composite state or choice).
  effect { /* ... */ }
  guard ( else ); // To specify the guard of this transition as [else].
}
// JtxtUML:
// Inside a Java class extending ModelClass.
@From(S1.class) // S1 is a state or composite state.
@To(V1.class) // V1 is a vertex (state, composite state or choice).
@Trigger(Sig.class) // Sig is a signal.
class LabeledTransition extends Transition {
  // Overriding effect or guard is optional.
  // The default implementation of effect does nothing.
  @Override
  public void effect() { /* ... */ }
  // The default implementation of guard returns true.
  @Override
  public boolean guard() { /* ... */ }  
}
 
@From(C1.class) // C1 is a choice.
@To(V1.class) // V1 is a vertex (state, composite state or choice).
class UnlabeledTransition extends Transition {
  @Override
  public void effect() { /* ... */ }
  @Override
  public boolean guard() {
    return Else(); // To specify the guard of this transition as [else].
  }  
}

In XtxtUML, use the trigger keyword inside effect or guard to obtain the signal instance that triggered the currently performed transition. Its type is automatically inferred as the common supertype of the possible triggers. In JtxtUML, the protected getTrigger method shall be used instead.

Transitions can also be labeled by ports. In that case the transition is triggered only if the specified signal arrives from the specified port.

transition ExampleTransition {
  from State1;
  to State2;
  port ExamplePort;
  trigger ExampleSignal;
}
@From(State1.class) @To(State2.class)
@Trigger(port = ExamplePort.class, value = ExampleSignal.class)
class ExampleTransition extends Transition {}

Choice nodes

// XtxtUML:
// Inside an XtxtUML class.
choice C1 { /* ... */ }
// JtxtUML:
// Inside a Java class extending ModelClass.
class C1 extends Choice { /* ... */ }

Hierarchical states

// XtxtUML:
composite CS1 {
  // May define entry and exit activities like a simple state.
  
  initial Init;
  // Write the code of the subregion here.
}
// JtxtUML:
class CS1 extends CompositeState {
  // May override entry and exit like a simple state.
  class Init extends Initial {}
  // Write the code of the subregion here.
}

Action code

Object creation

// XtxtUML:
// With parameters p1, ..., pn.
A obj = create(A, p1, ..., pn);
// JtxtUML:
// With parameters p1, ..., pn.
A obj = Action.create(A.class, p1, ..., pn);

Object deletion

// XtxtUML:
delete obj;
// JtxtUML:
Action.delete(obj);
// XtxtUML:
link(AB.a, instanceOfA, AB.b, instanceOfB);

// In case of the following association definition:
association AB {
  1..* A a;
  1..* B b;
}
// JtxtUML:
Action.link(AB.a.class, instanceOfA, AB.b.class, instanceOfB);
 
// In case of the following association definition:
class AB extends Association {
  class a extends Some<A> {}
  class b extends Some<B> {}
}
// XtxtUML:
unlink(AB.a, instanceOfA, AB.b, instanceOfB);
// JtxtUML:
Action.unlink(AB.a.class, instanceOfA, AB.b.class, instanceOfB);

Association navigation

// XtxtUML:
Collection<B> all = instanceOfA->(AB.b); // the parentheses after -> are mandatory
B obj = all.selectAny();
// JtxtUML:
Collection<B> all = instanceOfA.assoc(AB.b.class);
B obj = all.selectAny();

Note: even in XtxtUML, the selectAny() call can be performed directly on the navigation expression:

// XtxtUML:
B obj = instanceOfA->(AB.b).selectAny();

Connector instantiation

// XtxtUML:
connect(Comp1.a, aObj->(A.P), Comp2.b, bObj->(B.Q));
// JtxtUML:
Action.connect(Comp1.a.class, aObj.port(A.P.class),
               Comp2.b.class, bObj.port(B.Q.class));

Starting the state machine of an object

// XtxtUML:
start(obj);
// JtxtUML:
Action.start(obj);

Signal sending to objects

// XtxtUML:
send sig to obj; // sig is a signal instance.
// JtxtUML:
Action.send(sig, obj); // sig is a signal instance.

Signal sending to ports

// XtxtUML
send sig to this->(MyPort);
// JtxtUML
Action.send(sig, port(MyPort.class).required::reception);

Control structures

Both in XtxtUML and JtxtUML, the following Java control structures can be used:

  • if,
  • while,
  • for.
v060/language.txt · Last modified: 2017/04/24 07:09 by ndj94