1 | // ============================================================= // |
---|
2 | // // |
---|
3 | // File : Group.cxx // |
---|
4 | // Purpose : Handles for taxonomic groups // |
---|
5 | // // |
---|
6 | // Coded by Ralf Westram (coder@reallysoft.de) in March 2017 // |
---|
7 | // http://www.arb-home.de/ // |
---|
8 | // // |
---|
9 | // ============================================================= // |
---|
10 | |
---|
11 | #include "Group.hxx" |
---|
12 | #include "GroupIterator.hxx" |
---|
13 | |
---|
14 | #include <AP_TreeSet.hxx> |
---|
15 | |
---|
16 | using namespace std; |
---|
17 | |
---|
18 | static AP_tree *find_node_with_groupdata(AP_tree *subtree, GBDATA *gb_group) { |
---|
19 | // brute-force impl |
---|
20 | // @@@ instead use group id (as stored in node) as hint to find group |
---|
21 | if (subtree->is_leaf()) return NULp; |
---|
22 | if (subtree->gb_node == gb_group) return subtree; |
---|
23 | |
---|
24 | AP_tree *found = find_node_with_groupdata(subtree->get_leftson(), gb_group); |
---|
25 | if (!found) found = find_node_with_groupdata(subtree->get_rightson(), gb_group); |
---|
26 | return found; |
---|
27 | } |
---|
28 | |
---|
29 | bool Group::locate(AP_tree *subtree) const { |
---|
30 | td_assert(is_valid()); |
---|
31 | |
---|
32 | if (!is_located()) { |
---|
33 | node = find_node_with_groupdata(subtree, gb_group); |
---|
34 | td_assert(node); // wrong subtree specified! |
---|
35 | |
---|
36 | TreeNode *keeledToSon = node->keelTarget(); |
---|
37 | if (keeledToSon) { |
---|
38 | node = DOWNCAST(AP_tree*, keeledToSon); |
---|
39 | } |
---|
40 | } |
---|
41 | |
---|
42 | td_assert(implicated(node, at_node(node))); |
---|
43 | return node; |
---|
44 | } |
---|
45 | |
---|
46 | // -------------------------------------------------------------------------------- |
---|
47 | |
---|
48 | #ifdef UNIT_TESTS |
---|
49 | #ifndef TEST_UNIT_H |
---|
50 | #include <test_unit.h> |
---|
51 | #endif |
---|
52 | |
---|
53 | void TEST_groups() { |
---|
54 | GB_shell shell; |
---|
55 | GBDATA *gb_main = GB_open("../../demo.arb", "r"); |
---|
56 | |
---|
57 | SmartPtr<AP_tree_root> treeRoot = new AP_tree_root(new AliView(gb_main), NULp, false, NULp); |
---|
58 | |
---|
59 | { |
---|
60 | GB_transaction ta(gb_main); |
---|
61 | TEST_EXPECT_NO_ERROR(treeRoot->loadFromDB("tree_test")); |
---|
62 | } |
---|
63 | |
---|
64 | AP_tree *rootNode = treeRoot->get_root_node(); |
---|
65 | AP_tree_set existingGroups; |
---|
66 | |
---|
67 | const int GROUP_COUNT = 8; |
---|
68 | |
---|
69 | collect_contained_groups(rootNode, existingGroups); |
---|
70 | TEST_EXPECT_EQUAL(existingGroups.size(), GROUP_COUNT); |
---|
71 | |
---|
72 | { |
---|
73 | Group gunknown; |
---|
74 | TEST_EXPECT(!gunknown.is_valid()); |
---|
75 | TEST_EXPECT_NULL(gunknown.get_group_data()); |
---|
76 | |
---|
77 | for (AP_tree_set_iter i = existingGroups.begin(); i != existingGroups.end(); ++i) { |
---|
78 | AP_tree *node = *i; |
---|
79 | |
---|
80 | Group gfound(node); |
---|
81 | Group gexisting(node->gb_node); |
---|
82 | |
---|
83 | TEST_EXPECT(gfound.is_located()); |
---|
84 | TEST_EXPECT(!gexisting.is_located()); |
---|
85 | |
---|
86 | TEST_REJECT_NULL(gfound.get_group_data()); |
---|
87 | TEST_REJECT_NULL(gexisting.get_group_data()); |
---|
88 | |
---|
89 | TEST_EXPECT(gexisting.locate(rootNode)); |
---|
90 | TEST_EXPECT(gexisting.is_located()); |
---|
91 | TEST_EXPECT_EQUAL(gfound.get_node(), gexisting.get_node()); |
---|
92 | |
---|
93 | gexisting.dislocate(); |
---|
94 | TEST_EXPECT(!gexisting.is_located()); |
---|
95 | |
---|
96 | // for all groupnodes test whether group 'gexisting' is at_node |
---|
97 | int seen_exist = 0; |
---|
98 | int seen_found = 0; |
---|
99 | for (AP_tree_set_iter j = existingGroups.begin(); j != existingGroups.end(); ++j) { |
---|
100 | AP_tree *testnode = *j; |
---|
101 | if (gexisting.at_node(testnode)) seen_exist++; |
---|
102 | if (gfound.at_node(testnode)) seen_found++; |
---|
103 | } |
---|
104 | |
---|
105 | TEST_EXPECT_EQUAL(seen_found, 1); |
---|
106 | TEST_EXPECT_EQUAL(seen_exist, 1); |
---|
107 | TEST_EXPECT(gexisting.is_located()); |
---|
108 | TEST_EXPECT_EQUAL(gfound.get_node(), gexisting.get_node()); |
---|
109 | |
---|
110 | { // compare node name |
---|
111 | GB_transaction ta(gb_main); |
---|
112 | TEST_EXPECT_EQUAL(gfound.get_name(), gfound.get_node()->name); |
---|
113 | } |
---|
114 | } |
---|
115 | } |
---|
116 | |
---|
117 | // test GroupIterator |
---|
118 | { |
---|
119 | GroupIterator iter(rootNode); |
---|
120 | GroupIterator reverse(rootNode, false); |
---|
121 | |
---|
122 | TEST_EXPECT(iter.valid()); |
---|
123 | TEST_EXPECT(reverse.valid()); |
---|
124 | |
---|
125 | AP_tree *start = iter.node(); |
---|
126 | int count = 0; |
---|
127 | int differed = 0; |
---|
128 | |
---|
129 | AP_tree *at = start; |
---|
130 | do { |
---|
131 | TEST_ANNOTATE(GBS_global_string("count=%i", count)); |
---|
132 | |
---|
133 | AP_tree *rat = reverse.node(); |
---|
134 | |
---|
135 | TEST_EXPECT(at->is_normal_group()); |
---|
136 | TEST_EXPECT(rat->is_normal_group()); |
---|
137 | |
---|
138 | fprintf(stderr, "iter=%s reverse=%s\n", at->name, rat->name); |
---|
139 | |
---|
140 | // Note: groupname 'outer' and 'test' are each used at two different groups! |
---|
141 | // Counting leafs below ensures the iterator point to the right one of these duplicates! |
---|
142 | |
---|
143 | switch (count) { |
---|
144 | case 0: |
---|
145 | TEST_EXPECT_EQUAL(at->name, "outer"); TEST_EXPECT_EQUAL(at->count_leafs(), 15); |
---|
146 | TEST_EXPECT_EQUAL(rat->name, "last"); |
---|
147 | TEST_EXPECT_EQUAL(iter.get_clade_level(), 1); |
---|
148 | TEST_EXPECT_EQUAL(reverse.get_clade_level(), 1); |
---|
149 | break; |
---|
150 | case 2: |
---|
151 | TEST_EXPECT_EQUAL(at->name, "test"); TEST_EXPECT_EQUAL(at->count_leafs(), 4); |
---|
152 | TEST_EXPECT_EQUAL(rat->name, "inner"); |
---|
153 | TEST_EXPECT_EQUAL(iter.get_clade_level(), 2); |
---|
154 | TEST_EXPECT_EQUAL(reverse.get_clade_level(), 2); |
---|
155 | break; |
---|
156 | case GROUP_COUNT-1: |
---|
157 | TEST_EXPECT_EQUAL(at->name, "last"); |
---|
158 | TEST_EXPECT_EQUAL(rat->name, "outer"); TEST_EXPECT_EQUAL(rat->count_leafs(), 15); |
---|
159 | TEST_EXPECT_EQUAL(iter.get_clade_level(), 1); |
---|
160 | TEST_EXPECT_EQUAL(reverse.get_clade_level(), 1); |
---|
161 | break; |
---|
162 | } |
---|
163 | |
---|
164 | count++; |
---|
165 | if (at != rat) ++differed; |
---|
166 | |
---|
167 | { |
---|
168 | GroupIterator dup(iter); |
---|
169 | TEST_EXPECT(dup.node() == iter.node()); |
---|
170 | |
---|
171 | GroupIterator rdup(dup.next().node(), false); |
---|
172 | TEST_EXPECT(dup.node() == rdup.node()); |
---|
173 | |
---|
174 | dup.previous(); |
---|
175 | rdup.next(); |
---|
176 | TEST_EXPECT(dup.node() == iter.node()); |
---|
177 | TEST_EXPECT(dup.node() == rdup.node()); |
---|
178 | |
---|
179 | dup.next(); |
---|
180 | rdup.previous(); |
---|
181 | TEST_EXPECT(dup.node() == rdup.node()); |
---|
182 | } |
---|
183 | |
---|
184 | at = iter.next().node(); |
---|
185 | reverse.next(); |
---|
186 | } |
---|
187 | while (at != start); |
---|
188 | |
---|
189 | TEST_EXPECT_EQUAL(count, GROUP_COUNT); |
---|
190 | TEST_EXPECT_EQUAL(differed, GROUP_COUNT%2 ? GROUP_COUNT-1 : GROUP_COUNT); |
---|
191 | } |
---|
192 | |
---|
193 | |
---|
194 | |
---|
195 | GB_close(gb_main); |
---|
196 | } |
---|
197 | |
---|
198 | #endif // UNIT_TESTS |
---|
199 | |
---|
200 | // -------------------------------------------------------------------------------- |
---|
201 | |
---|