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