diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/AbstractSwingGUI.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/AbstractSwingGUI.java index 6c4eb40adba0f4c6b334434bd76fa069a3167cb8..27144c051f9c9ebcd406c4d7373d0ce7246545c5 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/AbstractSwingGUI.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/AbstractSwingGUI.java @@ -236,9 +236,8 @@ public abstract class AbstractSwingGUI @Override public void run() { - JOptionPane.showMessageDialog(parentFrame, - WordUtils.wrap(message, MESSAGE_WRAP_MAX_CHAR), title, - JOptionPane.ERROR_MESSAGE); + UiUtilities.showMessageAndException(parentFrame, throwable, + WordUtils.wrap(message, MESSAGE_WRAP_MAX_CHAR), title); } }); } @@ -269,90 +268,4 @@ public abstract class AbstractSwingGUI } } - // -------- errors reporting ----------------- - - protected static void showErrorsAndWarningsIfAny(JFrame frame, String firstMessageOrNull, - List<String> warningMessages, List<Throwable> exceptions) - { - String message = (firstMessageOrNull == null ? "" : firstMessageOrNull + "\n"); - message += joinMessages(warningMessages, exceptions); - if (exceptions.size() > 0) - { - showErrorMessage(frame, message); - } else if (warningMessages.size() > 0) - { - showWarningMessage(frame, message); - } - } - - private static void showErrorMessage(JFrame frame, String message) - { - showMessageDialog(frame, message, "Error", JOptionPane.ERROR_MESSAGE); - } - - private static void showWarningMessage(JFrame frame, String message) - { - showMessageDialog(frame, message, "Warning", JOptionPane.WARNING_MESSAGE); - } - - private static void showMessageDialog(JFrame frame, String message, String title, - int messageType) - { - JOptionPane.showMessageDialog(frame, message, title, messageType); - } - - private static String joinMessages(List<String> warningMessages, List<Throwable> exceptions) - { - StringBuffer sb = new StringBuffer(); - addErrorMessages(exceptions, sb); - addWarningMessages(warningMessages, sb); - return sb.toString(); - } - - private static void addErrorMessages(List<Throwable> exceptions, StringBuffer sb) - { - if (exceptions.size() > 0) - { - if (exceptions.size() > 1) - { - sb.append("Following errors occured: \n"); - } - for (Throwable exception : exceptions) - { - sb.append(getErrorMessage(exception)); - sb.append("\n"); - } - } - } - - private static void addWarningMessages(List<String> warningMessages, StringBuffer sb) - { - if (warningMessages.size() > 0) - { - sb.append("Following warnings occured (you can most probably ignore them): \n"); - String lastWarningMessage = ""; - for (String warningMessage : warningMessages) - { - if (lastWarningMessage.equals(warningMessage) == false) - { - sb.append(warningMessage); - sb.append("\n"); - lastWarningMessage = warningMessage; - } - } - } - } - - private static String getErrorMessage(Throwable throwable) - { - final String message; - if (throwable instanceof HighLevelException) - { - message = throwable.getMessage(); - } else - { - message = "ERROR: " + throwable; - } - return message; - } } \ No newline at end of file diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/AbstractTreeEntityPickerDialog.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/AbstractTreeEntityPickerDialog.java index 25de90dc8cf8bca521f571fa1b3cc1839c11ede6..7e1e9d1d6b523b494a7e70c03022480f3d02d610 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/AbstractTreeEntityPickerDialog.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/AbstractTreeEntityPickerDialog.java @@ -26,7 +26,6 @@ import java.util.List; import javax.swing.JDialog; import javax.swing.JFrame; -import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; @@ -49,6 +48,7 @@ import ch.systemsx.cisd.openbis.dss.client.api.gui.model.UploadClientSortingUtil import ch.systemsx.cisd.openbis.dss.client.api.gui.tree.FilterableMutableTreeNode; import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.NewDataSetDTO.DataSetOwnerType; import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Experiment; +import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Sample; /** * Abstract super class of all entity picker dialogs based on {@link JTree}. @@ -77,6 +77,8 @@ public abstract class AbstractTreeEntityPickerDialog extends AbstractEntityPicke this.entityKind = entityKind; tree = new JTree(); tree.setModel(new DefaultTreeModel(null)); + tree.setRootVisible(false); + tree.setShowsRootHandles(true); tree.addTreeWillExpandListener(this); tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); addTreeSelectionListener(); @@ -93,7 +95,7 @@ public abstract class AbstractTreeEntityPickerDialog extends AbstractEntityPicke final JScrollPane scrollPane = new JScrollPane(tree); List<Object> objectsAsList = new ArrayList<Object>(); - objectsAsList.add("Filter experiments: "); + objectsAsList.add("Filter experiments and samples: "); objectsAsList.add(northPanel); objectsAsList.add("Select " + entityKind.toString().toLowerCase() + ":"); @@ -159,66 +161,104 @@ public abstract class AbstractTreeEntityPickerDialog extends AbstractEntityPicke } } String label = entityKind.toString(); - JOptionPane.showMessageDialog(this, "No correct " + label.toLowerCase() + " found, " + selected + " is not correct!", - "No correct " + label.toLowerCase() + " found, " + selected + " is not correct!", JOptionPane.WARNING_MESSAGE); + JOptionPane.showMessageDialog(this, "Please, select a " + label.toLowerCase() + ".", + "No " + label.toLowerCase() + " selected!", JOptionPane.WARNING_MESSAGE); optionPane.setValue(optionPane.getInitialValue()); } @Override public void treeWillExpand(final TreeExpansionEvent event) throws ExpandVetoException { - final DefaultMutableTreeNode node = - (DefaultMutableTreeNode) event.getPath().getLastPathComponent(); + final FilterableMutableTreeNode node = + (FilterableMutableTreeNode) event.getPath().getLastPathComponent(); // if top level, then finish if (((TreeNode) node).getParent() == null) { return; } Object userObject = node.getUserObject(); - if (userObject instanceof Identifier) + if (UiUtilities.ROOT_EXPERIMENTS.equals(userObject)) + { + expandExperiments(node); + } else if (UiUtilities.ROOT_SAMPLES.equals(userObject)) + { + expandSamples(node); + } else if (userObject instanceof Identifier) { expandNode(node, (Identifier) userObject); } } + + private void expandExperiments(final FilterableMutableTreeNode node) + { + AsyncNodeAction<List<Experiment>> action = + new AsyncNodeAction<List<Experiment>>(tree, node, scheduler) + { + @Override + public void handleData(List<Experiment> experiments) + { + node.removeAllChildren(); + UploadClientSortingUtils.sortExperimentsByIdentifier(experiments); + for (Experiment experiment : experiments) + { + FilterableMutableTreeNode category = + new FilterableMutableTreeNode(Identifier.create(experiment)); + category.add(UiUtilities.createWaitingNode()); + node.add(category); + } + } + }; + clientModel.listExperiments(action); + } + + private void expandSamples(final FilterableMutableTreeNode node) + { + AsyncNodeAction<List<Sample>> action = + new AsyncNodeAction<List<Sample>>(tree, node, scheduler) + { + @Override + public void handleData(List<Sample> samples) + { + node.removeAllChildren(); + UploadClientSortingUtils.sortSamplesByIdentifier(samples); + for (Sample sample : samples) + { + FilterableMutableTreeNode category = + new FilterableMutableTreeNode(Identifier.create(sample)); + category.add(UiUtilities.createWaitingNode()); + node.add(category); + } + } + }; + clientModel.listSamplesWithNoExperiments(action); + } - protected abstract void expandNode(final DefaultMutableTreeNode node, Identifier identifier); + protected abstract void expandNode(final FilterableMutableTreeNode node, Identifier identifier); @Override public void treeWillCollapse(TreeExpansionEvent event) throws ExpandVetoException { - DefaultMutableTreeNode node = - (DefaultMutableTreeNode) event.getPath().getLastPathComponent(); + FilterableMutableTreeNode node = + (FilterableMutableTreeNode) event.getPath().getLastPathComponent(); if (node.isRoot()) { throw new ExpandVetoException(event); } node.removeAllChildren(); - node.add(new DefaultMutableTreeNode(UiUtilities.WAITING_NODE_LABEL)); - } - - protected void createNodes(FilterableMutableTreeNode top, List<Experiment> experiments) - { - UploadClientSortingUtils.sortExperimentsByIdentifier(experiments); - for (Experiment experiment : experiments) - { - DefaultMutableTreeNode category = - new DefaultMutableTreeNode(Identifier.create(experiment), true); - category.add(new DefaultMutableTreeNode(UiUtilities.WAITING_NODE_LABEL)); - top.add(category); - } + node.add(UiUtilities.createWaitingNode()); } @Override protected void setDialogData() { - FilterableMutableTreeNode top = new FilterableMutableTreeNode("Experiments"); - - final List<String> projectIdentifiers = clientModel.getProjectIdentifiers(); - List<Experiment> experiments = - clientModel.getOpenBISService().listExperimentsHavingSamplesForProjects( - projectIdentifiers); - createNodes(top, experiments); + FilterableMutableTreeNode top = new FilterableMutableTreeNode(null); + FilterableMutableTreeNode experimentsTree = new FilterableMutableTreeNode(UiUtilities.ROOT_EXPERIMENTS); + experimentsTree.add(UiUtilities.createWaitingNode()); + top.add(experimentsTree); + FilterableMutableTreeNode samplesTree = new FilterableMutableTreeNode(UiUtilities.ROOT_SAMPLES); + samplesTree.add(UiUtilities.createWaitingNode()); + top.add(samplesTree); DefaultTreeModel treeModel = (DefaultTreeModel) tree.getModel(); treeModel.setRoot(top); diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/AsyncNodeAction.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/AsyncNodeAction.java index 1c613630ccc618c1b1f6c92be965bc038f16025f..60027e7e13a0f8306773b5b7d4e8d8fb8845b494 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/AsyncNodeAction.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/AsyncNodeAction.java @@ -16,11 +16,20 @@ package ch.systemsx.cisd.openbis.dss.client.api.gui; +import java.awt.BorderLayout; import java.awt.EventQueue; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; import java.util.Timer; import java.util.TimerTask; +import javax.swing.JButton; +import javax.swing.JLabel; import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JTextArea; import javax.swing.JTree; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; @@ -61,9 +70,9 @@ public abstract class AsyncNodeAction<T> implements IAsyncAction<T> } @Override - public void handleException(Throwable throwable) + public void handleException(final Throwable throwable) { - JOptionPane.showMessageDialog(tree, throwable.toString()); + UiUtilities.showException(tree, throwable); } public abstract void handleData(T data); diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/DataSetPickerDialog.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/DataSetPickerDialog.java index b1718c5f45aba66c6a75cbf9ca03a265f45cf613..52128a080073aedcc7afa6449d89ddd948ae8561 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/DataSetPickerDialog.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/DataSetPickerDialog.java @@ -19,14 +19,11 @@ package ch.systemsx.cisd.openbis.dss.client.api.gui; import java.util.List; import javax.swing.JFrame; -import javax.swing.event.TreeExpansionEvent; -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.ExpandVetoException; -import javax.swing.tree.TreeNode; import ch.systemsx.cisd.openbis.dss.client.api.gui.model.DataSetUploadClientModel; import ch.systemsx.cisd.openbis.dss.client.api.gui.model.Identifier; import ch.systemsx.cisd.openbis.dss.client.api.gui.model.SamplesDataSets; +import ch.systemsx.cisd.openbis.dss.client.api.gui.tree.FilterableMutableTreeNode; import ch.systemsx.cisd.openbis.dss.client.api.v1.DataSet; import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.NewDataSetDTO.DataSetOwnerType; import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Sample; @@ -48,26 +45,7 @@ public class DataSetPickerDialog extends AbstractTreeEntityPickerDialog } @Override - public void treeWillExpand(final TreeExpansionEvent event) throws ExpandVetoException - { - final DefaultMutableTreeNode node = - (DefaultMutableTreeNode) event.getPath().getLastPathComponent(); - // if top level, then finish - if (((TreeNode) node).getParent() == null) - { - return; - } - Object userObject = node.getUserObject(); - if (userObject instanceof Identifier == false) - { - return; - } - Identifier identifier = (Identifier) userObject; - expandNode(node, identifier); - } - - @Override - protected void expandNode(final DefaultMutableTreeNode node, Identifier identifier) + protected void expandNode(final FilterableMutableTreeNode node, Identifier identifier) { if (identifier.getOwnerType() != DataSetOwnerType.DATA_SET) { @@ -82,22 +60,21 @@ public class DataSetPickerDialog extends AbstractTreeEntityPickerDialog node.removeAllChildren(); if (dataSets.size() > 0) { - DefaultMutableTreeNode dataSetsNode = - new DefaultMutableTreeNode("Data Sets"); + FilterableMutableTreeNode dataSetsNode = + new FilterableMutableTreeNode(UiUtilities.DATA_SETS); node.add(dataSetsNode); for (DataSet dataSet : dataSets) { - dataSetsNode.add(new DefaultMutableTreeNode(Identifier + dataSetsNode.add(new FilterableMutableTreeNode(Identifier .create(dataSet))); } } for (Sample s : samplesDataSets.getSamples()) { - DefaultMutableTreeNode sampleNode = - new DefaultMutableTreeNode(Identifier.create(s)); - sampleNode.add(new DefaultMutableTreeNode( - UiUtilities.WAITING_NODE_LABEL)); + FilterableMutableTreeNode sampleNode = + new FilterableMutableTreeNode(Identifier.create(s)); + sampleNode.add(UiUtilities.createWaitingNode()); node.add(sampleNode); } } diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/DataSetUploadClient.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/DataSetUploadClient.java index ad234da86a5a5d7031ac41918f598b3488907267..eb12cd64169b341049c9076f04c15571120d02b9 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/DataSetUploadClient.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/DataSetUploadClient.java @@ -154,13 +154,7 @@ public class DataSetUploadClient extends AbstractSwingGUI prefs.flush(); } catch (Exception ex) { - final JFrame frame = new JFrame(TITLE); - String message = ex.getMessage(); - if (null == message || message.length() == 0) - { - message = ex.toString(); - } - JOptionPane.showMessageDialog(frame, message, "Error", JOptionPane.ERROR_MESSAGE); + UiUtilities.showException(null, ex); } } @@ -187,14 +181,7 @@ public class DataSetUploadClient extends AbstractSwingGUI newMe.show(); } catch (RuntimeException ex) { - final JFrame frame = new JFrame(TITLE); - frame.setVisible(true); - String message = ex.getMessage(); - if (null == message || message.length() == 0) - { - message = ex.toString(); - } - JOptionPane.showMessageDialog(frame, message, "Error", JOptionPane.ERROR_MESSAGE); + UiUtilities.showException(null, ex); System.exit(1); } } @@ -210,14 +197,7 @@ public class DataSetUploadClient extends AbstractSwingGUI newMe.show(); } catch (RuntimeException ex) { - final JFrame frame = new JFrame(TITLE); - frame.setVisible(true); - String message = ex.getMessage(); - if (null == message || message.length() == 0) - { - message = ex.toString(); - } - JOptionPane.showMessageDialog(frame, message, "Error", JOptionPane.ERROR_MESSAGE); + UiUtilities.showException(null, ex); System.exit(1); } } diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/SamplePickerDialog.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/SamplePickerDialog.java index 0f73a69bf2a045fa43c421fde576490a67d94a41..ade5d7ac7a95d389505fb627323a20137fcd8e8c 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/SamplePickerDialog.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/SamplePickerDialog.java @@ -19,10 +19,10 @@ package ch.systemsx.cisd.openbis.dss.client.api.gui; import java.util.List; import javax.swing.JFrame; -import javax.swing.tree.DefaultMutableTreeNode; import ch.systemsx.cisd.openbis.dss.client.api.gui.model.DataSetUploadClientModel; import ch.systemsx.cisd.openbis.dss.client.api.gui.model.Identifier; +import ch.systemsx.cisd.openbis.dss.client.api.gui.tree.FilterableMutableTreeNode; import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.NewDataSetDTO.DataSetOwnerType; import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Sample; @@ -44,7 +44,7 @@ public class SamplePickerDialog extends AbstractTreeEntityPickerDialog } @Override - protected void expandNode(final DefaultMutableTreeNode node, Identifier identifier) + protected void expandNode(final FilterableMutableTreeNode node, Identifier identifier) { AsyncNodeAction<List<Sample>> action = new AsyncNodeAction<List<Sample>>(tree, node, scheduler) @@ -55,10 +55,9 @@ public class SamplePickerDialog extends AbstractTreeEntityPickerDialog node.removeAllChildren(); for (Sample s : samples) { - DefaultMutableTreeNode sampleNode = - new DefaultMutableTreeNode(Identifier.create(s)); - sampleNode.add(new DefaultMutableTreeNode( - UiUtilities.WAITING_NODE_LABEL)); + FilterableMutableTreeNode sampleNode = + new FilterableMutableTreeNode(Identifier.create(s)); + sampleNode.add(UiUtilities.createWaitingNode()); node.add(sampleNode); } } diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/UiUtilities.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/UiUtilities.java index d4696e15d1aec55423cc6d9d8f1b9109856219c8..03cfa90eab2fcbb509d36692c89b22fe8a1de4c5 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/UiUtilities.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/UiUtilities.java @@ -16,11 +16,26 @@ package ch.systemsx.cisd.openbis.dss.client.api.gui; +import java.awt.BorderLayout; import java.awt.Color; +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.util.regex.Pattern; +import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JTextArea; +import javax.swing.SwingUtilities; +import ch.systemsx.cisd.openbis.dss.client.api.gui.model.Identifier; +import ch.systemsx.cisd.openbis.dss.client.api.gui.tree.FilterableMutableTreeNode; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.NewDataSetDTO.DataSetOwnerType; import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.validation.ValidationError; /** @@ -50,5 +65,74 @@ public class UiUtilities } } - static final String WAITING_NODE_LABEL = "Loading data ..."; + static final String ROOT_SAMPLES = "Samples"; + static final String ROOT_EXPERIMENTS = "Experiments"; + static final String DATA_SETS = "Data Sets"; + private static final String WAITING_NODE_LABEL = "Loading data ..."; + + private static final String[] SPECIAL_NODES = {ROOT_EXPERIMENTS, ROOT_SAMPLES, DATA_SETS, WAITING_NODE_LABEL}; + + public static boolean isMatchingNode(Object node, Pattern pattern) + { + for (String specialNode : SPECIAL_NODES) + { + if (equals(specialNode, node)) + { + return true; + } + } + if (node instanceof FilterableMutableTreeNode) + { + Object userObject = ((FilterableMutableTreeNode) node).getUserObject(); + if (userObject instanceof Identifier) + { + if (((Identifier) userObject).getOwnerType() == DataSetOwnerType.DATA_SET) + { + return true; + } + } + } + return pattern.matcher(node.toString()).find(); + } + + private static boolean equals(String label, Object object) + { + return object.toString().equals(label); + } + + public static FilterableMutableTreeNode createWaitingNode() + { + return new FilterableMutableTreeNode(UiUtilities.WAITING_NODE_LABEL); + } + + public static void showException(Component parentComponent, final Throwable throwable) + { + showMessageAndException(parentComponent, throwable, throwable.toString(), "Error"); + } + + public static void showMessageAndException(Component parentComponent, final Throwable throwable, String message, String title) + { + final JPanel panel = new JPanel(new BorderLayout(20, 5)); + panel.add(new JLabel(message), BorderLayout.WEST); + JButton button = new JButton("Show Details"); + button.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + panel.removeAll(); + JTextArea textArea = new JTextArea(20, 20); + textArea.setEditable(false); + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + throwable.printStackTrace(new PrintStream(byteArrayOutputStream, true)); + textArea.setText(byteArrayOutputStream.toString()); + panel.add(textArea, BorderLayout.CENTER); + panel.validate(); + SwingUtilities.getWindowAncestor(panel).pack(); + } + }); + panel.add(button, BorderLayout.EAST); + JOptionPane.showMessageDialog(parentComponent, panel, title, JOptionPane.ERROR_MESSAGE); + } + } diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/model/DataSetUploadClientModel.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/model/DataSetUploadClientModel.java index dfcdd86a641cf9bc45772bb03224c816257a2a99..f02564db000ffc35d046038510a3fd2abfa37d69 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/model/DataSetUploadClientModel.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/model/DataSetUploadClientModel.java @@ -23,10 +23,13 @@ import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.fetchoptions.SampleFetchOptions; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.search.SampleSearchCriteria; import ch.systemsx.cisd.base.namedthread.NamingThreadPoolExecutor; import ch.systemsx.cisd.common.exceptions.UserFailureException; import ch.systemsx.cisd.common.io.TransmissionSpeedCalculator; @@ -34,6 +37,7 @@ import ch.systemsx.cisd.common.utilities.ITimeProvider; import ch.systemsx.cisd.openbis.dss.client.api.gui.model.DataSetUploadClientModel.NewDataSetInfo.Status; import ch.systemsx.cisd.openbis.dss.client.api.v1.DataSet; import ch.systemsx.cisd.openbis.dss.client.api.v1.IOpenbisServiceFacade; +import ch.systemsx.cisd.openbis.dss.client.api.v3.IOpenbisServiceFacadeV3; import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.FileInfoDssDTO; import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.NewDataSetDTO; import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.NewDataSetDTOBuilder; @@ -42,6 +46,7 @@ import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.validation.ValidationE import ch.systemsx.cisd.openbis.generic.shared.ResourceNames; import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSetType; import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSetTypeFilter; +import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.EntityRegistrationDetails; import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Experiment; import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.NewVocabularyTerm; import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Project; @@ -69,6 +74,8 @@ public class DataSetUploadClientModel private final IOpenbisServiceFacade openBISService; + private final IOpenbisServiceFacadeV3 serviceFacadeV3; + private final ITimeProvider timeProvider; private List<DataSetType> dataSetTypes; @@ -104,6 +111,7 @@ public class DataSetUploadClientModel public DataSetUploadClientModel(DssCommunicationState commState, ITimeProvider timeProvider, IUserNotifier userNotifier) { this.openBISService = commState.getOpenBISService(); + serviceFacadeV3 = commState.getServiceFacadeV3(); this.timeProvider = timeProvider; this.userNotifier = userNotifier; @@ -327,41 +335,108 @@ public class DataSetUploadClientModel { return !openBISService.getSamples(Arrays.asList(identifier)).isEmpty(); } - - public void listSamples(final Identifier identifier, - final IAsyncAction<List<Sample>> action) + + public void listExperiments(IAsyncAction<List<Experiment>> action) { - execute(new Runnable() + doAsync(new Callable<List<Experiment>>() { @Override - public void run() + public List<Experiment> call() throws Exception { - try + return getOpenBISService().listExperimentsHavingSamplesForProjects( + projectIdentifiers); + } + }, action); + } + + public void listSamplesWithNoExperiments(IAsyncAction<List<Sample>> action) + { + doAsync(new Callable<List<Sample>>() + { + @Override + public List<Sample> call() throws Exception + { + SampleSearchCriteria criteria = new SampleSearchCriteria(); + criteria.withoutExperiment(); + criteria.withType().withListable().setListable(true); + List<Sample> result = new ArrayList<>(); + for (ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.Sample sample : + serviceFacadeV3.searchSamples(criteria, new SampleFetchOptions()).getObjects()) { - List<Sample> samples = new ArrayList<Sample>(); - String permId = identifier.getPermId(); - switch (identifier.getOwnerType()) - { - case EXPERIMENT: - loadListableSamples(samples, permId); - break; - case SAMPLE: - loadSamplesLinkedToAnExperiment(samples, permId); - break; - default: - } - UploadClientSortingUtils.sortSamplesByIdentifier(samples); - action.performAction(samples); - } catch (Throwable throwable) + Sample.SampleInitializer initializer = new Sample.SampleInitializer(); + initializer.setIdentifier(sample.getIdentifier().getIdentifier()); + initializer.setPermId(sample.getPermId().getPermId()); + initializer.setId(-1l); // dummy value for validation + initializer.setCode(sample.getCode()); + initializer.setSampleTypeCode("dummy"); // dummy value for validation + initializer.setSampleTypeId(-1l); // dummy value for validation + EntityRegistrationDetails.EntityRegistrationDetailsInitializer detailsInitializer + = new EntityRegistrationDetails.EntityRegistrationDetailsInitializer(); + initializer.setRegistrationDetails(new EntityRegistrationDetails(detailsInitializer)); + result.add(new Sample(initializer)); + } + return result; + } + }, action); + } + + public void listSamples(final Identifier identifier, final IAsyncAction<List<Sample>> action) + { + doAsync(new Callable<List<Sample>>() + { + @Override + public List<Sample> call() throws Exception + { + List<Sample> samples = new ArrayList<Sample>(); + String permId = identifier.getPermId(); + switch (identifier.getOwnerType()) { - action.handleException(throwable); + case EXPERIMENT: + loadListableSamples(samples, permId); + break; + case SAMPLE: + loadSamplesLinkedToAnExperiment(samples, permId); + break; + default: } + UploadClientSortingUtils.sortSamplesByIdentifier(samples); + return samples; } - }); + }, action); } public void listSamplesDataSets(final Identifier identifier, final IAsyncAction<SamplesDataSets> action) { + doAsync(new Callable<SamplesDataSets>() + { + @Override + public SamplesDataSets call() throws Exception + { + List<Sample> samples = new ArrayList<Sample>(); + List<DataSet> dataSets = new ArrayList<DataSet>(); + String permId = identifier.getPermId(); + switch (identifier.getOwnerType()) + { + case EXPERIMENT: + loadListableSamples(samples, permId); + dataSets.addAll(openBISService.listDataSetsForExperiment(permId)); + break; + case SAMPLE: + loadSamplesLinkedToAnExperiment(samples, permId); + dataSets.addAll(openBISService.listDataSetsForSample(permId)); + break; + default: + } + UploadClientSortingUtils.sortSamplesByIdentifier(samples); + UploadClientSortingUtils.sortDataSetsByCode(dataSets); + return new SamplesDataSets(samples, dataSets); + } + }, action); + } + + private <T> void doAsync(final Callable<T> action, final IAsyncAction<T> subsequentAction) + { + execute(new Runnable() { @Override @@ -369,27 +444,10 @@ public class DataSetUploadClientModel { try { - List<Sample> samples = new ArrayList<Sample>(); - List<DataSet> dataSets = new ArrayList<DataSet>(); - String permId = identifier.getPermId(); - switch (identifier.getOwnerType()) - { - case EXPERIMENT: - loadListableSamples(samples, permId); - dataSets.addAll(openBISService.listDataSetsForExperiment(permId)); - break; - case SAMPLE: - loadSamplesLinkedToAnExperiment(samples, permId); - dataSets.addAll(openBISService.listDataSetsForSample(permId)); - break; - default: - } - UploadClientSortingUtils.sortSamplesByIdentifier(samples); - UploadClientSortingUtils.sortDataSetsByCode(dataSets); - action.performAction(new SamplesDataSets(samples, dataSets)); + subsequentAction.performAction(action.call()); } catch (Throwable throwable) { - action.handleException(throwable); + subsequentAction.handleException(throwable); } } }); diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/model/DssCommunicationState.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/model/DssCommunicationState.java index b7eb5db0614996eabc33daa58c5c52eb5e79c19a..b57f568928125885e8c1a8f2276e8d74f20e9e5d 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/model/DssCommunicationState.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/model/DssCommunicationState.java @@ -23,11 +23,15 @@ import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException; import ch.systemsx.cisd.common.exceptions.UserFailureException; import ch.systemsx.cisd.openbis.dss.client.api.v1.IOpenbisServiceFacade; import ch.systemsx.cisd.openbis.dss.client.api.v1.OpenbisServiceFacadeFactory; +import ch.systemsx.cisd.openbis.dss.client.api.v3.IOpenbisServiceFacadeV3; +import ch.systemsx.cisd.openbis.dss.client.api.v3.OpenbisServiceFacadeV3; public class DssCommunicationState { private final IOpenbisServiceFacade openBISService; + private final IOpenbisServiceFacadeV3 serviceFacadeV3; + private final boolean logoutOnClose; private static final long CONNECTION_TIMEOUT_MILLIS = 60 * DateUtils.MILLIS_PER_SECOND; @@ -48,28 +52,27 @@ public class DssCommunicationState { case 2: String sessionToken = args[1]; - openBISService = - OpenbisServiceFacadeFactory.tryCreate(sessionToken, openBisUrl, - CONNECTION_TIMEOUT_MILLIS); - if (null == openBISService) + serviceFacadeV3 = OpenbisServiceFacadeV3.tryCreate(sessionToken, openBisUrl, CONNECTION_TIMEOUT_MILLIS); + if (null == serviceFacadeV3) { throw new ConfigurationFailureException( "The openBIS File Upload Client was improperly configured -- the session token is not valid. Please talk to the openBIS administrator."); } + openBISService = OpenbisServiceFacadeFactory.tryCreate(sessionToken, openBisUrl, CONNECTION_TIMEOUT_MILLIS); // Don't logout -- the user wants to keep his/her session token alive. logoutOnClose = false; break; default: String userName = args[1]; String passwd = args[2]; - openBISService = - OpenbisServiceFacadeFactory.tryCreate(userName, passwd, openBisUrl, - CONNECTION_TIMEOUT_MILLIS); - if (null == openBISService) + serviceFacadeV3 = OpenbisServiceFacadeV3.tryCreate(userName, passwd, openBisUrl, CONNECTION_TIMEOUT_MILLIS); + if (null == serviceFacadeV3) { throw new ConfigurationFailureException( "The user name / password combination is incorrect."); } + String token = serviceFacadeV3.getSessionToken(); + openBISService = OpenbisServiceFacadeFactory.tryCreate(token, openBisUrl, CONNECTION_TIMEOUT_MILLIS); // Do logout on close logoutOnClose = true; } @@ -80,6 +83,11 @@ public class DssCommunicationState return openBISService; } + public IOpenbisServiceFacadeV3 getServiceFacadeV3() + { + return serviceFacadeV3; + } + public boolean isLogoutOnClose() { return logoutOnClose; diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/tree/FilterableMutableTreeNode.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/tree/FilterableMutableTreeNode.java index 5d4219b75102996901a94a6f336fa1809493ee4e..d75b50216882d03a721390ec4da699ae3605edb5 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/tree/FilterableMutableTreeNode.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/tree/FilterableMutableTreeNode.java @@ -24,6 +24,8 @@ import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.MutableTreeNode; import javax.swing.tree.TreeNode; +import ch.systemsx.cisd.openbis.dss.client.api.gui.UiUtilities; + /** * @author Pawel Glyzewski */ @@ -65,7 +67,7 @@ public class FilterableMutableTreeNode extends DefaultMutableTreeNode while (enumeration.hasMoreElements()) { final Object tmp = enumeration.nextElement(); - if (pattern.matcher(tmp.toString()).find()) + if (UiUtilities.isMatchingNode(tmp, pattern)) { next = tmp; break; @@ -95,6 +97,7 @@ public class FilterableMutableTreeNode extends DefaultMutableTreeNode private synchronized void setPattern(Pattern pattern) { this.pattern = pattern; + filter(pattern); } private synchronized ArrayList<Object> getFiltered() @@ -120,11 +123,13 @@ public class FilterableMutableTreeNode extends DefaultMutableTreeNode pattern = Pattern.compile(".*"); } setPattern(pattern); - - filter(pattern); + for (int i = 0, n = getChildCount(); i < n; i++) + { + ((FilterableMutableTreeNode) getChildAt(i)).setPattern(pattern); + } } - public void filter(@SuppressWarnings("hiding") Pattern pattern) + private void filter(@SuppressWarnings("hiding") Pattern pattern) { @SuppressWarnings("hiding") ArrayList<Object> filtered = new ArrayList<Object>(); @@ -133,14 +138,14 @@ public class FilterableMutableTreeNode extends DefaultMutableTreeNode while (enumeration.hasMoreElements()) { Object o = enumeration.nextElement(); - if (pattern.matcher(o.toString()).find()) + if (UiUtilities.isMatchingNode(o, pattern)) { filtered.add(o); } } setFiltered(filtered); } - + @Override public TreeNode getChildAt(int childIndex) { @@ -190,11 +195,25 @@ public class FilterableMutableTreeNode extends DefaultMutableTreeNode { return new FilteredEnumerationWrapper(super.children(), getPattern()); } - + @Override public void add(MutableTreeNode o) { super.add(o); + if (o instanceof FilterableMutableTreeNode) + { + FilterableMutableTreeNode filterableMutableTreeNode = (FilterableMutableTreeNode) o; + filterableMutableTreeNode.setPattern(getPattern()); + } + filter(getPattern()); + } + + @Override + public void removeAllChildren() + { + super.removeAllChildren(); filter(getPattern()); } + + } diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v3/IOpenbisServiceFacadeV3.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v3/IOpenbisServiceFacadeV3.java new file mode 100644 index 0000000000000000000000000000000000000000..394d0df88ffeaee455105e08cac8e2810f19a043 --- /dev/null +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v3/IOpenbisServiceFacadeV3.java @@ -0,0 +1,35 @@ +/* + * Copyright 2017 ETH Zuerich, SIS + * + * 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.dss.client.api.v3; + +import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.SearchResult; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.Sample; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.fetchoptions.SampleFetchOptions; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.search.SampleSearchCriteria; + +/** + * + * + * @author Franz-Josef Elmer + */ +public interface IOpenbisServiceFacadeV3 +{ + public String getSessionToken(); + + public SearchResult<Sample> searchSamples(SampleSearchCriteria searchCriteria, SampleFetchOptions fetchOptions); + +} diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v3/OpenbisServiceFacadeV3.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v3/OpenbisServiceFacadeV3.java new file mode 100644 index 0000000000000000000000000000000000000000..4b25d21161a0652d6b8e500ea5274f498b376481 --- /dev/null +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v3/OpenbisServiceFacadeV3.java @@ -0,0 +1,94 @@ +/* + * Copyright 2017 ETH Zuerich, SIS + * + * 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.dss.client.api.v3; + +import ch.ethz.sis.openbis.generic.asapi.v3.IApplicationServerApi; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.SearchResult; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.Sample; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.fetchoptions.SampleFetchOptions; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.search.SampleSearchCriteria; +import ch.systemsx.cisd.common.api.retry.RetryCaller; +import ch.systemsx.cisd.common.api.retry.RetryProxyFactory; +import ch.systemsx.cisd.openbis.common.api.client.ServiceFinder; + +/** + * @author Franz-Josef Elmer + */ +public class OpenbisServiceFacadeV3 implements IOpenbisServiceFacadeV3 +{ + public static IOpenbisServiceFacadeV3 tryCreate(final String username, final String password, + final String openbisUrl, final long timeoutInMillis) + { + RetryCaller<IOpenbisServiceFacadeV3, RuntimeException> caller = + new RetryCaller<IOpenbisServiceFacadeV3, RuntimeException>() + { + @Override + protected IOpenbisServiceFacadeV3 call() + { + IApplicationServerApi service = createService(openbisUrl, timeoutInMillis); + String sessionToken = service.login(username, password); + OpenbisServiceFacadeV3 facade = new OpenbisServiceFacadeV3(sessionToken, service); + return RetryProxyFactory.createProxy(facade); + } + }; + return caller.callWithRetry(); + } + + public static IOpenbisServiceFacadeV3 tryCreate(final String sessionToken, + final String openbisUrl, final long timeoutInMillis) + { + RetryCaller<IOpenbisServiceFacadeV3, RuntimeException> caller = + new RetryCaller<IOpenbisServiceFacadeV3, RuntimeException>() + { + @Override + protected IOpenbisServiceFacadeV3 call() + { + IApplicationServerApi service = createService(openbisUrl, timeoutInMillis); + OpenbisServiceFacadeV3 facade = new OpenbisServiceFacadeV3(sessionToken, service); + return RetryProxyFactory.createProxy(facade); + } + }; + return caller.callWithRetry(); + } + + private static IApplicationServerApi createService(String openbisUrl, long timeoutInMillis) + { + ServiceFinder serviceFinder = new ServiceFinder("openbis", IApplicationServerApi.SERVICE_URL); + return serviceFinder.createService(IApplicationServerApi.class, openbisUrl, timeoutInMillis); + } + + private String sessionToken; + private IApplicationServerApi service; + + private OpenbisServiceFacadeV3(String sessionToken, IApplicationServerApi service) + { + this.sessionToken = sessionToken; + this.service = service; + } + + @Override + public String getSessionToken() + { + return sessionToken; + } + + @Override + public SearchResult<Sample> searchSamples(SampleSearchCriteria searchCriteria, SampleFetchOptions fetchOptions) + { + return service.searchSamples(sessionToken, searchCriteria, fetchOptions); + } +}