meyfa/nsdlib

View on GitHub
README.md

Summary

Maintainability
Test Coverage
# nsdlib

[![Build Status](https://travis-ci.com/meyfa/nsdlib.svg?branch=master)](https://travis-ci.com/meyfa/nsdlib)
[![Test Coverage](https://api.codeclimate.com/v1/badges/c0a3b52c6757567ba2f5/test_coverage)](https://codeclimate.com/github/meyfa/nsdlib/test_coverage)
[![Maintainability](https://api.codeclimate.com/v1/badges/c0a3b52c6757567ba2f5/maintainability)](https://codeclimate.com/github/meyfa/nsdlib/maintainability)

This is a Java library for working with [Nassi-Shneiderman diagrams](https://en.wikipedia.org/wiki/Nassi–Shneiderman_diagram)
(structograms).

It offers the following functionality:

* **Construct elements through code**
  - All standard block types supported
* **Read structograms from files**
  - Currently only support for the [Structorizer](http://structorizer.fisch.lu/)
    format, but easy to add your own
* **Render structograms as images**
  - Basic layouting, dynamic size calculation
  - High amount of abstraction through `RenderAdapter` (AWT adapter included;
    support for custom adapters for other targets, e.g. Android)



## Reading a Structogram

The following code reads a structogram stored in Structorizer's XML format.

```java
NSDReader reader = new StructorizerReader();

NSDRoot root;

File file = new File("/path/to/file.nsd");
try (FileInputStream in = new FileInputStream(file)) {
    root = reader.read(in);
} catch (NSDReaderException | IOException e) {
    e.printStackTrace();
}

// do something with `root`
```

Feel free to submit a PR or open an issue if you require support for other
formats. The custom reader should implement the `NSDReader` interface.



## Rendering a Structogram

To render a structogram (or part of one), the following steps need to be done:

1. Convert the element into a `RenderPart` (do this for the root element).
2. Layout the render part.
3. Render the actual image.

The following example uses the `AwtRenderer` for rendering to a `BufferedImage`,
but you can easily substitute a custom renderer instead.

```java
AwtRenderer renderer = new AwtRenderer();

// 1. convert (`diagram` is an instance of `NSDRoot`)
RenderPart part = diagram.toRenderPart();

// 2. layout
part.layout(renderer.createContext());
// optional: get the resulting size
// Size s = part.getSize();

// 3. render
BufferedImage img = renderer.render(part);
```



## Manual Structogram Construction

Constructing a structogram with code is as simple as invoking a few
constructors.

```java
NSDRoot diagram = new NSDRoot("When start clicked");

NSDDecision dec = new NSDDecision("(pick random 1 to 10) = 1");
{
    dec.getThen().addChild(new NSDInstruction("say \"You're lucky!\""));
    dec.getElse().addChild(new NSDInstruction("say \"Not so lucky.\""));
}
diagram.addChild(dec);

NSDForever forever = new NSDForever(Arrays.asList(
    new NSDInstruction("wait 1 secs")
));
diagram.addChild(forever);

// etc
```



## Element Types

The base class for every element is `nsdlib.elements.NSDElement`. Elements that
contain other elements extend its subclass `nsdlib.elements.NSDContainer`.

| Type                 | Package                        | Class              |
| -------------------- | ------------------------------ | ------------------ |
| Root element         | `nsdlib.elements`              | `NSDRoot`          |
| Instruction          | `nsdlib.elements`              | `NSDInstruction`   |
| If/Then/Else         | `nsdlib.elements.alternatives` | `NSDDecision`      |
| Switch-Case          | `nsdlib.elements.alternatives` | `NSDCase`          |
| Test-first loop      | `nsdlib.elements.loops`        | `NSDTestFirstLoop` |
| Test-last loop       | `nsdlib.elements.loops`        | `NSDTestLastLoop`  |
| Unconditional loop   | `nsdlib.elements.loops`        | `NSDForever`       |
| Concurrent execution | `nsdlib.elements.parallel`     | `NSDParallel`      |