/*
* 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.model.tree;
import com.eviware.soapui.model.ModelItem;
import com.eviware.soapui.model.tree.nodes.PropertiesTreeNode;
import com.eviware.soapui.model.tree.nodes.PropertyTreeNode;
import com.eviware.soapui.model.tree.nodes.WorkspaceTreeNode;
import com.eviware.soapui.model.workspace.Workspace;
import org.apache.log4j.Logger;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* The Navigator TreeModel
*
* @author Ole.Matzura
*/
public class SoapUITreeModel implements TreeModel {
private Set<TreeModelListener> listeners = new HashSet<TreeModelListener>();
private SoapUITreeNode workspaceNode;
private final static Logger logger = Logger.getLogger(SoapUITreeModel.class);
private Map<ModelItem, SoapUITreeNode> modelItemMap = new HashMap<ModelItem, SoapUITreeNode>();
private boolean showProperties = false;
public SoapUITreeModel(Workspace workspace) {
workspaceNode = new WorkspaceTreeNode(workspace, this);
mapModelItem(workspaceNode);
}
public Object getRoot() {
return workspaceNode;
}
public Object getChild(Object parent, int index) {
SoapUITreeNode treeNode = (SoapUITreeNode) parent;
return treeNode.getChildNode(index);
}
public int getChildCount(Object parent) {
SoapUITreeNode treeNode = (SoapUITreeNode) parent;
return treeNode.getChildCount();
}
public boolean isLeaf(Object node) {
SoapUITreeNode treeNode = (SoapUITreeNode) node;
return treeNode.isLeaf();
}
public void valueForPathChanged(TreePath path, Object newValue) {
SoapUITreeNode treeNode = (SoapUITreeNode) path.getLastPathComponent();
if (treeNode.valueChanged(newValue)) {
// not implemented.. need to expose setName in ModelItem
}
}
public int getIndexOfChild(Object parent, Object child) {
SoapUITreeNode treeNode = (SoapUITreeNode) parent;
return treeNode.getIndexOfChild(child);
}
public void addTreeModelListener(TreeModelListener l) {
listeners.add(l);
}
public void removeTreeModelListener(TreeModelListener l) {
listeners.remove(l);
}
public void mapModelItem(SoapUITreeNode soapUITreeNode) {
modelItemMap.put(soapUITreeNode.getModelItem(), soapUITreeNode);
}
public void unmapModelItem(ModelItem modelItem) {
if (modelItemMap.containsKey(modelItem)) {
modelItemMap.remove(modelItem);
} else {
logger.error("Failed to unmap model item [" + modelItem.getName() + "]");
Thread.dumpStack();
}
}
public void notifyNodesInserted(TreeModelEvent e) {
Iterator<TreeModelListener> i = listeners.iterator();
while (i.hasNext()) {
i.next().treeNodesInserted(e);
}
}
public void notifyNodesRemoved(TreeModelEvent e) {
Iterator<TreeModelListener> i = listeners.iterator();
while (i.hasNext()) {
i.next().treeNodesRemoved(e);
}
}
public void notifyStructureChanged(TreeModelEvent e) {
Iterator<TreeModelListener> i = listeners.iterator();
while (i.hasNext()) {
i.next().treeStructureChanged(e);
}
}
public void notifyNodesChanged(TreeModelEvent e) {
Iterator<TreeModelListener> i = listeners.iterator();
while (i.hasNext()) {
i.next().treeNodesChanged(e);
}
}
public TreePath getPath(SoapUITreeNode treeNode) {
// SoapUITreeNode treeNode = modelItemMap.get( modelItem );
// if( treeNode == null )
// throw new RuntimeException( "Missing mapping for modelItem " +
// modelItem.getName() );
List<Object> nodes = new ArrayList<Object>();
if (treeNode != null) {
nodes.add(treeNode);
treeNode = treeNode.getParentTreeNode();
while (treeNode != null) {
nodes.add(0, treeNode);
treeNode = treeNode.getParentTreeNode();
}
}
return nodes.isEmpty() ? null : new TreePath(nodes.toArray());
}
public void notifyNodeChanged(SoapUITreeNode treeNode) {
SoapUITreeNode parent = treeNode.getParentTreeNode();
if (parent == null) {
notifyNodesChanged(new TreeModelEvent(this, new Object[]{treeNode}));
return;
}
int ix = parent.getIndexOfChild(treeNode);
if (ix == -1) {
if ((!(treeNode instanceof PropertyTreeNode) && !(treeNode instanceof PropertiesTreeNode))
|| isShowProperties()) {
logger.error("Changed node [" + treeNode + "] not found in parent [" + parent + "]");
}
return;
}
if (!(treeNode instanceof PropertyTreeNode) || showProperties) {
notifyNodesChanged(new TreeModelEvent(this, getPath(parent), new int[]{ix},
new Object[]{parent.getChildNode(ix)}));
}
}
public void notifyNodeInserted(SoapUITreeNode treeNode) {
SoapUITreeNode parent = treeNode.getParentTreeNode();
int ix = parent.getIndexOfChild(treeNode);
if (ix == -1) {
logger.error("Inserted node [" + treeNode + "] not found in parent [" + parent + "]");
return;
}
mapModelItem(treeNode);
if (!(treeNode instanceof PropertyTreeNode) || showProperties) {
notifyNodesInserted(new TreeModelEvent(this, getPath(parent), new int[]{ix},
new Object[]{parent.getChildNode(ix)}));
}
}
public void notifyNodeRemoved(SoapUITreeNode treeNode) {
notifyNodeRemoved(treeNode, true);
}
public void notifyNodeRemoved(SoapUITreeNode treeNode, boolean release) {
SoapUITreeNode parent = treeNode.getParentTreeNode();
int ix = parent.getIndexOfChild(treeNode);
if (ix == -1) {
logger.error("Removed node [" + treeNode + "] not found in parent [" + parent + "]");
return;
}
if (!(treeNode instanceof PropertyTreeNode) || showProperties) {
notifyNodesRemoved(new TreeModelEvent(this, getPath(parent), new int[]{ix},
new Object[]{parent.getChildNode(ix)}));
}
if (release) {
treeNode.release();
}
}
public SoapUITreeNode getTreeNode(ModelItem parentItem) {
return modelItemMap.get(parentItem);
}
public TreePath getPath(ModelItem modelItem) {
return getPath(modelItemMap.get(modelItem));
}
public void mapModelItems(List<? extends SoapUITreeNode> treeNodes) {
Iterator<? extends SoapUITreeNode> iterator = treeNodes.iterator();
while (iterator.hasNext()) {
SoapUITreeNode item = iterator.next();
mapModelItem(item);
}
}
public boolean isShowProperties() {
return showProperties;
}
public void setShowProperties(boolean showProperties) {
if (this.showProperties != showProperties) {
this.showProperties = showProperties;
notifyStructureChanged(new TreeModelEvent(this, getPath(workspaceNode)));
}
}
}