Modified: portals/jetspeed-2/branches/JETSPEED-2.1.3/components/portal/src/java/org/apache/jetspeed/layout/impl/PortletPlacementContextImpl.java URL: http://svn.apache.org/viewvc/portals/jetspeed-2/branches/JETSPEED-2.1.3/components/portal/src/java/org/apache/jetspeed/layout/impl/PortletPlacementContextImpl.java?rev=588454&r1=588453&r2=588454&view=diff ============================================================================== --- portals/jetspeed-2/branches/JETSPEED-2.1.3/components/portal/src/java/org/apache/jetspeed/layout/impl/PortletPlacementContextImpl.java (original) +++ portals/jetspeed-2/branches/JETSPEED-2.1.3/components/portal/src/java/org/apache/jetspeed/layout/impl/PortletPlacementContextImpl.java Thu Oct 25 17:40:57 2007 @@ -1,656 +1,615 @@ -/* +/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.jetspeed.layout.impl; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Set; -import java.util.Vector; -import java.util.Map; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.jetspeed.layout.Coordinate; -import org.apache.jetspeed.layout.PortletPlacementException; -import org.apache.jetspeed.layout.PortletPlacementContext; -import org.apache.jetspeed.om.page.Fragment; -import org.apache.jetspeed.om.page.Page; -import org.apache.jetspeed.request.RequestContext; - - -/** - * Portal Placement Context - * - * The purpose of the object is to provide an API that - * can be used to move a portlet fragment on the page. - * This includes moving, adding, removing and getting - * information about portlets that are on the page and - * portlets that are available to be added to the page. - * - * An important note about this object: - * This object is really only intended to be used to do - * a single operation such as "moveabs" or "add". After - * performing the operation, the hashmap data structures - * are not correct and should not be used for subsequent - * operations. The reason they are incorrect is that when - * a fragment is moved, the coordinate of fragments below - * it are now different. These could be updated, but it - * really doesn't serve a purpose since this is a short - * lived object. - * - * @author <a>David Gurney</a> - * @author <a href="mailto:[EMAIL PROTECTED]">David Sean Taylor</a> - * @version $Id: $ - */ -public class PortletPlacementContextImpl implements PortletPlacementContext -{ - private static final int NO_DEPTH_LIMIT = -1; - - /** Logger */ - private Log log = LogFactory.getLog(PortletPlacementContextImpl.class); - - // Columns are reference by index, the rows are held - // in the array list as shown below: - // - // [0] [1] [2] - // ArrayList ArrayList ArrayList - // Row1Frag Row1Frag Row1Frag - // Row2Frag Row2Frag Row2Frag - // Row3Frag Row3Frag Row3Frag - // ... - // - protected Vector[] columnsList = null; - - // Used as a convience when looking up a particular fragment - // - // Key is Fragment, value is a Coordinate object - protected Map fragmentCoordinateMap = new HashMap(); - - // Used as a convience when looking up a particular fragment by id - // - // Key is the Fragment id (String), value is the Fragment - protected Map fragmentMap = new HashMap(); - - // Number of columns found - protected int numberOfColumns = -1; - - protected Page page; - protected Fragment containerFragment; - - public PortletPlacementContextImpl(RequestContext requestContext) - throws PortletPlacementException - { - init(requestContext, null, NO_DEPTH_LIMIT); - } - - public PortletPlacementContextImpl(RequestContext requestContext, Fragment container, int maxdepth) - throws PortletPlacementException - { - init(requestContext, container, maxdepth); - } - - // Initialize the data structures by getting the fragments - // from the page manager - protected void init(RequestContext requestContext, Fragment container, int maxdepth) - throws PortletPlacementException - { - this.page = requestContext.getPage(); - if ( container == null ) - { - container = page.getRootFragment(); - } - this.containerFragment = container; - - // Recursively process each fragment - processFragment( container, maxdepth, 0 ); - - // The final step is to populate the array with the fragments - populateArray(); - - //debugFragments( "init" ); - } - - /** - * Evaluate each portlet fragment and populate the internal data - * structures - */ - protected int processFragment( Fragment fragment, int remainingDepth, int rowCount ) - throws PortletPlacementException - { - // Process this fragment, then its children - if(fragment != null) - { - // Only process portlet fragments - //if(fragment.getType().equalsIgnoreCase("portlet")) - { - // Get the column and row of this fragment - int col = getFragmentCol(fragment); - int row = getFragmentRow(fragment); - - if(row < 0) - { - row = rowCount; - } - // Add this fragment to the data structures - addFragmentInternal(fragment, col, row); - rowCount++; - } - - if ( remainingDepth == NO_DEPTH_LIMIT || remainingDepth > 0 ) - { - // Process the children - List children = fragment.getFragments(); - int childRowCount = 0; - for(int ix = 0; ix < children.size(); ix++) - { - Fragment childFrag = (Fragment)children.get(ix); - - if(childFrag != null) - { - childRowCount = processFragment(childFrag, ((remainingDepth == NO_DEPTH_LIMIT) ? NO_DEPTH_LIMIT : remainingDepth-1), childRowCount ); - } - } - } - } - return rowCount; - } - - public Fragment debugFragments(String debug) - { - StringBuffer out = new StringBuffer(); - out.append( "PortletPlacementContext - " ).append( debug ).append( " - container: " ).append( containerFragment == null ? "<null>" : ( containerFragment.getId() + " / " + containerFragment.getType() ) ).append( "\n" ); - for (int ix = 0; ix < this.columnsList.length; ix++) - { - Vector column = this.columnsList[ix]; - out.append( " column " ).append( ix ).append( "\n" ); - Iterator frags = column.iterator(); - while ( frags.hasNext() ) - { - Fragment f = (Fragment)frags.next(); - out.append( " frag " ).append( f == null ? "<null>" : f.getId() ); - if ( f != null ) - out.append( " / " ).append( f.getType() ).append( " col=" ).append( f.getLayoutColumn() ).append( " row=" ).append( f.getLayoutRow() ); - out.append( "\n" ); - } - } - log.debug( out.toString() ); - return containerFragment; - } - - /** - * Takes the internal portlet placement state and stores back - * out to fragment state - * - * @return the managed page layout with updated fragment state. - */ - public Page syncPageFragments() - { - for (int col = 0; col < this.columnsList.length; col++) - { - Vector column = this.columnsList[col]; - Iterator frags = column.iterator(); - int row = 0; - while (frags.hasNext()) - { - Fragment f = (Fragment)frags.next(); - if (f == null) - continue; - f.setLayoutColumn(col); - f.setLayoutRow(row); - row++; - } - } - //debugFragments( "syncPageFragments" ); - return page; - } - - // Helper method - // The implementation will probably change to get this information - // directly from the fragment via fragment.getFragmentCol() - protected int getFragmentRow(Fragment fragment) - { - return fragment.getLayoutRow(); - } - - // The implementation will probably change to get this information - // directly from the fragment via fragment.getFragmentRow() - protected int getFragmentCol(Fragment fragment) - { - int col = fragment.getLayoutColumn(); - if (col < 0) - col = 0; - return col; - } - - // Adds the fragment to the internal data structures - protected void addFragmentInternal(Fragment fragment, int col, int row) - { - // Create a Coordinate object to hold the row and column - CoordinateImpl coordinate = new CoordinateImpl(col, row); - - // Save the fragment in the lookup hash - this.fragmentCoordinateMap.put(fragment, coordinate); - this.fragmentMap.put(fragment.getId(), fragment); - - // Establish the maximum column number - if(col > this.numberOfColumns) - { - this.numberOfColumns = col + 1; - } - } - - /** - * Now that we know the number of columns, the array can be - * constructed and populated - */ - protected void populateArray() throws PortletPlacementException - { - if(this.numberOfColumns == -1) - { - //throw new PortletPlacementException("no columns found"); - this.numberOfColumns = 1; // create a new column - } - - // Allocate the memory for the array of ArrayLists - // Add one since it is zero based - this.columnsList = new Vector[this.numberOfColumns + 1]; - - // Put an array list into each index - for(int i = 0; i < this.numberOfColumns + 1; i++) - { - this.columnsList[i] = new Vector(); - } - - // Get all of the fragments from the hashmap - Set keys = this.fragmentCoordinateMap.keySet(); - Iterator keyIterator = keys.iterator(); - while(keyIterator.hasNext()) - { - // The key is a Fragment - Fragment fragment = (Fragment) keyIterator.next(); - - // Get the Coordinate associated with this fragment - Coordinate coordinate = (Coordinate)this.fragmentCoordinateMap.get(fragment); - - // Make sure we have both - if(fragment != null && coordinate != null) - { - // Get the array list for the column - Vector columnArray = this.columnsList[coordinate.getOldCol()]; - - int row = coordinate.getOldRow(); - - // Before setting the fragment in the array it might - // be necessary to add blank rows before this row - // An ArrayList can only set an element that already exists - prepareList(columnArray, row); - - // Place the fragment in the array list using the row - columnArray.set(row, fragment); - } - } - } - - // Ensures that the array list has at least row number of rows - protected void prepareList(Vector list, int row) - { - if(list != null) - { - int size = list.size(); - if(row + 1 > size) - { - // Add one to the row since it is zero based - for(int i = size; i < row + 1; i++) - { - list.add(null); - } - } - } - } - - // Ensures that there is room for the fragment at the given row - // This method will insert null rows as necessary - protected List makeSpace(Coordinate newCoordinate) - { - int newCol = newCoordinate.getNewCol(); - int newRow = newCoordinate.getNewRow(); - - // Find the column. Note that a new column will never be created - List column = this.columnsList[newCol]; - if(newRow + 1 > column.size()) - { - // Need to add rows - for(int i = column.size(); i < newRow + 1; i++) - { - column.add(null); - } - } - return column; - } - - public int addColumns( int col ) - throws PortletPlacementException - { - if ( col > this.numberOfColumns ) - { - if ( col < 100 ) // arbitrary limit of columns - { - // expand - int prevNumberOfColumns = this.numberOfColumns; - this.numberOfColumns = col + 1; - - Vector [] temp = new Vector[this.numberOfColumns]; - for (int ix = 0; ix < prevNumberOfColumns; ix++) - temp[ix] = this.columnsList[ix]; - for (int ix = prevNumberOfColumns; ix < temp.length; ix++) - temp[ix] = new Vector(); - this.columnsList = temp; - } - else - { - throw new PortletPlacementException( "cannot add column - " + col + " is above the limit of columns that this api supports" ); - } - } - return col; - } - - public Coordinate add(Fragment fragment, Coordinate coordinate) throws PortletPlacementException - { - int col = coordinate.getNewCol(); - int row = coordinate.getNewRow(); - - if (this.numberOfColumns == -1) - { - this.numberOfColumns = 1; - this.columnsList = new Vector[this.numberOfColumns]; - col = 0; - } - if (col > this.numberOfColumns) - { - col = addColumns( col ); - } - - Vector column = this.columnsList[col]; - if (column != null) - { - for (int ix = 0; ix < column.size(); ix++) - { - Fragment frag = (Fragment)column.get(ix); - if (frag == null) - continue; - Coordinate c = (Coordinate)this.fragmentCoordinateMap.get(frag); - if (c == null) - continue; - if (c.getNewCol() == row) - { - row++; - } - - } - // Make sure that the column has room to add the row - if(row < 0 || row > column.size()) { - // Add to the end - column.addElement(fragment); - row = column.size()-1; - } else { - column.add(row, fragment); - } - Coordinate newCoord = new CoordinateImpl(col, row, col, row); - this.fragmentCoordinateMap.put(fragment, newCoord); - return newCoord; - } - return coordinate; - } - - // Adds an existing fragment to the coordinate position - protected Coordinate addInternal(Fragment fragment, Coordinate coordinate) - throws PortletPlacementException - { - int newCol = coordinate.getNewCol(); - int newRow = coordinate.getNewRow(); - - // Check to see if the column exists - if(newCol < 0 || newCol > this.columnsList.length) - { - throw new PortletPlacementException("column out of bounds" + fragment.getName()); - } - - Vector columnArray = this.columnsList[newCol]; - - // Make sure the list has enough room for the set - prepareList(columnArray, newRow); - - columnArray.setElementAt(fragment, newRow); - - // Add the fragment to the hash map - this.fragmentCoordinateMap.put(fragment, coordinate); - - return coordinate; - } - - public Fragment getFragment(String fragmentId) throws PortletPlacementException - { - return (Fragment)this.fragmentMap.get(fragmentId); - } - - public Fragment getFragmentAtOldCoordinate(Coordinate coordinate) throws PortletPlacementException - { - return getFragmentAtCoordinate(coordinate, true); - } - - public Fragment getFragmentAtNewCoordinate(Coordinate coordinate) throws PortletPlacementException - { - return getFragmentAtCoordinate(coordinate, false); - } - - protected Fragment getFragmentAtCoordinate(Coordinate coordinate, boolean isOld) throws PortletPlacementException - { - int col = -1; - int row = -1; - if (isOld == true) - { - col = coordinate.getOldCol(); - row = coordinate.getOldRow(); - } else - { - col = coordinate.getNewCol(); - row = coordinate.getNewRow(); - } - - // Do some sanity checking about the request - if(col < 0 || col > this.columnsList.length) - { - throw new PortletPlacementException("requested column is out of bounds"); - } - - // Get the array list associated with the column - Vector columnArray = this.columnsList[col]; - if(row < 0 || row > columnArray.size()) - { - throw new PortletPlacementException("requested row is out of bounds"); - } - - return (Fragment)columnArray.get(row); - } - - public Fragment getFragmentById(String fragmentId) throws PortletPlacementException - { - return (Fragment)this.fragmentMap.get(fragmentId); - } - - public int getNumberColumns() throws PortletPlacementException - { - return numberOfColumns; - //return this.columnsList.length; - } - - public int getNumberRows(int col) throws PortletPlacementException - { - // Sanity check the column - if(col < 0 || col > this.columnsList.length) - { - throw new PortletPlacementException("column out of bounds"); - } - - return this.columnsList[col].size(); - } - - public Coordinate moveAbsolute(Fragment fragment, Coordinate newCoordinate) - throws PortletPlacementException - { - // Find the fragment - Coordinate oldCoordinate = (Coordinate)this.fragmentCoordinateMap.get(fragment); - if(oldCoordinate == null) - { - throw new PortletPlacementException("could not find fragment"); - } - - // Save the old coordinates - int oldCol = oldCoordinate.getOldCol(); - int oldRow = oldCoordinate.getOldRow(); - - // Create a new coordinate object with both the old and new positions - int newCol = newCoordinate.getNewCol(); - int newRow = newCoordinate.getNewRow(); - - // Make sure there is a place for the move - //List oldRowList = makeSpace(newCoordinate); - - List oldRowList = this.columnsList[oldCol]; - - // Remove the fragment from it's old position - oldRowList.remove(oldRow); - - // The next two lines must occur after the remove above. This is - // because the new and old columns might be the same and the remove - // will change the number of rows - if (newCol > this.numberOfColumns) - { - newCol = addColumns( newCol ); - } - - List newRowList = this.columnsList[newCol]; - int numRowsNewColumn = newRowList.size(); - - // Decide whether an insert or an add is appropriate - if(newRow > (numRowsNewColumn - 1)) - { - newRow = numRowsNewColumn; - // Add a new row - newRowList.add(fragment); - } - else - { - // Insert the fragment at the new position - ((Vector)newRowList).insertElementAt(fragment, newRow); - } - - //debugFragments("move absolute "); - - // New coordinates after moving - return new CoordinateImpl(oldCol, oldRow, newCol, newRow); - } - - protected Coordinate moveDirection(Fragment fragment, int deltaCol, int deltaRow) - throws PortletPlacementException - { - // Find the fragment - Coordinate foundCoordinate = (Coordinate)this.fragmentCoordinateMap.get(fragment); - if(foundCoordinate == null) - { - throw new PortletPlacementException("could not find fragment"); - } - - // Check the coordinates to make sure that there is room to move down - int oldCol = foundCoordinate.getOldCol(); - int oldRow = foundCoordinate.getOldRow(); - - Vector columnArray = this.columnsList[oldCol]; - - // Check the row and column boundaries to make sure there is room - // to do the move - if((oldRow + deltaRow + 1 > columnArray.size()) || ((oldRow + deltaRow) < 0) || - (oldCol + deltaCol + 1 > this.columnsList.length) || ((oldCol + deltaCol) < 0)) - { - // Out of bounds, don't do the move - Coordinate c = new CoordinateImpl(oldCol, oldRow, oldCol, oldRow); - //debugFragments("move direction (1)"); - return c; - } - else - { - Coordinate c = moveAbsolute(fragment, new CoordinateImpl(oldCol, oldRow, oldCol + deltaCol, oldRow + deltaRow)); - //debugFragments("move direction (2)"); - return c; - } - } - - public Coordinate moveDown(Fragment fragment) throws PortletPlacementException - { - return moveDirection(fragment, 0, 1); - } - - public Coordinate moveUp(Fragment fragment) throws PortletPlacementException - { - return moveDirection(fragment, 0, -1); - } - - public Coordinate moveLeft(Fragment fragment) throws PortletPlacementException - { - return moveDirection(fragment, -1, 0); - } - - public Coordinate moveRight(Fragment fragment) throws PortletPlacementException - { - return moveDirection(fragment, 1, 0); - } - - public Coordinate remove(Fragment fragment) throws PortletPlacementException - { - // Locate the fragment - Coordinate coordinate = (Coordinate)this.fragmentCoordinateMap.get(fragment); - if(coordinate == null) - { - throw new PortletPlacementException("fragment not found:" + fragment.getName()); - } - - int col = coordinate.getOldCol(); - int row = coordinate.getOldRow(); - - if(col < 0 || col > this.columnsList.length) - { - throw new PortletPlacementException("column out of bounds:" + fragment.getName()); - } - - Vector columnArray = this.columnsList[col]; - if(row < 0 || row > columnArray.size()) - { - throw new PortletPlacementException("row out of bounds:" + fragment.getName()); - } - - // Remove the fragment from the array - columnArray.remove(row); - - // Remove the fragment from the hashmap - this.fragmentCoordinateMap.remove(fragment); - this.fragmentMap.remove(fragment.getId()); - - return coordinate; - } - -} + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jetspeed.layout.impl; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.Vector; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.jetspeed.layout.Coordinate; +import org.apache.jetspeed.layout.PortletPlacementException; +import org.apache.jetspeed.layout.PortletPlacementContext; +import org.apache.jetspeed.om.page.Fragment; +import org.apache.jetspeed.om.page.Page; +import org.apache.jetspeed.request.RequestContext; + + +/** + * Portal Placement Context + * + * The purpose of the object is to provide an API that + * can be used to move a portlet fragment on the page. + * This includes moving, adding, removing and getting + * information about portlets that are on the page and + * portlets that are available to be added to the page. + * + * This object represents the fragment contents of a + * single layout fragment (i.e. nested depth cannot + * be captured by this object). + * + * An important note about this object: + * This object is really only intended to be used to do + * a single operation such as "moveabs" or "add". After + * performing the operation, the hashmap data structures + * are not correct and should not be used for subsequent + * operations. The reason they are incorrect is that when + * a fragment is moved, the coordinate of fragments below + * it are now different. These could be updated, but it + * really doesn't serve a purpose since this is a short + * lived object. + * + * @author <a>David Gurney</a> + * @author <a href="mailto:[EMAIL PROTECTED]">David Sean Taylor</a> + * @version $Id: $ + */ +public class PortletPlacementContextImpl implements PortletPlacementContext +{ + /** Logger */ + private Log log = LogFactory.getLog(PortletPlacementContextImpl.class); + + // Columns are reference by index, the rows are held + // in the array list as shown below: + // + // [0] [1] [2] + // ArrayList ArrayList ArrayList + // Row1Frag Row1Frag Row1Frag + // Row2Frag Row2Frag Row2Frag + // Row3Frag Row3Frag Row3Frag + // ... + // + protected Vector[] columnsList = null; + + // Used as a convience when looking up a particular fragment + // + // Key is Fragment, value is a Coordinate object + protected Map fragmentCoordinateMap = new HashMap(); + + // Used as a convience when looking up a particular fragment by id + // + // Key is the Fragment id (String), value is the Fragment + protected Map fragmentMap = new HashMap(); + + // Number of columns found + protected int numberOfColumns = -1; + + protected Page page; + protected Fragment layoutContainerFragment; + + public PortletPlacementContextImpl( RequestContext requestContext ) + throws PortletPlacementException + { + init( requestContext, null ); + } + + public PortletPlacementContextImpl( RequestContext requestContext, Fragment container ) + throws PortletPlacementException + { + init( requestContext, container ); + } + + // Initialize the data structures by getting the fragments + // from the page manager + protected void init( RequestContext requestContext, Fragment container ) + throws PortletPlacementException + { + this.page = requestContext.getPage(); + if ( container == null ) + { + container = page.getRootFragment(); + } + this.layoutContainerFragment = container; + + processLayoutContainerFragment(); + + // The final step is to populate the array with the fragments + populateArray(); + + //debugFragments( "init" ); + } + + /** + * For the layout container fragment, evaluate each child fragment and + * populate the internal data structures + */ + protected void processLayoutContainerFragment() + throws PortletPlacementException + { + // Process this fragment, then its children + if ( this.layoutContainerFragment != null ) + { + // Process the child fragments + List childFragments = this.layoutContainerFragment.getFragments(); + int highRow = 0; + for( int ix = 0; ix < childFragments.size(); ix++ ) + { + Fragment fragment = (Fragment)childFragments.get( ix ); + + if ( fragment != null ) + { + int col = getFragmentCol( fragment ); + int row = getFragmentRow( fragment ); + + if ( row < 0 ) + row = highRow; + else if ( row > highRow ) + highRow = row; + + // Add this fragment to the data structures + addFragmentInternal( fragment, col, row ); + } + } + } + } + + // Adds the fragment to the internal data structures + protected void addFragmentInternal( Fragment fragment, int col, int row ) + { + // Create a Coordinate object to hold the row and column + CoordinateImpl coordinate = new CoordinateImpl( col, row ); + + // Save the fragment in the lookup hash + this.fragmentCoordinateMap.put( fragment, coordinate ); + this.fragmentMap.put( fragment.getId(), fragment ); + + // Establish the maximum column number + if ( col > this.numberOfColumns ) + { + this.numberOfColumns = col + 1; + } + } + + public Fragment debugFragments(String debug) + { + StringBuffer out = new StringBuffer(); + out.append( "PortletPlacementContext - " ).append( debug ).append( " - container: " ).append( layoutContainerFragment == null ? "<null>" : ( layoutContainerFragment.getId() + " / " + layoutContainerFragment.getType() ) ).append( "\n" ); + for (int ix = 0; ix < this.columnsList.length; ix++) + { + Vector column = this.columnsList[ix]; + out.append( " column " ).append( ix ).append( "\n" ); + Iterator frags = column.iterator(); + while ( frags.hasNext() ) + { + Fragment f = (Fragment)frags.next(); + out.append( " frag " ).append( f == null ? "<null>" : f.getId() ); + if ( f != null ) + out.append( " / " ).append( f.getType() ).append( " col=" ).append( f.getLayoutColumn() ).append( " row=" ).append( f.getLayoutRow() ); + out.append( "\n" ); + } + } + log.info( out.toString() ); + return layoutContainerFragment; + } + + /** + * Takes the internal portlet placement state and stores back + * out to fragment state + * + * @return the managed page layout with updated fragment state. + */ + public Page syncPageFragments() + { + for ( int col = 0; col < this.columnsList.length; col++ ) + { + Vector column = this.columnsList[col]; + Iterator frags = column.iterator(); + int row = 0; + while ( frags.hasNext() ) + { + Fragment f = (Fragment)frags.next(); + if ( f == null ) + continue; + f.setLayoutColumn( col ); + f.setLayoutRow( row ); + row++; + } + } + //debugFragments( "syncPageFragments" ); + return page; + } + + // Helper method + // The implementation will probably change to get this information + // directly from the fragment via fragment.getFragmentCol() + protected int getFragmentRow(Fragment fragment) + { + return fragment.getLayoutRow(); + } + + // The implementation will probably change to get this information + // directly from the fragment via fragment.getFragmentRow() + protected int getFragmentCol(Fragment fragment) + { + int col = fragment.getLayoutColumn(); + if (col < 0) + col = 0; + return col; + } + + /** + * Now that we know the number of columns, the array can be + * constructed and populated + */ + protected void populateArray() throws PortletPlacementException + { + if ( this.numberOfColumns == -1 ) + { + //throw new PortletPlacementException("no columns found"); + this.numberOfColumns = 1; // create a new column + } + + // Allocate the memory for the array of ArrayLists + // Add one since it is zero based + this.columnsList = new Vector[this.numberOfColumns + 1]; + + // Put an array list into each index + for ( int i = 0; i < this.numberOfColumns + 1; i++ ) + { + this.columnsList[i] = new Vector(); + } + + // Get all of the fragments from the hashmap + Set keys = this.fragmentCoordinateMap.keySet(); + Iterator keyIterator = keys.iterator(); + while ( keyIterator.hasNext() ) + { + // The key is a Fragment + Fragment fragment = (Fragment) keyIterator.next(); + + // Get the Coordinate associated with this fragment + Coordinate coordinate = (Coordinate)this.fragmentCoordinateMap.get( fragment ); + + // Make sure we have both + if ( fragment != null && coordinate != null ) + { + // Get the array list for the column + Vector columnArray = this.columnsList[coordinate.getOldCol()]; + + int row = coordinate.getOldRow(); + + // Before setting the fragment in the array it might + // be necessary to add blank rows before this row + // An ArrayList can only set an element that already exists + prepareList( columnArray, row ); + + // Place the fragment in the array list using the row + columnArray.set( row, fragment ); + } + } + } + + // Ensures that the array list has at least row number of rows + protected void prepareList(Vector list, int row) + { + if(list != null) + { + int size = list.size(); + if(row + 1 > size) + { + // Add one to the row since it is zero based + for(int i = size; i < row + 1; i++) + { + list.add(null); + } + } + } + } + + public int addColumns( int col ) + throws PortletPlacementException + { + if ( col > this.numberOfColumns ) + { + if ( col < 100 ) // arbitrary limit of columns + { + // expand + int prevNumberOfColumns = this.numberOfColumns; + this.numberOfColumns = col + 1; + + Vector [] temp = new Vector[this.numberOfColumns]; + for (int ix = 0; ix < prevNumberOfColumns; ix++) + temp[ix] = this.columnsList[ix]; + for (int ix = prevNumberOfColumns; ix < temp.length; ix++) + temp[ix] = new Vector(); + this.columnsList = temp; + } + else + { + throw new PortletPlacementException( "cannot add column - " + col + " is above the limit of columns that this api supports" ); + } + } + return col; + } + + public Fragment getFragment(String fragmentId) throws PortletPlacementException + { + return (Fragment)this.fragmentMap.get(fragmentId); + } + + public Fragment getFragmentAtOldCoordinate(Coordinate coordinate) throws PortletPlacementException + { + return getFragmentAtCoordinate(coordinate, true); + } + + public Fragment getFragmentAtNewCoordinate(Coordinate coordinate) throws PortletPlacementException + { + return getFragmentAtCoordinate(coordinate, false); + } + + protected Fragment getFragmentAtCoordinate(Coordinate coordinate, boolean isOld) throws PortletPlacementException + { + int col = -1; + int row = -1; + if (isOld == true) + { + col = coordinate.getOldCol(); + row = coordinate.getOldRow(); + } else + { + col = coordinate.getNewCol(); + row = coordinate.getNewRow(); + } + + // Do some sanity checking about the request + if ( col < 0 || col > this.columnsList.length ) + { + throw new PortletPlacementException("requested column is out of bounds"); + } + + // Get the array list associated with the column + Vector columnArray = this.columnsList[col]; + if ( row < 0 || row > columnArray.size() ) + { + throw new PortletPlacementException("requested row is out of bounds"); + } + + return (Fragment)columnArray.get( row ); + } + + public Fragment getFragmentById(String fragmentId) throws PortletPlacementException + { + return (Fragment)this.fragmentMap.get( fragmentId ); + } + + public int getNumberColumns() throws PortletPlacementException + { + return numberOfColumns; + //return this.columnsList.length; + } + + public int getNumberRows(int col) throws PortletPlacementException + { + // Sanity check the column + if ( col < 0 || col > this.columnsList.length ) + { + throw new PortletPlacementException( "column out of bounds" ); + } + + return this.columnsList[col].size(); + } + + public Coordinate add( Fragment fragment, Coordinate coordinate ) throws PortletPlacementException + { + int col = coordinate.getNewCol(); + int row = coordinate.getNewRow(); + + if ( this.numberOfColumns == -1 ) + { + this.numberOfColumns = 1; + this.columnsList = new Vector[this.numberOfColumns]; + col = 0; + } + if ( col > this.numberOfColumns ) + { + col = addColumns( col ); + } + + Vector column = this.columnsList[col]; + if ( column != null ) + { + for ( int ix = 0; ix < column.size(); ix++ ) + { + Fragment frag = (Fragment)column.get( ix ); + if (frag == null) + continue; + Coordinate c = (Coordinate)this.fragmentCoordinateMap.get( frag ); + if (c == null) + continue; + if ( c.getNewCol() == row ) + { + row++; + } + } + // Make sure that the column has room to add the row + if ( row < 0 || row > column.size() ) + { + // Add to the end + column.addElement(fragment); + row = column.size()-1; + } + else + { + column.add(row, fragment); + } + Coordinate newCoord = new CoordinateImpl( col, row, col, row ); + this.fragmentCoordinateMap.put( fragment, newCoord ); + return newCoord; + } + return coordinate; + } + + public Coordinate moveAbsolute( Fragment fragment, Coordinate newCoordinate ) + throws PortletPlacementException + { + return moveAbsolute( fragment, newCoordinate, false ); + } + public Coordinate moveAbsolute( Fragment fragment, Coordinate newCoordinate, boolean addFragment ) + throws PortletPlacementException + { + int newCol = newCoordinate.getNewCol(); + int newRow = newCoordinate.getNewRow(); + + int oldCol = newCol, oldRow = newRow; + if ( ! addFragment ) + { + // Find the fragment + Coordinate oldCoordinate = (Coordinate)this.fragmentCoordinateMap.get(fragment); + if ( oldCoordinate == null ) + { + throw new PortletPlacementException("could not find fragment"); + } + + // Save the old coordinates + oldCol = oldCoordinate.getOldCol(); + oldRow = oldCoordinate.getOldRow(); + + List oldRowList = this.columnsList[oldCol]; + + // Remove the fragment from it's old position + oldRowList.remove( oldRow ); + } + + // Create a new coordinate object with both the old and new positions + + // The next two lines must occur after the remove above. This is + // because the new and old columns might be the same and the remove + // will change the number of rows + if ( newCol > this.numberOfColumns ) + { + newCol = addColumns( newCol ); + } + + List newRowList = this.columnsList[newCol]; + int numRowsNewColumn = newRowList.size(); + + // Decide whether an insert or an add is appropriate + if ( newRow > (numRowsNewColumn - 1) ) + { + newRow = numRowsNewColumn; + // Add a new row + newRowList.add(fragment); + } + else + { + // Insert the fragment at the new position + ((Vector)newRowList).insertElementAt( fragment, newRow ); + } + + //debugFragments( "move absolute [" + fragment.getId() + "] " + ( addFragment ? "(add-fragment) " : "" ) ); + + // New coordinates after moving + newCoordinate = new CoordinateImpl( oldCol, oldRow, newCol, newRow ); + this.fragmentCoordinateMap.put( fragment, newCoordinate ); + if ( addFragment ) + { + this.fragmentMap.put( fragment.getId(), fragment ); + } + return newCoordinate; + } + + protected Coordinate moveDirection(Fragment fragment, int deltaCol, int deltaRow) + throws PortletPlacementException + { + // Find the fragment + Coordinate foundCoordinate = (Coordinate)this.fragmentCoordinateMap.get(fragment); + if(foundCoordinate == null) + { + throw new PortletPlacementException("could not find fragment"); + } + + // Check the coordinates to make sure that there is room to move down + int oldCol = foundCoordinate.getOldCol(); + int oldRow = foundCoordinate.getOldRow(); + + Vector columnArray = this.columnsList[oldCol]; + + // Check the row and column boundaries to make sure there is room + // to do the move + if((oldRow + deltaRow + 1 > columnArray.size()) || ((oldRow + deltaRow) < 0) || + (oldCol + deltaCol + 1 > this.columnsList.length) || ((oldCol + deltaCol) < 0)) + { + // Out of bounds, don't do the move + Coordinate c = new CoordinateImpl(oldCol, oldRow, oldCol, oldRow); + //debugFragments("move direction (1)"); + return c; + } + else + { + Coordinate c = moveAbsolute(fragment, new CoordinateImpl(oldCol, oldRow, oldCol + deltaCol, oldRow + deltaRow)); + //debugFragments("move direction (2)"); + return c; + } + } + + public Coordinate moveDown(Fragment fragment) throws PortletPlacementException + { + return moveDirection(fragment, 0, 1); + } + + public Coordinate moveUp(Fragment fragment) throws PortletPlacementException + { + return moveDirection(fragment, 0, -1); + } + + public Coordinate moveLeft(Fragment fragment) throws PortletPlacementException + { + return moveDirection(fragment, -1, 0); + } + + public Coordinate moveRight(Fragment fragment) throws PortletPlacementException + { + return moveDirection(fragment, 1, 0); + } + + public Coordinate remove(Fragment fragment) throws PortletPlacementException + { + // Locate the fragment + Coordinate coordinate = (Coordinate)this.fragmentCoordinateMap.get(fragment); + if(coordinate == null) + { + throw new PortletPlacementException("fragment not found:" + fragment.getName()); + } + + int col = coordinate.getOldCol(); + int row = coordinate.getOldRow(); + + if(col < 0 || col > this.columnsList.length) + { + throw new PortletPlacementException("column out of bounds:" + fragment.getName()); + } + + Vector columnArray = this.columnsList[col]; + if(row < 0 || row > columnArray.size()) + { + throw new PortletPlacementException("row out of bounds:" + fragment.getName()); + } + + // Remove the fragment from the array + columnArray.remove(row); + + // Remove the fragment from the hashmap + this.fragmentCoordinateMap.remove(fragment); + this.fragmentMap.remove(fragment.getId()); + + return coordinate; + } + +}
Modified: portals/jetspeed-2/branches/JETSPEED-2.1.3/components/portal/src/java/org/apache/jetspeed/layout/impl/RemovePortletAction.java URL: http://svn.apache.org/viewvc/portals/jetspeed-2/branches/JETSPEED-2.1.3/components/portal/src/java/org/apache/jetspeed/layout/impl/RemovePortletAction.java?rev=588454&r1=588453&r2=588454&view=diff ============================================================================== --- portals/jetspeed-2/branches/JETSPEED-2.1.3/components/portal/src/java/org/apache/jetspeed/layout/impl/RemovePortletAction.java (original) +++ portals/jetspeed-2/branches/JETSPEED-2.1.3/components/portal/src/java/org/apache/jetspeed/layout/impl/RemovePortletAction.java Thu Oct 25 17:40:57 2007 @@ -1,159 +1,166 @@ -/* +/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.jetspeed.layout.impl; - -import java.util.Map; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.jetspeed.JetspeedActions; -import org.apache.jetspeed.ajax.AJAXException; -import org.apache.jetspeed.ajax.AjaxAction; -import org.apache.jetspeed.ajax.AjaxBuilder; -import org.apache.jetspeed.layout.PortletActionSecurityBehavior; -import org.apache.jetspeed.layout.PortletPlacementContext; -import org.apache.jetspeed.om.page.Fragment; -import org.apache.jetspeed.om.page.Page; -import org.apache.jetspeed.page.PageManager; -import org.apache.jetspeed.pipeline.PipelineException; -import org.apache.jetspeed.request.RequestContext; - - -/** - * Remove Portlet portlet placement action - * - * AJAX Parameters: - * id = the fragment id of the portlet to remove - * page = (implied in the URL) - * - * @author <a>David Gurney </a> - * @author <a href="mailto:[EMAIL PROTECTED]">David Sean Taylor </a> - * @version $Id: $ - */ -public class RemovePortletAction - extends BasePortletAction - implements AjaxAction, AjaxBuilder, Constants -{ - protected static final Log log = LogFactory.getLog(RemovePortletAction.class); - - public RemovePortletAction(String template, String errorTemplate) - throws PipelineException - { - this(template, errorTemplate, null, null); - } - - public RemovePortletAction(String template, - String errorTemplate, - PageManager pageManager, - PortletActionSecurityBehavior securityBehavior) - throws PipelineException - { - super(template, errorTemplate, pageManager, securityBehavior); - } - - public boolean runBatch(RequestContext requestContext, Map resultMap) throws AJAXException - { - return runAction(requestContext, resultMap, true); - } - - public boolean run(RequestContext requestContext, Map resultMap) - throws AJAXException - { - return runAction(requestContext, resultMap, false); - } - - public boolean runAction(RequestContext requestContext, Map resultMap, boolean batch) - { - boolean success = true; - String status = "success"; - try - { - resultMap.put(ACTION, "remove"); - // Get the necessary parameters off of the request - String portletId = getActionParameter(requestContext, PORTLETID); - if (portletId == null) - { - success = false; - resultMap.put(REASON, "Portlet ID not provided"); - return success; - } - resultMap.put(PORTLETID, portletId); - if (false == checkAccess(requestContext, JetspeedActions.EDIT)) - { - Page page = requestContext.getPage(); - Fragment fragment = page.getFragmentById(portletId); - if (fragment == null) - { - success = false; - resultMap.put(REASON, "Fragment not found"); - return success; - } - int column = fragment.getLayoutColumn(); - int row = fragment.getLayoutRow(); - if (!createNewPageOnEdit(requestContext)) - { - success = false; - resultMap.put(REASON, "Insufficient access to edit page"); - return success; - } - status = "refresh"; - // translate old portlet id to new portlet id - Fragment newFragment = getFragmentIdFromLocation(row, column, requestContext.getPage()); - if (newFragment == null) - { - success = false; - resultMap.put(REASON, "Failed to find new fragment"); - return success; - } - portletId = newFragment.getId(); - } - - // Use the Portlet Placement Manager to accomplish the removal - PortletPlacementContext placement = new PortletPlacementContextImpl(requestContext); - Fragment fragment = placement.getFragmentById(portletId); - if (fragment == null) - { - success = false; - resultMap.put(REASON, "Fragment not found"); - return success; - } - placement.remove(fragment); - Page page = placement.syncPageFragments(); - page.removeFragmentById(fragment.getId()); - if (!batch) - { - if (pageManager != null) - pageManager.updatePage(page); - } - // Build the results for the response - resultMap.put(PORTLETID, portletId); - resultMap.put(STATUS, status); - resultMap.put(OLDCOL, String.valueOf(fragment.getLayoutColumn())); - resultMap.put(OLDROW, String.valueOf(fragment.getLayoutRow())); - } - catch (Exception e) - { - // Log the exception - log.error("exception while adding a portlet", e); - resultMap.put(REASON, e.toString()); - // Return a failure indicator - success = false; - } - - return success; - } -} + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jetspeed.layout.impl; + +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.jetspeed.JetspeedActions; +import org.apache.jetspeed.ajax.AJAXException; +import org.apache.jetspeed.ajax.AjaxAction; +import org.apache.jetspeed.ajax.AjaxBuilder; +import org.apache.jetspeed.layout.PortletActionSecurityBehavior; +import org.apache.jetspeed.layout.PortletPlacementContext; +import org.apache.jetspeed.om.page.Fragment; +import org.apache.jetspeed.om.page.Page; +import org.apache.jetspeed.page.PageManager; +import org.apache.jetspeed.pipeline.PipelineException; +import org.apache.jetspeed.request.RequestContext; + + +/** + * Remove Portlet portlet placement action + * + * AJAX Parameters: + * id = the fragment id of the portlet to remove + * page = (implied in the URL) + * + * @author <a>David Gurney </a> + * @author <a href="mailto:[EMAIL PROTECTED]">David Sean Taylor </a> + * @version $Id: $ + */ +public class RemovePortletAction + extends BasePortletAction + implements AjaxAction, AjaxBuilder, Constants +{ + protected static final Log log = LogFactory.getLog(RemovePortletAction.class); + + public RemovePortletAction(String template, String errorTemplate) + throws PipelineException + { + this(template, errorTemplate, null, null); + } + + public RemovePortletAction(String template, + String errorTemplate, + PageManager pageManager, + PortletActionSecurityBehavior securityBehavior) + throws PipelineException + { + super(template, errorTemplate, pageManager, securityBehavior); + } + + public boolean runBatch(RequestContext requestContext, Map resultMap) throws AJAXException + { + return runAction(requestContext, resultMap, true); + } + + public boolean run(RequestContext requestContext, Map resultMap) + throws AJAXException + { + return runAction(requestContext, resultMap, false); + } + + public boolean runAction(RequestContext requestContext, Map resultMap, boolean batch) + { + boolean success = true; + String status = "success"; + try + { + resultMap.put(ACTION, "remove"); + // Get the necessary parameters off of the request + String portletId = getActionParameter(requestContext, PORTLETID); + if (portletId == null) + { + success = false; + resultMap.put(REASON, "Portlet ID not provided"); + return success; + } + resultMap.put(PORTLETID, portletId); + if (false == checkAccess(requestContext, JetspeedActions.EDIT)) + { + Page page = requestContext.getPage(); + Fragment fragment = page.getFragmentById(portletId); + if (fragment == null) + { + success = false; + resultMap.put(REASON, "Fragment not found"); + return success; + } + int column = fragment.getLayoutColumn(); + int row = fragment.getLayoutRow(); + if (!createNewPageOnEdit(requestContext)) + { + success = false; + resultMap.put(REASON, "Insufficient access to edit page"); + return success; + } + status = "refresh"; + // translate old portlet id to new portlet id + Fragment newFragment = getFragmentIdFromLocation(row, column, requestContext.getPage()); + if (newFragment == null) + { + success = false; + resultMap.put(REASON, "Failed to find new fragment"); + return success; + } + portletId = newFragment.getId(); + } + + // Use the Portlet Placement Manager to accomplish the removal + Fragment root = requestContext.getPage().getRootFragment(); + Fragment layoutContainerFragment = getParentFragmentById( portletId, root ); + PortletPlacementContext placement = null; + Fragment fragment = null; + if ( layoutContainerFragment != null ) + { + placement = new PortletPlacementContextImpl(requestContext, layoutContainerFragment); + fragment = placement.getFragmentById(portletId); + } + if ( fragment == null ) + { + success = false; + resultMap.put(REASON, "Fragment not found"); + return success; + } + placement.remove(fragment); + Page page = placement.syncPageFragments(); + page.removeFragmentById(fragment.getId()); + if (!batch) + { + if (pageManager != null) + pageManager.updatePage(page); + } + // Build the results for the response + resultMap.put(PORTLETID, portletId); + resultMap.put(STATUS, status); + resultMap.put(OLDCOL, String.valueOf(fragment.getLayoutColumn())); + resultMap.put(OLDROW, String.valueOf(fragment.getLayoutRow())); + } + catch (Exception e) + { + // Log the exception + log.error("exception while adding a portlet", e); + resultMap.put(REASON, e.toString()); + // Return a failure indicator + success = false; + } + + return success; + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]