/* * Copyright 2014 DataGenerator Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.finra.datagenerator.consumer; import org.apache.log4j.Logger; import org.finra.datagenerator.reporting.ReportingHandler; import org.finra.datagenerator.writer.DataWriter; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.URL; import java.net.URLConnection; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicBoolean; /** * Processes search results produced by a SearchDistributor. */ public class DataConsumer { private static final Logger log = Logger.getLogger(DataConsumer.class); private DataPipe dataPipe; private final List<DataTransformer> dataTransformers = new ArrayList<>(); private final List<DataWriter> dataWriters = new ArrayList<>(); private AtomicBoolean hardExitFlag; private long maxNumberOfLines = 10000; private String reportingHost; private final ExecutorService threadPool = Executors.newFixedThreadPool(1); /** * Public default constructor */ public DataConsumer() { this.dataPipe = new DataPipe(this); } /** * Adds a data transformer to the end of the data transformers list * * @param dc a reference to a DataTransformer * @return a reference to the current DataConsumer */ public DataConsumer addDataTransformer(DataTransformer dc) { dataTransformers.add(dc); return this; } /** * Adds a DataWriter to the end of the dataWriters list * * @param ow a reference to a data writer * @return a reference to the current DataConsumer */ public DataConsumer addDataWriter(DataWriter ow) { this.dataWriters.add(ow); return this; } /** * A setter for the reporting host * * @param reportingHost a String containing the URL of the reporting host * @return a reference to the current DataConsumer */ public DataConsumer setReportingHost(String reportingHost) { this.reportingHost = reportingHost; return this; } /** * A setter for maxNumberOfLines * * @param maxNumberOfLines the max number of lines * @return a reference to the current DataConsumer */ public DataConsumer setMaxNumberOfLines(long maxNumberOfLines) { this.maxNumberOfLines = maxNumberOfLines; return this; } /** * Setter for exit flag * * @param flag a reference to an AtomicBoolean * @return a reference to the current DataConsumer */ public DataConsumer setExitFlag(AtomicBoolean flag) { hardExitFlag = flag; return this; } public AtomicBoolean getExitFlag() { return hardExitFlag; } public long getMaxNumberOfLines() { return this.maxNumberOfLines; } public String getReportingHost() { return this.reportingHost; } public DataPipe getDataPipe() { return this.dataPipe; } /** * Consumes a produced result. Calls every transformer in sequence, then * calls every dataWriter in sequence. * * @param initialVars a map containing the initial variables assignments * @return the number of lines written */ public int consume(Map<String, String> initialVars) { this.dataPipe = new DataPipe(this); // Set initial variables for (Map.Entry<String, String> ent : initialVars.entrySet()) { dataPipe.getDataMap().put(ent.getKey(), ent.getValue()); } // Call transformers for (DataTransformer dc : dataTransformers) { dc.transform(dataPipe); } // Call writers for (DataWriter oneOw : dataWriters) { try { oneOw.writeOutput(dataPipe); } catch (Exception e) { //NOPMD log.error("Exception in DataWriter", e); } } return 1; } /** * Consumes a produced result. Calls every transformer in sequence, then * returns the produced result(s) back to the caller * * Children may override this class to produce more than one consumed result * * @param initialVars a map containing the initial variables assignments * @return the produced output map */ public List<Map<String, String>> transformAndReturn(Map<String, String> initialVars) { this.dataPipe = new DataPipe(this); // Set initial variables for (Map.Entry<String, String> ent : initialVars.entrySet()) { dataPipe.getDataMap().put(ent.getKey(), ent.getValue()); } // Call transformers for (DataTransformer dc : dataTransformers) { dc.transform(dataPipe); } List<Map<String, String>> result = new LinkedList<>(); result.add(dataPipe.getDataMap()); return result; } /** * Creates a future for sending a request to the reporting host and ignoring * the response. * * @param path the path at the reporting host where the request should be * sent * @return a {@link java.util.concurrent.Future} that wraps this activity */ public Future<String> sendRequest(final String path) { return sendRequest(path, null); } /** * Creates a future that will send a request to the reporting host and call * the handler with the response * * @param path the path at the reporting host which the request will be made * @param reportingHandler the handler to receive the response once executed * and recieved * @return a {@link java.util.concurrent.Future} for handing the request */ public Future<String> sendRequest(final String path, final ReportingHandler reportingHandler) { return threadPool.submit(new Callable<String>() { @Override public String call() { String response = getResponse(path); if (reportingHandler != null) { reportingHandler.handleResponse(response); } return response; } }); } /** * Sends a synchronous request to the reporting host returning the response * * @param path the path inside the reporting host to send the request to * @return a String containing the response */ public String sendRequestSync(String path) { return getResponse(path); } private String getResponse(String path) { StringBuilder content = new StringBuilder(); try { URL url = new URL("http://" + reportingHost + "/" + path); URLConnection urlConnection = url.openConnection(); try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()))) { String line; while ((line = bufferedReader.readLine()) != null) { content.append(line).append("\n"); } } } catch (IOException e) { log.error("Error while reading: " + path + " from " + reportingHost); } return content.toString(); } }