Projet

Général

Profil

SpeADL Dynamic Tutorial » Historique » Version 7

Anonyme, 14/10/2014 15:49

1 3 Anonyme
h1. SpeADL for Dynamic Architectures Tutorial
2 2 Anonyme
3 7 Anonyme
{{>toc}}
4
5 1 Anonyme
This is a tutorial for SpeADL: understanding ecosystems and species, defining a simple ecosystem, composing species together with uses.
6 3 Anonyme
7
h2. Objectives
8
9
The objective of this tutorial to understand the abstractions of species and uses.
10
11
We will create a Logging ecosystem that contains Logger species.
12
Then we will create a Banking ecosystem that contains Account species that need to log what happens.
13
Finally we will create a Bank ecosystem that compose Account species with Logger species thanks to the use abstraction.
14
15
h2. Prerequisites
16
17
It is needed to understand the content of the [[SpeADL Minus Tutorial|SpeADL⁻ tutorial]] before doing this one.
18
19
h2. Creating a New Project and Organisation
20
21
Create a Java project.
22
We will use again an organisation of the package and namespaces as explained in [[MAY Best Practices#Project Organisation|this best practice]].
23
24
h2. The Logging Ecosystem
25
26
Logging will be an ecosystem, and its particularity is that it will be able to create Loggers: while logging is the subsystem responsible of all logging, each logger will be responsible of logging one particular aspect of the system identified by a _name_.
27
We will have multiple implementation for the Logging ecosystem:
28
* One with only one file where to log with each line prepended with the name.
29
* One with one file per Logger all in the same directory.
30
31
h3. Organisation
32
33
Create the following hierarchy of packages:
34
* tutorial2.logging
35
** impl
36
** interfaces
37
38
h3. Defining the Ecosystem and the Species
39
40
Create a SpeADL file named _filesystem.speadl_ in the package _tutorial2.filesystem_.
41
42
Define in it the ecosystem and the species in the right namespace as well as the needed interface:
43
<pre>
44
import tutorial2.filesystem.interfaces.ILog
45
46
namespace tutorial2.filesystem {
47
	
48
	ecosystem Logging {
49
		species Logger(name: String) {
50
			provides log: ILog
51
		}
52
	}
53
	
54
}
55
</pre>
56
57
<pre>
58
package tutorial2.filesystem.interfaces;
59
60
public interface ILog {
61
62
	public void addLine(String line);
63
}
64
</pre>
65
66
h3. Implementing the Ecosystem and the Species, First One
67
68 4 Anonyme
Create a new Java class in _tutorial2.logging.impl_ named _LoggingImplOne_ that extends _Logging_, that takes the a _File_ as a parameter to the constructor to store the logs, and resolve the error with the Quick Fixes of Eclipse:
69 3 Anonyme
<pre>
70
package tutorial2.logging.impl;
71
72
import java.io.File;
73
import java.io.FileNotFoundException;
74 5 Anonyme
import java.io.FileWriter;
75 3 Anonyme
import java.io.IOException;
76
import java.io.PrintWriter;
77
78
import tutorial2.logging.Logging;
79
80
public class LoggingImplOne extends Logging {
81
82
	private PrintWriter logWriter;
83
	
84
	public LoggingImplOne(File logFile) {
85
		// if an exception happens, nothing can be done about it
86
		// we just let logStream be null and
87
		// the operations of logging won't be done
88
		try {
89 5 Anonyme
			this.logWriter = new PrintWriter(new FileWriter(logFile), true);
90 3 Anonyme
		} catch (FileNotFoundException e) {
91 5 Anonyme
			System.err.println("An error happened with the file, nothing will be logged.");
92 1 Anonyme
			this.logWriter = null;
93 3 Anonyme
		} catch (IOException e) {
94 5 Anonyme
			System.err.println("An error happened with the file, nothing will be logged.");
95 3 Anonyme
			this.logWriter = null;
96
		}
97
	}
98
	
99
	@Override
100
	protected Logger make_Logger(String name) {
101
		// TODO Auto-generated method stub
102
		return null;
103
	}
104
}
105
</pre>
106
107
As we can see, the species we defined needs to be implemented and this implementation needs to be returned by the method _Logger make_Logger(String name)_.
108
109 4 Anonyme
Let's define an inner class inside _LoggingImplOne_ to do that, it will take as a parameter to the constructor the _name_ of the Logger and that will exploit the _logWriter_ to do the actual logging.
110 3 Anonyme
<pre>
111
public class LoggingImplOne extends Logging {
112
113
	private PrintWriter logWriter;
114
	
115
	// ...
116
	
117
	@Override
118
	protected Logger make_Logger(String name) {
119
		return new LoggerImpl(name);
120
	}
121
	
122
	private class LoggerImpl extends Logger implements ILog {
123
124
		private final String name;
125
		
126
		public LoggerImpl(String name) {
127
			this.name = name;
128
		}
129
		
130
		@Override
131
		protected ILog make_log() {
132
			return this;
133
		}
134 1 Anonyme
135
		@Override
136
		public void addLine(String line) {
137 5 Anonyme
			if (logWriter != null) {
138
				logWriter.println("["+name+"] "+ line);
139
			}
140 1 Anonyme
		}
141
	}
142
}
143 5 Anonyme
</pre>
144
145
We now have a complete implementation for the Logging ecosystem.
146
Let's test it with a very simple program, for that we will subclass _LoggingImplOne_ in _tutorial2.logging.tests_, create some Logger in its *start()* method and instantiate it:
147
<pre>
148
package tutorial2.logging.tests;
149
150
import java.io.File;
151
152
import tutorial2.logging.impl.LoggingImplOne;
153
154
public class LoggingImplOneTest extends LoggingImplOne {
155
156
	public LoggingImplOneTest(File logFile) {
157
		super(logFile);
158
	}
159
160
	@Override
161
	protected void start() {
162
		// create new Loggers
163
		Logger.Component l1 = newLogger("a");
164
		Logger.Component l2 = newLogger("b");
165
		Logger.Component l3 = newLogger("c");
166
		// log things to them
167
		l1.log().addLine("1 a says hi");
168
		l1.log().addLine("2 test test");
169
		l2.log().addLine("3 b says hoy");
170
		l1.log().addLine("4 blabla");
171
		l3.log().addLine("5 hop");
172
	}
173
	
174
	public static void main(String[] args) {
175
		new LoggingImplOneTest(new File("/tmp/tutorial2-logging-test.txt")).newComponent();
176
		
177
	}
178
}
179
</pre>
180
181 6 Anonyme
Execute it and confirm that the file _/tmp/tutorial2-logging-test.txt_ contains the following:
182 5 Anonyme
<pre>
183
[a] 1 a says hi
184
[a] 2 test test
185
[b] 3 b says hoy
186
[a] 4 blabla
187
[c] 5 hop
188 3 Anonyme
</pre>
189
190 1 Anonyme
h3. Implementing the Ecosystem and the Species, Second One
191 6 Anonyme
192
We can now define a second implementation that stores the logs of each Logger in its own file:
193
<pre>
194
package tutorial2.logging.impl;
195
196
import java.io.File;
197
import java.io.FileNotFoundException;
198
import java.io.FileWriter;
199
import java.io.IOException;
200
import java.io.PrintWriter;
201
202
import tutorial2.logging.Logging;
203
import tutorial2.logging.interfaces.ILog;
204
205
public class LoggingImplTwo extends Logging {
206
207
	private final File logDir;
208
209
	public LoggingImplTwo(File logDir) {
210
		this.logDir = logDir;
211
		this.logDir.mkdirs();
212
	}
213
	
214
	@Override
215
	protected Logger make_Logger(String name) {
216
		return new LoggerImpl(new File(logDir, name+".txt"));
217
	}
218
	
219
	private class LoggerImpl extends Logger implements ILog {
220
221
		private PrintWriter logWriter;
222
		
223
		public LoggerImpl(File logFile) {
224
			// if an exception happens, nothing can be done about it
225
			// we just let logStream be null and
226
			// the operations of logging won't be done
227
			try {
228
				this.logWriter = new PrintWriter(new FileWriter(logFile), true);
229
			} catch (FileNotFoundException e) {
230
				System.err.println("An error happened with the file, nothing will be logged.");
231
				this.logWriter = null;
232
			} catch (IOException e) {
233
				System.err.println("An error happened with the file, nothing will be logged.");
234
				this.logWriter = null;
235
			}
236
		}
237
		
238
		@Override
239
		protected ILog make_log() {
240
			return this;
241
		}
242
243
		@Override
244
		public void addLine(String line) {
245
			if (logWriter != null) {
246
				logWriter.println(line);
247
			}
248
		}
249
	}
250
}
251
</pre>
252
253
That can be tested with the following subclass:
254
<pre>
255
package tutorial2.logging.tests;
256
257
import java.io.File;
258
259
import tutorial2.logging.impl.LoggingImplTwo;
260
261
public class LoggingImplTwoTest extends LoggingImplTwo {
262
263
	public LoggingImplTwoTest(File logDir) {
264
		super(logDir);
265
	}
266
	
267
	@Override
268
	protected void start() {
269
		// create new Loggers
270
		Logger.Component l1 = newLogger("a");
271
		Logger.Component l2 = newLogger("b");
272
		Logger.Component l3 = newLogger("c");
273
		// log things to them
274
		l1.log().addLine("1 a says hi");
275
		l1.log().addLine("2 test test");
276
		l2.log().addLine("3 b says hoy");
277
		l1.log().addLine("4 blabla");
278
		l3.log().addLine("5 hop");
279
	}
280
	
281
	public static void main(String[] args) {
282
		new LoggingImplTwoTest(new File("/tmp/tutorial2-logging2-test/")).newComponent();
283
	}
284
}
285
</pre>
286
287
Execute it and confirm that the _/tmp/tutorial2-logging2-test/_ directory contains one file per Logger with the correct content.