/*
 * Copyright (c) 2016, Groupon, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 *
 * Neither the name of GROUPON nor the names of its contributors may be
 * used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package com.groupon.lex.metrics;

import com.groupon.lex.metrics.api.ApiServer;
import com.groupon.lex.metrics.config.Configuration;
import com.groupon.lex.metrics.config.ConfigurationException;
import com.groupon.lex.metrics.history.CollectHistory;
import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.util.List;
import lombok.NonNull;

public class PipelineBuilder {
    @NonNull
    private final Configuration cfg_;
    private int api_port_ = 9998;
    private CollectHistory history_;
    private int interval_ = 60;

    public PipelineBuilder(Configuration cfg) {
        cfg_ = cfg;
    }

    public PipelineBuilder(File dir, Reader reader) throws IOException, ConfigurationException {
        cfg_ = Configuration.readFromFile(dir, reader).resolve();
    }

    public PipelineBuilder(File file) throws IOException, ConfigurationException {
        cfg_ = Configuration.readFromFile(file).resolve();
    }

    public PipelineBuilder withApiPort(int api_port) {
        if (api_port <= 0 || api_port >= 65536) throw new IllegalArgumentException("port must be a valid TCP port");
        api_port_ = api_port;
        return this;
    }

    public PipelineBuilder withHistory(CollectHistory history) {
        history_ = history;
        return this;
    }

    public PipelineBuilder withCollectIntervalSeconds(int seconds) {
        if (seconds <= 0) throw new IllegalArgumentException("not enough seconds: " + seconds);
        interval_ = seconds;
        return this;
    }

    public PushProcessorPipeline build(List<PushProcessor> processor) {
        final ApiServer api = new ApiServer(api_port_);
        final PushMetricRegistryInstance registry = cfg_.create(api);
        if (history_ != null)
            registry.setHistory(history_);
        return new PushProcessorPipeline(registry, interval_, processor);
    }
}

@@ -1794,16 +1794,75 @@
 istory;%0A
+import com.groupon.lex.metrics.httpd.EndpointRegistration;%0A
 import j
@@ -1874,16 +1874,16 @@
 o.File;%0A
-
 import j
@@ -1921,24 +1921,52 @@
 .io.Reader;%0A
+import java.util.ArrayList;%0A
 import java.
@@ -2031,16 +2031,154 @@
 ilder %7B%0A
+    public static interface PushProcessorSupplier %7B%0A        public PushProcessor build(EndpointRegistration epr) throws Exception;%0A    %7D%0A%0A
     @Non
@@ -3348,16 +3348,24 @@
 rocessor
+Supplier
 %3E proces
@@ -3371,35 +3371,238 @@
 ssor
-) %7B%0A        final ApiServer
+_suppliers) throws Exception %7B%0A        ApiServer api = null;%0A        PushMetricRegistryInstance registry = null;%0A        final List%3CPushProcessor%3E processors = new ArrayList%3C%3E(processor_suppliers.size());%0A        try %7B%0A           
  api
@@ -3626,24 +3626,28 @@
 api_port_);%0A
+    
         fina
@@ -3647,39 +3647,121 @@
    f
-inal PushMetricRegistryInstance
+or (PushProcessorSupplier pps : processor_suppliers)%0A                processors.add(pps.build(api));%0A%0A           
  reg
@@ -3786,16 +3786,20 @@
 e(api);%0A
+    
         
@@ -3824,32 +3824,36 @@
 ll)%0A            
+    
 registry.setHist
@@ -3863,24 +3863,28 @@
 (history_);%0A
+    
         retu
@@ -3942,19 +3942,255 @@
 rocessor
+s
 );%0A
+        %7D catch (Exception ex) %7B%0A            if (api != null) api.close();%0A            if (registry != null) registry.close();%0A            for (PushProcessor pp : processors)%0A                pp.close();%0A            throw ex;%0A        %7D%0A
     %7D%0A%7D%0A

Implement a pipeline builder.