User Tools

Site Tools


v040:language

This is an old revision of the document!


Language Guide for version 0.4.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

Starting from version 0.3.0, 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 "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:

  • boolean,
  • integer,
  • string.

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

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

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 have primitive types. 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

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

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 port, 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 define the of signals that can be sent to or from the ports. An interface lists the signals that can be received through that interface. 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 from 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> {}

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 and 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 `b` is a part of class `A`.

Let us suppose that class `A` has two parts: `b` of type `B` and `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:

TODO

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 sigdata 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 getSignal 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 sigdata 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 getSignal method shall be used instead.

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

Signal sending

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

Control structures

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

  • if,
  • while,
  • for.

In XtxtUML, the foreach variant of the for control structure can be used with separator in instead of the default : present in Java. That is:

// XtxtUML:
for (A a in collectionOfA) { /* ... */ }
v040/language.1458637600.txt.gz · Last modified: 2016/03/22 10:06 by deva