/*
* Copyright 2010-2015 Institut Pasteur.
*
* This file is part of Icy.
*
* Icy is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Icy is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Icy. If not, see <http://www.gnu.org/licenses/>.
*/
package icy.gui.component.model;
import icy.util.StringUtil;
import java.util.ArrayList;
import java.util.List;
import javax.swing.event.EventListenerList;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* @author Stephane
*/
public class XMLTreeModel implements TreeModel
{
public static class XMLAdapterNode
{
public Node node;
/**
* Creates a new instance of the XMLAdapterNode class
*/
public XMLAdapterNode(Node node)
{
super();
this.node = node;
}
/**
* Return all children
*/
public List<Node> getChildren()
{
final List<Node> result = new ArrayList<Node>();
if (node.hasAttributes())
{
final NamedNodeMap attributes = node.getAttributes();
final int count = attributes.getLength();
for (int i = 0; i < count; i++)
result.add(attributes.item(i));
}
final NodeList nodes = node.getChildNodes();
final int count = nodes.getLength();
for (int i = 0; i < count; i++)
{
final Node node = nodes.item(i);
if (node instanceof Element)
result.add(node);
}
return result;
}
/**
* Return index of child in this node.
*
* @param child
* The child to look for
* @return index of child, -1 if not present (error)
*/
public int index(XMLAdapterNode child)
{
int result = 0;
for (Node node : getChildren())
{
if (child.node == node)
return result;
result++;
}
return -1; // Should never get here.
}
/**
* Returns an adapter node given a valid index found through
* the method: public int index(XMLAdapterNode child)
*
* @param index
* find this by calling index(XMLAdapterNode)
* @return the desired child
*/
public XMLAdapterNode child(int index)
{
final Node n = getChildren().get(index);
if (n == null)
return null;
return new XMLAdapterNode(n);
}
/**
* Return the number of element children for this element/node
*
* @return int number of element children
*/
public int childCount()
{
return getChildren().size();
}
/**
* Return the value of this node from its sub text nodes
*/
protected String getValue()
{
final NodeList nodes = node.getChildNodes();
final int count = nodes.getLength();
String result = "";
for (int i = 0; i < count; i++)
{
final Node node = nodes.item(i);
// text node
if (!(node instanceof Element))
{
final String value = node.getNodeValue();
if ((value != null) && !StringUtil.equals(value, "null"))
result += value + " ";
}
}
return result.trim();
}
@Override
public String toString()
{
final String nodeName = node.getNodeName();
final String nodeValue = node.getNodeValue();
if (!StringUtil.isEmpty(nodeValue) && !StringUtil.equals(nodeValue, "null"))
return nodeName + " = " + nodeValue;
return nodeName;
}
}
protected Document document;
/**
* listeners
*/
protected EventListenerList listeners = new EventListenerList();
public XMLTreeModel(Document doc)
{
super();
if (doc == null)
throw new NullPointerException();
document = doc;
}
@Override
public Object getRoot()
{
if (document.getDocumentElement() == null)
return null;
return new XMLAdapterNode(document.getDocumentElement());
}
@Override
public Object getChild(Object parent, int index)
{
return ((XMLAdapterNode) parent).child(index);
}
@Override
public int getIndexOfChild(Object parent, Object child)
{
return ((XMLAdapterNode) parent).index((XMLAdapterNode) child);
}
@Override
public int getChildCount(Object parent)
{
return ((XMLAdapterNode) parent).childCount();
}
@Override
public boolean isLeaf(Object node)
{
return ((XMLAdapterNode) node).childCount() == 0;
}
@Override
public void valueForPathChanged(TreePath path, Object newValue)
{
// ignore here
}
/*
* Use these methods to add and remove event listeners.
* (Needed to satisfy TreeModel interface, but not used.)
*/
/**
* Adds a listener for the TreeModelEvent posted after the tree changes.
*
* @see #removeTreeModelListener
* @param l
* the listener to add
*/
@Override
public void addTreeModelListener(TreeModelListener l)
{
listeners.add(TreeModelListener.class, l);
}
/**
* Removes a listener previously added with <B>addTreeModelListener()</B>.
*
* @see #addTreeModelListener
* @param l
* the listener to remove
*/
@Override
public void removeTreeModelListener(TreeModelListener l)
{
listeners.remove(TreeModelListener.class, l);
}
public void fireTreeNodesChanged(TreeModelEvent e)
{
for (TreeModelListener listener : listeners.getListeners(TreeModelListener.class))
listener.treeNodesChanged(e);
}
public void fireTreeNodesInserted(TreeModelEvent e)
{
for (TreeModelListener listener : listeners.getListeners(TreeModelListener.class))
listener.treeNodesInserted(e);
}
public void fireTreeNodesRemoved(TreeModelEvent e)
{
for (TreeModelListener listener : listeners.getListeners(TreeModelListener.class))
listener.treeNodesRemoved(e);
}
public void fireTreeStructureChanged(TreeModelEvent e)
{
for (TreeModelListener listener : listeners.getListeners(TreeModelListener.class))
listener.treeStructureChanged(e);
}
}