cfb6d007791977be023f2222417a510aec1bb821
[debian/openrocket] / android / src / pl / polidea / treeview / TreeBuilder.java
1 package pl.polidea.treeview;
2
3 import net.sf.openrocket.android.util.AndroidLogWrapper;
4
5 /**
6  * Allows to build tree easily in sequential mode (you have to know levels of
7  * all the tree elements upfront). You should rather use this class rather than
8  * manager if you build initial tree from some external data source.
9  * 
10  * @param <T>
11  */
12 public class TreeBuilder<T> {
13
14     private final TreeStateManager<T> manager;
15
16     private T lastAddedId = null;
17     private int lastLevel = -1;
18
19     public TreeBuilder(final TreeStateManager<T> manager) {
20         this.manager = manager;
21     }
22
23     public void clear() {
24         manager.clear();
25     }
26
27     /**
28      * Adds new relation to existing tree. Child is set as the last child of the
29      * parent node. Parent has to already exist in the tree, child cannot yet
30      * exist. This method is mostly useful in case you add entries layer by
31      * layer - i.e. first top level entries, then children for all parents, then
32      * grand-children and so on.
33      * 
34      * @param parent
35      *            parent id
36      * @param child
37      *            child id
38      */
39     public synchronized void addRelation(final T parent, final T child) {
40         AndroidLogWrapper.d(TreeBuilder.class, "Adding relation parent:" + parent + " -> child: " + child);
41         manager.addAfterChild(parent, child, null);
42         lastAddedId = child;
43         lastLevel = manager.getLevel(child);
44     }
45
46     /**
47      * Adds sequentially new node. Using this method is the simplest way of
48      * building tree - if you have all the elements in the sequence as they
49      * should be displayed in fully-expanded tree. You can combine it with add
50      * relation - for example you can add information about few levels using
51      * {@link addRelation} and then after the right level is added as parent,
52      * you can continue adding them using sequential operation.
53      * 
54      * @param id
55      *            id of the node
56      * @param level
57      *            its level
58      */
59     public synchronized void sequentiallyAddNextNode(final T id, final int level) {
60         AndroidLogWrapper.d(TreeBuilder.class, "Adding sequentiall node " + id + " at level " + level);
61         if (lastAddedId == null) {
62             addNodeToParentOneLevelDown(null, id, level);
63         } else {
64             if (level <= lastLevel) {
65                 final T parent = findParentAtLevel(lastAddedId, level - 1);
66                 addNodeToParentOneLevelDown(parent, id, level);
67             } else {
68                 addNodeToParentOneLevelDown(lastAddedId, id, level);
69             }
70         }
71     }
72
73     /**
74      * Find parent of the node at the level specified.
75      * 
76      * @param node
77      *            node from which we start
78      * @param levelToFind
79      *            level which we are looking for
80      * @return the node found (null if it is topmost node).
81      */
82     private T findParentAtLevel(final T node, final int levelToFind) {
83         T parent = manager.getParent(node);
84         while (parent != null) {
85             if (manager.getLevel(parent) == levelToFind) {
86                 break;
87             }
88             parent = manager.getParent(parent);
89         }
90         return parent;
91     }
92
93     /**
94      * Adds note to parent at the level specified. But it verifies that the
95      * level is one level down than the parent!
96      * 
97      * @param parent
98      *            parent parent
99      * @param id
100      *            new node id
101      * @param level
102      *            should always be parent's level + 1
103      */
104     private void addNodeToParentOneLevelDown(final T parent, final T id,
105             final int level) {
106         if (parent == null && level != 0) {
107             throw new TreeConfigurationException("Trying to add new id " + id
108                     + " to top level with level != 0 (" + level + ")");
109         }
110         if (parent != null && manager.getLevel(parent) != level - 1) {
111             throw new TreeConfigurationException("Trying to add new id " + id
112                     + " <" + level + "> to " + parent + " <"
113                     + manager.getLevel(parent)
114                     + ">. The difference in levels up is bigger than 1.");
115         }
116         manager.addAfterChild(parent, id, null);
117         setLastAdded(id, level);
118     }
119
120     private void setLastAdded(final T id, final int level) {
121         lastAddedId = id;
122         lastLevel = level;
123     }
124
125 }