package de.mpicbg.knime.scripting.r.port; import java.awt.BorderLayout; import java.awt.Font; import java.io.File; import java.nio.file.Path; import java.util.Arrays; import java.util.HashMap; import java.util.List; import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.text.DefaultCaret; import org.apache.commons.lang.StringUtils; import org.knime.core.node.port.PortObject; import org.knime.core.node.port.PortObjectSpec; import org.knime.core.node.port.PortType; import org.knime.core.node.port.PortTypeRegistry; import org.rosuda.REngine.REXPString; import org.rosuda.REngine.Rserve.RConnection; import org.rosuda.REngine.Rserve.RserveException; import de.mpicbg.knime.scripting.core.exceptions.KnimeScriptingException; import de.mpicbg.knime.scripting.r.RUtils; public class RPortObject2 implements PortObject { public static final PortType TYPE = PortTypeRegistry.getInstance().getPortType(RPortObject2.class); private final File m_WorkspaceFile; private HashMap<String, String> m_rObjects; public RPortObject2(File workspaceFile) { this.m_WorkspaceFile = workspaceFile; this.m_rObjects = getRObjects(); } public RPortObject2(RConnection connection, File workspaceFile) { this.m_WorkspaceFile = workspaceFile; this.m_rObjects = getRObjects(connection); } @Override public RPortObjectSpec2 getSpec() { final RPortObjectSpec2 spec = new RPortObjectSpec2(m_rObjects); return spec; } /** * retrieve all R objects and their type from an existing connection * @param connection * @return hashmap containing the names of all R-objects and their class * @throws RserveException */ private HashMap<String, String> getRObjects(RConnection connection) { HashMap<String, String> rObjects = new HashMap<String, String>(); try { REXPString objTypes = (REXPString) connection.eval("sapply(mget(ls(), .GlobalEnv), class)"); REXPString objNames = (REXPString) objTypes.getAttribute("names"); String[] types = objTypes.asStrings(); String[] names = objNames.asStrings(); for(int i = 0; i < objTypes.length(); i++) { rObjects.put(names[i], types[i]); } } catch (RserveException e) { e.printStackTrace(); } return rObjects; } /** * retrieve all R objects and their type by loading the workspace file (new connection) * @return hashmap containing the names of all R-objects and their class */ private HashMap<String, String> getRObjects() { RConnection connection = null; HashMap<String, String> rObjects = null; try { connection = RUtils.createConnection(); RUtils.loadWorkspace(m_WorkspaceFile, connection); rObjects = getRObjects(connection); } catch (KnimeScriptingException e) { e.printStackTrace(); } if(connection != null) connection.close(); return rObjects; } @Override public String getSummary() { return "R Objects"; } /** * view provided after execution? * {@inheritDoc} */ @Override public JComponent[] getViews() { JPanel panel = new JPanel(new BorderLayout()); panel.setName("R Port"); JTextArea jep = new JTextArea(); // prevent autoscrolling DefaultCaret caret = (DefaultCaret)jep.getCaret(); caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE); jep.setEditable(false); RConnection connection ; try { connection = RUtils.createConnection(); } catch (KnimeScriptingException e) { jep.setText(e.getMessage()); panel.add(new JScrollPane(jep)); e.printStackTrace(); return new JComponent[]{panel}; } jep.setFont(new Font("Monospaced", Font.PLAIN, 14)); try { RUtils.loadWorkspace(m_WorkspaceFile, connection); // to get structure information about the output object, one needs to use capture the output // str(...) does not provide any return value connection.voidEval("tempfile <- tempfile(pattern = 'structure_', fileext = '.txt')"); List<String> objects = Arrays.asList(connection.eval("ls()").asStrings()); for(String obj : objects) { // exclude files which where created temporary TODO: it is too dependent on how temporary file variables are named... other solution? if(!(obj.equals("tempfile") || obj.equals("tmpwfile"))) connection.voidEval("capture.output(print(\"" + obj + "\"), str(" + obj + "), file = tempfile, append = TRUE)"); } String[] structure = connection.eval("readLines(tempfile)").asStrings(); connection.voidEval("unlink(tempfile)"); String summary = StringUtils.join(structure, '\n'); jep.setText(summary); } catch (Exception e) { jep.setText("Failed to retrieve the structure of R objects from port file " + getFilePath()); } connection.close(); panel.add(new JScrollPane(jep)); return new JComponent[]{panel}; } private String getFilePath() { assert m_WorkspaceFile != null; return m_WorkspaceFile.getAbsolutePath(); } public File getFile() { return m_WorkspaceFile; } }