1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.myfaces.tobago.model;
21
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
24
25 import javax.swing.tree.DefaultMutableTreeNode;
26 import javax.swing.tree.TreeNode;
27 import java.lang.invoke.MethodHandles;
28 import java.util.ArrayList;
29 import java.util.Collections;
30 import java.util.HashMap;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.Stack;
34
35
36
37
38 public class TreeNodeDataModel extends TreeDataModel<TreeNode> {
39
40 private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
41
42 private TreeNode data;
43 private int rowIndex = -1;
44 private Map<Integer, Data> mapping;
45 private Map<TreeNode, Integer> back;
46 private boolean showRoot;
47 private ExpandedState expandedState;
48
49
50
51
52
53
54 public TreeNodeDataModel(final TreeNode data, final boolean showRoot, final ExpandedState expandedState) {
55 this.data = data;
56 this.showRoot = showRoot;
57 this.mapping = new HashMap<>();
58 this.back = new HashMap<>();
59 this.expandedState = expandedState;
60 reset();
61 }
62
63 @Override
64 public void reset() {
65 this.mapping.clear();
66 this.back.clear();
67 TreeNode current = data;
68 for (int counter = back.size(); current != null; counter++) {
69
70 mapping.put(counter, new Data(current));
71 back.put(current, counter);
72
73
74 if (current.getChildCount() > 0 && expandedState.isExpanded(current)) {
75 current = current.getChildAt(0);
76 } else {
77 current = getNextNodeButNoChild(current);
78 }
79 }
80 }
81
82 @Override
83 public void update(final ExpandedState update) {
84 this.expandedState = update;
85 TreeNode current = data;
86 int counter = back.size();
87 while (current != null) {
88
89 if (!back.containsKey(current)) {
90 mapping.put(counter, new Data(current));
91 back.put(current, counter);
92 counter++;
93 }
94
95
96 if (current.getChildCount() > 0 && expandedState.isExpanded(current)) {
97 current = current.getChildAt(0);
98 } else {
99 current = getNextNodeButNoChild(current);
100 }
101 }
102 }
103
104 private TreeNode getNextNodeButNoChild(final TreeNode node) {
105 TreeNode next;
106 TreeNode p = node;
107 while (true) {
108 next = nextSibling(p);
109 if (next != null) {
110 break;
111 }
112 p = p.getParent();
113 if (p == null) {
114 return null;
115 }
116
117 }
118 return next;
119 }
120
121 private TreeNode nextSibling(final TreeNode node) {
122 final TreeNode parent = node.getParent();
123 if (parent == null) {
124 return null;
125 }
126 for (int i = 0; i < parent.getChildCount() - 1; i++) {
127 if (parent.getChildAt(i) == node) {
128 return parent.getChildAt(i + 1);
129 }
130 }
131 return null;
132 }
133
134 @Override
135 public int getRowCount() {
136 return mapping.size();
137 }
138
139 @Override
140 public TreeNode getRowData() {
141 return mapping.get(rowIndex).getNode();
142 }
143
144 @Override
145 public int getRowIndex() {
146 return rowIndex;
147 }
148
149 @Override
150 public int getLevel() {
151 int count = -1;
152 for (TreeNode node = getRowData(); node != null; node = node.getParent()) {
153 count++;
154 }
155 return count;
156 }
157
158 @Override
159 public TreePath getPath() {
160 return new TreePath(getRowData());
161 }
162
163 @Override
164 public int getDepth() {
165 if (data instanceof DefaultMutableTreeNode) {
166 return ((DefaultMutableTreeNode) data).getDepth();
167 }
168 return -1;
169 }
170
171 @Override
172 public boolean isFolder() {
173 return !getRowData().isLeaf();
174 }
175
176 @Override
177 public TreeNode getWrappedData() {
178 return data;
179 }
180
181 @Override
182 public boolean isRowAvailable() {
183 return 0 <= rowIndex && rowIndex < getRowCount();
184 }
185
186 @Override
187 public void setRowIndex(final int rowIndex) {
188 this.rowIndex = rowIndex;
189 }
190
191 @Override
192 public void setWrappedData(final Object wrappedData) {
193 this.data = (TreeNode) wrappedData;
194 }
195
196 @Override
197 public boolean isRowVisible() {
198 if (!isRowAvailable()) {
199 return false;
200 }
201 final TreeNode start = getRowData();
202 if (start.getParent() == null) {
203 return showRoot;
204 }
205 TreeNode node = start.getParent();
206 while (node != null && back.get(node) != null) {
207 final Data temp = mapping.get(back.get(node));
208 if (temp.getNode().getParent() == null && !showRoot) {
209 return true;
210 }
211 if (!expandedState.isExpanded(new TreePath(node))) {
212 return false;
213 }
214 node = node.getParent();
215 }
216 return true;
217 }
218
219 @Override
220 public String getRowClientId() {
221 if (isRowAvailable()) {
222 return mapping.get(rowIndex).getClientId();
223 } else {
224 return null;
225 }
226 }
227
228 @Override
229 public void setRowClientId(final String clientId) {
230 if (isRowAvailable()) {
231 mapping.get(rowIndex).setClientId(clientId);
232 } else {
233 LOG.warn("No row index set: clientId='" + clientId + "'");
234 }
235 }
236
237 @Override
238 public String getRowParentClientId() {
239 if (isRowAvailable()) {
240 final TreeNode parent = mapping.get(rowIndex).getNode().getParent();
241 if (parent != null && back.get(parent) != null) {
242 return mapping.get(back.get(parent)).getClientId();
243 } else {
244 return null;
245 }
246 } else {
247 return null;
248 }
249 }
250
251 @Override
252 public List<Integer> getRowIndicesOfChildren() {
253 final TreeNode node = getRowData();
254 final int n = node.getChildCount();
255 final List<Integer> children = new ArrayList<>(n);
256 for (int i = 0; i < n; i++) {
257 final Integer integer = back.get(node.getChildAt(i));
258 if (integer != null) {
259 children.add(integer);
260 }
261 }
262 return children;
263 }
264
265 @Override
266 public List<Boolean> getJunctions() {
267 TreeNode node = getRowData();
268 final List<Boolean> junctions = new Stack<>();
269 while (node != null) {
270 junctions.add(hasNextSibling(node));
271 node = node.getParent();
272 }
273 Collections.reverse(junctions);
274 return junctions;
275 }
276
277 private boolean hasNextSibling(final TreeNode node) {
278 final TreeNode parent = node.getParent();
279 return parent != null && parent.getChildAt(parent.getChildCount() - 1) != node;
280 }
281
282
283
284
285
286 private static class Data {
287
288 private final TreeNode node;
289 private String clientId;
290
291 private Data(final TreeNode node) {
292 this.node = node;
293 }
294
295 public TreeNode getNode() {
296 return node;
297 }
298
299 public String getClientId() {
300 return clientId;
301 }
302
303 public void setClientId(final String clientId) {
304 this.clientId = clientId;
305 }
306 }
307 }