KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > methodhead > tree > Tree


1 /*
2  * Copyright (C) 2006 Methodhead Software LLC. All rights reserved.
3  *
4  * This file is part of TransferCM.
5  *
6  * TransferCM is free software; you can redistribute it and/or modify it under the
7  * terms of the GNU General Public License as published by the Free Software
8  * Foundation; either version 2 of the License, or (at your option) any later
9  * version.
10  *
11  * TransferCM is distributed in the hope that it will be useful, but WITHOUT ANY
12  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14  * details.
15  *
16  * You should have received a copy of the GNU General Public License along with
17  * TransferCM; if not, write to the Free Software Foundation, Inc., 51 Franklin St,
18  * Fifth Floor, Boston, MA 02110-1301 USA
19  */

20
21 package com.methodhead.tree;
22
23 import javax.swing.tree.DefaultMutableTreeNode JavaDoc;
24 import java.util.Enumeration JavaDoc;
25 import com.methodhead.MhfException;
26 import java.util.Collections JavaDoc;
27 import java.util.Iterator JavaDoc;
28 import java.util.List JavaDoc;
29 import java.util.ArrayList JavaDoc;
30 import java.util.Comparator JavaDoc;
31
32 /**
33  * A tree of <tt>DefaultMutableTreeNode</tt>s. This class methods to manage
34  * nodes in the tree.
35  */

36 public class Tree {
37
38   // constructors /////////////////////////////////////////////////////////////
39

40   // constants ////////////////////////////////////////////////////////////////
41

42   public static final String JavaDoc POSITION_UNDER = "POSITION_UNDER";
43   public static final String JavaDoc POSITION_AFTER = "POSITION_AFTER";
44   public static final String JavaDoc POSITION_BEFORE = "POSITION_BEFORE";
45
46   public static final String JavaDoc INVALIDMOVE_CANNOTMOVEROOT =
47     "INVALIDMOVE_CANNOTMOVEROOT";
48   public static final String JavaDoc INVALIDMOVE_CANNOTMOVEBEFOREROOT =
49     "INVALIDMOVE_CANNOTMOVEBEFOREROOT";
50   public static final String JavaDoc INVALIDMOVE_CANNOTMOVEAFTERROOT =
51     "INVALIDMOVE_CANNOTMOVEAFTERROOT";
52   public static final String JavaDoc INVALIDMOVE_CANNOTMOVENEARSELF =
53     "INVALIDMOVE_CANNOTMOVENEARSELF";
54   public static final String JavaDoc INVALIDMOVE_CANNOTMOVEUNDERSELF =
55     "INVALIDMOVE_CANNOTMOVEUNDERSELF";
56
57   public static final String JavaDoc VALIDMOVE = "VALIDMOVE";
58
59   // classes //////////////////////////////////////////////////////////////////
60

61   // methods //////////////////////////////////////////////////////////////////
62

63   /**
64    * Returns the root of the tree or <tt>null</tt> if there is none.
65    */

66   public DefaultMutableTreeNode JavaDoc getRoot() {
67     return root_;
68   }
69
70   /**
71    * Sets the root of the tree; note: any existing nodes will be lost.
72    */

73   public void setRoot(
74     DefaultMutableTreeNode JavaDoc link ) {
75     root_ = link;
76   }
77
78   /**
79    * Inserts <tt>node</tt> under <tt>dest</tt>.
80    */

81   public void insertUnder(
82     DefaultMutableTreeNode JavaDoc dest,
83     DefaultMutableTreeNode JavaDoc node ) {
84
85     dest.add( node );
86   }
87
88   /**
89    * Inserts <tt>node</tt> after <tt>dest</tt>, throwing an
90    * exception if <tt>dest</tt> is the root.
91    */

92   public void insertAfter(
93     DefaultMutableTreeNode JavaDoc dest,
94     DefaultMutableTreeNode JavaDoc node ) {
95
96     if ( dest == root_ )
97       throw new MhfException( "Can't insert after the root node." );
98
99     DefaultMutableTreeNode JavaDoc p = ( DefaultMutableTreeNode JavaDoc )dest.getParent();
100     p.insert( node, p.getIndex( dest ) + 1 );
101   }
102
103   /**
104    * Inserts <tt>node</tt> before <tt>dest</tt>, throwing an
105    * exception if <tt>dest</tt> is the root.
106    */

107   public void insertBefore(
108     DefaultMutableTreeNode JavaDoc dest,
109     DefaultMutableTreeNode JavaDoc node ) {
110
111     if ( dest == root_ )
112       throw new MhfException(
113         "Can't insert before the root node." );
114
115     DefaultMutableTreeNode JavaDoc p = ( DefaultMutableTreeNode JavaDoc )dest.getParent();
116     p.insert( node, p.getIndex( dest ) );
117   }
118
119   /**
120    * Removes <tt>node</tt> and all of its children from the tree.
121    */

122   public void remove(
123     DefaultMutableTreeNode JavaDoc node ) {
124
125     if ( node == root_ )
126       root_ = null;
127     else
128       node.removeFromParent();
129     
130   }
131
132   /**
133    * Removes <tt>node</tt>, adding its child nodes to the parent node. If
134    * <tt>node</tt> is the root, its first child is promoted to root, adding its
135    * children after the root's remaining children.
136    */

137   public void removeAndPromoteChildren(
138     DefaultMutableTreeNode JavaDoc node ) {
139
140     DefaultMutableTreeNode JavaDoc tmp = null;
141     DefaultMutableTreeNode JavaDoc tmp2 = null;
142     
143     if ( node == root_ ) {
144       if ( root_.getChildCount() == 0 )
145         root_ = null;
146
147       else if ( root_.getChildCount() == 1 ) {
148         tmp = ( DefaultMutableTreeNode JavaDoc )root_.getChildAt( 0 );
149         root_.remove( tmp );
150         root_ = tmp;
151       }
152       else {
153         tmp = ( DefaultMutableTreeNode JavaDoc )root_.getChildAt( 0 );
154         root_.remove( tmp );
155
156         for ( int i = root_.getChildCount() - 1; i >= 0; i-- ) {
157           tmp2 = ( DefaultMutableTreeNode JavaDoc )root_.getChildAt( i );
158           root_.remove( tmp2 );
159           tmp.insert( tmp2, 0 );
160         }
161
162         root_ = tmp;
163       }
164     }
165     else {
166       for ( int i = 0; i < node.getChildCount(); i++ ) {
167         ( ( DefaultMutableTreeNode JavaDoc )node.getParent() ).add(
168           ( DefaultMutableTreeNode JavaDoc )node.getChildAt( i ) );
169       }
170
171       node.removeFromParent();
172     }
173   }
174
175   /**
176    * Confirms if <tt>dest</tt> can be positioned <tt>position</tt> (one of the
177    * <tt>POSITION_</tt> constants) near <tt>node</tt> successfully. If so,
178    * <tt>VALIDMOVE</tt> is returned, otherwise on of the <tt>INVALIDMOVE_</tt>
179    * constants is returned.
180    */

181   public String JavaDoc validateMove(
182     DefaultMutableTreeNode JavaDoc node,
183     DefaultMutableTreeNode JavaDoc dest,
184     String JavaDoc position ) {
185
186     if ( node == root_ )
187       return INVALIDMOVE_CANNOTMOVEROOT;
188
189     if ( ( dest == root_ ) && POSITION_BEFORE.equals( position ) )
190       return INVALIDMOVE_CANNOTMOVEBEFOREROOT;
191
192     if ( ( dest == root_ ) && POSITION_AFTER.equals( position ) )
193       return INVALIDMOVE_CANNOTMOVEAFTERROOT;
194
195     if ( dest == node )
196       return INVALIDMOVE_CANNOTMOVENEARSELF;
197
198     if ( dest.isNodeAncestor( node ) )
199       return INVALIDMOVE_CANNOTMOVEUNDERSELF;
200
201     return VALIDMOVE;
202   }
203
204   /**
205    * Moves <tt>node</tt> under <tt>dest</tt>. An exception is thrown if
206    * <tt>node</tt> is an ancestor of <tt>dest</tt>.
207    */

208   public void moveUnder(
209     DefaultMutableTreeNode JavaDoc dest,
210     DefaultMutableTreeNode JavaDoc node ) {
211
212     if ( dest.isNodeAncestor( node ) )
213       throw new MhfException( "Can't move node under itself." );
214
215     node.removeFromParent();
216     dest.add( node );
217   }
218
219   /**
220    * Moves <tt>node</tt> after <tt>dest</tt>. An exception is thrown if
221    * <tt>node</tt> is an ancestor of <tt>dest</tt>, or if <tt>dest</tt> is the
222    * root.
223    */

224   public void moveAfter(
225     DefaultMutableTreeNode JavaDoc dest,
226     DefaultMutableTreeNode JavaDoc node ) {
227
228     if ( dest == root_ )
229       throw new MhfException( "Can't move node after root." );
230
231     if ( dest.isNodeAncestor( node ) )
232       throw new MhfException( "Can't move node under itself." );
233
234     node.removeFromParent();
235     insertAfter( dest, node );
236   }
237
238   /**
239    * Moves <tt>node</tt> after <tt>dest</tt>. An exception is thrown if
240    * <tt>node</tt> is an ancestor of <tt>dest</tt>, or if <tt>dest</tt> is the
241    * root.
242    */

243   public void moveBefore(
244     DefaultMutableTreeNode JavaDoc dest,
245     DefaultMutableTreeNode JavaDoc node ) {
246
247     if ( dest == root_ )
248       throw new MhfException( "Can't move node after root." );
249
250     if ( dest.isNodeAncestor( node ) )
251       throw new MhfException( "Can't move node under itself." );
252
253     node.removeFromParent();
254     insertBefore( dest, node );
255   }
256
257   /**
258    * Sorts the children of <tt>node</tt> using <tt>comparator</tt>;
259    * <tt>comparator</tt> should expect <tt>DefaultMutableTreeNode</tt>s to be
260    * passed to it.
261    */

262   public static void sort(
263     DefaultMutableTreeNode JavaDoc node,
264     Comparator JavaDoc comparator ) {
265
266     //
267
// no children
268
//
269
if ( node.getChildCount() == 0 )
270       return;
271
272     List JavaDoc list = new ArrayList JavaDoc();
273     for ( int i = 0; i < node.getChildCount(); i++ ) {
274       DefaultMutableTreeNode JavaDoc n = ( DefaultMutableTreeNode JavaDoc )node.getChildAt( i );
275       n.removeFromParent();
276       list.add( n );
277     }
278
279     Collections.sort( list, comparator );
280
281     for ( Iterator JavaDoc iter = list.iterator(); iter.hasNext(); ) {
282       DefaultMutableTreeNode JavaDoc n = ( DefaultMutableTreeNode JavaDoc )iter.next();
283       node.add( n );
284     }
285   }
286
287   /**
288    * Recursively copies <tt>node</tt> using its <tt>clone()</tt> method (which,
289    * unless overridden, is a shallow copy).
290    */

291   public static DefaultMutableTreeNode JavaDoc copy(
292     DefaultMutableTreeNode JavaDoc node ) {
293
294     DefaultMutableTreeNode JavaDoc n = ( DefaultMutableTreeNode JavaDoc )node.clone();
295
296     for ( int i = 0; i < node.getChildCount(); i++ )
297       n.add( copy( ( DefaultMutableTreeNode JavaDoc )node.getChildAt( i ) ) );
298
299     return n;
300   }
301
302   // properties ///////////////////////////////////////////////////////////////
303

304   // attributes ///////////////////////////////////////////////////////////////
305

306   protected DefaultMutableTreeNode JavaDoc root_ = null;
307 }
308
Popular Tags