All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apacheextras.camel.examples.rcode.builder.RCodeRouteBuilder Maven / Gradle / Ivy

The newest version!
/**
 * ************************************************************************************
 * http://code.google.com/a/apache-extras.org/p/camel-extra
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 51
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * http://www.gnu.org/licenses/gpl-2.0-standalone.html
 **************************************************************************************
 */
package org.apacheextras.camel.examples.rcode.builder;

import org.apache.camel.Exchange;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.dataformat.csv.CsvDataFormat;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.apache.camel.Processor;
import org.apache.camel.model.dataformat.JsonLibrary;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.CharEncoding;
import org.apacheextras.camel.examples.rcode.bean.MonthlySalesFigureCalculator;
import org.apacheextras.camel.examples.rcode.types.ForecastDocument;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Contains all routes to integrate R with Camel.
 */
public class RCodeRouteBuilder extends RouteBuilder {

  /**
   * Logger provides some degree of debugging information.
   */
  private final static Logger LOGGER = LoggerFactory.getLogger(RCodeRouteBuilder.class);
  /**
   * Map contains all the R code which has been loaded via external files.
   */
  private final static Map R_CODE_SOURCES = new HashMap();

  static {
    R_CODE_SOURCES.put("FN_PLOT_HOLT_WINTERS_FORECAST", sourceRCodeSources("fn_PlotHoltWintersForecast.R"));
    R_CODE_SOURCES.put("CMD_LIBRARIES", sourceRCodeSources("cmd_Libraries.R"));
    R_CODE_SOURCES.put("CMD_TIME_SERIES", sourceRCodeSources("cmd_TimeSeries.R"));
    R_CODE_SOURCES.put("CMD_DEVICE", sourceRCodeSources("cmd_Device.R"));
    R_CODE_SOURCES.put("CMD_PLOT", sourceRCodeSources("cmd_Plot.R"));
    R_CODE_SOURCES.put("CMD_BINARY", sourceRCodeSources("cmd_Binary.R"));
  }
  /**
   * Source file containing the data to be forecasted.
   */
  private final File source;
  /**
   * Target directory the result will be written to.
   */
  private final File target;
  /**
   * Camel endpoint where the CSV result will be written to.
   */
  private static final String DIRECT_CSV_SINK_URI = "direct://csv_sink";
  /**
   * Camel endpoint that starts the R-Code processing.
   */
  private static final String DIRECT_RCODE_SOURCE_URI = "direct://rcode_source";
  /**
   * Camel endpoint that starts writing the output as binary file.
   */
  private static final String DIRECT_GRAPH_FILE_SOURCE_URI = "seda://graph_file_source";
  /**
   * Camel endpoint that writes the result as JSON formated file.
   */
  private static final String DIRECT_GRAPH_JSON_SOURCE_URI = "seda://graph_json_source";

  /**
   * Creates the routes by taking a source and a target file.
   *
   * @param source directory to read the CSV
   * @param target directory to write the JPEG
   */
  public RCodeRouteBuilder(File source, File target) {
    this.source = source;
    this.target = target;
  }

  /**
   * Reads the R code sources based on the given source path within the class
   * path. Returns the result as String that can be further used within the
   * route.
   *
   * @param rCodeSource - String value of of the resource within the class
   * loader
   * @return read sources as String value
   */
  private static String sourceRCodeSources(String rCodeSource) {
    LOGGER.debug("Try to source the following R Code snipped: {}", rCodeSource);
    // Sourcing the external file and read the UTF-8 encoded String
    try {
      InputStream inputStream = RCodeRouteBuilder.class.getResourceAsStream(rCodeSource);
      // Return the R code sources
      return IOUtils.toString(inputStream, CharEncoding.UTF_8);
    } catch (IOException ex) {
      LOGGER.error("Could not copy InputStream on to StringWriter: {}", ex);
      return null;
    }
  }

  /**
   * {@inheritDoc}
   * 

* Configures all routes required for the RCode demo. *

* * @throws java.lang.Exception */ @Override public void configure() throws Exception { configureCsvRoute(); configureRCodeRoute(); configureGraphFileRoute(); configureGraphJsonRoute(); wireRoutes(); } /** * Takes an input as bytes and writes it as JSON formatted file. */ private void configureGraphJsonRoute() { from(DIRECT_GRAPH_JSON_SOURCE_URI) .convertBodyTo(ForecastDocument.class) .setHeader(Exchange.FILE_NAME, simple("graph${exchangeId}.json")) .process(new Processor() { @Override public void process(Exchange exchng) throws Exception { ForecastDocument document = exchng.getIn().getBody(ForecastDocument.class); document.setTitle("Holt-Winters Forecast: " + exchng.getIn().getHeader(Exchange.FILE_NAME)); document.setDate(new Date()); document.setPath(target.getAbsolutePath() + '/' + exchng.getIn().getHeader(Exchange.FILE_NAME)); } }) .marshal().json(JsonLibrary.Gson) .to("file://" + target.getAbsolutePath()) .log("Generated JSON file: '${header.CamelFileNameProduced}'") .end(); } /** * Takes an input as bytes and writes it as an JPEG file. */ private void configureGraphFileRoute() { from(DIRECT_GRAPH_FILE_SOURCE_URI) .setHeader(Exchange.FILE_NAME, simple("graph${exchangeId}.jpeg")) .to("file://" + target.getAbsolutePath()) .log("Generated graph file: '${header.CamelFileNameProduced}'") .end(); } /** * Takes an incoming string argument containing monthly quantities and * generates an output graph. */ private void configureRCodeRoute() { from(DIRECT_RCODE_SOURCE_URI) // Create the R Command via simple language and String concatenation .setBody(simple(R_CODE_SOURCES.get("CMD_LIBRARIES") + "\n" + R_CODE_SOURCES.get("FN_PLOT_HOLT_WINTERS_FORECAST") + "\n" + "sales <- c(${body});\n" + R_CODE_SOURCES.get("CMD_TIME_SERIES") + "\n" + R_CODE_SOURCES.get("CMD_DEVICE") + "\n" + R_CODE_SOURCES.get("CMD_PLOT") + "\n" + R_CODE_SOURCES.get("CMD_BINARY") + "\n")) // Logs the R command in debug mode // Send the R command to Rserve .to("rcode://localhost:6311/parse_and_eval?bufferSize=4194304") // Convert the generated JPEG as bytes to byte code .setBody(simple("${body.asBytes}")) .end(); } /** * Configures a CSV route that reads the quantity values from the route and * sends the result to the RCode route. */ private void configureCsvRoute() { // Configure CSV data format with ';' as separator and skipping of the header final CsvDataFormat csv = new CsvDataFormat(); csv.setDelimiter(';'); csv.setSkipHeaderRecord(true); from("file://" + source.getPath() + "?noop=TRUE") .unmarshal(csv) // Call the processor to calculate the daily figures into monthly results .bean(MonthlySalesFigureCalculator.class) .to(DIRECT_CSV_SINK_URI) .end(); } /** * Wires the routes together. */ private void wireRoutes() { from(DIRECT_CSV_SINK_URI) .to(DIRECT_RCODE_SOURCE_URI) .multicast() .to(DIRECT_GRAPH_FILE_SOURCE_URI, DIRECT_GRAPH_JSON_SOURCE_URI) .end(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy