/* * SoapUI, Copyright (C) 2004-2016 SmartBear Software * * Licensed under the EUPL, Version 1.1 or - as soon as they will be approved by the European Commission - subsequent * versions of the EUPL (the "Licence"); * You may not use this work except in compliance with the Licence. * You may obtain a copy of the Licence at: * * http://ec.europa.eu/idabc/eupl * * Unless required by applicable law or agreed to in writing, software distributed under the Licence is * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the Licence for the specific language governing permissions and limitations * under the Licence. */ package com.eviware.soapui.impl.rest.panels.resource; import com.eviware.soapui.impl.rest.support.RestParamProperty; import com.eviware.soapui.impl.rest.support.RestParamsPropertyHolder; import com.eviware.soapui.impl.rest.support.RestParamsPropertyHolder.ParameterStyle; import com.eviware.soapui.impl.rest.support.RestUtils; import com.eviware.soapui.impl.support.actions.ShowOnlineHelpAction; import com.eviware.soapui.impl.wsdl.panels.teststeps.support.AddParamAction; import com.eviware.soapui.impl.wsdl.panels.teststeps.support.MovePropertyDownAction; import com.eviware.soapui.impl.wsdl.panels.teststeps.support.MovePropertyUpAction; import com.eviware.soapui.impl.wsdl.panels.teststeps.support.RemovePropertyAction; import com.eviware.soapui.impl.wsdl.support.HelpUrls; import com.eviware.soapui.model.testsuite.TestProperty; import com.eviware.soapui.support.UISupport; import com.eviware.soapui.support.components.JXToolBar; import com.eviware.soapui.support.components.SimpleBindingForm; import com.eviware.soapui.support.components.StringListFormComponent; import com.eviware.soapui.support.swing.JTableFactory; import com.jgoodies.binding.PresentationModel; import org.apache.xmlbeans.SchemaType; import org.apache.xmlbeans.XmlBeans; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.DefaultCellEditor; import javax.swing.DefaultComboBoxModel; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTable; import javax.swing.JTextField; import javax.swing.ListSelectionModel; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.table.TableCellEditor; import javax.swing.table.TableCellRenderer; import javax.xml.namespace.QName; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.KeyListener; import java.util.ArrayList; import java.util.List; import static com.eviware.soapui.impl.rest.actions.support.NewRestResourceActionBase.ParamLocation; public class RestParamsTable extends JPanel { public static final String REST_PARAMS_TABLE = "RestParamsTable"; public static final String REVERT_PARAMETER_VALUES = "Revert Parameter Values"; protected RestParamsPropertyHolder params; protected RestParamsTableModel paramsTableModel; protected JTable paramsTable; protected AddParamAction addParamAction = null; protected RemovePropertyAction removeParamAction = null; protected UseDefaultParamsAction defaultParamsAction = null; protected MovePropertyDownAction movePropertyDownAction = null; protected MovePropertyUpAction movePropertyUpAction = null; protected UpdateParamsAction updateParamsAction = null; private PresentationModel<RestParamProperty> paramDetailsModel; private SimpleBindingForm detailsForm; private ParamLocation defaultParamLocation; private boolean showEditableButtons; private boolean showDefaultParamsButton; private JSplitPane splitPane; private JScrollPane scrollPane; public RestParamsTable(RestParamsPropertyHolder params, boolean showInspector, ParamLocation defaultParamLocation, boolean showEditableButtons, boolean showDefaultParamsButton) { this(params, showInspector, new RestParamsTableModel(params, RestParamsTableModel.Mode.MEDIUM), defaultParamLocation, showEditableButtons, showDefaultParamsButton); } public RestParamsTable(RestParamsPropertyHolder params, boolean showInspector, RestParamsTableModel model, ParamLocation defaultParamLocation, boolean showEditableButtons, boolean showDefaultParamsButton) { super(new BorderLayout()); this.defaultParamLocation = defaultParamLocation; this.showEditableButtons = showEditableButtons; this.showDefaultParamsButton = showDefaultParamsButton; this.params = params; this.paramsTableModel = model; init(showInspector); } protected void init(boolean showInspector) { paramsTable = new JTable(paramsTableModel) { @Override public Component prepareRenderer(TableCellRenderer renderer, int row, int column) { Component defaultRenderer = super.prepareRenderer(renderer, row, column); if (UISupport.isMac()) { JTableFactory.applyStripesToRenderer(row, defaultRenderer); } return defaultRenderer; } @Override public void removeEditor() { TableCellEditor editor = getCellEditor(); // must be called here to remove the editor and to avoid an infinite // loop, because the table is an editor listener and the // editingCanceled method calls this removeEditor method super.removeEditor(); if (editor != null) { editor.cancelCellEditing(); } } @Override public Component prepareEditor(TableCellEditor editor, int row, int column) { Component component = super.prepareEditor(editor, row, column); if (getColumnClass(column) == ParameterStyle.class) { RestParamProperty parameter = paramsTableModel.getParameterAt(row); JComboBox comboBox = (JComboBox) ((DefaultCellEditor) editor).getComponent(); comboBox.setModel(getStylesForLocation(parameter.getParamLocation())); super.prepareEditor(editor, row, column); } if (getColumnClass(column) == ParamLocation.class) { RestParamProperty parameter = paramsTableModel.getParameterAt(row); JComboBox comboBox = (JComboBox) ((DefaultCellEditor) editor).getComponent(); comboBox.setModel(getLocationForParameter(parameter.getStyle())); super.prepareEditor(editor, row, column); } return component; } }; paramsTable.setName(REST_PARAMS_TABLE); paramsTable.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE); if (showDefaultParamsButton) { defaultParamsAction = new UseDefaultParamsAction(); } movePropertyDownAction = new MovePropertyDownAction(paramsTable, params, "Moves selected parameter down one row"); movePropertyUpAction = new MovePropertyUpAction(paramsTable, params, "Moves selected parameter up one row"); if (showEditableButtons) { initEditableButtons(); } paramsTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); paramsTable.setDefaultEditor(ParameterStyle.class, new DefaultCellEditor( new JComboBox(getStylesForLocation(ParamLocation.RESOURCE)))); paramsTable.setDefaultEditor(ParamLocation.class, new DefaultCellEditor( new JComboBox(ParamLocation.values()))); // Workaround: for some reason the lower part of text gets clipped on some platforms paramsTable.setRowHeight(25); paramsTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { public void valueChanged(ListSelectionEvent e) { int selectedRow = paramsTable.getSelectedRow(); if (showEditableButtons) { removeParamAction.setEnabled(selectedRow != -1); } if (showDefaultParamsButton) { defaultParamsAction.setEnabled(paramsTable.getRowCount() > 0); } movePropertyDownAction.setEnabled(selectedRow < paramsTable.getRowCount() - 1); movePropertyUpAction.setEnabled(selectedRow > 0); if (selectedRow != -1) { RestParamProperty selectedParameter = getSelectedParameter(); if (paramDetailsModel != null) { updateDetailsFormWith(selectedParameter); detailsForm.setEnabled(true); } } else { if (paramDetailsModel != null) { detailsForm.setEnabled(false); updateDetailsFormWith(null); } } } }); add(buildToolbar(), BorderLayout.NORTH); scrollPane = new JScrollPane(paramsTable); if (showInspector) { splitPane = UISupport.createVerticalSplit(scrollPane, buildDetails()); add(splitPane, BorderLayout.CENTER); splitPane.setResizeWeight(0.7); } else { add(scrollPane, BorderLayout.CENTER); } } private DefaultComboBoxModel getStylesForLocation(ParamLocation paramLocation) { if (paramLocation == ParamLocation.METHOD) { return new DefaultComboBoxModel( new ParameterStyle[]{ParameterStyle.QUERY, ParameterStyle.HEADER, ParameterStyle.MATRIX, ParameterStyle.PLAIN}); } else { return new DefaultComboBoxModel( new ParameterStyle[]{ParameterStyle.QUERY, ParameterStyle.TEMPLATE, ParameterStyle.HEADER, ParameterStyle.MATRIX, ParameterStyle.PLAIN}); } } private DefaultComboBoxModel getLocationForParameter(ParameterStyle style) { if (style != ParameterStyle.TEMPLATE) { return new DefaultComboBoxModel( new ParamLocation[]{ParamLocation.RESOURCE, ParamLocation.METHOD}); } else { return new DefaultComboBoxModel( new ParamLocation[]{ParamLocation.RESOURCE}); } } private void updateDetailsFormWith(RestParamProperty selectedParameter) { try { paramDetailsModel.setBean(selectedParameter); } catch (Exception e) { splitPane.setBottomComponent(buildDetails()); paramDetailsModel.setBean(selectedParameter); } } @Override public synchronized void addKeyListener(KeyListener l) { super.addKeyListener(l); paramsTable.addKeyListener(l); } private void initEditableButtons() { addParamAction = new AddParamAction(paramsTable, params, "Adds a parameter to the parameter table"); removeParamAction = new RemovePropertyAction(paramsTable, params, "Removes the selected parameter"); updateParamsAction = new UpdateParamsAction(); } private JComponent buildDetails() { paramDetailsModel = new PresentationModel<RestParamProperty>(null); detailsForm = new SimpleBindingForm(paramDetailsModel); detailsForm.addSpace(5); detailsForm.appendCheckBox("required", "Required", "Sets if parameter is required"); List<QName> types = new ArrayList<QName>(); for (SchemaType type : XmlBeans.getBuiltinTypeSystem().globalTypes()) { types.add(type.getName()); } detailsForm.appendComboBox("type", "Type", types.toArray(), "The type of the parameter"); StringListFormComponent optionsFormComponent = new StringListFormComponent("Available values for this Parameter"); //TODO: Consider removing hardcoded size optionsFormComponent.setPreferredSize(new Dimension(350, 100)); detailsForm.appendComponent("options", "Options", optionsFormComponent); detailsForm.appendTextField("description", "Description", "A short description of the parameter"); detailsForm.appendCheckBox("disableUrlEncoding", "Disable Encoding", "Disables URL-Encoding of the parameter value"); detailsForm.addSpace(5); detailsForm.setEnabled(false); return new JScrollPane(detailsForm.getPanel()); } protected RestParamProperty getSelectedParameter() { return paramsTable.getSelectedRow() == -1 ? null : paramsTableModel.getParameterAt(paramsTable.getSelectedRow()); } public JTable getParamsTable() { return paramsTable; } public void release() { paramsTableModel.release(); if (paramDetailsModel != null) { paramDetailsModel.setBean(null); } } protected Component buildToolbar() { JXToolBar toolbar = UISupport.createToolbar(); //TODO: the action should be disabled by default if the corresponding component (button) // is supposed to be disabled by default. if (showEditableButtons) { toolbar.add(UISupport.createToolbarButton(addParamAction)); toolbar.add(UISupport.createToolbarButton(removeParamAction, false)); toolbar.addSeparator(); toolbar.add(UISupport.createToolbarButton(updateParamsAction)); } if (showDefaultParamsButton) { toolbar.add(UISupport.createToolbarButton(defaultParamsAction, paramsTable.getRowCount() > 0)); } toolbar.addSeparator(); if (!inMinimalMode()) { toolbar.add(UISupport.createToolbarButton(movePropertyDownAction, false)); toolbar.add(UISupport.createToolbarButton(movePropertyUpAction, false)); } toolbar.addSeparator(); toolbar.addGlue(); toolbar.add(UISupport.createToolbarButton(new ShowOnlineHelpAction(HelpUrls.HTTP_REQUEST_PARAMS_HELP_URL))); return toolbar; } private boolean inMinimalMode() { RestParamsTableModel tableModel = (RestParamsTableModel) getParamsTable().getModel(); return tableModel.isInMinimalMode(); } public void extractParams(RestParamsPropertyHolder params, ParamLocation location) { for (int i = 0; i < paramsTable.getRowCount(); i++) { RestParamProperty prop = paramsTableModel.getParameterAt(i); if (paramsTableModel.getParamLocationAt(i) == location) { params.addParameter(prop); } } } public void focusParameter(String parameterName) { paramsTable.grabFocus(); for (int i = 0; i < paramsTable.getRowCount(); i++) { if (paramsTable.getValueAt(i, 0).equals(parameterName)) { paramsTable.setRowSelectionInterval(i, i); paramsTable.editCellAt(i, 1); JTextField editorComponent = (JTextField) paramsTable.getEditorComponent(); editorComponent.grabFocus(); editorComponent.selectAll(); scrollIntoPosition(i, paramsTable.getRowCount()); return; } } } private void scrollIntoPosition(int selectedIndex, int numOfIndices) { scrollIntoPosition((double) selectedIndex / numOfIndices); } private void scrollIntoPosition(double percent) { int maximumScrollPosition = scrollPane.getVerticalScrollBar().getMaximum(); int requestedScrollPosition = (int) Math.round(maximumScrollPosition * percent); scrollPane.getVerticalScrollBar().setValue(requestedScrollPosition); } private class UpdateParamsAction extends AbstractAction { private UpdateParamsAction() { putValue(Action.SMALL_ICON, UISupport.createImageIcon("/update-request-parameters-from-url.png")); putValue(Action.SHORT_DESCRIPTION, "Updates params from a specified URL"); } public void actionPerformed(ActionEvent e) { String str = UISupport.prompt("Enter new url below", "Extract Params", ""); if (str == null) { return; } try { RestUtils.extractParams(str, params, false, defaultParamLocation == ParamLocation.RESOURCE ? RestUtils.TemplateExtractionOption.EXTRACT_TEMPLATE_PARAMETERS : RestUtils.TemplateExtractionOption.IGNORE_TEMPLATE_PARAMETERS); } catch (Exception e1) { UISupport.showErrorMessage(e1); } } } private class UseDefaultParamsAction extends AbstractAction { public UseDefaultParamsAction() { super(REVERT_PARAMETER_VALUES); putValue(Action.SMALL_ICON, UISupport.createImageIcon("/default_properties.gif")); putValue(Action.SHORT_DESCRIPTION, "Reverts all current parameters to default values"); setEnabled(false); } public void actionPerformed(ActionEvent e) { if (UISupport.confirm("Revert all parameters to default values?", "Use Defaults")) { for (TestProperty property : params.getProperties().values()) { property.setValue(null); } } } } public void setParams(RestParamsPropertyHolder params) { this.params = params; paramsTableModel.setParams(params); } public void refresh() { paramsTableModel.fireTableDataChanged(); } }