aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/docs/src/learn/language/classes/index.md
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/docs/src/learn/language/classes/index.md')
-rw-r--r--subprojects/docs/src/learn/language/classes/index.md212
1 files changed, 212 insertions, 0 deletions
diff --git a/subprojects/docs/src/learn/language/classes/index.md b/subprojects/docs/src/learn/language/classes/index.md
new file mode 100644
index 00000000..73108039
--- /dev/null
+++ b/subprojects/docs/src/learn/language/classes/index.md
@@ -0,0 +1,212 @@
1---
2SPDX-FileCopyrightText: 2024 The Refinery Authors
3SPDX-License-Identifier: EPL-2.0
4description: Metamodeling in Refinery
5sidebar_position: 0
6---
7
8# Classes and references
9
10Refinery supports _metamodeling_ to describe the desired structure of generated models.
11
12The metamodeling facilities are inspired by object-oriented software and the [Eclipse Modeling Foundation](https://eclipse.dev/modeling/emf/) (EMF) Core, a lightweight framework for data models.
13The textual syntax in Refinery for defining metamodels is largely compatible with [Xcore](https://wiki.eclipse.org/Xcore), a textual syntax for EMF metamodels.
14
15## Classes
16
17Classes are declared with the `class` keyword.
18
19Like in many programming languages, class members are specified between curly braces `{}`.
20If a class has no members, the declaration may be terminated with a `.` instead.
21
22```refinery
23% Class with no members.
24class Region {}
25
26% Alternative syntax without curly braces.
27class State.
28```
29
30By default, a _new object_ is added to the partial model to represent the instances of a class.
31For example, the new objects `Region::new` and `State::new` represent potential instances of the classes `Region` and `State`, respectively:
32
33import NewObjectsSimple from './NewObjectsSimple.svg';
34
35<NewObjectsSimple />
36
37As you can see, no new objects represent potential nodes that are instanceof of both `Region` and `State`.
38In fact, such instances are not permitted at all.
39Each node must the instance of a _single most-specific class:_
40
41import InvalidInstance from './InvalidInstance.svg';
42
43<InvalidInstance />
44
45### Inheritance
46
47Like in object-oriented programming languages, classes may declare _superclasses_ with the `extends` keyword.
48The inheritance hierarchy may not contain any cycles (a class cannot be a superclass of itself), but _multiple inheritance_ is allowed.
49
50Classes that can't be instantiated directly (i.e., a subclass must be instantiated instead) can be marked with the `abstract` keyword.
51Such classes do not have a _new object,_ since there are no direct instances to represent.
52
53```refinery
54abstract class CompositeElement.
55class Region.
56abstract class Vertex.
57abstract class RegularState extends Vertex.
58class State extends RegularState, CompositeElement.
59```
60
61Notice that the new object `State::new` is an instance of `CompositeElement`, `Vertex`, `RegularState`, and `State` as well.
62
63import NewObjectsWithInheritance from './NewObjectsWithInheritance.svg';
64
65<NewObjectsWithInheritance />
66
67## References
68
69The graph structure of model generated by Refinery is determined by the _references_ of the metamodel, which will appear as labeled edges between nodes (class instances).
70
71References are declared as class members by providing the _target type,_ and optional _multiplicity,_ and the name of the reference:
72
73```refinery
74class Vertex.
75class Transition {
76 Vertex[1] source
77 Vertex[1] target
78}
79```
80
81import ReferencesSimple from './ReferencesSimple.svg';
82
83<ReferencesSimple />
84
85You may add the `refers` keyword for compatibility with [Xcore](https://wiki.eclipse.org/Xcore). The following specification is equivalent:
86
87```refinery
88class Vertex.
89class Transition {
90 refers Vertex[1] source
91 refers Vertex[1] target
92}
93```
94
95### Opposite constraints
96
97The `opposite` keywords specifies that two references are in an _opposite_ relationship, i.e., if one reference is present in a direction, the other must be present between the same nodes in the opposite direction.
98
99```
100class Vertex {
101 Transition[] outgoingTransition opposite source
102 Transition[] incomingTransition opposite target
103}
104class Transition {
105 Vertex[1] source opposite outgoingTransition
106 Vertex[1] target opposite incomingTransition
107}
108```
109
110import ReferencesOppositeInstance from './ReferencesOppositeInstance.svg';
111
112<ReferencesOppositeInstance />
113
114Opposites must be declared in pairs: it is a specification error to declare the `opposite` for one direction but not the other.
115
116Unlike in EMF, references that are the `opposite` of themselves are also supported.
117These must always be present in both directions between two nodes.
118Thus, they correspond to undirected graph edges.
119
120```refinery
121class Person {
122 Person[] friend opposite friend
123}
124```
125
126import ReferencesOppositeSelf from './ReferencesOppositeSelf.svg';
127
128<ReferencesOppositeSelf />
129
130### Multiplicity
131
132_Multiplicity constrains_ can be provided after the reference type in square braces.
133They specify how many _outgoing_ references should exist for any given instance of the class.
134
135:::info
136
137To control the number of _incoming_ references, add an `opposite` reference with multiplicity constraint.
138
139:::
140
141A multiplicity constraint is of the form `[n..m]`, where the non-negative integer `n` is the _lower_ bound of outgoing references,
142and `m` is a positive integer or `*` corresponding to the _upper_ bound of outgoing references.
143The value of `*` represent a reference with _unbounded_ upper multiplicity.
144
145If `n` = `m`, the shorter form `[n]` may be used.
146The bound `[0..*]` may be abbreviated as `[]`.
147If the multiplicity constraint is omitted, the bound `[0..1]` is assumed.
148
149---
150
151In the following model, the node `v1` satisfies all multiplicity constraints of `outgoingTransition`.
152The node `v2` violates the lower bound constraint, while `v3` violates the upper bound constraint.
153All `Transition` instances satisfy the multiplicity constrains associated with `source`.
154
155```refinery
156class Vertex {
157 Transition[2..3] outgoingTransition opposite source
158}
159class Transition {
160 Vertex[1] source opposite outgoingTransition
161}
162```
163
164import MultiplicityConstraintsInstance from './MultiplicityConstraintsInstance.svg';
165
166<MultiplicityConstraintsInstance />
167
168### Containment hierarchy
169
170To structure models and ensure their connectedness, Refinery supports _containment_ constraints.
171
172References may be marked as _containment_ references with the `contains` keyword.
173
174Classes that are the _target type_ of at least one _containment_ reference are considered `contained`.
175An instance of a `contained` class must have exactly 1 incoming containment reference.
176Instances of classes that are not `contained` must _not_ have any incoming containment references.
177
178Containment references have to form a _forest_, i.e., they must not contain any cycles.
179The _roots_ of the forest are instances of classes that are not `contained`, while `contained` classes for the internal nodes and leaves of the trees.
180
181Opposites of _containment_ references have to be marked with the `container` keyword.
182They must not specify any multiplicity constraint, since the multiplicity is already implied by the containment hierarchy.
183
184---
185
186In the following model, the instances of `Region` are the roots of the containment hierarchy.
187The classes `Vertex` are `Transition` are both considered `contained`.
188
189```refinery
190class Region {
191 contains Vertex[] vertices opposite region
192}
193
194class Vertex {
195 container Region region opposite vertices
196 contains Transition[] outgoingTransition opposite source
197 Transition[] incomingTransition opposite target
198}
199
200class Transition {
201 container Vertex source opposite outgoingTransition
202 Vertex[1] target opposite incomingTransition
203}
204```
205
206Containment edges are show with **thick** lines:
207
208import ContainmentInstance from './ContainmentInstance.svg';
209
210<ContainmentInstance />
211
212Containment edges form trees, while non-containment references, such as `target`, may point across the containment hierarchy.