1
2
3
4
5
6
7 package net.sf.tacos.services.impl;
8
9 import java.util.ArrayList;
10 import java.util.Arrays;
11 import java.util.HashMap;
12 import java.util.Iterator;
13 import java.util.LinkedList;
14 import java.util.List;
15 import java.util.Map;
16
17 import net.sf.tacos.services.CategoryInfo;
18 import net.sf.tacos.services.PageInfo;
19 import net.sf.tacos.services.SiteMap;
20
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23 import org.apache.hivemind.Resource;
24 import org.dom4j.Document;
25 import org.dom4j.DocumentException;
26 import org.dom4j.Element;
27 import org.dom4j.Node;
28 import org.dom4j.io.SAXReader;
29
30
31
32
33
34
35
36
37 public class SiteMapImpl implements SiteMap {
38
39 private static final Log log = LogFactory.getLog(SiteMapImpl.class);
40
41 private Resource resource;
42 private Document document;
43
44 private List cachedCategoryList = null;
45 private Map cachedPageMap = new HashMap();
46 private Map cachedCategoryInfo = new HashMap();
47
48 private boolean compact;
49
50
51
52
53
54 public SiteMapImpl() { }
55
56
57
58
59
60 public void setResource(Resource resource) {
61 this.resource = resource;
62 }
63
64
65
66
67
68
69 public void initialize() throws DocumentException {
70 if (resource == null)
71 throw new IllegalStateException(
72 "No resource set, call setResource(..) before initialize()");
73 if (resource.getResourceURL() == null)
74 throw new IllegalStateException(
75 "No valid resource URL could be resolved:" + resource);
76 log.debug("Sitemap resource: " + resource.getResourceURL());
77 SAXReader reader = new SAXReader();
78 document = reader.read(resource.getResourceURL());
79
80 Element main = (Element)document.selectSingleNode("/sitemap");
81
82 String val = main.attributeValue("compact");
83 if (val != null && !val.trim().equals(""))
84 compact = Boolean.valueOf(val).booleanValue();
85 }
86
87
88
89
90
91
92
93 public boolean contains(String parentName, String pageName) {
94 PageInfo pageInfo = getPageInfo(pageName);
95 return containsImpl(parentName, pageInfo);
96 }
97
98
99
100
101
102
103
104 private boolean containsImpl(String parentName, PageInfo pageInfo) {
105 if (pageInfo == null) return false;
106 PageInfo parent = pageInfo.getParent();
107 if (parent == null) return false;
108 else if (parent.getName().equals(parentName)) return true;
109 else return containsImpl(parentName, parent);
110 }
111
112
113
114
115
116
117 public PageInfo getPageInfo(String name) {
118 return getPageInfoCacheImpl(name, null);
119 }
120
121
122
123
124
125
126
127 private PageInfo getPageInfoCacheImpl(String name, String source) {
128 PageInfo pi = (PageInfo)cachedPageMap.get(name);
129 if (pi == null) {
130 pi = getPageInfoImpl(name, source);
131 if (pi != null) cachedPageMap.put(name, pi);
132 } else {
133
134 }
135 return pi;
136 }
137
138
139
140
141
142
143
144 private PageInfo getPageInfoImpl(String name, String source) {
145 if (document == null) throw new IllegalStateException("No document set, call setResource and initialize.");
146
147
148 if (source != null && name.equals(source))
149 throw new IllegalStateException("Found a cycle, " + name + "->" + source);
150 else if (source == null)
151 source = name;
152
153 Element node = findPageNode(name);
154 if (node != null) {
155
156 PageInfo page = parsePageNode(node);
157
158 Node pageCategoryNode = document.selectSingleNode("/sitemap/category//page[@name='" + name + "']");
159 if (pageCategoryNode != null) {
160 parseNodeTree(page, pageCategoryNode);
161
162 return (PageInfo)cachedPageMap.get(page.getName());
163 }
164
165 return page;
166 }
167
168 return null;
169 }
170
171
172
173
174
175
176
177 protected Element findPageNode(String page)
178 {
179 Element element = (Element)document.selectSingleNode("/sitemap/page[@name='" + page + "']");
180 if (element == null && compact)
181 {
182 element = (Element)document.selectSingleNode("/sitemap/category//page[@name='" + page + "']");
183 }
184 return element;
185 }
186
187
188
189
190
191
192
193
194 protected PageInfo parsePageNode(Element node)
195 {
196 if (node == null || !node.getName().equals("page"))
197 throw new IllegalArgumentException("Node was null or not a page node.");
198
199 String name = node.attributeValue("name");
200 String desc = node.attributeValue("desc");
201 String perm = node.attributeValue("permission");
202 String listItem = node.attributeValue("navigable");
203
204 boolean list = true;
205 if (listItem != null && !listItem.trim().equals(""))
206 list = Boolean.valueOf(listItem).booleanValue();
207
208 PageInfo page = new PageInfoImpl(name, desc, perm, new ArrayList(), list);
209 return page;
210 }
211
212
213
214
215
216
217
218
219 protected void parseNodeTree(PageInfo page, Node pageNode)
220 {
221
222 Node parent = pageNode;
223 while (parent.getParent() != null
224 && parent.getParent().getName().equals("page")) {
225 parent = parent.getParent();
226 }
227
228 log.debug("Parsing tree for page <" + page.getName() + ">");
229
230 parsePageNodes(parent, page);
231 }
232
233
234
235
236
237
238
239
240
241 protected PageInfo parsePageNodes(Node parent, PageInfo source)
242 {
243 PageInfo parentInfo = parsePageNode(findPageNode(((Element)parent).attributeValue("name")));
244 cachedPageMap.put(parentInfo.getName(), parentInfo);
245
246 log.debug("Parent page name <" + parent.valueOf("@name") + ">");
247 Iterator it = parent.selectNodes("*").iterator();
248 while (it.hasNext()) {
249 Node child = (Node)it.next();
250 PageInfo childInfo = parsePageNodes(child, source);
251
252 childInfo.setParent(parentInfo);
253 parentInfo.addChild(childInfo);
254 }
255
256 return parentInfo;
257 }
258
259
260
261
262
263 public synchronized List getCategories() {
264 if (document == null) throw new IllegalStateException("No document set, call setResource and initialize.");
265 if (cachedCategoryList == null) {
266 List nodes = document.selectNodes("/sitemap/category[@name]");
267 cachedCategoryList = new ArrayList(nodes.size());
268 for(int i = 0, size = nodes.size(); i < size; i++) {
269 String category = ((Node)nodes.get(i)).valueOf("@name");
270 cachedCategoryList.add(category);
271 }
272 }
273 return cachedCategoryList;
274 }
275
276
277
278
279
280
281
282 public CategoryInfo getCategoryInfo(String name) {
283 CategoryInfo ci = (CategoryInfo)cachedCategoryInfo.get(name);
284 if (ci != null) {
285 return ci;
286 }
287
288 if (document == null) throw new IllegalStateException("No document set, call setResource and initialize.");
289
290 String imgName = null;
291 String inactiveImgName = null;
292
293 Element catnode = (Element)document.selectSingleNode("/sitemap/category[@name='" + name + "']");
294 if (catnode != null) {
295 imgName = catnode.attributeValue("image-active");
296 inactiveImgName = catnode.attributeValue("image-inactive");
297 }
298
299
300 List nodes = document.selectNodes("/sitemap/category[@name='" + name + "']/page");
301 if (nodes != null) {
302 List pageNames = new ArrayList(nodes.size());
303 for(int i = 0; i < nodes.size(); i++) {
304 Node node = (Node)nodes.get(i);
305 String pageName = node.valueOf("@name");
306 pageNames.add(pageName);
307 }
308 ci = new CategoryInfoImpl(name, pageNames, imgName, inactiveImgName);
309 cachedCategoryInfo.put(name, ci);
310 return ci;
311 }
312 ci = new CategoryInfoImpl(name, null);
313 cachedCategoryInfo.put(name, ci);
314 return ci;
315 }
316
317
318
319
320
321
322 private PageInfo getOrigin(PageInfo pageInfo) {
323 if (pageInfo != null && pageInfo.getParent() != null) return getOrigin(pageInfo.getParent());
324 return pageInfo;
325 }
326
327
328
329
330
331
332 public CategoryInfo getCategoryFromPage(String pageName) {
333 PageInfo pageInfo = getPageInfo(pageName);
334 if (pageInfo != null) {
335 PageInfo topMostPage = getOrigin(pageInfo);
336 String topPageName = topMostPage.getName();
337
338 Node node = document.selectSingleNode("/sitemap/category/page[@name='" + topPageName + "']");
339 if (node != null) {
340 String categoryName = node.getParent().valueOf("@name");
341 return getCategoryInfo(categoryName);
342 }
343 }
344 return null;
345 }
346
347
348
349
350
351
352
353 public boolean inCategory(String pageName, String category) {
354 CategoryInfo ci = getCategoryFromPage(pageName);
355 return (ci != null && ci.getName().equals(category));
356 }
357
358
359
360
361
362
363 public PageInfo getDefaultPage(String category) {
364 CategoryInfo ci = getCategoryInfo(category);
365 if (ci == null) return null;
366 return getPageInfo(ci.getDefaultPage());
367 }
368
369
370
371
372
373
374 public List getCategoryPages(String pageName) {
375 CategoryInfo ci = getCategoryFromPage(pageName);
376 if (ci == null) return Arrays.asList(new Object[0]);
377 return ci.getPageNames();
378 }
379
380
381
382
383
384
385 public String getDefaultPageDesc(String category) {
386 PageInfo pi = getDefaultPage(category);
387 if (pi == null) return null;
388 return pi.getDesc();
389 }
390
391
392
393
394
395
396 public List getBreadCrumbs(String pageName) {
397 List list = new LinkedList();
398 PageInfo pageInfo = getPageInfo(pageName);
399 if (pageInfo == null) return Arrays.asList(new Object[0]);
400 loadBreadCrumbs(pageInfo, list);
401 return list;
402 }
403
404
405
406
407
408
409 private void loadBreadCrumbs(PageInfo pageInfo, List breadCrumbs) {
410 PageInfo parent = pageInfo.getParent();
411 if (parent == null || parent.getName().equals(""))
412 return;
413
414 breadCrumbs.add(0, parent.getName());
415 loadBreadCrumbs(parent, breadCrumbs);
416 }
417
418 public boolean getCompact()
419 {
420 return compact;
421 }
422
423 }