Projet

Général

Profil

SpeADL Minus Reference » Historique » Version 12

Anonyme, 06/10/2014 10:38

1 1 Anonyme
h1. SpeADL Minus Reference
2
3 2 Anonyme
{{>toc}}
4
5 1 Anonyme
In SpeADL, a set of abstractions are provided to define traditional component-oriented architectures.
6 4 Anonyme
With it, it is possible to define software components and compositions of components, called composites, implement in Java. while keeping a strong link between definition and implementation by relying on an Eclipse plugin.
7 1 Anonyme
8 4 Anonyme
A component is made of two elements: a class definition using SpeADL and an implementation using Java.
9
Optionally, the SpeADL definition can contain an implementation aspect in the form of a composition of components connected together through their ports.
10
From the SpeADL definition, an abstract Java class (which exactly reflect the content of the definition) is automatically generated and then relied upon through the Java extension mechanism to implement what is left in the component in a safe manner.
11 1 Anonyme
12
h2. Namespaces
13
14 5 Anonyme
A namespace plays the exact same role as a package in Java.
15
16 4 Anonyme
h3. Keyword
17
18 1 Anonyme
Components is defined inside namespace using the keyword *namespace*.
19
20 4 Anonyme
h3. Details
21
22 1 Anonyme
In a SpeADL file, there can be many as namespace (as well as nested ones) as wanted.
23
Hence a namespace does not have to follow the name of the directory it is located in as in Java.
24
25 4 Anonyme
Each namespace declaration can contain any component as desired as we are going to see.
26
27
h3. Example
28
29 1 Anonyme
<pre>
30
namespace simple {
31
32
	namespace things {
33
	}
34
}
35
36
namespace simple.stuffs {
37
}
38
</pre>
39
40
h2. Imports
41
42 5 Anonyme
As in Java, it is possible to import existing types into a file to avoid referring to them with their fully qualified name (i.e., including their package or namespace).
43 1 Anonyme
44 5 Anonyme
h3. Keyword and Role
45
46
As in Java, this is done with the keyword *import*.
47
48
h3. Details
49
50
The namespace of components are also considered to import component class definitions.
51
There is no semi-colon ";" at the end of the line.
52
53
Also the imports can be automatically handled and reorganised in Eclipse using the *Ctrl-Shift-O* shortcut as in the Java editor.
54
55
They are always at the top of a SpeADL file.
56
57
h3. Example
58
59 1 Anonyme
The syntax is similar to Java:
60
<pre>
61
import java.util.Collection
62
import java.util.*
63
import simple.stuffs.*
64
</pre>
65
66 5 Anonyme
h2. Component Class Definition
67 1 Anonyme
68 5 Anonyme
A software component is made of a class definition and a class implementation: an instance can then be created from the implementation.
69
A component class definition has provided and required ports, as well as parts which are themselves components.
70
A part is structurally similar to a class member in Java.
71
For each required port of a part, there must be a binding declaring what is providing the required port.
72 1 Anonyme
73 5 Anonyme
h3. Keywords
74 1 Anonyme
75 5 Anonyme
A component class is defined with the keyword *component* followed by a name starting with a capital letter and must be unique in its namespace.
76 1 Anonyme
77 5 Anonyme
The keywords *provided* and *required* are used to declare respectively provided and required ports, they are followed by a name (unique in the component and without capital letter) and an interface name.
78
It takes the form *provided name: Interface* or *required name: Interface*.
79 1 Anonyme
80 5 Anonyme
The keyword *part* is used to declare a part in the component: a part is structurally similar to a class member in Java.
81
It is followed by a name for the part (unique in the component and without capital letter), a component class definition name.
82
It takes the form *part name: ComponentName*.
83
84
A binding is used to declare for each required port, using the keywords *bind ...1 to ...2* where *...1* is the name of the required port of the part and *...2* is a reference to a port available in the current containing component.
85
Such a reference can either be:
86
* To another part's provided port, taking the form *bind req to name.port*.
87
* A provided or a required port of the current containing component, taking the form *bind req to port*.
88
89
A delegation is used to declare for the provided port of a component what other port will provides its implementation using the keyword = followed by a reference to a port available in the current containing component (as with bindings).
90 9 Anonyme
It takes the form *provided name: Interface = name.port* or *provided name: Interface = port*.
91 5 Anonyme
92
h3. Details
93
94
An interface is understood as a Java interface, i.e., a collection of methods, and must be declared in the classpath of the Java project.
95
96
A component with required ports must be composed with other components so that there exist an actual implementation of the interface of the required port.
97 1 Anonyme
98 5 Anonyme
In SpeADL, one can use completion to complete interface names.
99
Also, the shortcut to organize imports will take interfaces into account.
100
101
h3. Example
102
103 6 Anonyme
Component class definitions:
104 1 Anonyme
<pre>
105
import my.interfaces.*
106
107
namespace simple.stuffs {
108
109
	component MySimpleComponent {
110
		provides p1: AnotherJavaInterface
111
	}
112
113
	component MyBeautifulComponent {
114
		provides portName: AJavaInterface
115
		requires anotherPortName: AnotherJavaInterface
116
	}
117
118 5 Anonyme
	component MyComplexComponent {
119
		
120
		provides p1: AnotherJavaInterface
121
		provides p2: AnotherJavaInterface = s.p1
122
		requires p3: AnotherJavaInterface
123 1 Anonyme
124 5 Anonyme
		part b1: MyBeautifulComponent {
125
			bind anotherPortName to s.p1 
126
		}
127 1 Anonyme
128 5 Anonyme
		part b2: MyBeautifulComponent {
129
			bind anotherPortName to p1
130
		}
131
132
		part b3: MyBeautifulComponent {
133
			bind anotherPortName to p3
134
		}
135
		
136
		part s: MySimpleComponent
137
		
138
	}
139
}
140
</pre>
141
142
Interface definition in Java:
143 1 Anonyme
<pre>
144
package my.interfaces;
145
146
public interface AJavaInterface {
147
  public String aMethod(Integer param1);
148
}
149
</pre>
150
151
<pre>
152
package my.interfaces;
153
154
public interface AnotherJavaInterface {
155
	public Integer test();
156
}
157
</pre>
158
159 6 Anonyme
h2. Component Class Implementations
160 1 Anonyme
161
To implement a component, one has to extend the abstract class generated automatically by the Eclipse plugin.
162
For example, for the previous example of component, a Java class *simple.stuffs.MyBeautifulComponent* was generated (in the speadl-gen folder, separated from the src folder).
163
164
It is not needed to look at the generated code to use it: when extending the class, some abstract methods must be implemented.
165
It is a good idea to use the errors shown by the Eclipse Java editor and their quick-fixes to quickly generate the skeleton of the implementation itself.
166
167 12 Anonyme
When implementing a component, one only has to take care of implementing the provided port, and can exploit the required ports without assuming anything about their implementation and who provides it.
168
This is what makes a component fundamentally different from an object.
169
170 7 Anonyme
h3. Special Methods to Implement
171 1 Anonyme
172 7 Anonyme
Each provided port *p* of interface *I* must be implemented by overriding a method called *I make_p()* which returns an implementation for the port used for the whole life of the component (i.e., the *make_p()* method is called only once to construct the port when the component is instantiated).
173 6 Anonyme
174
Each part *p* of component class *C* has a corresponding abstract method *C make_p()* to override and which must return an instance of an implementation of *C*.
175 7 Anonyme
The bindings and other connections inside the components are totally taken care of by the generated code and the implementation only needs what is Java-specific.
176 6 Anonyme
177 8 Anonyme
Furthermore, optionally, a method *void start()* can be override as explained [[SpeADL_Minus_Reference#Component-Initialisation|below]].
178
179 7 Anonyme
h3. Special Methods to Exploit
180 6 Anonyme
181 7 Anonyme
The *requires()* method (inherited from the extended generated class) gives access to each of the required ports (e.g.,*requires().port()*).
182
A port being an implementation of an interface (and not of an operation), it is then necessary to call the desired method on it (e.g., *requires().port().method()*).
183 6 Anonyme
184 7 Anonyme
It is possible to access to the provided ports of the part from within the implementation of a composite by using the method *parts()* (e.g., *parts().partName().portName().method()*).
185 6 Anonyme
186
h3. Examples
187
188
Implementing a component with a provided port:
189 1 Anonyme
<pre>
190
package testpackage;
191
192
import my.interfaces.AnotherJavaInterface;
193
import simple.stuffs.MySimpleComponent;
194
195
public class MySimpleComponentImpl extends MySimpleComponent {
196
197
	@Override
198
	protected AnotherJavaInterface make_p1() {
199
		return new AnotherJavaInterface() {
200
			@Override
201
			public Integer test() {
202
				return 10;
203
			}
204
		};
205
	}
206
207
}
208
</pre>
209
210 6 Anonyme
The same result can be obtained by implementing the port directly by the component implementation as follow:
211 1 Anonyme
<pre>
212 6 Anonyme
public class MySimpleComponentImpl extends MySimpleComponent implements AnotherJavaInterface {
213
214
	@Override
215
	public Integer test() {
216
		return 10;
217
	}
218
	
219
	@Override
220
	protected AnotherJavaInterface make_p1() {
221
		return this;
222
	}
223
}
224
</pre>
225
226
Exploiting a required port:
227
<pre>
228 1 Anonyme
package testpackage;
229
230
import my.interfaces.AJavaInterface;
231
import simple.stuffs.MyBeautifulComponent;
232
233
public class MyComponentImpl extends MyBeautifulComponent {
234
235
	@Override
236
	protected AJavaInterface make_portName() {
237
		return new AJavaInterface() {
238
			@Override
239
			public String aMethod(Integer param1) {
240
				return "" + param1 + " and " + requires().anotherPortName().test();
241
			}
242
		};
243
	}
244
}
245
</pre>
246
247 6 Anonyme
Implementing a component with parts, calling a part's provided port:
248 1 Anonyme
<pre>
249
public class ComplexCompImpl extends MyComplexComponent {
250
251
	@Override
252
	protected MySimpleComponent make_s() {
253
		return new MySimpleComponentImpl();
254
	}
255
256
	@Override
257
	protected AnotherJavaInterface make_p1() {
258
		return new AnotherJavaInterface() {
259
			@Override
260
			public Integer test() {
261
				return parts().s().p1().test();
262
			}
263
		};
264
	}
265
266
	@Override
267
	protected MyBeautifulComponent make_b1() {
268
		return new MyComponentImpl();
269
	}
270
271
	@Override
272
	protected MyBeautifulComponent make_b2() {
273
		return new MyComponentImpl();
274
	}
275
276
	@Override
277
	protected MyBeautifulComponent make_b3() {
278
		return new MyComponentImpl();
279
	}
280
281
}
282
</pre>
283
284
h2. Instantiation
285
286
In order to instantiate a component, one need an instance of an implementation of the component and to call the *newComponent()* method (present in the generated class) to get an instance of the component.
287 10 Anonyme
288
h3. Details
289
290 1 Anonyme
Only component without required port can be manually instantiated: if a component has required ports, it must be composed with other components in a composite component.
291
292 10 Anonyme
Once we have an instance of a component, we can call the methods of its provided ports.
293
294
The same applies for composite components, the instantiation of the part of a composite is done automatically by the generated code.
295
296
h3. Example
297
298 1 Anonyme
<pre>
299
MySimpleComponent.Component c = new MySimpleComponentImpl().newComponent();
300
System.out.println(c.p1().test());
301
</pre>
302
303
h2. Component Initialisation
304
305
When the implementation of a component is instantiated (before calling *newComponent()*), its constructor is of course called but the component itself is not yet initialised: in particular its provided required ports and parts can't be called at that time.
306
307
In order to do some initialisation at the instantiation of a component (during the call to *newComponent()*), one can override the *void start()* method in the implementation as follow:
308
309
<pre>
310
public class MySimpleComponentImpl extends MySimpleComponent {
311
312
	@Override
313
	protected AnotherJavaInterface make_p1() {
314
		return new AnotherJavaInterface() {
315
			@Override
316
			public Integer test() {
317
				return 10;
318
			}
319
		};
320
	}
321
	
322
	@Override
323
	protected void start() {
324
		// do some initialisation using the requires() or the parts(), create a GUI, etc...
325
	}
326
}
327
</pre>