SpeADL Dynamic Tutorial » Historique » Révision 5
Révision 4 (Anonyme, 14/10/2014 15:22) → Révision 5/37 (Anonyme, 14/10/2014 15:39)
h1. SpeADL for Dynamic Architectures Tutorial
This is a tutorial for SpeADL: understanding ecosystems and species, defining a simple ecosystem, composing species together with uses.
h2. Objectives
The objective of this tutorial to understand the abstractions of species and uses.
We will create a Logging ecosystem that contains Logger species.
Then we will create a Banking ecosystem that contains Account species that need to log what happens.
Finally we will create a Bank ecosystem that compose Account species with Logger species thanks to the use abstraction.
h2. Prerequisites
It is needed to understand the content of the [[SpeADL Minus Tutorial|SpeADL⁻ tutorial]] before doing this one.
h2. Creating a New Project and Organisation
Create a Java project.
We will use again an organisation of the package and namespaces as explained in [[MAY Best Practices#Project Organisation|this best practice]].
h2. The Logging Ecosystem
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_.
We will have multiple implementation for the Logging ecosystem:
* One with only one file where to log with each line prepended with the name.
* One with one file per Logger all in the same directory.
h3. Organisation
Create the following hierarchy of packages:
* tutorial2.logging
** impl
** interfaces
h3. Defining the Ecosystem and the Species
Create a SpeADL file named _filesystem.speadl_ in the package _tutorial2.filesystem_.
Define in it the ecosystem and the species in the right namespace as well as the needed interface:
<pre>
import tutorial2.filesystem.interfaces.ILog
namespace tutorial2.filesystem {
ecosystem Logging {
species Logger(name: String) {
provides log: ILog
}
}
}
</pre>
<pre>
package tutorial2.filesystem.interfaces;
public interface ILog {
public void addLine(String line);
}
</pre>
h3. Implementing the Ecosystem and the Species, First One
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:
<pre>
package tutorial2.logging.impl;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import tutorial2.logging.Logging;
public class LoggingImplOne extends Logging {
private PrintWriter logWriter;
public LoggingImplOne(File logFile) {
// if an exception happens, nothing can be done about it
// we just let logStream be null and
// the operations of logging won't be done
try {
logFile.createNewFile();
this.logWriter = new PrintWriter(new FileWriter(logFile), true); PrintWriter(logFile);
} catch (FileNotFoundException e) {
System.err.println("An error happened with the file, nothing will be logged.");
this.logWriter = null;
} catch (IOException e) {
System.err.println("An error happened with the file, nothing will be logged.");
this.logWriter = null;
}
}
@Override
protected Logger make_Logger(String name) {
// TODO Auto-generated method stub
return null;
}
}
</pre>
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)_.
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.
<pre>
public class LoggingImplOne extends Logging {
private PrintWriter logWriter;
// ...
@Override
protected Logger make_Logger(String name) {
return new LoggerImpl(name);
}
private class LoggerImpl extends Logger implements ILog {
private final String name;
public LoggerImpl(String name) {
this.name = name;
}
@Override
protected ILog make_log() {
return this;
}
@Override
public void addLine(String line) {
if (logWriter != null) {
logWriter.println("["+name+"] "+ line);
}
}
}
}
</pre>
We now have a complete implementation for the Logging ecosystem.
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:
<pre>
package tutorial2.logging.tests;
import java.io.File;
import tutorial2.logging.impl.LoggingImplOne;
public class LoggingImplOneTest extends LoggingImplOne {
public LoggingImplOneTest(File logFile) {
super(logFile);
}
@Override
protected void start() {
// create new Loggers
Logger.Component l1 = newLogger("a");
Logger.Component l2 = newLogger("b");
Logger.Component l3 = newLogger("c");
// log things to them
l1.log().addLine("1 a says hi");
l1.log().addLine("2 test test");
l2.log().addLine("3 b says hoy");
l1.log().addLine("4 blabla");
l3.log().addLine("5 hop");
}
public static void main(String[] args) {
new LoggingImplOneTest(new File("/tmp/tutorial2-logging-test.txt")).newComponent();
}
}
</pre>
We can confirm that the file _/tmp/tutorial2-logging-test.txt_ contains the following:
<pre>
[a] 1 a says hi
[a] 2 test test
[b] 3 b says hoy
[a] 4 blabla
[c] 5 hop
</pre>
h3. Implementing the Ecosystem and the Species, Second One