Author: jcouteau Date: 2009-07-26 19:11:04 +0200 (Sun, 26 Jul 2009) New Revision: 115 Added: trunk/src/main/java/org/nuiton/j2r/types/REXPAbstract.java Modified: trunk/src/main/java/org/nuiton/j2r/types/RDataFrame.java trunk/src/main/java/org/nuiton/j2r/types/RList.java Log: Adding an REXPAbstract to avoid duplicate code Modified: trunk/src/main/java/org/nuiton/j2r/types/RDataFrame.java =================================================================== --- trunk/src/main/java/org/nuiton/j2r/types/RDataFrame.java 2009-07-26 14:21:18 UTC (rev 114) +++ trunk/src/main/java/org/nuiton/j2r/types/RDataFrame.java 2009-07-26 17:11:04 UTC (rev 115) @@ -14,7 +14,6 @@ * You should have received a copy of the GNU General Lesser Public * License along with this program. If not, see * <http://www.gnu.org/licenses/lgpl-3.0.html>. ##%*/ - package org.nuiton.j2r.types; import java.io.BufferedReader; @@ -26,15 +25,13 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nuiton.j2r.REngine; import org.nuiton.j2r.RException; -public class RDataFrame implements REXP { +public class RDataFrame extends REXPAbstract implements REXP { private Log log = LogFactory.getLog(RDataFrame.class); @@ -44,11 +41,6 @@ private List<String> rowNames; //Vector containing the vectors of the data.frame private List<List<? extends Object>> data; - //Name of the data.frame in R, default = a - private String variable; - //Attributes of the data.frame under a map -> name : R expression - private Map<String, Object> attributes; - private REngine engine; public RDataFrame(REngine engine) throws RException { super(); @@ -133,8 +125,8 @@ if (engine.isAutoCommit()) { //Get back the names from R. - String[] namesArray = (String[]) engine.eval("names(" - + this.variable + ")"); + String[] namesArray = (String[]) engine.eval("names(" + + this.variable + ")"); //Check if size is correct, if yes, modify local data. if (namesArray.length <= this.data.size()) { @@ -146,10 +138,10 @@ } else { //if size is not correct, throw a RException. throw new IndexOutOfBoundsException( - "Data inconsistency, local data is smaller (size : " - + this.data.size() - + ") than the names ArrayList in R (size : " - + namesArray.length + ")"); + "Data inconsistency, local data is smaller (size : " + + this.data.size() + + ") than the names ArrayList in R (size : " + + namesArray.length + ")"); } } else { return this.names; @@ -178,8 +170,8 @@ if (x < names.size()) { if (engine.isAutoCommit()) { //Get back the names from R. - String name = (String) engine.eval("names(" + this.variable - + ")[" + (x + 1) + "]"); + String name = (String) engine.eval("names(" + this.variable + + ")[" + (x + 1) + "]"); //Check if the String is returned. if ((name != null) && (!name.equals(""))) { @@ -224,10 +216,10 @@ } else { //if size is not correct, throw a IndexOutOfBoundsException. throw new IndexOutOfBoundsException( - "Cannot assign the names attribute, the names List is too long.\nThe size of names (" - + names.size() - + ") must be shorter or equal to the data.frame length(" - + data.size() + ")."); + "Cannot assign the names attribute, the names List is too long.\nThe size of names (" + + names.size() + + ") must be shorter or equal to the data.frame length(" + + data.size() + ")."); } } @@ -250,16 +242,16 @@ names.set(x, name); //create the r instruction (names(var)[x]<-"name") - String rexp = "names(" + this.variable + ")[" + (x + 1) + "]<-\"" - + name + "\""; + String rexp = "names(" + this.variable + ")[" + (x + 1) + "]<-\"" + + name + "\""; //Send the R instruction to the engine. engine.voidEval(rexp); } else { //if index is out of bounds, throw a IndexOutOfBOundsException throw new IndexOutOfBoundsException( - "Cannot assign the name, the index is out of bounds.\nIndex :" - + x + "; data.frame size : " + data.size() + "."); + "Cannot assign the name, the index is out of bounds.\nIndex :" + + x + "; data.frame size : " + data.size() + "."); } } @@ -278,8 +270,8 @@ IndexOutOfBoundsException { if (engine.isAutoCommit()) { //Get back the names from R. - String[] rowNamesArray = (String[]) engine.eval("row.names(" - + this.variable + ")"); + String[] rowNamesArray = (String[]) engine.eval("row.names(" + + this.variable + ")"); //Check if size is correct, if yes, modify local data. if (rowNamesArray.length <= this.data.get(0).size()) { @@ -291,11 +283,10 @@ } else { //if size is not correct, throw a RException. throw new IndexOutOfBoundsException( - "Data inconsistency, local data is smaller (size : " - + this.data.get(0).size() - + ") than the names ArrayList in R (size : " - + rowNamesArray.length - + ").\nYou may want to force an update"); + "Data inconsistency, local data is smaller (size : " + this.data.get(0). + size() + ") than the names ArrayList in R (size : " + + rowNamesArray.length + + ").\nYou may want to force an update"); } } else { return this.rowNames; @@ -319,8 +310,8 @@ if (y < names.size()) { if (engine.isAutoCommit()) { //Get back the names from R. - String name = (String) engine.eval("row.names(" + this.variable - + ")[" + (y + 1) + "]"); + String name = (String) engine.eval( + "row.names(" + this.variable + ")[" + (y + 1) + "]"); //Check if the String is returned. if ((name != null) && (!name.equals(""))) { @@ -367,10 +358,10 @@ } else { //if size is not correct, throw a RException. throw new IndexOutOfBoundsException( - "Cannot assign the names attribute, the ArrayList is too long.\nThe size of names (" - + rowNames.size() - + ") must be shorter or equal to the data.frame length(" - + data.get(0).size() + ")."); + "Cannot assign the names attribute, the ArrayList is too long.\nThe size of names (" + + rowNames.size() + + ") must be shorter or equal to the data.frame length(" + data.get(0). + size() + ")."); } } @@ -393,16 +384,16 @@ rowNames.set(x, rowName); //create the r instruction (row.names(var)[x]<-"rowName") - String rexp = "row.names(" + this.variable + ")[" + (x + 1) - + "]<-\"" + rowName + "\""; + String rexp = "row.names(" + this.variable + ")[" + (x + 1) + + "]<-\"" + rowName + "\""; //Send the R instruction to the engine. engine.voidEval(rexp); } else { //if index is out of bounds, throw a RException throw new IndexOutOfBoundsException( - "Cannot assign the name, the index is out of bounds.\nIndex :" - + x + "; data.frame size : " + data.size() + "."); + "Cannot assign the name, the index is out of bounds.\nIndex :" + + x + "; data.frame size : " + data.size() + "."); } } @@ -442,6 +433,7 @@ * @throws RException * If no variable name is given */ + @Override public String toRString() throws RException { if ((this.variable.equals("")) || (this.variable == null)) { throw new RException( @@ -470,8 +462,8 @@ } } else if (data.get(i).get(0) instanceof Integer) { for (int j = 0; j < data.get(i).size(); j++) { - returnString += "as.integer(" + data.get(i).get(j) - + "),"; + returnString += "as.integer(" + data.get(i).get(j) + + "),"; } } else { for (int j = 0; j < data.get(i).size(); j++) { @@ -489,8 +481,9 @@ for (int i = 0; i < rowNames.size(); i++) { returnString += "\"" + rowNames.get(i) + "\","; } - returnString = returnString.substring(0, returnString.length() - 1) - + "),stringsAsFactors=FALSE)"; + returnString = + returnString.substring(0, returnString.length() - 1) + + "),stringsAsFactors=FALSE)"; } else if (this.data.isEmpty()) { returnString += ")"; @@ -524,17 +517,17 @@ "Cannot propage modification in R, no variable name given"); } if (x >= this.data.size()) { - throw new IndexOutOfBoundsException("The x value is too high : " - + x + ">=" + this.data.size()); + throw new IndexOutOfBoundsException("The x value is too high : " + x + + ">=" + this.data.size()); } if (y >= this.data.get(0).size()) { - throw new IndexOutOfBoundsException("The y value is too high : " - + y + ">=" + this.data.get(0).size()); + throw new IndexOutOfBoundsException("The y value is too high : " + y + + ">=" + this.data.get(0).size()); } if (this.data.get(x).get(y) instanceof Double) { ((ArrayList<Double>) this.data.get(x)).set(y, data); - engine.voidEval(this.variable + "[" + (y + 1) + "," + (x + 1) - + "]<-" + data); + engine.voidEval(this.variable + "[" + (y + 1) + "," + (x + 1) + + "]<-" + data); } else { throw new ArrayStoreException( "The data.frame does not accept doubles on those coordinates"); @@ -564,21 +557,21 @@ "Cannot propage modification in R, no variable name given"); } if (x >= this.data.size()) { - throw new IndexOutOfBoundsException("The x value is too high : " - + x + ">=" + this.data.size()); + throw new IndexOutOfBoundsException("The x value is too high : " + x + + ">=" + this.data.size()); } if (y >= this.data.get(0).size()) { - throw new IndexOutOfBoundsException("The y value is too high : " - + y + ">=" + this.data.get(0).size()); + throw new IndexOutOfBoundsException("The y value is too high : " + y + + ">=" + this.data.get(0).size()); } if (this.data.get(x).get(y) instanceof Boolean) { ((ArrayList<Boolean>) this.data.get(x)).set(y, data); if (data) { - engine.voidEval(this.variable + "[" + (y + 1) + "," + (x + 1) - + "]<-TRUE"); + engine.voidEval(this.variable + "[" + (y + 1) + "," + (x + 1) + + "]<-TRUE"); } else { - engine.voidEval(this.variable + "[" + (y + 1) + "," + (x + 1) - + "]<-FALSE"); + engine.voidEval(this.variable + "[" + (y + 1) + "," + (x + 1) + + "]<-FALSE"); } engine.voidEval(""); } else { @@ -609,17 +602,17 @@ "Cannot propage modification in R, no variable name given"); } if (x >= this.data.size()) { - throw new IndexOutOfBoundsException("The x value is too high : " - + x + ">=" + this.data.size()); + throw new IndexOutOfBoundsException("The x value is too high : " + x + + ">=" + this.data.size()); } if (y >= this.data.get(0).size()) { - throw new IndexOutOfBoundsException("The y value is too high : " - + y + ">=" + this.data.get(0).size()); + throw new IndexOutOfBoundsException("The y value is too high : " + y + + ">=" + this.data.get(0).size()); } if (this.data.get(x).get(y) instanceof String) { ((ArrayList<String>) this.data.get(x)).set(y, data); - engine.voidEval(this.variable + "[" + (y + 1) + "," + (x + 1) - + "]<-\"" + data + "\""); + engine.voidEval(this.variable + "[" + (y + 1) + "," + (x + 1) + + "]<-\"" + data + "\""); } else { throw new ArrayStoreException( "The data.frame does not accept booleans on those coordinates"); @@ -648,17 +641,17 @@ "Cannot propage modification in R, no variable name given"); } if (x >= this.data.size()) { - throw new IndexOutOfBoundsException("The x value is too high : " - + x + ">=" + this.data.size()); + throw new IndexOutOfBoundsException("The x value is too high : " + x + + ">=" + this.data.size()); } if (y >= this.data.get(0).size()) { - throw new IndexOutOfBoundsException("The y value is too high : " - + y + ">=" + this.data.get(0).size()); + throw new IndexOutOfBoundsException("The y value is too high : " + y + + ">=" + this.data.get(0).size()); } if (this.data.get(x).get(y) instanceof Integer) { ((ArrayList<Integer>) this.data.get(x)).set(y, data); - engine.voidEval(this.variable + "[" + (y + 1) + "," + (x + 1) - + "]<-as.integer(" + data + ")"); + engine.voidEval(this.variable + "[" + (y + 1) + "," + (x + 1) + + "]<-as.integer(" + data + ")"); engine.voidEval(""); } else { throw new ArrayStoreException( @@ -682,16 +675,16 @@ public Object get(int x, int y) throws RException, IndexOutOfBoundsException { if (x >= this.data.size()) { - throw new IndexOutOfBoundsException("The x value is too high : " - + x + ">=" + this.data.size()); + throw new IndexOutOfBoundsException("The x value is too high : " + x + + ">=" + this.data.size()); } if (y >= this.data.get(0).size()) { - throw new IndexOutOfBoundsException("The y value is too high : " - + y + ">=" + this.data.get(0).size()); + throw new IndexOutOfBoundsException("The y value is too high : " + y + + ">=" + this.data.get(0).size()); } if (engine.isAutoCommit()) { - Object returnObject = engine.eval(this.variable + "[" + (y + 1) - + "," + (x + 1) + "]"); + Object returnObject = engine.eval(this.variable + "[" + (y + 1) + + "," + (x + 1) + "]"); if (returnObject instanceof String) { ((ArrayList<String>) this.data.get(x)).set(y, (String) returnObject); @@ -730,15 +723,6 @@ } /** - * Method to get the data.frame variable name. - * - * @return the data.frame variable name. - */ - public String getVariable() { - return this.variable; - } - - /** * Method to get the ArrayLists of the R data.frame (there is no * synchronizing with R, use the update() method to synchronize data with R * before using this method if you think data may have changed. @@ -774,6 +758,7 @@ * a REngine where the R session is located. * @throws RException */ + @Override public void getFrom(String variable) throws RException { this.variable = variable; if (engine.isAutoCommit()) { @@ -799,216 +784,50 @@ } //update row names - String[] rowNamesArray = (String[]) engine.eval("row.names(" - + this.variable + ")"); + String[] rowNamesArray = (String[]) engine.eval("row.names(" + + this.variable + ")"); for (int i = 0; i < rowNamesArray.length; i++) { rowNames.add(rowNamesArray[i]); } //update names - String[] namesArray = (String[]) engine.eval("names(" - + this.variable + ")"); + String[] namesArray = (String[]) engine.eval("names(" + + this.variable + ")"); for (int i = 0; i < namesArray.length; i++) { names.add(namesArray[i]); } //update data - Integer dataframelength = (Integer) engine.eval("length(" - + this.variable + ")"); + Integer dataframelength = (Integer) engine.eval("length(" + + this.variable + ")"); for (int i = 0; i < dataframelength; i++) { - Integer arrayListLength = (Integer) engine.eval("length(" - + this.variable + "[," + (i + 1) + "])"); - ArrayList<Serializable> thisColumn = new ArrayList<Serializable>(); + Integer arrayListLength = (Integer) engine.eval("length(" + + this.variable + "[," + (i + 1) + "])"); + ArrayList<Serializable> thisColumn = + new ArrayList<Serializable>(); for (int j = 0; j < arrayListLength; j++) { - thisColumn.add((Serializable) engine.eval(this.variable - + "[" + (j + 1) + "," + (i + 1) + "]")); + thisColumn.add((Serializable) engine.eval(this.variable + + "[" + (j + 1) + "," + (i + 1) + "]")); } data.add(thisColumn); } //update attributes - Integer attributeslength = (Integer) engine - .eval("length(attributes(" + this.variable + "))"); + Integer attributeslength = (Integer) engine.eval( + "length(attributes(" + this.variable + "))"); for (int i = 0; i < attributeslength; i++) { - String key = (String) engine.eval("names(attributes(" - + this.variable + "))[" + (i + 1) + "]"); + String key = (String) engine.eval("names(attributes(" + + this.variable + "))[" + (i + 1) + "]"); - String attribute = (String) engine.eval("toString(attributes(" - + this.variable + ")$" + key + ")"); + String attribute = (String) engine.eval("toString(attributes(" + + this.variable + ")$" + key + ")"); attributes.put(key, attribute); } } } - /** - * Method to set all the attributes of the data.frame (there is no - * synchronizing with R, use the commit() method to send data to R. - * - * @param attributes - * a Map containing the attributes (key) and values (value) - */ - public void setAttributes(Map<String, Object> attributes) throws RException { - this.attributes = attributes; - - Set<String> keyset = attributes.keySet(); - String[] keys = keyset.toArray(new String[0]); - for (int i = 0; i < keys.length; i++) { - if (this.attributes.get(keys[i]) instanceof String) { - engine.eval("attr(" + this.variable + ",\"" + keys[i] - + "\")<-\"" + this.attributes.get(keys[i]) + "\""); - } else if (this.attributes.get(keys[i]) instanceof Double) { - engine.eval("attr(" + this.variable + ",\"" + keys[i] + "\")<-" - + this.attributes.get(keys[i]) + ""); - } else if (this.attributes.get(keys[i]) instanceof Integer) { - engine.eval("attr(" + this.variable + ",\"" + keys[i] - + "\")<-as.integer(" + this.attributes.get(keys[i]) - + ")"); - } else if (this.attributes.get(keys[i]) instanceof Boolean) { - if ((Boolean) this.attributes.get(keys[i])) { - engine.eval("attr(" + this.variable + ",\"" + keys[i] - + "\")<-TRUE"); - } else { - engine.eval("attr(" + this.variable + ",\"" + keys[i] - + "\")<-FALSE"); - } - } else if (this.attributes.get(keys[i]) instanceof REXP) { - engine.eval("attr(" + this.variable + ",\"" + keys[i] + "\")<-" - + ((REXP) this.attributes.get(keys[i])).toRString()); - } else { - log.warn("This attribute is not valid : " + keys[i] + " ; " - + this.attributes.get(keys[i]) - + ". It will not be sent to R"); - } - } - } - - /** - * Method to get all the attributes of the data.frame (there is no - * synchronizing with R, use the update() method to synchronize data with R - * before using this method if you think data may have changed. - * - * @return a Map containing the attributes (key) and values (value) - */ - public Map<String, Object> getAttributes() throws RException { - - if (engine.isAutoCommit()) { - Integer attributeslength = (Integer) engine - .eval("length(attributes(" + this.variable + "))"); - - for (int i = 0; i < attributeslength; i++) { - String key = (String) engine.eval("names(attributes(" - + this.variable + "))[" + (i + 1) + "]"); - - Object attribute = engine.eval("attributes(" + this.variable - + ")$" + key); - if (attributes.containsKey(key)) { - attributes.remove(key); - attributes.put(key, attribute); - } else { - attributes.put(key, attribute); - } - } - } - return this.attributes; - } - - /** - * Method to get the value of an attribute (there is no synchronizing with - * R, use the update() method to synchronize data with R before using this - * method if you think data may have changed. - * - * @param attribute - * name of the attribute - * @return - */ - public Object getAttribute(String attribute) throws RException { - if (engine.isAutoCommit()) { - Object returnedAttribute = engine.eval("attr(" + this.variable - + ",\"" + attribute + "\")"); - if (returnedAttribute != null) { - if (attributes.containsKey(attribute)) { - attributes.remove(attribute); - attributes.put(attribute, returnedAttribute); - } else { - attributes.put(attribute, returnedAttribute); - } - } else { - throw new RException("Attribute does not exist"); - } - } - return attributes.get(attribute); - } - - /** - * Method to set the value of an attribute (there is no synchronizing with - * R, use the commit() method to send data to R. - * - * @param attribute - * name of the attribute - * @param value - * the value to be set (this is a R expression, String may be - * rounded with escaped quote like : \"this is a R string\" ). - */ - public void setAttribute(String attribute, Object value) throws RException { - if (value instanceof String) { - if (attributes.containsKey(attribute)) { - attributes.remove(attribute); - attributes.put(attribute, value); - } else { - attributes.put(attribute, value); - } - engine.voidEval("attr(" + this.variable + ",\"" + attribute - + "\")<-\"" + value + "\""); - } else if (value instanceof Double) { - if (attributes.containsKey(attribute)) { - attributes.remove(attribute); - attributes.put(attribute, value); - } else { - attributes.put(attribute, value); - } - engine.voidEval("attr(" + this.variable + ",\"" + attribute - + "\")<-" + value); - } else if (value instanceof Integer) { - if (attributes.containsKey(attribute)) { - attributes.remove(attribute); - attributes.put(attribute, value); - } else { - attributes.put(attribute, value); - } - engine.voidEval("attr(" + this.variable + ",\"" + attribute - + "\")<-as.integer(" + value + ")"); - } else if (value instanceof Boolean) { - if (attributes.containsKey(attribute)) { - attributes.remove(attribute); - attributes.put(attribute, value); - } else { - attributes.put(attribute, value); - } - if ((Boolean) value) { - engine.voidEval("attr(" + this.variable + ",\"" + attribute - + "\")<-TRUE"); - } else { - engine.voidEval("attr(" + this.variable + ",\"" + attribute - + "\")<-FALSE"); - } - } else if (value instanceof REXP) { - if (attributes.containsKey(attribute)) { - attributes.remove(attribute); - attributes.put(attribute, value); - } else { - attributes.put(attribute, value); - } - engine.voidEval("attr(" + this.variable + ",\"" + attribute - + "\")<-" + ((REXP) value).toRString()); - } else { - log.warn("This attribute is not valid : " + attribute + " ; " - + value + ". It will not be processed"); - } - - } - public void exportCsv(File outputFile, boolean rowNames, boolean names) { try { BufferedWriter file = new BufferedWriter(new FileWriter(outputFile)); @@ -1083,7 +902,8 @@ } } - List<List<? extends Object>> tempData = new ArrayList<List<? extends Object>>(); + List<List<? extends Object>> tempData = + new ArrayList<List<? extends Object>>(); for (int i = 0; i < dataSize; i++) { List<Object> column = new ArrayList<Object>(); @@ -1098,8 +918,8 @@ index = 1; } for (int i = 0 + index; i < splitted.length; i++) { - ((ArrayList<Object>) tempData.get(i - index)) - .add((Object) splitted[i]); + ((ArrayList<Object>) tempData.get(i - index)).add( + (Object) splitted[i]); } } br.close(); @@ -1158,7 +978,8 @@ } } - List<List<? extends Object>> tempData = new ArrayList<List<? extends Object>>(); + List<List<? extends Object>> tempData = + new ArrayList<List<? extends Object>>(); for (int i = 0; i < dataSize; i++) { List<Object> column = new ArrayList<Object>(); @@ -1174,14 +995,14 @@ } for (int i = 0 + index; i < splitted.length; i++) { if (importType instanceof String) { - ((ArrayList<Object>) tempData.get(i - index)) - .add((Object) splitted[i]); + ((ArrayList<Object>) tempData.get(i - index)).add( + (Object) splitted[i]); } else if (importType instanceof Double) { - ((ArrayList<Object>) tempData.get(i - index)) - .add(Double.valueOf(splitted[i])); + ((ArrayList<Object>) tempData.get(i - index)).add(Double. + valueOf(splitted[i])); } else if (importType instanceof Integer) { - ((ArrayList<Object>) tempData.get(i - index)) - .add(Integer.valueOf(splitted[i])); + ((ArrayList<Object>) tempData.get(i - index)).add(Integer. + valueOf(splitted[i])); } } } @@ -1243,7 +1064,8 @@ } } - List<List<? extends Object>> tempData = new ArrayList<List<? extends Object>>(); + List<List<? extends Object>> tempData = + new ArrayList<List<? extends Object>>(); for (int i = 0; i < dataSize; i++) { List<Object> column = new ArrayList<Object>(); @@ -1259,14 +1081,14 @@ } for (int i = 0 + index; i < splitted.length; i++) { if (importTypes.get(i - index) instanceof String) { - ((ArrayList<Object>) tempData.get(i - index)) - .add((Serializable) splitted[i]); + ((ArrayList<Object>) tempData.get(i - index)).add( + (Serializable) splitted[i]); } else if (importTypes.get(i - index) instanceof Double) { - ((ArrayList<Object>) tempData.get(i - index)) - .add(Double.valueOf(splitted[i])); + ((ArrayList<Object>) tempData.get(i - index)).add(Double. + valueOf(splitted[i])); } else if (importTypes.get(i - index) instanceof Integer) { - ((ArrayList<Object>) tempData.get(i - index)) - .add(Integer.valueOf(splitted[i])); + ((ArrayList<Object>) tempData.get(i - index)).add(Integer. + valueOf(splitted[i])); } } } @@ -1276,5 +1098,4 @@ e.printStackTrace(); } } - } Added: trunk/src/main/java/org/nuiton/j2r/types/REXPAbstract.java =================================================================== --- trunk/src/main/java/org/nuiton/j2r/types/REXPAbstract.java (rev 0) +++ trunk/src/main/java/org/nuiton/j2r/types/REXPAbstract.java 2009-07-26 17:11:04 UTC (rev 115) @@ -0,0 +1,224 @@ +/* *##% 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 + * <http://www.gnu.org/licenses/lgpl-3.0.html>. ##%*/ +package org.nuiton.j2r.types; + +import java.util.Map; +import java.util.Set; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.j2r.REngine; +import org.nuiton.j2r.RException; + +/** + * Abstract class for REXP interface, in order to avoid duplicate code for attributes related methods. + * + * @author couteau + */ +public class REXPAbstract implements REXP { + + protected Log log = LogFactory.getLog(REXPAbstract.class); + + //Name of the data.frame in R + protected String variable; + + //Attributes of the data.frame under a map -> name : R expression + protected Map<String, Object> attributes; + + //Engine used for R instructions. + protected REngine engine; + + /** + * Always need to be implemented by extending classes + * @return null + * @throws org.nuiton.j2r.RException + */ + @Override + public String toRString() throws RException { + return null; + } + + /** + * Always need to be implemented by extending classes. Do nothing. + * @param variable + * @throws org.nuiton.j2r.RException + */ + @Override + public void getFrom(String variable) throws RException { + } + + @Override + public void setAttributes(Map<String, Object> attributes) throws RException { + + this.attributes = attributes; + + + if ((this.attributes != null) && (!this.attributes.isEmpty())) { + Set<String> keyset = attributes.keySet(); + String[] keys = keyset.toArray(new String[0]); + for (int i = 0; i < keys.length; i++) { + if (this.attributes.get(keys[i]) instanceof String) { + engine.eval("attr(" + this.variable + ",\"" + keys[i] + + "\")<-\"" + this.attributes.get(keys[i]) + "\""); + } else if (this.attributes.get(keys[i]) instanceof Double) { + engine.eval("attr(" + this.variable + ",\"" + keys[i] + + "\")<-" + this.attributes.get(keys[i]) + ""); + } else if (this.attributes.get(keys[i]) instanceof Integer) { + engine.eval("attr(" + this.variable + ",\"" + keys[i] + + "\")<-as.integer(" + this.attributes.get(keys[i]) + + ")"); + } else if (this.attributes.get(keys[i]) instanceof Boolean) { + if ((Boolean) this.attributes.get(keys[i])) { + engine.eval("attr(" + this.variable + ",\"" + keys[i] + + "\")<-TRUE"); + } else { + engine.eval("attr(" + this.variable + ",\"" + keys[i] + + "\")<-FALSE"); + } + } else if (this.attributes.get(keys[i]) instanceof REXP) { + engine.eval("attr(" + this.variable + ",\"" + keys[i] + + "\")<-" + ((REXP) this.attributes.get(keys[i])). + toRString()); + } else { + log.warn("This attribute is not valid : " + keys[i] + " ; " + + this.attributes.get(keys[i]) + + ". It will not be sent to R"); + } + } + } + } + + @Override + public Map<String, Object> getAttributes() throws RException { + if (engine.isAutoCommit()) { + Integer attributeslength = (Integer) engine.eval( + "length(attributes(" + this.variable + "))"); + + for (int i = 0; i < attributeslength; i++) { + String key = (String) engine.eval("names(attributes(" + + this.variable + "))[" + (i + 1) + "]"); + + Object newAttribute = engine.eval( + "attributes(" + this.variable + ")$" + key); + if (attributes.containsKey(key)) { + attributes.remove(key); + attributes.put(key, newAttribute); + } else { + attributes.put(key, newAttribute); + } + } + } + return this.attributes; + } + + @Override + public Object getAttribute(String attribute) throws RException { + if (engine.isAutoCommit()) { + Object returnedAttribute; + if ((Boolean) engine.eval("is.data.frame(attr(" + this.variable + + ",\"" + attribute + "\"))")) { + returnedAttribute = new RDataFrame(engine); + ((RDataFrame) returnedAttribute).getFrom("attr(" + this.variable + + ",\"" + attribute + "\")"); + } else if ((Boolean) engine.eval("is.list(attr(" + this.variable + + ",\"" + attribute + "\"))")) { + returnedAttribute = new RList(engine); + ((RList) returnedAttribute).getFrom("attr(" + this.variable + + ",\"" + attribute + "\")"); + } else { + returnedAttribute = engine.eval( + "attr(" + this.variable + ",\"" + attribute + "\")"); + } + + if (returnedAttribute != null) { + if (attributes.containsKey(attribute)) { + attributes.remove(attribute); + attributes.put(attribute, returnedAttribute); + } else { + attributes.put(attribute, returnedAttribute); + } + } else { + throw new RException("Attribute does not exist"); + } + } else if (!attributes.containsKey(attribute)) { + throw new RException("Attribute does not exist"); + } + return attributes.get(attribute); + } + + @Override + public void setAttribute(String attribute, Object value) throws RException { + if (value instanceof String) { + if (attributes.containsKey(attribute)) { + attributes.remove(attribute); + attributes.put(attribute, value); + } else { + attributes.put(attribute, value); + } + engine.voidEval("attr(" + this.variable + ",\"" + attribute + + "\")<-\"" + value + "\""); + } else if (value instanceof Double) { + if (attributes.containsKey(attribute)) { + attributes.remove(attribute); + attributes.put(attribute, value); + } else { + attributes.put(attribute, value); + } + engine.voidEval("attr(" + this.variable + ",\"" + attribute + + "\")<-" + value); + } else if (value instanceof Integer) { + if (attributes.containsKey(attribute)) { + attributes.remove(attribute); + attributes.put(attribute, value); + } else { + attributes.put(attribute, value); + } + engine.voidEval("attr(" + this.variable + ",\"" + attribute + + "\")<-as.integer(" + value + ")"); + } else if (value instanceof Boolean) { + if (attributes.containsKey(attribute)) { + attributes.remove(attribute); + attributes.put(attribute, value); + } else { + attributes.put(attribute, value); + } + if ((Boolean) value) { + engine.voidEval("attr(" + this.variable + ",\"" + attribute + + "\")<-TRUE"); + } else { + engine.voidEval("attr(" + this.variable + ",\"" + attribute + + "\")<-FALSE"); + } + } else if (value instanceof REXP) { + if (attributes.containsKey(attribute)) { + attributes.remove(attribute); + attributes.put(attribute, value); + } else { + attributes.put(attribute, value); + } + engine.voidEval("attr(" + this.variable + ",\"" + attribute + + "\")<-" + ((REXP) value).toRString()); + } else { + log.warn("This attribute is not valid : " + attribute + " ; " + + value + ". It will not be processed"); + } + } + + @Override + public String getVariable() { + return this.variable; + } +} Modified: trunk/src/main/java/org/nuiton/j2r/types/RList.java =================================================================== --- trunk/src/main/java/org/nuiton/j2r/types/RList.java 2009-07-26 14:21:18 UTC (rev 114) +++ trunk/src/main/java/org/nuiton/j2r/types/RList.java 2009-07-26 17:11:04 UTC (rev 115) @@ -14,33 +14,23 @@ * You should have received a copy of the GNU General Lesser Public * License along with this program. If not, see * <http://www.gnu.org/licenses/lgpl-3.0.html>. ##%*/ - package org.nuiton.j2r.types; import java.util.ArrayList; import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nuiton.j2r.REngine; import org.nuiton.j2r.RException; -public class RList implements REXP { +public class RList extends REXPAbstract implements REXP { private Log log = LogFactory.getLog(RList.class); - private List<String> names; private List<Object> data; - //Name of the data.frame in R - private String variable; - //Attributes of the data.frame under a map -> name : R expression - private Map<String, Object> attributes; - private REngine engine; - public RList(REngine engine) { super(); this.names = new ArrayList<String>(); @@ -80,8 +70,8 @@ if (engine.isAutoCommit()) { //Get back the names from R. - String[] namesArray = (String[]) engine.eval("names(" - + this.variable + ")"); + String[] namesArray = (String[]) engine.eval("names(" + + this.variable + ")"); //Check if size is correct, if yes, modify local data. if (namesArray.length <= this.data.size()) { @@ -93,10 +83,9 @@ } else { //if size is not correct, throw a RException. throw new IndexOutOfBoundsException( - "Data inconsistency, local data is smaller (size : " - + this.data.size() - + ") than the names in R (size : " - + namesArray.length + ")"); + "Data inconsistency, local data is smaller (size : " + + this.data.size() + ") than the names in R (size : " + + namesArray.length + ")"); } } else { return this.names; @@ -125,8 +114,8 @@ if (x < names.size()) { if (engine.isAutoCommit()) { //Get back the names from R. - String name = (String) engine.eval("names(" + this.variable - + ")[" + (x + 1) + "]"); + String name = (String) engine.eval("names(" + this.variable + + ")[" + (x + 1) + "]"); //Check if the String is returned. if ((name != null) && (!name.equals(""))) { @@ -135,8 +124,8 @@ } } else { //if String is not returned, throw an IndexOutOfBOundsException. - throw new IndexOutOfBoundsException("Your index " + x - + " is not valid"); + throw new IndexOutOfBoundsException("Your index " + x + + " is not valid"); } return this.names.get(x); @@ -170,10 +159,10 @@ } else { //if size is not correct, throw a IndexOutOfBoundsException. throw new IndexOutOfBoundsException( - "Cannot assign the names attribute, the names List is too long.\nThe size of names (" - + names.size() - + ") must be shorter or equal to the list length(" - + data.size() + ")."); + "Cannot assign the names attribute, the names List is too long.\nThe size of names (" + + names.size() + + ") must be shorter or equal to the list length(" + + data.size() + ")."); } } @@ -210,16 +199,16 @@ } //create the r instruction (names(var)[x]<-"name") - String rexp = "names(" + this.variable + ")[" + (x + 1) + "]<-\"" - + name + "\""; + String rexp = "names(" + this.variable + ")[" + (x + 1) + "]<-\"" + + name + "\""; //Send the R instruction to the engine. engine.voidEval(rexp); } else { //if index is out of bounds, throw a IndexOutOfBOundsException throw new IndexOutOfBoundsException( - "Cannot assign the name, the index is out of bounds.\nIndex :" - + x + "; data.frame size : " + data.size() + "."); + "Cannot assign the name, the index is out of bounds.\nIndex :" + + x + "; data.frame size : " + data.size() + "."); } } @@ -273,16 +262,6 @@ } /** - * Method to get the list variable name. - * - * @return the list variable name. - */ - @Override - public String getVariable() { - return this.variable; - } - - /** * Method to export the list in a String for evaluation in R. * * @return a R string representation of the list to create it in R. @@ -430,9 +409,7 @@ } } - engine - .voidEval(this.variable + "[[" + (x + 1) + "]]<-\"" + data - + "\""); + engine.voidEval(this.variable + "[[" + (x + 1) + "]]<-\"" + data + "\""); } /** @@ -467,8 +444,8 @@ } } - engine.voidEval(this.variable + "[[" + (x + 1) + "]]<-as.integer(" - + data + ")"); + engine.voidEval(this.variable + "[[" + (x + 1) + "]]<-as.integer(" + + data + ")"); } /** @@ -502,8 +479,8 @@ } engine.voidEval(data.toRString()); - engine.voidEval(this.variable + "[[" + (x + 1) + "]]<-" - + data.getVariable()); + engine.voidEval(this.variable + "[[" + (x + 1) + "]]<-" + data. + getVariable()); } /** @@ -519,12 +496,12 @@ */ public Object get(int x) throws RException, IndexOutOfBoundsException { if (x >= this.data.size()) { - throw new IndexOutOfBoundsException("The x value is too high : " - + x + ">=" + this.data.size()); + throw new IndexOutOfBoundsException("The x value is too high : " + x + + ">=" + this.data.size()); } if (engine.isAutoCommit()) { - Object returnObject = engine.eval(this.variable + "[[" + (x + 1) - + "]]"); + Object returnObject = engine.eval(this.variable + "[[" + (x + 1) + + "]]"); if (returnObject instanceof String) { this.data.set(x, (String) returnObject); } else if (returnObject instanceof Double) { @@ -589,8 +566,8 @@ } //update names - String[] namesArray = (String[]) engine.eval("names(" + this.variable - + ")"); + String[] namesArray = (String[]) engine.eval("names(" + this.variable + + ")"); for (int i = 0; i < namesArray.length; i++) { names.add(namesArray[i]); } @@ -602,199 +579,16 @@ } //update attributes - Integer attributeslength = (Integer) engine.eval("length(attributes(" - + this.variable + "))"); + Integer attributeslength = (Integer) engine.eval("length(attributes(" + + this.variable + "))"); for (int i = 0; i < attributeslength; i++) { - String key = (String) engine.eval("names(attributes(" - + this.variable + "))[" + (i + 1) + "]"); + String key = (String) engine.eval("names(attributes(" + + this.variable + "))[" + (i + 1) + "]"); - Object attribute = engine.eval("attributes(" + this.variable + ")$" - + key); + Object attribute = engine.eval( + "attributes(" + this.variable + ")$" + key); attributes.put(key, attribute); } } - - /** - * Method to set all the attributes of the list - * - * @param attributes - * a Map containing the attributes (key) and values (value). - */ - @Override - public void setAttributes(Map<String, Object> attributes) throws RException { - this.attributes = attributes; - if ((this.attributes != null) && (!this.attributes.isEmpty())) { - String expr = "attributes(" + this.variable + ")<-list("; - - Set<String> keyset = attributes.keySet(); - String[] keys = keyset.toArray(new String[0]); - for (int i = 0; i < keys.length; i++) { - if (this.attributes.get(keys[i]) instanceof String) { - expr += keys[i] + "=\"" + this.attributes.get(keys[i]) - + "\","; - } else if (this.attributes.get(keys[i]) instanceof Double) { - expr += keys[i] + "=" + this.attributes.get(keys[i]) + ","; - } else if (this.attributes.get(keys[i]) instanceof Integer) { - expr += keys[i] + "=as.integer(" - + this.attributes.get(keys[i]) + "),"; - } else if (this.attributes.get(keys[i]) instanceof Boolean) { - if ((Boolean) this.attributes.get(keys[i])) { - expr += keys[i] + "=TRUE,"; - } else { - expr += keys[i] + "=FALSE,"; - } - } else if (this.attributes.get(keys[i]) instanceof REXP) { - expr += keys[i] + "=" - + ((REXP) this.attributes.get(keys[i])).toRString() - + "),"; - } else { - log.warn("This attribute is not valid : " + keys[i] + " ; " - + this.attributes.get(keys[i]) - + ". It will not be sent to R"); - } - } - - expr = expr.substring(0, expr.length() - 1) + ")"; - engine.voidEval(expr); - } - } - - /** - * Method to get all the attributes of the list - * - * @return a Map containing the attributes (key) and values (value) - */ - @Override - public Map<String, Object> getAttributes() throws RException { - - if (engine.isAutoCommit()) { - Integer attributeslength = (Integer) engine - .eval("length(attributes(" + this.variable + "))"); - - for (int i = 0; i < attributeslength; i++) { - String key = (String) engine.eval("names(attributes(" - + this.variable + "))[" + (i + 1) + "]"); - - Object attribute = engine.eval("attributes(" + this.variable - + ")$" + key); - if (attributes.containsKey(key)) { - attributes.remove(key); - attributes.put(key, attribute); - } else { - attributes.put(key, attribute); - } - } - } - return this.attributes; - } - - /** - * Method to get the value of an attribute - * - * @param attribute - * name of the attribute - * @return a String representing the attribute. - */ - @Override - public Object getAttribute(String attribute) throws RException { - if (engine.isAutoCommit()) { - Object returnedAttribute; - if ((Boolean) engine.eval("is.data.frame(attr(" + this.variable - + ",\"" + attribute + "\"))")) { - returnedAttribute = new RDataFrame(engine); - ((RDataFrame) returnedAttribute).getFrom("attr(" - + this.variable + ",\"" + attribute + "\")"); - } else if ((Boolean) engine.eval("is.list(attr(" + this.variable - + ",\"" + attribute + "\"))")) { - returnedAttribute = new RList(engine); - ((RList) returnedAttribute).getFrom("attr(" + this.variable - + ",\"" + attribute + "\")"); - } else { - returnedAttribute = engine.eval("attr(" + this.variable + ",\"" - + attribute + "\")"); - } - - if (returnedAttribute != null) { - if (attributes.containsKey(attribute)) { - attributes.remove(attribute); - attributes.put(attribute, returnedAttribute); - } else { - attributes.put(attribute, returnedAttribute); - } - } else { - throw new RException("Attribute does not exist"); - } - } else if (!attributes.containsKey(attribute)) { - throw new RException("Attribute does not exist"); - } - return attributes.get(attribute); - } - - /** - * Method to set the value of an attribute - * - * @param attribute - * name of the attribute - * @param value - * the value to be set. - */ - @Override - public void setAttribute(String attribute, Object value) throws RException { - if (value instanceof String) { - if (attributes.containsKey(attribute)) { - attributes.remove(attribute); - attributes.put(attribute, value); - } else { - attributes.put(attribute, value); - } - engine.voidEval("attr(" + this.variable + ",\"" + attribute - + "\")<-\"" + value + "\""); - } else if (value instanceof Double) { - if (attributes.containsKey(attribute)) { - attributes.remove(attribute); - attributes.put(attribute, value); - } else { - attributes.put(attribute, value); - } - engine.voidEval("attr(" + this.variable + ",\"" + attribute - + "\")<-" + value); - } else if (value instanceof Integer) { - if (attributes.containsKey(attribute)) { - attributes.remove(attribute); - attributes.put(attribute, value); - } else { - attributes.put(attribute, value); - } - engine.voidEval("attr(" + this.variable + ",\"" + attribute - + "\")<-as.integer(" + value + ")"); - } else if (value instanceof Boolean) { - if (attributes.containsKey(attribute)) { - attributes.remove(attribute); - attributes.put(attribute, value); - } else { - attributes.put(attribute, value); - } - if ((Boolean) value) { - engine.voidEval("attr(" + this.variable + ",\"" + attribute - + "\")<-TRUE"); - } else { - engine.voidEval("attr(" + this.variable + ",\"" + attribute - + "\")<-FALSE"); - } - } else if (value instanceof REXP) { - if (attributes.containsKey(attribute)) { - attributes.remove(attribute); - attributes.put(attribute, value); - } else { - attributes.put(attribute, value); - } - engine.voidEval("attr(" + this.variable + ",\"" + attribute - + "\")<-" + ((REXP) value).toRString()); - } else { - log.warn("This attribute is not valid : " + attribute + " ; " - + value + ". It will not be processed"); - } - - } }