edu.harvard.iq.dvn.ingest.dsb.impl.DvnRforeignFileConversionServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for edu.harvard.iq.dvn.ingest.dsb.impl.DvnRforeignFileConversionServiceImpl.java

Source

/*
   Copyright (C) 2005-2012, by the President and Fellows of Harvard College.
    
   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.
    
   Dataverse Network - A web application to share, preserve and analyze research data.
   Developed at the Institute for Quantitative Social Science, Harvard University.
   Version 3.0.
*/
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package edu.harvard.iq.dvn.ingest.dsb.impl;

import edu.harvard.iq.dvn.ingest.dsb.*;
import java.io.*;
import static java.lang.System.*;
import java.util.*;
import java.util.logging.*;
import java.lang.reflect.*;
import java.util.regex.*;

import org.rosuda.REngine.*;
import org.rosuda.REngine.Rserve.*;

import org.apache.commons.lang.*;
import org.apache.commons.lang.builder.*;

/**
 *
 * @author asone
 */

public class DvnRforeignFileConversionServiceImpl {

    // ----------------------------------------------------- static filelds

    private static Logger dbgLog = Logger
            .getLogger(DvnRforeignFileConversionServiceImpl.class.getPackage().getName());

    public static String DSB_TMP_DIR = null;

    private static String TMP_DATA_FILE_NAME = "susetfile4Rjob";
    public static String TMP_DATA_FILE_EXT = ".tab";
    private static String RSERVE_HOST = null;
    private static String RSERVE_USER = null;
    private static String RSERVE_PWD = null;
    private static int RSERVE_PORT;
    private static String DSB_HOST_PORT = null;
    public static String DSB_CTXT_DIR = null;

    private static Map<String, String> dwlndParam = new HashMap<String, String>();

    private static Map<String, Method> runMethods = new HashMap<String, Method>();

    private static String regexForRunMethods = "^run(\\w+)Request$";
    private static String RESULT_DIR_PREFIX = "Zlg_";

    public static String RWRKSP_FILE_PREFIX = "dvnDataFramefile_";

    public static String dtflprefix = "dvnDataFile_";

    public static String TEMP_DIR = System.getProperty("java.io.tmpdir");

    static {

        DSB_TMP_DIR = System.getProperty("vdc.dsb.temp.dir");

        if (DSB_TMP_DIR == null) {
            DSB_TMP_DIR = "/tmp/VDC/DSB";
        }

        RSERVE_HOST = System.getProperty("vdc.dsb.host");
        if (RSERVE_HOST == null) {
            //RSERVE_HOST= "dsb-2.hmdc.harvard.edu";
            RSERVE_HOST = "vdc-build.hmdc.harvard.edu";
        }

        DSB_HOST_PORT = System.getProperty("vdc.dsb.port");
        if (DSB_HOST_PORT == null) {
            DSB_HOST_PORT = "80";
        }

        RSERVE_USER = System.getProperty("vdc.dsb.rserve.user");
        if (RSERVE_USER == null) {
            RSERVE_USER = "rserve";
        }

        RSERVE_PWD = System.getProperty("vdc.dsb.rserve.pwrd");
        if (RSERVE_PWD == null) {
            RSERVE_PWD = "rserve";
        }

        if (System.getProperty("vdc.dsb.rserve.port") == null) {
            RSERVE_PORT = 6311;
        } else {
            RSERVE_PORT = Integer.parseInt(System.getProperty("vdc.dsb.rserve.port"));
        }

        // various constants: option-wise
        // download formats
        dwlndParam.put("D01", "dat");
        dwlndParam.put("D02", "ssc");
        dwlndParam.put("D03", "dta");
        dwlndParam.put("D04", "RData");

        Pattern p = Pattern.compile(regexForRunMethods);

        for (Method m : DvnRforeignFileConversionServiceImpl.class.getDeclaredMethods()) {

            Matcher mtr = p.matcher(m.getName());

            if (mtr.matches()) {
                runMethods.put(mtr.group(1), m);
            }
        }

    }

    static String VDC_R_STARTUP_FILE = "vdc_startup.R";
    static String librarySetup = "source(paste(.libPaths()[1], '/../share/dvn/" + VDC_R_STARTUP_FILE
            + "', sep = ''));";
    boolean DEBUG = true;

    // ----------------------------------------------------- instance filelds
    public String PID = null;
    public String tempFileName = null;
    public String tempFileNameNew = null;
    public String wrkdir = null;
    public String requestdir = null;
    public List<String> replicationFile = new LinkedList<String>();

    // ----------------------------------------------------- constructor
    public DvnRforeignFileConversionServiceImpl() {
        dbgLog.fine("***** DvnRforeignFileConversionServiceImpl: within the constructor starts here *****");
        // initialization
        PID = RandomStringUtils.randomNumeric(6);

        requestdir = "Zlg_" + PID;

        wrkdir = DSB_TMP_DIR + "/" + requestdir;

        tempFileName = DSB_TMP_DIR + "/" + TMP_DATA_FILE_NAME + "." + PID + TMP_DATA_FILE_EXT;

        tempFileNameNew = wrkdir + "/" + TMP_DATA_FILE_NAME + "." + PID + TMP_DATA_FILE_EXT;

        dbgLog.fine("requestdir=" + requestdir);
        dbgLog.fine("wrkdir=" + wrkdir);
        dbgLog.fine("tempFileName=" + tempFileName);
        dbgLog.fine("tempFileNameNew=" + tempFileNameNew);

    }

    public void setupWorkingDirectory(RConnection c) {
        try {
            // set up the working directory:

            String checkWrkDir = "if (!file_test('-d', '" + wrkdir + "')) {dir.create('" + wrkdir
                    + "', showWarnings = FALSE, recursive = TRUE);}";

            dbgLog.fine("w permission=" + checkWrkDir);
            c.voidEval(checkWrkDir);

        } catch (RserveException rse) {
            rse.printStackTrace();
        }
    }

    /** *************************************************************
     * Execute an R-based dvn statistical analysis request 
     *
     * @param sro    a DvnRJobRequest object that contains various parameters
     * @return    a Map that contains various information about results
     */

    public Map<String, String> execute(DvnRJobRequest sro) {
        dbgLog.fine("***** DvnRforeignFileConversionServiceImpl: execute() starts here *****");

        // set the return object
        Map<String, String> result = new HashMap<String, String>();
        // temporary result
        Map<String, String> tmpResult = new HashMap<String, String>();

        try {
            // Set up an Rserve connection
            dbgLog.fine("sro dump:\n" + ToStringBuilder.reflectionToString(sro, ToStringStyle.MULTI_LINE_STYLE));

            dbgLog.fine("RSERVE_USER=" + RSERVE_USER + "[default=rserve]");
            dbgLog.fine("RSERVE_PWD=" + RSERVE_PWD + "[default=rserve]");
            dbgLog.fine("RSERVE_PORT=" + RSERVE_PORT + "[default=6311]");

            RConnection c = new RConnection(RSERVE_HOST, RSERVE_PORT);
            dbgLog.fine("hostname=" + RSERVE_HOST);

            c.login(RSERVE_USER, RSERVE_PWD);
            dbgLog.fine(">" + c.eval("R.version$version.string").asString() + "<");

            // check working directories
            // This needs to be done *before* we try to create any files 
            // there!
            setupWorkingDirectory(c);

            // save the data file at the Rserve side
            String infile = sro.getSubsetFileName();
            InputStream inb = new BufferedInputStream(new FileInputStream(infile));

            int bufsize;
            byte[] bffr = new byte[1024];

            RFileOutputStream os = c.createFile(tempFileName);
            while ((bufsize = inb.read(bffr)) != -1) {
                os.write(bffr, 0, bufsize);
            }
            os.close();
            inb.close();

            // Rserve code starts here
            dbgLog.fine("wrkdir=" + wrkdir);
            c.voidEval(librarySetup);

            // variable type
            /* 
            vartyp <-c(1,1,1)
            */
            // java side
            // int [] jvartyp  = {1,1,1};// = mp.get("vartyp").toArray()
            // int [] jvartyp  = sro.getVariableTypes();
            /*
                        StringBuilder sb = new StringBuilder();
                        for (int i = 0 ; i< jvartyp.length; i++){
            if (i == (jvartyp.length -1)){
                sb.append(String.valueOf(jvartyp[i]));
            } else {
                sb.append(String.valueOf(jvartyp[i])+", ");
            }
                        }
                            
                        // R side
            */

            /*
             * Note that we want to use the "getVariableTypesWithBoolean method 
             * below; when we create a SRO object for analysis, in 
             * DvnRDataAnalysisServiceImpl, we'll still be using getVariableTypes
             * method, that don't recognize Booleans as a distinct class of 
             * variables. So those would be treated simply as numeric categoricals 
             * (factors) with the "TRUE" and "FALSE" labels. But for the purposes
             * of saving the subset in R format, we want to convert these into
             * R "logical" vectors.
             */

            dbgLog.fine("raw variable type=" + sro.getVariableTypesWithBoolean());
            c.assign("vartyp", new REXPInteger(sro.getVariableTypesWithBoolean()));
            String[] tmpt = c.eval("vartyp").asStrings();
            dbgLog.fine("vartyp length=" + tmpt.length + "\t " + StringUtils.join(tmpt, ","));

            // variable format (date/time)
            /* 
            varFmt<-list();
            c.voidEval("varFmt<-list()");
            */

            Map<String, String> tmpFmt = sro.getVariableFormats();
            dbgLog.fine("tmpFmt=" + tmpFmt);
            if (tmpFmt != null) {
                Set<String> vfkeys = tmpFmt.keySet();
                String[] tmpfk = (String[]) vfkeys.toArray(new String[vfkeys.size()]);
                String[] tmpfv = getValueSet(tmpFmt, tmpfk);
                c.assign("tmpfk", new REXPString(tmpfk));
                c.assign("tmpfv", new REXPString(tmpfv));
                String fmtNamesLine = "names(tmpfv)<- tmpfk";
                c.voidEval(fmtNamesLine);
                String fmtValuesLine = "varFmt<- as.list(tmpfv)";
                c.voidEval(fmtValuesLine);
            } else {
                String[] varFmtN = {};
                List<String> varFmtV = new ArrayList<String>();
                c.assign("varFmt", new REXPList(new RList(varFmtV, varFmtN)));
            }
            /*
            vnames<-c("race","age","vote")
            */

            // variable names
            // String [] jvnames = {"race","age","vote"};
            String[] jvnamesRaw = sro.getVariableNames();
            String[] jvnames = null;

            //VariableNameFilterForR nf = new VariableNameFilterForR(jvnamesRaw);

            if (sro.hasUnsafedVariableNames) {
                // create  list
                jvnames = sro.safeVarNames;
                dbgLog.fine("renamed=" + StringUtils.join(jvnames, ","));
            } else {
                jvnames = jvnamesRaw;
            }
            String vnQList = DvnDSButil.joinNelementsPerLine(jvnames, true);

            c.assign("vnames", new REXPString(jvnames));

            // confirmation
            String[] tmpjvnames = c.eval("vnames").asStrings();
            dbgLog.fine("vnames:" + StringUtils.join(tmpjvnames, ","));

            /*
            x<-read.table141vdc(file="/tmp/VDC/t.28948.1.tab", 
                col.names=vnames, colClassesx=vartyp, varFormat=varFmt)
            */

            //String datafilename = "/nfs/home/A/asone/java/rcode/t.28948.1.tab";

            // tab-delimited file name = tempFileName

            // Parameters:
            // file -> tempFileName
            // col.names -> Arrays.deepToString(new REXPString(jvnames)).asStrings())
            // colClassesx -> Arrays.deepToString((new REXPInteger(sro.getVariableTypes())).asStrings())
            // varFormat -> Arrays.deepToString((new REXPString(getValueSet(tmpFmt, tmpFmt.keySet().toArray(new String[tmpFmt.keySet().size()])))).asStrings())

            dbgLog.fine("<<<<<<<<<<<<<<<<<<<<<<<<<");
            dbgLog.fine("col.names = " + Arrays.deepToString((new REXPString(jvnames)).asStrings()));
            dbgLog.fine("colClassesx = "
                    + Arrays.deepToString((new REXPInteger(sro.getVariableTypesWithBoolean())).asStrings()));
            dbgLog.fine("varFormat = " + Arrays.deepToString((new REXPString(
                    getValueSet(tmpFmt, tmpFmt.keySet().toArray(new String[tmpFmt.keySet().size()]))))
                            .asStrings()));
            dbgLog.fine(">>>>>>>>>>>>>>>>>>>>>>>>>");

            String readtableline = "x<-read.table141vdc(file='" + tempFileName
                    + "', col.names=vnames, colClassesx=vartyp, varFormat=varFmt )";
            dbgLog.fine("readtable=" + readtableline);

            c.voidEval(readtableline);

            // safe-to-raw variable name
            /* 
              attr(x, "Rsafe2raw")<-list();
            */
            //if (nf.hasRenamedVariables()){
            if (sro.hasUnsafedVariableNames) {
                dbgLog.fine("unsafeVariableNames exist");
                // create  list
                //jvnames = nf.getFilteredVarNames();
                jvnames = sro.safeVarNames;
                String[] rawNameSet = sro.renamedVariableArray;
                String[] safeNameSet = sro.renamedResultArray;

                c.assign("tmpRN", new REXPString(rawNameSet));
                c.assign("tmpSN", new REXPString(safeNameSet));

                String raw2safevarNameTableLine = "names(tmpRN)<- tmpSN";
                c.voidEval(raw2safevarNameTableLine);
                String attrRsafe2rawLine = "attr(x, 'Rsafe2raw')<- as.list(tmpRN)";
                c.voidEval(attrRsafe2rawLine);
            } else {
                String attrRsafe2rawLine = "attr(x, 'Rsafe2raw')<-list();";
                c.voidEval(attrRsafe2rawLine);
            }

            //Map<String, String> Rsafe2raw = sro.getRaw2SafeVarNameTable();

            // asIs
            /* 
            for (i in 1:dim(x)[2]){if (attr(x,"var.type")[i] == 0) {
            x[[i]]<-I(x[[i]]);  x[[i]][ x[[i]] == '' ]<-NA  }}
            */
            String asIsline = "for (i in 1:dim(x)[2]){ " + "if (attr(x,'var.type')[i] == 0) {"
                    + "x[[i]]<-I(x[[i]]);  x[[i]][ x[[i]] == '' ]<-NA  }}";
            c.voidEval(asIsline);

            // replication: copy the data.frame
            String repDVN_Xdupline = "dvnData<-x";
            c.voidEval(repDVN_Xdupline);
            tmpResult.put("dvn_dataframe", "dvnData");

            // subsetting (mutating the data.frame strips non-default attributes 
            // 
            // variable type must be re-attached

            //String varTypeNew = "vartyp<-c(" + StringUtils.join( sro.getUpdatedVariableTypesAsString(),",")+")";
            // c.voidEval(varTypeNew);
            dbgLog.fine("updated var Type =" + sro.getUpdatedVariableTypes());
            c.assign("vartyp", new REXPInteger(sro.getUpdatedVariableTypes()));

            String reattachVarTypeLine = "attr(x, 'var.type') <- vartyp";
            c.voidEval(reattachVarTypeLine);

            // TODO: 
            // "getUpdatedVariableTypesWithBooleans" ?? -- L.A.

            // replication: variable type
            String repDVN_vt = "attr(dvnData, 'var.type') <- vartyp";
            c.voidEval(repDVN_vt);

            // variable Id
            /* 
            attr(x, "var.nmbr")<-c("v198057","v198059","v198060")
            */

            // String[] jvarnmbr = {"v198057","v198059","v198060"};
            //String[] jvarnmbr = sro.getVariableIds();
            // after recoding 
            String[] jvarnmbr = sro.getUpdatedVariableIds();

            String viQList = DvnDSButil.joinNelementsPerLine(jvarnmbr, true);
            c.assign("varnmbr", new REXPString(jvarnmbr));

            String attrVarNmbrLine = "attr(x, 'var.nmbr')<-varnmbr";
            c.voidEval(attrVarNmbrLine);

            // confirmation
            String[] vno = c.eval("attr(x, 'var.nmbr')").asStrings();
            dbgLog.fine("varNo=" + StringUtils.join(vno, ","));

            // replication: variable number
            String repDVN_vn = "attr(dvnData, 'var.nmbr') <- varnmbr";
            c.voidEval(repDVN_vn);

            // variable labels
            /* 
            attr(x, "var.labels")<-c("race","age","vote")
            */

            // String[] jvarlabels = {"race","age","vote"};
            // String[] jvarlabels = sro.getVariableLabels();
            // after recoding
            String[] jvarlabels = sro.getUpdatedVariableLabels();

            String vlQList = DvnDSButil.joinNelementsPerLine(jvarlabels, true);

            c.assign("varlabels", new REXPString(jvarlabels));

            String attrVarLabelsLine = "attr(x, 'var.labels')<-varlabels";
            c.voidEval(attrVarLabelsLine);

            // confirmation
            String[] vlbl = c.eval("attr(x, 'var.labels')").asStrings();
            dbgLog.fine("varlabels=" + StringUtils.join(vlbl, ","));

            // replication: 
            String repDVN_vl = "attr(dvnData, 'var.labels') <- varlabels";
            c.voidEval(repDVN_vl);

            // --------- start: block to be used for the production code
            // value-label table
            /* 
            VALTABLE<-list()
            VALTABLE[["1"]]<-list(
            "2"="white",
            "1"="others")
            attr(x, 'val.table')<-VALTABLE
            */

            // create the VALTABLE
            String vtFirstLine = "VALTABLE<-list()";
            c.voidEval(vtFirstLine);

            // vltbl includes both base and recoded cases when it was generated
            Map<String, Map<String, String>> vltbl = sro.getValueTable();
            Map<String, String> rnm2vi = sro.getRawVarNameToVarIdTable();
            String[] updatedVariableIds = sro.getUpdatedVariableIds();

            //for (int j=0;j<jvnamesRaw.length;j++){
            for (int j = 0; j < updatedVariableIds.length; j++) {
                // if this variable has its value-label table,
                // pass its key and value arrays to the Rserve
                // and finalize a value-table at the Rserve

                //String varId = rnm2vi.get(jvnamesRaw[j]);
                String varId = updatedVariableIds[j];

                if (vltbl.containsKey(varId)) {

                    Map<String, String> tmp = (HashMap<String, String>) vltbl.get(varId);
                    Set<String> vlkeys = tmp.keySet();
                    String[] tmpk = (String[]) vlkeys.toArray(new String[vlkeys.size()]);
                    String[] tmpv = getValueSet(tmp, tmpk);
                    // debug
                    dbgLog.fine("tmp:k=" + StringUtils.join(tmpk, ","));
                    dbgLog.fine("tmp:v=" + StringUtils.join(tmpv, ","));

                    // index number starts from 1(not 0)
                    int indx = j + 1;
                    dbgLog.fine("index=" + indx);

                    if (tmpv.length > 0) {

                        c.assign("tmpk", new REXPString(tmpk));

                        c.assign("tmpv", new REXPString(tmpv));

                        String namesValueLine = "names(tmpv)<- tmpk";
                        c.voidEval(namesValueLine);

                        String sbvl = "VALTABLE[['" + Integer.toString(indx) + "']]" + "<- as.list(tmpv)";
                        dbgLog.fine("frag=" + sbvl);
                        c.voidEval(sbvl);

                        // confirmation test for j-th variable name
                        REXP jl = c.parseAndEval(sbvl);
                        dbgLog.fine("jl(" + j + ") = " + jl);
                    }
                }
            }

            // debug: confirmation test for value-table
            dbgLog.fine("length of vl=" + c.eval("length(VALTABLE)").asInteger());
            String attrValTableLine = "attr(x, 'val.table')<-VALTABLE";
            c.voidEval(attrValTableLine);

            // replication: value-label table
            String repDVN_vlt = "attr(dvnData, 'val.table') <- VALTABLE";
            c.voidEval(repDVN_vlt);

            // --------- end: block to be used for the production code

            // missing-value list: TO DO
            /*
            MSVLTBL<-list(); attr(x, 'missval.table')<-MSVLTBL
            */
            String msvStartLine = "MSVLTBL<-list();";
            c.voidEval(msvStartLine);
            // data structure
            String attrMissvalLine = "attr(x, 'missval.table')<-MSVLTBL";
            c.voidEval(attrMissvalLine);

            // replication: missing value table
            String repDVN_mvlt = "attr(dvnData, 'missval.table') <- MSVLTBL";
            c.voidEval(repDVN_mvlt);

            // attach attributes(tables) to the data.frame
            /*
            x<-createvalindex(dtfrm=x, attrname='val.index')
            x<-createvalindex(dtfrm=x, attrname='missval.index')
            */
            String createVIndexLine = "x<-createvalindex(dtfrm=x, attrname='val.index');";
            c.voidEval(createVIndexLine);
            String createMVIndexLine = "x<-createvalindex(dtfrm=x, attrname='missval.index');";
            c.voidEval(createMVIndexLine);

            // reflection block: start ------------------------------------------>

            String requestTypeToken = sro.getRequestType();// (Download|EDA|Xtab|Zelig)
            dbgLog.fine("requestTypeToken=" + requestTypeToken);
            // get a test method
            Method mthd = runMethods.get(requestTypeToken);
            dbgLog.fine("method=" + mthd);

            try {
                // invoke this method
                result = (Map<String, String>) mthd.invoke(this, sro, c);
            } catch (InvocationTargetException e) {
                //Throwable cause = e.getCause();
                //err.format(cause.getMessage());
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }

            // add the variable list
            result.put("variableList", joinNelementsPerLine(jvnamesRaw, 5, null, false, null, null));

            //result.put("variableList",StringUtils.join(jvnamesRaw, ", "));

            // replication: var-level unf
            String repDVN_varUNF = "attr(dvnData, 'variableUNF') <- paste(unf(dvnData,version=3))";
            c.voidEval(repDVN_varUNF);

            // calculate the file-leve UNF

            String fileUNFline = "fileUNF <- paste(summary(unf(dvnData, version=3)))";
            c.voidEval(fileUNFline);
            String fileUNF = c.eval("fileUNF").asString();
            if (fileUNF == null) {
                fileUNF = "NA";
            }

            // replication: file-level unf
            String repDVN_fileUNF = "attr(dvnData, 'fileUNF') <- fileUNF";
            c.voidEval(repDVN_fileUNF);

            String RversionLine = "R.Version()$version.string";
            String Rversion = c.eval(RversionLine).asString();

            // replication: R version
            String repDVN_Rversion = "attr(dvnData, 'R.version') <- R.Version()$version.string";
            c.voidEval(repDVN_Rversion);

            String zeligVersionLine = "packageDescription('Zelig')$Version";
            String zeligVersion = c.eval(zeligVersionLine).asString();

            //String RexecDate = c.eval("date()").asString();
            String RexecDate = c.eval("as.character(as.POSIXct(Sys.time()))").asString();
            // replication: date
            String repDVN_date = "attr(dvnData, 'date') <- as.character(as.POSIXct(Sys.time()))";
            c.voidEval(repDVN_date);

            String repDVN_dfOrigin = "attr(dvnData, 'data.frame.origin')<- "
                    + "list('provider'='Dataverse Network Project',"
                    + "'format' = list('name' = 'DVN data.frame', 'version'='1.3'))";
            c.voidEval(repDVN_dfOrigin);
            /*
            if (result.containsKey("option")){
            result.put("R_run_status", "T");
            } else {
            result.put("option", requestTypeToken.toLowerCase()); //download  zelig eda xtab
            result.put("R_run_status", "F");
            }
            */
            if (sro.hasRecodedVariables()) {
                if (sro.getSubsetConditions() != null) {
                    result.put("subsettingCriteria", StringUtils.join(sro.getSubsetConditions(), "\n"));
                    // replication: subset lines
                    String[] sbst = null;
                    sbst = (String[]) sro.getSubsetConditions()
                            .toArray(new String[sro.getSubsetConditions().size()]);

                    c.assign("sbstLines", new REXPString(sbst));

                    String repDVN_sbst = "attr(dvnData, 'subsetLines') <- sbstLines";
                    c.voidEval(repDVN_sbst);
                }
                /* to be used in the future? */
                if (sro.getRecodeConditions() != null) {
                    result.put("recodingCriteria", StringUtils.join(sro.getRecodeConditions(), "\n"));
                    String[] rcd = null;
                    rcd = (String[]) sro.getRecodeConditions()
                            .toArray(new String[sro.getRecodeConditions().size()]);

                    c.assign("rcdtLines", new REXPString(rcd));

                    String repDVN_rcd = "attr(dvnData, 'recodeLines') <- rcdtLines";
                    c.voidEval(repDVN_rcd);
                }

            }

            // save workspace as a replication data set

            String RdataFileName = "DVNdataFrame." + PID + ".RData";
            result.put("Rdata", "/" + requestdir + "/" + RdataFileName);

            String saveWS = "save('dvnData', file='" + wrkdir + "/" + RdataFileName + "')";
            dbgLog.fine("save the workspace=" + saveWS);
            c.voidEval(saveWS);

            // write back the R workspace to the dvn 

            String wrkspFileName = wrkdir + "/" + RdataFileName;
            dbgLog.fine("wrkspFileName=" + wrkspFileName);

            int wrkspflSize = getFileSize(c, wrkspFileName);

            File wsfl = writeBackFileToDvn(c, wrkspFileName, RWRKSP_FILE_PREFIX, "RData", wrkspflSize);

            result.put("dvn_RData_FileName", wsfl.getName());

            if (wsfl != null) {
                result.put("wrkspFileName", wsfl.getAbsolutePath());
                dbgLog.fine("wrkspFileName=" + wsfl.getAbsolutePath());
            } else {
                dbgLog.fine("wrkspFileName is null");
            }

            result.put("library_1", "VDCutil");

            result.put("fileUNF", fileUNF);
            result.put("dsbHost", RSERVE_HOST);
            result.put("dsbPort", DSB_HOST_PORT);
            result.put("dsbContextRootDir", DSB_CTXT_DIR);
            result.put("PID", PID);
            result.put("Rversion", Rversion);
            result.put("zeligVersion", zeligVersion);
            result.put("RexecDate", RexecDate);

            result.putAll(tmpResult);
            dbgLog.fine("result object (before closing the Rserve):\n" + result);

            // reflection block: end

            // close the Rserve connection
            c.close();

        } catch (RserveException rse) {
            // RserveException (Rserve is not running)
            rse.printStackTrace();

            result.put("dsbContextRootDir", DSB_CTXT_DIR);
            result.put("PID", PID);
            result.put("option", sro.getRequestType().toLowerCase());

            result.put("RexecError", "true");
            return result;

        } catch (REXPMismatchException mme) {

            // REXP mismatch exception (what we got differs from what we expected)
            mme.printStackTrace();

            result.put("dsbContextRootDir", DSB_CTXT_DIR);
            result.put("PID", PID);
            result.put("option", sro.getRequestType().toLowerCase());

            result.put("RexecError", "true");
            return result;

        } catch (IOException ie) {
            ie.printStackTrace();

            result.put("dsbContextRootDir", DSB_CTXT_DIR);
            result.put("PID", PID);
            result.put("option", sro.getRequestType().toLowerCase());

            result.put("RexecError", "true");
            return result;

        } catch (Exception ex) {
            ex.printStackTrace();

            result.put("dsbContextRootDir", DSB_CTXT_DIR);
            result.put("PID", PID);

            result.put("option", sro.getRequestType().toLowerCase());

            result.put("RexecError", "true");
            return result;
        }

        return result;

    }

    // ----------------------------------------------------- utilitiy methods

    /**
     * Returns the array of values that corresponds the order of 
     * provided keys
     *
     * @param     
     * @return    
     */

    public static String[] getValueSet(Map<String, String> mp, String[] keys) {

        List<String> tmpvl = new ArrayList<String>();
        for (int i = 0; i < keys.length; i++) {
            tmpvl.add(mp.get(keys[i]));
        }
        String[] tmpv = (String[]) tmpvl.toArray(new String[tmpvl.size()]);
        return tmpv;
    }

    /** *************************************************************
     * Handles a downloading request 
     *
     * @param     
     * @return    
     */
    public Map<String, String> runDownloadRequest(DvnRJobRequest sro, RConnection c) {

        String optionBanner = "########### downloading option ###########\n";
        dbgLog.fine(optionBanner);

        Map<String, String> sr = new HashMap<String, String>();
        sr.put("requestdir", requestdir);
        sr.put("option", "download");

        String RcodeFile = "Rcode." + PID + ".R";

        try {
            // create a temp dir
            String createTmpDir = "dir.create('" + wrkdir + "')";
            dbgLog.fine("createTmpDir=" + createTmpDir);

            c.voidEval(createTmpDir);

            String dwnldOpt = sro.getDownloadRequestParameter();
            String dwnldFlxt = dwlndParam.get(dwnldOpt);

            sr.put("format", dwnldFlxt);

            String dataFileName = "Data." + PID + "." + dwnldFlxt;

            sr.put("subsetfile", "/" + requestdir + "/" + dataFileName);

            // data file to be copied back to the dvn
            String dsnprfx = wrkdir + "/" + dataFileName;

            String univarDataDwnld = "univarDataDwnld(dtfrm=x," + "dwnldoptn='" + dwnldOpt + "'" + ", dsnprfx='"
                    + dsnprfx + "')";

            dbgLog.fine("univarDataDwnld=" + univarDataDwnld);

            c.voidEval(univarDataDwnld);

            int wbFileSize = getFileSize(c, dsnprfx);

            dbgLog.fine("wbFileSize=" + wbFileSize);

            // write back the data file to the dvn

            File dtfl = writeBackFileToDvn(c, dsnprfx, dtflprefix, dwlndParam.get(dwnldOpt), wbFileSize);

            if (dtfl != null) {
                sr.put("wbDataFileName", dtfl.getAbsolutePath());
                dbgLog.fine("wbDataFileName=" + dtfl.getAbsolutePath());
            } else {
                dbgLog.fine("wbDataFileName is null");
            }

            // tab data file
            String mvTmpTabFile = "file.rename('" + tempFileName + "','" + tempFileNameNew + "')";
            c.voidEval(mvTmpTabFile);
            dbgLog.fine("move temp file=" + mvTmpTabFile);

            // move the temp dir to the web-temp root dir
            //            String mvTmpDir = "file.rename('"+wrkdir+"','"+webwrkdir+"')";
            //            dbgLog.fine("web-temp_dir="+mvTmpDir);
            //            c.voidEval(mvTmpDir);

        } catch (RserveException rse) {
            rse.printStackTrace();
            sr.put("RexecError", "true");
            return sr;
        }

        sr.put("RexecError", "false");
        return sr;
    }

    /** *************************************************************
     * 
     *
     * @param     
     * @return    
     */
    public String joinNelementsPerLine(String[] vn, int divisor) {
        String vnl = null;
        if (vn.length < divisor) {
            vnl = StringUtils.join(vn, ", ");
        } else {
            StringBuilder sb = new StringBuilder();

            int iter = vn.length / divisor;
            int lastN = vn.length % divisor;
            if (lastN != 0) {
                iter++;
            }
            int iterm = iter - 1;
            for (int i = 0; i < iter; i++) {
                int terminalN = divisor;
                if ((i == iterm) && (lastN != 0)) {
                    terminalN = lastN;
                }
                for (int j = 0; j < terminalN; j++) {
                    if ((divisor * i + j + 1) == vn.length) {
                        sb.append(vn[j + i * divisor]);
                    } else {

                        sb.append(vn[j + i * divisor] + ", ");
                    }
                }
                sb.append("\n");
            }
            vnl = sb.toString();
            dbgLog.fine(vnl);
        }
        return vnl;
    }

    /** *************************************************************
     * 
     *
     * @param     
     * @return    
     */
    public String joinNelementsPerLine(String[] vn, int divisor, String sp, boolean quote, String qm, String lnsp) {
        if (!(divisor >= 1)) {
            divisor = 1;
        } else if (divisor > vn.length) {
            divisor = vn.length;
        }
        String sep = null;
        if (sp != null) {
            sep = sp;
        } else {
            sep = ", ";
        }
        String qmrk = null;
        if (quote) {
            if (qm == null) {
                qmrk = ",";
            } else {
                if (qm.equals("\"")) {
                    qmrk = "\"";
                } else {
                    qmrk = qm;
                }
            }
        } else {
            qmrk = "";
        }
        String lineSep = null;
        if (lnsp == null) {
            lineSep = "\n";
        } else {
            lineSep = lnsp;
        }

        String vnl = null;
        if (vn.length < divisor) {
            vnl = StringUtils.join(vn, sep);
        } else {
            StringBuilder sb = new StringBuilder();

            int iter = vn.length / divisor;
            int lastN = vn.length % divisor;
            if (lastN != 0) {
                iter++;
            }
            int iterm = iter - 1;
            for (int i = 0; i < iter; i++) {
                int terminalN = divisor;
                if ((i == iterm) && (lastN != 0)) {
                    terminalN = lastN;
                }
                for (int j = 0; j < terminalN; j++) {
                    if ((divisor * i + j + 1) == vn.length) {

                        sb.append(qmrk + vn[j + i * divisor] + qmrk);

                    } else {

                        sb.append(qmrk + vn[j + i * divisor] + qmrk + sep);

                    }
                }
                if (i < (iter - 1)) {
                    sb.append(lineSep);
                }
            }
            vnl = sb.toString();
            dbgLog.fine("results:\n" + vnl);
        }
        return vnl;
    }

    /** *************************************************************
     * 
     *
     * @param     
     * @return    
     */
    public File writeBackFileToDvn(RConnection c, String targetFilename, String tmpFilePrefix, String tmpFileExt,
            int fileSize) {

        // set up a temp file
        File tmprsltfl = null;
        String resultFile = tmpFilePrefix + PID + "." + tmpFileExt;
        //String resultFilePrefix = tmpFilePrefix + PID + "_";

        //String rfsffx = "." + tmpFileExt;
        RFileInputStream ris = null;
        OutputStream outbr = null;
        try {
            //tmprsltfl = File.createTempFile(resultFilePrefix, rfsffx);
            tmprsltfl = new File(TEMP_DIR, resultFile);
            //outbr = new FileOutputStream(tmprsltfl);
            outbr = new BufferedOutputStream(new FileOutputStream(tmprsltfl));
            //File tmp = new File(targetFilename);
            //long tmpsize = tmp.length();
            // open the input stream
            ris = c.openFile(targetFilename);

            if (fileSize < 1024 * 1024 * 500) {
                int bfsize = fileSize;
                byte[] obuf = new byte[bfsize];
                ris.read(obuf);
                //while ((obufsize =)) != -1) {
                outbr.write(obuf, 0, bfsize);
                //}
            }
            ris.close();
            outbr.close();
            return tmprsltfl;
        } catch (FileNotFoundException fe) {
            fe.printStackTrace();
            dbgLog.fine("FileNotFound exception occurred");
            return tmprsltfl;
        } catch (IOException ie) {
            ie.printStackTrace();
            dbgLog.fine("IO exception occurred");
        } finally {
            if (ris != null) {
                try {
                    ris.close();
                } catch (IOException e) {

                }
            }

            if (outbr != null) {
                try {
                    outbr.close();
                } catch (IOException e) {

                }
            }

        }
        return tmprsltfl;
    }

    /** *************************************************************
     * 
     *
     * @param     
     * @return    
     */
    public int getFileSize(RConnection c, String targetFilename) {
        dbgLog.fine("targetFilename=" + targetFilename);
        int fileSize = 0;
        try {
            String fileSizeLine = "round(file.info('" + targetFilename + "')$size)";
            fileSize = c.eval(fileSizeLine).asInteger();
        } catch (RserveException rse) {
            rse.printStackTrace();
        } catch (REXPMismatchException mme) {
            mme.printStackTrace();
        }
        return fileSize;
    }
}