1
2
3
4
5
6
7
8
9
10
11
12 package sk.uniba.euromath.plugin.views.outline;
13
14 import java.util.ArrayList;
15 import java.util.HashMap;
16 import java.util.LinkedList;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.Queue;
20
21 import org.eclipse.core.runtime.IStatus;
22 import org.eclipse.jface.viewers.ITreeContentProvider;
23 import org.eclipse.jface.viewers.Viewer;
24 import org.w3c.dom.Attr;
25 import org.w3c.dom.CDATASection;
26 import org.w3c.dom.Comment;
27 import org.w3c.dom.Element;
28 import org.w3c.dom.EntityReference;
29 import org.w3c.dom.NamedNodeMap;
30 import org.w3c.dom.Node;
31 import org.w3c.dom.NodeList;
32 import org.w3c.dom.ProcessingInstruction;
33 import org.w3c.dom.Text;
34
35 import sk.uniba.euromath.Const;
36 import sk.uniba.euromath.EuroMath;
37 import sk.uniba.euromath.plugin.views.outline.items.AttributeOutlineItem;
38 import sk.uniba.euromath.plugin.views.outline.items.CDataOutlineItem;
39 import sk.uniba.euromath.plugin.views.outline.items.CommentOutlineItem;
40 import sk.uniba.euromath.plugin.views.outline.items.ElementOutlineItem;
41 import sk.uniba.euromath.plugin.views.outline.items.EntityOutlineItem;
42 import sk.uniba.euromath.plugin.views.outline.items.OutlineItem;
43 import sk.uniba.euromath.plugin.views.outline.items.PIOutlineItem;
44 import sk.uniba.euromath.plugin.views.outline.items.TextOutlineItem;
45 import sk.uniba.euromath.plugin.views.outline.lang.Messages;
46
47 /***
48 * Tree xml node structure content provider. Provided content is tree of outline
49 * items. Alows to configure which types of nodes are shown. Has auto refresh.
50 *
51 * @author Tomáš Studva 2.11.2005
52 */
53 public class XMLAccessContentProvider implements ITreeContentProvider {
54
55 /***
56 * Flag, if internal EM2 attributes should be shown.
57 */
58 protected static boolean showInternalAttributes = false;
59
60 /***
61 * Root outline item. Is invisible and abstract, don't corresponds to any
62 * node form xml.
63 */
64 private final TopLevelOutlineItem invisibleRoot;
65
66 /***
67 * Specifies if to refresh, when needed.
68 */
69 private boolean autoRefresh = true;
70
71 /***
72 * Map from model to outline. One node is associated with one or zero outline item.
73 */
74 private final Map<Node, OutlineItem> nodeItemMap = new HashMap<Node, OutlineItem>();
75
76 /***
77 * Holds which node types to show.
78 */
79 private final Map<Short, Boolean> visibilityFlagMap = new HashMap<Short, Boolean>();
80
81 /***
82 * Last content(input).
83 */
84 private Object lastInput;
85
86 /***
87 * Constructor. Refreshes content. Content is empty, only invisible root exists.
88 */
89 public XMLAccessContentProvider() {
90 super();
91 this.invisibleRoot = new TopLevelOutlineItem();
92 showAll();
93 }
94
95 /***
96 *
97 * @param parent
98 * @param xmlNode
99 */
100 protected void addToTree(OutlineItem parent, Node xmlNode) {
101
102 OutlineItem current = null;
103 Node node;
104
105 if ((xmlNode != null) && hasToBeShown(xmlNode)) {
106 current = createItem(xmlNode);
107 current.setParent(parent);
108 parent.addChild(current);
109
110 NamedNodeMap attrs = xmlNode.getAttributes();
111 if (attrs != null) {
112 for (int i = 0; i < attrs.getLength(); i++) {
113 node = attrs.item(i);
114 addToTree(current, node);
115 }
116 }
117
118 NodeList children = xmlNode.getChildNodes();
119 for (int i = 0; i < children.getLength(); i++) {
120 node = children.item(i);
121 addToTree(current, node);
122 }
123 }
124
125 }
126
127 /***
128 *
129 * @param topDataNode
130 */
131 protected void build(Node topDataNode) {
132 clear();
133 addToTree(getInvisibleRoot(), topDataNode);
134 }
135
136 /***
137 *
138 *
139 */
140 protected void clear() {
141 getInvisibleRoot().removeChild(getInvisibleRoot().getChild());
142 }
143
144 /***
145 * Creates outline item for node.
146 * @param model node
147 * @return new created outline item for node model
148 */
149 protected OutlineItem createItem(Node model) {
150
151 short type = model.getNodeType();
152
153 OutlineItem result = null;
154
155
156 switch (type) {
157 case Node.ATTRIBUTE_NODE:
158 result = new AttributeOutlineItem((Attr) model);
159 break;
160 case Node.CDATA_SECTION_NODE:
161 result = new CDataOutlineItem((CDATASection) model);
162 break;
163 case Node.COMMENT_NODE:
164 result = new CommentOutlineItem((Comment) model);
165 break;
166 case Node.ELEMENT_NODE:
167 result = new ElementOutlineItem((Element) model);
168 break;
169 case Node.ENTITY_REFERENCE_NODE:
170 result = new EntityOutlineItem((EntityReference) model);
171 break;
172 case Node.PROCESSING_INSTRUCTION_NODE:
173 result = new PIOutlineItem((ProcessingInstruction) model);
174 break;
175 case Node.TEXT_NODE:
176 result = new TextOutlineItem((Text) model);
177 break;
178 default:
179 EuroMath.log(IStatus.ERROR, 0, Messages.getString("XMLAccessContentProvider.0")
180 + model.getClass().getName() + Messages.getString("XMLAccessContentProvider.1"),
181 null);
182 break;
183 }
184
185 if (result != null) {
186 this.nodeItemMap.put(model, result);
187 }
188 return result;
189 }
190
191 public void dispose() {
192
193 }
194
195
196
197
198
199
200 public Object[] getChildren(Object parent) {
201 assert (parent instanceof OutlineItem);
202 return ((OutlineItem) parent).getChildren().toArray();
203 }
204
205
206
207
208
209
210 public Object[] getElements(Object parent) {
211 return getInvisibleRoot().getChildren().toArray();
212 }
213
214 /***
215 * Returns OutlineItem which displays node or null if outline view don't
216 * have outline item which correspond to that node.
217 *
218 * @param node
219 * which is displayed in outline by some outline item
220 * @return outline item which displays node or null if no such node exists
221 */
222 public OutlineItem getItem(Node node) {
223
224
225 if (this.nodeItemMap.containsKey(node)) {
226 return this.nodeItemMap.get(node);
227 }
228
229
230 Queue<OutlineItem> queue = new LinkedList<OutlineItem>();
231 queue.add(getInvisibleRoot());
232
233 while (queue.size() > 0) {
234 if (queue.peek().getModel() == node)
235 return queue.peek();
236 List<OutlineItem> children = queue.remove().getChildren();
237 queue.addAll(children);
238 }
239 return null;
240 }
241
242
243
244
245
246
247 public Object getParent(Object element) {
248 if ((element == null) || !(element instanceof OutlineItem))
249 throw new IllegalArgumentException(
250 Messages.getString("XMLAccessContentProvider.2"));
251 return ((OutlineItem) element).getParent();
252 }
253
254
255
256
257
258
259 public boolean hasChildren(Object parent) {
260 if (parent == null)
261 return false;
262 assert (parent instanceof OutlineItem);
263 return ((OutlineItem) parent).getChildren().size() > 0;
264 }
265
266 /***
267 * Computes if node should be shown.
268 *
269 * @param node
270 * the node
271 * @return true if node should be shown
272 */
273 protected boolean hasToBeShown(Node node) {
274
275 if ((node.getNodeType() == Node.ATTRIBUTE_NODE)
276 && (node.getNamespaceURI() != null)
277 && (node.getNamespaceURI().equals(Const.EM_URI)))
278 return showInternalAttributes;
279
280
281 Object o = getVisibilityFlagMap().get(new Short(node.getNodeType()));
282 if (o == null)
283 throw new IllegalArgumentException(
284 Messages.getString("XMLAccessContentProvider.3"));
285 return ((Boolean) o).booleanValue();
286
287 }
288
289 /***
290 * @return Returns the visibilityFlagMap.
291 */
292 protected Map<Short, Boolean> getVisibilityFlagMap() {
293 return this.visibilityFlagMap;
294 }
295
296
297
298
299
300
301
302 public void inputChanged(Viewer v, Object oldInput, Object newInput) {
303 this.lastInput = newInput;
304 if (newInput == null) {
305 clear();
306 } else {
307 assert ((newInput instanceof Node));
308 build((Node) newInput);
309 }
310 }
311
312 /***
313 * Refreshes the content.
314 *
315 */
316 protected void refresh() {
317 inputChanged(null, null, this.lastInput);
318 }
319
320 /***
321 * Sets visibility to nodes of type nodeType. If show is true, nodes of that
322 * type will be shown.
323 *
324 * @param nodeType
325 * type of node
326 * @param show
327 * specifies if to show
328 */
329 public void setShowType(short nodeType, boolean show) {
330
331 getVisibilityFlagMap().put(new Short(nodeType), new Boolean(show));
332
333 if (isAutoRefresh()) {
334 refresh();
335 }
336 }
337
338 /***
339 * @return Returns the autoRefresh.
340 */
341 protected boolean isAutoRefresh() {
342 return this.autoRefresh;
343 }
344
345 /***
346 * @param autoRefresh The autoRefresh to set.
347 */
348 protected void setAutoRefresh(boolean autoRefresh) {
349 this.autoRefresh = autoRefresh;
350 }
351
352 /***
353 * Sets visibility of all nodes types to true and refreshes content if auto
354 * refresh is on.
355 */
356 public void showAll() {
357 boolean old = isAutoRefresh();
358 setAutoRefresh(false);
359 setShowType(Node.ATTRIBUTE_NODE, true);
360 setShowType(Node.CDATA_SECTION_NODE, true);
361 setShowType(Node.COMMENT_NODE, true);
362 setShowType(Node.ELEMENT_NODE, true);
363 setShowType(Node.PROCESSING_INSTRUCTION_NODE, true);
364 setShowType(Node.TEXT_NODE, true);
365 setShowType(Node.ENTITY_REFERENCE_NODE, true);
366
367
368 setAutoRefresh(old);
369 if (isAutoRefresh())
370 refresh();
371 }
372
373 /***
374 * Outline item for holding only one child. Corresponds to no model.
375 *
376 * @author Tomáš Studva 2.11.2005
377 */
378 private class TopLevelOutlineItem extends OutlineItem {
379
380 /***
381 * The only child of this item.
382 */
383 private OutlineItem child;
384
385 /***
386 * Constructor. No model is passed, no is assumed.
387 */
388 public TopLevelOutlineItem() {
389 super(null);
390 }
391
392 /***
393 * Overrides currently holded child. Remenber only one child has this
394 * item.
395 */
396 @Override
397 public void addChild(OutlineItem child) {
398 this.child = child;
399 }
400
401 /***
402 * Overrides currently holded child. Remenber only one child has this
403 * item.
404 */
405 @Override
406 public void removeChild(OutlineItem child) {
407 if (getChild() == child)
408 setChild(null);
409 }
410
411 /***
412 * @param child The child to set.
413 */
414 protected void setChild(OutlineItem child) {
415 this.child = child;
416 }
417
418 /***
419 * Returns the only child.
420 * @return the child
421 */
422 public OutlineItem getChild() {
423 return this.child;
424 }
425
426 /***
427 * Returns list with the only child.
428 */
429 @Override
430 public List<OutlineItem> getChildren() {
431 List<OutlineItem> children = new ArrayList<OutlineItem>();
432 children.add(getChild());
433 return children;
434 }
435
436 }
437
438 /***
439 * @return Returns the invisibleRoot.
440 */
441 protected TopLevelOutlineItem getInvisibleRoot() {
442 return this.invisibleRoot;
443 }
444
445 }