1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.jetspeed.layout.impl;
18
19 import java.util.HashMap;
20 import java.util.Iterator;
21 import java.util.List;
22 import java.util.ArrayList;
23 import java.util.Set;
24 import java.util.Map;
25 import java.util.Collections;
26 import java.util.Comparator;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30 import org.apache.jetspeed.components.portletregistry.PortletRegistry;
31 import org.apache.jetspeed.layout.Coordinate;
32 import org.apache.jetspeed.layout.PortletPlacementException;
33 import org.apache.jetspeed.layout.PortletPlacementContext;
34 import org.apache.jetspeed.om.page.Fragment;
35 import org.apache.jetspeed.om.page.Page;
36 import org.apache.pluto.om.common.Parameter;
37 import org.apache.pluto.om.common.ParameterSet;
38 import org.apache.pluto.om.portlet.PortletDefinition;
39
40
41 /***
42 * Portal Placement Context
43 *
44 * The purpose of the object is to provide an API that
45 * can be used to move a portlet fragment on the page.
46 * This includes moving, adding, removing and getting
47 * information about portlets that are on the page and
48 * portlets that are available to be added to the page.
49 *
50 * This object represents the fragment contents of a
51 * single layout fragment (i.e. nested depth cannot
52 * be captured by this object).
53 *
54 * An important note about this object:
55 * This object is really only intended to be used to do
56 * a single operation such as "moveabs" or "add". After
57 * performing the operation, the hashmap data structures
58 * are not correct and should not be used for subsequent
59 * operations. The reason they are incorrect is that when
60 * a fragment is moved, the coordinate of fragments below
61 * it are now different. These could be updated, but it
62 * really doesn't serve a purpose since this is a short
63 * lived object.
64 *
65 * @author <a>David Gurney</a>
66 * @author <a href="mailto:taylor@apache.org">David Sean Taylor</a>
67 * @author <a href="mailto:smilek@apache.org">Steve Milek</a>
68 * @version $Id: $
69 */
70 public class PortletPlacementContextImpl implements PortletPlacementContext
71 {
72 private static Log log = LogFactory.getLog( PortletPlacementContextImpl.class );
73 protected static final String eol = System.getProperty( "line.separator" );
74
75
76
77
78
79
80
81
82
83
84
85 protected ArrayList[] columnsList = null;
86
87
88
89
90 protected Map fragmentCoordinateMap = new HashMap();
91
92
93
94
95 protected Map fragmentMap = new HashMap();
96
97
98 protected int numberOfColumns = -1;
99
100 protected Page page;
101 private PortletRegistry registry;
102 protected Fragment layoutContainerFragment;
103
104 public PortletPlacementContextImpl( Page page, PortletRegistry registry )
105 throws PortletPlacementException
106 {
107 this( page, registry, null );
108 }
109
110 public PortletPlacementContextImpl( Page page, PortletRegistry registry, Fragment container )
111 throws PortletPlacementException
112 {
113 if ( page == null )
114 throw new NullPointerException( "PortletPlacementContext cannot be instantiated with a null Page argument" );
115 if ( registry == null )
116 throw new NullPointerException( "PortletPlacementContext cannot be instantiated with a null PortletRegistry argument" );
117
118 this.page = page;
119 this.registry = registry;
120
121 init( container );
122 }
123
124 protected void init( Fragment container )
125 throws PortletPlacementException
126 {
127 if ( container == null )
128 {
129 container = page.getRootFragment();
130 if ( container == null )
131 throw new PortletPlacementException( "PortletPlacementContext cannot acquire root layout fragment from page" );
132 }
133 if ( ! "layout".equals( container.getType() ) )
134 {
135 throw new PortletPlacementException( "PortletPlacementContext specified container fragment (" + container.getId() + ") is not a layout fragment, but is type: " + container.getType() );
136 }
137 this.layoutContainerFragment = container;
138
139 int columnCount = PortletPlacementContextImpl.getColumnCountAndSizes( container, registry, null );
140 if ( columnCount <= 0 )
141 {
142 throw new PortletPlacementException( "PortletPlacementContext cannot detemine number of columns in layout fragment (" + container.getId() + ")" );
143 }
144 this.numberOfColumns = columnCount;
145
146 initProcessLayoutContainerFragment();
147
148
149 }
150
151 private void initProcessLayoutContainerFragment()
152 throws PortletPlacementException
153 {
154 List fragChildren = this.layoutContainerFragment.getFragments();
155 int fragChildCount = fragChildren.size();
156
157 int columnCount = this.numberOfColumns;
158
159
160 FragmentLinkedListEntry[][] colLinkedLists = new FragmentLinkedListEntry[columnCount][fragChildCount];
161 FragmentLinkedListInfo[] colLinkedListsInfo = new FragmentLinkedListInfo[columnCount];
162 for ( int colIndex = 0 ; colIndex < columnCount ; colIndex++ )
163 {
164 colLinkedListsInfo[ colIndex ] = new FragmentLinkedListInfo();
165 }
166 for( int fragChildIndex = 0; fragChildIndex < fragChildCount; fragChildIndex++ )
167 {
168 Fragment fragment = (Fragment)fragChildren.get( fragChildIndex );
169 if ( fragment != null )
170 {
171 int col = getColumnFromFragment( fragment );
172
173 FragmentLinkedListEntry[] ll = colLinkedLists[col];
174 FragmentLinkedListInfo llInfo = colLinkedListsInfo[col];
175
176 Integer rowObj = getRowFromFragment( fragment );
177 int row;
178 if ( rowObj != null )
179 row = rowObj.intValue();
180 else
181 row = llInfo.getHigh() + 1;
182
183
184
185 FragmentLinkedListEntry fragLLentry = new FragmentLinkedListEntry( fragChildIndex, row );
186 int llLen = llInfo.useNextAvailableIndex();
187 ll[ llLen ] = fragLLentry;
188 if ( llLen == 0 )
189 {
190 llInfo.setHead( 0 );
191 llInfo.setTail( 0 );
192 llInfo.setHigh( row );
193 }
194 else
195 {
196 if ( row > llInfo.getHigh() )
197 {
198 ll[ llInfo.getTail() ].setNextEntry( llLen );
199 llInfo.setHigh( row );
200 llInfo.setTail( llLen );
201 }
202 else
203 {
204 int llEntryIndex = llInfo.getHead();
205 int llPrevEntryIndex = -1;
206 while ( ll[llEntryIndex].getRow() < row )
207 {
208 llPrevEntryIndex = llEntryIndex;
209 llEntryIndex = ll[llEntryIndex].getNextEntry();
210 }
211 if ( ll[llEntryIndex].getRow() == row )
212 {
213
214
215 int incrementedRow = row + 1;
216 ll[llEntryIndex].setRow( incrementedRow );
217 if ( llInfo.getTail() == llEntryIndex )
218 llInfo.setHigh( incrementedRow );
219 }
220 fragLLentry.setNextEntry( llEntryIndex );
221 if ( llPrevEntryIndex == -1 )
222 llInfo.setHead( llLen );
223 else
224 ll[llPrevEntryIndex].setNextEntry( llLen );
225 }
226 }
227 }
228 }
229
230 ArrayList[] columnFragments = new ArrayList[ columnCount ];
231 for ( int colIndex = 0 ; colIndex < columnCount ; colIndex++ )
232 {
233 ArrayList fragmentsInColumn = new ArrayList();
234 columnFragments[ colIndex ] = fragmentsInColumn;
235
236 FragmentLinkedListEntry[] ll = colLinkedLists[colIndex];
237 FragmentLinkedListInfo llInfo = colLinkedListsInfo[colIndex];
238
239 int rowIndex = 0;
240 int nextEntryIndex = llInfo.getHead();
241 while ( nextEntryIndex != -1 )
242 {
243 FragmentLinkedListEntry fragLLentry = ll[nextEntryIndex];
244 Fragment fragment = (Fragment)fragChildren.get( fragLLentry.getFragmentIndex() );
245
246 fragmentsInColumn.add( fragment );
247 CoordinateImpl coordinate = new CoordinateImpl( colIndex, rowIndex );
248 this.fragmentCoordinateMap.put( fragment.getId(), coordinate );
249 this.fragmentMap.put( fragment.getId(), fragment );
250
251 nextEntryIndex = fragLLentry.getNextEntry();
252 rowIndex++;
253 }
254 }
255 this.columnsList = columnFragments;
256 }
257
258 private int getColumnFromFragment( Fragment fragment )
259 {
260
261
262
263 String colStr = (String)fragment.getProperties().get( "column" );
264 int columnCount = this.numberOfColumns;
265 int col = columnCount - 1;
266 if ( colStr != null )
267 {
268 try
269 {
270 col = Integer.parseInt( colStr );
271 if ( col < 0 )
272 col = 0;
273 else if ( col >= columnCount )
274 col = columnCount - 1;
275 }
276 catch ( NumberFormatException ex )
277 {
278 col = columnCount - 1;
279 }
280 }
281 return col;
282 }
283 private Integer getRowFromFragment( Fragment fragment )
284 {
285
286
287
288 String rowStr = (String)fragment.getProperties().get( "row" );
289 if ( rowStr != null )
290 {
291 try
292 {
293 int row = Integer.parseInt( rowStr );
294 if ( row < 0 )
295 row = 0;
296 return new Integer( row );
297 }
298 catch ( NumberFormatException ex )
299 {
300 }
301 }
302 return null;
303 }
304
305 private int normalizeColumnIndex( int col, ArrayList[] columnFragments, int defaultForUnspecifiedCol )
306 {
307 int columnCount = this.numberOfColumns;
308 if ( col >= columnCount )
309 col = (columnCount -1);
310 else if ( col < 0 && defaultForUnspecifiedCol >= 0 && defaultForUnspecifiedCol < columnCount )
311 col = defaultForUnspecifiedCol;
312 else if ( col < 0 )
313 col = 0;
314 return col;
315 }
316
317 class FragmentLinkedListInfo
318 {
319 private int head = -1;
320 private int tail = -1;
321 private int high = -1;
322 private int availableNextIndex = 0;
323
324 FragmentLinkedListInfo()
325 {
326 }
327
328 public int getHead()
329 {
330 return head;
331 }
332 public void setHead( int newOne )
333 {
334 this.head = newOne;
335 }
336 public int getTail()
337 {
338 return tail;
339 }
340 public void setTail( int newOne )
341 {
342 this.tail = newOne;
343 }
344 public int getHigh()
345 {
346 return high;
347 }
348 public void setHigh( int newOne )
349 {
350 this.high = newOne;
351 }
352 public int useNextAvailableIndex()
353 {
354 return this.availableNextIndex++;
355 }
356 }
357
358 class FragmentLinkedListEntry
359 {
360 private int fragmentIndex;
361 private int row;
362 private int nextEntry = -1;
363
364 FragmentLinkedListEntry( int fragmentIndex, int row )
365 {
366 this.fragmentIndex = fragmentIndex;
367 this.row = row;
368 }
369
370 public int getFragmentIndex()
371 {
372 return this.fragmentIndex;
373 }
374 public int getRow()
375 {
376 return this.row;
377 }
378 public void setRow( int newOne )
379 {
380 this.row = newOne;
381 }
382 public int getNextEntry()
383 {
384 return this.nextEntry;
385 }
386 public void setNextEntry( int newOne )
387 {
388 this.nextEntry = newOne;
389 }
390 }
391
392 public String dumpFragments( String debug )
393 {
394 StringBuffer out = new StringBuffer();
395 out.append( "PortletPlacementContext - " );
396 if ( debug != null )
397 out.append( debug ).append( " - " );
398 out.append( "container: " ).append( this.layoutContainerFragment == null ? "<null>" : ( this.layoutContainerFragment.getId() + " / " + this.layoutContainerFragment.getType() ) ).append( " column-count=" ).append( this.numberOfColumns ).append( eol );
399 for (int ix = 0; ix < this.columnsList.length; ix++)
400 {
401 ArrayList column = this.columnsList[ix];
402 out.append( " column " ).append( ix ).append( eol );
403 Iterator frags = column.iterator();
404 while ( frags.hasNext() )
405 {
406 Fragment f = (Fragment)frags.next();
407 out.append( " frag " ).append( f == null ? "<null>" : ( f.getId() + " / " + f.getType() ) ).append( eol );
408 }
409 }
410 return out.toString();
411 }
412 public Fragment debugFragments( String debug )
413 {
414 log.info( dumpFragments( debug ) );
415 return layoutContainerFragment;
416 }
417
418 /***
419 * Takes the internal portlet placement state and stores back
420 * out to fragment state
421 *
422 * @return the managed page layout with updated fragment state.
423 */
424 public Page syncPageFragments()
425 {
426 syncFragments( true, -1 );
427
428 return this.page;
429 }
430
431 protected int getLatestColumn( Coordinate coordinate )
432 {
433 int col = -1;
434 if ( coordinate != null )
435 {
436 col = coordinate.getNewCol();
437 if ( col == -1 )
438 col = coordinate.getOldCol();
439 }
440 return col;
441 }
442 protected int getLatestRow( Coordinate coordinate )
443 {
444 int row = -1;
445 if ( coordinate != null )
446 {
447 row = coordinate.getNewRow();
448 if ( row == -1 )
449 row = coordinate.getOldRow();
450 }
451 return row;
452 }
453
454 protected void syncFragments( boolean updateFragmentObjects, int onlyForColumnIndex )
455 {
456 for ( int colIndex = 0; colIndex < this.columnsList.length; colIndex++ )
457 {
458 if ( onlyForColumnIndex == -1 || onlyForColumnIndex == colIndex )
459 {
460 ArrayList column = this.columnsList[colIndex];
461 int colRowCount = column.size();
462 for ( int rowIndex= 0; rowIndex < colRowCount; rowIndex++ )
463 {
464 Fragment fragment = (Fragment)column.get( rowIndex );
465 Coordinate coordinate = (Coordinate)this.fragmentCoordinateMap.get( fragment.getId() );
466 boolean needsReplacementCoordinate = false;
467
468 if ( getLatestColumn( coordinate ) != colIndex || getLatestRow( coordinate ) != rowIndex )
469 needsReplacementCoordinate = true;
470
471 if ( needsReplacementCoordinate )
472 {
473 Coordinate replacementCoordinate = new CoordinateImpl( coordinate.getOldCol(), coordinate.getOldRow(), colIndex, rowIndex );
474 this.fragmentCoordinateMap.put( fragment.getId(), replacementCoordinate );
475 }
476 if ( updateFragmentObjects )
477 {
478 fragment.setLayoutColumn( colIndex );
479 fragment.setLayoutRow( rowIndex );
480 }
481 }
482 }
483 }
484 }
485
486 public int getFragmentRow( Fragment fragment )
487 {
488 if ( fragment == null ) return -1;
489 Coordinate coordinate = (Coordinate)this.fragmentCoordinateMap.get( fragment.getId() );
490
491 if ( coordinate == null )
492 return -1;
493 if ( coordinate.getNewRow() >= 0 )
494 return coordinate.getNewRow();
495 return coordinate.getOldRow();
496 }
497
498 public int getFragmentCol( Fragment fragment )
499 {
500 if ( fragment == null ) return -1;
501 Coordinate coordinate = (Coordinate)this.fragmentCoordinateMap.get( fragment.getId() );
502
503 if ( coordinate == null )
504 return -1;
505 if ( coordinate.getNewCol() >= 0 )
506 return coordinate.getNewCol();
507 return coordinate.getOldCol();
508 }
509
510 public Fragment getFragment( String fragmentId ) throws PortletPlacementException
511 {
512 return (Fragment)this.fragmentMap.get( fragmentId );
513 }
514
515 public Fragment getFragmentAtOldCoordinate( Coordinate coordinate ) throws PortletPlacementException
516 {
517 return getFragmentAtCoordinate( coordinate, true, false );
518 }
519
520 public Fragment getFragmentAtNewCoordinate( Coordinate coordinate ) throws PortletPlacementException
521 {
522 return getFragmentAtCoordinate( coordinate, false, false );
523 }
524
525 protected Fragment getFragmentAtCoordinate( Coordinate coordinate, boolean useOldCoordinateValues, boolean suppressExceptions ) throws PortletPlacementException
526 {
527 int col = -1;
528 int row = -1;
529 if ( useOldCoordinateValues )
530 {
531 col = coordinate.getOldCol();
532 row = coordinate.getOldRow();
533 }
534 else
535 {
536 col = coordinate.getNewCol();
537 row = coordinate.getNewRow();
538 }
539
540
541 if ( col < 0 || col >= this.numberOfColumns )
542 {
543 if ( suppressExceptions )
544 return null;
545 throw new PortletPlacementException( "Requested column (" + col + ") is out of bounds (column-count=" + this.numberOfColumns + ")" );
546 }
547
548
549 ArrayList columnArray = this.columnsList[col];
550 if ( row < 0 || row >= columnArray.size() )
551 {
552 if ( suppressExceptions )
553 return null;
554 throw new PortletPlacementException( "Requested row (" + row + ") is out of bounds (col[" + col + "].row-count=" + columnArray.size() + ")" );
555 }
556
557 return (Fragment)columnArray.get( row );
558 }
559
560 public Fragment getFragmentById( String fragmentId ) throws PortletPlacementException
561 {
562 return (Fragment)this.fragmentMap.get( fragmentId );
563 }
564
565 public int getNumberColumns() throws PortletPlacementException
566 {
567 return this.numberOfColumns;
568 }
569
570 public int getNumberRows( int col ) throws PortletPlacementException
571 {
572
573 if ( col < 0 || col >= this.numberOfColumns )
574 {
575 throw new PortletPlacementException( "Requested column (" + col + ") is out of bounds (column-count=" + this.numberOfColumns + ")" );
576 }
577 return this.columnsList[col].size();
578 }
579
580 public Coordinate add( Fragment fragment, Coordinate coordinate ) throws PortletPlacementException
581 {
582 return moveAbsolute( fragment, coordinate, true );
583 }
584
585 public Coordinate moveAbsolute( Fragment fragment, Coordinate newCoordinate )
586 throws PortletPlacementException
587 {
588 return moveAbsolute( fragment, newCoordinate, false );
589 }
590 public Coordinate moveAbsolute( Fragment fragment, Coordinate newCoordinate, boolean okToAddFragment )
591 throws PortletPlacementException
592 {
593 if ( fragment == null )
594 throw new NullPointerException( "PortletPlacementContext moveAbsolute() cannot accept a null Fragment argument" );
595
596 Coordinate currentCoordinate = (Coordinate)this.fragmentCoordinateMap.get( fragment.getId() );
597 int currentCol = getLatestColumn( currentCoordinate );
598 int currentRow = getLatestRow( currentCoordinate );
599
600 int newCol = normalizeColumnIndex( getLatestColumn( newCoordinate ), this.columnsList, currentCol );
601 int newRow = getLatestRow( newCoordinate );
602
603 if ( currentCoordinate == null )
604 {
605 if ( ! okToAddFragment )
606 throw new NullPointerException( "PortletPlacementContext moveAbsolute() cannot add fragment (" + fragment.getId() + ") unless the okToAddFragment argument is set to true" );
607
608
609 ArrayList newColumn = this.columnsList[newCol];
610 if ( newRow < 0 || newRow >= newColumn.size() )
611 newRow = newColumn.size();
612 newColumn.add( newRow, fragment );
613
614 CoordinateImpl coordinate = new CoordinateImpl( newCol, newRow );
615 this.fragmentCoordinateMap.put( fragment.getId(), coordinate );
616 this.fragmentMap.put( fragment.getId(), fragment );
617 syncFragments( false, newCol );
618 }
619 else
620 {
621 boolean columnChanged = ( currentCol != newCol );
622 boolean rowChanged = ( currentRow != newRow );
623
624 if ( columnChanged || rowChanged )
625 {
626 verifyFragmentAtExpectedCoordinate( currentCol, currentRow, fragment, "moveAbsolute()" );
627
628 ArrayList currentColumn = this.columnsList[currentCol];
629 currentColumn.remove( currentRow );
630
631 ArrayList newColumn = currentColumn;
632 if ( columnChanged )
633 newColumn = this.columnsList[newCol];
634
635 if ( newRow < 0 || newRow >= newColumn.size() )
636 newColumn.add( fragment );
637 else
638 newColumn.add( newRow, fragment );
639
640 this.fragmentMap.put( fragment.getId(), fragment );
641
642 syncFragments( false, currentCol );
643 if ( columnChanged )
644 syncFragments( false, newCol );
645 }
646 }
647 return (Coordinate)this.fragmentCoordinateMap.get( fragment.getId() );
648 }
649
650 protected Coordinate moveDirection( Fragment fragment, int deltaCol, int deltaRow )
651 throws PortletPlacementException
652 {
653 if ( fragment == null )
654 throw new NullPointerException( "PortletPlacementContext moveDirection() cannot accept a null Fragment argument" );
655
656 if ( deltaCol != 0 || deltaRow != 0 )
657 {
658 Coordinate currentCoordinate = (Coordinate)this.fragmentCoordinateMap.get( fragment.getId() );
659 if ( currentCoordinate == null )
660 throw new NullPointerException( "PortletPlacementContext moveDirection() cannot locate target fragment (" + fragment.getId() + ")" );
661
662 int currentCol = getLatestColumn( currentCoordinate );
663 int currentRow = getLatestRow( currentCoordinate );
664
665 verifyFragmentAtExpectedCoordinate( currentCol, currentRow, fragment, "moveDirection()" );
666
667 int newCol = currentCol + deltaCol;
668 int newRow = currentRow + deltaRow;
669 if ( newCol >= 0 && newCol < this.numberOfColumns )
670 {
671 ArrayList currentColumn = this.columnsList[currentCol];
672 ArrayList newColumn = currentColumn;
673 if ( newCol != currentCol )
674 newColumn = this.columnsList[newCol];
675
676 currentColumn.remove( currentRow );
677
678 if ( newRow < 0 || newRow >= newColumn.size() )
679 newColumn.add( fragment );
680 else
681 newColumn.add( newRow, fragment );
682
683 this.fragmentMap.put( fragment.getId(), fragment );
684
685 syncFragments( false, currentCol );
686 if ( newCol != currentCol )
687 syncFragments( false, newCol );
688 }
689 }
690 return (Coordinate)this.fragmentCoordinateMap.get( fragment.getId() );
691 }
692
693 public Coordinate moveDown( Fragment fragment ) throws PortletPlacementException
694 {
695 return moveDirection( fragment, 0, 1 );
696 }
697
698 public Coordinate moveUp( Fragment fragment ) throws PortletPlacementException
699 {
700 return moveDirection( fragment, 0, -1 );
701 }
702
703 public Coordinate moveLeft( Fragment fragment ) throws PortletPlacementException
704 {
705 return moveDirection( fragment, -1, 0 );
706 }
707
708 public Coordinate moveRight( Fragment fragment ) throws PortletPlacementException
709 {
710 return moveDirection( fragment, 1, 0 );
711 }
712
713 public Coordinate remove( Fragment fragment ) throws PortletPlacementException
714 {
715 if ( fragment == null )
716 throw new NullPointerException( "PortletPlacementContext remove() cannot accept a null Fragment argument" );
717
718 Coordinate currentCoordinate = (Coordinate)this.fragmentCoordinateMap.get( fragment.getId() );
719 if ( currentCoordinate == null )
720 throw new NullPointerException( "PortletPlacementContext remove() cannot locate target fragment (" + fragment.getId() + ")" );
721
722 int currentCol = getLatestColumn( currentCoordinate );
723 int currentRow = getLatestRow( currentCoordinate );
724
725 verifyFragmentAtExpectedCoordinate( currentCol, currentRow, fragment, "moveDirection()" );
726
727 ArrayList currentColumn = this.columnsList[currentCol];
728
729 currentColumn.remove( currentRow );
730
731 this.fragmentCoordinateMap.remove( fragment.getId() );
732 this.fragmentMap.remove( fragment.getId() );
733
734 syncFragments( false, currentCol );
735
736 return currentCoordinate;
737 }
738
739 protected Fragment verifyFragmentAtExpectedCoordinate( int colIndex, int rowIndex, Fragment fragment, String sourceDesc )
740 throws PortletPlacementException
741 {
742 CoordinateImpl coordinate = new CoordinateImpl( colIndex, rowIndex );
743
744 boolean suppressExceptions = ( fragment != null );
745 Fragment foundFragment = getFragmentAtCoordinate( coordinate, true, suppressExceptions );
746
747 if ( fragment != null )
748 {
749 if ( foundFragment == null || foundFragment.getId() != fragment.getId() )
750 {
751 sourceDesc = ( sourceDesc == null ? "getFragmentAtExpectedCoordinate" : sourceDesc );
752
753 ArrayList column = null;
754 int colFragCount = -1;
755 if ( colIndex >= 0 && colIndex < this.numberOfColumns )
756 {
757 column = this.columnsList[colIndex];
758 colFragCount = column.size();
759 }
760 StringBuffer out = new StringBuffer();
761 out.append( "PortletPlacementContext " ).append( sourceDesc ).append( " has encountered unexpected results");
762 out.append( " using the current instance state to locate fragment " ).append( fragment.getId() ).append( " (" );
763 if ( foundFragment == null )
764 out.append( "no fragment" );
765 else
766 out.append( "different fragment" );
767 out.append( " in row " ).append( rowIndex ).append( " of column " ).append( colIndex );
768 if ( column == null )
769 {
770 out.append( " - column is out of bounds, column-count=" ).append( this.numberOfColumns );
771 }
772 else
773 {
774 out.append( " - " );
775 if ( rowIndex < 0 || rowIndex >= colFragCount )
776 out.append( "row is out of bounds, " );
777 out.append( "row-count=" ).append( colFragCount );
778 }
779 out.append( ")" );
780 throw new PortletPlacementException( out.toString() );
781 }
782 }
783 return fragment;
784 }
785
786 static public int getColumnCountAndSizes( Fragment layoutFragment, PortletRegistry registry, Map fragSizes )
787 {
788 return PortletPlacementContextImpl.getColumnCountAndSizes( layoutFragment, registry, fragSizes, false );
789 }
790 static public int getColumnCountAndSizes( Fragment layoutFragment, PortletRegistry registry, Map fragSizes, boolean suppressErrorLogging )
791 {
792 if ( layoutFragment == null )
793 throw new NullPointerException( "getColumnCountAndSizes cannot accept a null Fragment argument" );
794 if ( registry == null )
795 throw new NullPointerException( "getColumnCountAndSizes cannot accept a null PortletRegistry argument" );
796
797 int columnCount = -1;
798 if ( ! "layout".equals( layoutFragment.getType() ) )
799 {
800 if ( ! suppressErrorLogging )
801 log.error( "getColumnCountAndSizes not a layout fragment - " + layoutFragment.getId() + " type=" + layoutFragment.getType() );
802 }
803 else
804 {
805 String sizesVal = layoutFragment.getProperty( "sizes" );
806 String layoutName = layoutFragment.getName();
807 layoutName = ( (layoutName != null && layoutName.length() > 0) ? layoutName : (String)null );
808 ParameterSet paramSet = null;
809 PortletDefinition portletDef = null;
810 if ( sizesVal == null || sizesVal.length() == 0 )
811 {
812 if ( layoutName != null )
813 {
814
815 portletDef = registry.getPortletDefinitionByUniqueName( layoutName );
816 if ( portletDef != null )
817 {
818 paramSet = portletDef.getInitParameterSet();
819 if ( paramSet != null )
820 {
821 Parameter sizesParam = paramSet.get( "sizes" );
822 sizesVal = ( sizesParam == null ) ? null : sizesParam.getValue();
823 }
824 }
825 }
826 }
827 if ( sizesVal != null && sizesVal.length() > 0 )
828 {
829 if ( fragSizes != null )
830 fragSizes.put( layoutFragment.getId(), sizesVal );
831
832 int sepPos = -1, startPos = 0, sizesLen = sizesVal.length();
833 columnCount = 0;
834 do
835 {
836 sepPos = sizesVal.indexOf( ',', startPos );
837 if ( sepPos != -1 )
838 {
839 if ( sepPos > startPos )
840 columnCount++;
841 startPos = sepPos +1;
842 }
843 else if ( startPos < sizesLen )
844 {
845 columnCount++;
846 }
847 } while ( startPos < sizesLen && sepPos != -1 );
848 if ( ! suppressErrorLogging && columnCount <= 0 )
849 log.error( "getColumnCountAndSizes invalid columnCount - " + layoutFragment.getId() + " / " + layoutName + " count=" + columnCount + " sizes=" + sizesVal );
850 }
851 else if ( paramSet == null )
852 {
853 if ( ! suppressErrorLogging )
854 {
855 if ( layoutName == null )
856 log.error( "getColumnCountAndSizes null sizes, null layoutName - " + layoutFragment.getId() );
857 else if ( portletDef == null )
858 log.error( "getColumnCountAndSizes null sizes, null PortletDefinition - " + layoutFragment.getId() + " / " + layoutName );
859 else
860 log.error( "getColumnCountAndSizes null sizes, null ParameterSet - " + layoutFragment.getId() + " / " + layoutName );
861 }
862 }
863 else
864 {
865 Parameter colsParam = paramSet.get( "columns" );
866 String colsParamVal = ( colsParam == null ) ? null : colsParam.getValue();
867 if ( colsParamVal != null && colsParamVal.length() > 0 )
868 {
869 try
870 {
871 columnCount = Integer.parseInt( colsParamVal );
872 }
873 catch ( NumberFormatException ex )
874 {
875 }
876 if ( columnCount < 1 )
877 {
878 columnCount = 2;
879 }
880 switch ( columnCount )
881 {
882 case 1: sizesVal = "100%"; break;
883 case 2: sizesVal = "50%,50%"; break;
884 case 3: sizesVal = "34%,33%,33%"; break;
885 case 4: sizesVal = "25%,25%,25%,25%"; break;
886 default:
887 {
888 sizesVal = "50%,50%";
889 columnCount = 2;
890 break;
891 }
892 }
893 if ( fragSizes != null )
894 fragSizes.put( layoutFragment.getId(), sizesVal );
895
896 }
897 else
898 {
899 if ( ! suppressErrorLogging )
900 log.error( "getColumnCountAndSizes null sizes, columns not defined in ParameterSet - " + layoutFragment.getId() + " / " + layoutName );
901 }
902 }
903 }
904 return columnCount;
905 }
906 }