Coverage report

  %line %branch
org.apache.jetspeed.layout.impl.PortletPlacementContextImpl
0% 
0% 

 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  * 
 9  
  *      http://www.apache.org/licenses/LICENSE-2.0
 10  
  * 
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 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.Set;
 23  
 import java.util.Vector;
 24  
 import java.util.Map;
 25  
 
 26  
 import org.apache.commons.logging.Log;
 27  
 import org.apache.commons.logging.LogFactory;
 28  
 import org.apache.jetspeed.layout.Coordinate;
 29  
 import org.apache.jetspeed.layout.PortletPlacementException;
 30  
 import org.apache.jetspeed.layout.PortletPlacementContext;
 31  
 import org.apache.jetspeed.om.page.Fragment;
 32  
 import org.apache.jetspeed.om.page.Page;
 33  
 import org.apache.jetspeed.request.RequestContext;
 34  
 
 35  
 
 36  
 /**
 37  
  * Portal Placement Context
 38  
  * 
 39  
  * The purpose of the object is to provide an API that
 40  
  * can be used to move a portlet fragment on the page.
 41  
  * This includes moving, adding, removing and getting
 42  
  * information about portlets that are on the page and
 43  
  * portlets that are available to be added to the page.
 44  
  * 
 45  
  * An important note about this object:
 46  
  * This object is really only intended to be used to do
 47  
  * a single operation such as "moveabs" or "add".  After
 48  
  * performing the operation, the hashmap data structures
 49  
  * are not correct and should not be used for subsequent
 50  
  * operations.  The reason they are incorrect is that when
 51  
  * a fragment is moved, the coordinate of fragments below
 52  
  * it are now different.  These could be updated, but it
 53  
  * really doesn't serve a purpose since this is a short
 54  
  * lived object.
 55  
  * 
 56  
  * @author <a>David Gurney</a>
 57  
  * @author <a href="mailto:taylor@apache.org">David Sean Taylor</a>
 58  
  * @version $Id: $
 59  
  */
 60  
 public class PortletPlacementContextImpl implements PortletPlacementContext 
 61  
 {
 62  
     private static final int NO_DEPTH_LIMIT = -1;
 63  
 
 64  
     /** Logger */
 65  0
     private Log log = LogFactory.getLog(PortletPlacementContextImpl.class);
 66  
 
 67  
 	// Columns are reference by index, the rows are held
 68  
 	// in the array list as shown below:
 69  
 	//
 70  
 	// [0]        [1]          [2]
 71  
 	// ArrayList  ArrayList    ArrayList
 72  
 	//  Row1Frag   Row1Frag     Row1Frag
 73  
 	//  Row2Frag   Row2Frag     Row2Frag
 74  
 	//  Row3Frag   Row3Frag     Row3Frag
 75  
 	//  ...
 76  
 	//
 77  0
 	protected Vector[] columnsList = null;
 78  
 	
 79  
 	// Used as a convience when looking up a particular fragment
 80  
 	//
 81  
 	// Key is Fragment, value is a Coordinate object
 82  0
 	protected Map fragmentCoordinateMap = new HashMap();
 83  
 	
 84  
 	// Used as a convience when looking up a particular fragment by id
 85  
 	//
 86  
 	// Key is the Fragment id (String), value is the Fragment
 87  0
 	protected Map fragmentMap = new HashMap();
 88  
 	
 89  
 	// Number of columns found
 90  0
 	protected int numberOfColumns = -1;
 91  
 	
 92  
     protected Page page;
 93  
     protected Fragment containerFragment;
 94  
         
 95  
 	public PortletPlacementContextImpl(RequestContext requestContext) 
 96  
     throws PortletPlacementException 
 97  0
     {
 98  0
 		init(requestContext, null, NO_DEPTH_LIMIT);
 99  0
 	}
 100  
     
 101  
     public PortletPlacementContextImpl(RequestContext requestContext, Fragment container, int maxdepth) 
 102  
     throws PortletPlacementException 
 103  0
     {
 104  0
         init(requestContext, container, maxdepth);
 105  0
     }
 106  
 	
 107  
 	// Initialize the data structures by getting the fragments
 108  
 	// from the page manager
 109  
 	protected void init(RequestContext requestContext, Fragment container, int maxdepth) 
 110  
     throws PortletPlacementException 
 111  
     {
 112  0
         this.page = requestContext.getPage();
 113  0
         if ( container == null )
 114  
         {
 115  0
             container = page.getRootFragment();
 116  
         }
 117  0
         this.containerFragment = container;
 118  
         
 119  
         // Recursively process each fragment
 120  0
         processFragment( container, maxdepth, 0 );
 121  
 
 122  
         // The final step is to populate the array with the fragments
 123  0
 		populateArray();
 124  
         
 125  
         //debugFragments( "init" );
 126  0
 	}
 127  
 	
 128  
 	/**
 129  
 	 * Evaluate each portlet fragment and populate the internal data
 130  
 	 * structures
 131  
 	 */
 132  
 	protected int processFragment( Fragment fragment, class="keyword">int remainingDepth, class="keyword">int rowCount ) 
 133  
     throws PortletPlacementException 
 134  
     {
 135  
         // Process this fragment, then its children
 136  0
 		if(fragment != null) 
 137  
         {
 138  
 			// Only process portlet fragments
 139  
 			//if(fragment.getType().equalsIgnoreCase("portlet")) 
 140  
             {
 141  
 				// Get the column and row of this fragment
 142  0
 				int col = getFragmentCol(fragment);
 143  0
 				int row = getFragmentRow(fragment);
 144  
 		        
 145  0
 		        if(row < 0) 
 146  
                 {
 147  0
                     row = rowCount;
 148  
                 }
 149  
 	        	// Add this fragment to the data structures
 150  0
 	        	addFragmentInternal(fragment, col, row);
 151  0
                 rowCount++;
 152  
 			}
 153  
 			
 154  0
             if ( remainingDepth == NO_DEPTH_LIMIT || remainingDepth > 0 )
 155  
             {
 156  
                 // Process the children
 157  0
                 List children = fragment.getFragments();
 158  0
                 int childRowCount = 0;
 159  0
                 for(int ix = 0; ix < children.size(); ix++) 
 160  
                 {
 161  0
                     Fragment childFrag = (Fragment)children.get(ix);
 162  
 				
 163  0
                     if(childFrag != null) 
 164  
                     {
 165  0
                         childRowCount = processFragment(childFrag, ((remainingDepth == NO_DEPTH_LIMIT) ? NO_DEPTH_LIMIT : remainingDepth-1), childRowCount );
 166  
                     }
 167  
                 }
 168  
 			}
 169  
 		}
 170  0
         return rowCount;
 171  
 	}
 172  
     
 173  
     public Fragment debugFragments(String debug)
 174  
     {       
 175  0
         StringBuffer out = new StringBuffer();
 176  0
         out.append( "PortletPlacementContext - " ).append( debug ).append( " - container: " ).append( containerFragment == null ? "<null>" : ( containerFragment.getId() + " / " + containerFragment.getType() ) ).append( "\n" );
 177  0
         for (int ix = 0; ix < this.columnsList.length; ix++)
 178  
         {
 179  0
             Vector column = this.columnsList[ix];
 180  0
             out.append( "   column " ).append( ix ).append( "\n" );
 181  0
             Iterator frags = column.iterator();
 182  0
             while ( frags.hasNext() )
 183  
             {
 184  0
                 Fragment f = (Fragment)frags.next();
 185  0
                 out.append( "      frag " ).append( f == null ? "<null>" : f.getId() );
 186  0
                 if ( f != null )
 187  0
                     out.append( " / " ).append( f.getType() ).append( " col=" ).append( f.getLayoutColumn() ).append( " row=" ).append( f.getLayoutRow() );
 188  0
                 out.append( "\n" );
 189  0
             }
 190  
         }
 191  0
         log.debug( out.toString() );
 192  0
         return containerFragment;
 193  
     }
 194  
 
 195  
     /**
 196  
      * Takes the internal portlet placement state and stores back
 197  
      * out to fragment state
 198  
      * 
 199  
      * @return the managed page layout with updated fragment state. 
 200  
      */
 201  
     public Page syncPageFragments()
 202  
     {        
 203  0
         for (int col = 0; col < this.columnsList.length; col++)
 204  
         {
 205  0
             Vector column = this.columnsList[col];
 206  0
             Iterator frags = column.iterator();
 207  0
             int row = 0;
 208  0
             while (frags.hasNext())
 209  
             {
 210  0
                 Fragment f = (Fragment)frags.next();
 211  0
                 if (f == null)
 212  0
                     continue;
 213  0
                 f.setLayoutColumn(col);
 214  0
                 f.setLayoutRow(row);
 215  0
                 row++;
 216  0
             }
 217  
         }
 218  
         //debugFragments( "syncPageFragments" );
 219  0
         return page;
 220  
     }
 221  
     
 222  
 	// Helper method
 223  
 	// The implementation will probably change to get this information
 224  
 	// directly from the fragment via fragment.getFragmentCol()
 225  
 	protected int getFragmentRow(Fragment fragment)
 226  
     {
 227  0
         return fragment.getLayoutRow();
 228  
 	}
 229  
 	
 230  
 	// The implementation will probably change to get this information
 231  
 	// directly from the fragment via fragment.getFragmentRow()
 232  
 	protected int getFragmentCol(Fragment fragment) 
 233  
     {
 234  0
         int col = fragment.getLayoutColumn();
 235  0
         if (col < 0)
 236  0
             col = 0;
 237  0
         return col;
 238  
 	}
 239  
 	
 240  
 	// Adds the fragment to the internal data structures
 241  
 	protected void addFragmentInternal(Fragment fragment, int col, class="keyword">int row) 
 242  
     {
 243  
 		// Create a Coordinate object to hold the row and column
 244  0
 		CoordinateImpl coordinate = new CoordinateImpl(col, row);
 245  
 		
 246  
 		// Save the fragment in the lookup hash
 247  0
 		this.fragmentCoordinateMap.put(fragment, coordinate);
 248  0
 		this.fragmentMap.put(fragment.getId(), fragment);
 249  
 		
 250  
 		// Establish the maximum column number
 251  0
 		if(col > this.numberOfColumns) 
 252  
         {
 253  0
 			this.numberOfColumns = col + 1;
 254  
 		}
 255  0
 	}
 256  
 	
 257  
 	/**
 258  
 	 * Now that we know the number of columns, the array can be
 259  
 	 * constructed and populated
 260  
 	 */
 261  
 	protected void populateArray() throws PortletPlacementException 
 262  
     {
 263  0
 		if(this.numberOfColumns == -1) 
 264  
         {
 265  
 			//throw new PortletPlacementException("no columns found");
 266  0
             this.numberOfColumns = 1; // create a new column
 267  
 		}
 268  
 		
 269  
 		// Allocate the memory for the array of ArrayLists
 270  
 		// Add one since it is zero based
 271  0
 		this.columnsList = new Vector[class="keyword">this.numberOfColumns + 1];
 272  
 		
 273  
 		// Put an array list into each index
 274  0
 		for(int i = 0; i < this.numberOfColumns + 1; i++) 
 275  
         {
 276  0
 			this.columnsList[i] = new Vector();
 277  
 		}
 278  
 		
 279  
 		// Get all of the fragments from the hashmap
 280  0
 		Set keys = this.fragmentCoordinateMap.keySet();
 281  0
 		Iterator keyIterator = keys.iterator();
 282  0
 		while(keyIterator.hasNext()) 
 283  
         {
 284  
 			// The key is a Fragment
 285  0
 			Fragment fragment = (Fragment) keyIterator.next();
 286  
 			
 287  
 			// Get the Coordinate associated with this fragment
 288  0
 			Coordinate coordinate = (Coordinate)this.fragmentCoordinateMap.get(fragment);
 289  
 			
 290  
 			// Make sure we have both
 291  0
 			if(fragment != null && coordinate != class="keyword">null) 
 292  
             {
 293  
 				// Get the array list for the column
 294  0
 				Vector columnArray = this.columnsList[coordinate.getOldCol()];
 295  
 				
 296  0
 				int row = coordinate.getOldRow();
 297  
 				
 298  
 				// Before setting the fragment in the array it might
 299  
 				// be necessary to add blank rows before this row
 300  
 				// An ArrayList can only set an element that already exists
 301  0
 				prepareList(columnArray, row);
 302  
 				
 303  
 				// Place the fragment in the array list using the row
 304  0
 				columnArray.set(row, fragment);
 305  
 			}
 306  0
 		}
 307  0
 	}
 308  
 	
 309  
 	// Ensures that the array list has at least row number of rows
 310  
 	protected void prepareList(Vector list, int row) 
 311  
     {
 312  0
 		if(list != null) 
 313  
         {
 314  0
 			int size = list.size();
 315  0
 			if(row + 1 > size) 
 316  
             {
 317  
 				// Add one to the row since it is zero based
 318  0
 				for(int i = size; i < row + 1; i++) 
 319  
                 {
 320  0
 					list.add(null);
 321  
 				}
 322  
 			}
 323  
 		}
 324  0
 	}
 325  
 	
 326  
 	// Ensures that there is room for the fragment at the given row
 327  
 	// This method will insert null rows as necessary
 328  
 	protected List makeSpace(Coordinate newCoordinate) 
 329  
     {
 330  0
 		int newCol = newCoordinate.getNewCol();
 331  0
 		int newRow = newCoordinate.getNewRow();
 332  
 		
 333  
 		// Find the column. Note that a new column will never be created
 334  0
 		List column = this.columnsList[newCol];
 335  0
 		if(newRow + 1 > column.size()) 
 336  
         {
 337  
 			// Need to add rows
 338  0
 			for(int i = column.size(); i < newRow + 1; i++) 
 339  
             {
 340  0
 				column.add(null);
 341  
 			}
 342  
 		}
 343  0
 		return column;
 344  
 	}
 345  
 	
 346  
     public int addColumns( class="keyword">int col )
 347  
         throws PortletPlacementException 
 348  
     {
 349  0
         if ( col > this.numberOfColumns )
 350  
         {            
 351  0
             if ( col < 100 ) // arbitrary limit of columns
 352  
             {
 353  
                 // expand
 354  0
                 int prevNumberOfColumns = this.numberOfColumns;
 355  0
                 this.numberOfColumns = col + 1;
 356  
                 
 357  0
                 Vector [] temp = new Vector[this.numberOfColumns];
 358  0
                 for (int ix = 0; ix < prevNumberOfColumns; ix++)
 359  0
                     temp[ix] = this.columnsList[ix];
 360  0
                 for (int ix = prevNumberOfColumns; ix < temp.length; ix++)
 361  0
                     temp[ix] = new Vector();
 362  0
                 this.columnsList = temp;
 363  0
             }
 364  
             else
 365  
             {
 366  0
                 throw new PortletPlacementException( "cannot add column - " + col + " is above the limit of columns that this api supports" );
 367  
             }
 368  
         }
 369  0
         return col;
 370  
     }
 371  
 
 372  
 	public Coordinate add(Fragment fragment, Coordinate coordinate) throws PortletPlacementException 
 373  
     {
 374  0
         int col = coordinate.getNewCol();
 375  0
         int row = coordinate.getNewRow();
 376  
         
 377  0
         if (this.numberOfColumns == -1)
 378  
         {
 379  0
             this.numberOfColumns = 1;
 380  0
             this.columnsList = new Vector[class="keyword">this.numberOfColumns];
 381  0
             col = 0;
 382  
         }        
 383  0
         if (col > this.numberOfColumns)
 384  
         {    
 385  0
             col = addColumns( col );
 386  
         }
 387  
         
 388  0
         Vector column = this.columnsList[col];
 389  0
         if (column != null)
 390  
         {
 391  0
             for (int ix = 0; ix < column.size(); ix++)
 392  
             {                
 393  0
                 Fragment frag = (Fragment)column.get(ix);
 394  0
                 if (frag == null)
 395  0
                     continue;
 396  0
                 Coordinate c = (Coordinate)this.fragmentCoordinateMap.get(frag);
 397  0
                 if (c == null)
 398  0
                     continue;
 399  0
                 if (c.getNewCol() == row)
 400  
                 {
 401  0
                     row++;
 402  
                 }
 403  
                 
 404  
             }
 405  
             // Make sure that the column has room to add the row
 406  0
             if(row < 0 || row > column.size()) {
 407  
             	// Add to the end
 408  0
             	column.addElement(fragment);
 409  0
             	row = column.size()-1;
 410  
             } else {
 411  0
             	column.add(row, fragment);
 412  
             }
 413  0
             Coordinate newCoord = new CoordinateImpl(col, row, col, row);
 414  0
             this.fragmentCoordinateMap.put(fragment, newCoord);
 415  0
             return newCoord;
 416  
         }
 417  0
         return coordinate;
 418  
 	}
 419  
 	
 420  
 	// Adds an existing fragment to the coordinate position
 421  
 	protected Coordinate addInternal(Fragment fragment, Coordinate coordinate) 
 422  
     throws PortletPlacementException 
 423  
     {
 424  0
 		int newCol = coordinate.getNewCol();
 425  0
 		int newRow = coordinate.getNewRow();
 426  
 		
 427  
 		// Check to see if the column exists
 428  0
 		if(newCol < 0 || newCol > this.columnsList.length) 
 429  
         {
 430  0
 			throw new PortletPlacementException("column out of bounds" + fragment.getName());
 431  
 		}
 432  
 		
 433  0
 		Vector columnArray = this.columnsList[newCol];
 434  
 
 435  
 		// Make sure the list has enough room for the set
 436  0
 		prepareList(columnArray, newRow);
 437  
 		
 438  0
 		columnArray.setElementAt(fragment, newRow);
 439  
 		
 440  
 		// Add the fragment to the hash map
 441  0
 		this.fragmentCoordinateMap.put(fragment, coordinate);
 442  
 		
 443  0
 		return coordinate;
 444  
 	}
 445  
 
 446  
 	public Fragment getFragment(String fragmentId) throws PortletPlacementException 
 447  
     {
 448  0
 		return (Fragment)this.fragmentMap.get(fragmentId);
 449  
 	}
 450  
 	
 451  
 	public Fragment getFragmentAtOldCoordinate(Coordinate coordinate) throws PortletPlacementException 
 452  
     {
 453  0
 		return getFragmentAtCoordinate(coordinate, true);
 454  
 	}
 455  
 
 456  
 	public Fragment getFragmentAtNewCoordinate(Coordinate coordinate) throws PortletPlacementException 
 457  
     {
 458  0
 		return getFragmentAtCoordinate(coordinate, false);
 459  
 	}
 460  
 
 461  
 	protected Fragment getFragmentAtCoordinate(Coordinate coordinate, boolean isOld) throws PortletPlacementException 
 462  
     {
 463  0
 		int col = -1;
 464  0
 		int row = -1;
 465  0
 		if (isOld == true) 
 466  
         {
 467  0
 			col = coordinate.getOldCol();
 468  0
 			row = coordinate.getOldRow();
 469  
 		} else 
 470  
         {
 471  0
 			col = coordinate.getNewCol();
 472  0
 			row = coordinate.getNewRow();
 473  
 		}
 474  
 		
 475  
 		// Do some sanity checking about the request
 476  0
 		if(col < 0 || col > this.columnsList.length) 
 477  
         {
 478  0
 			throw new PortletPlacementException("requested column is out of bounds");
 479  
 		}
 480  
 		
 481  
 		// Get the array list associated with the column
 482  0
 		Vector columnArray = this.columnsList[col];
 483  0
 		if(row < 0 || row > columnArray.size()) 
 484  
         {
 485  0
 			throw new PortletPlacementException("requested row is out of bounds");
 486  
 		}
 487  
 		
 488  0
 		return (Fragment)columnArray.get(row);
 489  
 	}
 490  
 	
 491  
 	public Fragment getFragmentById(String fragmentId) throws PortletPlacementException 
 492  
     {
 493  0
 		return (Fragment)this.fragmentMap.get(fragmentId);
 494  
 	}
 495  
 
 496  
 	public int getNumberColumns() throws PortletPlacementException 
 497  
     {
 498  0
         return numberOfColumns;
 499  
 		//return this.columnsList.length;
 500  
 	}
 501  
 
 502  
 	public int getNumberRows(class="keyword">int col) throws PortletPlacementException 
 503  
     {
 504  
 		// Sanity check the column
 505  0
 		if(col < 0 || col > this.columnsList.length) 
 506  
         {
 507  0
 			throw new PortletPlacementException("column out of bounds");
 508  
 		}
 509  
 		
 510  0
 		return this.columnsList[col].size();
 511  
 	}
 512  
 
 513  
 	public Coordinate moveAbsolute(Fragment fragment, Coordinate newCoordinate) 
 514  
     throws PortletPlacementException 
 515  
     {
 516  
 		// Find the fragment
 517  0
 		Coordinate oldCoordinate = (Coordinate)this.fragmentCoordinateMap.get(fragment);
 518  0
 		if(oldCoordinate == null) 
 519  
         {
 520  0
 			throw new PortletPlacementException("could not find fragment");
 521  
 		}
 522  
 		
 523  
 		// Save the old coordinates
 524  0
 		int oldCol = oldCoordinate.getOldCol();
 525  0
 		int oldRow = oldCoordinate.getOldRow();
 526  
 
 527  
 		// Create a new coordinate object with both the old and new positions
 528  0
 		int newCol = newCoordinate.getNewCol();
 529  0
 		int newRow = newCoordinate.getNewRow();
 530  
 		
 531  
 		// Make sure there is a place for the move
 532  
 		//List oldRowList = makeSpace(newCoordinate);
 533  
 
 534  0
 		List oldRowList = this.columnsList[oldCol];
 535  
 		
 536  
 		// Remove the fragment from it's old position
 537  0
 		oldRowList.remove(oldRow);
 538  
 
 539  
 		// The next two lines must occur after the remove above.  This is
 540  
 		// because the new and old columns might be the same and the remove
 541  
 		// will change the number of rows
 542  0
         if (newCol > this.numberOfColumns)
 543  
         {    
 544  0
             newCol = addColumns( newCol );
 545  
         }
 546  
 
 547  0
 		List newRowList = this.columnsList[newCol];
 548  0
 		int numRowsNewColumn = newRowList.size();
 549  
 		
 550  
 		// Decide whether an insert or an add is appropriate
 551  0
 		if(newRow > (numRowsNewColumn - 1)) 
 552  
         {
 553  0
 			newRow = numRowsNewColumn;
 554  
 			// Add a new row
 555  0
 			newRowList.add(fragment);
 556  
 		} 
 557  
         else 
 558  
         {
 559  
 			// Insert the fragment at the new position
 560  0
 			((Vector)newRowList).insertElementAt(fragment, newRow);		
 561  
 		}
 562  
 
 563  
         //debugFragments("move absolute ");
 564  
         
 565  
 		// New coordinates after moving
 566  0
 		return new CoordinateImpl(oldCol, oldRow, class="keyword">newCol, class="keyword">newRow);
 567  
 	}
 568  
 
 569  
 	protected Coordinate moveDirection(Fragment fragment, int deltaCol, class="keyword">int deltaRow) 
 570  
     throws PortletPlacementException 
 571  
     {
 572  
 		// Find the fragment
 573  0
 		Coordinate foundCoordinate = (Coordinate)this.fragmentCoordinateMap.get(fragment);
 574  0
 		if(foundCoordinate == null) 
 575  
         {
 576  0
 			throw new PortletPlacementException("could not find fragment");
 577  
 		}
 578  
 
 579  
 		// Check the coordinates to make sure that there is room to move down
 580  0
 		int oldCol = foundCoordinate.getOldCol();
 581  0
 		int oldRow = foundCoordinate.getOldRow();
 582  
 		
 583  0
 		Vector columnArray = this.columnsList[oldCol];
 584  
 		
 585  
 		// Check the row and column boundaries to make sure there is room
 586  
 		// to do the move
 587  0
 		if((oldRow + deltaRow + 1 > columnArray.size()) || ((oldRow + deltaRow) < 0) ||
 588  
 		   (oldCol + deltaCol + 1 > this.columnsList.length) || ((oldCol + deltaCol) < 0)) 
 589  
         {
 590  
 			// Out of bounds, don't do the move
 591  0
 			Coordinate c = new CoordinateImpl(oldCol, oldRow, oldCol, oldRow);
 592  
             //debugFragments("move direction (1)");
 593  0
             return c;
 594  
 		}
 595  
         else 
 596  
         {
 597  0
 			Coordinate c = moveAbsolute(fragment, new CoordinateImpl(oldCol, oldRow, oldCol + deltaCol, oldRow + deltaRow));
 598  
             //debugFragments("move direction (2)");
 599  0
             return c;
 600  
 		}        
 601  
 	}
 602  
 	
 603  
 	public Coordinate moveDown(Fragment fragment) throws PortletPlacementException 
 604  
     {
 605  0
 		return moveDirection(fragment, 0, 1);
 606  
 	}
 607  
 
 608  
 	public Coordinate moveUp(Fragment fragment) throws PortletPlacementException 
 609  
     {
 610  0
 		return moveDirection(fragment, 0, -1);
 611  
 	}
 612  
 
 613  
 	public Coordinate moveLeft(Fragment fragment) throws PortletPlacementException 
 614  
     {
 615  0
 		return moveDirection(fragment, -1, 0);
 616  
 	}
 617  
 
 618  
 	public Coordinate moveRight(Fragment fragment) throws PortletPlacementException 
 619  
     {
 620  0
 		return moveDirection(fragment, 1, 0);
 621  
 	}
 622  
 
 623  
 	public Coordinate remove(Fragment fragment) throws PortletPlacementException 
 624  
     {
 625  
 		// Locate the fragment
 626  0
 		Coordinate coordinate = (Coordinate)this.fragmentCoordinateMap.get(fragment);
 627  0
 		if(coordinate == null) 
 628  
         {
 629  0
 			throw new PortletPlacementException("fragment not found:" + fragment.getName());
 630  
 		}
 631  
 		
 632  0
 		int col = coordinate.getOldCol();
 633  0
 		int row = coordinate.getOldRow();
 634  
 		
 635  0
 		if(col < 0 || col > this.columnsList.length) 
 636  
         {
 637  0
 			throw new PortletPlacementException("column out of bounds:" + fragment.getName());
 638  
 		}
 639  
 		
 640  0
 		Vector columnArray = this.columnsList[col];
 641  0
 		if(row < 0 || row > columnArray.size()) 
 642  
         {
 643  0
 			throw new PortletPlacementException("row out of bounds:" + fragment.getName());
 644  
 		}
 645  
 		
 646  
 		// Remove the fragment from the array
 647  0
 		columnArray.remove(row);
 648  
 		
 649  
 		// Remove the fragment from the hashmap
 650  0
 		this.fragmentCoordinateMap.remove(fragment);
 651  0
 		this.fragmentMap.remove(fragment.getId());
 652  
 		
 653  0
 		return coordinate;
 654  
 	}
 655  
 
 656  
 }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.