Memra

Part 1 recap: events, parsing, exceptions, serialize & restore

The non-concurrent half: parameterized events, parsing examples*.txt with Scanner + regex, a custom ControllerException, an orderly shutdown that logs to error.log, serializing the whole controller to dump.out, and a Restore that resumes from it via a Fixable factory.

What Part 1 adds to the skeleton

The starter GreenhouseControls hard-codes its schedule. Part 1 turns it into a real, fault-tolerant program by adding six things, each a topic from earlier modules made concrete.

### 1. Parameterized events The starter Bell rings once. Part 1 makes it ring rings times — and the event files declare it: Event=Bell,time=9000,rings=5 (see examples2.txt). So Bell gains a second constructor argument and a loop in action():

public class Bell extends Event {
    private int rings;
    public Bell(long delayTime, int rings) {
        super(delayTime);
        this.rings = rings;
    }
    public void action() {
        for (int i = 0; i < rings; i++) System.out.println("Bing!");
    }
}

examples2.txt also introduces FansOn / FansOff — proving the framework extends by *adding an inner Event subclass*, never by editing the controller.

### 2. Parse the event file with Scanner + regex Each line looks like Event=LightOn,time=2000 (optionally ,rings=5). You read the file with a Scanner and pull the fields with a capturing regex (Module 4): a group for the event name, a group for the time, an optional group for rings. The captured name string is what later (Part 2) feeds reflection.

Pattern p = Pattern.compile("Event=(\\w+),time=(\\d+)(?:,rings=(\\d+))?");
Matcher m = p.matcher(line);
if (m.matches()) {
    String name = m.group(1);
    long time = Long.parseLong(m.group(2));
    // m.group(3) is null when ,rings= is absent
}

### 3. A custom checked exception A fault — a stuck window, a power cut — is a *recoverable* condition the caller must handle, so it is a checked exception (extends Exception, Module 3):

public class ControllerException extends Exception {
    public ControllerException(String why) { super(why); }
}

The new fault events throw it: WindowMalfunction and PowerOut (added in examples3.txt / examples4.txt) throw new ControllerException(...) from action().

### 4. Orderly shutdown that logs When run() catches a ControllerException, it does not crash — it calls shutdown(), which records the failure to error.log (append mode + a timestamp, Module 8) and then exits cleanly. This is the *fault* half of the project.

### 5. Serialize the whole controller GreenhouseControls is made Serializable, so on certain faults the program can write its entire object graph — controller, event list, current state — to dump.out with an ObjectOutputStream (Module 8). The clock-related fields are marked transient (absolute times are meaningless after a reload).

### 6. Restore from the dump Run with -d dump.out and a Restore path deserializes that file with an ObjectInputStream, calls start() on each surviving event to re-base its time onto *now*, and resumes the run() loop — the program picks up where it crashed.

The Fixable factory ties it together Faults map to fixes through an interface used as a factory (Module 2.3). A Fixable declares fix() and log(); a getFixable(int errorcode) method returns the right Fixable for each error code — so adding a new fault is adding a case, not rewriting the recovery logic:

public interface Fixable {
    void fix();
    void log();
}

How it runs java GreenhouseControls -f examples3.txt parses the file into events, runs them in time order, and when WindowMalfunction fires it throws ControllerException; run() catches it, shutdown() logs to error.log and serializes to dump.out; later java GreenhouseControls -d dump.out restores and continues.

NORMAL ~/memra/learn/comp-308/part-1-recap utf-8 LF