org.obiba.opal.web.datashield.RPackageResource.java Source code

Java tutorial

Introduction

Here is the source code for org.obiba.opal.web.datashield.RPackageResource.java

Source

/*
 * Copyright (c) 2014 OBiBa. All rights reserved.
 *
 * This program and the accompanying materials
 * are made available under the terms of the GNU Public License v3.0.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.obiba.opal.web.datashield;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;

import javax.annotation.Nullable;

import org.obiba.opal.r.RMatrix;
import org.obiba.opal.r.RScriptROperation;
import org.obiba.opal.r.RStringMatrix;
import org.obiba.opal.r.service.OpalRService;
import org.obiba.opal.web.datashield.support.NoSuchRPackageException;
import org.obiba.opal.web.model.Opal;
import org.obiba.opal.web.model.OpalR;
import org.rosuda.REngine.REXP;
import org.rosuda.REngine.REXPMismatchException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;

import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Strings;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;

/**
 * Base class for R package management.
 */
public abstract class RPackageResource {

    private static final Logger log = LoggerFactory.getLogger(RPackageResource.class);

    protected static final String VERSION = "Version";

    protected static final String AGGREGATE_METHODS = "AggregateMethods";

    protected static final String ASSIGN_METHODS = "AssignMethods";

    protected static final String OPTIONS = "Options";

    private static final String[] defaultFields = new String[] { "Title", "Description", "Author", "Maintainer",
            "Date/Publication", AGGREGATE_METHODS, ASSIGN_METHODS, OPTIONS };

    private static final String[] defaultRepos = new String[] { "http://cran.obiba.org", //"http://cran.datashield.org",
            "http://cran.rstudio.com" };

    @Autowired
    protected OpalRService opalRService;

    protected RScriptROperation getInstalledPackages() {
        return getInstalledPackages(new ArrayList<String>());
    }

    protected RScriptROperation getInstalledPackages(Iterable<String> fields) {
        Iterable<String> allFields = Iterables.concat(Arrays.asList(defaultFields), fields);
        String fieldStr = StringUtils.collectionToDelimitedString(Lists.newArrayList(allFields), ",", "'", "'");
        String cmd = "installed.packages(fields=c(" + fieldStr + "))";
        return execute(cmd);
    }

    protected RScriptROperation removePackage(String name) {
        String cmd = "remove.packages('" + name + "')";
        return execute(cmd);
    }

    protected RScriptROperation installPackage(String name) {
        RScriptROperation rval = execute(getInstallPackagesCommand(name));
        restartRServer();
        return rval;
    }

    protected RScriptROperation installDatashieldPackage(String name, String ref) {
        String cmd;
        if (Strings.isNullOrEmpty(ref)) {
            cmd = getInstallPackagesCommand(name);
        } else {
            execute(getInstallDevtoolsPackageCommand());
            cmd = getInstallGitHubCommand(name, "datashield", ref);
        }
        RScriptROperation rval = execute(cmd);
        restartRServer();
        return rval;
    }

    private void restartRServer() {
        try {
            opalRService.stop();
            opalRService.start();
        } catch (Exception ex) {
            log.error("Error while restarting R server after package install: {}", ex.getMessage(), ex);
        }
    }

    private String getInstallPackagesCommand(String name) {
        String repos = StringUtils.collectionToDelimitedString(Lists.newArrayList(defaultRepos), ",", "'", "'");
        return "install.packages('" + name + "', repos=c(" + repos + "), dependencies=TRUE)";
    }

    private String getInstallDevtoolsPackageCommand() {
        return "if (!require('devtools', character.only=TRUE)) { " + getInstallPackagesCommand("devtools") + " }";
    }

    private String getInstallGitHubCommand(String name, String username, String ref) {
        return "devtools::install_github('" + name + "', username='" + username + "', ref='" + ref + "')";
    }

    protected RScriptROperation execute(String rscript) {
        log.info(rscript);
        RScriptROperation rop = new RScriptROperation(rscript, false);
        opalRService.execute(rop);
        return rop;
    }

    protected OpalR.RPackageDto getDatashieldPackage(final String name) throws REXPMismatchException {
        RScriptROperation rop = getInstalledPackages();
        REXP rexp = rop.getResult();
        RStringMatrix matrix = new RStringMatrix(rexp);

        Iterator<OpalR.RPackageDto> iter = Iterables
                .filter(Iterables.transform(matrix.iterateRows(), new StringsToRPackageDto(matrix)),
                        new DataShieldPackagePredicate() {
                            @Override
                            public boolean apply(@Nullable OpalR.RPackageDto input) {
                                return input != null && input.getName().equals(name) && super.apply(input);
                            }
                        })
                .iterator();

        if (iter.hasNext()) {
            return iter.next();
        }
        throw new NoSuchRPackageException(name);
    }

    public static class StringsToRPackageDto implements Function<String[], OpalR.RPackageDto> {

        private int current = 0;

        private final RMatrix<String> matrix;

        public StringsToRPackageDto(RMatrix<String> matrix) {
            this.matrix = matrix;
        }

        @Override
        public OpalR.RPackageDto apply(@Nullable String[] input) {
            OpalR.RPackageDto.Builder builder = OpalR.RPackageDto.newBuilder();
            if (input != null) {
                for (int i = 0; i < input.length; i++) {
                    if (!Strings.isNullOrEmpty(input[i]) && !"NA".equals(input[i])) {
                        Opal.EntryDto.Builder entry = Opal.EntryDto.newBuilder();
                        entry.setKey(matrix.getColumnName(i));
                        entry.setValue(input[i]);
                        builder.addDescription(entry);
                    }
                }
            }
            builder.setName(matrix.getRowName(current++));
            return builder.build();
        }
    }

    protected static class DataShieldPackagePredicate implements Predicate<OpalR.RPackageDto> {
        @Override
        public boolean apply(@Nullable OpalR.RPackageDto input) {
            if (input == null)
                return false;
            for (Opal.EntryDto entry : input.getDescriptionList()) {
                String key = entry.getKey();
                if (AGGREGATE_METHODS.equals(key) || ASSIGN_METHODS.equals(key) || OPTIONS.equals(key)) {
                    return !"NA".equals(entry.getValue());
                }
            }
            return false;
        }
    }
}