/*
* Copyright 2004-2014 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.wsdl.support;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import javax.xml.namespace.QName;
import org.apache.xmlbeans.SchemaType;
import org.apache.xmlbeans.XmlString;
import com.eviware.soapui.SoapUI;
import com.eviware.soapui.config.PropertiesTypeConfig;
import com.eviware.soapui.config.PropertyConfig;
import com.eviware.soapui.impl.wsdl.MutableTestPropertyHolder;
import com.eviware.soapui.impl.wsdl.support.wsdl.UrlWsdlLoader;
import com.eviware.soapui.model.ModelItem;
import com.eviware.soapui.model.propertyexpansion.PropertyExpansion;
import com.eviware.soapui.model.support.TestPropertyUtils;
import com.eviware.soapui.model.testsuite.RenameableTestProperty;
import com.eviware.soapui.model.testsuite.TestProperty;
import com.eviware.soapui.model.testsuite.TestPropertyListener;
import com.eviware.soapui.support.StringUtils;
public class XmlBeansPropertiesTestPropertyHolder implements MutableTestPropertyHolder, Map<String, TestProperty> {
private PropertiesTypeConfig config;
private List<PropertiesStepProperty> properties = new ArrayList<PropertiesStepProperty>();
private Map<String, PropertiesStepProperty> propertyMap = new LinkedHashMap<String, PropertiesStepProperty>();
private Set<TestPropertyListener> listeners = new HashSet<TestPropertyListener>();
private ModelItem modelItem;
private Properties overrideProperties;
private String propertiesLabel = "Test Properties";
public XmlBeansPropertiesTestPropertyHolder(ModelItem modelItem, PropertiesTypeConfig config) {
this.modelItem = modelItem;
this.config = config;
for (int c = 0; c < config.sizeOfPropertyArray(); c++) {
PropertyConfig propertyConfig = config.getPropertyArray(c);
if (StringUtils.hasContent(propertyConfig.getName())) {
addProperty(propertyConfig, false, null);
} else {
config.removeProperty(c);
c--;
}
}
}
protected PropertiesStepProperty addProperty(PropertyConfig propertyConfig, boolean notify,
TestProperty virtualProperty) {
PropertiesStepProperty propertiesStepProperty = new PropertiesStepProperty(propertyConfig, virtualProperty);
properties.add(propertiesStepProperty);
sortVirtualLast();
propertyMap.put(propertiesStepProperty.getName().toUpperCase(), propertiesStepProperty);
if (notify) {
firePropertyAdded(propertiesStepProperty.getName());
}
return propertiesStepProperty;
}
/**
* sort properties list and make sure that virtualproperties are always
* placed after properties
*/
private void sortVirtualLast() {
List<PropertiesStepProperty> virtualProperties = new ArrayList<PropertiesStepProperty>();
List<PropertiesStepProperty> nonVirtualProperties = new ArrayList<PropertiesStepProperty>();
for (PropertiesStepProperty psp : properties) {
if (psp.isVirtualProperty()) {
if (!virtualProperties.contains(psp)) {
virtualProperties.add(psp);
}
} else {
nonVirtualProperties.add(psp);
}
}
properties.clear();
properties.addAll(nonVirtualProperties);
properties.addAll(virtualProperties);
}
private void firePropertyAdded(String name) {
TestPropertyListener[] listenersArray = listeners.toArray(new TestPropertyListener[listeners.size()]);
for (TestPropertyListener listener : listenersArray) {
listener.propertyAdded(name);
}
}
private void firePropertyRemoved(String name) {
TestPropertyListener[] listenersArray = listeners.toArray(new TestPropertyListener[listeners.size()]);
for (TestPropertyListener listener : listenersArray) {
listener.propertyRemoved(name);
}
}
private void firePropertyMoved(String name, int oldIndex, int newIndex) {
TestPropertyListener[] listenersArray = listeners.toArray(new TestPropertyListener[listeners.size()]);
for (TestPropertyListener listener : listenersArray) {
listener.propertyMoved(name, oldIndex, newIndex);
}
}
private void firePropertyRenamed(String oldName, String newName) {
TestPropertyListener[] listenersArray = listeners.toArray(new TestPropertyListener[listeners.size()]);
for (TestPropertyListener listener : listenersArray) {
listener.propertyRenamed(oldName, newName);
}
}
public TestProperty addProperty(String name) {
PropertyConfig propertyConfig = config.addNewProperty();
propertyConfig.setName(name);
return addProperty(propertyConfig, true, null);
}
public TestProperty addVirtualProperty(String key, TestProperty virtualProperty) {
PropertyConfig propertyConfig = PropertyConfig.Factory.newInstance();
propertyConfig.setName(key);
return addProperty(propertyConfig, true, virtualProperty);
}
public void addTestPropertyListener(TestPropertyListener listener) {
listeners.add(listener);
}
public PropertiesStepProperty getProperty(String name) {
return propertyMap.get(name.toUpperCase());
}
public String[] getPropertyNames() {
String[] result = new String[properties.size()];
for (int c = 0; c < properties.size(); c++) {
result[c] = properties.get(c).getName();
}
return result;
}
public List<TestProperty> getPropertyList() {
List<TestProperty> result = new ArrayList<TestProperty>();
for (TestProperty property : properties) {
result.add(property);
}
return result;
}
public String getPropertyValue(String name) {
TestProperty property = getProperty(name);
return property == null ? null : property.getValue();
}
public TestProperty removeProperty(String propertyName) {
TestProperty property = getProperty(propertyName);
if (property != null) {
if (property instanceof PropertiesStepProperty && ((PropertiesStepProperty) property).isVirtualProperty()) {
return property;
}
int ix = properties.indexOf(property);
propertyMap.remove(propertyName.toUpperCase());
properties.remove(ix);
firePropertyRemoved(propertyName);
config.removeProperty(ix);
return property;
}
return null;
}
public void removeTestPropertyListener(TestPropertyListener listener) {
listeners.remove(listener);
}
public void setPropertyValue(String name, String value) {
PropertiesStepProperty property = getProperty(name);
if (property != null) {
property.setValue(value);
} else {
addProperty(name).setValue(value);
}
}
public void resetPropertiesConfig(PropertiesTypeConfig config) {
this.config = config;
for (int c = 0; c < config.sizeOfPropertyArray(); c++) {
properties.get(c).setConfig(config.getPropertyArray(c));
}
}
public boolean renameProperty(String name, String newName) {
if (getProperty(newName) != null) {
return false;
}
PropertiesStepProperty property = getProperty(name);
if (property == null) {
return false;
}
property.setName(newName);
return true;
}
/**
* Internal property class
*
* @author ole
*/
public class PropertiesStepProperty implements RenameableTestProperty {
private PropertyConfig propertyConfig;
private final TestProperty virtualProperty;
public PropertiesStepProperty(PropertyConfig propertyConfig, TestProperty virtualProperty) {
this.propertyConfig = propertyConfig;
this.virtualProperty = virtualProperty;
}
public boolean isVirtualProperty() {
return virtualProperty != null;
}
public void setConfig(PropertyConfig propertyConfig) {
this.propertyConfig = propertyConfig;
}
public String getName() {
return propertyConfig.getName();
}
public void setName(String name) {
String oldName = getName();
propertyConfig.setName(name);
propertyMap.remove(oldName.toUpperCase());
propertyMap.put(name.toUpperCase(), this);
firePropertyRenamed(oldName, name);
}
public String getDescription() {
if (virtualProperty != null) {
return virtualProperty.getDescription();
}
return null;
}
public String getValue() {
if (overrideProperties != null && overrideProperties.containsKey(getName())) {
return overrideProperties.getProperty(getName());
}
if (virtualProperty != null) {
return virtualProperty.getValue();
}
return propertyConfig.getValue();
}
public void setValue(String value) {
String oldValue = getValue();
propertyConfig.setValue(value);
if (overrideProperties != null && overrideProperties.containsKey(getName())) {
overrideProperties.remove(getName());
if (overrideProperties.isEmpty()) {
overrideProperties = null;
}
}
firePropertyValueChanged(getName(), oldValue, value);
}
public void firePropertyValueChanged(String name, String oldValue, String newValue) {
XmlBeansPropertiesTestPropertyHolder.this.firePropertyValueChanged(name, oldValue, newValue);
}
public boolean isReadOnly() {
if (virtualProperty != null) {
return virtualProperty.isReadOnly();
}
return false;
}
public QName getType() {
if (virtualProperty != null) {
return virtualProperty.getType();
}
return XmlString.type.getName();
}
public ModelItem getModelItem() {
return modelItem;
}
public String getDefaultValue() {
if (virtualProperty != null) {
return virtualProperty.getDefaultValue();
}
return null;
}
@Override
public boolean isRequestPart() {
return false;
}
@Override
public SchemaType getSchemaType() {
if (virtualProperty != null) {
return virtualProperty.getSchemaType();
}
return XmlString.type;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof TestProperty) {
TestProperty testProperty = (TestProperty) obj;
if (getModelItem() != null && testProperty.getModelItem() != null) {
return getModelItem().equals(testProperty.getModelItem()) && getName().equals(testProperty.getName());
} else {
return getName().equals(testProperty.getName());
}
} else {
return false;
}
}
@Override
public int hashCode() {
return super.hashCode();
}
}
public 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);
}
}
public int saveTo(String fileName) throws IOException {
return TestPropertyUtils.saveTo(this, fileName);
}
public int getPropertyCount() {
return properties.size();
}
public TestProperty getPropertyAt(int index) {
return properties.get(index);
}
public Map<String, TestProperty> getProperties() {
Map<String, TestProperty> result = new LinkedHashMap<String, TestProperty>();
for (TestProperty property : propertyMap.values()) {
result.put(property.getName(), property);
}
return result;
}
public boolean hasProperty(String name) {
return propertyMap.containsKey(name.toUpperCase());
}
public int addPropertiesFromFile(String propFile) {
if (!StringUtils.hasContent(propFile)) {
return 0;
}
try {
InputStream input = null;
File file = new File(propFile);
if (file.exists()) {
input = new FileInputStream(file);
} else if (propFile.toLowerCase().startsWith("http://") || propFile.toLowerCase().startsWith("https://")) {
UrlWsdlLoader loader = new UrlWsdlLoader(propFile, getModelItem());
loader.setUseWorker(false);
input = loader.load();
}
if (input != null) {
if (overrideProperties == null) {
overrideProperties = new Properties();
}
int sz = overrideProperties.size();
overrideProperties.load(input);
for (Object key : overrideProperties.keySet()) {
String name = key.toString();
if (!hasProperty(name)) {
addProperty(name);
}
}
return overrideProperties.size() - sz;
}
} catch (Exception e) {
SoapUI.logError(e);
}
return 0;
}
public ModelItem getModelItem() {
return modelItem;
}
public PropertyExpansion[] getPropertyExpansions() {
List<PropertyExpansion> result = new ArrayList<PropertyExpansion>();
return result.toArray(new PropertyExpansion[result.size()]);
}
public void moveProperty(String propertyName, int targetIndex) {
PropertiesStepProperty property = getProperty(propertyName);
int ix = properties.indexOf(property);
if (ix == targetIndex) {
return;
}
if (targetIndex < 0) {
targetIndex = 0;
}
String value = property.getValue();
config.removeProperty(ix);
PropertyConfig propertyConfig = null;
if (targetIndex < properties.size()) {
properties.add(targetIndex, properties.remove(ix));
propertyConfig = config.insertNewProperty(targetIndex);
} else {
properties.add(properties.remove(ix));
propertyConfig = config.addNewProperty();
}
propertyConfig.setName(propertyName);
propertyConfig.setValue(value);
resetPropertiesConfig(config);
if (targetIndex > properties.size()) {
targetIndex = properties.size();
}
firePropertyMoved(propertyName, ix, targetIndex);
}
public void clear() {
while (size() > 0) {
removeProperty(getPropertyAt(0).getName());
}
}
public boolean containsKey(Object key) {
return hasProperty((String) key);
}
public boolean containsValue(Object value) {
return propertyMap.containsValue(value);
}
public Set<java.util.Map.Entry<String, TestProperty>> entrySet() {
HashSet<java.util.Map.Entry<String, TestProperty>> result = new HashSet<Entry<String, TestProperty>>();
for (TestProperty p : propertyMap.values()) {
// This does not compile on JDK 1.5:
// result.add( new java.util.HashMap.SimpleEntry<String,
// TestProperty>(p.getName(), p));
result.add(new HashMapEntry<String, TestProperty>(p.getName(), p));
}
return result;
}
private static class HashMapEntry<K, V> implements java.util.Map.Entry<K, V> {
private K key;
private V value;
public HashMapEntry(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey() {
return key;
}
public V getValue() {
return value;
}
public V setValue(V value) {
throw new UnsupportedOperationException();
}
}
public TestProperty get(Object key) {
return getProperty((String) key);
}
public boolean isEmpty() {
return propertyMap.isEmpty();
}
public Set<String> keySet() {
return new HashSet<String>(Arrays.asList(getPropertyNames()));
}
public TestProperty put(String key, TestProperty value) {
TestProperty result = addProperty(key);
result.setValue(value.getValue());
return result;
}
public void putAll(Map<? extends String, ? extends TestProperty> m) {
for (TestProperty p : m.values()) {
addProperty(p.getName()).setValue(p.getValue());
}
}
public TestProperty remove(Object key) {
return removeProperty((String) key);
}
public int size() {
return propertyMap.size();
}
public Collection<TestProperty> values() {
ArrayList<TestProperty> result = new ArrayList<TestProperty>();
result.addAll(propertyMap.values());
return result;
}
public String getPropertiesLabel() {
return propertiesLabel;
}
public void setPropertiesLabel(String propertiesLabel) {
this.propertiesLabel = propertiesLabel;
}
}