/* * 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.support; import com.eviware.soapui.config.RestRequestConfig; import com.eviware.soapui.config.StringListConfig; import com.eviware.soapui.impl.rest.RestRequest; import com.eviware.soapui.impl.rest.actions.support.NewRestResourceActionBase; import com.eviware.soapui.model.ModelItem; import com.eviware.soapui.model.propertyexpansion.PropertyExpansion; import com.eviware.soapui.model.testsuite.TestProperty; import com.eviware.soapui.model.testsuite.TestPropertyListener; import com.eviware.soapui.support.types.StringToStringMap; import org.apache.xmlbeans.SchemaType; import javax.xml.namespace.QName; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; public class RestRequestParamsPropertyHolder implements RestParamsPropertyHolder, TestPropertyListener { private StringToStringMap values; private RestParamsPropertyHolder methodParams; private List<String> sortedPropertyNames; private RestRequest restRequest; private Set<TestPropertyListener> listeners = new HashSet<TestPropertyListener>(); private Map<RestParamProperty, InternalRestParamProperty> wrappers = new HashMap<RestParamProperty, InternalRestParamProperty>(); private String parameterBeingMoved; public RestRequestParamsPropertyHolder(RestParamsPropertyHolder methodParams, RestRequest restRequest, StringToStringMap values) { this.methodParams = methodParams; this.restRequest = restRequest; buildPropertyNameList(); this.values = values; methodParams.addTestPropertyListener(this); } private void buildPropertyNameList() { RestRequestConfig requestConfig = restRequest.getConfig(); List<String> propertyNames; List<String> methodParamNames = new ArrayList<String>(Arrays.asList(methodParams.getPropertyNames())); if (requestConfig.isSetParameterOrder()) { propertyNames = new ArrayList<String>(requestConfig.getParameterOrder().getEntryList()); propertyNames.retainAll(methodParamNames); methodParamNames.removeAll(propertyNames); propertyNames.addAll(methodParamNames); } else { propertyNames = new ArrayList<String>(methodParamNames); } sortedPropertyNames = propertyNames; } public void reset(RestParamsPropertyHolder methodParams, StringToStringMap values) { this.methodParams = methodParams; this.values = values; clearWrappers(); } private void clearWrappers() { for (InternalRestParamProperty property : wrappers.values()) { property.release(); } wrappers.clear(); } public RestParamProperty addProperty(String name) { RestParamProperty property = methodParams.addProperty(name); setParameterLocation(property, NewRestResourceActionBase.ParamLocation.RESOURCE); //setting the param location changes the parent of the property, hence need to get it again return getWrapper(methodParams.getProperty(name)); } public void addParameter(RestParamProperty prop) { methodParams.addParameter(prop); } @Override public void setParameterLocation(RestParamProperty parameter, NewRestResourceActionBase.ParamLocation newLocation) { if (newLocation == parameter.getParamLocation()) { return; } parameterBeingMoved = parameter.getName(); try { ParameterStyle parameterStyle = parameter.getStyle(); String parameterValue = parameter.getValue(); QName type = parameter.getType(); String[] options = parameter.getOptions(); boolean required = parameter.getRequired(); String description = parameter.getDescription(); boolean disableURLEncoding = parameter.isDisableUrlEncoding(); RestParamProperty newParameter; List<String> copyOfSortedPropertyNames = new ArrayList<String>(sortedPropertyNames); if (newLocation == NewRestResourceActionBase.ParamLocation.METHOD) { restRequest.getResource().removeProperty(parameterBeingMoved); newParameter = restRequest.getRestMethod().addProperty(parameterBeingMoved); } else { restRequest.getRestMethod().removeProperty(parameterBeingMoved); newParameter = restRequest.getResource().addProperty(parameterBeingMoved); } newParameter.setType(type); newParameter.setStyle(parameterStyle); newParameter.setValue(parameterValue); newParameter.setDefaultValue(parameterValue); newParameter.setOptions(options); newParameter.setRequired(required); newParameter.setDescription(description); newParameter.setDisableUrlEncoding(disableURLEncoding); restRequest.getProperty(parameterBeingMoved).setValue(parameterValue); sortedPropertyNames = copyOfSortedPropertyNames; firePropertyRemoved(parameterBeingMoved); firePropertyAdded(parameterBeingMoved); } finally { parameterBeingMoved = null; } } public void addTestPropertyListener(TestPropertyListener listener) { listeners.add(listener); } public void clear() { for (String key : getPropertyNames()) { String oldValue = getPropertyValue(key); values.put(key, ""); firePropertyValueChanged(key, oldValue, ""); } } public boolean containsKey(Object key) { return methodParams.containsKey(key); } public boolean containsValue(Object value) { return values.containsValue(value) || methodParams.containsValue(value); } public Set<Entry<String, TestProperty>> entrySet() { Set<Entry<String, TestProperty>> entrySet = methodParams.entrySet(); for (Entry<String, TestProperty> entry : entrySet) { entry.setValue(getWrapper((RestParamProperty) entry.getValue())); } return entrySet; } public RestParamProperty get(Object key) { if (!methodParams.containsKey(key)) { return null; } return getWrapper(methodParams.get(key)); } public ModelItem getModelItem() { return this.restRequest; } public Map<String, TestProperty> getProperties() { Map<String, TestProperty> map = methodParams.getProperties(); for (Entry<String, TestProperty> entry : map.entrySet()) { map.put(entry.getKey(), getWrapper((RestParamProperty) entry.getValue())); } return map; } public String getPropertiesLabel() { return methodParams.getPropertiesLabel(); } public RestParamProperty getProperty(String name) { if (!methodParams.hasProperty(name)) { return null; } return getWrapper(methodParams.getProperty(name)); } public RestParamProperty getPropertyAt(int index) { if (methodParams.getPropertyCount() <= index) { return null; } buildPropertyNameList(); String propertyName = sortedPropertyNames.get(index); RestParamProperty propertyToWrap = methodParams.getProperty(propertyName); return getWrapper(propertyToWrap); } public int getPropertyCount() { return methodParams.getPropertyCount(); } public PropertyExpansion[] getPropertyExpansions() { return methodParams.getPropertyExpansions(); } public int getPropertyIndex(String name) { return sortedPropertyNames.indexOf(name); } public String[] getPropertyNames() { return sortedPropertyNames.toArray(new String[sortedPropertyNames.size()]); } public String getPropertyValue(String name) { return values.containsKey(name) ? values.get(name) : methodParams.getPropertyValue(name); } public boolean hasProperty(String name) { return methodParams.hasProperty(name); } public boolean isEmpty() { return methodParams.isEmpty(); } public Set<String> keySet() { return new LinkedHashSet<String>(sortedPropertyNames); } public void moveProperty(String propertyName, int targetIndex) { if (sortedPropertyNames.contains(propertyName)) { int oldIndex = sortedPropertyNames.indexOf(propertyName); String valueAtNewindex = sortedPropertyNames.get(targetIndex); sortedPropertyNames.set(targetIndex, propertyName); sortedPropertyNames.set(oldIndex, valueAtNewindex); firePropertyMoved(propertyName, oldIndex, targetIndex); } } public TestProperty put(String key, TestProperty value) { if (value.getValue() != null) { values.put(key, value.getValue()); } else { values.remove(key); } return get(key); } public void putAll(Map<? extends String, ? extends TestProperty> m) { for (Entry<? extends String, ? extends TestProperty> e : m.entrySet()) { put(e.getKey(), e.getValue()); } } public TestProperty remove(Object key) { return removeProperty((String) key); } public RestParamProperty removeProperty(String propertyName) { values.remove(propertyName); RestParamProperty property = methodParams.removeProperty(propertyName); sortedPropertyNames.remove(propertyName); firePropertyRemoved(propertyName); return property; } public void removeTestPropertyListener(TestPropertyListener listener) { listeners.remove(listener); } public boolean renameProperty(String name, String newName) { if (name.equals(newName)) { return false; } RestParamProperty parameter = methodParams.getProperty(name); boolean renamePerformed; if (parameter.getParamLocation() == NewRestResourceActionBase.ParamLocation.METHOD) { renamePerformed = methodParams.renameProperty(name, newName); } else { renamePerformed = restRequest.getResource().renameProperty(name, newName); } if (renamePerformed) { RestRequestConfig requestConfig = restRequest.getConfig(); if (requestConfig.isSetParameterOrder()) { List<String> entryList = requestConfig.getParameterOrder().getEntryList(); for (int i = 0; i < entryList.size(); i++) { if (entryList.get(i).equals(name)) { requestConfig.getParameterOrder().setEntryArray(i, newName); break; } } } buildPropertyNameList(); } return renamePerformed; } public void resetValues() { values.clear(); } public void release() { methodParams.removeTestPropertyListener(this); clearWrappers(); } public void saveTo(Properties props) { int count = getPropertyCount(); for (int i = 0; i < count; i++) { RestParamProperty p = getPropertyAt(i); String name = p.getName(); String value = values.containsKey(name) ? values.get(name) : p.getValue(); if (value == null) { value = ""; } props.setProperty(name, value); } } public void setPropertiesLabel(String propertiesLabel) { // methodParams.setPropertiesLabel(propertiesLabel); } public void setPropertyValue(String name, String value) { if (value == null) { values.remove(name); } else { values.put(name, value); } } public int size() { return methodParams.size(); } public Collection<TestProperty> values() { List<TestProperty> ret = new ArrayList<TestProperty>(); for (TestProperty p : methodParams.values()) { ret.add(getWrapper((RestParamProperty) p)); } return ret; } private void firePropertyAdded(String name) { saveParameterOrder(); TestPropertyListener[] listenersArray = listeners.toArray(new TestPropertyListener[listeners.size()]); for (TestPropertyListener listener : listenersArray) { listener.propertyAdded(name); } } private void firePropertyRemoved(String name) { saveParameterOrder(); TestPropertyListener[] listenersArray = listeners.toArray(new TestPropertyListener[listeners.size()]); for (TestPropertyListener listener : listenersArray) { listener.propertyRemoved(name); } } private void firePropertyMoved(String name, int oldIndex, int newIndex) { saveParameterOrder(); TestPropertyListener[] listenersArray = listeners.toArray(new TestPropertyListener[listeners.size()]); for (TestPropertyListener listener : listenersArray) { listener.propertyMoved(name, oldIndex, newIndex); } } private void firePropertyRenamed(String oldName, String newName) { saveParameterOrder(); TestPropertyListener[] listenersArray = listeners.toArray(new TestPropertyListener[listeners.size()]); for (TestPropertyListener listener : listenersArray) { listener.propertyRenamed(oldName, newName); } } private void firePropertyValueChanged(String name, String oldValue, String newValue) { TestPropertyListener[] listenersArray = listeners.toArray(new TestPropertyListener[listeners.size()]); for (TestPropertyListener listener : listenersArray) { listener.propertyValueChanged(name, oldValue, newValue); } } private void saveParameterOrder() { StringListConfig mapConfig = StringListConfig.Factory.newInstance(); mapConfig.setEntryArray(keySet().toArray(new String[keySet().size()])); restRequest.getConfig().setParameterOrder(mapConfig); } private RestParamProperty getWrapper(RestParamProperty key) { if (!wrappers.containsKey(key)) { wrappers.put(key, new InternalRestParamProperty(key)); } return wrappers.get(key); } public void propertyAdded(String name) { if (isChangingLocationOfParameter(name)) { return; } if (!sortedPropertyNames.contains(name)) { sortedPropertyNames.add(name); } firePropertyAdded(name); } public void propertyMoved(String name, int oldIndex, int newIndex) { firePropertyMoved(name, oldIndex, newIndex); } public void propertyRemoved(String name) { if (isChangingLocationOfParameter(name)) { return; } sortedPropertyNames.remove(name); values.remove(name); firePropertyRemoved(name); } public void propertyRenamed(String oldName, String newName) { if (values.containsKey(oldName)) { values.put(newName, values.get(oldName)); values.remove(oldName); } else { if (sortedPropertyNames.contains(oldName)) { sortedPropertyNames.set(sortedPropertyNames.indexOf(oldName), newName); } firePropertyRenamed(oldName, newName); } } public void propertyValueChanged(String name, String oldValue, String newValue) { if (!values.containsKey(name)) { values.put(name, newValue); firePropertyValueChanged(name, oldValue, newValue); } } private boolean isChangingLocationOfParameter(String name) { return parameterBeingMoved != null && parameterBeingMoved.equals(name); } public class InternalRestParamProperty implements RestParamProperty, PropertyChangeListener { private RestParamProperty overriddenProp; private PropertyChangeSupport propertySupport; public InternalRestParamProperty(RestParamProperty override) { overriddenProp = override; overriddenProp.addPropertyChangeListener(this); propertySupport = new PropertyChangeSupport(this); } public void addPropertyChangeListener(PropertyChangeListener listener) { propertySupport.addPropertyChangeListener(listener); } public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { propertySupport.addPropertyChangeListener(propertyName, listener); } public boolean isDisableUrlEncoding() { return overriddenProp.isDisableUrlEncoding(); } public void removePropertyChangeListener(PropertyChangeListener listener) { propertySupport.removePropertyChangeListener(listener); } public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { propertySupport.removePropertyChangeListener(propertyName, listener); } public void setDisableUrlEncoding(boolean encode) { overriddenProp.setDisableUrlEncoding(encode); } public void setName(String name) { overriddenProp.setName(name); } public String getDefaultValue() { return overriddenProp.getDefaultValue(); } public String getDescription() { return overriddenProp.getDescription(); } public ModelItem getModelItem() { return restRequest; } public String getName() { return overriddenProp.getName(); } public QName getType() { return overriddenProp.getType(); } public String getValue() { if (values.containsKey(getName()) && values.get(getName()) != null) { return values.get(getName()); } return getDefaultValue(); } public boolean isReadOnly() { return overriddenProp.isReadOnly(); } public void setValue(String value) { String oldValue = getValue(); if (getDefaultValue() != null && getDefaultValue().equals(value)) { value = null; } if (value == null) { values.remove(getName()); } else { values.put(getName(), value); } firePropertyValueChanged(getName(), oldValue, getValue()); } public String[] getOptions() { return overriddenProp.getOptions(); } public boolean getRequired() { return overriddenProp.getRequired(); } public ParameterStyle getStyle() { return overriddenProp.getStyle(); } public void setDefaultValue(String default1) { //overriddenProp.setDefaultValue(default1); } public void setDescription(String description) { overriddenProp.setDescription(description); } public void setOptions(String[] arg0) { overriddenProp.setOptions(arg0); } public void setRequired(boolean arg0) { overriddenProp.setRequired(arg0); } public void setStyle(ParameterStyle style) { overriddenProp.setStyle(style); } @Override public NewRestResourceActionBase.ParamLocation getParamLocation() { return overriddenProp.getParamLocation(); } @Override public void setParamLocation(NewRestResourceActionBase.ParamLocation paramLocation) { overriddenProp.setParamLocation(paramLocation); } public void setType(QName arg0) { overriddenProp.setType(arg0); } public void propertyChange(PropertyChangeEvent evt) { propertySupport.firePropertyChange(evt); } public void release() { overriddenProp.removePropertyChangeListener(this); overriddenProp = null; propertySupport = null; } @Override public String getPath() { return overriddenProp.getPath(); } @Override public void setPath(String path) { overriddenProp.setPath(path); } @Override public boolean isRequestPart() { return false; } @Override public SchemaType getSchemaType() { return overriddenProp.getSchemaType(); } } public List<TestProperty> getPropertyList() { List<TestProperty> propertyList = new ArrayList<TestProperty>(); for (InternalRestParamProperty internalRestParamProperty : wrappers.values()) { propertyList.add(internalRestParamProperty); } return propertyList; } }