/*
* 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.support.propertyexpansion;
import com.eviware.soapui.impl.support.AbstractHttpRequest;
import com.eviware.soapui.impl.support.AbstractHttpRequestInterface;
import com.eviware.soapui.impl.wsdl.MutableTestPropertyHolder;
import com.eviware.soapui.impl.wsdl.WsdlProject;
import com.eviware.soapui.impl.wsdl.WsdlTestSuite;
import com.eviware.soapui.impl.wsdl.mock.WsdlMockService;
import com.eviware.soapui.impl.wsdl.panels.teststeps.support.GroovyEditor;
import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase;
import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestStep;
import com.eviware.soapui.model.ModelItem;
import com.eviware.soapui.model.TestModelItem;
import com.eviware.soapui.model.TestPropertyHolder;
import com.eviware.soapui.model.iface.Operation;
import com.eviware.soapui.model.mock.MockResponse;
import com.eviware.soapui.model.mock.MockService;
import com.eviware.soapui.model.propertyexpansion.PropertyExpansion;
import com.eviware.soapui.model.propertyexpansion.PropertyExpansionImpl;
import com.eviware.soapui.model.propertyexpansion.PropertyExpansionUtils;
import com.eviware.soapui.model.testsuite.TestProperty;
import com.eviware.soapui.security.SecurityTest;
import com.eviware.soapui.support.JsonUtil;
import com.eviware.soapui.support.StringUtils;
import com.eviware.soapui.support.UISupport;
import com.eviware.soapui.support.components.GroovyEditorComponent;
import com.eviware.soapui.support.components.ShowPopupAction;
import com.eviware.soapui.support.propertyexpansion.scrollmenu.ScrollableMenu;
import com.eviware.soapui.support.xml.XmlUtils;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JMenu;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JSeparator;
import javax.swing.JTextField;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import javax.swing.text.JTextComponent;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.event.ActionEvent;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class PropertyExpansionPopupListener implements PopupMenuListener {
private final Container targetMenu;
private final ModelItem modelItem;
private final PropertyExpansionTarget target;
public PropertyExpansionPopupListener(Container transferMenu, ModelItem modelItem, PropertyExpansionTarget target) {
this.modelItem = modelItem;
this.target = target;
this.targetMenu = transferMenu;
}
@Override
public void popupMenuCanceled(PopupMenuEvent arg0) {
}
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent arg0) {
}
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent arg0) {
// create transfer menus
targetMenu.removeAll();
WsdlTestStep testStep;
WsdlTestCase testCase = null;
WsdlTestSuite testSuite = null;
WsdlProject project = null;
MockService mockService = null;
MockResponse mockResponse = null;
SecurityTest securityTest = null;
if (modelItem instanceof WsdlTestStep) {
testStep = (WsdlTestStep) modelItem;
testCase = testStep.getTestCase();
testSuite = testCase.getTestSuite();
project = testSuite.getProject();
} else if (modelItem instanceof WsdlTestCase) {
testCase = (WsdlTestCase) modelItem;
testSuite = testCase.getTestSuite();
project = testSuite.getProject();
} else if (modelItem instanceof WsdlTestSuite) {
testSuite = (WsdlTestSuite) modelItem;
project = testSuite.getProject();
} else if (modelItem instanceof WsdlMockService) {
project = ((WsdlMockService) modelItem).getProject();
} else if (modelItem instanceof MockResponse) {
mockResponse = (MockResponse) modelItem;
mockService = (mockResponse).getMockOperation().getMockService();
project = mockService.getProject();
} else if (modelItem instanceof WsdlProject) {
project = (WsdlProject) modelItem;
} else if (modelItem instanceof AbstractHttpRequestInterface<?>) {
project = ((AbstractHttpRequest<?>) modelItem).getOperation().getInterface().getProject();
} else if (modelItem instanceof Operation) {
project = (WsdlProject) ((Operation) modelItem).getInterface().getProject();
} else if (modelItem instanceof SecurityTest) {
securityTest = (SecurityTest) modelItem;
testCase = securityTest.getTestCase();
testSuite = testCase.getTestSuite();
project = testSuite.getProject();
}
TestPropertyHolder globalProperties = PropertyExpansionUtils.getGlobalProperties();
if (globalProperties.getProperties().size() > 0) {
targetMenu.add(createPropertyMenu("Global", globalProperties));
}
if (project != null) {
targetMenu.add(createPropertyMenu("Project: [" + project.getName() + "]", project));
}
if (testSuite != null) {
targetMenu.add(createPropertyMenu("TestSuite: [" + testSuite.getName() + "]", testSuite));
}
if (mockService != null) {
targetMenu.add(createPropertyMenu("MockService: [" + mockService.getName() + "]", mockService));
}
if (mockResponse != null) {
targetMenu.add(createPropertyMenu("MockResponse: [" + mockResponse.getName() + "]", mockResponse));
}
if (testCase != null) {
targetMenu.add(createPropertyMenu("TestCase: [" + testCase.getName() + "]", testCase));
for (int c = 0; c < testCase.getTestStepCount(); c++) {
testStep = testCase.getTestStepAt(c);
if (testStep.getPropertyNames().length == 0) {
continue;
}
if (targetMenu.getComponentCount() == 3) {
targetMenu.add(new JSeparator());
}
targetMenu.add(createPropertyMenu("Step " + (c + 1) + ": [" + testStep.getName() + "]", testStep));
}
}
if (securityTest != null) {
targetMenu.add(createPropertyMenu("SecurityTest: [" + securityTest.getName() + "]", securityTest));
}
}
private JMenu createPropertyMenu(String string, TestPropertyHolder holder) {
ScrollableMenu menu = new ScrollableMenu(string);
if (holder instanceof TestModelItem) {
menu.setIcon(((TestModelItem) holder).getIcon());
}
String[] propertyNames = holder.getPropertyNames();
for (String name : propertyNames) {
menu.add(new TransferFromPropertyActionInvoker(holder, name));
}
if (holder instanceof MutableTestPropertyHolder) {
menu.addHeader(new TransferFromPropertyActionInvoker((MutableTestPropertyHolder) holder));
}
return menu;
}
private class TransferFromPropertyActionInvoker extends AbstractAction {
private final TestPropertyHolder sourceStep;
private String sourceProperty;
public TransferFromPropertyActionInvoker(TestPropertyHolder sourceStep, String sourceProperty) {
super("Property [" + sourceProperty + "]");
this.sourceStep = sourceStep;
this.sourceProperty = sourceProperty;
}
public TransferFromPropertyActionInvoker(MutableTestPropertyHolder testStep) {
super("Create new...");
this.sourceStep = testStep;
}
@Override
public void actionPerformed(ActionEvent arg0) {
if (sourceProperty == null && sourceStep instanceof MutableTestPropertyHolder) {
MutableTestPropertyHolder step = (MutableTestPropertyHolder) sourceStep;
sourceProperty = target.getNameForCreation();
sourceProperty = UISupport.prompt("Specify name of source property to create", "Create source property",
sourceProperty);
while (sourceProperty != null && step.getProperty(sourceProperty) != null) {
sourceProperty = UISupport.prompt("Name is taken, specify unique name of source property to create",
"Create source property", sourceProperty);
}
if (sourceProperty == null) {
return;
}
((MutableTestPropertyHolder) sourceStep).addProperty(sourceProperty);
String newVal = UISupport.prompt("Specify the value of the new property '" + sourceProperty + "'",
"Set the value of the property", "");
if (newVal != null) {
sourceStep.setPropertyValue(sourceProperty, newVal);
}
}
String sourceXPath = "";
String val = sourceStep.getPropertyValue(sourceProperty);
try {
if (StringUtils.isNullOrEmpty(val)) {
String defaultValue = sourceStep.getProperty(sourceProperty).getDefaultValue();
if (StringUtils.hasContent(defaultValue)) {
if (UISupport.confirm("Missing property value, use default value instead?", "Get Data")) {
val = defaultValue;
}
}
}
if (XmlUtils.seemsToBeXml(val)) {
XmlUtils.createXmlObject(val);
sourceXPath = UISupport.selectXPath("Select XPath", "Select source xpath", val,
null);
} else if (JsonUtil.isValidJson(val)) {
sourceXPath = UISupport.selectJsonPath("Select JSON", "Select JSON value", val, null);
}
} catch (Exception e) {
e.printStackTrace();
// just ignore.. this wasn't xml..
}
if (StringUtils.hasContent(sourceXPath)) {
sourceXPath = PropertyExpansionUtils.shortenXPathForPropertyExpansion(sourceXPath, val);
}
TestProperty property = sourceStep.getProperty(sourceProperty);
PropertyExpansion pe = new PropertyExpansionImpl(property, sourceXPath);
String userSelectedValue = target.getValueForCreation();
target.insertPropertyExpansion(pe, null);
if (!StringUtils.hasContent(sourceXPath) && StringUtils.hasContent(userSelectedValue)
&& !property.isReadOnly()) {
if (!userInputIsPropertyExpansion(userSelectedValue)) {
userSelectedValue = UISupport.prompt("Do you want to update the value of the property? (" + val + ")",
"Get Data", userSelectedValue);
if (userSelectedValue != null) {
property.setValue(userSelectedValue);
}
}
}
}
}
private static final Pattern pattern = Pattern.compile("^\\$\\{(.*)\\}$");
private static boolean userInputIsPropertyExpansion(String userSelectedValue) {
if (userSelectedValue == null) {
return false;
}
Matcher matcher = pattern.matcher(userSelectedValue);
return matcher.matches();
}
public static void addMenu(JPopupMenu popup, String menuName, ModelItem item, PropertyExpansionTarget component) {
ScrollableMenu menu = new ScrollableMenu(menuName);
menu.setName(menuName);
boolean contains = false;
for (int i = 0; i < popup.getComponentCount(); i++) {
if (menu.getName() != null && menu.getName().equals(popup.getComponent(i).getName())) {
contains = true;
break;
}
}
if (!contains) {
popup.add(menu);
popup.addPopupMenuListener(new PropertyExpansionPopupListener(menu, item, component));
}
}
public static void enable(JTextComponent textField, ModelItem modelItem, JPopupMenu popup) {
JTextComponentPropertyExpansionTarget target = new JTextComponentPropertyExpansionTarget(textField, modelItem);
DropTarget dropTarget = new DropTarget(textField, new PropertyExpansionDropTarget(target));
dropTarget.setDefaultActions(DnDConstants.ACTION_COPY_OR_MOVE);
textField.setComponentPopupMenu(popup);
if (popup != null) {
PropertyExpansionPopupListener.addMenu(popup, "Get Data...", target.getContextModelItem(), target);
}
}
public static JPanel addPropertyExpansionPopup(JTextField textField, JPopupMenu popup, ModelItem modelItem) {
PropertyExpansionPopupListener.enable(textField, modelItem, popup);
JButton popupButton = new JButton();
popupButton.setAction(new ShowPopupAction(textField, popupButton));
popupButton.setBackground(Color.WHITE);
popupButton.setForeground(Color.WHITE);
popupButton.setBorder(null);
popupButton.setOpaque(true);
JPanel panel = new JPanel(new BorderLayout());
panel.add(textField, BorderLayout.CENTER);
panel.add(popupButton, BorderLayout.EAST);
panel.setBorder(textField.getBorder());
textField.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
return panel;
}
public static void enable(RSyntaxTextArea textField, ModelItem modelItem) {
RSyntaxTextAreaPropertyExpansionTarget target = new RSyntaxTextAreaPropertyExpansionTarget(textField, modelItem);
DropTarget dropTarget = new DropTarget(textField, new PropertyExpansionDropTarget(target));
dropTarget.setDefaultActions(DnDConstants.ACTION_COPY_OR_MOVE);
JPopupMenu popup = textField.getPopupMenu();
if (popup != null) {
PropertyExpansionPopupListener.addMenu(popup, "Get Data...", target.getContextModelItem(), target);
}
}
public static void enable(GroovyEditor groovyEditor, ModelItem modelItem) {
GroovyEditorPropertyExpansionTarget target = new GroovyEditorPropertyExpansionTarget(groovyEditor, modelItem);
DropTarget dropTarget = new DropTarget(groovyEditor.getEditArea(), new PropertyExpansionDropTarget(target));
dropTarget.setDefaultActions(DnDConstants.ACTION_COPY_OR_MOVE);
JPopupMenu popup = groovyEditor.getEditArea().getComponentPopupMenu();
if (popup != null) {
ScrollableMenu menu = new ScrollableMenu("Get Data...");
popup.insert(menu, 0);
popup.addPopupMenuListener(new PropertyExpansionPopupListener(menu, target.getContextModelItem(), target));
popup.insert(new JSeparator(), 1);
}
}
public static void enable(JTextComponent textField, ModelItem modelItem) {
JPopupMenu popupMenu = textField.getComponentPopupMenu();
if (popupMenu == null) {
popupMenu = new JPopupMenu();
textField.setComponentPopupMenu(popupMenu);
}
enable(textField, modelItem, popupMenu);
}
public static void enable(GroovyEditorComponent gec, ModelItem modelItem) {
enable(gec.getEditor(), modelItem);
}
}