001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/portal/context/Node.java $
002    /*----------------------------------------------------------------------------
003     This file is part of deegree, http://deegree.org/
004     Copyright (C) 2001-2009 by:
005       Department of Geography, University of Bonn
006     and
007       lat/lon GmbH
008    
009     This library is free software; you can redistribute it and/or modify it under
010     the terms of the GNU Lesser General Public License as published by the Free
011     Software Foundation; either version 2.1 of the License, or (at your option)
012     any later version.
013     This library is distributed in the hope that it will be useful, but WITHOUT
014     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
015     FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
016     details.
017     You should have received a copy of the GNU Lesser General Public License
018     along with this library; if not, write to the Free Software Foundation, Inc.,
019     59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020    
021     Contact information:
022    
023     lat/lon GmbH
024     Aennchenstr. 19, 53177 Bonn
025     Germany
026     http://lat-lon.de/
027    
028     Department of Geography, University of Bonn
029     Prof. Dr. Klaus Greve
030     Postfach 1147, 53001 Bonn
031     Germany
032     http://www.geographie.uni-bonn.de/deegree/
033    
034     e-mail: info@deegree.org
035    ----------------------------------------------------------------------------*/
036    package org.deegree.portal.context;
037    
038    import java.util.ArrayList;
039    import java.util.Collections;
040    import java.util.List;
041    
042    /**
043     * encapsulates about a node described/contained by a Web Map Context
044     *
045     * @version $Revision: 18195 $
046     * @author <a href="mailto:vesll@idgis.nl">Linda Vels</a>
047     * @author last edited by: $Author: mschneider $
048     *
049     * @version 1.0. $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
050     *
051     * @since 2.0
052     */
053    public class Node {
054    
055        private int id;
056    
057        private String title = null;
058    
059        private boolean selectable = false;
060    
061        private boolean collapsed = false;
062    
063        private Node[] nodes = new Node[0];
064    
065        private Node parent = null;
066    
067        List<Node[]> tree = new ArrayList<Node[]>( 50 );
068    
069        /**
070         * Creates a new ContextNode object.
071         *
072         * @param id
073         *            id of the selected node
074         * @param parent
075         * @param title
076         *            title of the selected node
077         * @param selectable
078         * @param collapsed
079         *            defines if the node is collapsed in the legend viewer
080         * @throws ContextException
081         */
082        public Node( int id, Node parent, String title, boolean selectable, boolean collapsed ) throws ContextException {
083            setId( id );
084            setParent( parent );
085            setTitle( title );
086            setCollapsed( collapsed );
087            setSelectable( selectable );
088        }
089    
090        /**
091         * The childnodes of the selected node in the tree
092         *
093         * @return all nodes
094         */
095        public Node[] getNodes() {
096            return nodes;
097        }
098    
099        /**
100         * Returns a childnode of the selected node by id
101         *
102         * @param nodeId
103         *            to retrieve
104         *
105         * @return node by id or <code>null</code> if not found
106         */
107        public Node getNode( int nodeId ) {
108            Node node = null;
109            for ( int i = 0; i < nodes.length; i++ ) {
110                node = nodes[i].getNode( nodeId );
111                if ( node != null ) {
112                    return node;
113                }
114                if ( nodes[i].getId() == nodeId ) {
115                    return nodes[i];
116                }
117            }
118            return node;
119        }
120    
121        /**
122         *
123         * @param nodeId
124         * @param nodes
125         * @return node by id from a list
126         */
127        public Node getNode( int nodeId, Node[] nodes ) {
128            Node node = null;
129            for ( int i = 0; i < nodes.length; i++ ) {
130                node = nodes[i].getNode( nodeId, nodes[i].getNodes() );
131                if ( node != null ) {
132                    return node;
133                }
134                if ( nodes[i].getId() == nodeId ) {
135                    return nodes[i];
136                }
137    
138            }
139            return node;
140        }
141    
142        /**
143         * return the maximum id of all nodes
144         *
145         * @return maximum id of all nodes
146         */
147        public int getMaxNodeId() {
148            int maxNodeId = id;
149            for ( int i = 0; i < nodes.length; i++ ) {
150                Node[] brancheNodes = nodes[i].getNodes();
151                if ( nodes[i].getId() > maxNodeId ) {
152                    maxNodeId = nodes[i].getId();
153    
154                }
155                maxNodeId = getMaxId( brancheNodes, maxNodeId );
156            }
157            return maxNodeId;
158        }
159    
160        /**
161         *
162         * @param nodes
163         * @param maxNodeId
164         * @return maximum id
165         */
166        private int getMaxId( Node[] nodes, int maxNodeId ) {
167            for ( int i = 0; i < nodes.length; i++ ) {
168                Node[] brancheNodes = nodes[i].getNodes();
169                if ( nodes[i].getId() > maxNodeId ) {
170                    maxNodeId = nodes[i].getId();
171    
172                }
173                maxNodeId = getMaxId( brancheNodes, maxNodeId );
174            }
175            return maxNodeId;
176        }
177    
178        /**
179         *
180         * @param parent
181         */
182        public void setParent( Node parent ) {
183            this.parent = parent;
184        }
185    
186        /**
187         *
188         * @return parent node
189         */
190        public Node getParent() {
191            return parent;
192        }
193    
194        /**
195         * The id of the selected node.
196         *
197         * @return id
198         */
199        public int getId() {
200            return id;
201        }
202    
203        /**
204         * The title of the selected node.
205         *
206         * @return title
207         */
208        public String getTitle() {
209            return title;
210        }
211    
212        /**
213         * The status of the node (collapsed or not (expanded)).
214         *
215         * @return true if node is collapsed
216         */
217        public boolean isCollapsed() {
218            return collapsed;
219        }
220    
221        /**
222         * The selectable status of the node.
223         *
224         * @return true if node is selectable
225         */
226        public boolean isSelectable() {
227            return selectable;
228        }
229    
230        /**
231         * @param nodes
232         */
233        public void setNodes( Node[] nodes ) {
234            if ( nodes == null ) {
235                nodes = new Node[0];
236            }
237            this.nodes = nodes;
238        }
239    
240        /**
241         * @param selectable
242         */
243        public void setSelectable( boolean selectable ) {
244            this.selectable = selectable;
245        }
246    
247        /**
248         * @param collapsed
249         */
250        public void setCollapsed( boolean collapsed ) {
251            this.collapsed = collapsed;
252        }
253    
254        /**
255         * @param id
256         */
257        public void setId( int id ) {
258            this.id = id;
259        }
260    
261        /**
262         *
263         * @param title
264         *
265         * @throws ContextException
266         */
267        public void setTitle( String title )
268                                throws ContextException {
269            if ( title == null ) {
270                throw new ContextException( "title isn't allowed to be null" );
271            }
272            this.title = title;
273        }
274    
275        /**
276         *
277         * @return flat tree as node matrix
278         */
279        public Node[][] getFlatTree() {
280            tree = new ArrayList<Node[]>();
281            tree = getBranches( nodes );
282            Node[][] flatTree = new Node[tree.size()][];
283            return tree.toArray( flatTree );
284        }
285    
286        /**
287         *
288         * @param nodes
289         * @return tree branches
290         */
291        private List<Node[]> getBranches( Node[] nodes ) {
292            for ( int i = 0; i < nodes.length; i++ ) {
293                Node[] branchNodes = nodes[i].getNodes();
294                if ( branchNodes.length == 0 ) {
295                    List<Node> treeRowList = new ArrayList<Node>( 50 );
296                    Node tmpNode = nodes[i];
297                    while ( tmpNode != null ) {
298                        treeRowList.add( tmpNode );
299                        tmpNode = tmpNode.getParent();
300                    }
301                    Collections.reverse( treeRowList );
302                    Node[] treeRow = new Node[treeRowList.size()];
303                    tree.add( treeRowList.toArray( treeRow ) );
304                } else {
305                    getBranches( branchNodes );
306                }
307            }
308            return tree;
309    
310        }
311    
312        /**
313         * moves a node within the tree up or down
314         *
315         * @param nodeId
316         * @param up
317         */
318        public void moveNode( int nodeId, Boolean up ) {
319    
320            for ( int i = 0; i < nodes.length; i++ ) {
321                if ( nodes[i].getId() == nodeId ) {
322                    Node source = null;
323                    Node target = null;
324                    if ( up ) {
325                        source = nodes[i];
326                        target = nodes[i - 1];
327                        nodes[i] = target;
328                        nodes[i - 1] = source;
329                        return;
330                    }
331                    source = nodes[i];
332                    target = nodes[i + 1];
333                    nodes[i] = target;
334                    nodes[i + 1] = source;
335                    return;
336    
337                }
338                nodes[i].moveNode( nodeId, up );
339            }
340    
341        }
342    
343        /**
344         * adds a new child node to the node
345         *
346         * @param childNode
347         */
348        public void appendNode( Node childNode ) {
349            Node[] newNodes = new Node[nodes.length + 1];
350            System.arraycopy( nodes, 0, newNodes, 0, nodes.length );
351            newNodes[nodes.length] = childNode;
352            nodes = newNodes;
353        }
354    
355        /**
356         * insert a new child node at given position
357         *
358         * @param childNode
359         *            the new child node
360         * @param index
361         *            the position of the new child node (0=first node)
362         * @throws IndexOutOfBoundsException
363         */
364        public void insertNode( Node childNode, int index ) {
365            if ( index > nodes.length ) {
366                throw new IndexOutOfBoundsException();
367            }
368            Node[] newNodes = new Node[nodes.length + 1];
369            System.arraycopy( nodes, 0, newNodes, 0, index );
370            newNodes[index] = childNode;
371            System.arraycopy( nodes, index, newNodes, index + 1, nodes.length - index );
372            nodes = newNodes;
373        }
374    
375        /**
376         * removes a node
377         *
378         * @param nodeID
379         *            the id of the node
380         * @return true if node is removed
381         */
382        public boolean removeNode( int nodeID ) {
383            boolean removed = false;
384    
385            for ( int i = 0; i < nodes.length; i++ ) {
386                if ( nodes[i].id == nodeID ) {
387                    Node[] tmpNodes = new Node[nodes.length - 1];
388                    System.arraycopy( nodes, 0, tmpNodes, 0, i );
389                    System.arraycopy( nodes, i + 1, tmpNodes, i, tmpNodes.length - i );
390                    nodes = tmpNodes;
391                    removed = true;
392                    break;
393                }
394                // try to find and remove in child node
395                if ( nodes[i].removeNode( nodeID ) ) {
396                    removed = true;
397                    break;
398                }
399            }
400            return removed;
401        }
402    
403        /**
404         * returns the index of the child node
405         *
406         * @param nodeID
407         *            the node id to look for
408         * @return index of the child node, -1 if node is not found
409         */
410        public int getIndex( int nodeID ) {
411            for ( int i = 0; i < nodes.length; i++ ) {
412                if ( nodes[i].id == nodeID ) {
413                    return i;
414                }
415            }
416            return -1;
417        }
418    
419    }