001    /**
002     * Copyright (C) 2007-2008, Jens Lehmann
003     *
004     * This file is part of DL-Learner.
005     * 
006     * DL-Learner is free software; you can redistribute it and/or modify
007     * it under the terms of the GNU General Public License as published by
008     * the Free Software Foundation; either version 3 of the License, or
009     * (at your option) any later version.
010     *
011     * DL-Learner is distributed in the hope that it will be useful,
012     * but WITHOUT ANY WARRANTY; without even the implied warranty of
013     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014     * GNU General Public License for more details.
015     *
016     * You should have received a copy of the GNU General Public License
017     * along with this program.  If not, see <http://www.gnu.org/licenses/>.
018     *
019     */
020    package org.dllearner.gui;
021    
022    import java.util.LinkedList;
023    import java.util.List;
024    import java.util.Map;
025    import java.util.SortedSet;
026    import java.util.TreeMap;
027    
028    import javax.swing.event.TreeModelEvent;
029    import javax.swing.event.TreeModelListener;
030    import javax.swing.tree.TreeModel;
031    import javax.swing.tree.TreePath;
032    
033    import org.dllearner.algorithms.refinement2.ExampleBasedNode;
034    import org.dllearner.algorithms.refinement2.NodeComparatorStable;
035    
036    /**
037     * A tree model used for displaying example based nodes. A search tree can
038     * become very large, so lazy loading should be used, i.e. never load the full
039     * search tree but only the nodes selected by the user. Note that the search
040     * tree changes over time.
041     * 
042     * @author Jens Lehmann
043     * 
044     */
045    public class EBNodeTreeModel implements TreeModel {
046    
047            // root of the search tree
048            private ExampleBasedNode rootNode;
049    
050            // a mapping from nodes to their children;
051            // the main problem is that example based nodes use sets instead
052            // of lists, so we need to convert these sets to lists and store
053            // them here
054            private Map<ExampleBasedNode, List<ExampleBasedNode>> childrenMap = new TreeMap<ExampleBasedNode, List<ExampleBasedNode>>(
055                            new NodeComparatorStable());
056    
057            // listeners for this model
058            private List<TreeModelListener> treeModelListeners = new LinkedList<TreeModelListener>();
059    
060            public EBNodeTreeModel(ExampleBasedNode rootNode) {
061                    this.rootNode = rootNode;
062            }
063    
064            public void addTreeModelListener(TreeModelListener l) {
065                    treeModelListeners.add(l);
066            }
067    
068            public Object getChild(Object parent, int index) {
069                    return getChildren((ExampleBasedNode) parent).get(index);
070            }
071    
072            public int getChildCount(Object parent) {
073                    return ((ExampleBasedNode) parent).getChildren().size();
074            }
075    
076            public int getIndexOfChild(Object parent, Object child) {
077                    return getChildren((ExampleBasedNode) parent).indexOf(child);
078            }
079    
080            public Object getRoot() {
081                    return rootNode;
082            }
083    
084            public boolean isLeaf(Object node) {
085                    return (getChildCount(node) == 0);
086            }
087    
088            public void removeTreeModelListener(TreeModelListener l) {
089                    treeModelListeners.remove(l);
090            }
091    
092            public void valueForPathChanged(TreePath path, Object newValue) {
093    
094            }
095    
096            @SuppressWarnings("unused")
097            private void fireTreeStructureChanged(ExampleBasedNode node) {
098                    TreeModelEvent e = new TreeModelEvent(this, new Object[] { node });
099                    for (TreeModelListener tml : treeModelListeners) {
100                            tml.treeStructureChanged(e);
101                    }
102            }
103    
104            // convert the set of children to a list and store it in this model
105            private List<ExampleBasedNode> getChildren(ExampleBasedNode node) {
106                    // System.out.println("asking for children of " + node);
107    
108                    List<ExampleBasedNode> children = childrenMap.get(node);
109                    // if the children have not been cached or the list is outdated
110                    // (node has more children now) we do an update
111                    if (children == null || children.size() != node.getChildren().size()) {
112                            SortedSet<ExampleBasedNode> childrenSet = node.getChildren();
113                            children = new LinkedList<ExampleBasedNode>(childrenSet);
114    
115                            // we need to ensure that the children are sorted correctly
116                            // children = new LinkedList<ExampleBasedNode>();
117                            // for(ExampleBasedNode child : childrenSet) {
118                            // children.add(child);
119                            // }
120    
121                            childrenMap.put(node, children);
122    
123                            // fireTreeStructureChanged(node);
124                            // System.out.println("updating children of " + node);
125                    }
126                    return children;
127            }
128    
129    }