Downloader

This example models a simple downloader object that tracks the progress of a download operation by combining typestates and ghost variables.

import liquidjava.specification.*;

@RefinementAlias("Percentage(int p) { 0 <= p && p <= 100 }")
@Ghost("int progress")
@StateSet({"created", "downloading", "completed"})
public class Downloader {
    @StateRefinement(to="created() && progress() == 0")
    public Downloader() {}

    @StateRefinement(from="created() && progress() == 0", to="downloading() && progress() == 0")
    public void start() {}

    @StateRefinement(from="downloading() && percentage > progress()", to="downloading() && progress() == percentage")
    public void update(@Refinement("Percentage(_)") int percentage) {}

    @StateRefinement(from="downloading() && progress() == 100", to="completed()")
    public void finish() {}
}
Downloader d = new Downloader();
d.start();
d.update(50);
d.update(100);
d.finish();
Downloader d = new Downloader();
d.start();
d.update(50);
d.finish(); // State Refinement Error