Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/* *##% Nuiton Java-2-R library
* Copyright (C) 2006 - 2009 CodeLutin
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 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 Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* . ##%*/
/* *
* RNetEngine.java
*
* Created: 22 aout 06
*
* @author Arnaud Thimel
*/
package org.nuiton.j2r.net;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuiton.j2r.REngine;
import org.nuiton.j2r.REngineAbstract;
import org.nuiton.j2r.RException;
import org.nuiton.j2r.RInstructions;
import org.nuiton.j2r.types.RDataFrame;
import org.rosuda.REngine.REXP;
import org.rosuda.REngine.REXPMismatchException;
import org.nuiton.j2r.types.RList;
import org.rosuda.REngine.Rserve.RConnection;
import org.rosuda.REngine.Rserve.RserveException;
/**
* This class represents the network engine to access R. By default, it tries to
* connect on address 127.0.0.1 and port 6311. Meanwhile, it is possible to
* parametrize it.
*
* You only need to replace the launch option -DR.type=net by
* -DR.type=net://192.168.99.122:6312 where 192.168.99.122 is the
* distant machine adress and 6312 the port on which the server is running.
*/
public class RNetEngine extends REngineAbstract implements REngine {
public static final int DEFAULT_PORT = 6311;
public static final String DEFAULT_HOST = "127.0.0.1";
private Log log = LogFactory.getLog(RNetEngine.class);
private RConnection conn;
/**
* If true, commit each R instruction on the fly, if false, commit only when
* the commit() method is called.
*/
private Boolean autocommit = true;
/**
* List used to store all the R instructions when not in autocommit mode
* (when autocommit == false).
*/
private List rInstructions = new LinkedList();
/**
* Initialize the engine.
*
* @see org.nuiton.j2r.REngine#init()
*/
@Override
public boolean init() {
String typeProp = System.getProperty("R.type", "net");
int urlPos = typeProp.indexOf("net://");
String host = null;
String portAsString = null;
if (urlPos != -1) {
String url = typeProp.substring(urlPos + 6);
int commaPos = url.indexOf(':');
if (commaPos != -1) {
host = url.substring(0, commaPos);
portAsString = url.substring(commaPos + 1);
} else {
host = url;
}
}
if (host == null || "".equals(host)) {
host = DEFAULT_HOST;
}
int port = DEFAULT_PORT;
if (portAsString != null) {
try {
port = Integer.parseInt(portAsString);
} catch (NumberFormatException nfe) {
if (log.isWarnEnabled()) {
log.warn("Bad port format " + portAsString +
", using default" + " port : " + port);
}
}
}
return init(host, port);
}
/**
* Method to initialize the connection with specified host and port.
*
* @param host Adress of the Rserve instance
* @param port Port on which the Rserve instance is listening.
*
* @return true if initialized false otherwise.
*/
public boolean init(String host, int port) {
if (log.isInfoEnabled()) {
log.info("Trying to connect to the Rserve on '" + host + ":" + port +
"'");
}
try {
conn = new RConnection(host, port);
} catch (RserveException eee) {
log.error("Unable to establish a connection to the R server. " +
"Maybe you forgot to start it. " +
"Try using the command \"R CMD Rserve\".", eee);
return false;
}
return conn.isConnected();
}
/**
* Method to send a R instruction to the engine and get back the result.
*
* @param expr the R expression to evaluate.
*
* @return the result of the R expression.
*
* @throws org.nuiton.j2r.RException if an error occur while evaluating the
* R expression.
*
* @see org.nuiton.j2r.REngine#eval(java.lang.String)
*/
@Override
public Object eval(String expr) throws RException {
REXP result = null;
try {
//Encapsulate the R expression to get back the R error message
//if thrown.
if (log.isDebugEnabled()) {
log.debug(String.format(RInstructions.RTRY, expr));
}
result = conn.eval(String.format(RInstructions.RTRY, expr));
if (result.inherits(RInstructions.CLASS_ERROR)) {
//If the R expression is an error, throw an expression with the
//real R error message
throw new RException(result.asString());
}
} catch (RserveException rse) {
//If a communication error occur.
throw new RException(
"An error occured while eval on net",
rse);
} catch (REXPMismatchException rme) {
//If the error message cannot be read.
throw new RException("Cannot read error message from R :", rme);
}
return convertResult(result);
}
/**
* Method to convert a R expression to Java.
*
* @param rexp the R expression to convert.
*
* @return the resulting Java object.
*/
private Object convertResult(REXP rexp) {
if (rexp == null) {
//if rexp is null, avoid the tests on its type.
if (log.isDebugEnabled()) {
log.debug("Null returned");
}
return null;
}
if (log.isDebugEnabled()) {
log.debug("Converting : " + rexp.toString());
}
Object result = null;
try {
if (rexp.isInteger()) {
//true if rexp is an integer or an integer array.
//get rexp as an integer array
int[] array = rexp.asIntegers();
Integer[] bigArray = new Integer[array.length];
for (int i = 0; i < array.length; i++) {
bigArray[i] = (Integer) array[i];
}
result = bigArray;
//if the size of the array is 1, then return the integer alone.
//else return the integer array.
if (array.length == 1) {
result = (Integer) array[0];
}
} else if (rexp.isFactor()) {
//if rexp is a factor, return it as a RFactor.
result = rexp.asFactor();
} else if (rexp.isNumeric()) {
//true if rexp is a double or a double array.
//get rexp as a double array
double[] doublearray = rexp.asDoubles();
Double[] bigDoubleArray = new Double[doublearray.length];
for (int i = 0; i < doublearray.length; i++) {
bigDoubleArray[i] = (Double) doublearray[i];
}
result = bigDoubleArray;
//if the size of the array is 1, then return the double alone.
//else return the double array.
if (doublearray.length == 1) {
result = (Double) doublearray[0];
}
} else if (rexp.isString()) {
//true if rexp is a string or a string array.
//get rexp as a string array
result = rexp.asStrings();
String[] stringArray = (String[]) result;
//if the size of the array is 1, then return the string alone.
//else return the string array.
if (stringArray.length == 1) {
result = stringArray[0];
}
} else if (rexp.isLogical()) {
//true if rexp is a boolean or a boolean array.
//get rexp as a string array (there is no method for booleans)
result = rexp.asStrings();
String[] strings = ((String[]) result);
//create a boolean array of the same length
Boolean[] booleanArray = new Boolean[strings.length];
//parse each string into boolean and out it into the array.
for (int i = 0; i < ((String[]) result).length; i++) {
booleanArray[i] = Boolean.parseBoolean(strings[i]);
}
if (booleanArray.length == 1) {
result = booleanArray[0];
} else {
result = booleanArray;
}
} else if (rexp.isNull()) {
//if rexp contains a null R expression
return null;
} else if (rexp.inherits(RInstructions.CLASS_DATAFRAME)) {
//if rexp is a data.frame
RDataFrame temp = new RDataFrame((REngine) this);
//create the data list.
List> data =
new ArrayList>();
//get rexp as a list (data.frame is a list of vectors)
org.rosuda.REngine.RList dataList = rexp.asList();
for (int i = 0; i < dataList.size(); i++) {
//for each vector, create a list and fill it with the
//content of the vector.
List