improved navigation
[svjatoslav_commons.git] / src / main / java / eu / svjatoslav / commons / network / navigation / NavigationItem.java
1 /*
2  * Svjatoslav Commons - shared library of common functionality.
3  * Copyright ©2012-2014, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of version 3 of the GNU Lesser General Public License
7  * or later as published by the Free Software Foundation.
8  */
9
10 package eu.svjatoslav.commons.network.navigation;
11
12 import java.util.ArrayList;
13 import java.util.HashMap;
14 import java.util.List;
15 import java.util.Map;
16
17 import eu.svjatoslav.commons.string.WildCardMatcher;
18
19 public class NavigationItem {
20
21         private String matchingPattern;
22
23         private final Map<String, String> localeToTitle = new HashMap<String, String>();
24         private final ArrayList<NavigationItem> subElements = new ArrayList<NavigationItem>();
25         private final NavigationItem parent;
26         private final Navigation<? extends NavigationItem> navigation;
27         private final String linkUrl;
28         /**
29          * CSS prefix is inherited to child menu items.
30          */
31         private String cssPrefix;
32
33         /**
34          * Used to build root navigation item.
35          */
36         public NavigationItem(final Navigation<? extends NavigationItem> navigation) {
37                 this.navigation = navigation;
38                 parent = null;
39                 matchingPattern = null;
40                 linkUrl = null;
41         }
42
43         public NavigationItem(final NavigationItem parent, final String linkUrl, final String... titles) {
44
45                 navigation = parent.getNavigation();
46                 this.parent = parent;
47                 this.linkUrl = linkUrl;
48                 matchingPattern = linkUrl;
49
50                 initializeLocalizedTitles(titles);
51
52                 parent.addNavigationItem(this);
53         }
54
55         public void addNavigationItem(final NavigationItem navigationItem) {
56                 subElements.add(navigationItem);
57         }
58
59         protected String getCssPrefix() {
60                 if (cssPrefix != null)
61                         return cssPrefix;
62
63                 if (parent == null)
64                         return null;
65
66                 return parent.getCssPrefix();
67         }
68
69         public String getLinkUrl() {
70                 return linkUrl;
71         }
72
73         NavigationItem getMatchingNavigationItem(final String requestPath) {
74                 if (matchesUrl(requestPath))
75                         return this;
76
77                 for (final NavigationItem childNavigationItem : subElements) {
78                         final NavigationItem match = childNavigationItem.getMatchingNavigationItem(requestPath);
79
80                         if (match != null)
81                                 return match;
82                 }
83                 return null;
84         }
85
86         public Navigation<? extends NavigationItem> getNavigation() {
87                 return navigation;
88         }
89
90         public List<NavigationItem> getSubElements() {
91                 return subElements;
92         }
93
94         public String getTitle(final String locale) {
95                 return localeToTitle.get(locale);
96         }
97
98         private void initializeLocalizedTitles(final String... titles) {
99                 final List<String> locales = getNavigation().getLocaleConfiguration().getAllowedLocales();
100                 if (locales.size() != titles.length)
101                         throw new RuntimeException("There should be exactly " + locales.size() + " title(s).");
102
103                 for (int i = 0; i < titles.length; i++)
104                         localeToTitle.put(locales.get(i), titles[i]);
105         }
106
107         public boolean matchesUrl(final String url) {
108                 return WildCardMatcher.match(url, matchingPattern);
109         }
110
111         public void setCssPrefix(final String cssPrefix) {
112                 this.cssPrefix = cssPrefix;
113         }
114
115         public NavigationItem setPattern(final String pattern) {
116                 matchingPattern = pattern;
117                 return this;
118         }
119
120         @Override
121         public String toString() {
122                 return "NavigationItem [matchingPattern=" + matchingPattern + ", localeToTitle=" + localeToTitle
123                                 + ", subElements count=" + subElements.size() + ", linkUrl=" + linkUrl + ", cssPrefix=" + cssPrefix
124                                 + "]";
125         }
126
127 }