diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/DataSetMetadataPanel.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/DataSetMetadataPanel.java index d0fefe37d8a0298791c390b784c6b399f54c406a..a9be0c569a79a55e38de8f052cb7d6101387fbbe 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/DataSetMetadataPanel.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/DataSetMetadataPanel.java @@ -144,7 +144,11 @@ public class DataSetMetadataPanel extends JPanel implements Observer private final JLabel ownerIdLabel; - private final JTextField ownerIdText; + private final JTextField sampleIdText; + + private final ExperimentPickerPanel experimentPicker; + + private final JPanel ownerIdPanel; private final ButtonGroup ownerButtonGroup; @@ -186,13 +190,20 @@ public class DataSetMetadataPanel extends JPanel implements Observer // Initialize the fields in the gui ownerIdLabel = new JLabel("Owner:", JLabel.TRAILING); - ownerIdText = new JTextField(); + sampleIdText = new JTextField(); + experimentPicker = new ExperimentPickerPanel(mainWindow, clientModel.getExperiments()); + + ownerIdPanel = new JPanel(new CardLayout()); + ownerButtonGroup = new ButtonGroup(); experimentButton = new JRadioButton("Experiment"); sampleButton = new JRadioButton("Sample"); ownerButtonGroup.add(experimentButton); ownerButtonGroup.add(sampleButton); + ownerIdPanel.add(experimentPicker, experimentButton.getText()); + ownerIdPanel.add(sampleIdText, sampleButton.getText()); + dataSetTypeComboBox = new JComboBox(); dataSetTypePanel = new JPanel(); @@ -218,7 +229,8 @@ public class DataSetMetadataPanel extends JPanel implements Observer { if (null == newDataSetInfo) { - ownerIdText.setText(EMPTY_FILE_SELECTION); + sampleIdText.setText(EMPTY_FILE_SELECTION); + experimentPicker.setText(EMPTY_FILE_SELECTION); updateFileLabel(); disableAllWidgets(); return; @@ -227,14 +239,15 @@ public class DataSetMetadataPanel extends JPanel implements Observer enableAllWidgets(); NewDataSetDTOBuilder builder = newDataSetInfo.getNewDataSetBuilder(); - ownerIdText.setText(builder.getDataSetOwnerIdentifier()); switch (builder.getDataSetOwnerType()) { case EXPERIMENT: ownerButtonGroup.setSelected(experimentButton.getModel(), true); + experimentPicker.setText(builder.getDataSetOwnerIdentifier()); break; case SAMPLE: ownerButtonGroup.setSelected(sampleButton.getModel(), true); + sampleIdText.setText(builder.getDataSetOwnerIdentifier()); break; } @@ -274,10 +287,12 @@ public class DataSetMetadataPanel extends JPanel implements Observer private ArrayList<JComponent> getAllEditableWidgets() { ArrayList<JComponent> editableWidgets = new ArrayList<JComponent>(); - editableWidgets.add(ownerIdText); + editableWidgets.add(sampleIdText); + editableWidgets.add(experimentPicker); editableWidgets.add(dataSetFileButton); editableWidgets.add(experimentButton); editableWidgets.add(sampleButton); + editableWidgets.add(experimentPicker); editableWidgets.add(dataSetTypeComboBox); for (DataSetPropertiesPanel panel : propertiesPanels.values()) @@ -367,22 +382,44 @@ public class DataSetMetadataPanel extends JPanel implements Observer // The owner row ownerIdLabel.setPreferredSize(new Dimension(LABEL_WIDTH, BUTTON_HEIGHT)); - ownerIdText.setPreferredSize(new Dimension(BUTTON_WIDTH, BUTTON_HEIGHT)); - ownerIdText.addActionListener(new ActionListener() + sampleIdText.setPreferredSize(new Dimension(BUTTON_WIDTH, BUTTON_HEIGHT)); + sampleIdText.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { - setOwnerId(ownerIdText.getText()); + setOwnerId(sampleIdText.getText()); } }); - ownerIdText.addFocusListener(new FocusListener() + sampleIdText.addFocusListener(new FocusListener() { public void focusLost(FocusEvent e) { - setOwnerId(ownerIdText.getText()); + setOwnerId(sampleIdText.getText()); + } + + public void focusGained(FocusEvent e) + { + // Do nothing + } + }); + + experimentPicker.setPreferredSize(new Dimension(BUTTON_WIDTH, BUTTON_HEIGHT)); + experimentPicker.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + setOwnerId(experimentPicker.getText()); + } + + }); + experimentPicker.addFocusListener(new FocusListener() + { + public void focusLost(FocusEvent e) + { + setOwnerId(experimentPicker.getText()); } public void focusGained(FocusEvent e) @@ -396,7 +433,9 @@ public class DataSetMetadataPanel extends JPanel implements Observer public void actionPerformed(ActionEvent e) { setOwnerType(DataSetOwnerType.EXPERIMENT); - + setOwnerId(experimentPicker.getText()); + CardLayout cardLayout = (CardLayout) ownerIdPanel.getLayout(); + cardLayout.show(ownerIdPanel, experimentButton.getText()); } }); experimentButton.setSelected(true); @@ -405,10 +444,13 @@ public class DataSetMetadataPanel extends JPanel implements Observer public void actionPerformed(ActionEvent e) { setOwnerType(DataSetOwnerType.SAMPLE); + setOwnerId(sampleIdText.getText()); + CardLayout cardLayout = (CardLayout) ownerIdPanel.getLayout(); + cardLayout.show(ownerIdPanel, sampleButton.getText()); } }); - addRow(2, ownerIdLabel, ownerIdText, ownerButtonGroup); + addRow(2, ownerIdLabel, ownerIdPanel, ownerButtonGroup); // The data set type row JLabel label = new JLabel("Data Set Type:", JLabel.TRAILING); @@ -628,7 +670,7 @@ public class DataSetMetadataPanel extends JPanel implements Observer public synchronized void syncErrors() { // Clear all errors first - clearError(ownerIdLabel, ownerIdText, null); + clearError(ownerIdLabel, ownerIdPanel, null); clearError(dataSetFileLabel, dataSetFileComboBox, validationErrors); List<ValidationError> errors = newDataSetInfo.getValidationErrors(); @@ -637,7 +679,7 @@ public class DataSetMetadataPanel extends JPanel implements Observer switch (error.getTarget()) { case DATA_SET_OWNER: - displayError(ownerIdLabel, ownerIdText, validationErrors, error); + displayError(ownerIdLabel, ownerIdPanel, validationErrors, error); break; case DATA_SET_TYPE: diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/DataSetUploadClientModel.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/DataSetUploadClientModel.java index 8a27b1bb821ebb0feb82a21f967d662bd5d5ff89..8271f79d3d1a31c8de9bbd75abc65187d707f7d5 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/DataSetUploadClientModel.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/DataSetUploadClientModel.java @@ -40,11 +40,14 @@ import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.NewDataSetMetadataDTO; import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.validation.ValidationError; import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.ControlledVocabularyPropertyType.VocabularyTerm; import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSetType; +import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Experiment; +import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Project; import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.PropertyType; import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.PropertyTypeGroup; import ch.systemsx.cisd.openbis.generic.shared.basic.TechId; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataTypeCode; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Vocabulary; +import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifier; import ch.systemsx.cisd.openbis.generic.shared.util.SimplePropertyValidator; /** @@ -84,12 +87,25 @@ public class DataSetUploadClientModel private HashMap<Vocabulary, List<VocabularyTerm>> vocabularyTerms; + private List<Project> projects; + + private List<Experiment> experiments; + public DataSetUploadClientModel(DssCommunicationState commState, ITimeProvider timeProvider) { this.openBISService = commState.getOpenBISService(); this.timeProvider = timeProvider; dataSetTypes = openBISService.listDataSetTypes(); vocabularyTerms = openBISService.getVocabularyTermsMap(); + projects = openBISService.listProjects(); + + List<String> projectIds = new ArrayList<String>(); + for (Project project : projects) + { + ProjectIdentifier id = new ProjectIdentifier(project.getSpaceCode(), project.getCode()); + projectIds.add(id.toString()); + } + experiments = openBISService.listExperimentsForProjects(projectIds); } /** @@ -513,8 +529,8 @@ public class DataSetUploadClientModel public void addUnofficialVocabularyTerm(Vocabulary vocabulary, String code, String label, String description, Long previousTermOrdinal) { - openBISService.addAdHocVocabularyTerm(TechId.create(vocabulary), code, label, - description, previousTermOrdinal); + openBISService.addAdHocVocabularyTerm(TechId.create(vocabulary), code, label, description, + previousTermOrdinal); dataSetTypes = openBISService.listDataSetTypes(); vocabularyTerms = openBISService.getVocabularyTermsMap(); @@ -538,4 +554,9 @@ public class DataSetUploadClientModel { return vocabularyTerms.get(vocabulary); } + + public List<Experiment> getExperiments() + { + return experiments; + } } diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/ExperimentPickerDialog.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/ExperimentPickerDialog.java new file mode 100644 index 0000000000000000000000000000000000000000..14b30da99c6181d26f9bf397285f056282e3ed5a --- /dev/null +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/ExperimentPickerDialog.java @@ -0,0 +1,202 @@ +/* + * Copyright 2011 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.dss.client.api.gui; + +import java.awt.Dimension; +import java.awt.Point; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JOptionPane; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.JTextField; +import javax.swing.ListSelectionModel; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.table.JTableHeader; + +import ch.systemsx.cisd.openbis.dss.client.api.gui.table.SortButtonRenderer; +import ch.systemsx.cisd.openbis.dss.client.api.gui.table.SortableFilterableTableModel; +import ch.systemsx.cisd.openbis.dss.client.api.gui.table.TableHeaderMouseListener; +import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Experiment; +import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifier; +import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifierFactory; + +/** + * @author Pawel Glyzewski + */ +public class ExperimentPickerDialog extends JDialog +{ + private static final long serialVersionUID = 6688336042860619854L; + + private static String[] HEADERS = new String[] + { "Space code", "Project code", "Experiment code", "Experiment identifier" }; + + private final JFrame mainWindow; + + private final JTable table; + + final JTextField filterField; + + private final JOptionPane optionPane; + + public ExperimentPickerDialog(JFrame mainWindow, List<Experiment> experiments) + { + super(mainWindow, "Pick an experiment", true); + + this.mainWindow = mainWindow; + table = createTable(prepareData(experiments)); + filterField = createFilterField(table); + optionPane = createOptionPane(filterField, table, this); + + this.setContentPane(optionPane); + } + + private static JOptionPane createOptionPane(JTextField filterField, final JTable table, + final JDialog parent) + { + final JScrollPane scrollPane = new JScrollPane(table); + + Object[] objects = new Object[] + { "Filter experiments: ", filterField, "Select Experiment:", scrollPane }; + final JOptionPane optionPane = + new JOptionPane(objects, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION); + optionPane.addPropertyChangeListener(new PropertyChangeListener() + { + public void propertyChange(PropertyChangeEvent evt) + { + if (evt.getPropertyName().equals(JOptionPane.VALUE_PROPERTY) + && evt.getNewValue() != null) + { + if (((Integer) evt.getNewValue()).intValue() == JOptionPane.OK_OPTION + && table.getSelectedRow() == -1) + { + JOptionPane.showMessageDialog(parent, + "Experiment needs to be selected!", "No experiment selected!", + JOptionPane.WARNING_MESSAGE); + optionPane.setValue(optionPane.getInitialValue()); + } else + { + parent.setVisible(false); + } + } + } + }); + return optionPane; + } + + private static List<String[]> prepareData(List<Experiment> experiments) + { + List<String[]> data = new ArrayList<String[]>(experiments.size()); + for (Experiment experiment : experiments) + { + ExperimentIdentifier expId = + ExperimentIdentifierFactory.parse(experiment.getIdentifier()); + + data.add(new String[] + { expId.getSpaceCode(), expId.getProjectCode(), expId.getExperimentCode(), + experiment.getIdentifier() }); + } + + return data; + } + + private static JTable createTable(List<String[]> data) + { + final JTable table = new JTable(new SortableFilterableTableModel(data, HEADERS)); + + table.setPreferredScrollableViewportSize(new Dimension(500, 150)); + table.setFillsViewportHeight(true); + table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + + JTableHeader header = table.getTableHeader(); + for (int i = 0; i < table.getColumnModel().getColumnCount() - 1; i++) + { + table.getColumnModel().getColumn(i).setPreferredWidth(110); + } + table.getColumnModel().getColumn(3).setPreferredWidth(200); + + header.addMouseListener(new TableHeaderMouseListener((SortableFilterableTableModel) table + .getModel())); + header.setDefaultRenderer(new SortButtonRenderer()); + + return table; + } + + private static JTextField createFilterField(final JTable table) + { + final JTextField filterField = new JTextField(); + filterField.setEditable(true); + filterField.getDocument().addDocumentListener(new DocumentListener() + { + public void removeUpdate(DocumentEvent e) + { + SortableFilterableTableModel model = + (SortableFilterableTableModel) table.getModel(); + model.filter(filterField.getText()); + } + + public void insertUpdate(DocumentEvent e) + { + SortableFilterableTableModel model = + (SortableFilterableTableModel) table.getModel(); + model.filter(filterField.getText()); + } + + public void changedUpdate(DocumentEvent e) + { + SortableFilterableTableModel model = + (SortableFilterableTableModel) table.getModel(); + model.filter(filterField.getText()); + } + }); + + return filterField; + } + + public String pickExperiment() + { + this.pack(); + + int height = this.getHeight() > 500 ? 500 : this.getHeight(); + int width = this.getWidth() > 600 ? 600 : this.getWidth(); + this.setSize(width, height); + + Point mwLocation = mainWindow.getLocationOnScreen(); + int x = mwLocation.x + (mainWindow.getWidth() / 2) - (this.getWidth() / 2); + int y = mwLocation.y + (mainWindow.getHeight() / 2) - (this.getHeight() / 2); + + this.setLocation(x > 0 ? x : 0, y > 0 ? y : 0); + + this.setVisible(true); + + Object value = optionPane.getValue(); + optionPane.setValue(optionPane.getInitialValue()); + if (value == null || ((Integer) value).intValue() == JOptionPane.CANCEL_OPTION) + { + return null; + } else + { + return table.getValueAt(table.getSelectedRow(), 3).toString(); + } + } +} diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/ExperimentPickerPanel.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/ExperimentPickerPanel.java new file mode 100644 index 0000000000000000000000000000000000000000..41f8c71b5b2294f724eff6730bb839ef5ede16ee --- /dev/null +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/ExperimentPickerPanel.java @@ -0,0 +1,98 @@ +/* + * Copyright 2011 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.dss.client.api.gui; + +import java.awt.BorderLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.FocusListener; +import java.util.List; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTextField; + +import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Experiment; + +/** + * @author Pawel Glyzewski + */ +public class ExperimentPickerPanel extends JPanel +{ + private static final long serialVersionUID = -8093481985680332715L; + + private final JTextField textField = new JTextField(); + + private final JButton button = new JButton("..."); + + private final ExperimentPickerDialog dialog; + + public ExperimentPickerPanel(final JFrame mainWindow, final List<Experiment> experiments) + { + super(new BorderLayout()); + + dialog = new ExperimentPickerDialog(mainWindow, experiments); + + button.setMargin(new Insets(button.getMargin().top, 2, button.getMargin().bottom, 2)); + + button.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + String experimentId = dialog.pickExperiment(); + if (experimentId != null) + { + textField.setText(experimentId); + } + } + }); + + add(textField, BorderLayout.CENTER); + add(button, BorderLayout.EAST); + } + + public String getText() + { + return textField.getText(); + } + + public void setText(String text) + { + textField.setText(text); + } + + public void addActionListener(ActionListener actionListener) + { + textField.addActionListener(actionListener); + } + + @Override + public void addFocusListener(FocusListener focusListener) + { + textField.addFocusListener(focusListener); + } + + @Override + public void setEnabled(boolean enabled) + { + textField.setEditable(enabled); + textField.setEnabled(enabled); + button.setEnabled(enabled); + } +} diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/table/BevelArrowIcon.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/table/BevelArrowIcon.java new file mode 100644 index 0000000000000000000000000000000000000000..2cf524f5057344f47eb06ea7e823f55fa8f0da57 --- /dev/null +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/table/BevelArrowIcon.java @@ -0,0 +1,249 @@ +/* + * Copyright 2011 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.dss.client.api.gui.table; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; + +import javax.swing.Icon; +import javax.swing.UIManager; + +/** + * @author Pawel Glyzewski + */ +public class BevelArrowIcon implements Icon +{ + + /** Constant indicating that the arrow is pointing up. */ + public static final int UP = 0; + + /** Constant indicating that the arrow is pointing down. */ + public static final int DOWN = 1; + + /** The default arrow size. */ + private static final int DEFAULT_SIZE = 11; + + /** Edge color 1. */ + private Color edge1; + + /** Edge color 2. */ + private Color edge2; + + /** The fill color for the arrow icon. */ + private Color fill; + + /** The size of the icon. */ + private int size; + + /** The direction that the arrow is pointing (UP or DOWN). */ + private int direction; + + /** + * Standard constructor - builds an icon with the specified attributes. + * + * @param direction . + * @param isRaisedView . + * @param isPressedView . + */ + public BevelArrowIcon(final int direction, final boolean isRaisedView, + final boolean isPressedView) + { + if (isRaisedView) + { + if (isPressedView) + { + init(UIManager.getColor("controlLtHighlight"), + UIManager.getColor("controlDkShadow"), UIManager.getColor("controlShadow"), + DEFAULT_SIZE, direction); + } else + { + init(UIManager.getColor("controlHighlight"), UIManager.getColor("controlShadow"), + UIManager.getColor("control"), DEFAULT_SIZE, direction); + } + } else + { + if (isPressedView) + { + init(UIManager.getColor("controlDkShadow"), + UIManager.getColor("controlLtHighlight"), + UIManager.getColor("controlShadow"), DEFAULT_SIZE, direction); + } else + { + init(UIManager.getColor("controlShadow"), UIManager.getColor("controlHighlight"), + UIManager.getColor("control"), DEFAULT_SIZE, direction); + } + } + } + + /** + * Standard constructor - builds an icon with the specified attributes. + * + * @param edge1 the color of edge1. + * @param edge2 the color of edge2. + * @param fill the fill color. + * @param size the size of the arrow icon. + * @param direction the direction that the arrow points. + */ + public BevelArrowIcon(final Color edge1, final Color edge2, final Color fill, final int size, + final int direction) + { + init(edge1, edge2, fill, size, direction); + } + + /** + * Paints the icon at the specified position. Supports the Icon interface. + * + * @param c . + * @param g . + * @param x . + * @param y . + */ + public void paintIcon(final Component c, final Graphics g, final int x, final int y) + { + switch (this.direction) + { + case DOWN: + drawDownArrow(g, x, y); + break; + case UP: + drawUpArrow(g, x, y); + break; + } + } + + /** + * Returns the width of the icon. Supports the Icon interface. + * + * @return the icon width. + */ + public int getIconWidth() + { + return this.size; + } + + /** + * Returns the height of the icon. Supports the Icon interface. + * + * @return the icon height. + */ + public int getIconHeight() + { + return this.size; + } + + /** + * Initialises the attributes of the arrow icon. + * + * @param edge1 the color of edge1. + * @param edge2 the color of edge2. + * @param fill the fill color. + * @param size the size of the arrow icon. + * @param direction the direction that the arrow points. + */ + @SuppressWarnings("hiding") + private void init(final Color edge1, final Color edge2, final Color fill, final int size, + final int direction) + { + this.edge1 = edge1; + this.edge2 = edge2; + this.fill = fill; + this.size = size; + this.direction = direction; + } + + /** + * Draws the arrow pointing down. + * + * @param g the graphics device. + * @param xo ?? + * @param yo ?? + */ + private void drawDownArrow(final Graphics g, final int xo, final int yo) + { + g.setColor(this.edge1); + g.drawLine(xo, yo, xo + this.size - 1, yo); + g.drawLine(xo, yo + 1, xo + this.size - 3, yo + 1); + g.setColor(this.edge2); + g.drawLine(xo + this.size - 2, yo + 1, xo + this.size - 1, yo + 1); + int x = xo + 1; + int y = yo + 2; + int dx = this.size - 6; + while (y + 1 < yo + this.size) + { + g.setColor(this.edge1); + g.drawLine(x, y, x + 1, y); + g.drawLine(x, y + 1, x + 1, y + 1); + if (0 < dx) + { + g.setColor(this.fill); + g.drawLine(x + 2, y, x + 1 + dx, y); + g.drawLine(x + 2, y + 1, x + 1 + dx, y + 1); + } + g.setColor(this.edge2); + g.drawLine(x + dx + 2, y, x + dx + 3, y); + g.drawLine(x + dx + 2, y + 1, x + dx + 3, y + 1); + x += 1; + y += 2; + dx -= 2; + } + g.setColor(this.edge1); + g.drawLine(xo + (this.size / 2), yo + this.size - 1, xo + (this.size / 2), yo + this.size + - 1); + } + + /** + * Draws the arrow pointing up. + * + * @param g the graphics device. + * @param xo ?? + * @param yo ?? + */ + private void drawUpArrow(final Graphics g, final int xo, final int yo) + { + g.setColor(this.edge1); + int x = xo + (this.size / 2); + g.drawLine(x, yo, x, yo); + x--; + int y = yo + 1; + int dx = 0; + while (y + 3 < yo + this.size) + { + g.setColor(this.edge1); + g.drawLine(x, y, x + 1, y); + g.drawLine(x, y + 1, x + 1, y + 1); + if (0 < dx) + { + g.setColor(this.fill); + g.drawLine(x + 2, y, x + 1 + dx, y); + g.drawLine(x + 2, y + 1, x + 1 + dx, y + 1); + } + g.setColor(this.edge2); + g.drawLine(x + dx + 2, y, x + dx + 3, y); + g.drawLine(x + dx + 2, y + 1, x + dx + 3, y + 1); + x -= 1; + y += 2; + dx += 2; + } + g.setColor(this.edge1); + g.drawLine(xo, yo + this.size - 3, xo + 1, yo + this.size - 3); + g.setColor(this.edge2); + g.drawLine(xo + 2, yo + this.size - 2, xo + this.size - 1, yo + this.size - 2); + g.drawLine(xo, yo + this.size - 1, xo + this.size, yo + this.size - 1); + } + +} diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/table/SortButtonRenderer.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/table/SortButtonRenderer.java new file mode 100644 index 0000000000000000000000000000000000000000..4b22a969654a7023641100b0839b36be1b8be6b7 --- /dev/null +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/table/SortButtonRenderer.java @@ -0,0 +1,267 @@ +/* + * Copyright 2011 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.dss.client.api.gui.table; + +import java.awt.Component; +import java.awt.Insets; + +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JTable; +import javax.swing.SwingConstants; +import javax.swing.UIManager; +import javax.swing.border.Border; +import javax.swing.table.JTableHeader; +import javax.swing.table.TableCellRenderer; + +/** + * A table cell renderer for table headings - uses one of three JButton instances to indicate the + * sort order for the table column. + * <P> + * This class (and also BevelArrowIcon) is adapted from original code by Nobuo Tamemasa (version + * 1.0, 26-Feb-1999) posted on www.codeguru.com. + * + * @author Pawel Glyzewski + */ +public class SortButtonRenderer implements TableCellRenderer +{ + + /** + * Useful constant indicating NO sorting. + */ + public static final int NONE = 0; + + /** + * Useful constant indicating ASCENDING (that is, arrow pointing down) sorting in the table. + */ + public static final int DOWN = 1; + + /** + * Useful constant indicating DESCENDING (that is, arrow pointing up) sorting in the table. + */ + public static final int UP = 2; + + /** + * The current pressed column (-1 for no column). + */ + private int pressedColumn = -1; + + /** + * The three buttons that are used to render the table header cells. + */ + private JButton normalButton; + + /** + * The three buttons that are used to render the table header cells. + */ + private JButton ascendingButton; + + /** + * The three buttons that are used to render the table header cells. + */ + private JButton descendingButton; + + /** + * Used to allow the class to work out whether to use the buttuns or labels. Labels are required + * when using the aqua look and feel cos the buttons won't fit. + */ + private boolean useLabels; + + /** + * The normal label (only used with MacOSX). + */ + private JLabel normalLabel; + + /** + * The ascending label (only used with MacOSX). + */ + private JLabel ascendingLabel; + + /** + * The descending label (only used with MacOSX). + */ + private JLabel descendingLabel; + + /** + * Creates a new button renderer. + */ + public SortButtonRenderer() + { + + this.pressedColumn = -1; + this.useLabels = UIManager.getLookAndFeel().getID().equals("Aqua"); + + final Border border = UIManager.getBorder("TableHeader.cellBorder"); + + if (this.useLabels) + { + this.normalLabel = new JLabel(); + this.normalLabel.setHorizontalAlignment(SwingConstants.LEADING); + + this.ascendingLabel = new JLabel(); + this.ascendingLabel.setHorizontalAlignment(SwingConstants.LEADING); + this.ascendingLabel.setHorizontalTextPosition(SwingConstants.LEFT); + this.ascendingLabel.setIcon(new BevelArrowIcon(BevelArrowIcon.DOWN, false, false)); + + this.descendingLabel = new JLabel(); + this.descendingLabel.setHorizontalAlignment(SwingConstants.LEADING); + this.descendingLabel.setHorizontalTextPosition(SwingConstants.LEFT); + this.descendingLabel.setIcon(new BevelArrowIcon(BevelArrowIcon.UP, false, false)); + + this.normalLabel.setBorder(border); + this.ascendingLabel.setBorder(border); + this.descendingLabel.setBorder(border); + } else + { + this.normalButton = new JButton(); + this.normalButton.setMargin(new Insets(0, 0, 0, 0)); + this.normalButton.setHorizontalAlignment(SwingConstants.LEADING); + + this.ascendingButton = new JButton(); + this.ascendingButton.setMargin(new Insets(0, 0, 0, 0)); + this.ascendingButton.setHorizontalAlignment(SwingConstants.LEADING); + this.ascendingButton.setHorizontalTextPosition(SwingConstants.LEFT); + this.ascendingButton.setIcon(new BevelArrowIcon(BevelArrowIcon.DOWN, false, false)); + this.ascendingButton + .setPressedIcon(new BevelArrowIcon(BevelArrowIcon.DOWN, false, true)); + + this.descendingButton = new JButton(); + this.descendingButton.setMargin(new Insets(0, 0, 0, 0)); + this.descendingButton.setHorizontalAlignment(SwingConstants.LEADING); + this.descendingButton.setHorizontalTextPosition(SwingConstants.LEFT); + this.descendingButton.setIcon(new BevelArrowIcon(BevelArrowIcon.UP, false, false)); + this.descendingButton + .setPressedIcon(new BevelArrowIcon(BevelArrowIcon.UP, false, true)); + + this.normalButton.setBorder(border); + this.ascendingButton.setBorder(border); + this.descendingButton.setBorder(border); + } + } + + /** + * Returns the renderer component. + * + * @param table the table. + * @param value the value. + * @param isSelected selected? + * @param hasFocus focussed? + * @param row the row. + * @param column the column. + * @return the renderer. + */ + public Component getTableCellRendererComponent(final JTable table, final Object value, + final boolean isSelected, final boolean hasFocus, final int row, final int column) + { + + if (table == null) + { + throw new NullPointerException("Table must not be null."); + } + + final JComponent component; + final int cc = table.convertColumnIndexToModel(column); + final SortableFilterableTableModel model = (SortableFilterableTableModel) table.getModel(); + final boolean isSorting = model.isSorting(column); + final boolean isAscending = model.isAscending(column); + + final JTableHeader header = table.getTableHeader(); + final boolean isPressed = (cc == this.pressedColumn); + + if (this.useLabels) + { + final JLabel label = getRendererLabel(isSorting, isAscending); + label.setText((value == null) ? "" : value.toString()); + component = label; + } else + { + final JButton button = getRendererButton(isSorting, isAscending); + button.setText((value == null) ? "" : value.toString()); + button.getModel().setPressed(isPressed); + button.getModel().setArmed(isPressed); + component = button; + } + + if (header != null) + { + component.setForeground(header.getForeground()); + component.setBackground(header.getBackground()); + component.setFont(header.getFont()); + } + + return component; + } + + /** + * Returns the correct button component. + * + * @param isSorting whether the render component represents the sort column. + * @param isAscending whether the model is ascending. + * @return either the ascending, descending or normal button. + */ + private JButton getRendererButton(final boolean isSorting, final boolean isAscending) + { + if (isSorting) + { + if (isAscending) + { + return ascendingButton; + } else + { + return descendingButton; + } + } else + { + return normalButton; + } + } + + /** + * Returns the correct label component. + * + * @param isSorting whether the render component represents the sort column. + * @param isAscending whether the model is ascending. + * @return either the ascending, descending or normal label. + */ + private JLabel getRendererLabel(final boolean isSorting, final boolean isAscending) + { + if (isSorting) + { + if (isAscending) + { + return ascendingLabel; + } else + { + return descendingLabel; + } + } else + { + return normalLabel; + } + } + + /** + * Sets the pressed column. + * + * @param column the column. + */ + public void setPressedColumn(final int column) + { + this.pressedColumn = column; + } +} diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/table/SortableFilterableTableModel.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/table/SortableFilterableTableModel.java new file mode 100644 index 0000000000000000000000000000000000000000..daaaa9bd9bd795846d4f3418a5351444bc73f248 --- /dev/null +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/table/SortableFilterableTableModel.java @@ -0,0 +1,182 @@ +/* + * Copyright 2011 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.dss.client.api.gui.table; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.regex.Pattern; + +import javax.swing.table.AbstractTableModel; + +/** + * @author Pawel Glyzewski + */ +public class SortableFilterableTableModel extends AbstractTableModel +{ + private static final long serialVersionUID = -7363632554479395042L; + + private static enum Direction + { + ASC, DESC + } + + private static class RowComparator implements Comparator<String[]> + { + private final int columnNumber; + + private final boolean reverse; + + private RowComparator(int columnNumber, boolean reverse) + { + this.columnNumber = columnNumber; + this.reverse = reverse; + } + + public int compare(String[] o1, String[] o2) + { + if (reverse) + { + return -o1[columnNumber].compareTo(o2[columnNumber]); + + } else + { + return o1[columnNumber].compareTo(o2[columnNumber]); + } + } + } + + private int sortByColumn = -1; + + private Direction sortingOrder = Direction.ASC; + + private final String[] headers; + + private final List<String[]> data; + + private List<String[]> viewData; + + private String filter = ""; + + public SortableFilterableTableModel(List<String[]> data, String[] headers) + { + this.data = data; + this.headers = headers; + } + + @Override + public String getColumnName(int col) + { + return headers[col]; + } + + public int getRowCount() + { + if (viewData != null) + { + return viewData.size(); + } else + { + return data.size(); + } + } + + public int getColumnCount() + { + return headers.length; + } + + public void filter(@SuppressWarnings("hiding") String filter) + { + this.filter = "(?i)" + filter; + Pattern pattern; + + try + { + pattern = Pattern.compile(this.filter); + } catch (RuntimeException e) + { + pattern = Pattern.compile(".*"); + } + viewData = new ArrayList<String[]>(); + for (String[] row : data) + { + boolean matches = false; + for (String value : row) + { + matches = matches || pattern.matcher(value).find(); + if (matches) + { + viewData.add(row); + break; + } + } + } + + if (sortByColumn > -1) + { + Collections.sort(viewData, new RowComparator(sortByColumn, + Direction.ASC != sortingOrder)); + } + + fireTableDataChanged(); + } + + public Object getValueAt(int rowIndex, int columnIndex) + { + if (viewData != null) + { + return viewData.get(rowIndex)[columnIndex]; + } else + { + return data.get(rowIndex)[columnIndex]; + } + } + + public boolean isAscending(int column) + { + return Direction.ASC == sortingOrder; + } + + public boolean isSorting(int column) + { + return column == sortByColumn; + } + + public synchronized void toggleSort(int column) + { + if (column == sortByColumn) + { + switch (sortingOrder) + { + case ASC: + sortingOrder = Direction.DESC; + break; + case DESC: + sortByColumn = -1; + break; + } + } else + { + sortByColumn = column; + sortingOrder = Direction.ASC; + } + + filter(filter); + } +} diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/table/TableHeaderMouseListener.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/table/TableHeaderMouseListener.java new file mode 100644 index 0000000000000000000000000000000000000000..6be9443e7f879fae7d6f58ed987afee63aa96123 --- /dev/null +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/table/TableHeaderMouseListener.java @@ -0,0 +1,69 @@ +/* + * Copyright 2011 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.dss.client.api.gui.table; + +import java.awt.Rectangle; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +import javax.swing.JTable; +import javax.swing.table.JTableHeader; +import javax.swing.table.TableColumnModel; + +/** + * @author Pawel Glyzewski + */ +public class TableHeaderMouseListener extends MouseAdapter +{ + private SortableFilterableTableModel model; + + public TableHeaderMouseListener(SortableFilterableTableModel model) + { + this.model = model; + } + + @Override + public void mouseClicked(MouseEvent evt) + { + JTable table = ((JTableHeader) evt.getSource()).getTable(); + TableColumnModel colModel = table.getColumnModel(); + + // The index of the column whose header was clicked + int vColIndex = colModel.getColumnIndexAtX(evt.getX()); + int mColIndex = table.convertColumnIndexToModel(vColIndex); + + // Return if not clicked on any column header + if (vColIndex == -1) + { + return; + } + + // Determine if mouse was clicked between column heads + Rectangle headerRect = table.getTableHeader().getHeaderRect(vColIndex); + if (vColIndex == 0) + { + headerRect.width -= 3; // Hard-coded constant + } else + { + headerRect.grow(-3, 0); // Hard-coded constant + } + if (headerRect.contains(evt.getX(), evt.getY())) + { + model.toggleSort(mColIndex); + } + } +} diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/ISimpleOpenbisServiceFacade.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/ISimpleOpenbisServiceFacade.java index fefc476f6290eed26510f7c02eddd67f90e98d89..2be32866619d8af9bc410bd66bce1ed1132794e0 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/ISimpleOpenbisServiceFacade.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/ISimpleOpenbisServiceFacade.java @@ -25,6 +25,7 @@ import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.NewDataSetDTO; import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.validation.ValidationError; import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSetType; import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Experiment; +import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Project; import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Sample; import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SpaceWithProjectsAndRoleAssignments; @@ -41,6 +42,12 @@ import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SpaceWithProjectsAndRo */ public interface ISimpleOpenbisServiceFacade { + + /** + * Returns all available projects. + */ + List<Project> listProjects(); + /** * Return all spaces enriched with their projects and role assignments. */ diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/impl/OpenbisServiceFacade.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/impl/OpenbisServiceFacade.java index d1f2a2828cb49c71f6d37daa024a7e6d92040aad..bb433c30f7a1e580c08dcaa7b9decc5095ce5e7a 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/impl/OpenbisServiceFacade.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/impl/OpenbisServiceFacade.java @@ -151,6 +151,11 @@ public class OpenbisServiceFacade implements IOpenbisServiceFacade // ISimpleOpenbisServiceFacade // + public List<Project> listProjects() + { + return service.listProjects(sessionToken); + } + public List<SpaceWithProjectsAndRoleAssignments> getSpacesWithProjects() throws EnvironmentFailureException { diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationService.java index 91e99fb36faf489ead4849f356a62e854ee2811c..c24208e8157667b6f919ec74c0aa4d5e7f0749b2 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationService.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationService.java @@ -163,7 +163,7 @@ public class GeneralInformationService extends AbstractServer<IGeneralInformatio public int getMinorVersion() { - return 9; + return 10; } private Map<String, List<RoleAssignmentPE>> getRoleAssignmentsPerSpace() @@ -421,4 +421,11 @@ public class GeneralInformationService extends AbstractServer<IGeneralInformatio return Translator.translateExperiments(experiments); } + + public List<Project> listProjects(String sessionToken) + { + checkSession(sessionToken); + + return Translator.translateProjects(commonServer.listProjects(sessionToken)); + } } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationServiceLogger.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationServiceLogger.java index d983033ccf9ad93af35ba79489a4e8e3af089d2f..e054059f441e0f7f559ae1208aba77ba301cc557 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationServiceLogger.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationServiceLogger.java @@ -157,4 +157,9 @@ class GeneralInformationServiceLogger extends AbstractServerLogger implements return null; } + public List<Project> listProjects(String sessionToken) + { + logAccess(sessionToken, "list-projects"); + return null; + } } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/Translator.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/Translator.java index 2af9a350c4a49cc9358d10cee538475dc1148d56..0f9102c7e545578fd74593c343e18aae2fff7775 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/Translator.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/Translator.java @@ -36,6 +36,7 @@ import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSetType; import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSetType.DataSetTypeInitializer; import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Experiment; import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Experiment.ExperimentInitializer; +import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Project; import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.PropertyType; import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.PropertyType.PropertyTypeInitializer; import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.PropertyTypeGroup; @@ -65,6 +66,24 @@ public class Translator return new Role(roleCode.name(), spaceLevel); } + public static List<Project> translateProjects( + List<ch.systemsx.cisd.openbis.generic.shared.basic.dto.Project> projects) + { + ArrayList<Project> translated = new ArrayList<Project>(); + + for (ch.systemsx.cisd.openbis.generic.shared.basic.dto.Project project : projects) + { + translated.add(translate(project)); + } + + return translated; + } + + static Project translate(ch.systemsx.cisd.openbis.generic.shared.basic.dto.Project project) + { + return new Project(project.getSpace().getCode(), project.getCode()); + } + public static List<Sample> translateSamples( Collection<ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample> privateSamples) { diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/IGeneralInformationService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/IGeneralInformationService.java index b64615df257e73b40ebf53a9be5daacc1579f1f6..16c1a62574ef461e19dc4d0df4fdb6fb8308cf15 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/IGeneralInformationService.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/IGeneralInformationService.java @@ -220,4 +220,11 @@ public interface IGeneralInformationService extends IRpcService @Transactional(readOnly = true) @RolesAllowed(RoleWithHierarchy.INSTANCE_OBSERVER) public List<Experiment> listExperiments(String sessionToken, List<String> experimentIdentifiers); + + /** + * Returns all available projects. + */ + @Transactional(readOnly = true) + @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER) + public List<Project> listProjects(String sessionToken); } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/Project.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/Project.java index 16bad61f1adbf86d10b1a82903c785d492b727f3..026d4ad2b75612137e4c48be8afdcf8c4b1f7035 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/Project.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/Project.java @@ -19,17 +19,17 @@ package ch.systemsx.cisd.openbis.generic.shared.api.v1.dto; import java.io.Serializable; /** - * Immutable value object representing a project. A project is specified by its code and the code - * of the space to which it belongs. - * + * Immutable value object representing a project. A project is specified by its code and the code of + * the space to which it belongs. + * * @author Franz-Josef Elmer */ public final class Project implements Serializable { private static final long serialVersionUID = 1L; - + private final String spaceCode; - + private final String code; /** @@ -51,7 +51,7 @@ public final class Project implements Serializable } this.code = code; } - + /** * Returns the space code. */ @@ -59,7 +59,7 @@ public final class Project implements Serializable { return spaceCode; } - + /** * Returns the project code. */