Commit | Line | Data |
---|---|---|
fd69647f NR |
1 | package be.nikiroo.fanfix.searchable; |
2 | ||
3 | import java.util.ArrayList; | |
4 | import java.util.List; | |
5 | ||
6 | /** | |
7 | * This class represents a tag that can be searched on a supported website. | |
8 | * | |
9 | * @author niki | |
10 | */ | |
11 | public class SearchableTag { | |
12 | private String id; | |
13 | private String name; | |
14 | private boolean complete; | |
15 | private long count; | |
e66c9078 NR |
16 | |
17 | private SearchableTag parent; | |
fd69647f NR |
18 | private List<SearchableTag> children; |
19 | ||
76ec935e NR |
20 | /** |
21 | * The number of stories result pages this tag can get. | |
22 | * <p> | |
23 | * We keep more information than what the getter/setter returns/accepts. | |
24 | * <ul> | |
25 | * <li>-2: this tag does not support stories results (not a leaf tag)</li> | |
26 | * <li>-1: the number is not yet known, but will be known after a | |
27 | * {@link BasicSearchable#fillTag(SearchableTag)} operation</li> | |
28 | * <li>X: the number of pages</li> | |
29 | * </ul> | |
30 | */ | |
31 | private int pages; | |
32 | ||
fd69647f NR |
33 | /** |
34 | * Create a new {@link SearchableTag}. | |
76ec935e NR |
35 | * <p> |
36 | * Note that tags are complete by default. | |
fd69647f NR |
37 | * |
38 | * @param id | |
39 | * the ID (usually a way to find the linked stories later on) | |
40 | * @param name | |
41 | * the tag name, which can be displayed to the user | |
76ec935e NR |
42 | * @param leaf |
43 | * the tag is a leaf tag, that is, it will not return subtags | |
44 | * with {@link BasicSearchable#fillTag(SearchableTag)} but will | |
45 | * return stories with | |
aaeabf3a | 46 | * {@link BasicSearchable#search(SearchableTag, int)} |
76ec935e NR |
47 | */ |
48 | public SearchableTag(String id, String name, boolean leaf) { | |
49 | this(id, name, leaf, true); | |
50 | } | |
51 | ||
52 | /** | |
53 | * Create a new {@link SearchableTag}. | |
54 | * | |
55 | * @param id | |
56 | * the ID (usually a way to find the linked stories later on) | |
57 | * @param name | |
58 | * the tag name, which can be displayed to the user | |
59 | * @param leaf | |
60 | * the tag is a leaf tag, that is, it will not return subtags | |
61 | * with {@link BasicSearchable#fillTag(SearchableTag)} but will | |
62 | * return stories with | |
aaeabf3a | 63 | * {@link BasicSearchable#search(SearchableTag, int)} |
fd69647f | 64 | * @param complete |
76ec935e | 65 | * the tag {@link SearchableTag#isComplete()} or not |
fd69647f | 66 | */ |
76ec935e | 67 | public SearchableTag(String id, String name, boolean leaf, boolean complete) { |
fd69647f NR |
68 | this.id = id; |
69 | this.name = name; | |
70 | this.complete = complete; | |
71 | ||
76ec935e NR |
72 | setLeaf(leaf); |
73 | ||
fd69647f NR |
74 | children = new ArrayList<SearchableTag>(); |
75 | } | |
76 | ||
76ec935e NR |
77 | /** |
78 | * The ID (usually a way to find the linked stories later on). | |
79 | * | |
80 | * @return the ID | |
81 | */ | |
fd69647f NR |
82 | public String getId() { |
83 | return id; | |
84 | } | |
85 | ||
76ec935e NR |
86 | /** |
87 | * The tag name, which can be displayed to the user. | |
88 | * | |
89 | * @return then name | |
90 | */ | |
fd69647f NR |
91 | public String getName() { |
92 | return name; | |
93 | } | |
94 | ||
aaeabf3a NR |
95 | /** |
96 | * The fully qualified tag name, which can be displayed to the user. | |
97 | * <p> | |
98 | * It will display all the tags that lead to this one as well as this one. | |
99 | * | |
100 | * @return the fully qualified name | |
101 | */ | |
102 | public String getFqName() { | |
103 | if (parent != null) { | |
104 | return parent.getFqName() + " / " + name; | |
105 | } | |
106 | ||
107 | return name; | |
108 | } | |
109 | ||
fd69647f | 110 | /** |
76ec935e NR |
111 | * Non-complete, non-leaf tags can still be completed via a |
112 | * {@link BasicSearchable#fillTag(SearchableTag)} operation from a | |
fd69647f | 113 | * {@link BasicSearchable}, in order to gain (more?) subtag children. |
76ec935e NR |
114 | * <p> |
115 | * This method does not make sense for leaf tags. | |
fd69647f | 116 | * |
76ec935e | 117 | * @return TRUE if it is complete |
fd69647f NR |
118 | */ |
119 | public boolean isComplete() { | |
120 | return complete; | |
121 | } | |
122 | ||
123 | /** | |
76ec935e NR |
124 | * Non-complete, non-leaf tags can still be completed via a |
125 | * {@link BasicSearchable#fillTag(SearchableTag)} operation from a | |
fd69647f | 126 | * {@link BasicSearchable}, in order to gain (more?) subtag children. |
76ec935e NR |
127 | * <p> |
128 | * This method does not make sense for leaf tags. | |
fd69647f NR |
129 | * |
130 | * @param complete | |
76ec935e | 131 | * TRUE if it is complete |
fd69647f NR |
132 | */ |
133 | public void setComplete(boolean complete) { | |
134 | this.complete = complete; | |
135 | } | |
136 | ||
137 | /** | |
138 | * The number of items that can be found with this tag if it is searched. | |
139 | * <p> | |
140 | * Will report the number of subtags by default. | |
141 | * | |
142 | * @return the number of items | |
143 | */ | |
144 | public long getCount() { | |
145 | long count = this.count; | |
146 | if (count <= 0) { | |
147 | count = children.size(); | |
148 | } | |
149 | ||
150 | return count; | |
151 | } | |
152 | ||
fd69647f NR |
153 | /** |
154 | * The number of items that can be found with this tag if it is searched. | |
155 | * | |
156 | * @param count | |
157 | * the new count | |
158 | */ | |
159 | public void setCount(long count) { | |
160 | this.count = count; | |
161 | } | |
162 | ||
76ec935e NR |
163 | /** |
164 | * The number of stories result pages this tag contains, only make sense if | |
165 | * {@link SearchableTag#isLeaf()} returns TRUE. | |
166 | * <p> | |
167 | * Will return -1 if the number is not yet known. | |
168 | * | |
169 | * @return the number of pages, or -1 | |
170 | */ | |
171 | public int getPages() { | |
172 | return Math.max(-1, pages); | |
173 | } | |
174 | ||
175 | /** | |
176 | * The number of stories result pages this tag contains, only make sense if | |
177 | * {@link SearchableTag#isLeaf()} returns TRUE. | |
178 | * | |
179 | * @param pages | |
180 | * the (positive or 0) number of pages | |
181 | */ | |
182 | public void setPages(int pages) { | |
183 | this.pages = Math.max(-1, pages); | |
184 | } | |
185 | ||
186 | /** | |
187 | * This tag is a leaf tag, that is, it will not return other subtags with | |
188 | * {@link BasicSearchable#fillTag(SearchableTag)} but will return stories | |
aaeabf3a | 189 | * with {@link BasicSearchable#search(SearchableTag, int)}. |
76ec935e NR |
190 | * |
191 | * @return TRUE if it is | |
192 | */ | |
193 | public boolean isLeaf() { | |
194 | return pages > -2; | |
195 | } | |
196 | ||
197 | /** | |
198 | * This tag is a leaf tag, that is, it will not return other subtags with | |
199 | * {@link BasicSearchable#fillTag(SearchableTag)} but will return stories | |
aaeabf3a | 200 | * with {@link BasicSearchable#search(SearchableTag, int)}. |
76ec935e NR |
201 | * <p> |
202 | * Will reset the number of pages to -1. | |
203 | * | |
204 | * @param leaf | |
205 | * TRUE if it is | |
206 | */ | |
207 | public void setLeaf(boolean leaf) { | |
208 | pages = leaf ? -1 : -2; | |
209 | } | |
210 | ||
fd69647f NR |
211 | /** |
212 | * The subtag children of this {@link SearchableTag}. | |
213 | * <p> | |
214 | * Never NULL. | |
215 | * <p> | |
216 | * Note that if {@link SearchableTag#isComplete()} returns false, you can | |
217 | * still fill (more?) subtag children with a {@link BasicSearchable}. | |
218 | * | |
219 | * @return the subtag children, never NULL | |
220 | */ | |
221 | public List<SearchableTag> getChildren() { | |
222 | return children; | |
223 | } | |
224 | ||
225 | /** | |
226 | * Add the given {@link SearchableTag} as a subtag child. | |
227 | * | |
228 | * @param tag | |
229 | * the tag to add | |
230 | */ | |
231 | public void add(SearchableTag tag) { | |
232 | children.add(tag); | |
e66c9078 NR |
233 | tag.parent = this; |
234 | } | |
235 | ||
236 | /** | |
237 | * This {@link SearchableTag} parent tag, or NULL if none. | |
238 | * | |
239 | * @return the parent or NULL | |
240 | */ | |
241 | public SearchableTag getParent() { | |
242 | return parent; | |
fd69647f NR |
243 | } |
244 | ||
245 | /** | |
246 | * Display a DEBUG {@link String} representation of this object. | |
247 | */ | |
248 | @Override | |
249 | public String toString() { | |
250 | String rep = name + " [" + id + "]"; | |
251 | if (!complete) { | |
252 | rep += "*"; | |
253 | } | |
254 | ||
255 | if (getCount() > 0) { | |
596ed3d6 | 256 | rep += " (" + getCount() + ")"; |
fd69647f NR |
257 | } |
258 | ||
259 | if (!children.isEmpty()) { | |
260 | String tags = ""; | |
261 | int i = 1; | |
262 | for (SearchableTag tag : children) { | |
263 | if (!tags.isEmpty()) { | |
264 | tags += ", "; | |
265 | } | |
266 | ||
267 | if (i > 10) { | |
268 | tags += "..."; | |
269 | break; | |
270 | } | |
271 | ||
272 | tags += tag; | |
273 | i++; | |
274 | } | |
275 | ||
276 | rep += ": " + tags; | |
277 | } | |
278 | ||
279 | return rep; | |
280 | } | |
281 | } |