BrightSide Workbench Full Report + Source Code
Navigator.java
Go to the documentation of this file.
1 /*
2  * TurrĂ³ i Cutiller Foundation. License notice.
3  * Copyright (C) 2011 Lluis TurrĂ³ Cutiller <http://www.turro.org/>
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Affero General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU Affero General Public License for more details.
14  *
15  * You should have received a copy of the GNU Affero General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 package org.turro.elephant.impl.navigation;
19 
20 import java.io.IOException;
21 import java.io.PrintWriter;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.SortedSet;
25 import org.turro.elephant.context.Application;
26 import org.turro.elephant.context.ElephantContext;
27 import org.turro.elephant.context.IConstructor;
28 import org.turro.elephant.impl.context.ContextAdapter;
29 import org.turro.elephant.web.ElContext;
30 import org.turro.elephant.web.ElContextMap;
31 
36 public class Navigator {
37 
39  protected ElContext context, current;
40  protected SortedSet<ElContext> contexts;
41  protected int level, levelUsed, preloaded;
42  protected boolean dynamicLoad, showCurrent, showTitle, drawDecorators = true;
43  protected NavigatorType type;
44  protected String cssClass;
45 
49  this.context = context;
50  this.level = context.getLevel();
51  }
52 
53  public void initialize() {
54  this.constructor = Application.getApplication().getConstructor();
55  this.current = constructor.getCurrentContext();
56  if(current != null) {
57  if(type == NavigatorType.FLOATING) {
58  this.contexts = new ContextAdapter(context.getChildren()).getVisible();
59  }
60  else {
61  levelUsed = level;
63  levelUsed--;
64  }
65  this.contexts = ElContextMap.getContexts(current.getPath(), levelUsed);
66  }
67  if(cssClass == null) {
68  cssClass = type.name().toLowerCase();
69  }
70  }
71  }
72 
73  public boolean somethingToShow() {
74  return (contexts != null) && (!contexts.isEmpty());
75  }
76 
77  public void draw() throws IOException {
78  if (!contexts.isEmpty()) {
79  PrintWriter out = constructor.getOut();
80  out.print(getStart());
81  if (type == NavigatorType.LOCATION) {
82  ElContext[] ancestor = current.getAncestors().toArray(new ElContext[0]);
83  for (ElContext ancestor1 : ancestor) {
84  out.print("<a href='" + ancestor1.getWebPath() + "'>" + ancestor1.getName() + "</a>");
85  }
86  // TODO: provide aditional entries comming from elements, JavaScript?
87  out.print("<span id='ext_location'></span>");
88 // if (dynamicLoad) {
89 // constructor.addOnLoadedJavaScript("$$('.location a').each(function(node) { prepareNavigator('" + constructor.getRootWebPath() + "', node, 0); });");
90 // }
91  } else if (type == NavigatorType.TRAVERSAL) {
92  int levelUsed = level - 1;
93  ElContext previous = getPrevious(current),
94  next = getNext(current, true);
95  int currLevel = current.getLevel();
96  out.print("<table width='100%'><tr><td width='35%' align='left'>");
97  if (previous != null && ((levelUsed > 0 && currLevel > levelUsed) || levelUsed == 0)) {
98  out.print("<span id='trav-previous'><a href='" + previous.getWebPath() + "'>" + previous.getName() + "</a></span>");
99  }
100  out.print("</td><td width='30%' align='center'>");
101  if (current.getParent() != null && !current.getParent().equals(previous) && ((levelUsed > 0 && currLevel > levelUsed) || levelUsed == 0)) {
102  out.print("<span id='trav-parent'><a href='" + current.getParent().getWebPath() + "'>" + current.getParent().getName() + "</a></span>");
103  }
104  out.print("</td><td width='35%' align='right'>");
105  if (next != null) {
106  out.print("<span id='trav-next'><a href='" + next.getWebPath() + "'>" + next.getName() + "</a></span>");
107  }
108  out.print("</td></tr></table>");
109  if (showTitle) {
110  out.print("<div class='context-title'>" + current.getName() + "</div>");
111  }
112 // if (dynamicLoad) {
113 // constructor.addOnLoadedJavaScript("$$('.traversal a').each(function(node) { prepareNavigator('" + constructor.getRootWebPath() + "', node, 0); });");
114 // }
115  } else if (type == NavigatorType.FLOATING) {
116  if (drawDecorators && type != NavigatorType.TABULATOR) {
117  out.print("<div class='" + cssClass + "_top'><div></div></div>");
118  }
119  out.print(getStartBody());
120  for (ElContext ctx : contexts) {
121  if (ctx.canDisplay()) {
122  renderContext(out, ctx, current);
123  doChildren(out, ctx, current, preloaded);
124  out.print("</li>");
125  }
126  }
127  out.print(getEndBody());
128  if (drawDecorators && type != NavigatorType.TABULATOR) {
129  out.print("<div class='" + cssClass + "_bottom'><div></div></div>");
130  }
131  } else {
132  String offsetLeft = "0";
133  if (drawDecorators && type != NavigatorType.TABULATOR) {
134  out.print("<div class='" + cssClass + "_top'><div></div></div>");
135  }
136  out.print(getStartBody());
137  for (ElContext ctx : contexts) {
138  if (ctx.canDisplay()) {
139  renderContext(out, ctx, current);
140  doChildren(out, ctx, current, preloaded);
141  out.print("</li>");
142  }
143  }
144  out.print(getEndBody());
145  if (drawDecorators && type != NavigatorType.TABULATOR) {
146  out.print("<div class='" + cssClass + "_bottom'><div></div></div>");
147  offsetLeft = "100";
148  }
149  //TODO: check roles and make children also sortable
150  //constructor.addOnLoadedJavaScript("Sortable.create('id_" + cssClass +
151  // "' " + (type == NavigatorType.TABULATOR ? ",{constraint: 'horizontal'}" : "") + ")");
153  //constructor.addOnLoadedJavaScript("$$('." + cssClass + " a').each(function(node) { prepareNavigator('" + constructor.getRootWebPath() + "', node, " + offsetLeft + "); });");
154  constructor.addOnLoadedJavaScript("$('." + cssClass + "').find('a').each(function(index) { prepareNavigator('" + ElephantContext.getRootWebPath() + "', $(this), " + offsetLeft + "); });");
155  }
156  }
157  out.print(getEnd());
158  }
159  }
160 
161  public Collection<ContextNavigatorItem> contexts() throws IOException {
162  ArrayList<ContextNavigatorItem> list = new ArrayList<>();
163  if(current != null) {
164  ElContext elCurrent = ElContextMap.getContext(current.getPath());
165  if(elCurrent != null) {
166  if (type == NavigatorType.LOCATION) {
167  for(ElContext ctx : elCurrent.getAncestors()) {
168  list.add(new ContextNavigatorItem(ctx, elCurrent));
169  }
170  } else if (type == NavigatorType.TRAVERSAL) {
171  int levelUsed = level - 1;
172  ElContext previous = elCurrent.getPrevious(),
173  next = elCurrent.getNext(true);
174  int currLevel = elCurrent.getLevel();
175  if (previous != null && ((levelUsed > 0 && currLevel > levelUsed) || levelUsed == 0)) {
176  list.add(new ContextNavigatorItem(previous, elCurrent));
177  } else {
178  list.add(null);
179  }
180  if (elCurrent.getParent() != null && !elCurrent.getParent().equals(previous) && ((levelUsed > 0 && currLevel > levelUsed) || levelUsed == 0)) {
181  list.add(new ContextNavigatorItem(elCurrent.getParent(), elCurrent));
182  } else {
183  list.add(null);
184  }
185  if (next != null) {
186  list.add(new ContextNavigatorItem(next, elCurrent));
187  } else {
188  list.add(null);
189  }
190  } else if (type == NavigatorType.FLOATING) {
191  for(ElContext ctx : elCurrent.getVisibleChildren()) {
192  if (ctx.canDisplay()) {
193  list.add(new ContextNavigatorItem(ctx, elCurrent));
194  }
195  }
196  } else {
197  for(ElContext ctx : ElContextMap.getContexts(elCurrent.getPath(), level)) {
198  if (ctx.canDisplay()) {
199  list.add(new ContextNavigatorItem(ctx, elCurrent));
200  }
201  }
202  }
203  }
204  }
205  return list;
206  }
207 
208  private void doChildren(PrintWriter out, ElContext parent, ElContext current, int preload) {
209  if (preload <= 0 && !(showCurrent && parent.inPath(current))) {
210  return;
211  }
212  SortedSet<ElContext> children = parent.getChildren();
213  if (children.size() > 0) {
214  out.print("<ul>");
215  for (ElContext ic : children) {
216  if (ic.canDisplay()) {
217  renderContext(out, ic, current);
218  doChildren(out, ic, current, preload - 1);
219  out.print("</li>");
220  }
221  }
222  out.print("</ul>");
223  }
224  }
225 
226  public String getStart() {
227  return "<div class='" + cssClass + "'>";
228  }
229 
230  public String getEnd() {
231  return "</div>";
232  }
233 
234  public String getStartBody() {
235  return "<ul id='id_" + cssClass + "' class='" + cssClass + "'>";
236  }
237 
238  public String getEndBody() {
239  return "</ul>";
240  }
241 
242  private void renderContext(PrintWriter out, ElContext context, ElContext current) {
243  //TODO: add level to cssClass
244  String classCss = (context.equals(current) ? " class='active'" : (context.inPath(current) ? " class='inpath'" : (!context.isInRole() ? " class='protected'" : "")));
245  out.print("<li" + classCss + ">");
246  out.print("<a" + classCss + " href='" + context.getWebPath() + "'>");
247  out.print(context.getName());
248  out.print("</a>");
249  }
250 
251  private ElContext getPrevious(ElContext current) {
252  if (current == null) {
253  return null;
254  }
255  if (current.getParent() != null) {
256  SortedSet<ElContext> siblings = new ContextAdapter(current.getParent().getChildren()).getVisible();
257  for (ElContext ctx : siblings) {
258  if(current.equals(ctx) && !ctx.equals(siblings.first()) && ctx.canDisplay()) {
259  return getLastChildren(ctx);
260  }
261  }
262  return current.getParent();
263  }
264  return null;
265  }
266 
267  private ElContext getLastChildren(ElContext current) {
268  SortedSet<ElContext> children = new ContextAdapter(current.getChildren()).getVisible();
269  if(children.size() > 0) {
270  return getLastChildren(children.last());
271  }
272  return current;
273  }
274 
275  private ElContext getNext(ElContext current, boolean doChildren) {
276  if (current == null) {
277  return null;
278  }
279  if (doChildren) {
280  SortedSet<ElContext> children = new ContextAdapter(current.getChildren()).getVisible();
281  if (children.size() > 0) {
282  return children.first();
283  }
284  }
285  if (current.getParent() != null) {
286  SortedSet<ElContext> siblings = new ContextAdapter(current.getParent().getChildren()).getVisible();
287  for (ElContext ctx : siblings) {
288  if (current.equals(ctx) && !ctx.equals(siblings.last())) {
289  return ctx;
290  }
291  }
292  }
293  return getNext(current.getParent(), false);
294  }
295 
297  return type;
298  }
299 
300  public void setType(NavigatorType type) {
301  this.type = type;
302  }
303 
304  public void setTypeString(String typeStr) {
305  for (NavigatorType nt : NavigatorType.values()) {
306  if (nt.name().toLowerCase().equals(typeStr.toLowerCase())) {
307  this.type = nt;
308  }
309  }
310  }
311 
312  public String getCssClass() {
313  return cssClass;
314  }
315 
316  public void setCssClass(String cssClass) {
317  this.cssClass = cssClass;
318  }
319 
320  public boolean isDrawDecorators() {
321  return drawDecorators;
322  }
323 
324  public void setDrawDecorators(boolean drawDecorators) {
325  this.drawDecorators = drawDecorators;
326  }
327 
328  public int getPreloaded() {
329  return preloaded;
330  }
331 
332  public void setPreloaded(int preloaded) {
333  this.preloaded = preloaded;
334  }
335 
336  public boolean isDynamicLoad() {
337  return dynamicLoad;
338  }
339 
340  public void setDynamicLoad(boolean dynamicLoad) {
341  this.dynamicLoad = dynamicLoad;
342  }
343 
344  public int getLevel() {
345  return level;
346  }
347 
348  public void setLevel(int level) {
349  this.level = level;
350  }
351 
352  public boolean isShowCurrent() {
353  return showCurrent;
354  }
355 
356  public void setShowCurrent(boolean showCurrent) {
357  this.showCurrent = showCurrent;
358  }
359 
360  public boolean isShowTitle() {
361  return showTitle;
362  }
363 
364  public void setShowTitle(boolean showTitle) {
365  this.showTitle = showTitle;
366  }
367 
368  public void drawTabulator(int level) throws IOException {
370  setCssClass(null);
371  setLevel(level);
372  initialize();
373  draw();
374  }
375 
376  public void drawLocation() throws IOException {
378  setCssClass(null);
379  initialize();
380  draw();
381  }
382 
383  public void drawOptions(boolean decorators, int level, int preloaded, boolean current) throws IOException {
385  setCssClass(null);
386  setDrawDecorators(decorators);
387  setLevel(level);
388  setPreloaded(preloaded);
389  setShowCurrent(current);
390  initialize();
391  draw();
392  }
393 
394  public boolean hasOptions(int level, int preloaded, boolean current) throws IOException {
396  setCssClass(null);
397  setLevel(level);
398  setPreloaded(preloaded);
399  setShowCurrent(current);
400  initialize();
401  for(ElContext ctx : contexts) {
402  if (ctx.canDisplay()) {
403  return true;
404  }
405  }
406  return false; //contexts.length > 0;
407  }
408 
409  public void drawTraversal(boolean title) throws IOException {
411  setCssClass(null);
412  setShowTitle(title);
413  initialize();
414  draw();
415  }
416 
417  public Collection<ContextNavigatorItem> contextTabulator(int level) throws IOException {
419  setCssClass(null);
420  setLevel(level);
421  initialize();
422  return contexts();
423  }
424 
425  public Collection<ContextNavigatorItem> contextLocation() throws IOException {
427  setCssClass(null);
428  initialize();
429  return contexts();
430  }
431 
432  public Collection<ContextNavigatorItem> contextOptions(int level, int preloaded, boolean current) throws IOException {
434  setCssClass(null);
435  setDrawDecorators(false);
436  setLevel(level);
437  setPreloaded(preloaded);
438  setShowCurrent(current);
439  initialize();
440  return contexts();
441  }
442 
443  public Collection<ContextNavigatorItem> contextTraversal() throws IOException {
445  setCssClass(null);
446  initialize();
447  return contexts();
448  }
449 
450 }
void setDrawDecorators(boolean drawDecorators)
Definition: Navigator.java:324
Collection< ContextNavigatorItem > contexts()
Definition: Navigator.java:161
void setDynamicLoad(boolean dynamicLoad)
Definition: Navigator.java:340
void setShowCurrent(boolean showCurrent)
Definition: Navigator.java:356
Collection< ContextNavigatorItem > contextOptions(int level, int preloaded, boolean current)
Definition: Navigator.java:432
Collection< ContextNavigatorItem > contextTraversal()
Definition: Navigator.java:443
Collection< ContextNavigatorItem > contextTabulator(int level)
Definition: Navigator.java:417
boolean hasOptions(int level, int preloaded, boolean current)
Definition: Navigator.java:394
Collection< ContextNavigatorItem > contextLocation()
Definition: Navigator.java:425
void drawOptions(boolean decorators, int level, int preloaded, boolean current)
Definition: Navigator.java:383
static ElContext getContext(IConstructor constructor)
static SortedSet< ElContext > getContexts(String from, int level)
TreeSet< ElContext > getChildren()
Definition: ElContext.java:196
boolean equals(Object obj)
Definition: ElContext.java:621
TreeSet< ElContext > getAncestors()
Definition: ElContext.java:235
boolean inPath(ElContext context)
Definition: ElContext.java:122
ElContext getNext(boolean doChildren)
Definition: ElContext.java:265
TreeSet< ElContext > getVisibleChildren()
Definition: ElContext.java:209
void addOnLoadedJavaScript(String script)