001    /*
002     * Copyright 2011 The Kuali Foundation.
003     * 
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     * 
008     * http://www.opensource.org/licenses/ecl2.php
009     * 
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.kuali.kfs.sys.document.service.impl;
017    
018    import java.util.HashSet;
019    import java.util.List;
020    import java.util.Set;
021    
022    import org.kuali.kfs.sys.document.service.AccountingLineTableTransformation;
023    import org.kuali.kfs.sys.document.web.AccountingLineTableCell;
024    import org.kuali.kfs.sys.document.web.AccountingLineTableRow;
025    import org.kuali.kfs.sys.document.web.RenderableElement;
026    
027    /**
028     * A transformation which takes all of the non-visible hidden fields of the accounting line and moves them
029     * to the first possible position
030     */
031    public class HiddenFieldRearrangementAccountingLineRenderingTransformationImpl implements AccountingLineTableTransformation {
032    
033        public void transformRows(List<AccountingLineTableRow> rows) {
034            // 1. find the first top-level container element with non-hidden variables
035            AccountingLineTableCell cell = findFirstNonHiddenCell(rows);
036            // 2. move all the hidden fields
037            for (AccountingLineTableRow row : rows) {
038                moveHiddenFields(row, cell);
039            }
040        }
041        
042        /**
043         * Finds the first top-level non-hidden container from the given list of elements
044         * @param elements the elements to find the first non-hidden container from
045         * @return the first top-level non-hidden container
046         */
047        protected AccountingLineTableCell findFirstNonHiddenCell(List<AccountingLineTableRow> rows) {
048            for (AccountingLineTableRow row : rows) {
049                for (AccountingLineTableCell cell : row.getCells()) {
050                    if (!cell.isHidden()) {
051                        return cell;
052                    }
053                }
054            }
055            throw new IllegalArgumentException("The renderable element tree specified does not seem to have any elements that will display as non-hidden specified");
056        }
057        
058        /**
059         * Moves any hidden fields in the source container to the target container 
060         * @param sourceContainer the container which may have hidden fields
061         * @param targetContainer the container which should be carrying all hidden fields
062         */
063        protected void moveHiddenFields(AccountingLineTableRow sourceRow, AccountingLineTableCell targetCell) {
064            for (AccountingLineTableCell cell : sourceRow.getCells()) {
065                moveHiddenFields(cell, targetCell);
066            }
067        }
068        
069        /**
070         * Moves any hidden renderable fields in the source cell to the target cell
071         * @param sourceCell the source cell to move hidden elements from
072         * @param targetCell the target cell to move hidden elements to
073         */
074        protected void moveHiddenFields(AccountingLineTableCell sourceCell, AccountingLineTableCell targetCell) {
075            Set<RenderableElement> renderableElementsToRemove = new HashSet<RenderableElement>();
076            for (RenderableElement element : sourceCell.getRenderableElement()) {
077                if (element.isHidden()) {
078                    renderableElementsToRemove.add(element);
079                }
080            }
081            sourceCell.getRenderableElement().removeAll(renderableElementsToRemove);
082            targetCell.getRenderableElement().addAll(renderableElementsToRemove);
083        }
084    }