1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.jetspeed.modules.actions.controllers;
18
19
20 import org.apache.jetspeed.om.profile.Profile;
21 import org.apache.jetspeed.om.registry.RegistryEntry;
22 import org.apache.jetspeed.om.profile.Portlets;
23 import org.apache.jetspeed.om.profile.Entry;
24 import org.apache.jetspeed.om.profile.Layout;
25 import org.apache.jetspeed.om.profile.psml.PsmlLayout;
26 import org.apache.jetspeed.portal.PortletSet;
27 import org.apache.jetspeed.portal.PortletController;
28 import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
29 import org.apache.jetspeed.services.logging.JetspeedLogger;
30 import org.apache.jetspeed.services.Registry;
31 import org.apache.jetspeed.services.rundata.JetspeedRunData;
32 import org.apache.jetspeed.util.AutoProfile;
33
34
35
36 import org.apache.turbine.util.RunData;
37 import org.apache.turbine.modules.ActionLoader;
38
39
40 import org.apache.velocity.context.Context;
41
42
43 import java.util.Vector;
44 import java.util.List;
45 import java.util.StringTokenizer;
46 import java.util.Iterator;
47 import java.util.ArrayList;
48 import java.util.Map;
49 import java.util.HashMap;
50 import java.util.Collections;
51 import java.util.Comparator;
52
53 /***
54 * This action builds a context suitable for controllers handlings simple
55 * sorted lists of portlets
56 *
57 * @author <a href="mailto:raphael@apache.org">Raphaël Luta</a>
58 * @author <a href="mailto:paulsp@apache.org">Paul Spencer</a>
59 */
60 public class RowColumnControllerAction extends VelocityControllerAction
61 {
62
63 /***
64 * Static initialization of the logger for this class
65 */
66 private static final JetspeedLogger logger = JetspeedLogFactoryService.getLogger(RowColumnControllerAction.class.getName());
67
68 /***
69 * Subclasses must override this method to provide default behavior
70 * for the portlet action
71 */
72 protected void buildNormalContext( PortletController controller,
73 Context context,
74 RunData rundata )
75 {
76
77 String sizes = controller.getConfig().getInitParameter("sizes");
78 context.put("sizes", getCellSizes(sizes));
79 }
80
81 /*** Parses the size config info and returns a list of
82 * size values for the current set
83 *
84 * @param sizeList java.lang.String a comma separated string a values
85 * @return a List of values
86 */
87 public static List getCellSizes(String sizelist)
88 {
89 List list = new Vector();
90
91 if (sizelist!=null)
92 {
93 StringTokenizer st = new StringTokenizer(sizelist,",");
94 while (st.hasMoreTokens())
95 {
96 list.add(st.nextToken());
97 }
98 }
99
100 return list;
101 }
102
103 /***
104 * Adds a "pane" portlet object in the context which represents the
105 * currently selected pane
106 */
107 protected void buildCustomizeContext( PortletController controller,
108 Context context,
109 RunData rundata )
110 {
111 super.buildCustomizeContext(controller, context, rundata);
112
113 JetspeedRunData jdata = (JetspeedRunData)rundata;
114 PortletSet set = (PortletSet)jdata.getCustomized();
115
116 Portlets portlets = jdata.getCustomizedProfile()
117 .getDocument()
118 .getPortletsById(set.getID());
119
120 List plist = new ArrayList();
121 List work = new ArrayList();
122 List filler = Collections.nCopies(portlets.getPortletsCount()+portlets.getEntryCount(),null);
123 plist.addAll(filler);
124
125 for (int i=0; i < portlets.getPortletsCount(); i++)
126 {
127 Portlets p = portlets.getPortlets(i);
128 if (logger.isDebugEnabled())
129 {
130 logger.debug("RowColumnControllerAction: processing portlet: " + p.getTitle());
131 }
132 Layout layout = p.getLayout();
133 if (layout == null)
134 {
135
136 if (logger.isDebugEnabled())
137 {
138 logger.debug("RowColumnControllerAction: no layout, creating a new one");
139 }
140 layout = new PsmlLayout();
141 layout.setPosition(i);
142 p.setLayout(layout);
143 }
144 if (layout!=null)
145 {
146 try
147 {
148 int pos = (int)layout.getPosition();
149 if (logger.isDebugEnabled())
150 {
151 logger.debug("RowColumnControllerAction: layout has position: " + pos);
152 }
153 if (pos >= 0 && pos < plist.size())
154 {
155 plist.set(pos,p);
156 }
157 else
158 {
159 work.add(p);
160 }
161 }
162 catch (Exception e)
163 {
164 logger.error("Layout error", e);
165 layout.setPosition(-1);
166 work.add(p);
167 }
168 }
169 else
170 {
171 work.add(p);
172 }
173 }
174
175 for (int i=0; i < portlets.getEntryCount(); i++)
176 {
177 Entry p = portlets.getEntry(i);
178 Layout layout = p.getLayout();
179 if (layout!=null)
180 {
181 try
182 {
183 int pos = (int)layout.getPosition();
184 if (pos>=0)
185 {
186 plist.set(pos,p);
187 }
188 else
189 {
190 work.add(p);
191 }
192 }
193 catch (Exception e)
194 {
195 layout.setPosition(-1);
196 work.add(p);
197 }
198 }
199 else
200 {
201 work.add(p);
202 }
203 }
204
205 Iterator i = work.iterator();
206 for(int idx=0;idx < plist.size(); idx++)
207 {
208 if (plist.get(idx)==null)
209 {
210 if (i.hasNext())
211 {
212 plist.set(idx,i.next());
213 }
214 else
215 {
216 plist.remove(idx);
217 }
218 }
219 }
220
221 Map titles = new HashMap();
222 i = plist.iterator();
223 while(i.hasNext())
224 {
225 Object obj = i.next();
226
227 if (obj instanceof Portlets)
228 {
229 Portlets entry = (Portlets)obj;
230 if ((entry.getMetaInfo()!=null)&&(entry.getMetaInfo().getTitle()!=null))
231 {
232 titles.put(entry.getId(),entry.getMetaInfo().getTitle());
233 }
234 }
235 else
236 {
237 Entry entry = (Entry)obj;
238 if ((entry.getMetaInfo()!=null)&&(entry.getMetaInfo().getTitle()!=null))
239 {
240 titles.put(entry.getId(), entry.getMetaInfo().getTitle());
241 }
242 else
243 {
244 RegistryEntry pentry = Registry.getEntry(Registry.PORTLET,entry.getParent());
245
246 if (pentry!=null)
247 {
248 titles.put(entry.getId(), pentry.getTitle());
249 }
250 }
251 }
252 }
253
254
255 context.put("portlets",plist);
256 context.put("titles",titles);
257
258 /***
259 * Make a list of all used portlets available thru the 'runs' reference
260 * --------------------------------------------------------------------------
261 * last modified: 10/31/01
262 * Andreas Kempf, Siemens ICM S CP PE, Munich
263 * mailto: A.Kempf@web.de
264 */
265 context.put("runs", AutoProfile.getPortletList(rundata));
266
267 }
268
269 /***
270 * Cancel the current customizations. If this was the last customization
271 * on the stack, then return the user to the home page.
272 */
273 public void doCancel(RunData data, Context context)
274 {
275 ((JetspeedRunData)data).setCustomized(null);
276
277 if (((JetspeedRunData)data).getCustomized() == null)
278 {
279 try
280 {
281 ActionLoader.getInstance().exec( data, "controls.EndCustomize" );
282 }
283 catch (Exception e)
284 {
285 logger.error("Unable to load action controls.EndCustomize ",e);
286 }
287 }
288 }
289
290 public void doSave(RunData data, Context context)
291 {
292 doApply(data, context);
293 }
294
295 public void doApply(RunData data, Context context)
296 {
297
298 ((JetspeedRunData) data).setCustomized(null);
299
300
301 if (((JetspeedRunData) data).getCustomized() == null)
302 {
303
304 try
305 {
306 ((JetspeedRunData) data).getCustomizedProfile().store();
307 }
308 catch (Exception e)
309 {
310 logger.error("Unable to save profile ",e);
311 }
312
313 try
314 {
315 ActionLoader.getInstance().exec( data, "controls.EndCustomize" );
316 }
317 catch (Exception e)
318 {
319 logger.error("Unable to load action controls.EndCustomize ",e);
320 }
321 }
322 }
323
324 /*** Remove a pane from the current set
325 * This method expects the following parameters
326 * - paneid: the id a the pane to modify within the current profile
327 * - position: the position of the component to delete
328 */
329 public void doDelete(RunData data, Context context) throws Exception
330 {
331 JetspeedRunData jdata = (JetspeedRunData)data;
332 PortletSet customizedSet = (PortletSet)jdata.getCustomized();
333 int position = data.getParameters().getInt("position",-1);
334 Profile profile = jdata.getCustomizedProfile();
335
336
337
338
339
340 if (customizedSet == null) return;
341
342 if (position > -1)
343 {
344 Portlets set = profile.getDocument()
345 .getPortletsById(customizedSet.getID());
346 if (set != null)
347 {
348
349 for(int i=0; i < set.getPortletsCount(); i++)
350 {
351 Portlets p = set.getPortlets(i);
352 Layout layout = p.getLayout();
353
354
355
356
357
358
359
360 if ((layout!=null) && (layout.getPosition() != -1))
361 {
362
363 int lpos = (int)layout.getPosition();
364 if (lpos==position)
365 {
366 set.removePortlets(i);
367
368 updateLayoutPositions(set);
369
370
371
372
373
374 return;
375 }
376 }
377 }
378
379
380 for(int i=0; i < set.getEntryCount(); i++)
381 {
382 Entry p = set.getEntry(i);
383 Layout layout = p.getLayout();
384
385 if ((layout!=null) && (layout.getPosition() != -1))
386 {
387 int lpos = (int)layout.getPosition();
388
389 if (lpos==position)
390 {
391 set.removeEntry(i);
392
393
394
395
396 return;
397 }
398 }
399 }
400
401
402 if (position < set.getPortletsCount())
403 {
404 set.removePortlets(position);
405
406
407
408
409 return;
410 }
411
412 if (position < set.getEntryCount())
413 {
414 set.removeEntry(position);
415
416
417
418
419 return;
420 }
421 }
422 }
423
424
425 }
426
427 /***
428 * Updates the layout position based on physical order within the resorted portlet list. Assures that
429 * layout position is always consecutive and within bounds.
430 *
431 * @param set
432 */
433 private void updateLayoutPositions(Portlets set)
434 {
435
436 List list = new ArrayList();
437 for(int i = 0; i < set.getPortletsCount(); i++)
438 {
439 Portlets pane = set.getPortlets(i);
440 list.add(pane);
441 }
442
443
444 Collections.sort(list,
445 new Comparator()
446 {
447 public int compare(Object pane1, Object pane2)
448 {
449 Long pos1 = new Long(((Portlets) pane1).getLayout().getPosition());
450 Long pos2 = new Long(((Portlets) pane2).getLayout().getPosition());
451 return pos1.compareTo(pos2);
452 }
453 });
454
455
456 int position = 0;
457 for (Iterator iter = list.iterator(); iter.hasNext();)
458 {
459 Portlets pane = (Portlets) iter.next();
460 Layout layout = pane.getLayout();
461 layout.setPosition(position++);
462 }
463 }
464
465 /*** Move a component up within the pane
466 * This method expects the following parameters
467 * - paneid: the id a the pane to modify within the current profile
468 * - position: move the component which occupies this position
469 */
470 public void doUp(RunData data, Context context) throws Exception
471 {
472 doMove(data,context,true);
473 }
474
475 /*** Move a component down within the pane
476 * This method expects the following parameters
477 * - paneid: the id a the pane to modify within the current profile
478 * - position: move the component which occupies this position
479 */
480 public void doDown(RunData data, Context context) throws Exception
481 {
482 doMove(data,context,false);
483 }
484
485 /*** Move a component within the pane
486 * This method expects the following parameters
487 * - paneid: the id a the pane to modify within the current profile
488 * - position: move the component which occupies this position
489 * The moveUp boolean determines the direction of the move
490 */
491 public void doMove(RunData data, Context context, boolean moveUp) throws Exception
492 {
493 JetspeedRunData jdata = (JetspeedRunData)data;
494 PortletSet customizedSet = (PortletSet)jdata.getCustomized();
495 int position = data.getParameters().getInt("position",-1);
496 Profile profile = jdata.getCustomizedProfile();
497
498
499
500
501
502 if (customizedSet == null) return;
503
504 if (position > -1)
505 {
506 int target = -1;
507
508 Portlets set = profile.getDocument()
509 .getPortletsById(customizedSet.getID());
510 Layout targetLayout = null;
511 Layout baseLayout = null;
512
513 if (set != null)
514 {
515
516
517 if ( moveUp )
518 {
519 if ( (position >= set.getPortletsCount())
520 && (position >= set.getEntryCount()) ) return;
521 target = position + 1;
522 }
523 else
524 {
525 if (position ==0) return;
526 target = position - 1;
527 }
528
529
530 for(int i=0; i < set.getPortletsCount(); i++)
531 {
532 if ((targetLayout!=null) && (baseLayout!=null)) break;
533
534 Portlets p = set.getPortlets(i);
535 Layout layout = p.getLayout();
536 if ((layout!=null)&&(layout.getPosition()!=-1))
537 {
538 int lpos = (int)layout.getPosition();
539 if ((baseLayout == null) && (lpos==position))
540 {
541 baseLayout = layout;
542 }
543
544 if ((targetLayout == null) && (lpos==target))
545 {
546 targetLayout = layout;
547 }
548 }
549 }
550
551
552 for(int i=0; i < set.getEntryCount(); i++)
553 {
554 if ((targetLayout!=null) && (baseLayout!=null)) break;
555
556 Entry p = set.getEntry(i);
557 Layout layout = p.getLayout();
558 if ((layout!=null)&&(layout.getPosition()!=-1))
559 {
560 int lpos = (int)layout.getPosition();
561 if ((baseLayout == null) && (lpos==position))
562 {
563 baseLayout = layout;
564 }
565
566 if ((targetLayout == null) && (lpos==target))
567 {
568 targetLayout = layout;
569 }
570 }
571 }
572
573
574 if (baseLayout == null)
575 {
576 if (position < set.getPortletsCount())
577 {
578 Portlets p = set.getPortlets(position);
579 if (p.getLayout()==null)
580 {
581 p.setLayout(new PsmlLayout());
582 }
583 baseLayout=p.getLayout();
584 }
585
586 if (position < set.getEntryCount())
587 {
588 Entry p = set.getEntry(position);
589 if (p.getLayout()==null)
590 {
591 p.setLayout(new PsmlLayout());
592 }
593 baseLayout=p.getLayout();
594 }
595 }
596
597 if (targetLayout == null)
598 {
599 if (target < set.getPortletsCount())
600 {
601 Portlets p = set.getPortlets(target);
602 if (p.getLayout()==null)
603 {
604 p.setLayout(new PsmlLayout());
605 }
606 targetLayout=p.getLayout();
607 }
608
609 if (target < set.getEntryCount())
610 {
611 Entry p = set.getEntry(target);
612 if (p.getLayout()==null)
613 {
614 p.setLayout(new PsmlLayout());
615 }
616 targetLayout=p.getLayout();
617 }
618 }
619
620
621
622
623 if ((baseLayout == null) || (targetLayout == null)) return;
624
625 baseLayout.setPosition(target);
626 targetLayout.setPosition(position);
627 }
628 }
629
630
631
632
633
634 }
635 }