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.web;
017    
018    import java.util.ArrayList;
019    import java.util.List;
020    import java.util.Map;
021    import java.util.Set;
022    
023    import org.kuali.kfs.sys.businessobject.AccountingLine;
024    import org.kuali.kfs.sys.document.datadictionary.AccountingLineViewHideShowLinesDefinition;
025    import org.kuali.kfs.sys.document.service.AccountingLineFieldRenderingTransformation;
026    
027    /**
028     * The layout element for a hide/show wrapper of other elements
029     */
030    public class HideShowLayoutElement implements AccountingLineViewLineFillingElement {
031        private List<AccountingLineViewLineFillingElement> lines;
032        private AccountingLineViewHideShowLinesDefinition definition;
033    
034        /**
035         * Returns the name of the child element - if that gets removed, then we need to be removed as well
036         * @see org.kuali.kfs.sys.document.web.TableJoining#getName()
037         */
038        public String getName() {
039            return definition.getName();
040        }
041    
042        /**
043         * All hide/show elements fit into one row
044         * @see org.kuali.kfs.sys.document.web.TableJoining#getRequestedRowCount()
045         */
046        public int getRequestedRowCount() {
047            return 1;
048        }
049    
050        /**
051         * Joins the header label row with a cell that colspans the width of the row and that spans 2
052         * @see org.kuali.kfs.sys.document.web.TableJoining#joinRow(org.kuali.kfs.sys.document.web.AccountingLineTableRow, org.kuali.kfs.sys.document.web.AccountingLineTableRow)
053         */
054        public void joinRow(AccountingLineTableRow headerLabelRow, AccountingLineTableRow row) {
055            AccountingLineTableCell cell = new AccountingLineTableCell();
056            if (row != null) {
057                cell.setRowSpan(2);
058            }
059            cell.setStyleClassOverride("total-line");
060            cell.addRenderableElement(createHideShowBlock((row == null ? 1 : 2)));
061            headerLabelRow.addCell(cell);
062        }
063    
064        /**
065         * This layout element should be stretched
066         * @see org.kuali.kfs.sys.document.web.AccountingLineViewLineFillingElement#stretchToFillLine()
067         */
068        public boolean shouldStretchToFillLine() {
069            return true;
070        }
071    
072        /**
073         * 
074         * @see org.kuali.kfs.sys.document.web.TableJoining#joinTable(java.util.List)
075         */
076        public void joinTable(List<AccountingLineTableRow> rows) {
077            throw new IllegalStateException("Line elements may not join a table directly; the specified rendering is incorrect");
078        }
079        
080        /**
081         * Creates the hide/show block
082         * @param headerRowCount the number of header rows 
083         * @return the hide show block
084         */
085        protected HideShowBlock createHideShowBlock(int headerRowCount) {
086            HideShowBlock block = new HideShowBlock();
087            List<AccountingLineTableRow> rows = createBlankRows(getRowsRequested());
088            
089            haveLinesJoinRows(rows, headerRowCount);
090            
091            block.setContentRows(rows);
092            block.setDefinition(definition);
093            return block;
094        }
095        
096        /**
097         * Returns the total number of rows requested by each child line
098         * @return the total number of rows requested
099         */
100        protected int getRowsRequested() {
101            int count = 0;
102            for (AccountingLineViewLineFillingElement line : lines) {
103                count += line.getRequestedRowCount();
104            }
105            return count;
106        }
107        
108        /**
109         * Creates empty rows to populate the content of the hide/show block
110         * @param cellCount the number of rows which will be returned
111         * @return a List of empty rows
112         */
113        protected List<AccountingLineTableRow> createBlankRows(int cellCount) {
114            List<AccountingLineTableRow> rows = new ArrayList<AccountingLineTableRow>();
115            int count = 0;
116            while (count < cellCount) {
117                rows.add(new AccountingLineTableRow());
118                count += 1;
119            }
120            return rows;
121        }
122        
123        /**
124         * Causes child lines to join the given set of rows
125         * @param rows the List of rows which child lines can join
126         * @param headerRowCount the number of header rows
127         */
128        protected void haveLinesJoinRows(List<AccountingLineTableRow> rows, int headerRowCount) {
129            int count = 0;
130            for (AccountingLineViewLineFillingElement line : lines) {
131                
132                if (line.getRequestedRowCount() > 1) {
133                    line.joinRow(rows.get(count), rows.get(count+1));
134                    count += 2;
135                } else {
136                    line.joinRow(rows.get(count), null);
137                    count += 1;
138                }
139            }
140        }
141    
142        /**
143         * Has the inner content perform any field transformations 
144         * @see org.kuali.kfs.sys.document.web.TableJoining#performFieldTransformations(java.util.List, org.kuali.kfs.sys.businessobject.AccountingLine, java.util.Map, java.util.Map)
145         */
146        public void performFieldTransformations(List<AccountingLineFieldRenderingTransformation> fieldTransformations, AccountingLine accountingLine, Map unconvertedValues) {
147            for (AccountingLineViewLineFillingElement line : lines) {
148                line.performFieldTransformations(fieldTransformations, accountingLine, unconvertedValues);
149            }
150        }
151    
152        /**
153         * Has the inner content read onlyize any blocks it needs to
154         * @see org.kuali.kfs.sys.document.web.TableJoining#readOnlyizeReadOnlyBlocks(java.util.Set)
155         */
156        public void readOnlyizeReadOnlyBlocks(Set<String> readOnlyBlocks) {
157            for (AccountingLineViewLineFillingElement line : lines) {
158                line.readOnlyizeReadOnlyBlocks(readOnlyBlocks);
159            }
160        }
161    
162        /**
163         * Shuffles the responsibility off to the inner content
164         * @see org.kuali.kfs.sys.document.web.TableJoining#removeAllActionBlocks()
165         */
166        public void removeAllActionBlocks() {
167            for (AccountingLineViewLineFillingElement line : lines) {
168                line.removeAllActionBlocks();
169            }
170        }
171    
172        /**
173         * Passes the unviewable blocks off the inner content
174         * @see org.kuali.kfs.sys.document.web.TableJoining#removeUnviewableBlocks(java.util.Set)
175         */
176        public void removeUnviewableBlocks(Set<String> unviewableBlocks) {
177            List<AccountingLineViewLineFillingElement> unviewableLines = new ArrayList<AccountingLineViewLineFillingElement>();
178            for (AccountingLineViewLineFillingElement line : lines) {
179                if (unviewableBlocks.contains(line.getName())) {
180                    unviewableLines.add(line);
181                } else {
182                    line.removeUnviewableBlocks(unviewableBlocks);
183                }
184            }
185            lines.removeAll(unviewableLines);
186        }
187    
188        /**
189         * Gets the lines attribute. 
190         * @return Returns the lines.
191         */
192        public List<AccountingLineViewLineFillingElement> getLines() {
193            return lines;
194        }
195    
196        /**
197         * Sets the lines attribute value.
198         * @param lines The lines to set.
199         */
200        public void setLines(List<AccountingLineViewLineFillingElement> lines) {
201            this.lines = lines;
202        }
203        
204        /**
205         * Adds a single line to this element's list of lines
206         * @param line the line to add
207         */
208        public void addLine(AccountingLineViewLineFillingElement line) {
209            if (lines == null) {
210                lines = new ArrayList<AccountingLineViewLineFillingElement>();
211            }
212            lines.add(line);
213        }
214    
215        /**
216         * Gets the definition attribute. 
217         * @return Returns the definition.
218         */
219        public AccountingLineViewHideShowLinesDefinition getDefinition() {
220            return definition;
221        }
222    
223        /**
224         * Sets the definition attribute value.
225         * @param definition The definition to set.
226         */
227        public void setDefinition(AccountingLineViewHideShowLinesDefinition definition) {
228            this.definition = definition;
229        }
230    
231        /**
232         * Checks that all child lines are read only; if none are, then this must be read only too
233         * @see org.kuali.kfs.sys.document.web.ReadOnlyable#isReadOnly()
234         */
235        public boolean isReadOnly() {
236            for (AccountingLineViewLineFillingElement line : lines) {
237                if (!line.isReadOnly()) return false;
238            }
239            return true;
240        }
241    
242        /**
243         * Read-onlyizes child lines
244         * @see org.kuali.kfs.sys.document.web.ReadOnlyable#readOnlyize()
245         */
246        public void readOnlyize() {
247            for (AccountingLineViewLineFillingElement line : lines) {
248                line.readOnlyize();
249            }
250        }
251    
252        /**
253         * Always returns 1; this will appear in one table cell
254         * @see org.kuali.kfs.sys.document.web.AccountingLineViewLineFillingElement#getDisplayingFieldWidth()
255         */
256        public int getDisplayingFieldWidth() {
257            return 1;
258        }
259    
260        /**
261         * @see org.kuali.kfs.sys.document.web.TableJoining#setEditableBlocks(java.util.Set)
262         */
263        public void setEditableBlocks(Set<String> editableBlocks) {
264            for (AccountingLineViewLineFillingElement line : lines) {
265                line.setEditableBlocks(editableBlocks);
266            }
267        }
268    
269        /**
270         * @see org.kuali.kfs.sys.document.web.ReadOnlyable#setEditable()
271         */
272        public void setEditable() {
273            for (AccountingLineViewLineFillingElement line : lines) {
274                line.setEditable();
275            }
276        }
277        
278    }