diff --git a/openbis_knime/.classpath b/openbis_knime/.classpath index 8e08285d5bf6a384f9958c1b8a6db2a883696592..c3513cd8d96a27277f0a19d100e987639f9a0a06 100644 --- a/openbis_knime/.classpath +++ b/openbis_knime/.classpath @@ -2,9 +2,17 @@ <classpath> <classpathentry kind="src" path="source/java"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/> - <classpathentry kind="lib" path="/libraries/knime/knime-base.jar"/> - <classpathentry kind="lib" path="/libraries/knime/knime-core.jar"/> + <classpathentry kind="lib" path="/libraries/knime/knime-base.jar"> + <attributes> + <attribute name="javadoc_location" value="jar:platform:/resource/libraries/knime/knime_2.1.2_API.zip!/"/> + </attributes> + </classpathentry> + <classpathentry kind="lib" path="/libraries/knime/knime-core.jar"> + <attributes> + <attribute name="javadoc_location" value="jar:platform:/resource/libraries/knime/knime_2.1.2_API.zip!/"/> + </attributes> + </classpathentry> <classpathentry kind="lib" path="/libraries/openbis-apis/query/openbis-query-api.jar"/> - <classpathentry kind="lib" path="/libraries/log4j/log4j.jar" sourcepath="/libraries/log4j/src.zip"/> + <classpathentry kind="lib" path="/libraries/cisd-base/cisd-base.jar" sourcepath="/libraries/cisd-base/cisd-base-src.zip"/> <classpathentry kind="output" path="targets/classes"/> </classpath> diff --git a/openbis_knime/dist/plugin.xml b/openbis_knime/dist/plugin.xml index c2ef97692956e37673f7942f14fed7b6d523aa3c..b4a1f0bff8e6ff0a830010ce483e9f0d103d79e2 100644 --- a/openbis_knime/dist/plugin.xml +++ b/openbis_knime/dist/plugin.xml @@ -3,12 +3,13 @@ <plugin> <extension point="org.knime.workbench.repository.nodes"> - <node category-path="/openbis" factory-class="ch.systemsx.cisd.openbis.knime.TestNodeFactory" - id="ch.systemsx.cisd.openbis.knime.node"/> + <node category-path="/openbis/query" factory-class="ch.systemsx.cisd.openbis.knime.query.QueryNodeFactory" + id="ch.systemsx.cisd.openbis.knime.query.QueryNodeFactory"/> </extension> <extension point="org.knime.workbench.repository.categories"> <category icon="icons/openbis.png" level-id="openbis" name="openBIS" path="/"/> + <category icon="icons/openbis.png" level-id="query" name="Query" path="/openbis"/> </extension> </plugin> \ No newline at end of file diff --git a/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/TestNodeDialog.java b/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/TestNodeDialog.java deleted file mode 100644 index f06e6eeb620c856380872c2910e8fc9cb35e1a99..0000000000000000000000000000000000000000 --- a/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/TestNodeDialog.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2010 ETH Zuerich, CISD - * - * 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. - */ - -package ch.systemsx.cisd.openbis.knime; - -import java.awt.BorderLayout; -import java.awt.GridLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.List; - -import javax.swing.JButton; -import javax.swing.JComboBox; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JPasswordField; -import javax.swing.JTextField; - -import org.apache.log4j.Logger; -import org.knime.core.node.InvalidSettingsException; -import org.knime.core.node.NodeDialogPane; -import org.knime.core.node.NodeSettingsRO; -import org.knime.core.node.NodeSettingsWO; -import org.knime.core.node.NotConfigurableException; -import org.knime.core.node.port.PortObjectSpec; - -import ch.systemsx.cisd.openbis.plugin.query.client.api.v1.QueryApiFacade; -import ch.systemsx.cisd.openbis.plugin.query.shared.api.v1.dto.QueryDescription; - -/** - * - * - * @author Franz-Josef Elmer - */ -public class TestNodeDialog extends NodeDialogPane -{ - private JTextField urlField; - private JTextField userField; - private JPasswordField passwordField; - private JComboBox queryComboBox; - - TestNodeDialog() - { - super(); - addTab("openBIS Settings", createGUI()); - } - - private JPanel createGUI() - { - JPanel panel = new JPanel(new BorderLayout()); - JPanel form = new JPanel(new GridLayout(0, 2)); - form.add(new JLabel("openBIS URL:")); - urlField = new JTextField(); - form.add(urlField); - form.add(new JLabel("User:")); - userField = new JTextField(); - form.add(userField); - form.add(new JLabel("Password:")); - passwordField = new JPasswordField(); - form.add(passwordField); - form.add(new JLabel("Queries:")); - queryComboBox = new JComboBox(); - form.add(queryComboBox); - panel.add(form, BorderLayout.NORTH); - JButton button = new JButton("connect"); - button.addActionListener(new ActionListener() - { - - public void actionPerformed(ActionEvent e) - { - QueryApiFacade facade = QueryApiFacade.create(urlField.getText(), userField.getText(), passwordField.getText()); - List<QueryDescription> queries = facade.listQueries(); - for (QueryDescription queryDescription : queries) - { - queryComboBox.addItem(queryDescription.getName()); - } - // TODO Auto-generated method stub - - } - }); - panel.add(button, BorderLayout.SOUTH); - return panel; - } - - @Override - protected void loadSettingsFrom(NodeSettingsRO settings, PortObjectSpec[] specs) - throws NotConfigurableException - { - } - - @Override - protected void saveSettingsTo(NodeSettingsWO settings) throws InvalidSettingsException - { - // TODO Auto-generated method stub - - } - -} diff --git a/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/TestNodeFactory.xml b/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/TestNodeFactory.xml deleted file mode 100644 index 8128aed79d12698473e73cc68a9feafe8a046942..0000000000000000000000000000000000000000 --- a/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/TestNodeFactory.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!DOCTYPE knimeNode PUBLIC "-//UNIKN//DTD KNIME Node 2.0//EN" "http://www.knime.org/Node.dtd"> -<knimeNode icon="./openbis.png" type="Source"> - <name>openBIS Test</name> - - <shortDescription> - openBIS test node - </shortDescription> - - <fullDescription> - <intro>Just testing a very simple node. - </intro> - - - <option name="short name of first option (like in the dialog)">has no first option</option> - <option name="short name of second option (like in the dialog)">has no second option</option> - </fullDescription> - - <ports> - <inPort index="0" name="First In Port">Actual there are no in ports I guess</inPort> - <outPort index="0" name="First out Port">A simple table</outPort> - </ports> - <views> - <view index="0" name="name of first view">Description of first view...</view> - </views> -</knimeNode> diff --git a/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/TestNodeModel.java b/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/TestNodeModel.java deleted file mode 100644 index ba1e739538afe25f032883a44f2d00bb14dde98d..0000000000000000000000000000000000000000 --- a/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/TestNodeModel.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2010 ETH Zuerich, CISD - * - * 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. - */ - -package ch.systemsx.cisd.openbis.knime; - -import java.io.File; -import java.io.IOException; - -import org.knime.core.data.DataTableSpec; -import org.knime.core.data.DataType; -import org.knime.core.data.def.DefaultRow; -import org.knime.core.data.def.StringCell; -import org.knime.core.node.BufferedDataContainer; -import org.knime.core.node.BufferedDataTable; -import org.knime.core.node.CanceledExecutionException; -import org.knime.core.node.ExecutionContext; -import org.knime.core.node.ExecutionMonitor; -import org.knime.core.node.InvalidSettingsException; -import org.knime.core.node.NodeModel; -import org.knime.core.node.NodeSettingsRO; -import org.knime.core.node.NodeSettingsWO; - -/** - * - * - * @author Franz-Josef Elmer - */ -public class TestNodeModel extends NodeModel -{ - - protected TestNodeModel() - { - super(0, 1); - } - - @Override - protected void loadInternals(File arg0, ExecutionMonitor arg1) throws IOException, - CanceledExecutionException - { - // TODO Auto-generated method stub - - } - - @Override - protected void loadValidatedSettingsFrom(NodeSettingsRO arg0) throws InvalidSettingsException - { - // TODO Auto-generated method stub - - } - - @Override - protected void reset() - { - // TODO Auto-generated method stub - - } - - @Override - protected void saveInternals(File arg0, ExecutionMonitor arg1) throws IOException, - CanceledExecutionException - { - // TODO Auto-generated method stub - - } - - @Override - protected void saveSettingsTo(NodeSettingsWO arg0) - { - // TODO Auto-generated method stub - - } - - @Override - protected void validateSettings(NodeSettingsRO arg0) throws InvalidSettingsException - { - // TODO Auto-generated method stub - - } - - @Override - protected BufferedDataTable[] execute(BufferedDataTable[] inData, ExecutionContext exec) - throws Exception - { - BufferedDataContainer container = exec.createDataContainer(new DataTableSpec(new String[] {"col1", "col2"}, - new DataType[] {StringCell.TYPE, StringCell.TYPE})); - for (int i = 0; i < 5; i++) - { - container.addRowToTable(new DefaultRow("row-"+i, "a-"+i, "b-"+i)); - } - container.close(); - return new BufferedDataTable[] {container.getTable()}; - } - - @Override - protected DataTableSpec[] configure(final DataTableSpec[] inSpecs) - throws InvalidSettingsException - { - return new DataTableSpec[0]; - } -} diff --git a/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/ParameterBindings.java b/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/ParameterBindings.java new file mode 100644 index 0000000000000000000000000000000000000000..6616201802297ea3b497bc7677e3d11c31fb69cd --- /dev/null +++ b/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/ParameterBindings.java @@ -0,0 +1,96 @@ +/* + * Copyright 2010 ETH Zuerich, CISD + * + * 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. + */ + +package ch.systemsx.cisd.openbis.knime.query; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.Map.Entry; + +import org.knime.core.node.InvalidSettingsException; +import org.knime.core.node.NodeSettingsRO; +import org.knime.core.node.NodeSettingsWO; + +import ch.systemsx.cisd.base.exceptions.CheckedExceptionTunnel; + +/** + * + * + * @author Franz-Josef Elmer + */ +class ParameterBindings +{ + static final String PARAMETER_KEYS_KEY = "query-parameter-keys"; + static final String PARAMETER_VALUES_KEY = "query-parameter-values"; + + private Map<String, String> bindings = new LinkedHashMap<String, String>(); + + void removeAllBindings() + { + bindings.clear(); + } + + void bind(String parameter, String value) + { + bindings.put(parameter, value); + } + + Map<String, String> getBindings() + { + return bindings; + } + + String tryToGetBinding(String parameter) + { + return bindings.get(parameter); + } + + void loadValidatedSettingsFrom(NodeSettingsRO settings) + { + String[] parameterKeys; + String[] parameterValues; + try + { + parameterKeys = settings.getStringArray(PARAMETER_KEYS_KEY); + parameterValues = settings.getStringArray(PARAMETER_VALUES_KEY); + } catch (InvalidSettingsException ex) + { + throw CheckedExceptionTunnel.wrapIfNecessary(ex); + } + bindings.clear(); + for (int i = 0, n = Math.min(parameterKeys.length, parameterValues.length); i < n; i++) + { + bindings.put(parameterKeys[i], parameterValues[i]); + } + } + + void saveSettingsTo(NodeSettingsWO settings) + { + List<String> parameterKeys = new ArrayList<String>(bindings.size()); + List<String> parameterValues = new ArrayList<String>(bindings.size()); + Set<Entry<String, String>> entrySet = bindings.entrySet(); + for (Entry<String, String> entry : entrySet) + { + parameterKeys.add(entry.getKey()); + parameterValues.add(entry.getValue()); + } + settings.addStringArray(PARAMETER_KEYS_KEY, parameterKeys.toArray(new String[0])); + settings.addStringArray(PARAMETER_VALUES_KEY, parameterValues.toArray(new String[0])); + } +} diff --git a/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/QueryNodeDialog.java b/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/QueryNodeDialog.java new file mode 100644 index 0000000000000000000000000000000000000000..91cc59b63409648bafe15d2e517c2f02e8380fd1 --- /dev/null +++ b/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/QueryNodeDialog.java @@ -0,0 +1,251 @@ +/* + * Copyright 2010 ETH Zuerich, CISD + * + * 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. + */ + +package ch.systemsx.cisd.openbis.knime.query; + +import static ch.systemsx.cisd.openbis.knime.query.QueryNodeModel.PASSWORD_KEY; +import static ch.systemsx.cisd.openbis.knime.query.QueryNodeModel.QUERY_DESCRIPTION_KEY; +import static ch.systemsx.cisd.openbis.knime.query.QueryNodeModel.URL_KEY; +import static ch.systemsx.cisd.openbis.knime.query.QueryNodeModel.USER_KEY; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.GridLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.Map.Entry; + +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JPasswordField; +import javax.swing.JScrollPane; +import javax.swing.JTextField; + +import org.knime.core.node.InvalidSettingsException; +import org.knime.core.node.NodeDialogPane; +import org.knime.core.node.NodeLogger; +import org.knime.core.node.NodeSettingsRO; +import org.knime.core.node.NodeSettingsWO; +import org.knime.core.node.NotConfigurableException; +import org.knime.core.node.port.PortObjectSpec; + +import ch.systemsx.cisd.openbis.plugin.query.client.api.v1.FacadeFactory; +import ch.systemsx.cisd.openbis.plugin.query.client.api.v1.IQueryApiFacade; +import ch.systemsx.cisd.openbis.plugin.query.shared.api.v1.dto.QueryDescription; + +/** + * + * + * @author Franz-Josef Elmer + */ +public class QueryNodeDialog extends NodeDialogPane +{ + private static final NodeLogger log = NodeLogger.getLogger(QueryNodeDialog.class); + + private JTextField urlField; + private JTextField userField; + private JPasswordField passwordField; + private JComboBox queryComboBox; + private JPanel parametersPanel; + private ParameterBindings parameterBindings = new ParameterBindings(); + private Map<String, JTextField> parameterFields = new HashMap<String, JTextField>(); + + QueryNodeDialog() + { + super(); + addTab("Query Settings", createGUI()); + } + + private JComponent createGUI() + { + JPanel panel = new JPanel(new BorderLayout()); + panel.setPreferredSize(new Dimension(400, 450)); + JPanel connectionPanel = new JPanel(new GridBagLayout()); + connectionPanel.setBorder(BorderFactory.createTitledBorder("Connection Parameters")); + urlField = addField(connectionPanel, "openBIS URL", new JTextField(20)); + userField = addField(connectionPanel, "User", new JTextField(20)); + passwordField = addField(connectionPanel, "Password", new JPasswordField(20)); + JButton button = new JButton("connect"); + button.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + connectToOpenBIS(); + } + }); + connectionPanel.add(button, createLast()); + panel.add(connectionPanel, BorderLayout.NORTH); + JPanel queryPanel = new JPanel(new BorderLayout()); + panel.add(queryPanel, BorderLayout.CENTER); + queryComboBox = new JComboBox(); + queryComboBox.addItemListener(new ItemListener() + { + public void itemStateChanged(ItemEvent e) + { + QueryDescription queryDescription = (QueryDescription) e.getItem(); + updateParametersPanel(queryDescription); + log.info(queryDescription); + } + }); + JPanel querySelectionPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); + querySelectionPanel.add(new JLabel("Query:")); + querySelectionPanel.add(queryComboBox); + queryPanel.add(querySelectionPanel, BorderLayout.NORTH); + parametersPanel = new JPanel(new GridLayout(0, 2)); + parametersPanel.setBorder(BorderFactory.createTitledBorder("Query Parameters")); + JPanel northPanel = new JPanel(new BorderLayout()); + northPanel.add(parametersPanel, BorderLayout.NORTH); + queryPanel.add(northPanel, BorderLayout.CENTER); + JScrollPane scrollPane = new JScrollPane(panel); + scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); + scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); + return scrollPane; + } + + @Override + protected void loadSettingsFrom(NodeSettingsRO settings, PortObjectSpec[] specs) + throws NotConfigurableException + { + urlField.setText(settings.getString(URL_KEY, "")); + userField.setText(settings.getString(USER_KEY, "")); + passwordField.setText(settings.getString(PASSWORD_KEY, "")); + byte[] bytes = settings.getByteArray(QUERY_DESCRIPTION_KEY, null); + QueryDescription queryDescriptionOrNull = Util.deserializeQueryDescription(bytes); + parameterBindings.loadValidatedSettingsFrom(settings); + if (queryDescriptionOrNull != null && queryComboBox.getItemCount() == 0) + { + queryComboBox.addItem(queryDescriptionOrNull); + queryComboBox.setSelectedIndex(0); + } + } + + @Override + protected void saveSettingsTo(NodeSettingsWO settings) throws InvalidSettingsException + { + settings.addString(URL_KEY, urlField.getText().trim()); + settings.addString(USER_KEY, userField.getText().trim()); + settings.addString(PASSWORD_KEY, passwordField.getText().trim()); + byte[] bytes = Util.serializeQueryDescription(getSelectedQueryDescriptionOrNull()); + settings.addByteArray(QUERY_DESCRIPTION_KEY, bytes); + parameterBindings.removeAllBindings(); + Set<Entry<String, JTextField>> entrySet = parameterFields.entrySet(); + for (Entry<String, JTextField> entry : entrySet) + { + parameterBindings.bind(entry.getKey(), entry.getValue().getText()); + } + parameterBindings.saveSettingsTo(settings); + } + + private QueryDescription getSelectedQueryDescriptionOrNull() + { + Object selectedItem = queryComboBox.getSelectedItem(); + return selectedItem == null ? null : (QueryDescription) selectedItem; + } + + private <T extends JComponent> T addField(JPanel panel, String label, T field) + { + panel.add(new JLabel(label + ":"), createFirst()); + panel.add(field, createLast()); + return field; + } + + private GridBagConstraints createLast() + { + GridBagConstraints last = createFirst(); + last.gridwidth = GridBagConstraints.REMAINDER; + return last; + } + + private GridBagConstraints createFirst() + { + GridBagConstraints constraints = new GridBagConstraints(); + constraints.anchor = GridBagConstraints.WEST; + constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.insets = new Insets(2, 3, 2, 3); + return constraints; + } + + private void connectToOpenBIS() + { + String url = urlField.getText(); + String userID = userField.getText(); + String password = passwordField.getText(); + IQueryApiFacade facade = FacadeFactory.create(url, userID, password); + List<QueryDescription> queries = facade.listQueries(); + Collections.sort(queries, new Comparator<QueryDescription>() + { + public int compare(QueryDescription d1, QueryDescription d2) + { + return d1.getName().compareTo(d2.getName()); + } + }); + QueryDescription selectedQueryDescription = getSelectedQueryDescriptionOrNull(); + queryComboBox.removeAllItems(); + for (QueryDescription queryDescription : queries) + { + queryComboBox.addItem(queryDescription); + if (queryDescription.equals(selectedQueryDescription)) + { + queryComboBox.setSelectedItem(queryDescription); + } + } + } + + private void updateParametersPanel(QueryDescription queryDescription) + { + log.info("update parameters panel for '" + queryDescription + "' which has " + + queryDescription.getParameters().size() + " parameters."); + parametersPanel.removeAll(); + parameterFields.clear(); + List<String> parameters = queryDescription.getParameters(); + parametersPanel.setVisible(parameters.isEmpty() == false); + for (String parameter : parameters) + { + JTextField field = parameterFields.get(parameter); + if (field == null) + { + field = new JTextField(15); + parameterFields.put(parameter, field); + } + String value = parameterBindings.tryToGetBinding(parameter); + if (value != null) + { + field.setText(value); + } + addField(parametersPanel, parameter, field); + } + parametersPanel.invalidate(); + parametersPanel.getParent().validate(); + } + + +} diff --git a/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/TestNodeFactory.java b/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/QueryNodeFactory.java similarity index 77% rename from openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/TestNodeFactory.java rename to openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/QueryNodeFactory.java index daa77002197ca8176aac96c8c8f3bbdda80efc02..d10a56ce721bea47aff9d509c1e5ef2f5e4b547a 100644 --- a/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/TestNodeFactory.java +++ b/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/QueryNodeFactory.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package ch.systemsx.cisd.openbis.knime; +package ch.systemsx.cisd.openbis.knime.query; import org.knime.core.node.NodeDialogPane; import org.knime.core.node.NodeFactory; @@ -25,23 +25,23 @@ import org.knime.core.node.NodeView; * * @author Franz-Josef Elmer */ -public class TestNodeFactory extends NodeFactory<TestNodeModel> +public class QueryNodeFactory extends NodeFactory<QueryNodeModel> { @Override protected NodeDialogPane createNodeDialogPane() { - return new TestNodeDialog(); + return new QueryNodeDialog(); } @Override - public TestNodeModel createNodeModel() + public QueryNodeModel createNodeModel() { - return new TestNodeModel(); + return new QueryNodeModel(); } @Override - public NodeView<TestNodeModel> createNodeView(int arg0, TestNodeModel arg1) + public NodeView<QueryNodeModel> createNodeView(int viewIndex, QueryNodeModel model) { return null; } diff --git a/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/QueryNodeFactory.xml b/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/QueryNodeFactory.xml new file mode 100644 index 0000000000000000000000000000000000000000..85a654551c6f5d60d5890317be9cc0a1d9e0cfc0 --- /dev/null +++ b/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/QueryNodeFactory.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE knimeNode PUBLIC "-//UNIKN//DTD KNIME Node 2.0//EN" "http://www.knime.org/Node.dtd"> +<knimeNode icon="./openbis.png" type="Source"> + <name>openBIS Query Reader</name> + + <shortDescription>openBIS query node</shortDescription> + + <fullDescription> + <intro>Data source node to run a parameterized SQL query on openBIS Application Server + </intro> + </fullDescription> + + <ports> + <outPort index="0" name="Result Set">Table with result set</outPort> + </ports> +</knimeNode> diff --git a/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/QueryNodeModel.java b/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/QueryNodeModel.java new file mode 100644 index 0000000000000000000000000000000000000000..bdb3ae5bf7d3a709d09f403d2d2b1244b0f89c4c --- /dev/null +++ b/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/QueryNodeModel.java @@ -0,0 +1,169 @@ +/* + * Copyright 2010 ETH Zuerich, CISD + * + * 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. + */ + +package ch.systemsx.cisd.openbis.knime.query; + +import java.io.File; +import java.io.IOException; +import java.io.Serializable; +import java.util.List; + +import org.knime.core.data.DataCell; +import org.knime.core.data.DataTableSpec; +import org.knime.core.data.DataType; +import org.knime.core.data.def.DefaultRow; +import org.knime.core.data.def.DoubleCell; +import org.knime.core.data.def.LongCell; +import org.knime.core.data.def.StringCell; +import org.knime.core.node.BufferedDataContainer; +import org.knime.core.node.BufferedDataTable; +import org.knime.core.node.CanceledExecutionException; +import org.knime.core.node.ExecutionContext; +import org.knime.core.node.ExecutionMonitor; +import org.knime.core.node.InvalidSettingsException; +import org.knime.core.node.NodeModel; +import org.knime.core.node.NodeSettingsRO; +import org.knime.core.node.NodeSettingsWO; + +import ch.systemsx.cisd.openbis.plugin.query.client.api.v1.FacadeFactory; +import ch.systemsx.cisd.openbis.plugin.query.client.api.v1.IQueryApiFacade; +import ch.systemsx.cisd.openbis.plugin.query.shared.api.v1.dto.QueryDescription; +import ch.systemsx.cisd.openbis.plugin.query.shared.api.v1.dto.QueryTableColumn; +import ch.systemsx.cisd.openbis.plugin.query.shared.api.v1.dto.QueryTableModel; + +/** + * + * + * @author Franz-Josef Elmer + */ +public class QueryNodeModel extends NodeModel +{ + static final String URL_KEY = "url"; + static final String USER_KEY = "user"; + static final String PASSWORD_KEY = "password"; + static final String QUERY_DESCRIPTION_KEY = "query-description"; + + private String url; + private String userID; + private String password; + private QueryDescription queryDescription; + private ParameterBindings parameterBindings = new ParameterBindings(); + + protected QueryNodeModel() + { + super(0, 1); + } + + @Override + protected DataTableSpec[] configure(final DataTableSpec[] inSpecs) + throws InvalidSettingsException + { + return new DataTableSpec[1]; + } + + @Override + protected void validateSettings(NodeSettingsRO settings) throws InvalidSettingsException + { + } + + @Override + protected void loadValidatedSettingsFrom(NodeSettingsRO settings) throws InvalidSettingsException + { + url = settings.getString(URL_KEY); + userID = settings.getString(USER_KEY); + password = settings.getString(PASSWORD_KEY); + queryDescription = Util.deserializeQueryDescription(settings.getByteArray(QUERY_DESCRIPTION_KEY)); + parameterBindings.loadValidatedSettingsFrom(settings); + } + + @Override + protected void saveSettingsTo(NodeSettingsWO settings) + { + settings.addString(URL_KEY, url); + settings.addString(USER_KEY, userID); + settings.addString(PASSWORD_KEY, password); + settings.addByteArray(QUERY_DESCRIPTION_KEY, Util + .serializeQueryDescription(queryDescription)); + parameterBindings.saveSettingsTo(settings); + } + + @Override + protected void reset() + { + } + + @Override + protected void saveInternals(File arg0, ExecutionMonitor arg1) throws IOException, + CanceledExecutionException + { + } + + @Override + protected void loadInternals(File arg0, ExecutionMonitor arg1) throws IOException, + CanceledExecutionException + { + } + + @Override + protected BufferedDataTable[] execute(BufferedDataTable[] inData, ExecutionContext exec) + throws Exception + { + IQueryApiFacade facade = createFacade(url, userID, password); + QueryTableModel result = facade.executeQuery(queryDescription.getId(), parameterBindings.getBindings()); + List<QueryTableColumn> columns = result.getColumns(); + String[] columnTitles = new String[columns.size()]; + DataType[] columnTypes = new DataType[columns.size()]; + for (int i = 0, n = columns.size(); i < n; i++) + { + QueryTableColumn column = columns.get(i); + columnTitles[i] = column.getTitle(); + columnTypes[i] = Util.translateDataType(column.getDataType()); + } + DataTableSpec dataTableSpec = new DataTableSpec(columnTitles, columnTypes); + BufferedDataContainer container = exec.createDataContainer(dataTableSpec); + List<Serializable[]> rows = result.getRows(); + for (int i = 0, n = rows.size(); i < n; i++) + { + Serializable[] row = rows.get(i); + DataCell[] cells = new DataCell[row.length]; + for (int c = 0; c < row.length; c++) + { + Serializable value = row[c]; + DataCell cell = null; + if (value instanceof Double) + { + cell = new DoubleCell((Double) value); + } else if (value instanceof Long) + { + cell = new LongCell((Long) value); + } else + { + cell = new StringCell(value.toString()); + } + cells[c] = cell; + } + container.addRowToTable(new DefaultRow(Integer.toString(i), cells)); + } + container.close(); + return new BufferedDataTable[] {container.getTable()}; + } + + protected IQueryApiFacade createFacade(String serverURL, String user, String psswrd) + { + return FacadeFactory.create(serverURL, user, psswrd); + } + +} diff --git a/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/Util.java b/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/Util.java new file mode 100644 index 0000000000000000000000000000000000000000..02023d45fca50f3b3a3df2dd70a19b0cb1c0b09e --- /dev/null +++ b/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/Util.java @@ -0,0 +1,82 @@ +/* + * Copyright 2010 ETH Zuerich, CISD + * + * 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. + */ + +package ch.systemsx.cisd.openbis.knime.query; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +import org.knime.core.data.DataType; +import org.knime.core.data.def.DoubleCell; +import org.knime.core.data.def.LongCell; +import org.knime.core.data.def.StringCell; + +import ch.systemsx.cisd.openbis.plugin.query.shared.api.v1.dto.QueryDescription; +import ch.systemsx.cisd.openbis.plugin.query.shared.api.v1.dto.QueryTableColumnDataType; + +/** + * + * + * @author Franz-Josef Elmer + */ +class Util +{ + static byte[] serializeQueryDescription(QueryDescription queryDescriptionOrNull) + { + if (queryDescriptionOrNull == null) + { + return null; + } + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try + { + new ObjectOutputStream(baos).writeObject(queryDescriptionOrNull); + return baos.toByteArray(); + } catch (IOException ex) + { + return null; + } + } + + static QueryDescription deserializeQueryDescription(byte[] serializeQueryDescriptionOrNull) + { + if (serializeQueryDescriptionOrNull == null) + { + return null; + } + ByteArrayInputStream bais = new ByteArrayInputStream(serializeQueryDescriptionOrNull); + try + { + return (QueryDescription) new ObjectInputStream(bais).readObject(); + } catch (Exception ex) + { + return null; + } + } + + static DataType translateDataType(QueryTableColumnDataType dataType) + { + switch (dataType) + { + case DOUBLE: return DoubleCell.TYPE; + case LONG: return LongCell.TYPE; + default: return StringCell.TYPE; + } + } +} diff --git a/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/openbis.png b/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/openbis.png similarity index 100% rename from openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/openbis.png rename to openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/openbis.png