Projet

Général

Profil

Actions

SpeADL Dynamic Tutorial » Historique » Révision 8

« Précédent | Révision 8/37 (diff) | Suivant »
Anonyme, 14/10/2014 16:21


SpeADL for Dynamic Architectures Tutorial

This is a tutorial for SpeADL: understanding ecosystems and species, defining a simple ecosystem, composing species together with uses.

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.

Prerequisites

It is needed to understand the content of the SpeADL⁻ tutorial before doing this one.

Creating a New Project and Organisation

Create a Java project.
We will use again an organisation of the package and namespaces as explained in this best practice.

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.

Defining the Ecosystem and the Species

Create a SpeADL file named logging.speadl in the package tutorial2.logging.

Define in it the ecosystem and the species in the right namespace as well as the needed interface:

import tutorial2.logging.interfaces.ILog

namespace tutorial2.logging {

    ecosystem Logging {
        species Logger(name: String) {
            provides log: ILog
        }
    }

}

package tutorial2.logging.interfaces;

public interface ILog {

    public void addLine(String line);
}

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:

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 {
            this.logWriter = new PrintWriter(new FileWriter(logFile), true);
        } 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;
    }
}

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.

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

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:

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

    }
}

Execute it and confirm that the file /tmp/tutorial2-logging-test.txt contains the following:

[a] 1 a says hi
[a] 2 test test
[b] 3 b says hoy
[a] 4 blabla
[c] 5 hop

Implementing the Ecosystem and the Species, Second One

We can now define a second implementation that stores the logs of each Logger in its own file:

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;
import tutorial2.logging.interfaces.ILog;

public class LoggingImplTwo extends Logging {

    private final File logDir;

    public LoggingImplTwo(File logDir) {
        this.logDir = logDir;
        this.logDir.mkdirs();
    }

    @Override
    protected Logger make_Logger(String name) {
        return new LoggerImpl(new File(logDir, name+".txt"));
    }

    private class LoggerImpl extends Logger implements ILog {

        private PrintWriter logWriter;

        public LoggerImpl(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 {
                this.logWriter = new PrintWriter(new FileWriter(logFile), true);
            } 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 ILog make_log() {
            return this;
        }

        @Override
        public void addLine(String line) {
            if (logWriter != null) {
                logWriter.println(line);
            }
        }
    }
}

That can be tested with the following subclass:

package tutorial2.logging.tests;

import java.io.File;

import tutorial2.logging.impl.LoggingImplTwo;

public class LoggingImplTwoTest extends LoggingImplTwo {

    public LoggingImplTwoTest(File logDir) {
        super(logDir);
    }

    @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 LoggingImplTwoTest(new File("/tmp/tutorial2-logging2-test/")).newComponent();
    }
}

Execute it and confirm that the /tmp/tutorial2-logging2-test/ directory contains one file per Logger with the correct content.

The Banking Ecosystem

Banking will also be an ecosystem, it will contain Account that are species with a particularity: they have required ports!
Because of that, they can't simply be created but must be composed with other components or species to be usable.

Defining the Ecosystem and the Species

Mis à jour par Anonyme il y a plus de 11 ans · 37 révisions