package com.timgroup.tucker.info;

import java.util.Optional;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;

public abstract class Component {
    private final String id;
    private final String label;
    private final Runbook runbook;
    
    public Component(String id, String label) {
        this(id, label, null);
    }

    public Component(String id, String label, Runbook defaultRunbook) {
        this.id = id;
        this.label = label;
        this.runbook = defaultRunbook;
    }
    
    public final String getId() {
        return id;
    }
    
    public final String getLabel() {
        return label;
    }
    
    public Optional<Runbook> getRunbook() {
        return Optional.ofNullable(runbook);
    }

    public boolean hasRunbook() {
        return runbook != null;
    }

    public abstract Report getReport();

    public Component mapReport(UnaryOperator<Report> operator) {
        return new Component(id, label, runbook) {
            @Override
            public Report getReport() {
                return operator.apply(Component.this.getReport());
            }

            @Override
            public String toString() {
                return Component.this.toString();
            }
        };
    }

    public Component mapValue(UnaryOperator<Object> operator) {
        return mapReport(r -> r.mapValue(operator));
    }

    public Component mapStatus(UnaryOperator<Status> operator) { return mapReport(r -> r.mapStatus(operator)); }

    public Component withStatusNoWorseThan(Status notWorse) { return mapReport(r -> r.withStatusNoWorseThan(notWorse)); }

    public static Component supplyReport(String id, String label, Supplier<Report> supplier) {
        return new Component(id, label) {
            @Override
            public Report getReport() {
                return supplier.get();
            }

            @Override
            public String toString() {
                return getId() + ":" + supplier;
            }
        };
    }

    public static Component supplyInfo(String id, String label, Supplier<String> supplier) {
        return new Component(id, label) {
            @Override
            public Report getReport() {
                return new Report(Status.INFO, supplier.get());
            }

            @Override
            public String toString() {
                return getId() + ":info:" + supplier;
            }
        };
    }
}

@@ -28,16 +28,63 @@
 .info;%0A%0A
+import java.net.URI;%0Aimport java.util.Objects;%0A
 import j
@@ -1312,32 +1312,552 @@
       %7D;%0A    %7D%0A%0A
+    public Component withRunbook(Runbook runbook) %7B%0A        return new Component(id, label, Objects.requireNonNull(runbook)) %7B%0A            @Override%0A            public Report getReport() %7B%0A                return Component.this.getReport();%0A            %7D%0A%0A            @Override%0A            public String toString() %7B%0A                return Component.this.toString();%0A            %7D%0A        %7D;%0A    %7D%0A%0A    public Component withRunbook(URI runbookUri) %7B%0A        return withRunbook(new Runbook(runbookUri.toString()));%0A    %7D%0A%0A
     public Compo

Add methods to wrap component with runbook