package com.timgroup.tucker.info.status;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import com.timgroup.tucker.info.Status;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.timgroup.tucker.info.Component;
import com.timgroup.tucker.info.Report;
import com.timgroup.tucker.info.component.VersionComponent;

public class StatusPageGenerator {
    
    public static final String DTD_FILENAME = "status-page.dtd";
    public static final String CSS_FILENAME = "status-page.css";

    public static final String COMPONENT_STATUS_FORMAT = "{\"eventType\": \"ComponentStatus\", "
            +" \"event\": {\"id\": \"{}\", \"label\": \"{}\", \"status\": \"{}\", \"value\": \"{}\"}}";

    private static final Logger LOGGER = LoggerFactory.getLogger(StatusPageGenerator.class);
    
    private final String applicationId;
    private final VersionComponent versionComponent;
    private final List<Component> components = new ArrayList<Component>();
    
    public StatusPageGenerator(String applicationId, VersionComponent versionComponent) {
        this.applicationId = applicationId;
        this.versionComponent = versionComponent;
        components.add(versionComponent);
    }
    
    public synchronized void addComponent(Component component) {
        components.add(component);
    }
    
    public StatusPage getApplicationReport() {
        List<Component> snapshot = componentsSnapshot();
        Map<Component, Report> componentReports = new LinkedHashMap<Component, Report>(snapshot.size());
        for (Component component : snapshot) {
            Report report;
            try {
                report = component.getReport();
            } catch (Throwable e) {
                LOGGER.error("exception getting report from component {}", component.getId(), e);
                report = new Report(e);
            }

            if (Status.CRITICAL.equals(report.getStatus()) || Status.WARNING.equals(report.getStatus())) {
                LOGGER.info(COMPONENT_STATUS_FORMAT, component.getId(), component.getLabel(), report.getStatus(), report.getValue());
            }

            componentReports.put(component, report);
        }
        return new StatusPage(applicationId, componentReports);
    }

    public Component getVersionComponent() {
        return versionComponent;
    }

    private synchronized List<Component> componentsSnapshot() {
        return new ArrayList<Component>(components);
    }
}

@@ -39,36 +39,8 @@
 s;%0A%0A
-import java.util.ArrayList;%0A
 impo
@@ -67,16 +67,16 @@
 ashMap;%0A
+
 import j
@@ -111,16 +111,66 @@
 til.Map;
+%0Aimport java.util.concurrent.CopyOnWriteArrayList;
 %0A%0Aimport
@@ -1016,24 +1016,35 @@
 nents = new 
+CopyOnWrite
 ArrayList%3CCo
@@ -1308,29 +1308,16 @@
  public 
-synchronized 
 void add
@@ -1446,65 +1446,8 @@
 ) %7B%0A
-        List%3CComponent%3E snapshot = componentsSnapshot();%0A
     
@@ -1529,24 +1529,26 @@
 Report%3E(
-snapshot
+components
 .size())
@@ -1588,16 +1588,18 @@
 t : 
-snapshot
+components
 ) %7B%0A
@@ -2311,24 +2311,24 @@
 mponent() %7B%0A
+
         retu
@@ -2357,131 +2357,7 @@
    %7D
-%0A%0A    private synchronized List%3CComponent%3E componentsSnapshot() %7B%0A        return new ArrayList%3CComponent%3E(components);%0A    %7D
 %0A%7D%0A

Use CopyOnWriteArrayList rather than manually synchronizing/snapshotting components list